[
  {
    "path": ".ccls",
    "content": "clang\n%h --include=makeint.h\n-DHAVE_CONFIG_H\n-Isrc\n-Ilib\n-DLIBDIR=\"/usr/local/lib\"\n-DLOCALEDIR=\"/usr/local/share/locale\"\n-DMAKE_MAINTAINER_MODE\n-pthread\n-isystem\n/usr/include/guile/2.0\n-Wall\n-Wextra\n-Werror\n-Wwrite-strings\n-Wshadow\n-Wdeclaration-after-statement\n-Wbad-function-cast\n-Wformat-security\n-Wtype-limits\n-Wunused-but-set-parameter\n-Wlogical-op\n-Wpointer-arith\n-Wignored-qualifiers\n-Wformat-signedness\n-Wduplicated-cond\n-Wno-address\n-Wno-string-compare\n"
  },
  {
    "path": ".clangd",
    "content": "CompileFlags:\n  Add: [-xc, -DHAVE_CONFIG_H, -DMAKE_MAINTAINER_MODE, -DLIBDIR=\"/usr/local/lib\", -DLOCALEDIR=\"/usr/local/share/locale\", -I../src, -Isrc, -I../lib, -Ilib, -Wall, -Wextra, -Wwrite-strings, -Wshadow, -Wdeclaration-after-statement, -Wbad-function-cast, -Wformat-security, -Wtype-limits, -Wunused-but-set-parameter, -Wlogical-op, -Wpointer-arith, -Wignored-qualifiers, -Wformat-signedness, -Wduplicated-cond, -Wno-string-compare, -Wno-unused-includes]\n\n---\nIf:\n  PathMatch: .*\\.h\nCompileFlags:\n  Add: [-xc-header, --include=makeint.h]\n\n---\nIf:\n  PathMatch: .*/makeint\\.h\nDiagnostics:\n  UnusedIncludes: None\n"
  },
  {
    "path": ".dir-locals.el",
    "content": "(\n (nil . ((bug-reference-bug-regexp . \"\\\\(\\\\bSV[- ]\\\\([0-9]+\\\\)\\\\)\")\n         (bug-reference-url-format . \"https://savannah.gnu.org/bugs/?%s\")\n         (ccls-initialization-options\n          . (:index (:threads 6\n                     :initialBlacklist [\"/make-[0-9]\" \"tests/work/\" \"/\\\\.deps\"\n                                        \"/\\\\..*cache\" \"/\\\\.git\"])))\n         (lsp-file-watch-ignored-directories\n          . (\"[/\\\\\\\\]\\\\.git$\"\n             \"[/\\\\\\\\]\\\\..*cache$\"\n             ;; autotools content\n             \"[/\\\\\\\\]\\\\.deps$\"\n             \"[/\\\\\\\\]autom4te\\\\.cache$\"\n             \"[/\\\\\\\\]build-aux$\"\n             ;; make-specific content\n             \"[/\\\\\\\\]doc[/\\\\\\\\]manual$\"\n             \"[/\\\\\\\\]tests[/\\\\\\\\]work$\"\n             \"[/\\\\\\\\]make-[0-9]\"))\n         ))\n (c-mode . ((c-file-style . \"gnu\")))\n)\n"
  },
  {
    "path": ".gitignore",
    "content": "# Development artifacts\nID\nTAGS\nGPATH\nGRTAGS\nGTAGS\n.*cache\n.*gdbinit\n.gdb_history\n.vscode\n*~\n#*\n.#*\n*.diff\n*.patch\n*.orig\n*.rej\n\n# Configure artifacts\n/lib/\n/m4/\nABOUT-NLS\nINSTALL\nMakefile\nMakefile.in\nBasic.mk\naclocal.m4\nautom4te.cache/\nbuild-aux/\nconfig.cache\nconfig.h\nconfig.h.in\nconfig.log\nconfig.status\nconfigure\n/mk/Posix.mk\nstamp-*\n.dirstamp\ngnulib\n*.sed\n\n# Build artifacts\n.deps/\ngmk-default.h\nloadavg\nmake\n*.i\n*.o\n*.a\n*.exe\n*.dll.a\n*.obj\n*.lib\n*.pdb\n*.sbr\n\n# Windows build artifacts\nWinDebug/\nWinRel/\nGccDebug/\nGccRel/\nTccDebug/\nTccRel/\n\n# Test artifacts\nmakeerror-*\ntest-suite.log\n\n# Distribution artifacts\n.dep_segment\n.check-git-HEAD\nChangeLog\nREADME\nbuild.cfg\nmkconfig.h\nmake-[0-9]*/\nmake-[0-9]*.tar.*\ncheckcfg.*.log\n"
  },
  {
    "path": "AUTHORS",
    "content": "-----------------------------------\n\nGNU Make development starting with GNU Make 3.76 by:\n    Paul D. Smith <psmith@gnu.org>\n\n    Additional development starting with GNU Make 4.3 by:\n        Dmitry Goncharov <dgoncharov@users.sf.net>\n\n    Additional development starting with GNU Make 3.81 by:\n        Boris Kolpackov <boris@kolpackov.net>\n\nGNU Make development up to version 3.75 by:\n    Roland McGrath <roland@gnu.org>\n\nGNU Make User's Manual\n  Written by:\n    Richard M. Stallman <rms@gnu.org>\n\n  Edited by:\n    Roland McGrath <roland@gnu.org>\n    Bob Chassell <bob@gnu.org>\n    Melissa Weisshaus <melissa@gnu.org>\n    Paul D. Smith <psmith@gnu.org>\n\n-----------------------------------\nGNU Make porting efforts:\n\n  Port to VMS by:\n      Klaus Kaempf <kkaempf@progis.de>\n      Hartmut Becker <Hartmut.Becker@hp.com>\n      Archive support/Bug fixes by:\n        John W. Eaton <jwe@bevo.che.wisc.edu>\n        Martin Zinser <zinser@decus.decus.de>\n\n  Port to MS-Windows (native/MinGW) maintained by:\n      Eli Zaretskii <eliz@gnu.org>\n\n  Port to MS-DOS (DJGPP), OS/2, and MS-Windows (native/MinGW) by:\n      DJ Delorie <dj@delorie.com>\n      Rob Tulloh <rob_tulloh@tivoli.com>\n      Eli Zaretskii <eliz@gnu.org>\n      Jonathan Grant <jg@jguk.org>\n      Andreas Beuning <andreas.buening@nexgo.de>\n      Earnie Boyd <earnie@uses.sf.net>\n      Troy Runkel <Troy.Runkel@mathworks.com>\n      Juan M. Guerrero <juan.guerrero@gmx.de>\n      KO Myung-Hun <komh78@gmail.com>\n\n  Port to z/OS by:\n      Igor Todorovski <itodorov@ca.ibm.com>\n\n-----------------------------------\nOther contributors:\n\n  Luke Allardyce <lukeallardyce@gmail.com>\n  Costas Argyris <costas.argyris@gmail.com>\n  Aron Barath <baratharon@caesar.elte.hu>\n  David Boyce <dsb@boyski.com>\n  Kevin Buettner <kevinb@redhat.com>\n  Janet Carson <janet_carson@tivoli.com>\n  Howard Chu <hyc@highlandsun.com>\n  Ludovic Courtès <ludo@gnu.org>\n  Joe Crayne <oh.hello.joe@gmail.com>\n  Jeremy Devenport <jeremy.devenport@gmail.com>\n  Pete Dietl <petedietl@gmail.com>\n  Aaron Digulla <digulla@fh-konstanz.de>\n  Hannes Domani <ssbssa@yahoo.de>\n  Martin Dorey <martin.dorey@hds.com>\n  Christian Eggers <ceggers@arri.de>\n  Paul Eggert <eggert@twinsun.com>\n  Mike Frysinger <vapier@gentoo.org>\n  Ramon Garcia Fernandez <ramon.garcia.f@gmail.com>\n  Noah Goldstein <goldstein.w.n@gmail.com>\n  Mike Haboustak <haboustak@gmail.com>\n  Frank Heckenbach <f.heckenbach@fh-soft.de>\n  Klaus Heinz <kamar@ease.rhein-main.de>\n  Ben Hutchings <ben@decadent.org.uk>\n  Cao jin <caoj.fnst@cn.fujitsu.com>\n  Michael Joosten\n  Christian Jullien <eligis@orange.fr>\n  Jim Kelton <jim_kelton@tivoli.com>\n  Kaz Kylheku <kaz@kylheku.com>\n  David Lubbren <uhay@rz.uni-karlsruhe.de>\n  Tim Magill <tim.magill@telops.gte.com>\n  Markus Mauhart <qwe123@chello.at>\n  Greg McGary <greg@mcgary.org>\n  Thien-Thi Nguyen <ttn@gnuvola.org>\n  Han-Wen Nienhuys <hanwen@cs.uu.nl>\n  Enrique Olaizola <enrique_olaizola16@hotmail.com>\n  Ola Olsson <ola1olsson@gmail.com>\n  Jens Rehsack <sno@netbsd.org>\n  Thomas Riedl <thomas.riedl@siemens.com>\n  Jaak Ristioja <jaak@ristioja.ee>\n  Christoph Schulz <develop@kristov.de>\n  Andreas Schwab <schwab@suse.de>\n  spagoveanu <spagoveanu@gmail.com>\n  Carl Staelin (Princeton University)\n  Ian Stewartson (Data Logic Limited)\n  Tobias Stoeckmann <tobias@stoeckmann.org>\n  Torbjörn Svensson <torbjorn.svensson@foss.st.com>\n  Sergei Trofimovich <siarheit@google.com>\n  Justine Tunney <jtunney@gmail.com>\n  Marc Ullman <marc@mathworks.com>\n  Christof Warlich <cwarlich@gmx.de>\n  Florian Weimer <fweimer@redhat.com>\n  David A. Wheeler <dwheeler@dwheeler.com>\n  Bernhard M. Wiedemann <bwiedemann@suse.de>\n  Ben Wijen <ben@wijen.net>\n  Jouke Witteveen <j.witteveen@gmail.com>\n\nWith suggestions/comments/bug reports from a cast of ... well ...\nhundreds, anyway :)\n\n-------------------------------------------------------------------------------\nCopyright (C) 1997-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "Basic.mk.template",
    "content": "# Basic GNU -*-Makefile-*- to build GNU Make\n#\n# NOTE:\n# If you have no 'make' program at all to process this makefile:\n#   * On Windows, run \".\\build_w32.bat\" to bootstrap one.\n#   * On MS-DOS, run \".\\builddos.bat\" to bootstrap one.\n#\n# Once you have a GNU Make program created, you can use it with this makefile\n# to keep it up to date if you make changes, as:\n#\n#   make.exe -f Basic.mk\n#\n# Copyright (C) 2017-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nall:\n\nsrc = src/\nlib = lib/\n\nmake_SOURCES = %make_SOURCES%\nglob_SOURCES = %glob_SOURCES%\nloadavg_SOURCES = %loadavg_SOURCES%\nalloca_SOURCES = %alloca_SOURCES%\nw32_SOURCES = %w32_SOURCES%\nvms_SOURCES = %vms_SOURCES%\n\nremote_SOURCES = $(src)remote-stub.c\n\nOUTDIR =\nSRCDIR = .\n\nOBJEXT = o\nEXEEXT =\n\nPREFIX = /usr/local\nINCLUDEDIR = $(PREFIX)/include\nLIBDIR = $(PREFIX)/lib\nLOCALEDIR = $(PREFIX)/share\n\nPROG = $(OUTDIR)make$(EXEEXT)\n\nprog_SOURCES = $(make_SOURCES) $(remote_SOURCES)\n\nBUILT_SOURCES =\n\nOBJECTS = $(patsubst %.c,$(OUTDIR)%.$(OBJEXT),$(prog_SOURCES))\n\nRESOURCE_OBJECTS =\n\nOBJDIRS = $(addsuffix .,$(sort $(dir $(OBJECTS))))\n\n# Use the default value of CC\nLD = $(CC)\n\n# Reserved for command-line override\nCPPFLAGS =\nCFLAGS = -g -O2\nLDFLAGS =\n\nextra_CPPFLAGS = -DHAVE_CONFIG_H -I$(OUTDIR)src -I$(SRCDIR)/src -I$(OUTDIR)lib -I$(SRCDIR)/lib \\\n\t-DLIBDIR=\\\"$(LIBDIR)\\\" -DINCLUDEDIR=\\\"$(INCLUDEDIR)\\\" -DLOCALEDIR=\\\"$(LOCALDIR)\\\"\nextra_CFLAGS =\nextra_LDFLAGS = $(extra_CFLAGS) $(CFLAGS)\n\nC_SOURCE = -c\nOUTPUT_OPTION = -o $@\nLINK_OUTPUT = -o $@\n\n# Command lines\n\n# $(call COMPILE.cmd,<src>,<tgt>)\nCOMPILE.cmd = $(CC) $(extra_CFLAGS) $(CFLAGS) $(extra_CPPFLAGS) $(CPPFLAGS) $(TARGET_ARCH) $(OUTPUT_OPTION) $(C_SOURCE) $1\n\n# $(call LINK.cmd,<objectlist>)\nLINK.cmd = $(LD) $(extra_LDFLAGS) $(LDFLAGS) $(TARGET_ARCH) $1 $(LDLIBS) $(LINK_OUTPUT)\n\n# $(CHECK.cmd) $(CHECK.args)\nCHECK.cmd = cd $(SRCDIR)/tests && ./run_make_tests -make $(shell cd $(<D) && pwd)/$(<F)\nCHECK.args ?=\n\n# $(call MKDIR.cmd,<dirlist>)\nMKDIR.cmd = mkdir -p $1\n\n# $(call RM.cmd,<filelist>)\nRM.cmd = rm -f $1\n\n# $(call CP.cmd,<from>,<to>)\nCP.cmd = cp $1 $2\n\nCLEANSPACE = $(call RM.cmd,$(OBJECTS) $(RESOURCE_OBJECTS) $(PROG) $(BUILT_SOURCES))\n\n# Load overrides for the above variables.\ninclude $(firstword $(wildcard $(SRCDIR)/mk/$(lastword $(subst -, ,$(MAKE_HOST)).mk)))\n\nVPATH = $(SRCDIR)\n\nall: $(PROG)\n\n$(PROG): $(OBJECTS) $(RESOURCE_OBJECTS)\n\t$(call LINK.cmd,$^)\n\n$(OBJECTS): $(OUTDIR)%.$(OBJEXT): %.c\n\t$(call COMPILE.cmd,$<)\n\n$(OBJECTS): | $(OBJDIRS) $(BUILT_SOURCES)\n\n$(OBJDIRS):\n\t$(call MKDIR.cmd,$@)\n\ncheck:\n\t$(CHECK.cmd) $(CHECK.args)\n\nclean:\n\t$(CLEANSPACE)\n\n$(filter %.h,$(BUILT_SOURCES)): %.h : %.in.h\n\t$(call RM.cmd,$@)\n\t$(call CP.cmd,$<,$@)\n\n.PHONY: all check clean\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "ChangeLog.1",
    "content": "Tue Oct 29 20:57:36 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.\n\n\t* remake.c (update_file_1): Check for deps still running before\n\tgiving up if any dep has failed.\n\nSat Oct 26 16:20:00 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h [uts]: #undef S_ISREG and S_ISDIR if defined.\n\nFri Oct 25 19:50:39 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.17.\n\nThu Oct 24 16:58:36 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* job.c (start_job): Don't check for empty cmds before tweaking the\n\tcommand_ptr.  Just let construct_command_argv do it.\n\nTue Oct 22 20:21:03 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* remake.c, arscan.c [POSIX]: <fcntl.h> instead of <sys/file.h>.\n\n\t* make.h [POSIX]: Declare vfork as pid_t.\n\nMon Oct 21 15:37:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.16.\n\n\t* job.c (construct_command_argv, construct_command_argv_internal):\n\tTake new 2nd arg RESTP.  If non-NULL, stop parsing at newline, and\n\tstore addr of the NL in *RESTP.\n\t(start_job): Don't chop expanded cmd lines up; use above code to do it.\n\t* function.c (expand_function: `shell'): Pass RESTP==NULL.\n\nSat Oct 19 15:36:34 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.15.\n\nFri Oct 18 15:26:55 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (start_job): If on the same cmds->command_lines elt, look\n\tat cmds->lines_recurse[CHILD->command_line - 1] instead of\n\t[CHILD->command_line].\n\n\t* dir.c [sgi]: <sys/dir.h>, not ndir or anything else.\n\nThu Oct 17 16:28:55 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* file.c (print_file_data_base): Remove unused var.\n\n\t* make.h [NeXT]: No #define ANSI_STRING.\n\nTue Oct 15 20:08:41 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.60.14.\n\nFri Oct 11 16:23:52 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* make.h: Use PATH_MAX for getwd defn.\n\n\t* make.h: Move getcwd/getwd outside of #ifndef POSIX, and make it\n\t#if USG||POSIX.\n\nThu Oct 10 11:53:31 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.60.13.\n\n\t* read.c (read_all_makefiles): When processing MAKEFILES, save the\n\tmalloc'd ptr to be freed, instead of freeing part-way thru it.\n\n\t* remake.c (update_file_1): Don't tweak FILE->also_make.\n\t(update_file): Do it here.  After calling update_file_1, set the\n\tcommand_state, update_status, and updated members of each also_make\n\telt to FILE's values.\n\nTue Oct  8 14:56:04 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.60.12.\n\n\t* remake.c (notice_finished_file): Set command_state of FILE and\n\tits also_make chain to cs_finished here.\n\t* commands.c (execute_file_commands), job.c (child_handler),\n\tremake.c (remake_file): Don't set it before calling\n\tnotice_finished_file.\n\n\t* file.h (struct file): Changed `also_make' to struct dep *.\n\t* job.c (delete_child_targets), file.c (print_file_data_base),\n\tremake.c (notice_finished_file), implicit.c (pattern_search):\n\tUse dep chain instead of array of file names.\n\nMon Oct  7 17:04:33 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.60.11.\n\n\t* arscan.c: Declare open.\n\t* misc.c: Declare {get,set}{re,}[ug]id.\n\t* variable.c (target_environment): Declare getenv.\n\nSat Oct  5 15:13:03 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* make.h [NeXT]: <string.h> instead of <strings.h>.\n\nFri Oct  4 16:05:41 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* default.c (default_suffixes, defualt_suffix_rules): Add .texi\n\tjust like .texinfo.\n\n\t* Version 3.60.10.\n\n\t* job.c: Move vfork decl into make.h.\n\nFri Sep 27 18:45:30 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* compatMakefile (glob/libglob.a): Pass CC value to submake.\n\nThu Sep 26 00:08:15 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* load.c (load_average): Made not static.\n\n\t* load.c [ultrix && vax]: Define LDAV_TYPE and LDAV_CVT for Ultrix 4.2.\n\nTue Sep 24 00:17:20 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.9.\n\n\t* read.c (record_files): Warn about extra cmds even if the target's\n\tname begins with a dot.  I think the lusers can handle this.\n\nMon Sep 23 22:33:26 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h, arscan.c: Don't declare bcmp, bzero, or bcopy if they're\n\t#define'd.\n\t* make.h: Declare write and open.\n\n\t* default.c (default_suffixes, default_suffix_rules,\n\tdefault_variables): Add .C just like .cc.\n\t* make.texinfo (Catalogue of Rules): Document .C.\n\n\t* make.man (-w): Fix gramo.\n\nFri Sep 20 17:18:16 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h: No text after #endif.\n\nSun Sep 15 16:20:46 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.60.8.\n\n\t* implicit.c (pattern_search): In the second pass, recurse on rule\n\tdeps that don't have a %.  Why did I make it not do this?\n\nFri Sep 14 18:29:39 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* read.c (record_files): For extra cmds, use the last ones given.\n\tIf the target's name doesn't begin with a dot (bletch!!), emit a\n\ttwo-line warning, one line giving the old cmds' location and the\n\tother the new cmds' location.\n\n\t* misc.c (makefile_error, makefile_fatal): New fns.\n\t* make.h: Declare them.\n\t* Use them instead of error/fatal for all msgs including a file\n\tname and line number.\n\nThu Sep 13 16:35:54 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* make.h: Declare define_default_variables.\n\tDeclare ar_parse_name, instead of ar_name_parse (M-t).\n\nMon Sep 10 18:35:40 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* Version 3.60.7.\n\n\t* make.texinfo (Variables: Setting): Say whitespace is removed if\n\t\"immediately after =\", rather than simply \"after =\".\n\n\t* job.c: Don't declare wait #ifdef POSIX.\n\n\t* make.h [__GNUC__]: #undef alloca and then #define it.\n\n\t* main.c (main): When pruning makefiles which might loop from the\n\tread_makefiles chain, look at all `prev' entries of double-colon rules.\n\nFri Sep  7 00:41:53 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* main.c (main): Only remove makefiles with cmds but no deps from\n\tthe list of makefiles to be rebuilt if they are :: targets.\n\t: targets with cmds and no deps are not dangerous.\n\nWed Sep  5 17:35:51 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (defines): Add comment that some compilers take\n\tENUM_BITFIELDS but produce bogus code.\n\t(LOAD_AVG): Fix examples to \\ \"s.\n\t(LOADLIBES): Add comment that SGI Irix needs -lmld for nlist.\n\nTue Sep  4 20:26:26 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.6.\n\nFri Aug 30 19:34:04 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (update_file_1): When checking the command_state of\n\tdeps, check through the prev chain.\n\t(update_goal_chain): When a target is finished, start checking its\n\tprev (if it has one) instead.\n\nWed Aug  7 17:32:03 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* rule.c (convert_to_pattern): Allow files with deps to define\n\tsuffix rules (really this time).\n\nMon Aug  5 17:09:21 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* misc.c (user_access, make_access): Do saved-IDs (USG) flavor\n\t#ifdef POSIX.\n\n\t* file.c (enter_file): Strip ./s here.\n\t* read.c (parse_file_seq): Not here.\n\nTue Jul 23 23:34:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile: Added comment that -lPW alloca is broken on HPUX.\n\nThu Jul 18 03:10:41 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.5.\n\n\t* read.c (read_makefile): Ignore lines containing chars that are\n\tall isspace, not just all isblank.\n\n\t* make.texinfo (Copying): @include gpl.texinfo, rather than copying\n\tthe text.\n\t* gpl.texinfo: New file (symlink to /gd/gnu/doc/gpl.texinfo).\n\t* GNUmakefile: Put gpl.texinfo in distribution.\n\nTue Jul 16 12:50:35 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* make.h: #define _GNU_SOURCE before including headers.\n\tInclude <ctype.h> and define isblank if <ctype.h> doesn't.\n\t* commands.c: Don't include <ctype.h> here.\n\t* *.c: Use isblank instead of explicit ' ' || '\\t'.\n\nMon Jul 15 17:43:38 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* function.c (expand_function: `filter'/`filter-out'): Fixed to not\n\tloop infinitely.\n\nFri Jul 12 12:18:12 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* function.c (expand_function: `filter'/`filter-out'): Rewritten to\n\thandle filter-out of multiple patterns properly.  Also no longer\n\tmallocs and reallocs for temp array; uses alloca and a linked-list\n\tinstead.\n\nWed Jul 10 22:34:54 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.4.\n\n\t* make.texinfo: Moved some @groups that were outside @examples to\n\tbe inside them.\n\n\t* load.c [apollo] (load_average): Define using special syscall for\n\tApollo DOMAIN/OS SR10.n.\n\nThu Jul  4 12:32:53 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* make.texinfo (Missing): Added Unix excessive implicit rule\n\tsearch; mention that POSIX.2 doesn't require any of the missing\n\tfeatures.\n\t(Top): Updated printed manual price to $15.\n\nWed Jul  3 18:17:50 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* file.c (rename_file): Carry over last_mtime when merging files.\n\t* remake.c (f_mtime): Tail-recurse after renaming VPATH file, to\n\tcheck for saved date in existing renamed-to file.\n\n\t* remote-cstms.c (start_remote_job): Use PATH_VAR.\n\n\t* commands.c [POSIX || __GNU_LIBRARY__]: Don't declare getpid.\n\n\t* compatMakefile (glob-{clean,realclean}): Run clean/realclean in glob.\n\t(clean, realclean): Require those.\n\n\t* make.h: Always declare environ.\n\tDon't declare old glob functions.\n\n\t* GNUmakefile: Make no-lib deps for load.c and remote.c.\n\nTue Jul  2 18:35:20 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.60.3.\n\nMon Jul  1 16:58:30 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (multi_glob): Don't pass GLOB_QUOTE flag to glob.\n\n\t* make.h [POSIX]: Include <unistd.h>, and don't declare things that\n\tshould be there.\n\n\t* main.c (main) [USG && sgi]: malloc a buffer for broken sgi stdio.\n\nSat Jun 29 11:22:21 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* function.c (expand_function: `shell'): Use alloca for the error\n\tmsg buffer, instead of assuming an arbitrary max size.\n\nFri Jun 28 18:15:08 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c [POSIX] (search_path): Do real 1003.1 goop to get NGROUPS_MAX.\n\nWed Jun 26 11:04:44 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* default.c (define_default_variables): New fn.\n\t(install_default_implicit_rules): Code for above fn moved there.\n\t* main.c (main): Do define_default_variables before reading the\n\tmakefile.\n\nTue Jun 25 17:30:46 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* main.c (main): Quote ; in MAKEOVERRIDES.\n\nTue Jun 18 13:56:30 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* compatMakefile: Fixed typo in comment.\n\nTue Jun 11 00:14:59 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.60.2.\n\nMon Jun 10 14:46:37 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h: Always include <sys/types.h>.\n\t[POSIX]: Include <limits.h> and #define MAXPATHLEN to be PATH_MAX.\n\n\t* default.c (default_suffix_rules: .texinfo.dvi): Use $(TEXI2DVI).\n\t(default_variables): Define TEXI2DVI.\n\nThu Jun  6 16:49:19 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.60.1.\n\n\t* make.h (SIGNAL): Cast handler arg to SIGHANDLER type.\n\nWed Jun  5 06:00:43 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* read.c (multi_glob): Use POSIX.2 `glob' function.\n\tIf a glob pattern matches nothing, leave it as is (a la sh, bash).\n\tAlso, if can't find USER for ~USER, leave it as is (a la bash).\n\nMon Jun  3 16:36:00 1991  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* compatMakefile: Rewrote comments about -Ds to be easier to use.\n\n\t* make.h, arscan.c, remake.c, main.c, dir.c, job.c: Changed tests\n\tof _POSIX_SOURCE to POSIX.\n\n\t* job.c: Take getdtablesize out of #ifdef __GNU_LIBRARY__.\n\tPut separately #ifdef USG.\n\n\t* COPYING: Replaced with version 2.\n\t* Changed copyright notices to refer to GPL v2.\n\nThu May 30 00:31:11 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h: Don't declare sigblock for POSIX.\n\n\t* main.c (main, log_working_directory) [USG]: Get getcwd failure\n\tmode from errno, not passed buffer like BSD getwd.\n\n\t* misc.c (child_access): New fn to set access for a child process;\n\tlike user_access, but you can't change back.\n\t* make.h: Declare it.\n\t* job.c (exec_command): Use it in place of user_access.\n\nWed May 29 23:28:48 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (default_variables) [pyr]: PC = pascal.\n\nTue May 28 20:24:56 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (print_variable): Put a newline before `endef'.\n\nSat May 25 02:39:52 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.60.\n\nWed May 22 19:41:37 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.59.5.\n\nThu May 16 13:59:24 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (main): Do USGr3 setvbuf behavior #ifdef APOLLO.\n\tDon't handle SIGCHLD #ifdef USG (Apollo is USG but defines SIGCHLD).\n\nFri May 10 14:59:33 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* remake.c [sgi]: Don't include <sys/file.h>.\n\nWed May  8 01:54:08 1991  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* make.h (SIGHANDLER): #define as (void *) #if __STDC__,\n\telse (int (*)()).\n\t(SIGNAL): Use it to cast return value.\n\t* main.c (main): Cast SIG_IGN to SIGHANDLER when comparing.\n\t* job.c (block_signals, unblock_signals): Use SIGNAL instead of signal.\n\n\t* main.c: Declare mktemp to return char*, not int.\n\n\t* job.c (new_job): Don't increment files_remade.\n\t* remake.c (notice_finished_file): Do it here.\n\n\t* read.c (do_define): Don't clobber DEFINITION[-1] on empty defns.\n\tFree storage that is no longer needed.\n\nWed Apr 24 20:49:48 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)\n\n\t* misc.c (message): New fn to print informational msgs with\n\tleading \"make: \" or \"make[N]: \".\n\t* make.h: Declare it.\n\t* remake.c (update_file): Use it instead of printf.\n\nFri Apr 19 05:52:45 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): When there are no targets, if there were no\n\tmakefiles, print a different error message, which mentions makefiles.\n\nTue Apr 16 03:22:45 1991  Roland McGrath  (roland at geech.gnu.ai.mit.edu)\n\n\t* remake.c (update_file): Print \"nothing to be done\" instead of \"is\n\tup to date\" if FILE->cmds == 0.\n\n\t* job.c [!WIFEXITED]: Define if not already defined.\n\nThu Apr 11 18:00:50 1991  Roland McGrath  (roland at wookumz.gnu.ai.mit.edu)\n\n\t* arscan.c (ar_name_equal): Fixed truncation comparison.\n\nTue Apr  2 16:17:35 1991  Roland McGrath  (roland at churchy.gnu.ai.mit.edu)\n\n\t* glob.c: Use common version from djm.\n\t* dir.c: Snarfed #ifdef mess for <dirent.h> or whatever from glob.c.\n\t(dir_file_exists_p): Ignore directory entries with d_ino==0.\n\nMon Apr  1 20:49:45 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)\n\n\t* Version 3.59.4.\n\nFri Mar 29 19:16:18 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)\n\n\t* job.c (free_child): Free CHILD->environment and its elts.\n\nSat Mar 23 14:08:09 1991  Roland McGrath  (roland at albert.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Don't ignore lines containing only\n\tcomments if they start with a tab.  Such lines should be passed to\n\tthe shell for it to decide about the comments.\n\n\t* job.c (free_child): Free CHILD->command_lines and its elts, not\n\tCHILD->commands (which is obsolete).\n\t* job.h, job.c: Remove obsolete `commands' member of `struct child'.\n\nSun Mar 17 18:40:53 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* remake.c (update_file): Print a msg for a top-level up-to-date\n\tphony target (a different one than for a real file).\n\n\t* read.c (conditional_line): Boundary check so we don't check the\n\tvalue of the -1th elt of the stack (which is bogus).\n\nSat Mar 16 16:58:47 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* read.c (conditional_line): Don't evaluate an if* when we're\n\talready ignoring.  Instead, just push a new level, with a value of\n\t1, to keep ignoring.\n\nTue Mar 12 00:16:52 1991  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* Version 3.59.3.\n\nMon Mar 11 23:56:57 1991  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Quote backslashes\n\twhen building the shell -c line.\n\nFri Mar  8 01:40:18 1991  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* job.c (exec_command): Call user_access rather than setgid(getgid()).\n\n\t* misc.c (remove_comments): Renamed from collapse_line; took out\n\tcollapse_continuations call.\n\t* make.h: Change decl.\n\t* read.c (read_makefile): Collapse continuations on the line buffer\n\timmediately after reading it.  Call remove_comments rather than\n\tcollapse_line (which is now defunct).\n\nThu Feb 21 18:06:51 1991  Roland McGrath  (mcgrath at cygint.cygnus.com)\n\n\t* misc.c (user_access, make_access): New fns to toggle btwn permissions\n\tfor user data (files and spawning children), and permissions for make\n\t(for taking the load average, mostly).\n\t* make.h: Declare them.\n\t* job.c (start_job): Call make_access before wait_to_start_job, and\n\tuser_access after.\n\t* main.c (main): Call user_access before doing much.\n\nMon Feb  3 15:02:03 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* Version 3.59.2.\n\nTue Jan 29 20:30:50 1991  Roland McGrath  (roland at cygint.cygnus.com)\n\n\t* read.c (read_all_makefiles): Use allocated_variable_expand to expand\n\t`$(MAKEFILES)', since the results are used across calls to\n\tread_makefile, which could clobber them.\n\nWed Jan 23 00:24:10 1991  Roland McGrath  (roland at cygint.cygnus.com)\n\n\t* main.c (main): Call install_default_implicit_rules after reading\n\tmakefiles, not before.\n\t* default.c (install_default_implicit_rules): If a suffix-rule file\n\tentry has cmds, don't give it any from default_suffix_rules.\n\nFri Jan 17 17:39:49 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* arscan.c: Added support for AIX archives.\n\n\t* remake.c: Don't include ar.h.\n\t* main.c: Removed unused atol decl.\n\t* arscan.c (ar_scan): Declare arg FUNCTION to return long int.\n\t* ar.c (ar_touch): Don't perror for an invalid archive.\n\t* make.h: Declare lseek as long int.\n\n\t* job.c [hpux]: Define getdtablesize a la USG.\n\nSun Jan 12 21:08:34 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* Version 3.59.1.\n\nFri Jan 10 03:48:08 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* job.c (search_path): Take new arg, place to put full pathname (rather\n\tthan mallocing it).\n\t(exec_command): Pass it, using auto storage.\n\n\t* main.c (print_version): Updated copyright years.\n\nWed Jan  8 19:46:19 1991  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* job.c [_POSIX_SOURCE]: Just #include <sys/wait.h>, and define macro\n\tWAIT_NOHANG in terms of waitpid.\n\t[!_POSIX_SOURCE && (HAVE_SYS_WAIT || !USG)]: Don't #include <signal.h>\n\t(make.h does).\n\tDefine macro WAIT_NOHANG in terms of wait3.\n\t(child_handler): #ifdef on WAIT_NOHANG, not HAVE_SYS_WAIT || !USG.\n\tUse WAIT_NOHANG macro instead of wait3.\n\n\t* file.h (struct file.command_state): Remove unused elt.\n\nWed Dec 26 18:10:26 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* commands.c (set_file_variables): If FILE got its commands from\n\t.DEFAULT, make $< == $@ (4.3 BSD/POSIX.2d11 compat).\n\nMon Dec 24 17:36:27 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* default.c (default_variables): Rename 2nd LINK.s defn to LINK.S.\n\nFri Dec 14 15:05:25 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* vpath.c (selective_vpath_search): Check for makefile-mentioned before\n\tchecking for actual existence.  The old order loses if the containing\n\tdirectory doesn't exist (but a rule might make it).\n\n\t* make.h [__GNUC__]: Don't #define alloca if already #define'd.\n\n\t* rule.c (convert_to_pattern): Don't look at the target constructed for\n\tthe empty rule when making the null-suffix rule.  Construct it over\n\tagain, since the former may have been freed already.\n\nThu Dec 13 17:21:03 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* make.h [__GNU_LIBRARY__]: Include <unistd.h> to get random fn decls.\n\nWed Dec 12 17:12:59 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* make.h, arscan.c, glob.c: Only include <memory.h> #ifdef USG.\n\n\t* variable.c (define_variable_in_set): Replace env_overrides check that\n\twasn't really redundant (undoing Sep 28 change).  Add comment saying\n\twhy this check is necessary.\n\n\t* job.c, main.c [DGUX]: Needs siglist like USG.\n\nMon Dec 11 01:19:29 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* default.c [M_XENIX]: For rules that are different for Xenix, use the\n\tgeneric Unix version #ifdef __GNUC__.\n\n\t* main.c [M_XENIX]: Use USGr3-style setvbuf call.\n\n\t* read.c (find_percent): Do backslash folding correctly, not leaving\n\textra crud on the end of the string.\n\nSun Dec 10 21:48:36 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* job.c: Don't declare wait3 if it's #defined.\n\n\t* GNUmakefile, compatMakefile, make.texinfo: Change make-info\n\tto make.info.\n\nThu Dec  7 21:20:01 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* make.h [STDC_HEADERS || __GNU_LIBRARY__ || _POSIX_SOURCE]: Use\n\tANSI <string.h> and names for str/mem functions.\n\tUse <stdlib.h> to declare misc fns rather than explicit decls.\n\t[_POSIX_SOURCE]: Don't declare kill (<signal.h> will).\n\tInclude <sys/types.h> before <signal.h> because some braindead\n\tnonconformant 1003.1 implementation needs it.\n\t* misc.c: Don't declare malloc, realloc.  Do it in make.h.\n\t* arscan.c, glob.c: Use sequence for string fns from make.h verbatim.\n\t* make.h (S_ISDIR, S_ISREG): Declare if necessary.\n\t* commands.c (delete_child_targets), job.c (search_path), read.c\n\t(construct_include_path): Use S_ISfoo(m) instead of\n\t(m & S_IFMT) == S_IFfoo.\n\t* dir.c, glob.c [_POSIX_SOURCE]: Use dirent.\n\nWed Nov 29 22:53:32 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* Version 3.59.\n\nTue Nov 28 16:00:04 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* arscan.c (ar_name_equal) [APOLLO]: Don't do `.o' hacking.  On Apollos\n\tthe full file name is elsewhere, and there is no length restriction (or\n\tso I'm told).\n\nThu Nov 23 17:33:11 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* load.c [hp300 && BSD] (LDAV_CVT): Define for this system.\n\nTue Nov 21 07:58:40 1990  Roland McGrath  (roland at albert.ai.mit.edu)\n\n\t* read.c (record_files): Fix trivial bug with deciding to free storage\n\tfor a file name.\n\nThu Nov 16 06:21:38 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* compatMakefile ($(bindir)/make): Install it setgid kmem.\n\nThu Nov  1 16:12:55 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* GNUmakefile (make-*.tar.Z): Use `h' option to tar (dereference\n\tsymlinks), to grab texinfo.tex from wherever it lives.\n\nTue Oct 30 16:15:20 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* Version 3.58.13.\n\nFri Oct 26 14:33:34 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* GNUmakefile: make-*.tar.Z: Include texinfo.tex.\n\nTue Oct 23 19:34:33 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* main.c (define_makeflags): When there are no flags to write, make\n\tsure the array has two leading nulls, since `MAKEFLAGS' is defined from\n\t&flags[1].\n\n\t* main.c (default_keep_going_flag): New variable (constant one).\n\t(command_switches: -k, -S): Use above for default value.\n\t(define_makeflags): Only write flag/flag_off switches if they are on,\n\tand either there is no default value, or they are not the default.\n\nMon Oct 22 16:14:44 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* main.c (struct command_switch): New member `no_makefile'.\n\t(command_switches: -n, -q, -t): Set no_makefile == 1.\n\t(define_makeflags): Take new arg MAKEFILE: if nonzero, don't use\n\toptions whose `no_makefile' flags are set.\n\t(main): Call define_makeflags with MAKEFILE==1 before remaking\n\tmakefiles, and again with MAKEFILE==0 before remaking goals.\n\nTue Oct  2 17:16:45 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* Version 3.58.12.\n\nMon Oct  1 15:43:23 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* arscan.c [HPUX]: Use PORTAR==1 format.\n\nSat Sep 29 16:38:05 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* make.h, remake.c, arscan.c: Don't declare `open'.\n\nFri Sep 28 04:46:23 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* variable.c (define_variable_in_set): Remove redundant -e check.\n\nWed Sep 26 00:28:59 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* job.c (start_job): Set RECURSIVE from the right elt of\n\tCHILD->file->cmds->lines_recurse.\n\n\t* commands.c (chop_commands): Don't botch the line count for allocating\n\tCMDS->lines_recurse.\n\n\t* Version 3.58.11.\n\n\t* job.c (start_job): Don't always increment CHILD->command_line!  Only\n\tdo it when CHILD->command_ptr has run out!  (Dumb bug.  Sigh.)\n\nThu Sep 20 02:18:51 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* GNUmakefile [ARCH]: Give explicit rule for remote.{c,dep} to use\n\tvariable `REMOTE' for more flags.\n\t($(prog)): Link in $(LOADLIBES).\n\nWed Sep 19 02:30:36 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* commands.h (struct commands): New member `ncommand_lines', the number\n\tof elts in `command_lines' et al.\n\t* commands.c (chop_commands): Set `ncommand_lines' elt of CMDS, and\n\tdon't put a nil pointer at the end of `command_lines'.\n\t* job.h (struct child): New member `command_lines' to hold\n\tvariable-expanded command lines.\n\t* job.c (new_job): Store expanded command lines in `command_lines'\n\tmember of new child.  Don't clobber FILE->cmds.\n\t(start_job): Use CHILD->command_lines in place of\n\tCHILD->file->cmds->command_lines.\n\n\t* variable.h, variable.c, job.c, expand.c: Undo yesterday's change,\n\twhich is no longer necessary since we have cleverly avoided the issue.\n\n\t* job.c (start_job): Don't variable-expand each command line.\n\t(new_job): Do them all here, storing the expansions in the array.\n\nTue Sep 18 01:23:13 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* variable.h (struct variable): Remove `expanding' member.\n\t* variable.c (define_variable_in_set): Don't initialize it.\n\t* expand.c (struct variable_expanding): New type, a linked list\n\tcontaining `struct variable' pointers.\n\t(variables_expanding): New variable, the chain of variables currently\n\tbeing expanded.\n\t(recursively_expand): Don't test and set `expanding' member.\n\tInstead, run through the `variables_expanding' chain looking for a link\n\treferring to V to find self-reference.  Add a new link to the chain,\n\tdescribing V, before recursive expansion, and pop it off afterward.\n\t* job.c (child_handler): Save `variables_expanding' and clear it before\n\tcalling start_job, and restore it afterward.  This avoids major lossage\n\twhen the SIGCHLD comes in the middle of variable expansion.\n\nMon Sep 17 14:46:26 1990  Roland McGrath  (roland at geech.ai.mit.edu)\n\n\t* job.c, commands.c: Don't define sigmask.\n\t* make.h: Put it here instead.\n\n\t* variable.c (target_environment): If `.NOEXPORT' was specified as a\n\ttarget, only export command-line and environment variables, and\n\tfile-origin variables that were in the original environment.\n\n\t* make.man: Add missing ?roff control for `-I' option description.\n\nThu Sep 13 14:10:02 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* load.c [UMAX]: Move #include <sys/sysdefs.h> to [not UMAX_43].\n\nWed Sep 12 15:10:15 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* expand.c (recursively_expand): Don't use `reading_filename' and\n\t`reading_lineno_ptr' if they're nil.\n\nThu Aug 30 17:32:50 1990  Roland McGrath  (roland at geech)\n\n\t* Version 3.58.10.\n\nTue Aug 28 04:06:29 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* job.c [USG] (unknown_children_possible): New variable, set nonzero\n\twhen it's possible for children not in the `children' chain to die.\n\t(block_signals) [USG]: Set it.\n\t(unblock_signals) [USG]: Clear it.\n\t(child_handler) [USG]: Don't complain about unknown children if\n\t`unknown_children_possible' is set.\n\n\t* read.c (do_define): Make sure there's enough space for the newline,\n\tso we don't write off the end of allocated space.\n\n\t* arscan.c (ar_name_equal): Fixed to work when MEM is AR_NAMELEN-1 but\n\tNAME is not the same length.\n\nSat Aug 25 16:17:14 1990  Roland McGrath  (roland at geech)\n\n\t* job.c (construct_command_argv_internal): Use a static char array for\n\ta constant, since old C has no auto aggregate initializers.\n\nThu Aug 23 16:11:03 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* job.c (search_path): If PATH is nil or \"\" use a default path.\n\nWed Aug 22 01:05:32 1990  Roland McGrath  (roland at churchy.ai.mit.edu)\n\n\t* Version 3.58.9.\n\n\t* job.c (exec_command): Don't take PATH and SHELL args.  Get them from\n\tENVP.\n\t(child_execute_job): Don't take FILE arg, and don't pass path and shell\n\tto exec_command.\n\t(start_job): Don't pass FILE arg to child_execute_job.\n\t* function.c (expand_function: `shell'): Ditto.\n\t* main.c (main): Don't pass path and shell to exec_command.\n\nFri Aug 17 23:17:27 1990  Roland McGrath  (roland at geech)\n\n\t* job.c (construct_command_argv_internal): New fn broken out of\n\tconstruct_command_argv.  Takes strings SHELL and IFS instead of doing\n\tvariable expansion for them.  Recurse to make an argv for SHELL,\n\tpassing SHELL==0.  When SHELL==0, don't recurse for shell argv; make a\n\tsimple one using /bin/sh.\n\t(construct_command_argv): Do the variable expansions and call above.\n\nThu Aug 16 19:03:14 1990  Roland McGrath  (roland at geech)\n\n\t* read.c (multi_glob): For ~USER/FILE, if USER isn't found, don't\n\tchange the file name at all.\n\nTue Aug  7 18:33:28 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* function.c (expand_function: `suffix'/`notdir'): Don't kill the last\n\tspace if we never wrote one.\n\n\t* function.c (expand_function: `suffix'): Retain the dot, like the\n\tdocumentation says.\n\nMon Aug  6 14:35:06 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.58.8.\n\n\t* main.c (decode_switches): For positive_int and floating cases, move\n\tSW past the arg (and don't set it to \"\"), so another switch can follow.\n\nFri Aug  3 00:43:15 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* job.c (child_execute_job): Use unblock_signals instead of\n\tpush_signals_blocked_p (0).\n\n\t* main.c (fatal_signal_mask): New variable, mask of signals caught with\n\tfatal_error_signal.\n\t(main): Set it.\n\t* job.c ({block,unblock}_children): Renamed to {block,unblock}_signals.\n\tBlock/unblock both child signal and signals in fatal_signal_mask.\n\t(children_blocked_p_{stack,max,depth}, {push,pop}_children_blocked_p):\n\tRenamed from children to signals.  Use {block,unblock}_signals instead\n\tof {block,unblock}_children.\n\t* commands.c (fatal_error_signal), job.c (wait_for_children, new_job,\n\tchild_execute_job, main, log_working_directory), function.c\n\t(expand_function: `shell'), job.h: Rename {push,pop}_children_blocked_p\n\tto {push,pop}_signals_blocked_p.\n\t* job.c (child_handler): Call {block,unblock}_signals instead of just\n\t{block,unblock}_remote_children.  We need to block the fatal signals.\n\nThu Aug  2 22:41:06 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* main.c, function.c: Fixed typos in comments.\n\n\t* file.c (print_file_data_base): Fix computation of avg files/bucket.\n\nTue Jul 31 22:11:14 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.58.7.\n\nWed Jul 25 16:32:38 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* arscan.c (ar_name_equal): Fixed to really do it right.\n\t(ar_member_pos): Fixed order of args.\n\t* ar.c (ar_member_date_1): Ditto.\n\nFri Jul 20 15:30:26 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* arscan.c (ar_name_equal): Rewritten.  Accounts for a possible\n\ttrailing slash in MEM.\n\n\t* remake.c (f_mtime): Keep track of whether ARNAME is used and free it\n\tif not.  Also free MEMNAME.\n\t* ar.c (ar_member_date, ar_touch): Ditto.\n\n\t* arscan.c (arscan) [HPUX or hpux]: Treat same as USGr3 PORTAR==1.\n\n\t* make.h: If NSIG is not defined, but _NSIG is, #define NSIG _NSIG.\n\n\t* compatMakefile: Don't use $* in explicit rules.\n\n\t* default.c (default_variables: \"PREPROCESS.S\"): Include $(CPPFLAGS).\n\n\t* remake.c (f_mtime): If FILE is an ar ref, get the member modtime.\n\n\t* function.c (string_glob): Terminate the string properly when it's\n\tempty.\n\nWed Jul 18 11:26:56 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.58.6.\n\n\t* commands.c (set_file_variables): Fixed computation for ^F/?F elt len.\n\nSat Jul 14 13:41:24 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* job.c (construct_command_argv): Always use\n\tallocated_variable_expand_for_file instead of variable_expand_for_file\n\tbecause we might be called from inside a variable expansion (for the\n\t`shell' function).\n\n\t* function.c (expand_function: `shell'): Free the arglist's storage\n\tcorrectly.  construct_command_argv only allocates ARGV and ARGV[0].\n\n\t* job.c (children_blocked_p_idx): Renamed to children_blocked_p_depth.\n\t(push_children_blocked_p, pop_children_blocked_p): Use ..._depth\n\tinstead of ..._idx, and do it right!\n\nWed Jul 11 15:35:43 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.h (SIGNAL): New macro to replace `signal' calls.  Does arg and\n\tret value casts to (void *) #ifdef __STDC__ to avoid conflicts btwn\n\tANSI and BSD `signal' and handler types.\n\t* main.c (main), job.c (child_handler): Use it.\n\nFri Jul  6 00:00:38 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* ar.c (ar_member_date, ar_touch): Pass 2nd arg to f_mtime.\n\n\t* read.c (read_makefile): Search the include path for MAKEFILES\n\tvariable makefiles (TYPE == 1), like it says in the manual.\n\n\t* file.h (struct file), main.c (struct command_switch): Remove trailing\n\tcommas from enums.\n\n\t* commands.c (execute_file_commands): Remove unused variables.\n\t* commands.h: Declare chop_commands.\n\t* make.h: Declare uniquize_deps.\n\t* main.c (main): Remove unused variable.\n\t(decode_switches): Remove unused label.\n\t* remake.c: Include \"ar.h\" for ar_parse_name decl.\n\t* implicit.c (try_implicit_rule): Remove unused variable.\n\t* function.c (expand_function: `shell'): Declare fork, pipe.\n\t* ar.c: Declare ar_name_equal.\n\n\t* GNUmakefile: If using gcc, add warning flags to CFLAGS.\n\n\t* remake.c: Remove decl of ar_member_date, since it's done in make.h.\n\n\t* remake.c (f_mtime): For ar refs, allow the archive to be found via\n\tVPATH search if we're searching, and change the ar ref accordingly.\n\n\t* ar.c (ar_parse_name): New global fn to parse archive-member\n\treferences into the archive and member names.\n\t(ar_member_date, ar_touch): Use it.\n\t* make.h: Declare it.\n\n\t* remake.c (f_mtime): After doing rename_file, do check_renamed instead\n\tof assuming rename_file will always set FILE->renamed (which it won't).\n\n\t* vpath.c (selective_vpath_search): Only accept prospective files that\n\tdon't actually exist yet are mentioned in a makefile if the file we are\n\tsearching for isn't a target.\n\nWed Jul  4 04:11:55 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* remake.c (update_goal_chain): Do check_renamed after calling\n\tfile_mtime.\n\t(check_dep): Ditto after update_file.\n\n\t* file.c (rename_file): Prettied up long message for merging cmds.\n\n\t* remake.c (update_file_1): Get each dep file's modtime, and allow for\n\tit being renamed, before checking for a circular dep, since a renaming\n\tmay have introduced one.\n\nTue Jul  3 18:15:01 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* ar.c (ar_touch): Don't free ARNAME since enter_file holds onto the\n\tstorage.\n\n\t* function.c (string_glob): Don't leave a trailing space.\n\n\t* read.c (do_define): Allow leading whitespace before `endef'.\n\nMon Jul  2 14:10:16 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* implicit.c (pattern_search): No longer take NAME arg.  Instead take\n\tARCHIVE flag.  If ARCHIVE is nonzero, FILE->name is of the form\n\t\"LIB(MEMBER)\"; rule for \"(MEMBER)\" is searched for, and LASTSLASH is\n\tset to nil.  Since NAME was only non-nil when it was the archive member\n\tname passed by try_implicit_rule, this change easily allows turning off\n\tLASTSLASH checking for archive members without excessive kludgery.\n\t(try_implicit_rule): Pass ARCHIVE flag instead of file name.\n\n\t* Version 3.58.5.\n\n\t* commands./c (set_file_variables): Don't kill last char of $(^D) elts.\n\nSat Jun 30 00:53:38 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* ar.c (ar_member_date): Don't free ARNAME since enter_file holds onto\n\tthe storage.\n\n\t* arscan.c (ar_scan) [sun386 && PORTAR == 1]: Treat like USGr3.\n\nWed Jun 27 14:38:49 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* main.c (main): Put a newline on the debugging message when deciding\n\tnot to remake a makefile to avoid a possible loop.\n\tOnly decide not to remake makefiles that have commands (as well as\n\tbeing targets and having no deps).\n\nFri Jun 22 12:35:37 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* default.c (default_variables): Define `LINK.s' and `LINK.S'.\n\t(default_suffix_rules): Define .S.o rule.\n\n\t* job.c (construct_command_argv): If we decide to go the slow route,\n\tfree all storage for the chopped args.\n\t(start_job): Free the argument list's storage correctly.\n\tconstruct_command_argv only allocates ARGV and ARGV[0].\n\nTue Jun 19 18:27:43 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.58.4.\n\nFri Jun 15 21:12:10 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* glob.c: New version from ai-lab which doesn't do [^abc].\n\nThu Jun  7 00:30:46 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* dir.c: Copied dirent vs direct et al mess from glob.c.\n\n\t* glob.c: Replaced with updated version from djm.\n\t* glob.c: Check macro DIRENT instead of _POSIX_SOURCE for <dirent.h>.\n\t__GNU_LIBRARY__ implies DIRENT and STDC_HEADERS.\n\nThu May 31 22:19:49 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* vpath.c (vpath_search): Don't stop the loop if a pattern matches but\n\tthe search fails.  All matching patterns have their paths searched\n\t(like it says in the manual).\n\n\t* make.texinfo (Rules: Directory Search: Selective Search): Say that\n\tmultiple `vpath' directives with the same pattern DO accumulate, not\n\tsupersede earlier ones.\n\n\t* vpath.c (print_vpath_data_base): Increment the count of vpaths on\n\teach loop iteration, rather than letting it stay zero.\n\n\t* Version 3.58.3.\n\n\t* job.c (block_children, unblock_children): Made static.\n\t(push_children_blocked_p, pop_children_blocked_p): New functions to\n\tpush and pop whether children are blocked or not.\n\t* job.h: Declare push_children_blocked_p, pop_children_blocked_p and\n\tnot block_children, unblock_children.\n\t* commands.c (fatal_error_signal), job.c (wait_for_children, new_job,\n\tchild_execute_job), main.c (main, log_working_directory): Use sequences\n\tof push_children_blocked_p (1) and pop_children_blocked_p () instead of\n\texplicitly blocking and unblocking children.\n\t* function.c (expand_function: `shell'): Don't unblock children.  The\n\tpush-pop sequence in wait_for_children makes it unnecessary.\n\nTue May 29 21:30:00 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* read.c (do_define): Don't include the last newline in the definition.\n\n\t* function.c (expand_function: `shell'): Call construct_command_argv\n\tbefore forking and don't fork if it returns nil.  Free the argument\n\tlist's storage before finishing.\n\n\t* job.c (start_job): Free the storage for the child's argument list\n\tin the parent side of the fork after the child has been spawned.\n\n\t* job.c (start_job): If construct_command_argv returns nil, go to the\n\tnext command line.\n\n\t* job.c (construct_command_argv): Use the shell if the command contains\n\tan unterminated quote.\n\nWed May 23 19:54:10 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.58.2.\n\n\t* read.c (read_makefile): Parse \"override define\" correctly.\n\nThu May 17 15:25:58 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* arscan.c [USG]: Don't declare memcpy and memcmp.  <memory.h> should\n\tdo this anyway (and lack of declarations is harmless).\n\n\t* remote-customs.c: Renamed to remote-cstms.c for System V.\n\t* remote.c [CUSTOMS]: Changed accordingly.\n\nSun May 13 14:38:39 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* GNUmakefile: Use same cmds for doc tar.Z as for dist tar.Z (so the\n\tcontents go in make-N.NN).\n\nThu Apr 26 19:33:25 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.58.1.\n\nWed Apr 25 20:27:52 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* job.c (init_siglist): Don't do SIGUSR1 and SIGUSR2 if they are the\n\tsame as SIGIO and SIGURG (true on Cray).\n\nTue Apr 24 20:26:41 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* arscan.c (ar_scan): Do behavior for PORTAR == 1 and USGr3 also\n\t#ifdef APOLLO.\n\nWed Apr 11 10:00:39 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* job.c (exec_command): Set the effective GID to the real GID.  Somehow\n\tthis code got lost.\n\n\t* implicit.c (pattern_search): Use the right index variable when\n\tseeing if we need to expand FILE->also_make.\n\nSun Mar  4 09:18:58 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.58.0.\n\n\t* remake.c (remake_file): Treat non-targets without commands under -t\n\tthe same as anything else without commands.\n\nSat Feb 24 17:46:04 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* default.c (default_variables: PREPROCESS.S): Removed $< from defn.\n\n\t* main.c (main): Ignore arguments that are the empty string, rather\n\tthan feeding them to enter_file and barfing therein.\n\nWed Feb 14 16:28:37 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* main.c (main): Call construct_include_path after doing chdirs.\n\nThu Feb  8 13:43:44 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.58.\n\nSat Feb  3 22:06:55 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.57.7.\n\n\t* make.texinfo (Implicit: Catalogue of Rules): For RCS, noted that\n\tworking files are never overwritten by the default rule.\n\nThu Feb  1 17:27:54 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* rule.c (count_implicit_rule_limits): Redid loop control to not run\n\ttwice on freed rules.\n\n\t* GNUmakefile: Made `.dep' files be architecture-specific too.\n\n\t* main.c (main, log_working_directory) [USG]: Block children around\n\tcalls to `getwd' (actually `getcwd' on USG), because that function\n\tsometimes spawns a child running /bin/pwd on USG.\n\nTue Jan 30 14:02:50 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* function.c (subst_expand): Pay attention to SUFFIX_ONLY, putz.\n\nWed Jan 24 21:03:29 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* make.man: Fixed repeated word.\n\n\t* make.texinfo (Missing): Reworded a buggy sentence.\n\nMon Jan 22 12:39:22 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* main.c (print_version): Added 1990 to copyright notice.\n\n\t* Version 3.57.6.\n\nSat Jan 20 11:52:01 1990  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* file.c (rename_file): Don't free the storage for the old name, since\n\tit might not have been malloc'd.\n\n\t* job.c (construct_command_argv): Call\n\tallocated_variable_expand_for_file instead of variable_expand_for_file\n\tto expand `$(SHELL)'.\n\n\t* make.texinfo (Bugs): Change address from roland@wheaties.ai.mit.edu\n\tto roland@prep.ai.mit.edu.\n\nTue Jan 16 19:22:33 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.57.5.\n\nSun Jan 14 16:48:01 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* job.c (start_job): Only call wait_to_start_job for the first command\n\tline in each sequence.\n\nThu Jan  4 14:27:20 1990  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* load.c [LDAV_BASED] (wait_to_start_job): Loop while job_slots_used >\n\t0, not > 1.\n\n\t* job.c (search_path): Don't return a pointer to local storage.\n\tAllocate data space for the pathname instead.\n\n\t* function.c (expand_function: `shell'): Don't write garbage if the\n\tchild wrote no output.\n\nWed Jan  3 15:28:30 1990  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.57.4.\n\n\t* file.h (struct file): New member `renamed', a `struct file *' that is\n\tthe place this file has been renamed to (or nil).\n\t(check_renamed): Macro to check for a file having been renamed.\n\tDereferences the renaming and sets the given variable.\n\t* file.c (rename_file): Completely rewritten.  Renames in place if\n\tpossible, or moves FILE to a different hash bucket if there is no\n\texisting file with the new name.  If there is an existing file with the\n\tnew name, FILE is merged into it and FILE->renamed is set to point to\n\tit.\n\t* variable.c (merge_variable_sets): New fn to merge two variable sets.\n\t(merge_variable_set_lists): New fn to merge two variable set lists.\n\t* variable.h: Declare merge_variable_set_lists.\n\t* remake.c (update_file_1, check_dep): Run `check_renamed' after\n\tcalling file_mtime, check_dep.\n\t(update_file): Same after update_file_1.\n\t(update_goal_chain, update_file_1, check_dep): Same after update_file.\n\n\t* read.c (uniquize_deps): New fn, broken out of record_files, to remove\n\tduplicate deps from a chain.\n\t(record_files): Use it.\n\t* implicit.c (pattern_search): Use uniquize_deps.\n\n\t* file.h (file_mtime_1): New macro, like file_mtime, but take second\n\targ, passed to f_mtime.\n\t(file_mtime): Implement as file_mtime_1 (file, 1).\n\t(file_mtime_no_search): New macro: file_mtime (file, 0).\n\t* remake.c (f_mtime): Take new arg SEARCH.  Only do VPATH and `-lNAME'\n\tsearching if it is nonzero.\n\t* main.c (main): Use file_mtime_no_search for makefiles.\n\t* remake.c (update_goal_chain): Use file_mtime_no_search if MAKEFILES.\n\n\t* main.c (printed_version): New variable, init'd to zero.\n\t(print_version): Set it to nonzero before returning.\n\t(die): If -v and !printed_version, call print_version before clean up\n\tand death.\n\n\t* main.c (log_working_directory): Keep track of whether or not the\n\t\"Entering\" message has been printed, and return without printing the\n\t\"Leaving\" message if not.\n\n\t* main.c (decode_switches): Don't complain about missing args before\n\tchecking for a noarg_value elt in the command_switch structure.\n\nTue Jan  2 15:41:08 1990  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.texinfo (Commands: Recursion: Options/Recursion): Document\n\tspecial case of -j.\n\n\t* make.texinfo, main.c, job.c: Changed copyright notices to include\n\t1990.\n\n\t* make.texinfo (Top): Fixed introductory paragraph, which said that\n\t`make' itself (instead of the manual) has various chapters.\n\t(Variables: Advanced: Substitution Refs): When pxref'ing about\n\t`patsubst', use node `Text Functions', not `Functions'.\n\tAdd an xref about `patsubst' after description of $(var:a%b=c%d).\n\t(Functions: Syntax of Functions): Explain why mixing delimiters in\n\tfunction/var refs is unwise.  Clarify fn arg evaluation order.\n\t(Options): Reworded sentence about `-e'.\n\t(Implicit: Implicit Variables): Don't say `RM' is unused.\n\tSay the dflt values for the flag vars is empty unless otherwise noted,\n\tsince some have defaults.\n\t(Implicit: Pattern Rules: Pattern Examples): Clarified use of $< and $@\n\tin first example.\n\t(Implicit: Last Resort): Don't say the .DEFAULT example creates files\n\t\"silently\".  It's automatic, but not silent.\n\t(Implicit: Search Algorithm): Fixed confusing ungrammatical sentence\n\tfor item 5.1.\n\t(Archives: Archive Update): Added missing `next' pointer.\n\t(Archives: Archive Symbols): Note that GNU `ar' deals with this\n\tautomatically.\n\n\t* job.c (search_path): New fn, to search for an executable file in a\n\tsearch path (broken out of exec_command).\n\t(exec_command): Take fourth arg, the shell program to use (if\n\tnecessary).  Use search_path for the program, and the shell program.\n\tPass args \"file args ...\" to shell program (with no -c), where FILE is\n\tthe full pathname of the program (script) to be run.\n\t(child_execute_job): Pass shell program to exec_command.\n\t* main.c (main): Ditto.\n\n\t* main.c (main): Don't write a message if exec_command returns, because\n\tit will never return.\n\nFri Dec 22 16:19:58 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* default.c (default_variables: \"LINK.cc\"): Use $(C++FLAGS) instead of\n\t$(CFLAGS).\n\nWed Dec 20 09:58:48 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* job.c (new_job): If start_job set the child's `command_state' to\n\t`cs_finished', call notice_finished_file.\n\nSun Dec 17 19:45:41 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* Version 3.57.3.\n\nWed Dec 13 17:57:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* rule.c (convert_to_pattern): Accept files with dependencies as\n\tsuffix rules.\n\nThu Nov 30 15:47:13 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.57.2.\n\n\t* function.c (expand_function: `shell'): Don't clobber BUFFER and then\n\ttry to free it.\n\n\t* remake.c (update_file_1): Took code to force remake of nonexistent\n\tdeps out of #if 0, and changed the test to nonexistent non-intermediate\n\tdeps.  In version 4, I think removing this test completely will\n\timplement the new feature that if a: b and b: c and c is newer than a,\n\tb need not be remade.\n\nSun Nov 26 16:12:41 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* compatMakefile (load.o, remote.o): Use $*.c instead of explicit file\n\tnames so that using VPATH works.\n\nTue Nov 21 14:57:18 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.57.1.\n\nFri Nov 10 03:28:40 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remake.c (check_dep): Set *MUST_MAKE_PTR if FILE does not exist after\n\tbeing updated.  (The exact opposite test was here before; why???)\n\t(update_file_1): Set a dep's `changed' member after updating it if it\n\tis phony and has commands (because they will then always be executed).\n\nThu Nov  9 13:47:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* load.c [UMAX]: #ifdef UMAX_43 include different headers for the\n\t`inq_stats' call.\n\t* compatMakefile (LOAD_AVG): Document UMAX_43.\n\n\t* Version 3.57.0.\n\n\t* commands.c (chop_commands): New function to chop commands into lines.\n\t* job.c (new_job): Break that code out, and call chop_commands.\n\t* remake.c (remake_file): Call chop_commands before looking at\n\tFILE->cmds->any_recurse.\n\n\t* make.texinfo (Running: Goals): Don't say that the default target\n\twon't be taken from an included makefile.\n\n\t* remake.c (update_file_1): #if 0 out setting MUST_MAKE if a dep\n\tdoesn't exist.\n\nFri Nov  3 15:53:03 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.57.\n\n\t* variable.c (try_variable_definition): Don't calculate useless value.\n\n\t* main.c (define_makeflags): Fixed -j propagation.\n\n\t* commands.c (execute_file_commands): Removed unused variable.\n\nSun Oct 29 11:11:15 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (execute_file_commands): If the commands are empty, call\n\tnotice_finished_file before returning.\n\nSat Oct 28 23:06:32 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remake.c (update_file_1): Don't always update a target that has no\n\tdeps.  Only do this for double-colon targets.\n\nWed Oct 25 16:36:16 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* main.c (main) [hpux]: hpux == HPUX.\n\t* compatMakefile (defines): Document that HPUX should be defined.\n\nTue Oct 24 19:19:48 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.8.\n\n\t* job.c (exec_command): Fixed what mode bits are checked.\n\n\t* remake.c (update_file_1): \"No cmds and no deps actually changed\"\n\tloses if ! FILE->is_target.\n\n\t* make.texinfo (Variables: Setting): Don't say that spaces after a\n\tvariable definition are ignored (since they aren't).\n\nMon Oct 23 14:34:23 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.7.\n\n\t* remake.c (update_file_1): If, after being updated, any dependency\n\tdoes not exist, remake the target.\n\n\t* remake.c (update_file_1): Always update if FILE has commands but no\n\tdeps.\n\n\t* commands.c (execute_file_commands): If we return early because there\n\tare no commands, set FILE->updated.\n\nThu Oct 19 18:47:37 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* arscan.c (ar_scan) [M_XENIX]: Don't run atoi or atol on the\n\t`struct ar_hdr' members that are int or long int on Xenix.\n\nSat Oct 14 10:43:03 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* arscan.c (ar_scan): Cosmetic clean ups.\n\t(ar_name_equal): New function to compare names, handling truncated\n\tmember names and special `.o' truncation.\n\t(ar_member_pos): Use ar_name_equal.\n\t* ar.c (ar_member_date_1): Use ar_name_equal.\n\n\t* Version 3.56.6.\n\n\t* file.h (struct file): Made `update_status' a `short int', and moved\n\tit before `command_state' so the bitfields can be packed better.\n\n\t* remake.c (files_remade): Made global.\n\t(notice_finished_file): Don't increment files_remade.\n\t* job.c (new_job): Do.\n\n\t* job.c (start_job): Don't return a value.  Always set\n\tCHILD->file->command_state to either cs_running or cs_finished.\n\t(new_job, child_handler): Don't expect start_job to return a value.\n\tInstead, look at the file's command_state.\n\n\t* commands.c (chop_commands): Merged into job.c (new_job).\n\t* commands.h: Don't declare chop_commands.\n\n\t* job.c (start_job): Made static.\n\t(new_job): New function to create a `struct child' and call start_job.\n\t(free_child): New function to free a `struct child'.\n\t(child_handler, new_job): Call it.\n\t* job.h: Don't declare start_job.  Do declare new_job.\n\t* commands.c (execute_file_commands): Call new_job.\n\n\t* commands.c (execute_file_commands): Don't set FILE->update_status if\n\tstart_job fails.\n\n\t* function.c (expand_function): Don't use `reading_filename' and\n\t`reading_lineno_ptr' if they're nil.\n\nFri Oct 13 18:16:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* read.c (find_semicolon): New function to look for an unquoted ; not\n\tpreceded by an unquoted # in a string.\n\t(read_makefile): Call it before expanding the line.  If it finds a ;,\n\tcut the line short there before expanding it.  If not, call it again\n\tafter expanding.\n\n\t* commands.c (execute_file_commands): Don't check FILE->command_state.\n\tWe won't get called unless it's cs_not_started.\n\n\t* read.c (read_makefile): Call collapse_line on the variable-expanded\n\trule line after checking for ; and #.\n\n\t* job.c (start_job): When there are no more commands, always return 0.\n\t* commands.c (execute_file_commands): Don't put the new child in the\n\t`children' chain unless FILE->command_state is cs_running.\n\n\t* read.c (read_makefile): Rewrote ;-handling to only do it once (why\n\tdid I do it twice??) and to check for a # before the ;.\n\n\t* job.c (start_job): Set CHILD->file->update_status to 0 when we run\n\tout of commands.  Set it to 1 before returning failure.\n\t(child_handler): Don't set C->file->update_status to 0 when start_job\n\treturns success and commands are not running.\n\n\t* read.c (read_makefile): If there is a # before the ; for commands,\n\tforget the ; and commands.\n\nThu Oct 12 15:48:16 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* job.c (child_execute_job): Pass -c to the shell.\n\nWed Oct 11 18:41:10 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.5.\n\n\t* main.c (define_makeflags): Cleaned up to keep better track of dashes\n\twritten, etc.\n\n\t* function.c (expand_function: `shell'): When converting newlines to\n\tspaces in output, search with `index' calls rather than a simple loop.\n\n\t* main.c (main): Make sure stdout is line-buffered.\n\n\t* main.c (decode_switches): Always check for missing switch arg.\n\nMon Oct  9 17:17:23 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.4.\n\nSat Oct  7 00:32:25 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (set_file_variables): #ifdef NO_ARCHIVES, still set $@ and\n\t$%.\n\n\t* commands.c (set_file_variables): Include a trailing slash in the\n\tdirectory variables (@D, etc.).\n\n\t* job.c (child_handler): Call notice_finished_file after changing a\n\tchild's state to `cs_finished'.\n\t* remake.c (update_file_1): Don't call notice_finished_file if\n\tFILE->command_state == cs_finished.\n\nWed Oct  4 16:09:33 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.3.\n\nTue Oct  3 21:09:51 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* read.c (read_all_makefiles): When setting elements of MAKEFILES from\n\tthe contents of read_makefiles, make sure we're using the right\n\telement.\n\n\t* dir.c, glob.c [USGr3 || DIRENT]: Don't define d_ino as d_fileno.\n\n\t* Version 3.56.2.\n\n\t* remake.c (update_file_1): Return zero after calling remake_file if\n\tFILE->command_state != cs_finished.  Test update_status thoroughly.\n\n\t* commands.c (execute_file_commands): Don't call notice_finished_file.\n\n\t* remake.c (remake_file): Return immediately after calling\n\texecute_file_commands.\n\nSat Sep 30 14:57:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.1 (alpha).\n\n\t* file.h (struct file): Made `update_status' not be a bitfield, since\n\tsome broken compilers don't handle it right.\n\n\t* function.c (expand_function: `join'): Don't clobber the pointers and\n\tthen try to free them.\n\n\t* job.c (exec_command): Fixed & vs = precedence problem.\n\nThu Sep 28 17:29:56 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remake.c (update_file_1): Fixed typo in debugging output.\n\n\t* remake.c (library_file_mtime): Search for /usr/local/lib/libLIB.a\n\tafter /usr/lib/libLIB.a.\n\nTue Sep 26 16:07:58 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* read.c (conditional_line): For `ifeq (a, b)', swallow space after the\n\tcomma.\n\nSun Sep 24 13:25:32 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* function.c (patsubst_function): If BY_WORD and the match is not a\n\tfull word, update the text pointer correctly.\n\n\t* function.c (expand_function: `word'): Don't lose track of the second\n\targ's expansion and free something else instead.\n\nFri Sep 22 16:15:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.56.\n\nThu Sep 21 14:28:42 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* main.c (main): Make an array of the mtimes of the makefiles before\n\tupdating them, and compare their file_mtimes against this later.  Don't\n\tre-exec if a makefile was successfully updated but didn't change.  If a\n\tmakefile failed to be remade and no longer exists, die.  If a makefile\n\tfailed to be remade, but changed anyway, re-exec.  If a makefile failed\n\tto be remade, but is unchanged, continue on.\n\nWed Sep 20 18:02:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.55.6.\n\n\t* implicit.c (pattern_search): Maintain an array CHECK_LASTSLASH of the\n\tCHECK_LASTSLASH flag values used to match each member of TRYRULES.\n\tWhen making FILE->stem, if CHECKED_LASTSLASH[FOUNDRULE], prepend the\n\tpart of FILENAME before LASTSLASH.\n\nTue Sep 19 17:44:08 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* dir.c (dir_file_exists_p): Check for FILENAME being nil before\n\tchecking for it being \"\".\n\n\t* main.c (define_makeflags): Fixed test for whether a flag/flag_off\n\toption was non-default.  Also changed to generate a string that Unix\n\tMake will grok (except for FP/int values and new flags).\n\n\t* job.c (child_execute_job): Don't use the shell's -c option.\n\tAlso fixed an off-by-one bug in the ARGV -> shell arg list copying.\n\nMon Sep 18 15:17:31 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.55.5.\n\n\t* read.c (parse_file_seq): Check the beginning of the file name for a\n\t`./', not the two chars after the end of the name (Q rather than P).\n\n\t* job.c (child_execute_job): Include all of ARGV in the arg list for\n\tthe shell.\n\n\t* main.c (define_makeflags): Don't include floating and positive_int\n\toptions in !PF.\n\n\t* job.c (exec_command): Set the effective gid to the real gid before\n\texecing.\n\n\t* job.c (child_execute_job): Don't clobber the arg list when execing\n\tthe shell.\n\nSun Sep 17 15:27:19 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* main.c (define_makeflags): Moved all the checking inside the switch.\n\n\t* load.c [LDAV_BASED] (load_average): When we can't get the load\n\taverage, return zero instead of running off the end.\n\n\t* file.c: Include variables.h.\n\t* job.c: Declare dup2 and {block,unblock}_remote_children.\n\t* file.h: Declare f_mtime.\n\t* job.c: Don't declare construct_command_argv, since job.h does.\n\t* function.c, main.c, load.c, remake.c: Include job.h.\n\t* load.c [LDAV_BASED] (load_average): Declare nlist.\n\t* variable.h: Declare print_file_variables.\n\t* job.c [!USG]: Don't declare sigsetmask.\n\t[!USG]: Declare getdtablesize.\n\tDon't declare load_average.  Do declare wait_to_start_job.\n\tDeclare vfork, gete[gu]id, execve.\n\t* commands.c: Declare remote_kill, getpid.\n\t* make.h: Declare kill, exit, sigblock, pipe, close, ctime, open,\n\tlseek, read.\n\t* make.h [not USG]: Declare sigsetmask.\n\t* job.h: Declare wait_for_children and {block,unblock}_children.\n\n\t* dir.c (dir_file_exists_p): If FILENAME is nil, read in the whole\n\tdirectory.\n\t(find_directory): When we want to read in the whole directory, call\n\tdir_file_exists_p with nil instead of \"\".\n\n\t* file.h (struct file), job.h (struct child),\n\t  variable.h (struct variable): Use bitfields for flags.\n\t* make.h (ENUM_BITFIELD): If GCC or #ifdef ENUM_BITFIELDS, define as\n\t:BITS, else empty.\n\t* compatMakefile (defines): Document ENUM_BITFIELDS.\n\nSat Sep 16 12:38:58 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.55.4 (alpha).\n\n\t* GNUmakefile (dist): Depend on default and doc.\n\n\t* load.c [LDAV_BASED]: Include <nlist.h> rather than <a.out.h>; #ifdef\n\tNLIST_NAME_UNION, use n_un.n_name instead of n_name.\n\t* compatMakefile (LOAD_AVG): Document NLIST_NAME_UNION.\n\n\t* job.c [USG-ish]: Don't redefine WIF{SIGNALED,EXITED} if they're\n\talready defined.\n\nFri Sep 15 13:59:42 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* glob.c, dir.c [USGr3 or DIRENT]: If neither d_ino, nor d_fileno is\n\tdefined, define d_ino as d_fileno.\n\nThu Sep 14 18:29:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* job.c: Don't declare exec_command static.\n\n\t* make.texinfo (Name Index): Changed title to include directives.\n\n\t* Version 3.55.3 (alpha).\n\n\t* make.texinfo (Running: Options): Document -e.\n\n\t* main.c (main): Always give imported environment variables origin\n\t`o_env'.\n\t* variable.c (define_variable_in_set): Under -e, if ORIGIN, or an\n\texisting variable's origin, is `o_env', make it `o_env_override'.\n\n\t* load.c: Use the symbol KERNEL_FILE_NAME instead of KERNEL_FILE.\n\t* compatMakefile: Changed the comment for `LOAD_AVG' accordingly.\n\nThu Sep  7 16:46:26 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.55.2 (alpha).\n\n\t* variable.c (print_variable_set), rule.c (print_rule_data_base),\n\tfile.c (print_file_data_base): If NO_FLOAT is defined, don't use\n\tfloating-point for printing statistics.\n\t* compatMakefile (defines): Document NO_FLOAT.\n\n\t* make.h (HASH): New macro to add the hashing value of one char to a\n\tvariable.c.\n\t* file.c (lookup_file, enter_file, rename_file): Use it.\n\t* dir.c (find_directory, dir_file_exists_p, file_impossible_p): Ditto.\n\t* variable.c (define_variable_in_set, lookup_variable): Same here.\n\n\t* variable.c, file.c, dir.c: Don't define *_BUCKETS if they are already\n\tdefined.\n\n\t* compatMakefile (defines): Added comment about defining NO_ARCHIVES.\n\t(ARCHIVES, ARCHIVES_SRC): New variables for {ar,arscan}.[oc].\n\t(objs, srcs): Use $(ARCHIVES) and $(ARCHIVES_SRC).\n\t* commands.c (set_file_variables), dir.c (file_exists_p),\n\tremake.c (touch_file, name_mtime), implicit.c (try_implicit_rule,\n\tpattern_search), make.h: If NO_ARCHIVES is #defined, don't do any\n\tarchive stuff.\n\n\t* commands.c (set_file_variables): Don't kill the last char of\n\tdirectory names in $([@*<%?^]D).\n\nWed Sep  6 15:23:11 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* default.c (default_terminal_rules {%:: %,v}, {%:: RCS/%,v}): Don't\n\trun co if the target exists.\n\n\t* glob.c (glob_match): [!xyz], rather than [^xyz], means none of [xyz].\n\n\t* glob.c: Misc minor cosmetic changes.\n\nTue Sep  5 14:49:56 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* load.c [LDAV_BASED] (load_average): Check for == -1, rather than < 0\n\tto see if lseek fails.  On some systems, `avenrun' is at an offset >\n\t(2**31)-1, and lseek succeeds, returning a negative value.\n\nMon Sep  4 11:07:58 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* rule.c (new_pattern_rule): Return `int' instead of `void': nonzero if\n\tthe passed rule was used, zero if not.\n\t(install_pattern_rule): Pay attention to the return from\n\tnew_pattern_rule, and don't set the rule's `terminal' flag or give it\n\tcommands unless it's used.\n\t(create_pattern_rule): Same idea.\n\n\t* dir.c (find_directory): Removed unused variable.\n\n\t* commands.c (execute_file_commands): Removed unused variable.\n\n\t* read.c (record_files): Don't use NAME after freeing it.\n\nSat Sep  2 00:33:19 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* Version 3.55.1 (alpha).\n\n\t* function.c (string_glob): Don't add spaces after file names that\n\taren't added.  (Also means don't add spaces without checking the size\n\tof the buffer.)\n\n\t* remake.c (update_goal_chain): Don't remove makefiles with cmds and no\n\tdeps from the chain.\n\t* main.c (main): Do it here, before calling update_goal_chain.\n\n\t* remake.c (update_goal_chain): When updating fails, change STATUS even\n\tif MAKEFILES is set.  Also stop remaking when updating fails if not\n\tunder -k and MAKEFILES is not set.\n\n\t* remake.c (remake_file, update_file_1, notice_finished_file),\n\tcommands.c (execute_file_commands), make.h, commands.h: The functions\n\tremake_file, notice_finished_file, and execute_file_commands no longer\n\treturn values, and their callers no longer expect values returned.\n\n\t* remake.c (notice_finished_file): Don't set FILE's modtime to now if\n\tit is a non-target with no commands.\n\nFri Sep  1 00:04:39 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* read.c (read_all_makefiles): After freeing each element on MAKEFILES,\n\treplace it with the name stored in read_makefiles by read_makefile.\n\n\t* remake.c (update_file_1): Don't decide not to remake if FILE has no\n\tcmds and no deps actually changed if FILE doesn't have any deps.\n\n\t* file.c (remove_intermediate): Remove precious files that also have\n\tthe `dontcare' flag set.\n\n\t* remake.c (update_file_1): Don't always remake if FILE has cmds but no\n\tdeps; only if FILE is double-colon.  (I don't know why this should be\n\tdone for double-colon targets, but that's what Unix make does.)\n\n\t* load.c [LDAV_BASED] (load_average): Write error messages if the\n\tvarious system calls fail.  Keep track of if we've failed before.\n\tThe first time we fail, write a message saying -l won't be enforced.\n\tThe first time we succeed after having failed, write a message saying\n\t-l will be enforced again.\n\n\t* remake.c [USG]: Don't #include <sys/file.h>\n\n\t* load.c [generic Unix LDAV_BASED]: #include <fcntl.h> #ifdef USG,\n\telse <sys/file.h> instead.\n\n\t* job.c [USG && !USGr3 && !HAVE_DUP2]: Remove redundant\n\t#include <errno.h> and declaration of `errno'.\n\t[...] (dup2): Fixed so it won't always lose.\n\n\t* default.c (default_suffix_rules: .texinfo.dvi): Copy, rather than\n\tmove, the aux and index files, so the TeX run can use them.\n\n\t* compatMakefile: Remove redundant comment.\n\n\t* load.c [generic Unix LDAV_BASED]: Include <a.out.h> instead of\n\t<nlist.h>, since the `struct nlist' declaration in <nlist.h> varies\n\tmore than the one in <a.out.h>.\n\t(load_average): Use the `n_un.n_name' field of the `struct nlist',\n\tsince the <a.out.h> declaration uses the union.\n\n\t* main.c (main): For the temporary files made for stdin makefiles, set\n\tthe `intermediate' and `dontcare' flags.\n\t* file.c (remove_intermediates): Don't print any messages for files\n\twhose `dontcare' flag is set.  (The only files that will be\n\tintermediate and `dontcare' will be the temporary files made for stdin\n\tmakefiles.)\n\n\t* job.c (exec_command): Made global.\n\t* job.h: Declare it.\n\t* main.c (main): Use exec_command when re-execing.\n\n\t* make.h: Declare environ.\n\t* make.c: Don't.\n\n\t* job.c (child_execute_job): New function to perform everything done in\n\tthe child side of a fork (for a job or `shell' function).\n\t(start_job): Call it.\n\t* job.h: Declare construct_command_argv and child_execute_job.\n\t* function.c (expand_function: `shell'): Use child_execute_job.\n\nThu Aug 31 18:42:51 1989  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* function.c (expand_function: `shell'): Remove a trailing newline\n\tinstead of turning it into a space.\n\n\t* main.c (main): Do init_siglist #ifdef HAVE_SIGLIST.\n\n\t* job.c [WTERMSIG || (USG && !HAVE_SYS_WAIT)]: Test each W* macro\n\tseparately and define all those that aren't defined.\n\nSat Aug 26 15:13:21 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* ar.c (ar_name): Return zero for `(foo)'.\n\n\t* Version 3.55.\n\n\t* make.texinfo (Rules: Multiple Targets): Make this node's `next'\n\tpointer point to `Static Pattern'.\n\t* make.texinfo (Makefiles: MAKEFILES Variable): Make this node's `prev'\n\tpointer point to `Makefile Names'.\n\n\t* make.1: Renamed to make.man.\n\t* compatMakefile: Define `mandir' and `manext'.\n\t(install): Depend on $(mandir)/make.$(manext).\n\t($(mandir)/make.$(manext)): Depend on make.man and copy it to $@.\n\t($(bindir)/make): Use `make' rather than $<; so Unix make can grok it.\n\nThu Aug 24 03:35:48 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* variable.c (target_environment): Allow variables that start with\n\tunderscores.\n\nWed Aug 23 22:50:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* variable.c (target_environment): Reject variables that don't start\n\twith letters.\n\nTue Aug 22 04:14:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* GNUmakefile (make-$(version).tar.Z): Put make.1 (the Unix manual\n\tpage) in the tar file.\n\n\t* variable.c (target_environment): Don't write variables with origin\n\to_default (i.e., ones from default.c).\n\t* make.texinfo (Commands: Recursion: Variables/Recursion): Document\n\tthat default variables are not put in the environment.\n\n\t* remake.c (update_file_1): Remake all targets with commands but no\n\tdeps.\n\nSat Aug 19 06:03:16 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (update_file_1): In the final loop, set the deps'\n\t`changed' members if they are newer than FILE.\n\n\t* remake.c (update_goal_chain): Under -d, print a message if we decide\n\tnot to remake a makefile so as to avoid a possible infinite loop.\n\nFri Aug 18 20:30:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (remake_file): Cleaned up.\n\n\t* commands.c (execute_file_commands): If the commands are empty, set\n\tFILE->update_status to zero before returning.\n\n\t* remake.c (notice_finished_file): Set `last_mtime' fields to zero\n\tinstead of calling name_mtime; file_mtime will do that later if anybody\n\tcares.\n\nThu Aug 17 10:01:11 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* make.texinfo (Rules: Wildcards: Wildcard Examples): Give this node a\n\t`prev' pointer.\n\n\t* Version 3.54.9 (alpha).\n\n\t* make.texinfo: Fixed some @nodes.\n\n\t* remake.c (check_dep): Don't set *MUST_MAKE_PTR if FILE doesn't exist\n\tafter running update_file.\n\n\t* remake.c (notice_finished_file): If FILE has no commands, pretend its\n\tmodtime is now.\n\n\t* remake.c (update_file_1): In the loops that call update_file on the\n\tdeps, compare modtimes before and after (unless deps are still being\n\tmade) and set the deps' `changed' members.  Do not set the `changed'\n\tmembers in the loop that prints the newer/older debugging messages.\n\t* remake.c (update_file_1): If no deps changed and FILE has no\n\tcommands, decide it doesn't need remaking.\n\n\t* remake.c (update_file_1): Print a debugging message if we take\n\tcommands from default_file.\n\n\t* make.texinfo (Rules: Directory Search: Selective Search): Removed\n\tnote about warning for `vpath' with a constant pathname, since it isn't\n\twarned about anymore.\n\n\t* remake.c (update_goal_chain): If MAKEFILES, remove makefiles which\n\tare targets and have no deps.\n\t* make.texinfo (Makefiles: Remaking Makefiles): Document that makefiles\n\twill not be remade if they are targets but have no dependencies.\n\nTue Aug 15 00:00:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)\n\n\t* remake.c (notice_finished_file): Increment files_remade for non-phony\n\tfiles if they didn't exist before (even if they still don't).\n\n\t* job.c: Include <errno.h> and declare errno.\n\n\t* job.c (exec_command): If the execve fails with ENOEXEC (Exec format\n\terror), return instead of exiting the child process.\n\n\t* job.c (start_job): In the child side, if exec_command fails, try\n\tusing the shell.\n\n\t* job.c (start_job): In the child side, call unblock_children instead\n\tof sigsetmask.\n\n\t* remake.c (notice_finished_file): Under -n or -q, always increment\n\tfiles_remade for non-phony files.\n\n\t* rule.c (intall_pattern_rule): Use find_percent.\n\n\t* vpath.c (vpath_search): Pass the `percent' members to\n\tpattern_matches.\n\nMon Aug 14 23:30:24 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)\n\n\t* vpath.c (struct vpath): New member `percent', to hold a pointer into\n\tthe pattern where the % is.\n\t(construct_vpath_list): Call find_percent on the pattern and set the\n\tnew `percent' member.\n\t* read.c (read_makefile): Don't run find_percent on `vpath' directive\n\tpatterns.\n\n\t* function.c (pattern_matches): Take new arg PERCENT, a pointer into\n\tPATTERN where the % is.  If PERCENT is nil, copy PATTERN into local\n\tspace and run find_percent on it.\n\t(expand_function: `filter', `filter-out'): Pass new arg to\n\tpattern_matches.\n\t* read.c (record_files): Pass PATTERN_PERCENT to pattern_matches for\n\tstatic pattern rules.  Save the percent pointer into implicit rule\n\ttargets, and pass them to create_pattern_rule.\n\t* rule.c (convert_to_pattern): Pass new arg to create_pattern_rule.\n\t(create_pattern_rule): Take new arg TARGET_PERCENTS, nil or an array of\n\tpointers into the corresponding elements of TARGETS, where the %s are.\n\nSun Aug 13 00:29:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.8.\n\n\t* README.templatate, README-doc.template: New files, turned into README\n\tand README-doc to go into the two distribution tar files.\n\t* GNUmakefile: Added a rule to edit the version number in\n\tREADME.template and README-doc.template, producing README and\n\tREADME-doc.\n\n\t* remake.c (update_goal_chain): If -n or -q is in effect for a\n\tmakefile, and it got updated, don't change STATUS, so we can still\n\treturn -1 (meaning nothing was done).  This avoids an infinite loop on\n\t\"make -n Makefile\".\n\nSat Aug 12 23:14:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (notice_finished_file): Treat -q the same as -n.\n\n\t* remake.c (update_goal_chain): Fixed handling of return from\n\tupdate_file.  If -n or -q is in effect, ignore it.\n\n\t* job.c (start_job): Don't test for -t.  We should never get called in\n\tthat case.\n\nFri Aug 11 04:09:14 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* function.c (expand_function): Removed unused variables.\n\t(handle_function): Removed unused variable.\n\n\t* main.c (main): Removed unused variable.\n\nWed Aug  9 09:37:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.7.\n\n\t* remake.c (notice_finished_file): If FILE's modtime actually changed,\n\tincrement files_remade.\n\t(remake_file): Don't increment files_remade.\n\n\t* remake.c (update_file): Don't print \"up to date\" messages for\n\tphony files.\n\n\t* job.c (child_handler): Don't set C->file->update_status to 1 if\n\tstart_job returns nonzero under -n or -t.\n\n\t* expand.c (variable_expand): Count parens in $(foo:a=b) refs.\n\n\t* main.c: Removed old declaration of `glob_tilde' (which hasn't existed\n\tfor a few months).\n\nTue Aug  8 23:53:43 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* job.c (exec_command): Fixed to not ignore the last path component and\n\tto do the right thing with an empty path.\n\nFri Aug  4 15:58:19 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (library_file_mtime): Look for libLIB.a, not /libLIB.a.\n\tDo VPATH search on libLIB.a, not /usr/lib/libLIB.a\n\nThu Aug  3 20:42:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* job.c [HAVE_SYS_WAIT or not USG]: If WIFSIGNALED is not defined by\n\t<sys/wait.h>, define it as (WTERMSIG != 0).\n\nTue Aug  1 19:25:34 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (remake_file): If FILE has no commands and is a target,\n\tdon't set its time to now.  The time gets reset by notice_finished_file\n\tanyway, and it isn't needed since check_dep checks for nonexistence.\n\n\t* Version 3.54.6.\n\n\t* read.c (read_makefile): Don't read off the end of the string after an\n\t`include'.\n\n\t* job.c (exec_command): New function to search the path for a file and\n\texecute it.\n\t(start_job): Use exec_command rather than execvp.\n\n\t* read.c (read_makefile): Expand `include' directive args before\n\tparsing them.  Allow trailing whitespace after filename.\n\n\t* variable.c (target_environment): Put makelevel + 1, rather than\n\tmakelevel, in the `MAKELEVEL' envariable.\n\nSat Jul 29 10:27:04 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* remake.c (notice_finished_file): Don't get the new modtime of phony\n\tfiles.\n\n\t* remake.c (remake_file): Run commands instead of touching under -t if\n\tFILE->cmds->any_recurse is set.\n\n\t* commands.h (struct commands): Add new member `any_recurse', to be set\n\tnonzero if any `lines_recurse' element is nonzero.\n\t* commands.c (chop_commands): Set the `any_recurse' member.\n\n\t* commands.c (execute_file_commands): Split chopping of commands into\n\tlines into new function chop_commands.\n\t* commands.h: Declare chop_commands.\n\n\t* read.c (read_makefile): Test for a line beginning with a tab after\n\tchecking for conditional lines, but before all other checks.\n\nFri Jul 28 18:10:29 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* read.c (read_makefile): Match directives against collapsed line\n\tand use that for their args.\n\n\t* read.c (read_makefile): Warn about extra text after `include'.\n\nTue Jul 25 14:34:25 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* make.texinfo (Rules: Directory Search: Selective Search): Fixed\n\texample to use correct `vpath' syntax.\n\nMon Jul 24 12:10:58 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.5.\n\n\t* job.c (start_job): In the child side, unblock SIGCHLD.\n\nFri Jul 21 18:25:59 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* make.h: Don't include <sys/types.h> #ifdef sun.\n\nMon Jul 17 14:29:10 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* implicit.c (pattern_search): If ar_name (FILENAME), don't check for\n\tdirectory names.\n\n\t* job.c (wait_for_children): Changed \"waiting for children\" message to\n\t\"waiting for unfinished jobs\".\n\nFri Jul 14 13:17:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* load.c (load_average): Use an unsigned offset into kmem.\n\nThu Jul 13 18:44:49 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* variable.c (pop_variable_scope): Don't free the head of the chain of\n\tvariables in each bucket twice.\n\nTue Jul 11 06:45:24 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* GNUmakefile: Include COPYING in the doc tar file.\n\n\t* variable.c, read.c, misc.c, job.c, function.c: Replace some identical\n\t\"for\" loops with next_token or end_of_token calls.\n\nMon Jul 10 16:55:08 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.4.\n\n\t* compatMakefile: Documented new conditionals.\n\n\t* job.c: Don't define sys_siglist if HAVE_SIGLIST is defined.\n\tDon't define dup2 if HAVE_DUP2 is defined.\n\n\t* job.c (child_handler): Interpret the return from start_job correctly.\n\n\t* remake.c (update_file_1): Don't write \"target not remade because of\n\terrors\" message under -n or -q.\n\n\t* read.c: Declare getpwnam.\n\n\t* glob.c: Use <dirent.h> if DIRENT is defined.\n\t[USG]: Don't declare memcpy, since <memory.h> does.\n\nFri Jul  7 20:53:13 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* misc.c (collapse_line): Copy the line over in the right place.\n\nFri Jul  7 18:33:24 1989  Roland McGrath    (fsf at void.ai.mit.edu)\n\n\t* remake.c: Conditionalize inclusion of <sys/file.h> on not\n\tUSG, since HP-UX defines a `struct file' there.\n\nFri Jul  7 12:11:30 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* job.c: If WTERMSIG is defined by <sys/wait.h>, define WAIT_T as int,\n\tand don't define other macros; this covers HP-UX.\n\tIf WTERMSIG is not defined, use int or union wait based on USG and\n\tHAVE_SYS_WAIT; this covers BSD and SysV.\n\n\t* Version 3.54.3 (alpha).\n\n\t* job.c [USG and not USGr3]: Include <errno.h> and declare errno.\n\n\t* job.c (unblock_children [USG]): Declare child_handler.\n\n\t* job.c: Renamed WRETCODE to WEXITSTATUS.\n\t[HAVE_SYS_WAIT or not USG]: Undefine WTERMSIG, WCOREDUMP, and\n\tWEXITSTATUS before defining them.  The HP-UX <sys/wait.h> defines them.\n\n\t* main.c (main): If there are no goals, fatal AFTER printing the data\n\tbase under -p.\n\nThu Jul  6 22:43:33 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)\n\n\t* glob.c [USG]: #define rindex as strrchr.\n\n\t* job.c [USG]: Include <sys/param.h> and #define getdtablesize() as\n\tNOFILE.\n\nWed Jul  5 09:36:00 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.2 (alpha).\n\n\t* expand.c (variable_expand): When expanding recursive variable\n\treferences (${${a}}), use the correct delimiters in the constructed\n\tvariable reference.\n\nMon Jul  3 18:29:26 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)\n\n\t* compatMakefile: Clear out and redefine the .SUFFIXES list because\n\tsilly Sun 4 make defines .cps.h.\n\n\t* compatMakefile: Fix comment about -DNO_MINUS_C_MINUS_O.\n\n\t* remake.c: Include <sys/file.h> for O_* on 4.2.\n\n\t* commands.c: Define sigmask if it's not defined.\n\nFri Jun 30 07:33:08 1989  Roland McGrath  (roland at apple-gunkies.ai.mit.edu)\n\n\t* remake.c (remake_file): Don't always increment files_remade.\n\n\t* variable.c (push_new_variable_scope): Zero the new variable hash\n\ttable.\n\nThu Jun 29 17:14:32 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* expand.c (variable_expand): When terminating the variable expansion\n\tbuffer, use variable_buffer_output instead of a simply zero store,\n\tbecause the buffer may need to be enlarged.\n\nWed Jun 28 16:53:47 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.54.\n\n\t* default.c (default_suffixes): Added `.ln'.\n\t(default_suffix_rules): Changed lint rules to use -C.\n\nThu Jun 22 20:49:35 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* job.c (start_job): Set `environ' to CHILD->environment before execing\n\tin the child process!\n\nTue Jun 20 17:23:13 1989  Roland McGrath  (roland at spiff.ai.mit.edu)\n\n\t* compatMakefile: Put job.h and rule.h in `srcs'.\n\n\t* Version 3.53.\n\nMon Jun 19 16:25:18 1989  Roland McGrath  (roland at spiff.ai.mit.edu)\n\n\t* job.c (start_job): If there are no more commands, return nonzero\n\tunder -n or -t.\n\n\t* compatMakefile (make): Pass `-f' to mv.\n\n\t* GNUmakefile: If `ARCH' or `machine' is defined, make $(ARCH)/*.o and\n\t$(ARCH)/make instead of *.o and make.\n\n\t* function.c (string_glob): Don't try to use freed storage!\n\n\t* read.c (readline): If there is only one byte of space in the buffer,\n\tenlarge the buffer before reading more.\n\n\t* arscan.c [M_XENIX]: Miscellaneous minor changes for Xenix.\n\nSun Jun 18 13:07:45 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* GNUmakefile (depend): Split commands into two lines so they won't be\n\tso long when variable-expanded.\n\n\t* compatMakefile: Documented MINUS_C_MINUS_O meaning.  The line\n\tdescribing it got removed when the USG/wait stuff was documented.\n\nSat Jun 17 22:56:54 1989  Roland McGrath  (roland at hobbes.ai.mit.edu)\n\n\t* Version 3.52.\n\nMon Jun 12 17:45:11 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remake.c (check_dep): Drop circular dependencies instead of fataling.\n\t(update_file_1 already does this.)\n\n\t* default.c (default_suffix_rules): For .s -> .o, put the -o flag to\n\tthe assembler before the source file name.\n\nSun Jun 11 12:00:52 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.51.\n\n\t* make.texinfo (Features): Noted 1003.2 requirement of `+' meaning.\n\n\t* file.c (remove_intermediates): If !SIG, write a single \"rm\" command\n\tline, listing all files.\n\n\t* read.c (read_makefile): Don't free the storage for the passed\n\tfilename, since it might not be malloc'd.  When doing an included\n\tmakefile, free the name's storage.\n\t(read_all_makefiles): Use variable_expand to find the value of\n\t`MAKEFILES'.  Free the storage for the names of -f makefiles.\n\t(read_makefile): Allocate storage for the makefile name in the\n\t`struct file' in read_makefiles.\n\n\t* make.texinfo (Running: Instead of Execution): Document the effect of\n\t+ and $(MAKE)/${MAKE}.\n\n\t* make.texinfo (Functions: Foreach Function): Document that if the\n\titeration variable was undefined before the `foreach' call, it will be\n\tundefined after the call.\n\n\t* commands.c: Split into commands.c, job.h, and job.c.\n\n\t* rule.c (try_implicit_rule, pattern_search): Moved to new file\n\timplicit.c.\n\n\t* rule.c: Split into rule.h, rule.c, and default.c.\n\t* default.c (install_default_pattern_rules): Renamed to\n\tinstall_default_implicit_rules.\n\t* make.h, main.c (main): Renamed uses.\n\n\t* make.c: Renamed to misc.c.\n\n\t* make.c (main, log_working_directory, decode_switches,\n\tdecode_env_switches, define_makeflags, die, print_version,\n\tprint_data_base): Moved to new file main.c.\n\n\t* commands.c (execute_file_commands): Don't collapse backslash-newlines\n\there.  When chopping the commands up into lines, don't chop at\n\tbackslash-newlines.\n\t(start_job): Collapse backslash-newlines after printing the line.\n\n\t* commands.c (start_job): Don't collapse backslash-newlines here.\n\t(execute_file_commands): Collapse backslash-newlines before chopping\n\tthe commands up into lines.\n\n\t* commands.c (set_file_variables): Initialize the length counters for\n\t$^ and $? to zero!\n\n\t* commands.c (start_job): Use vfork instead of fork.  Someone else says\n\tthe child and parent DO have separate file descriptors.\n\n\t* variable.c: Split internals into variable.c, function expansion into\n\tfunction.c, and variable expansion into expand.c.\n\t* function.c (handle_function): New function to check for a function\n\tinvocation and expand it.\n\t* expand.c (variable_expand): Use handle_function.\n\t* variable.c (push_new_variable_scope): New function to push a new\n\tempty variable set onto the current setlist.\n\t(pop_variable_scope): New function to pop the topmost set from the\n\tcurrent setlist and free its storage.\n\t* function.c (expand_function: `foreach'): Push a new variable scope\n\tfor the iteration variable and pop the scope when finished.\n\t* variable.h: Declare new functions.\n\t* variable.c (initialize_variable_output): New function to return a\n\tpointer to the beginning of the output buffer.\n\t(save_variable_output): New function to save the variable output state.\n\t(restore_variable_output): New function to restore it.\n\t* expand.c (variable_expand): Use initialize_variable_output.\n\t(allocated_variable_expand): Use {save,restore}_variable_output.\n\t* variable.c (current_setlist): Renamed to current_variable_set_list\n\tand made global.\n\nSat Jun 10 00:11:25 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remake.c (library_file_mtime): Check for libNAME.a in the current\n\tdirectory before doing VPATH search.\n\n\t* variable.c (print_variable_set): Don't write \"# Variables\", and write\n\tfewer blank lines.\n\t(print_variable_data_base): Precede the variables with \"# Variables\".\n\n\t* make.c (main): Print the data base under -p after doing everything\n\telse, just before exitting.  This way it gets info determined in\n\tupdating the goal targets.\n\n\t* variable.c (print_variable_data_base): Split into print_variable,\n\twhich prints one variable, and print_variable_set, which prints a set.\n\tReplaced with a call to print_variable_set for the global set.\n\t(print_file_variables): New function to print a given file's local\n\tvariables.\n\n\t* file.c (print_file_data_base): Call print_file_variables to print\n\teach file's local variables.\n\n\t* commands.c (set_file_variables): Actually define the values for\n\tthe $^ and $? variables!!!\n\n\t* make.texinfo (Implicit: Pattern Rules: Automatic): Document new D and\n\tF versions of $^ and $?.\n\n\t* commands.c (start_job): In the child fork, use getdtablesize and a\n\tloop to close all file descriptors other than 0, 1, and 2.  We need to\n\tdo this since not only the bad stdin pipe, but also some directories,\n\tmay be open.\n\n\t* commands.c (start_job): Use fork instead of vfork, because a vfork\n\tparent and child share file descriptors, and our child needs to diddle\n\twith stdin.\n\n\t* variable.c (initialize_file_variables): When created a new variable\n\tset, zero out the hash table.\n\n\t* variable.c (target_environment): Don't use variables whose names are\n\tnot made up of alphanumerics and underscores.\n\n\t* remake.c (update_file_1): Set the `parent' member of each dependency\n\tto FILE before updating it.\n\n\t* file.h (struct file): Add `parent' member.\n\n\t* variable.c (initialize_file_variables): Don't take second arg PARENT.\n\tUse FILE->parent instead.  If FILE->parent->variables is nil, recurse\n\tto initialize it.\n\n\t* variable.h: Declare {allocated_}variable_expand_for_file.\n\n\t* variable.c (allocated_variable_expand): Now\n\tallocated_variable_expand_for_file, calling variable_expand_for_file,\n\tand taking second arg FILE.\n\t(allocated_variable_expand): New function, a wrapper around\n\tallocated_variable_expand_for_file, passing a nil second arg.\n\nFri Jun  9 12:11:45 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (start_job): On the child side of the fork, always close\n\tthe bad stdin file descriptor.\n\n\t* commands.c (struct child): New member `environment', to hold the\n\tenvironment for the child.\n\t(execute_file_commands): Set the new childs `environment' member to nil\n\tbefore calling start_job.\n\t(start_job): Set up CHILD->environment before running the commands if\n\tit is nil.\n\n\t* make.c (main): Don't call new_environ.  `shell' functions will now be\n\trun with the environment make was called with.\n\n\t* commands.c (child_handler): Don't check C->command_ptr before calling\n\tstart_job since we now have to check C->file->cmds->command_lines and\n\tit's easier to let start_job handle all that.\n\n\t* commands.c (struct child): New member `command_line', to hold an\n\tindex into file->cmds->command_lines.\n\t(execute_file_commands): Set the new child's `command_line' to 0 and\n\tits `commands' and `commands_ptr' to nil.\n\t(start_job): When CHILD->command_ptr runs out, increment\n\tCHILD->command_line and run the corresponding line from\n\tCHILD->file->cmds->command_lines.  Run it even under -t, -q, or -n if\n\tthe CHILD->file->cmds->lines_recurse element for that line is set.\n\n\t* commands.c (execute_file_commands): Chop CMDS up into lines, setting\n\tits `command_lines' and `lines_recurse' members, if it wasn't already\n\tchopped.\n\n\t* commands.h (struct commands): New members `command_lines' and\n\t`lines_recurse'.  The first is an array of chopped-up lines; the second\n\tis an array of flags, each nonzero if the corresponding line is\n\trecursive.\n\n\t* variable.c (variable_expand_for_file): If FILE is nil, just do a\n\tvanilla variable_expand.\n\t(expand_function: `shell'): Pass second arg (as nil) to\n\tconstruct_command_argv.\n\n\t* commands.c (construct_command_argv): Use variable_expand_for_file on\n\t`$(SHELL)' and `$(IFS)' instead of lookup_variable to check those\n\tvariables.  This handles file-local and recursive values correctly.\n\tTo support this, take an additional argument FILE.\n\n\t* variable.c (initialize_file_variables): New function to initialize\n\tFILE's variable set list from PARENT's setlist.  PARENT is the\n\timmediate dependent that caused FILE to be remade, or nil if FILE is a\n\tgoal.  (When user-level per-file variables are implemented, PARENT\n\tshould be passed as nil when defining per-file variables.)\n\n\t* variable.c (variable_expand_for_file): New function to expand a line\n\tusing the variable set of a given file, and reporting error messages\n\tfor the file and line number of that file's commands.\n\n\t* variable.h: Don't declare lookup_variable_for_file.\n\n\t* variable.c (lookup_variable_*): Turned back into lookup_variable.  It\n\tnow uses current_setlist.\n\t(global_setlist): New static `struct variable_set_list', a setlist\n\tcontaining global_variable_set.\n\t(current_setlist): New static `struct variable_set_list *', a pointer\n\tto the current variable set list.\n\t(define_variable): Define in the current top-level set, not the global\n\tset.\n\n\t* commands.c (set_file_variables): New function to set up the automatic\n\tvariables for a file in its own variable set.\n\t(execute_file_commands): Use set_file_variables.\n\n\t* variable.c (new_environ): Replaced with target_environment, taking an\n\targument FILE, and returning an environment for FILE's commands.\n\n\t* variable.c, variable.h: Remove all global special variable pointers.\n\n\t* variable.c (define_variable_for_file): New function like\n\tdefine_variable, but takes additional arg FILE, and defines the\n\tvariable in the variable set at the top of FILE's chain.\n\t(lookup_variable_for_file): New function like lookup_variable, but\n\ttakes additional arg FILE, and looks the variable up in all of FILE's\n\tvariable sets.\n\n\t* file.h (struct file): New member `variables', a `struct\n\tvariable_set_list' containing the list of variable sets used in the\n\texpansion of the file's commands.\n\n\t* variable.c (variables): Replaced with static `struct variable_set'\n\tglobal_variable_set.\n\t(define_variable): Now define_variable_in_set, taking additional\n\targument SET, the `struct variable_set' to define it in.\n\t(define_variable): Use define_variable_in_set with global_variable_set.\n\t(lookup_variable): Now lookup_variable_in_set, taking additional\n\targument SET, the `struct variable_set' to look it up in.\n\t(lookup_variable): Use lookup_variable_in_set with global_variable_set.\n\t(lookup_variable_in_setlist): New function to look up a variable in a\n\t`struct variable_set_list' using lookup_variable_in_set.\n\n\t* variable.h (struct variable_set): New structure, containing a hash\n\ttable and the number of hash buckets.\n\t(struct variable_set_list): New structure, containing a link for a\n\tlinked-list, and a `struct variable_set'.\n\n\t* commands.c (start_job): Under -n, return what the recursive start_job\n\tcall returns, since it might actually start a child.\n\n\t* make.texinfo (Rules: Wildcards): Document ~ and ~USER expansion.\n\n\t* commands.c (execute_file_commands): If start_job returns\n\tfailure, but -t is set, set FILE->update_status to success.\n\t(start_job): If -t is set, and the commands are not recursive, return\n\tfailure (is is done for -q).\n\n\t* remake.c (touch_file): New function to touch FILE.\n\t(remake_file): Use touch_file.  When touching a file, still do\n\texecute_file_commands.\n\n\t* remake.c (remake_file): Don't check question_flag (-q), since we\n\tcan't know here if the commands are recursive.\n\n\t* commands.c (start_job): Don't use the `recursive' member of\n\tCHILD->file->cmds.  Instead, check for leading +s and $(MAKE) or\n\t${MAKE} in the command line here.\n\n\t* commands.h (struct commands): Remove `recursive' member.\n\n\t* rule.c (install_default_pattern_rules): Remove use of `recursive'\n\tmember.\n\n\t* read.c (record_files): Don't check commands from $(MAKE) and set\n\ttheir `recursive' member.\n\n\t* commands.c (fatal_error_signal): Treat SIGQUIT like SIGINT, SIGHUP,\n\tand SIGTERM, but don't send it to ourselves because it will cause a\n\tcore dump.\n\nThu Jun  8 20:30:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.50.\n\n\t* variable.c (variable_expand): Use allocated_variable_expand instead\n\tof expand_argument in a few places.\n\n\t* variable.c (allocated_variable_expand): Do static variable shuffling\n\there instead of using expand_argument.\n\t(expand_argument): Use allocated_variable_expand.\n\n\t* variable.c (recursively_expand): New function to recursively expand\n\tits argument (a `struct variable'), returning the malloc'd value.\n\t(variable_expand): Use recursively_expand.\n\nSun May 28 12:49:27 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (main): Fixed buggy fix in deciding to increase space for\n\tcommand-line variable definitions.  (First it never did it, then it\n\talways did it; now it does it when necessary.)\n\nSat May 27 14:01:54 1989  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* make.c (main): Fixed bug in deciding to increase space for\n\tcommand-line variable definitions.\n\nFri May 26 15:48:01 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* read.c (multi_glob): Use allocated_expand_variable for checking\n\t`HOME' variable for ~ expansion, since this may be called from inside a\n\t`wildcard' function expansion.\n\n\t* variable.h: Declare allocated_expand_variable.\n\n\t* variable.c (allocated_expand_variable): New function to do variable\n\texpansion in an allocated buffer, rather than the static one.\n\n\t* make.c (main): Don't set glob_tilde (it no longer exists).\n\n\t* variable.c (string_glob): Use multi_glob and parse_file_seq.\n\n\t* read.c (multi_glob): Do ~ expansion here.\n\n\t* glob.c (glob_tilde, glob_filename): Removed ~ expansion.\n\n\t* variable.c (define_variable, lookup_variable): Use a smarter hashing\n\talgorithm (the same one used for files and directories).\n\t(VARIABLE_BUCKETS): Increased to 523.\n\n\t* file.c (enter_file, lookup_file, rename_file): Use a smarter hashing\n\talgorithm, spreading the bits about somewhat.\n\n\t* make.c (log_working_directory): Under `-p', precede the directory\n\tmessage with a `#'.\n\n\t* make.c (print_version): Under `-p', precede each line with a `#'.\n\t(print_data_base): Precede the header line with a `#' and include the\n\tdate and time on it.\n\n\t* vpath.c (print_vpath_data_base): Precede non-directive\n\tlines with `#'s.\n\n\t* commands.c (print_commands): Precede the non-command line with a `#'.\n\n\t* rule.c (print_rule_data_base), file.c (print_file_data_base): Precede\n\tnon-rule lines with `#'s.\n\n\t* dir.c (print_dir_data_base): Precede all lines with `#'s.\n\n\t* variable.c (print_variable_data_base): Changed format so that it can\n\tbe makefile input.  Lines that are not variable definitions are\n\tpreceded with `#'.  Nonrecursive variable definitions are made with all\n\tdollar signs doubled to reproduce the initial value.  Recursive\n\tvariable definitions containing newlines are done with `define'\n\tdirectives.  Nonrecursive variable definitions containing newlines, and\n\tvariable names containing :, =, or newlines, will come out garbled.\n\nWed May 24 00:20:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.49.\n\nTue May 23 19:18:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* variable.c (expand_function: `filter'/`filter-out'): Use\n\tfind_percent instead of pattern_p.\n\n\t* variable.c (expand_function: `patsubst'): Pass new args (both nil)\n\tto patsubst_expand.\n\t(variable_expand): For $(var:pat%=rep%) references, pass new args to\n\tpatsubst_expand so as to avoid find_percent and thus disallow\n\tquoting the %s.\n\n\t* read.c (record_files): Pass new args to patsubst_expand.\n\n\t* variable.c (patsubst_expand): Take two new args: PATTERN_PERCENT\n\tand REPLACE_PERCENT.  Each of these, if non-nil, means that PATTERN\n\t(or REPLACE) has already been run through find_percent, and\n\tPATTERN_PERCENT (or REPLACE_PERCENT) is the result.\n\n\t* make.h: Declare find_percent instead of pattern_p.\n\n\t* read.c (pattern_p): Changed to find_percent, returning a pointer\n\tto the %, or nil if there is none.\n\t(record_files): Take another arg, PATTERN_PERCENT, a pointer to the\n\t% in PATTERN.\n\t(read_makefile): Pass PATTERN_PERCENT to record_files.\n\n\t* make.texinfo (Rules: Static Pattern: Static Usage,\n\tRules: Directory Search: Selective Search,\n\tFunctions: Text Functions): Documented that `%' can be quoted.\n\n\t* variable.c (expand_function: `filter'/`filter-out'): Use pattern_p\n\tto allow quoted %s in patterns.\n\n\t* variable.c (patsubst_expand): Use pattern_p on PATTERN and REPLACE\n\tto allow quoted %s.  Quoting backslashes are removed from REPLACE\n\teven if PATTERN contains no unquoted %.\n\n\t* read.c (pattern_p): Made global.\n\t* make.h: Declare pattern_p.\n\n\t* read.c (pattern_p): New function to search for an unquoted % in a\n\tstring.  Backslashes quote %s and backslashes.  Quoting backslashes\n\tare removed from the string by compacting it into itself.  Returns\n\tnonzero if an unquoted % was found, zero if not.\n\t(record_files): Use pattern_p to check for implicit rules.\n\t(read_makefile): Use pattern_p to check for static pattern rules.\n\tAlso use it to allow quoted %s in `vpath' patterns; warn about\n\t`vpath' patterns with no %s.\n\nMon May 22 16:31:52 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* glob.c (glob_filename): Replace a `1' with the `l' that should\n\thave been there.  This incidentally stops it from dumping core.\n\n\t* glob.c (glob_filename): If the path is just a directory, with no\n\tfile name pattern, return the directory alone.\n\n\t* glob.c (glob_tilde): New global variable (int), defaults to zero.\n\t(glob_filename): If glob_tilde is nonzero, expand ~ or ~USER.\n\n\t* variable.c (string_glob): Keep a static allocated buffer for file\n\tnames taken from the list, instead of allocating and freeing one\n\tevery time.\n\nFri May 19 18:06:26 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.c (decode_switches): Get floating numbers from the right string.\n\nSun May 14 13:48:04 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* commands.c (delete_child_targets): When deleting `also_make'\n\tfiles, include the target's name in the message:\n\t\tmake: *** [foo] Deleting file `bar'\n\nSat May 13 17:34:26 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (max_load_average, default_load_average): Default to -1.\n\n\t* load.c (wait_to_start_job): Return if max_load_average is < 0.0,\n\tnot equal.\n\nFri May 12 16:08:05 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* variable.c (variable_buffer_output): Don't try to do pointer\n\tarithmetic between objects not in the same array.\n\nWed May 10 15:55:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* rule.c [M_XENIX] (default_suffix_rules, default_variables): Minor\n\tchanges to allow for strange compiler syntax.\n\n\t* rule.c (default_variables): Don't include \"> $@\" in\n\t$(PREPROCESS.S), since it's already in the .S.s rule.\n\n\t* file.c (enter_file): Make a new double-colon file the `prev'\n\tmember of the bottom `prev' file (the one whose `prev' is nil).\n\n\t* read.c (do_define): Append newlines after copying the lines into\n\tthe value buffer, so we end up with a trailing newline.\n\n\t* make.c (print_version): If the global variable\n\t`remote_description' is not nil or \"\", append \"-%s\" (its value) to\n\tthe version number.\n\t* remote-*.c: Define remote_description appropriately.\n\nSun May  7 15:15:53 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (error_status): Converted to new function child_error,\n\ttaking new arguments TARGET_NAME and IGNORED, and writing an error\n\tmessage: \"*** [target] Error 1\" (or signal #, etc.), appending\n\t\" (ignored)\" if IGNORED is nonzero.\n\t(child_handler): Use child_error instead of error_status.\n\n\t* compatMakefile (all): Don't depend on `doc'.\n\n\t* compatMakefile (clean): Don't remove make-info*.\n\t(realclean): New rule, depends on `clean', removes tags, TAGS,\n\tand all Info and TeX files.\n\nThu May  4 17:00:46 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* variable.c (print_variable_data_base), file.c\n\t(print_file_data_base), rule.c (print_rule_data_base),\n\tUse floating-point for averages and percentages.\n\n\t* make.c (print_data_base): Print messages before and after the data\n\tbase information.\n\n\t* commands.c (print_commands): Changed output format to separate\n\tlines in commands and prefix them with tabs.\n\n\t* dir.c (print_dir_data_base): Changed output format slightly.\n\n\t* vpath.c (struct vpath, construct_vpath_list,\n\tselective_vpath_search): Remove the `exists' member and its uses.\n\n\t* vpath.c (print_vpath_data_base): New function to print all\n\tselective and general VPATH search paths (for -p).\n\n\t* make.c (print_data_base): Call print_vpath_data_base.\n\n\t* file.c (print_file_data_base): Changed format to look more like a\n\tmakefile rule.  Now reports all information in the `struct file'.\n\n\t* rule.c (print_rule_data_base): Changed format of display from:\n\t  %: (terminal)\n\t   depends on: RCS/%,v\n\tto:\n\t  %: RCS/%,v\n\t    is terminal.\n\t    references nonexistent subdirectory.\n\tAlso include number and percent that refer to nonexistent\n\tsubdirectories.\n\nThu Apr 27 15:45:40 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.c (main): Figure out the level of recursion before writing\n\tthe `Entering directory' message.\n\t* variable.c (define_automatic_variables): Don't figure out the\n\tlevel of recursion from `MAKELEVEL'.  It's now done in main.\n\n\t* Version 3.48.\n\nWed Apr 26 16:39:17 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (child_handler): Set `update_status' to zero when there\n\tare no more commands.\n\n\t* make.c (log_working_directory): If MAKELEVEL > 0, indicate the\n\trecurson in the message (make[1]: ...).\n\n\t* commands.c (child_handler): Change status to `cs_finished' when\n\tcommands fail.\n\n\t* commands.c (start_job): Return 0 (success) if there were no more\n\tcommands for the child.\n\t(child_handler): Change the status to `cs_finished' when start_job\n\tfails to start the commands.\n\n\t* make.c (main): Don't handle SIGEMT if it's not defined.\n\tDo handle SIGDANGER if it is defined.\n\n\t* commands.c (child_handler): Reorganized inner loop so that it\n\tdoesn't try to inspect the child before finding it.\n\nTue Apr 25 16:28:24 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.c (end_of_token): Fixed bug wherein backslashes caused\n\timmediate return.\n\n\t* Version 3.47.\n\n\t* make.texinfo (Implicit: Pattern Rules: Automatic): Document\n\tsetting of `$*' for explicit rules.  Add note clarifying that\n\tautomatic variables, though referred to in the documentation as\n\t`$<', etc. are no different than `$(<)', etc.\n\nFri Apr 21 18:00:12 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* file.c (enter_file): Don't strip leading `./'s.\n\n\t* read.c (parse_file_seq): Strip leading `./'s.\n\nThu Apr 13 17:26:41 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.texinfo (Commands: Parallel, Running: Options): Document that\n\t-l with no argument removes a previous load limit.\n\n\t* make.c (struct command_switch): New member `default_value'.\n\t(default_job_slots): Default value (of 1) for -j.\n\t(default_load_average): Default value (of 0, unlimited) for -l.\n\t(command_switches): Use default values for -j and -l.\n\tAlso, -l without an arg now means no load limit.\n\t(define_makeflags): Don't write positive_int or floating options\n\twhose values are their defaults.\n\n\t* make.c (main): Under -w, write a `Leaving directory' message\n\tbefore re-execing.\n\nTue Apr 11 16:46:29 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.46.\n\n\t* Makefile: Provide an easy place for system-specific definitions\n\t(-DUSG, etc.) and extra object files (for whatever).\n\n\t* make.texinfo: Miscellaneous fixes from RMS.\n\nMon Apr 10 19:31:34 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* rule.c (pattern_search): Put rules with `subdir' flags set in\n\tTRYRULES, since these might be valid with VPATHs.  In the TRYRULES\n\tloop, don't do lookup_file or file_exists_p calls for dependencies\n\tof rules with `subdir' flags set, but still do vpath_search calls\n\tand intermediate-file searches.\n\nThu Apr  6 16:33:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.texinfo (Implicit: Pattern Rules: Automatic): Document the\n\tnew definition of $* for explicit rules.\n\n\t* commands.c (execute_file_commands): If FILE->stem is nil, figure\n\tout if FILE->name ends in a suffix in the .SUFFIXES list; if so,\n\tstore the name sans suffix in FILE->stem (and $*).\n\nWed Apr  5 15:24:48 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* file.c (remove_intermediates): Don't use `file_exists_p' to check\n\tfor the existence of intermediate files, because the hashed\n\tdirectories will probably be out of date.\n\n\t* commands.c (child_handler): Free the good stdin before running the\n\tnext command line.\n\n\t* commands.c [USG] (init_siglist): Don't case SIGEMT if it's not\n\tdefined.  Do case SIGDANGER (for IBM RT) if it is defined.\n\n\t* commands.c: Changed `SYS_WAIT' to `HAVE_SYS_WAIT'.\n\t(child_handler): Use `wait3' if HAVE_SYS_WAIT is #defined.\n\n\t* file.c (enter_file): If any `./'s are stripped off, allocate a new\n\tcopy of the shortened name.\n\n\t* rule.c (pattern_search): Allocate the right length strings for\n\t`also_make' members.\n\nSat Apr  1 13:28:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.45.\n\n\t* GNUmakefile: Make a separate tarfile of the DVI and info files.\n\n\t* make.c (define_makeflags): If a switch that takes an argument has\n\tits default value, put the switch in MAKEFLAGS with no arguments.\n\n\t* make.c (command_switches): Pass `-l' in MAKEFLAGS.\n\nWed Mar 29 17:50:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* GNUmakefile: Don't include the DVI and info files in the dist.\n\n\t* commands.c (child_handler): Don't call\n\tcheck_changed_{directories,vpaths}.\n\n\t* make.h: Don't declare check_changed_{directories,vpaths}.\n\n\t* vpath.c (check_changed_vpaths): Removed this function.\n\n\t* dir.c (struct directory): Remove `modtime' member.\n\t(find_directory): Don't set `modtime' member.\n\t(check_changed_directories): Removed this function.\n\n\t* remake.c (update_file_1): Set FILE->command_state to cs_finished\n\tif it didn't need to be remade.\n\n\t* remake.c (update_file): Only write the \"up to date\" message if the\n\ttarget went from `not_started' state to `finished' state without\n\tincrementing the count of files remade.\n\n\t* commands.c [USG] (init_siglist): If both SIGCHLD and SIGCLD are\n\tdefined, don't put them both in the `switch'.\n\nTue Mar 28 15:37:02 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* file.c (rename_file): Change FILE's name!!!\n\n\t* rule.c (create_pattern_rule): Set the `terminal' member of the new\n\trule after calling new_pattern_rule, which zeros it.\n\n\t* rule.c (default_variables): Use $(C++) in $(COMPILE.cc)!\n\nSun Mar 26 15:52:30 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Makefile: Added a `clean' target.\n\nFri Mar 24 15:08:46 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* Version 3.44.\n\n\t* file.c (rename_file): If a `struct file' for the renamed-to name\n\texists, and it is a target or has deps or commands, barf.\n\tIf not just remove the old one for put in the new one.\n\n\t* remake.c (update_file_1, check_dep): Changed it back so that equal\n\tmodtimes to NOT make dependencies be considered newer.  RCS checks\n\tout files with equal modtimes as the RCS files, so this screws it.\n\n\t* make.h, glob.c: If __GNUC__ is defined, use __builtin_alloca.\n\n\t* Makefile: Use variables `ALLOCA' and `ALLOCASRC' so systems\n\twithout a good standard alloca can get it from the Emacs\n\tdistribution (or somewhere).\n\n\t* dir.c: Don't include <sys/stat.h>, since make.h does.\n\n\t* make.c: Removed debugging version of getwd.\n\nThu Mar 23 16:16:27 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.43.\n\n\t* remake.c (update_file_1): If a dependency loop is found, don't\n\tfatal.  Emit an error message and remove the dependency.\n\n\t* remake.c (library_file_mtime): Fixed to use the right names.\n\t(update_file_1, check_dep): Consider a dependency \"newer\" than its\n\tdependent if they have the same modification time.\n\nWed Mar 22 19:31:35 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* file.c (remove_intermediates): Don't try to remove nonexistent files.\n\nMon Mar 20 10:21:22 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.42.\n\n\t* rule.c (default_variables): Set F77 to $(FC) and F77FLAGS to\n\t$(FFLAGS) so explicit rules expecting these (which are in System V)\n\twill work.  However, there is no way to make setting these affect\n\tthe implicit rules, unless we trash FC and FFLAGS (which BSD uses).\n\t[USG]: Set GET to `get' rather than `/usr/sccs/get'.\n\nSun Mar 19 20:00:27 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* vpath.c (construct_vpath_list): Don't replace VPATH[ELEM] with\n\tdir_name (V), because the latter may get freed.\n\nSat Mar 18 15:01:39 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.41.\n\n\t* make.texinfo: Cleaned-up edition 0.1 Beta from RMS and Bob Chassell.\n\n\t* file.c (rename_file): If a file with the new name already existed,\n\tuse the same storage space, after freeing the old file's name, deps,\n\tand `also_make' member, preserving the link in the chain.\n\tAlso write an error message telling the user to report the incident;\n\tI don't think this should be able to happen, but I'm not sure.\n\n\t* file.c (rename_file): Don't add the hash values of the old and new\n\tnames together!  Reset HASHVAL before computing the second value.\n\n\t* dir.c (check_changed_directories): Zero the new file hash table\n\tafter allocating it.\n\n\t* dir.c (dir_file_exists_p): If FILENAME is \"\", return 1 if the\n\tdirectory exists.\n\n\t* vpath.c (check_changed_vpaths): New function to run through the\n\tsearch paths of all VPATHs, making the `exists' members correspond\n\tto reality.\n\n\t* commands.c (child_handler): Call check_changed_vpaths.\n\n\t* make.h: Declare check_changed_vpaths.\n\n\t* vpath.c (struct vpath): New element `exists', an array of char\n\tflags; exists[N] is nonzero if searchpath[N] exists.\n\t(construct_vpath_list): Set the `exists' member.\n\t(selective_vpath_search): Don't search directories whose `exists'\n\telements are zero.\n\n\t* read.c (read_makefile): Set the `dontcare' flag of makefiles\n\tfrom the MAKEFILES variable if they were not mentioned anywhere but\n\tin the MAKEFILES variable.\n\n\t* read.c (read_makefile): Don't write an error message if fopen\n\tfails for a makefile from the MAKEFILES variable.\n\n\t* dir.c (struct directory): Add `modtime' member to record the\n\tmodification time of the directory when it was opened.\n\t(check_changed_directories): New function to check all known\n\tdirectories; if their modtimes have changed since they were opened,\n\ttheir file tables are cleared and they are reset to be read in.\n\n\t* commands.c (child_handler): Call check_changed_directories before\n\treturning.\n\tmake.h: Declare check_changed_directories.\n\nTue Mar 14 20:07:13 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.40.\n\n\t* make.c (print_version): Made the copyright say 1988, 1989.\n\n\t* read.c (read_all_makefiles): Don't set *MAKEFILES to the name of\n\tthe end of the read_makefiles chain, since the latter may be from an\n\tincluded makefile.  (Why did I do this before?)\n\n\t* make.c (main): Set argv[0] to \"\" if it was nil.  Don't put the\n\tcommand-line variable definitions into argv[0], only into the MAKE\n\tvariable!\n\nSun Mar  5 20:44:08 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* ar.c (ar_member_date, ar_touch): Remove the trailing ) from the\n\tmember name.\n\nFri Mar  3 18:15:15 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (construct_command_argv): Initialize NEW_ARGV to 0.  At\n\t`slow' label, if NEW_ARGV is not 0, free it; then allocate 4 strings.\n\nTue Feb 28 14:29:39 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.39.\n\n\t* COPYING, make.texinfo: New GNU General Public License, version 1.\n\n\t* *.c, *.h, Makefile: New copyright notices for the new GNU General\n\tPublic License, version 1.\n\n\t* commands.c [USG]: Define WRETCODE correctly (again).\n\n\t* variable.c (expand_function: `shell'): Don't capture the standard\n\terror output of the shell command.\n\n\t* ar.c (ar_touch, ar_member_date): Allocate MEMNAME with the right\n\tlength.\n\n\t* load.c [not UMAX] (load_average): Don't clobber the first nlist\n\tmember when trying to set the second!\n\nThu Feb 23 13:13:53 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* commands.c (child_handler): Really ignore errors under -i and for\n\t- lines, don't just print a different message.\n\n\t* make.c (decode_switches): Fixed handling of arguments (or lack\n\tthereof) to switches.\n\nWed Feb 22 16:25:39 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* commands.c (construct_command_argv): Don't clobber LINE when\n\tchecking the IFS variable.\n\nSun Feb 19 11:17:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* load.c [UMAX, not NO_LDAV] (load_average): Return 0.0 rather than\n\trandomness when calls fail.\n\n\t* Version 3.38.\n\n\t* commands.c (fatal_error_signal): If handling a user kill signal\n\t(TERM, INT, HUP), wait for the children without printing the\n\t\"Waiting for children\" message, since they will die quickly.\n\n\t* Version 3.37.\n\n\t* remote-stub.c (remote_status): Take another arg, BLOCK.  If this\n\tis nonzero block waiting for remote children.  If not, return 0 if\n\twe would have to block.\n\n\t* commands.c (child_handler) [not USG]: If called as a signal\n\thandler, use wait3 and don't block.\n\t[USG]: If called as a signal handler, return after handling one child.\n\nSat Feb 18 13:37:04 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* file.c (snap_deps): Process all double-colon entries of each file,\n\tnot just the first one.\n\n\t* Version 3.36.\n\n\t* remote-stub.c: remote.c renamed.\n\tremote.c: Just include remote-stub.c\n\n\t* commands.c (child_handler): If we were called as a signal handler,\n\treturn after handling one child.\n\n\t* commands.c [not USG]: Include <signal.h> and define `sigmask' if\n\t<signal.h> doesn't.\n\t(block_children, unblock_children): Use sigmask rather than\n\tbitshifting explicitly (and incorrectly).\n\n\t* remote.c (remote_kill): New function to send a signal to a\n\tremote child.\n\n\t* commands.c (fatal_error_signal): If we get a SIGTERM, send one to\n\teach living child.  If we get a SIGTERM, SIGINT, or SIGHUP, delete\n\tall pending targets before waiting for children.\n\t(struct child): Add new member `deleted'.\n\t(start_job): Initialize `deleted' member to 0.\n\t(delete_child_targets): New function to delete a given child's\n\ttargets, unless the `deleted' flag in the `struct child' says they\n\thave already been deleted.  Sets this flag before returning.\n\nThu Feb 16 18:32:07 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c [USG]: Define `WRETCODE' correctly (X & 0xff00).\n\nTue Feb 14 16:05:00 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (construct_command_argv): Don't make the 0th element of\n\tthe argument list be \"sh\" when executing /bin/sh, because start_job\n\tuses the 0th element as the program name.\n\nSun Feb 12 17:42:05 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.35.\n\n\t* read.c (readline): Put a null in the beginning of the buffer\n\tbefore starting the reading loop.\n\n\t* read.c (read_makefile): Made main reading loop while\n\t!feof (infile), and removed EOF check after calling readline.\n\nSun Feb  5 19:52:38 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* remote.c (block_remote_children, unblock_remote_children): New\n\t(stub) functions to block and restore asynchronous notification of\n\tremote child death.\n\n\t* commands.c (block_children): Call block_remote_children.\n\t(unblock_children): Call unblock_remote_children.\n\t(child_handler): If called as a signal handler, block remote\n\tchildren on entry and unblock them before returning.\n\n\t* commands.c (child_handler): For unknown children, if they are\n\tremote, give their remote ID; if local, give their PID and make's.\n\n\t* commands.c (execute_file_command): Don't put a new child in the\n\tchain unless start_job succeeds.  Block children before calling\n\tstart_job, and unblock them after putting the child in the chain and\n\tincrementing `job_slots_used' (if start_job succeeded).\n\n\t* commands.c (block_children, unblock_children): Make these globally\n\tvisible (not `static').\n\tcommands.h: Declare block_children and unblock_children.\n\n\t* variable.c (expand_function: `shell'): Use\n\t`shell_function_completed'.  Block children before forking and\n\tunblock after `shell_function_pid' is set properly and\n\t`shell_function_completed' is reset to 0.\n\n\t* commands.c (child_handler): When the child of the `shell' function\n\tcompletes, set `shell_function_completed' to 1 if it actually ran,\n\tor -1 if it didn't (due to fork or exec failure).\n\n\t* commands.c (block_children, unblock_children): New functions to\n\tblock and unblock the child termination signal.\n\t(wait_for_children): Use block_children and unblock_children.\n\t(execute_file_commands): Block children around the critical section\n\twherein a new child is put on the chain.\n\n\t* make.c (main): Change the environment to contain the correct\n\tMAKELEVEL before re-execing.\n\nSat Feb  4 18:28:48 1989  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.34.\n\nFri Feb  3 16:36:49 1989  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* rule.c (default_variables): Fixed $(LINK.c).\n\nWed Feb  1 18:05:07 1989  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Version 3.33.\n\n\t* version.c: Removed copyright notice, since this is a one-line file.\n\n\t* commands.c (error_status): Made it return BUF, rather than running\n\toff the end (this apparently worked on Sun 3s for some reason).\n\n\t* ar.c, commands.c, dep.h, load.c, make.c, make.h, read.c, remake.c,\n\trule.c, variable.c, Makefile: Changed copyrght notices to cover 1989.\n\nMon Jan 30 15:51:28 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.32.\n\nFri Jan 27 20:09:24 1989  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* remake.c (remake_file): Don't touch phony targets.\n\n\t* rule.c (convert_to_pattern): Fixed an incorrect length passed to\n\tsavestring.\n\n\t* variable.c (expand_function: `shell'): Close the read side of the\n\tpipe on the parent side of the fork.\n\n\t* commands.c (start_job): On the child of the fork, close the\n\tBAD_STDIN fd if we're not using it.\n\n\t* read.c (record_files): A file beginning with a dot can be a\n\tdefault target if it also contains a slash (as in `../foo').\n\n\t* commands.c (wait_for_children): For BSD, block SIGCHLD rather than\n\tignoring it to avoid a race condition when child_handler is returning.\n\n\t* commands.c (child_handler): Do blocking waits.\n\t(error_status): Return a string describing exit status.  (Split out\n\tof child_handler).\n\n\t* read.c (multi_glob): Change VECTOR to VEC for Alliant.\n\nThu Jan  5 00:06:51 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.31.\n\n\t* make.texinfo (Features): Noted $(foo:PAT=SUB) from SunOS 4.0.\n\n\t* make.texinfo (Options/Recursion): -d and -p go in the environment.\n\n\t* load.c: Include \"commands.h\".\n\nWed Jan  4 17:49:25 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* make.c (switches): -d and -p can come from the environment and are\n\tput into it.\n\n\t* read.c (record_files): Fixed the checking for duplicate deps so it\n\tdoesn't clobber the first one.\n\n\t* make.texinfo: Documented default implicit rule changes.\n\n\t* rule.c: Revamped default suffix rules.  They now use Sun's style\n\tof using variables `COMPILE.c', `LINK.c', etc. for each suffix, and\n\tuse `TARGET_ARCH' and `TARGET_MACH' variable where appropriate.\n\tAlso support Modula-2 compilation (suffixes .sym, .def, and .mod).\n\tRatfor Yacc support is gone, since nobody has yacc -r.\n\tAll EFL support is gone, since nobody uses EFL.\n\n\t* ar.c, arscan.c: Don't assume `long int' and `int' are the same.\n\n\t* commands.c [USG]: Fixed wait status bit encoding.\n\t[USG and not USGr3] (dup2): Define this for SysVr2.\n\n\t* make.h, dep.h, make.c [iAPX286]: Make allowances for this\n\tbrain-damaged compiler.\n\n\t* make.texinfo (Variables: Flavors): Fixed a typo.\n\nTue Jan  3 18:09:31 1989  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* ar.c (ar_member_date, ar_touch): Truncate member names to 15 chars.\n\n\t* Version 3.30.\n\n\t* commands.c [SYS_WAIT]: If this is defined, use BSD <sys/wait.h>\n\tand wait3 even if USG.\n\n\t* read.c (record_files): Defining .DEFAULT with no deps or commands\n\tclears its commands.\n\n\t* rule.c (default_suffixes): Added `.sh'.\n\t(default_suffix_rules): Added single-suffix .sh rule, copies source\n\tto target and makes target executable.\n\tmake.texinfo (Catalogue of Rules): Documented .sh rule and its use\n\tin conjunction with SCCS.\n\n\t* rule.c (set_default_suffixes): Define variable `SUFFIXES' to the\n\tdefault list (\"\" under -r).\n\tmake.texinfo (Suffix Rules): Document `SUFFIXES' variable.\n\n\t* rule.c (default_variables), make.texinfo (Implicit Variables):\n\tVariable AR defaults to `ar', ARFLAGS to `rv', and RM to `rm -f'.\n\n\t* rule.c (install_default_pattern_rules): Default variables are made\n\trecursive.\n\t(default_variables): Added \"CPP\", defined to \"$(CC) -E\".\n\t(default_suffixes): Added `.S', before `.s'.\n\t(default_suffix_rules): New rule for .S to .s, runs CPP.\n\tAll rules that use CPP now include \"$(CPPFLAGS)\".\n\tmake.texinfo (Catalogue of Implicit Rules, Implicit Variables):\n\tDocumented above changes.\n\n\t* commands.c [USG] (sys_siglist): Don't define.\n\t[USG] (init_siglist): New function to initialize sys_siglist.\n\n\t* make.texinfo (Variables: Reference): Documented `$(foo:PAT=SUB)'\n\treferences.\n\n\t* variable.c (variable_expand): A reference `$(foo:PAT=SUB)' is\n\tequivalent to `$(patsubst PAT,SUB,$(foo))'.\n\n\t* variable.c (variable_expand): Free the storage for the expansion\n\tof a recursive variable when it is nod longer needed.\n\n\t* variable.c (variable_expand): When checking for `$($(foo))', use\n\tlindex so as not to search for the second `$' outside the parens.\n\n\t* make.c (struct stringlist, main, decode_switches): Changed `index'\n\tmember to `idx'.\n\nSat Dec 24 16:02:32 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (wait_for_children [USG]): Handle SIGCLD with SIG_DFL,\n\trather than SIG_IGN.  Ignoring SIGCLD reportedly makes wait return -1.\n\n\t* arscan.c [USGr3]: Define PORTAR to 1 (as with sun386).\n\t(ar_scan [USGr3]): Remove trailing slashes from member names.\n\nThu Dec 22 17:54:05 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* make.texinfo (Makefiles: Overriding Makefiles): New node\n\tdocumenting use of .DEFAULT to have one makefile defer unmakeable\n\ttargets to another.\n\n\t* make.texinfo (Implicit: Using Implicit, Implicit: Last Resort):\n\tMention empty commands and xref node `Empty Commands'.\n\nWed Dec 21 20:12:40 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.29.\n\n\t* make.c (struct command_switch, command_switches, et al): New\n\tmember `noarg_value', if not nil, ptr to value to use if no arg is\n\tgiven to a switch that would otherwise require one.  The -j option\n\tcan now be given w/o an arg, to mean infinite jobs.\n\t* commands.c: If job_slots is zero, infinite jobs.\n\n\t* read.c (read_all_makefiles, read_makefile): Make makefiles precious.\n\n\t* make.c (decode_switches): For a positive_int or floating option,\n\tif we moved to the next argument word, but found no argument for the\n\toption, move back to the correct word.\n\n\t* make.c (decode_switches): If we got any unknown options, die after\n\tprocessing all arguments.\n\n\t* GNUmakefile: Moved `include depend' to the end, so the default\n\tgoal will be set before then.\n\n\t* load.c (wait_to_start_job [Unix, UMAX]): Merged into one version\n\tunder #ifdef LDAV_BASED.  Only loop while we have jobs running.\n\tSleep for increasing amounts (increase one second per iteration)\n\tbefore checking the load average (after the first check).\n\tGet the load average from function load_average.\n\t(wait_to_start_job [not LDAV_BASED]): Always return.\n\t(load_average [UMAX]): Fetch load average for Encore UMAX.\n\t(load_average [not NO_LDAV]): Fetch load average from /dev/kmem.\n\t[not NO_LDAV]: Define LDAV_BASED.\n\nTue Dec 20 18:54:50 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.28.\n\n\t* commands.c (wait_for_children): Take second arg, ERROR.  If\n\tnonzero, and there are children, print a message on stderr.\n\t(execute_file_commands, fatal_error_signal): Pass second arg.\n\t* make.c (die), remake.c (update_goal_chain), variable.c\n\t(expand_function: `shell'): Ditto.\n\nSat Dec 17 01:05:38 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* commands.c (start_job): Call wait_to_start_job before forking.\n\n\t* load.c (load_average): Converted to wait_to_start_job.\n\n\t* remote.c: New file for remote execution functions.\n\t(start_remote_job_p): Return nonzero if the next job should be run\n\tremotely.\n\t(start_remote_job): Start a remote job and return an ID for it.\n\t(remote_status): Get status of dead remote children.\n\nFri Dec 16 16:51:07 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* commands.c (start_job): If start_remote_job_p () returns nonzero,\n\tcall start_remote_job to start the job rather than fork and exec.\n\t(child_handler):\n\n\t* commands.c (execute_file_commands): Moved load average checking to\n\tstart_job.\n\n\t* commands.c (child_handler: USG): Record the pid wait returns.\n\n\t* load.c (UMAX): Added some #include's needed for UMAX.\n\n\t* read.c (multi_glob), variable.c (string_glob): Ignore a (char **)\n\t-1 return from glob_filename.\n\n\t* variable.c (variable_expand): Make sure we don't increment past\n\tthe end of the string we were passed.\n\n\t* variable.c (variable_expand): Terminate the expansion.\n\n\t* file.c (rename_file): If there is already a file under the new\n\tname, set its contents equal to FILE's (ick).\n\n\t* variable.c (define_automatic_variables): Pass all the args to\n\tdefine_variable when defining MAKELEVEL!\n\n\t* commands.c (execute_file_commands): If max_load_average > 0, and\n\twe have children running, don't start up another child until the\n\tload average goes below max_load_average.\n\n\t* make.c: New variable `max_load_average'.\n\t(struct command_switch, decode_switches, decode_env_switches):\n\tHandle floating-point (double) args.\n\t(command_switches): Added `-l' switch to set `max_load_average'.\n\n\t* load.c (load_average): New file and function to return a double\n\tthat is the current load average (1.00 scale).\n\t* GNUmakefile, oldMakefile: Pass flags in $(LOAD_AVG) for load.c.\n\nThu Dec 15 15:22:08 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Makefile: Renamed to oldMakefile.\n\t* GNUmakefile: Make Makefile from oldMakefile and depend.\n\n\t* read.c (read_all_makefiles): When putting the default makefiles in\n\tthe read_makefiles chain so they will be remade, put them in the\n\tright order.\n\n\t* remake.c (update_goal_chain): If MAKEFILES is nonzero, always make\n\tin serial, and return as soon as one goal whose `changed' member is\n\tnonzero  is successfully remade.\n\n\t* commands.c: Don't include <sys/fcntl.h>.\n\n\t* commands.c (construct_command_argv): Added ` to sh_chars.\n\n\t* make.h: Don't declare construct_makeflags.\n\n\t* make.c (main): Set up MAKEFLAGS and MFLAGS and make an environment\n\tboth before and after reading the makefiles, so the makefiles can\n\tuse them and possible change them, and later children will get the\n\tright information.\n\t(construct_makeflags): Replaced with define_makeflags (static void),\n\twhich defines the two variables.\n\t* variable.c (define_automatic_variables): Don't define MAKEFLAGS\n\tand MFLAGS.\n\nMon Dec 12 14:40:31 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* Version 3.27.\n\n\t* commands.c (child_handler): Reset the handler to ourselves when\n\tcalled for USG, since it has no safe signals.\n\n\t* commands.c: For USG, use an int rather than a `union wait' for\n\twait calls, and dissect it with bitmasks.\n\t(child_handler): No wait3 system call in USG.  Since we can't\n\tprotect from hanging, always return immediately if we have no\n\tchildren we know about and we're not running a `shell' function.\n\t(There is still the danger of hanging waiting for a child that died\n\twithout our being notified.)\n\n\t* remake.c: Include <fcntl.h> instead of <sys/file.h>.  What we need\n\tis really in <fcntl.h>, and while BSD <sys/file.h> includes\n\t<fcntl.h>, USG doesn't.\n\n\t* make.c (main): Figure out the program name before doing anything\n\twhich might need it (in a call to error or fatal).\n\n\t* dir.c, glob.c: Use `struct dirent' and <dirent.h> for USGr3.\n\n\t* arscan.c (ar_scan): Added missing & before buf (which is an int)\n\tif SARMAG is not defined (SysV).\n\nFri Dec  9 18:44:13 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Version 3.26.\n\n\t* dir.c (find_directory, dir_file_exists_p): Keep track of how many\n\tdirectories we have open and don't let it be more than\n\tMAX_OPEN_DIRECTORIES (currently 10).\n\n\t* variable.c (expand_function: `foreach'): Use expand_argument\n\trather than variable_expand so each repetition doesn't clobber the\n\tlast!!!\n\nMon Dec  5 15:58:46 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* Version 3.25.\n\n\t* Makefile: Define `install' target.\n\n\t* GNUmakefile: Don't include GNUmakefile or depend in the\n\tdistribution file.\n\nWed Nov 30 15:53:42 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* commands.c (execute_file_commands): Don't clobber a null into\n\trandom storage if there were no $^ and/or $? words.\n\n\t* remake.c (check_dep): Set *MUST_MAKE_PTR nonzero if a dependency\n\tdoesn't exist.\n\n\t* ar.c (ar_member_date, ar_touch): Make sure the modtime of the\n\tarchive file itself is known before we fetch or change the modtime\n\tof one of its members.\n\n\t* read.c (read_makefile): Expand variable and function references\n\tbefore parsing rules so variable can contain special characters\n\t(colons and semicolons).\n\nSat Nov 26 11:36:31 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* variable.c (expand_function: `filter', `filter-out'): Fixed so\n\tthat filter-out works right.\n\n\t* variable.c (expand_function: `filter', `filter-out'): Made these\n\tfunctions use each word of their first argument as a pattern.\n\nFri Nov 25 10:51:47 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.24.\n\n\t* read.c (record_files): If a target is listed more than once in a\n\tsingle rule (that defines commands), give a warning message rather\n\tthan the counter-intuitive message saying commands were already\n\tdefined (in the same place).\n\n\t* make.c (fatal, error): Made them both take 6 args since there is\n\tat least one error message that need that many.  Too bad vfprintf is\n\tnot universal!\n\n\t* Version 3.23.\n\n\t* read.c (read_makefile): Moved the construction of the `struct\n\tcommands' into record_files.  Call record_files before recursing for an\n\tincluded makefile so the higher-up will determine the default goal.\n\t(record_files): Take arguments COMMANDS, COMMANDS_IDX and\n\tCOMMANDS_STARTED and construct a `struct commands.\n\nThu Nov 24 14:36:33 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.22.\n\n\t* make.c (main): Made it a fatal error if we can't move back to the\n\tdirectory we started in before re-execing.\n\n\t* make.c (main): Get the current directory before doing anything\n\telse, so we know it even if we don't need it for the value of\n\t`MAKE', since we might want it when re-execing.\n\nWed Nov 23 13:34:44 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.21.\n\n\t* read.c (record_files): Eliminate duplicate deps in a chain.\n\n\t* variable.c (expand_function: `sort'): Pass the right number to\n\tqsort, not one less.\n\n\t* remake.c (remake_file): Always call notice_finished_file if\n\tFILE->command_state == cs_finished.\n\n\t* commands.c (execute_file_commands): Call notice_finished_file to\n\tset FILE's status correctly when start_job fails (because it's out\n\tof commands or running under -n).\n\nFri Nov 18 15:31:12 1988  Roland McGrath  (mcgrath at saffron.Berkeley.EDU)\n\n\t* Version 3.20.\n\n\t* remake.c (update_file_1): Set the `update_status' of FILE to\n\tnonzero and set FILE's `updated' bit if we have decided to give up\n\ton remaking FILE because of errors in the dependencies.\n\n\t* rule.c (pattern_search): Debugging messages use `dependency' (vs.\n\t`dependent') properly.\n\n\t* make.texinfo (Conditionals: Conditional Syntax): Function index\n\tentries for `ifndef' and `ifneq'.\n\n\t* variable.c (define_automatic_variables): Define `MAKELEVEL' to the\n\tdecimal number of the makelevel, since it may be malformed or blank.\n\n\t* remake.c (remake_file): Call notice_finished_file after touching.\n\nSat Nov 12 19:29:34 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.19.\n\n\t* GNUmakefile (dist): Pass the `-f' flag to compress.\n\n\t* vpath.c (build_vpath_lists): Check for VPATHS being nil after\n\tconstructing the general VPATH list from the `VPATH' variable.\n\nFri Nov 11 08:02:26 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (fatal, error): Made error messages for recursive runs be\n\tshorter.\n\nThu Nov 10 16:51:36 1988  Roland McGrath  (mcgrath at basil.Berkeley.EDU)\n\n\t* Version 3.18.\n\n\t* read.c (read_makefile): Made it eat leading spaces and formfeeds\n\t(but not tabs), like it's documented to.\n\n\t* read.c (read_makefile): Let included makefiles determine the\n\tdefault goal, as is done by System V Make.\n\nTue Nov  1 19:03:08 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* variable.c (new_environ): Don't increment VCNT when a variable is\n\trejected.\n\nFri Oct 28 16:54:15 1988  Roland McGrath  (mcgrath at basil.Berkeley.EDU)\n\n\t* Version 3.17.\n\n\t* rule.c (convert_to_pattern): Don't use the same storage for a name\n\tin two rules since new_pattern_rule may free this storage when a\n\trule is discarded.\n\n\t* rule.c (new_pattern_rule): Undid useless change I made Oct 25.\n\nThu Oct 27 19:17:53 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.16.\n\n\t* GNUmakefile, Makefile: Fixed a typo in a comment.\n\t* Makefile: Removed malloc.o from object file list.\n\n\t* variable.c: Removed old debugging #define's for xmalloc and\n\txrealloc so non-ANSI cpp's won't barf.\n\n\t* make.c (main): Made local array for temp file name static so\n\tcompilers that don't do auto aggregate initialization won't barf.\n\n\t* read.c: Removed static declaration of copy_dep_chain since it is\n\tno longer static.\n\nTue Oct 25 16:59:30 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* rule.c (new_pattern_rule): If we threw out the new rule because it\n\tmatched an old one and OVERRIDE was zero, don't put the freed\n\tpointer in the chain!\n\nWed Oct 19 15:07:43 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Version 3.15.\n\n\t* variable.c (expand_function: `sort'): Don't do the sorting and\n\twriting out if there were no words in the first place.\n\n\t* remake.c (remake_file): Only fail with a \"no way to make\" message\n\tfor a dependency (non-target) file.  If we don't know how to remake\n\ta target file, pretend it was successfully remade and is very new.\n\n\t* remake.c (remake_file): Don't increment `files_remade' for a\n\tnon-target file we don't know how to remake.\n\n\t* read.c (record_files): Don't die with \"both : and :: entries\" for\n\ta file whose `is_target' flag is not set.\n\nTue Oct 18 17:24:11 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* variable.c (expand_function: `patsubst', `subst'): Free the right\n\tthings!\n\n\t* variable.c (expand_function: `subst'): Don't clobber the\n\tpointer to the end of the second arg and then try to use it!!!\n\nMon Oct 17 16:44:45 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)\n\n\t* variable.c (expand_function: `patsubst'): Don't clobber the\n\tpointer to the end of the second arg and then try to use it!!!\n\n\t* variable.c (expand_function: `word' function): Made it parse its\n\tsecond argument correctly.\n\n\t* ar.c (ar_touch): Return 1 rather than -1 for on errors.\n\nSat Oct 15 15:12:16 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.14.\n\n\t* GNUmakefile: Removed explicit rule for make.dvi since the built-in\n\timplicit rule now works.\n\n\t* rule.c (default_suffix_rules): Fixed .texinfo.dvi rule yet again\n\tso that it really works, now that parens are counted.\n\n\t* remake.c (update_file_1): Set FILE's `updated' flag after calling\n\tremake_file if it failed or finished immediately.\n\n\t* remake.c (update_file): Use the `updated' flag rather than the\n\tcommand state to decide if a file was fully considered, and\n\ttherefore might give an \"up to date\" message.\n\n\t* variable.c (expand_function): Made all functions that take more\n\tthan one argument count parens of the appropriate flavor in their\n\targs and ignore commands nested in parens.\n\nFri Oct 14 18:35:00 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* read.c (read_all_makefiles): Pass second arg to read_makefile for\n\tdefault makefiles.\n\nThu Oct 13 16:40:08 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.13.\n\n\t* GNUmakefile: Added an explicit rule for make.dvi since the\n\tbuilt-in .texinfo.dvi implicit rule is screwed up.\n\n\t* rule.c (default_suffix_rules): Added a comment that the\n\t.texinfo.dvi rule does not work because of an ahem, feature of Make\n\tthat at some point will be fixed--er, enhanced to alleviate this\n\tdifficulty.\n\n\t* rule.c (default_suffix_rules): Fixed Texinfo -> DVI rule (again).\n\n\t* make.texinfo (Commands: Execution): Documented new competing for\n\tstandard input among children.\n\n\t* commands.c (struct child): Added `good_stdin' flag to tell if this\n\tchild has the stdin that doesn't point into nirvana.\n\t(good_stdin_used): New variable to tell if any child has the good\n\tstandard input.\n\t(child_handler): Reset `good_stdin_used' if a dead child's\n\t`good_stdin' flag is set.\n\t(start_job): Give the new child the good standard input if\n\t`good_stdin_used' is no set, and set the child's `good_stdin' flag\n\tappropriately.\n\n\t* rule.c (default_suffix_rules): Changed Texinfo -> DVI rule to work\n\tbetter (I hope).\n\n\t* read.c (read_all_makefiles): Stop reading default makefiles after\n\tone is found.\n\n\t* read.c (read_makefile): Reset `reading_filename' and\n\t`reading_lineno_ptr' after recursing for an included makefile.\n\n\t* GNUmakefile: New GNU Make-specific makefile that does everything\n\tMakefile does plus distribution stuff, and doesn't contain any hacks\n\tto try to work with Unix make.\n\n\t* Makefile: Removed distribution stuff.\n\n\t* make.c (main): Use mktemp to construct the names of temporary\n\tfiles used for standard input makefiles.\n\n\t* make.c (main): Don't turn standard input into a broken pipe.\n\n\t* commands.c (start_job): Keep two extra file descriptors around: a\n\tgood standard input, and a bad one that reads from a broken pipe.\n\tOn the child side of the fork, if there are other children, give\n\tthis one the broken pipe so they won't compete; if this is the only\n\tone, give it the good standard input.\n\n\t* make.h: Declare notice_finished_file.\n\n\t* commands.c (execute_file_commands): Use noticed_finished_file\n\tafter waiting for the child when there is only one job slot.\n\n\t* remake.c (notice_finished_file): New function to re-check mtime's\n\tand such things to be done when commands finish.\n\t(update_file_1): Use notice_finished_file.\n\n\t* commands.c (child_handler, execute_file_commands): Use new\n\tvariable `job_slots_used' to record the number of jobs currently\n\trunning, rather than diddling with `job_slots'.\n\t(execute_file_commands): Increment `job_slots_used' before calling\n\tstart_job and decrement it on failure to avoid race condition.\n\tIf there is only one job slot, wait for the child to finish and\n\treturn its status so commands are run in linear order, as if there\n\twere no parallelism.\n\nWed Oct 12 15:59:03 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* remake.c (remake_file): Don't print a \"No way to make\" message for\n\ttargets whose `dontcare' flags are set.\n\n\t* read.c (read_all_makefiles): Set the `dontcare' flag of the\n\t`struct file' each default makefile added to the chain.\n\n\t* file.h (struct file): Add `dontcare' member.\n\n\t* read.c (read_all_makefiles): When no default makefiles are found,\n\tput the names of all those tried in the `read_makefiles' chain so\n\tthey will be updated if possible, giving their `struct dep's'\n\t`changed' members the value of 0 so we won't care if they cannot be\n\tfound or remade.\n\n\t* make.texinfo (Makefiles: Remaking Makefiles): Documented that\n\tdefault makefiles will be remade if not found.\n\n\t* read.c (read_all_makefiles): If no default makefiles can be found,\n\tgo through the list of default names, trying to make one, stopping\n\tif one is made.\n\n\t* remake.c (remake_file): Set STATUS to 0 after successfully touching.\n\n\t* dir.c (file_impossible, file_impossible_p): Don't clobber FILENAME\n\tto \"\" and then try to to a strcmp on it!!!\n\nMon Oct 10 16:09:18 1988  Roland McGrath  (mcgrath at cinnamon.Berkeley.EDU)\n\n\t* make.c (main): Don't do `dir_load (\".\")'.\n\n\t* rule.c (count_implicit_rule_limits), vpath.c\n\t(construct_vpath_list): Test the existence of a given directory by\n\t`dir_file_exists_p (DIR, \".\")' and assume that if this returns zero,\n\tit means the directory really does not exist.\n\n\t* dir.c (struct dirdata): Replaced with `struct directory' for\n\tdirectories, each containing a chain of `struct dirfiles', one for\n\teach file (real or impossible).\n\t(dir_load): Removed.\n\t(find_directory): New function to find the `struct directory' for a\n\tnamed directory and return it (possibly creating a new one).\n\t(dir_file_exists_p): Read the directory on the fly if its stream is\n\tstill valid (and ever was) if the file we're looking for is not\n\talready in the hash tables.\n\t(file_impossible, file_impossible_p, dir_name, print_dir_data_base):\n\tUse the new directory/file scheme.\n\n\t* make.texinfo: Miscellaneous editorial changes and clarifiactions.\n\n\t* commands.c (struct child): Remove `environ' member.\n\t(child_handler, start_job, execute_file_commands): Remove use of\n\t`environ' member and new_environ.\n\n\t* make.c (main): Call new_environ after reading makefiles.\n\n\t* variable.h: Declare `new_environ' to return void.\n\n\t* variable.c (new_environ): Put the environment in `environ' and\n\treturn void.\n\nFri Oct  7 15:48:39 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Version 3.12.\n\n\t* Makefile: Don't make the uncompressed tar file.\n\n\t* variable.c (expand_function: `shell' function): Made it not expect\n\tread to null-terminate the buffer.\n\n\t* Makefile: Made it use a temporary symlink to . rather than a\n\ttemporary directory to make the distribution tar file.\n\nThu Oct  6 17:52:35 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.11.\n\n\t* make.texinfo: Fixed a line that got garbaged somehow.\n\nMon Oct  3 16:14:39 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* make.c (main): Try to move back to the directory we started in\n\tbefore re-exec ourself.\n\n\t* remake.c (update_file_1): A double-colon target with no deps\n\talways needs to be remade.\n\n\t* remake.c (remake_file): Changed \"No way to make\" message to say\n\t`target' rather than `file'.\n\nSun Oct  2 12:50:47 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)\n\n\t* remake.c (update_file_1): Set FILE->update_status to the return\n\tvalue of remake_file.\n\n\t* rule.c (convert_to_pattern): Fixed swapped lengths passed to\n\txmalloc for source/target suffixes.\n\n\t* make.texinfo: Documented that MAKEFLAGS and MFLAGS are read in\n\tfrom makefiles.  Updated the `Features' section a bit.\n\n\t* make.c (main): Read switches from MAKEFLAGS and MFLAGS variables\n\tafter reading in makefiles.\n\n\t* make.c (main): Put a line \"/tmp/foo:;\" rather than \".PHONY:\n\t/tmp/foo\" in front of temp files made for stdin makefiles.\n\n\t* remake.c (update_file): Test the state of the right `struct file'\n\tfor double-colon files.\n\n\t* make.c (main): Put a \".PHONY: /tmp/foo\" line in front of temp\n\tfiles made for stdin makefiles so they won't be remade when we\n\tre-exec.  Kludge-o-matic!!\n\n\t* remake.c (update_goal_chain): Judge files as being finished based\n\ton their `updated' flag, not their state.\n\n\t* read.c (read_makefile): Don't check for FILENAME being \"-\".\n\t(read_all_makefiles): Set each element of MAKEFILES to the name put\n\tin READ_MAKEFILES by read_makefile, since read_makefile may free the\n\tstorage for the name it is passed, and someone might want to look at\n\tthe elements of MAKEFILES again.\n\n\t* make.c (main): For each `-f' flag with arg `-' (standard input),\n\tread standard input into a temp file and pass the temp file's name\n\tto read_all_makefiles, after making sure it will not be remade.\n\n\t* make.c (construct_makeflags): Always put out `-j1'.\n\nSat Oct  1 00:19:59 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* commands.c (execute_file_commands): If commands are nothing but\n\twhitespace, set the state to `cs_finished' before returning 0.\n\n\t* make.c (decode_switches): Allocate space for args in stringlists\n\tso they can be freed later.\n\n\t* make.h: Declare `makelevel'.\n\n\t* variable.c (makelevel): Moved to make.c (and made global).\n\n\t* make.c (fatal, error): Print the makelevel if it's > 0.\n\t(perror_with_name): Use error rather than calling fprintf directly.\n\t(pfatal_with_name): Use fatal rather than fprintf and die.\n\n\t* variable.c (new_environ): Don't put default variables (origin\n\t`o_default') into the environment; they just take up space.\n\n\t* read.c (read_makefile): Don't add FILENAME to the chain of read\n\tmakefiles if it's \"-\" (standard input).\n\n\t* remake.c (update_goal_chain): Set STATUS correctly when nothing\n\thappens (as well as in all other situations).\n\n\t* make.c (construct_makeflags): Put a `-' before each switch and\n\tspaces between them.\n\n\t* Version 3.10.\n\n\t* commands.c (wait_for_children): Don't check if `children' is nil.\n\tThis is the case when waiting for the child of a `shell' function.\n\n\t* dir.c (dir_load): Don't add a hash-table entry for directory\n\tDIRNAME and filename \"\" if DIRNAME doesn't exist.\n\n\t* commands.c (execute_file_commands): Return 0 after start_job\n\treturns 1 (failure) under the -n flag.\n\n\t* remake.c (remake_file): Set the state to `cs_finished' when not\n\tcalling execute_file_commands.\n\n\t* remake.c (update_goal_chain): Second arg is now MAKEFILES, nonzero\n\tmeaning to disable -t, -q, and -n for each target unless the target\n\twas also given on the command-line.\n\n\t* read.c (read_makefile): Enter the `struct file's for the makefiles\n\tadded to the `read_makefiles' `struct dep' chain.\n\n\t* remake.c (update_goal_chain): Made it not enter the files for the\n\tgoals in the chain.  It will already have been done.\n\n\t* rule.c (convert_to_pattern): Null-terminate the names of targets\n\tand deps of the pattern rules properly.\n\nFri Sep 30 18:56:20 1988  Roland McGrath  (mcgrath at nutmeg.Berkeley.EDU)\n\n\t* make.c (main): Call install_default_pattern_rules.\n\n\t* make.h: Declare copy_dep_chain.\n\n\t* read.c (copy_dep_chain): Moved to make.c (and made global).\n\n\t* make.c (main): Call update_goal_chain to update goals.\n\tUpdate read makefiles and re-exec self if they change.\n\n\t* remake.c (update_file): Make this function static.\n\t(update_goal_chain): New function to update a `struct dep' chain of\n\tgoals, waiting until they are all finished before returning.\n\n\t* make.h: Don't declare update_file.  Declare update_goal_chain.\n\n\t* make.c (main): Call snap_deps, etc. that were in read_all_makefiles.\n\n\t* read.c (find_makefile): Removed this function.\n\t(read_all_makefiles): Don't update makefiles, don't diddle with\n\tpattern rules, don't call snap_deps, etc.  Return a `struct dep'\n\tchain of all makefiles read.\n\t(read_makefile): Now takes two args: FILENAME and TYPE, which is 0\n\tfor a normal makefile, 1 for MAKEFILES variable or 2 for an included\n\tmakefile.  Add a `struct dep' containing the name of the makefile\n\t(as it was found in the search path for type 2s), and TYPE in the\n\t`changed' member to the global `read_makefiles' chain.\n\n\t* make.h, rule.c (displace_pattern_rules,\n\tadd_displaced_pattern_rules): Removed these functions.\n\n\t* read.c (read_makefile): Variable-expand the name of an `include'd\n\tmakefile before calling find_makefile on it.\n\n\t* file.c (snap_deps): If the `struct file' for a `struct dep'\n\talready exists, free the `struct dep's `name' member before setting\n\tit to nil (since this info is in the `struct file').\n\n\t* read.c (copy_dep_chain): Made it copy each name rather than\n\tleaving multiple `struct dep's with the same pointers.\n\nThu Sep 29 19:08:13 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)\n\n\t* make.c (decode_switches): Fixed second decode_env_switches call to\n\tuse correct length of \"MFLAGS\" (6, not 5).\n\n\t* read.c (read_makefile): Don't stop reading when readline returns\n\tzero lines read.  Only stop when the stream reaches EOF.  This makes\n\tit recognize the last line of a makefile without a newline.\n\n\t* remake.c (remake_file): If we don't know how to make FILE, set its\n\tcommand state to `cs_finished'.\n\n\t* remake.c (update_file): Don't write the \"up to date\" message if\n\tupdate_file_1 returned a nonzero status.\n\nWed Sep 28 16:30:07 1988  Roland McGrath  (mcgrath at catnip.Berkeley.EDU)\n\n\t* commands.c (child_handler): Set the `update_status' member\n\tproperly for ignored errors.\n\n\t* rule.c (convert_to_pattern): Made it not care about if the target\n\tsuffix comes before the source suffix in the .SUFFIXES list.\n\n\t* make.texinfo: Misc editorial changes.\n\n\t* commands.c (wait_for_children): Return immediately if `children'\n\tis nil (there are no children).\n\nTue Sep 27 15:33:14 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Version 3.09.\n\n\t* commands.c (struct child): New member `command_ptr' to hold the\n\tcurrent position in the commands.  The `commands' member is never\n\tchanged.\n\t(start_job, child_handler, execute_file_commands): Use new method\n\tfor `commands' and `command_ptr' members.\n\n\t* make.c (decode_env_switches): Skip past an invalid letter (instead\n\tof looping forever).\n\n\t* commands.c (struct child): Add `environ' member to hold the\n\tenvironment for this child.\n\t(execute_file_commands): Get a new environment from new_environ and\n\tput in the the new `struct child's `environ' member.\n\t(child_handler): When freeing a child, free its `commands' member, the\n\telements of its `environ' array and its `environ' member itself.\n\t(start_job): Set `environ' to the child's `environ' member before\n\texec'ing the command.\n\n\t* variable.h, variable.c (new_environ): Made it return the new\n\tenvironment, not putting it in `environ'.\n\n\t* remake.c (update_file): Don't give a \"is up to date\" message\n\tunless no files were remade and the state went from `cs_not_started'\n\tto `cs_finished', so repeat calls to finish jobs won't get the message.\n\nMon Sep 26 16:26:08 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* Version 3.08.\n\n\t* make.texinfo (Commands: Execution): Documented that children will\n\tbe waited for rather than killed.\n\n\t* commands.c (fatal_error_signal): Wait for children.\n\t(kill_children): Removed this function.\n\n\t* make.c (main, die): Wait for children to die, don't kill them.\n\n\t* variable.c (expand_function): Use wait_for_children.\n\n\t* make.c (main): Use wait_for_children rather than child_handler.\n\n\t* commands.c (wait_for_children): New function to block waiting for\n\tchildren, insuring that child_handler is not called recursively.\n\t(execute_file_commands, kill_children): Use wait_for_children.\n\n\t* commands.c (child_handler): Start up additional commands in a\n\tsequence after an ignored error.\n\n\t* remake.c (update_file): Don't print \"`foo' is up to date\" messages\n\twhen update_file_1 returns while commands are executing.\n\n\t* remake.c (update_file_1): Pass the file name to name_mtime, not\n\tthe bloody `struct file', dammit!!\n\n\t* commands.c (child_handler): Print out the \"*** ...\" error message\n\twhen not under -i.  (I somehow forgot this.)\n\n\t* remake.c (update_file_1): Use name_mtime rather than file_mtime to\n\tre-get the mtime of a file whose commands have finished.\n\n\t* make.c (command_switches, decode_switches, decode_env_switches):\n\tMake all switches that take string args allow them right after the\n\tswitch letter.\n\n\t* commands.c (child_handler): Check for a child being the `shell'\n\tfunction's command returning and set the global variable for\n\texpand_function to check.\n\n\t* variable.c (expand_function): For the `shell' function, instead of\n\twaiting for the child shell ourselves, let child_handler do it and\n\tloop around waiting for something to happen.\n\n\t* make.c (print_version): Made the copyright year static, not dynamic.\n\n\t* make.h, make.c: Remove construct_argv function.\n\n\t* make.c (main): Say \"no goal target\" instead of \"no target\".\n\n\t* make.texinfo (Commands: Parallel): Don't send SIGKILL.\n\n\t* commands.c (kill_children): Don't send SIGKILL to children that\n\taren't killed by the first signal.\n\n\t* make.c (main), commands.c (kill_children): Decide between SIGCHLD\n\tand SIGCLD based on whether or not SIGCHLD is defined, not on USG.\n\n\t* Makefile: Link make with $(LOADLIBES).\n\n\t* read.c (construct_include_path): Fixed another bad xrealloc call.\n\n\t* make.c (decode_switches): Fixed an xrealloc call with no first arg.\n\nSat Sep 24 01:16:21 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* Version 3.07.\n\n\t* remake.c (update_file_1): If deps are running, set state to\n\t`cs_deps_running' and return 0.  If deps are done, run commands.\n\n\t* commands.c (child_handler): Made it delete non-precious targets\n\tkilled by fatal signals.\n\n\t* make.texinfo: Documented parallelism.\n\nFri Sep 23 16:52:27 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* remake.c (update_file_1): Don't return if FILE's state is\n\t`cs_deps_running'.  In that case, we need to run through and check\n\tthe states of all our dependencies.\n\n\t* commands.c (execute_file_commands): Decrement `job_slots' after\n\tstarting a new job to run file commands.\n\n\t* commands.c (start_job): Made it set the state to `cs_running'.\n\n\t* make.c (main): Fixed usage of `g', `lastgoal', and `goals' in the\n\tgoal-making loop.\n\n\t* commands.c (child_handler): When commands finish, set the\n\tcorresponding file's `update_status' and `updated' flags as\n\tappropriate, and reset the modtimes of the file and any `also_make'\n\tfiles it has.\n\n\t* remake.c (remake_file): Don't re-set `last_mtime' and set `updated'.\n\n\t* commands.c (fatal_error_signal): Don't swallow all the children\n\twith a loop around `wait ((union wait *) 0)'!!!\n\n\t* make.c (struct command_switch): Added `positive_int' type.\n\t(switches): Added -j (job_slots).\n\t(construct_makeflags, decode_switches, decode_env_switches):\n\tHandle`positive_int'-type switches.\n\n\t* glob.c (glob_vector): Rename local variable `vector' to `VeCtOr'.\n\tThis is said to avoid a conflict with some system's global `vector'\n\tvariable.\n\n\t* variable.c (expand_function): Made the `shell' function use\n\tconstruct_command_argv and do its own child control and piping.\n\n\t* make.c (main): Turn standard input into a broken pipe after\n\treading in all makefiles (the last time it will be needed).\n\n\t* commands.c (struct child): Remove `pipe_fd' member.  We don't use\n\tpipes any more.\n\t(start_job): Return 0 for success, 1 or failure (rather than void).\n\tDon't use pipes.  Don't turn the child's stdin into a broken pipe.\n\t(child_handler): Print \"*** Error\" messages when necessary.\n\tDie on failed commands when -k was not given.\n\t(execute_file_commands): Check the return of start_job and remove\n\tthe child from the chain and return failure if it is nonzero.\n\n\t* make.c (die): New function to clean up and exit.\n\t(fatal, pfatal_with_name): Use die.\n\nThu Sep 22 14:27:11 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* commands.c (struct child): Added `commands', `pipe_fd', and\n\t`noerror' members to keep track of info about a command thread.\n\t(start_job): New function to start a job and update the argument\n\t`struct child' to reflect its status.\n\t(execute_file_commands): Merged run_file_commands back in.\n\tMade it use new start_job function.\n\n\t* rule.c (freerule): Don't free the `struct commands' of the\n\tdiscarded rule.  It may be used in more than one place.\n\n\t* commands.c (execute_command_line): Made it not try to delete the\n\tpossibly partly-made file.  The child_handler function will do this.\n\t(fatal_error_signal): Ditto + call kill_children.\n\n\t* make.h: Declare job_slots.\n\n\t* make.c (main): Collect goals in a dep chain and run through this\n\tchain waiting for a child, eliminating finished goals, updating all\n\tremaining goals, and quitting if they fail and not -k.\n\n\t* commands.c (child_handler): If called with SIG < 0, - SIG is the\n\tmax number of children to bury.\n\n\t* commands.c (child_handler): If called with SIG as zero,\n\tblock waiting for running children.\n\t(kill_children): Call child_handler with zero rather than SIGCHLD.\n\n\t* remake.c (update_file_1): Use the `command_state' member of FILE\n\tand its dependencies to determine what commands are running, what to\n\tdo, etc.  If commands or dep commands are running when we are\n\tcalled, return success (0).  If commands finished since the last\n\ttime we were called, return their status.\n\n\t* commands.h: Declare kill_children.\n\n\t* commands.c: Define `struct child' to keep track of child\n\tprocesses, with the chain in `children'.\n\t(child_handler): New function to catch child-termination signals\n\t(SIGCHLD, or SIGCLD for USG), store the returned status in the\n\tappropriate structure, take the now-obsolete `struct child' out of\n\tthe chain, and free its storage.\n\t(execute_file_commands): Put all of the stuff invloving running the\n\tcommands into new function run_file_commands.  Execute_file_commands\n\tnow does process management for the commands, while\n\trun_file_commands (which is run in a subprocess) runs the commands.\n\t(kill_children): New function to kill all running children by\n\tsending them signal SIG.  If there are any children still living\n\tafter they are all sent SIG, they are all sent SIGKILL.\n\n\t* make.c (main): Catch SIGCHLD (SIGCLD for USG) with child_handler.\n\n\t* commands.h: Declare child_handler function.\n\n\t* commands.c (execute_file_commands): Check the `command_state'\n\tmember of FILE and return 0 if it is `cs_running' or\n\t`cs_deps_running' and return the stored status if it is `cs_finished'.\n\n\t* file.h (struct file): Added `command_state' member.\n\n\t* commands.c (execute_command_line): Add `$' to the list of\n\tcharacters special to the shell.\n\nWed Sep 21 15:57:41 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* read.c (read_all_makefiles): Call convert_to_pattern before\n\trecomputing the limits after adding the displaced rules.\n\n\t* make.c (main): Move calls to snap_deps, convert_to_pattern, and\n\tbuild_vpath_lists to read_all_makefiles.\n\n\t* read.c (read_all_makefiles): Install the default pattern rules\n\tbefore checking to remake the makefiles, displace these rules before\n\treading in the makefiles, and then add the displaced rules to the\n\tchain after reading in all the makefiles.\n\n\t* make.c (main): Don't call install_default_pattern_rules or\n\tcount_implicit_rule_limits.\n\n\t* make.h: Declare displace_pattern_rules and\n\tadd_displaced_pattern_rules.\n\n\t* rule.c (displace_pattern_rules, add_displaced_pattern_rules): New\n\tfunctions to stow the chain and add the stowed chain on the end of\n\tthe current chain.\n\n\t* make.texinfo (Implicit: Search Algorithm): Fixed PREV reference.\n\n\t* make.c (main): Call construct_include_path right after decoding\n\tthe switches.\n\n\t* read.c (find_makefile): Use rename_file.\n\n\t* file.h: Declare rename_file.\n\n\t* file.c (rename_file): New function to rename a `struct file' and\n\tput it in the correct hash bucket.\n\n\t* read.c (find_makefile): New function to find and update a makefile.\n\t (read_all_makefilese): Use find_makefile.\n\t (read_makefile): Don't do updating.  Removed UPDATEIT arg.\n\n\t* remake.c (update_file_1): Took out setting the `updated' member to\n\t-1 rather than 1 sometimes.\n\n\t* make.c (main): Made it print version info before doing anything else.\n\n\t* remake.c (library_file_mtime, f_mtime): Removed use of last two\n\targuments to vpath_search.\n\n\t* rule.c (pattern_search): Removed use of last two arguments\n\tto vpath_search.\n\n\t* vpath.c (vpath_search, selective_vpath_search): Removed unused\n\tDIRPREFIX and DPLEN args.\n\n\t* read.c (read_makefile): Also turn off -n when updating makefiles.\n\nTue Sep 20 17:01:10 1988  Roland McGrath  (mcgrath at pepper.Berkeley.EDU)\n\n\t* Makefile: Put tags files in the tarfile.\n\n\t* read.c (read_makefile): Get the modtime of the makefile via a stat\n\tcall so that a later file_mtime call won't do VPATH search for it.\n\n\t* read.c (read_makefile): Don't turn off -t and -q if the makefile\n\twas a command-line target.\n\n\t* make.c (main): Enter command-line targets as files and set their\n\t`cmd_target' members.\n\n\t* file.h (struct file): Added `cmd_target' member.\n\n\t* read.c (read_makefile): Temporarily turn off -t and -q while\n\tupdating makefiles.\n\n\t* make.c (main): Don't use arg 0 from other_args (which is now\n\targv[0]; i.e., the program's name).\n\n\t* read.c (read_makefile): Only return nonzero if commands were\n\tactually run to remake the makefile.\n\n\t* remake.c (update_file_1): Set FILE->updated to -1 if no commands\n\twere actually run (because no update was done or -t was given).\n\n\t* make.c (decode_switches): Fixed bug wherein xrealloc was passed\n\tbad args if it tried to expand other_args->list.\n\n\t* read.c (read_all_makefiles): Made it not look at the `MAKE'\n\tvariable, just use argv[0].\n\nSun Sep 18 17:34:11 1988  Roland McGrath  (mcgrath at paris.Berkeley.EDU)\n\n\t* read.c (rerun_make): New function to re-exec make.\n\n\t* make.c (construct_makeflags, construct_argv): New functions to\n\tconstruct the `MAKEFLAGS' variable and to construct an arg list from\n\tparsed info.\n\n\t* read.c (read_makefile): New arg UPDATEIT, if nonzero, says to\n\tupdate the makefile as a target before reading it in.  When reading\n\tincluded makefiles, pass this as zero.  Now returns nonzero if the\n\tmakefile was updated, zero if not.\n\t(read_all_makefiles): Pass a nonzero UPDATEIT arg to read_makefile\n\tfor all default and -f makefiles and all makefiles from the\n\t`MAKEFILES' variable.  If any of the makefiles has changed, re-exec\n\tself to re-read them.\n\n\t* remake.c (update_file): Print a \"File `foo' up to date'\" message\n\tunder -p.\n\n\t* commands.c (execute_file_commands): Allocate one byte for each of\n\t$^ and $< rather than zero if they are to be empty.\n\nFri Sep 16 13:59:59 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Version 3.06.\n\n\t* make.c (command_switches): Fixed entry for `-o' switch.\n\n\t* make.texinfo: Renamed -c switch to -C.\n\n\t* make.c: Renamed -c switch to -C.\n\n\t* Miscellaneous de-linting.\n\n\t* read.c (record_files): Made it not free the storage for the name\n\tif it started with `./' and was therefore not quite the same as in\n\tthe `struct file'.\n\n\t* read.c (record_files): If commands were specified twice, the error\n\tmessage specifies in what files and at what line numbers.\n\n\t* make.c (main): If any of the signals we usually fatal on were\n\tignored by the parent (probably a shell), ignore them.\n\n\t* make.c (main): Print version info for -v, -p, or -d.\n\t(print_data_base): Don't print version info.  It will be done in main.\n\n\t* variable.c: Increased number of hash buckets to 257.\n\n\t* file.c: Increased number of hash buckets to 1007.\n\n\t* rule.c (count_implicit_rule_limits): Moved comptation of\n\t`maxsuffix' to convert_to_pattern, since that function uses\n\t`maxsuffix', and must be called before count_implicit_rule_limits.\n\n\t* rule.c (pattern_search): If an existent (non-intermediate)\n\tdependency was found via a terminal rule, set its\n\t`tried_implicit' flag, so it will never have implicit rule search done.\n\n\t* glob.c: Bug fix to avoid alloca(0).\n\n\t* arscan.c: USG and Sun386i fixes.\n\nThu Sep 15 19:40:26 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* make.texinfo: Fixed some typos and spelling errors.\n\nWed Sep  7 14:20:39 1988  Roland McGrath  (mcgrath at helen.Berkeley.EDU)\n\n\t* make.c (decode_switches): Fixed bug wherein a bad option would\n\tgive a useless error message and loop forever.\n\nTue Sep  6 14:36:02 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.texinfo: Documented `shell' function.\n\n\t* variable.c (expand_function): New function `shell', does\n\tbackquote-style command expansion of its arg.\n\n\t* commands.c (execute_command_line): Second arg OUTBUF, if not nil,\n\tgets filled in with a malloc'd buffer containing the piped stdout of\n\tthe command.\n\t(execute_file_commands): Use above (pass nil).\n\nMon Sep  5 17:03:49 1988  Roland McGrath  (mcgrath at hecuba.Berkeley.EDU)\n\n\t* Makefile: Added copyright notice.\n\tAdded a comment about defining `NO_MINUS_C_MINUS_O' if necessary.\n\n\t* Version 3.05.\n\n\t* rule.c (default_suffix_rules): Don't pass `-o' switches with `-c'\n\tswitches if `NO_MINUS_C_MINUS_O' is #define'd.\n\n\t* make.texinfo: Documented `GNUmakefile'.\n\n\t* read.c (read_all_makefiles): Made it try default makefile\n\t`GNUmakefile' before others.\n\n\t* make.texinfo: Added new-style Texinfo header thingies.\n\nSat Sep  3 18:09:39 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* Version 3.04.\n\n\t* make.texinfo (Chained Rules): Added a @cindex about using\n\t.PRECIOUS to preserve intermediate files.\n\n\t* remake.c (update_file_1): Made it not just return before executing\n\tcommands under -p.\n\n\t* rule.c (default_pattern_rules, default_variables): Made it use\n\t`$(AR)' for `ar r' (to put files in archives).\n\n\t* vpath.c (build_vpath_lists): Made it recursively expand the\n\t`VPATH' variable (by using variable_expand instead of lookup_variable).\n\n\t* read.c (conditional_line): Made it not swallow whitespace after\n\tthe comma in an `ifeq' using the `(a,b)' syntax.\n\n\t* rule.c (count_implicit_rule_limits): Made it not crash if a\n\tpattern rule dep begins with `/'.\n\nSun Aug 28 15:51:12 1988  Roland McGrath  (mcgrath at homer.Berkeley.EDU)\n\n\t* make.texinfo: Clarified that the arg to the `origin' function is a\n\tvariable *name*, not a reference.\n\n\t* make.texinfo: Clarified that both -Idir and -I dir are allowed.\n\nSat Aug 27 13:49:28 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* remake.c (remake_file): Made touching phonies work right.\n\nWed Aug 24 20:40:48 1988  Roland McGrath  (mcgrath at nutmeg.Berkeley.EDU)\n\n\t* make.texinfo: Removed reference to `RANLIB' variable.\n\n\t* Version 3.03.\n\n\t* variables.c (expand_function): Added `origin' function.\n\t* make.texinfo: Documented same.\n\n\t* read.c (record_files): Made double-colon entries work.\n\nSat Aug 20 21:09:39 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (collapse_continuations): Bug fix from RMS.\n\n\t* rule.c (install_default_pattern_rules): Made it set the\n\t`in_use' flag of the created rules to zero, rather than letting\n\tit be random garbage.\n\n\t* rule.c (pattern_search): Fixed putting `also make' targets into\n\tfile strucutres.\n\n\t* read.c (record_files): Fixed bug which made double-colon entries\n\tmake it read off into space.\n\n\t* make.c (decode_switches): Made it understand `ignored' switches\n\trather than dumping core.\n\nSun Aug 14 16:49:00 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* read.c (read_makefile): Made `include' filenames be\n\tvariable-expanded.\n\n\t* read.c (read_makefile): Fixed an error message.\n\n\t* read.c (read_makefile): Made it accept ^L's as whitespace.\n\t* make.c (next_token, end_of_token): Ditto.\n\n\t* vpath.c (vpath_search): Fixed it so that the general VPATH (from\n\tthe variable) is always checked, even if a selective VPATH (from a\n\tdirective) matched the filename.\n\nSat Aug 13 14:20:46 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (decode_switches, main): Made the command switches be\n\tprocessed from a table of switches, variables, and types.  No\n\tfunctions are passed argc and argv any more.  They are passed arrays\n\tof strings they need to process.\n\t* read.c (read_all_makefiles): Made it take an array rather than\n\targc and argv.\n\t(construct_include_path): Ditto.\n\n\t* make.c (collapse_continuations): Made it work right (I hope).\n\n\t* make.texinfo: Minor editorial changes.\n\n\t* read.c (read_makefile): Minor speed improvement by freeing and\n\tthen mallocing something rather than reallocing it to avoid the\n\tunnecessary bcopy.\n\nThu Aug 11 00:10:43 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.texinfo: Fixed some unquoted @'s.\n\n\t* make.texinfo: Documented multiple-target pattern rules.\n\tMiscellaneous minor editorial changes and corrections.\n\n\t* make.texinfo (Implicit: Catalogue of Rules): Removed the list of\n\tvariables.  That's what the next section is for.\n\t(Implicit: Implicit Variables): Made it agree with reality.\n\nWed Aug 10 00:55:39 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* variable.c (print_variable_data_base): Fixed bug which made -p\n\tdump core.  (This was a really idiotic bug.)\n\n\t* rule.c (pattern_search): Fixed a bug which made it make the\n\t`also_make' member of the file in question nil if the first of\n\tthe successful rule's targets was the matching one.\n\tMade it use only as much storage as necessary in the `also_make'\n\tmember.\n\t(create_pattern): Made it use only as much storage as necessary in\n\tthe `lens' and `suffixes' members of the created rule.\n\n\t* remake.c (library_file_mtime): Made it `static'.\n\n\t* file.c: Added a declaration for `errno', which is declared in some\n\t<errno.h>'s, but not all.\n\n\t* file.h (struct file): Added `also_make' member for multiple-target\n\timplicit rules.\n\t* rule.c (pattern_search): Made it put the names of files updated by\n\tthe given file's commands in its `also_make' member.\n\t* remake.c (update_file_1): Made it mark the files in a file's\n\t`also_make' member as updated when the file is updated.\n\n\t* variable.c (try_variable_definition): Fixed a bug which made it\n\tdefine a variable with the name of the whole definition when there\n\twas no space before the = or :=.\n\n\t* make.texinfo (Features): Made the changes which were made in RCS\n\trevision 2.7 but somehow lost since then.  Added -W.\n\nTue Aug  9 10:04:50 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* variable.h: Added `o_default' to `enum variable_origin'.\n\t* variable.c (print_variable_data_base): Made it print the origins of\n\tthe variables.\n\t* rule.c (install_default_pattern_rules): Made it define the default\n\tvariables with origin `o_default'.\n\n\t* make.texinfo: Documented -W.\n\n\t* make.c (decode_switches, main): Added the -W flag to give files a\n\ttime-stamp of now, for a `what if' effect when used with -n.\n\n\t* commands.c (print_commands): Made it say `(built-in)' for commands\n\tthat are built into the default ruleset.\n\n\t* read.c (record_file): Made .SUFFIXES get its deps frontwards (again).\n\t* rule.c (set_default_suffixes, convert_to_pattern): Made it read\n\t.SUFFIXES's deps frontwards, so the converted rules will not be in\n\treverse order.\n\n\t* rule.c (new_pattern_rule): Fixed a bug wherein it would keep\n\tsearching after it had removed a matching rule and ended up diddling\n\twith freed storage.\n\n\t* rule.c (freerule): Made it take the given rule off the chain.\n\t(new_pattern_rule, count_implicit_rule_limits): Use freerule to\n\tremove rules from the chain.\n\n\t* vpath.c (construct_vpath_list): Made it return after cleaning out\n\tall previous searchpaths when given a nil DIRPATH arg, so it won't\n\tgo into the construction code and dump core dereferencing a nil\n\tpointer.\n\n\t* variable.c (patsubst_expand): Fixed a bug which made it not match\n\tcorrectly and sometimes dump core.\n\nMon Aug  8 16:35:48 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* rule.c (default_suffix_rules): Made the .texinfo.dvi rule remove\n\tthe files used in the comparison to determine whether or not a\n\tsecond TeX run is necessary.\n\n\t* make.texinfo: Fixed some overfull TeX hboxes.\n\n\t* make.texinfo (Implicit: Catalogue of Rules): Fixed a Texinfo error.\n\n\t* rule.c (create_pattern_rule): Fixed bug wherein index was not\n\tbeing passed its second arg.\n\n\t* read.c (getline): Merged back into readline.\n\n\t* rule.c (default_suffixes, default_suffix_rules,\n\tdefault_variables): Added .texinfo.info rule.\n\t* make.texinfo (Implicit: Catalogue of Rules): Documented\n\t.texinfo.dvi and .texinfo.info rules.\n\n\t* make.texinfo (Top): Changed `last updated' date to be correct (for\n\tthe last time it was updated, not today).  Changed `for version\n\t3.00' since it's not going to be called that.\n\nSat Aug  6 19:51:10 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* commands.c (print_commands): Added this function to print the\n\tcontents of a `struct commands' for -p.\n\t* rule.c (print_rule_data_base): Use above.\n\t* file.c (print_file_data_base): Ditto.\n\n\t* rule.c (count_implicit_rule_limits, new_pattern_rule,\n\tinstall_pattern_rule, print_rule_data_base): Made it understand the\n\tchanged `struct rule' and act accordingly.\n\t(freerule): Added this function to free all the storage used by a rule.\n\n\t* rule.c (pattern_search): Made it grok multiple targets of pattern\n\trules.  The matching is done properly, but at present, only the\n\tmatching pattern's target is used to give deps and commands.\n\nFri Aug  5 18:00:29 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* rule.c (struct rule): Changed name, namelen, and patsuffix members\n\tto targets, lens, and suffixes, which are arrays, for multiple targets.\n\t(create_pattern_rule): Now takes first arg TARGETS, a nil-terminated\n\tarray of targets, rather than a single target and patsuffix pointer.\n\n\t* read.c (record_files): If it finds an implicit pattern rule, it\n\tcollects all the targets into an array and passes the whole thing to\n\tcreate_pattern_rule.  If there are non-pattern targets, it is a\n\tfatal error.\n\nTue Aug  2 15:06:38 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (readline): Split backslash-newline checking from reading\n\tand buffer-expanding.\n\t(getline): Created to do the reading and buffer-expanding formerly\n\tdone in readline.\n\n\t* rule.c (pattern_search): Made it reject nonterminal match-anything\n\trules when a specific rule has matched, rather than rejecting\n\tterminal match-anything rules in this case.\n\n\t* rule.c (convert_to_pattern): Fixed a bug caused when the change to\n\tmake it only recognize two-suffix rules whose target suffixes\n\tprecede their dependency suffixes which made it work in the opposite\n\tdirection (even worse than it started out).\n\n\t* rule.c (pattern_search): Made it reject nonterminal match-anything\n\trules as intermediate targets when searching for both real and\n\tintermediate dependencies, rather than only when searching for\n\tintermediate ones.\n\nSun Jul 31 00:33:56 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* rule.c (convert_to_pattern): Made it only recognize two-suffix\n\trules whose target suffix comes before the dependency suffix in the\n\t.SUFFIXES list.\n\n\t* variable.c (define_automatic_variables): Made all automatic\n\tvariables be defined with origin `o_automatic'.\n\n\t* variable.h: Added `o_automatic' to `enum variable_origin'\n\n\t* file.c (remove_intermediates): Made it not print an error message\n\tif the error was that the file does not exist.\n\n\t* rule.c: Removed `recursive' member from `struct rule'.\n\n\t* remake.c (library_file_mtime): Made it not use the directory hash\n\tfunctions, as reading in and hashing /usr/lib and /lib is slow and\n\tmost likely unnecessary.\n\n\t* remake.c (remake_file): Changed message from ``No specification\n\tfor making'' to ``No way to make'' so it will be short enough that\n\tmost filenames will fit on a line.\n\tMade it look at the `recursive' member of the `struct commands',\n\trather than of the `struct file' (which no longer has one).\n\n\t* commands.c (execute_file_commands): Made it look at the\n\t`recursive' member of the `struct commands', rather than of the\n\t`struct file' (which no longer has one).\n\n\t* file.h: Removed `recursive' member from `struct file'.\n\n\t* commands.h: Added `recursive' member to `struct commands'.\n\n\t* dep.h: Removed unused `quotedparen' member from `struct nameseq'\n\tand `struct dep'.\n\n\t* read.c (dequote): Removed this function.\n\t(multi_glob): Removed reference to `quotedparen' member of\n\ta `struct nameseq' and calls to dequote.\n\n\t* read.c (record_files): Made it set the stem for $* for all static\n\tpattern rules, not just those with commands given at that time.\n\tRemoved check for recursive commands.\n\tMade it check for pairs of .SUFFIXES dependencies to reject as\n\tdefault goals as well as single ones (that don't start with dots).\n\t(read_makefile): Added checks for recursive commands to set\n\tthe `recursive' flag in the `struct commands'.\n\nSat Jul 30 15:47:23 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (find_next_token): Made the LENGTHPTR arg optionally nil.\n\n\t* make.c: Removed `files_made' variable which is defined static in\n\tremake.c and used only there.\n\t(main): Cleaned up somewhat.\n\t(decode_switches): Cleaned up a bit.  Made an unknown option be a\n\tnon-fatal error.\n\t(decode_env_switches): Made LEN arg unsigned.  Cleaned up.\n\t(print_version): Made it say ``see the source'' rather than ``see\n\tthe source file'', since there is more than one.\n\n\t* file.h: Made `num_intermediates' declared unsigned.\n\n\t* file.c: Made `num_intermediates' variable unsigned.\n\t(remove_intermediates): Removed unused FORMAT arg.\n\t(enter_file): Made it handle double-colon files properly, adding the\n\tnew entry as the old entry's prev pointer.\n\n\t* dir.c: Re-indented the `struct dir' definition to be right.\n\t(dir_load): Cleaned up slightly.\n\t(file_exists_p): Removed comment saying we could use `access', since\n\tthat is a bad idea (except for setuid programs).  Cleaned up slightly.\n\n\t* commands.c: Changed some comments slightly.\n\t(execute_file_commands): Cleaned up a bit.  Changed some comments,\n\tadded others.  Moved freeing of storage for $^ and $? to the same\n\tplace as for the other automatic variables.\n\t(execute_command_line): Made `#' trigger a shell.\n\tAdded some comments.  Cleaned up a bit.  Put all the special chars\n\tthat trigger shells into an array easily changeable at the top.\n\n\t* ar.c: Added comments explaining each function.\n\t(ar_scan_1): Merged into ar_member_date.\n\t(ar_member_date): Changed call to ar_scan_1 to the body of that\n\tfunction.\n\t(ar_member_date_1): Simplified to a ?: expression rather than an\n\tif-else statement.\n\t(ar_member_touch): Changed error handling around a bit.\n\tNone of these errors are fatal now.\n\n\t* variable.c (subst_expand): Added a new arg BY_WORD, to do substs\n\tonly on full words.\n\t(patsubst_expand): Fixed bug which made calls whose patterns\n\tcontained no `%' to not work correctly, by using above.\n\t(variable_expand): Pass extra arg to `subst_expand'.\n\n\t* variable.c (expand_function): Fixed bug which made `foreach' calls\n\twith one-word lists run off into never-never land.\n\nFri Jul 29 20:12:36 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* variable.c (expand_function): Made a very minor speed improvement\n\tby avoiding an unnecessary strlen call.\n\nWed Jul 27 16:01:47 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* rule.c (default_suffixes): Rearranged the list somewhat; added\n\t`.el' and `.elc' to speed things up (especially when building\n\tEmacs), for the same reason `.h' is there.\n\n\t* read.c (record_files): Changed `lineno' from `long' to\n\t`unsigned int'.\n\nSun Jul 24 02:15:30 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* variable.c (expand_function): Eliminated use of `wstok'\n\tbecause it is non-reentrant and unreliable.\n\tFixed a minor bug which would cause something not to be freed.\n\t* make.c (wstok): Removed `wstok' because it is no longer used.\n\n\t* variable.c (expand_function): Made `foreach' function put\n\tspaces between output texts like it's supposed to.\n\nSat Jul 23 17:32:55 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* rule.c (default_suffixes, default_suffix_rules): Added rule\n\tto make %.dvi from %.texinfo.\n\n\t* dir.c (print_dir_data_base): Made it say a bit more.\n\nFri Jul 22 23:13:16 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* make.c (print_data_base): Split this function up into one\n\tfor each thing.\n\t* variable.c (print_variable_data_base): One of the above.\n\t* rule.c (print_rule_data_base): Ditto.\n\t* file.c (print_file_data_base): Ditto.\n\t* dir.c (print_dir_data_base): Ditto.\n\n\t* rule.c (install_pattern_rule): Fixed a bug which caused the\n\tterminal and recursive flags to always be zero for rules\n\tentered by this function.\n\n\t* make.texinfo (Rules: Double-colon): Added a paragraph\n\texplaining the purpose of double-colon rules.\n\n\t* make.texinfo (Implicit: Catalogue of Rules): Updated to\n\treflect new C++, TeX, Web, and Texinfo rules.  Other slight\n\teditorial changes.\n\n\t* commands.c (execute_file_commands): Fixed a bug wherein\n\trandom memory could get written for files with no deps.\n\nWed Jul 20 19:30:31 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* read.c (readline): Fix bug wherein it would not recognize a\n\tbackslash-newline if the buffer filled up and was enlarged\n\tright before reading the newline.\n\nTue Jul 19 19:55:02 1988  Roland McGrath  (mcgrath at chilli.Berkeley.EDU)\n\n\t* read.c: Added default suffix rules for .cc (using $(C++),\n\twhich defaults to `g++', and $(C++FLAGS)), .tex, .dvi, .web\n\tand .cweb (using $(TEX), $(WEAVE), $(TANGLE), $(CWEAVE) and\n\t$(CTANGLE)).\n\nSat Jul 16 21:24:28 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Made error formats use %u rather than %ld for line numbers,\n\twhich are now unsigned int's rather than long's.\n\n\t* read.c (conditional_line): Fixed some bugs caused by use of\n\tunsigned int rather than int in one place.\n\n\t* read.c (conditional_line): Put the info about active\n\tconditionals in a struct.\n\t(read_makefile): Make a new struct of info about conditionals\n\tfor included makefiles and restore the old one after the\n\tincluded makefile has been read.\n\n\t* read.c (read_makefile): Don't try to read a makefile with\n\tname \"\" after giving an error message because an `include'\n\tdirective gave no filename.\n\n\t* read.c (read_makefile): Give an error message for\n\tnon-whitespace text after the filename in an `include' directive.\n\n\t* make.c (error): Take five args, like `fatal'.  It managed to\n\tlose with only two.  Is there a better way to do this without vfprintf?\n\n\t* read.c (read_makefile): Commands consisting of only\n\twhitespace are not the same as no commands.  I thought I'd\n\tfixed this bug months ago; it seems to have come back.\n\n\t* make.c (collapse_continuations): All whitespace around a\n\tbackslash-newline combination is turned into a single space.\n\n\t* Added COPYING file and copyright notices to all files.\n\n\t* make.texinfo (Running: Goals): Fix a typo.\n\n\t* read.c (do_define): Take an arg for the origin of the\n\tvariable being defined.\n\t(read_makefile): Grok `override define'.\n\n\t* make.texinfo (Variables: Override Directive, Defining):\n\tDocument the `override define' combination directive.\n\n\t* ar.c (ar_member_date): Make a 0 return from `ar_scan' return\n\t(time_t) -1 (nonexistent file), rather than (time_t) 0, which,\n\twhen put in the `struct file', makes `file_mtime' try to get\n\tthe mtime over and over again.\n\n\t* variable.c (pattern_matches): Fix a bug that made patterns\n\tnot beginning with `%' never match.\n\nFri Jul 15 21:01:44 1988  Roland McGrath  (mcgrath at tully.Berkeley.EDU)\n\n\t* Took Make out of RCS.\n\n\t* Split the monolithic `make.c' into several smaller files.\n\n\f\n\nCopyright (C) 1988-2009 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "ChangeLog.2",
    "content": "2000-06-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): Increment commands_started before the\n\tspecial check for \":\" (empty command) to avoid spurious \"is up to\n\tdate\" messages.  Also move the test for question_flag after we\n\texpand arguments, and only stop if the expansion provided an\n\tactual command to run, not just whitespace.  This fixes PR/1780.\n\n2000-06-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): If we find a semicolon in the target\n\tdefinition, remember where it was.  If the line turns out to be a\n\ttarget-specific variable, add back the semicolon and everything\n\tafter it.  Fixes PR/1709.\n\n2000-06-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h-vms.template: #define uintmax_t for this system.\n\t* config.ami.template: Ditto.\n\t* config.h.W32.template: Ditto.\n\n\t* configure.in: We don't use select(2) anymore, so don't bother\n\tchecking for it.\n\t* acconfig.h: Ditto.\n\t* acinclude.m4: Ditto.\n\n\t* file.c (all_secondary): New static global; if 1 it means\n\t.SECONDARY with no prerequisites was seen in the makefile.\n\t(snap_deps): Set it appropriately.\n\t(remove_intermediates): Check it.\n\t(num_intermediates): Remove this global, it's not used anywhere.\n\t(considered): Move this to remake.c and make it static.\n\n\t* NEWS: Document the change to .SECONDARY.\n\t* make.texinfo (Special Targets): Document the change to .SECONDARY.\n\n\t* implicit.c (pattern_search): Remove the increment of\n\tnum_intermediates; it's not used.\n\t* filedef.h: Remove num_intermediates and considered.\n\n\t* function.c (handle_function): If the last argument was empty, we\n\twere pretending it didn't exist rather than providing an empty\n\tvalue.  Keep looking until we're past the end, not just at the end.\n\n\t* implicit.c (pattern_search): Multi-target implicit rules weren't\n\texpanding the \"also made\" targets correctly if the pattern didn't\n\tcontain a slash but the target did; in that case the directory\n\tpart wasn't being added back to the stem on the \"also made\"\n\ttargets.  Reported by Seth M LaForge <sethml@newtonlabs.com>, with\n\ta patch.\n\n2000-06-17  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS.template (DESTDIR, bindir, datadir, libdir)\n\t(infodir, mandir, includedir): Support installation under a\n\tnon-default DESTDIR.\n\n\t* remake.c (f_mtime): Fix the spelling of __MSDOS__.\n\n\t* configh.DOS.template (HAVE_FDOPEN, HAVE_MKSTEMP): Define.\n\n2000-06-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* acinclude.m4 (pds_WITH_GETTEXT): rewrite fp_WITH_GETTEXT and\n\trename it to avoid confusion.  This version is very specific: it\n\twon't accept any gettext that isn't GNU.  If the user doesn't\n\texplicitly ask for the included gettext, we look to see if the\n\tsystem gettext is GNU (testing both the actual libintl library,\n\tand the libintl.h header file).  Only if the system gettext is\n\treally GNU gettext will we allow it to be used.\n\t(pds_CHECK_SYSTEM_GETTEXT): A helper function.\n\n2000-06-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* gettext.h: If we have libintl.h, use that instead of any of the\n\tcontents of gettext.h.  We won't check for libintl.h unless we're\n\tusing the system gettext.\n\n\t* function.c (func_word): Clarify error message.\n\n2000-06-10  Paul Eggert  <eggert@twinsun.com>\n\n\tSupport nanosecond resolution on hosts with 64-bit time_t and\n\tuintmax_t (e.g. 64-bit Sparc Solaris), by splitting\n\tFILE_TIMESTAMP into a 30-bit part for nanoseconds, with the\n\trest for seconds, if FILE_TIMESTAMP is at least 64 bits wide.\n\n\t* make.h: Always define FILE_TIMESTAMP to be uintmax_t, for\n\tsimplicity.\n\n\t* filedef.h (FILE_TIMESTAMP_HI_RES, FILE_TIMESTAMP_LO_BITS)\n\t(UNKNOWN_MTIME, NONEXISTENT_MTIME, OLD_MTIME)\n\t(ORDINARY_MTIME_MIN, ORDINARY_MTIME_MAX): New macros.\n\t(FILE_TIMESTAMP_STAT_MODTIME): Now takes fname arg.  All uses changed.\n\t(FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD)\n\t(FILE_TIMESTAMP_FROM_S_AND_NS): Remove.\n\t(FILE_TIMESTAMP_S, FILE_TIMESTAMP_NS): Use shifts instead of\n\tmultiplication and division.  Offset the timestamps by\n\tORDINARY_MTIME_MIN.\n\t(file_timestamp_cons): New decl.\n\t(NEW_MTIME): Now just the maximal timestamp value, as we no longer use\n\t-1 to refer to nonexistent files.\n\n\t* file.c (snap_deps, print_file): Use NONEXISTENT_MTIME,\n\tUNKNOWN_MTIME, and OLD_MTIME instead of magic constants.\n\t* filedef.h (file_mtime_1): Likewise.\n\t* main.c (main): Likewise.\n\t* remake.c (update_file_1, notice_finished_file, check_dep)\n\t(f_mtime, name_mtime, library_search): Likewise.\n\t* vpath.c (selective_vpath_search): Likewise.\n\n\t* remake.c (f_mtime): Do not assume that (time_t) -1 equals\n\tNONEXISTENT_MTIME.  When futzing with time stamps, adjust by\n\tmultiples of 2**30, not 10**9.  Do not calculate timestamp\n\tadjustments on DOS unless they are needed.\n\n\t* commands.c (delete_target): Do not assume that\n\tFILE_TIMESTAMP_S yields -1 for a nonexistent file, as that is\n\tno longer true with the new representation.\n\n\t* file.c (file_timestamp_cons): New function, replacing\n\tFILE_TIMESTAMP_FROM_S_AND_NS.  All uses changed.\n\t(file_timestamp_now): Use FILE_TIMESTAMP_HI_RES instead of 1 <\n\tFILE_TIMESTAMPS_PER_S to determine whether we're using hi-res\n\ttimestamps.\n\t(print_file): Print OLD_MTIME values as \"very old\" instead of\n\tas a timestamp.\n\n2000-05-31  Paul Eggert  <eggert@twinsun.com>\n\n\t* remake.c (name_mtime): Check for stat failures.  Retry if EINTR.\n\n2000-05-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (decode_switches): The \"positive_int\" switch uses atoi()\n\twhich succeeds for any input, and doesn't notice if extra,\n\tnon-digit text is after the number.  This causes make to mis-parse\n\tcommand lines like \"make -j 5foo\" as \"make -j5\" (ignoring \"foo\"\n\tcompletely) instead of \"make -j0 5foo\" (where \"5foo\" is a\n\ttarget).  Fix this by checking the value by hand.  We could use\n\tstrtol() if we were sure of having it; this is the only\n\tquestionable use of atoi() I found so we'll just stick with that.\n\tFixes PR/1716.\n\n\t* i18n/ja.po, i18n/nl.po, i18n/pt_BR.po: New translation files.\n\t* configure.in (ALL_LINGUAS): Added pt_BR.\n\n2000-05-22  Paul Eggert  <eggert@twinsun.com>\n\n\t* remake.c (f_mtime): Fix bug when handling future odd\n\ttimestamps in the WINDOWS32 case.  Do not bother initializing\n\tstatic var to zero.  Simplify code that works around WINDOWS32\n\tand __MSDOS__ time skew brain damage.\n\n2000-05-22  Paul Eggert  <eggert@twinsun.com>\n\n\t* job.c: Don't include time.h, as make.h already does this.\n\n2000-05-22  Paul Eggert  <eggert@twinsun.com>\n\n\t* configure.in (AC_CHECK_HEADERS): Add sys/time.h.\n\t(AC_HEADER_TIME): Add.\n\t(clock_gettime): Prefer -lrt to -lposix4, for Solaris 7.\n\t(gettimeofday): Add check for standard version of gettimeofday.\n\tThis merges changes written by Paul D. Smith.\n\n\t* file.c (file_timestamp_now):  Use gettimeofday if available\n\tand if clock_gettime does not work.  Don't bother with\n\thigh-resolution clocks if file timestamps have only one-second\n\tresolution.\n\n\t* make.h <sys/time.h>: Include, conditionally on the usual\n\tTIME_WITH_SYS_TIME and HAVE_SYS_TIME_H macros.  This is needed\n\tfor gettimeofday.\n\n2000-05-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): We weren't keeping makefile names around\n\tunless there was a rule defined in them; but now we need to keep\n\tthem for variables as well.  Forget trying to be fancy: just keep\n\tevery makefile name we successfully open.\n\n\t* remote-cstms.c (start_remote_job_p): Change DB_EXTRA (?) to DB_JOBS.\n\n2000-05-17  Paul Eggert  <eggert@twinsun.com>\n\n\t* commands.c (chop_commands): Ensure ctype macro args are nonnegative.\n\t* expand.c (variable_expand_string): Likewise.\n\t* function.c (subst_expand, lookup_function, msdos_openpipe):\n\tLikewise.\n\t* job.c (vms_redirect, start_job_command, new_job, child_execute_job,\n\tconstruct_command_argv_internal, construct_command_argv): Likewise.\n\t* main.c (decode_env_switches, quote_for_env): Likewise.\n\t* misc.c (collapse_continuations, end_of_token, end_of_token_w32,\n\tnext_token): Likewise.\n\t* read.c (read_makefile, do_define, conditional_line,\n\tfind_char_unquote,get_next_mword): Likewise.\n\t* variable.c (try_variable_definition): Likewise.\n\t* vpath.c (construct_vpath_list): Likewise.\n\t* w32/pathstuff.c (convert_vpath_to_windows32): Likewise.\n\n2000-05-10  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* main.c (main) [__MSDOS__]: Add SIGFPE to signals we block when\n\trunning child programs, to prevent Make from dying on Windows 9X\n\twhen the child triggers an FP exception.\n\n2000-05-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (find_directory) [WINDOWS32]: If we strip a trailing \"\\\"\n\tfrom the directory name, remember to add it back.  The argument\n\tmight really be inside a longer string (e.g. %Path%) and if you\n\tdon't restore the \"\\\" it'll be truncated permanently.  Fixes PR/1722.\n\tReported by <steven@surfcast.com>\n\n2000-05-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal) [WINDOWS32]: Added \"rd\"\n\tand \"rmdir\" to the list of command.com commands.\n\tReported by Elod Horvath <Elod_Horvath@lnotes5.bankofny.com>\n\n2000-04-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/ja.po: New translation file from the Japanese language team.\n\n2000-04-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): If ar_member_date() returns -1 (the member\n\tdoesn't exist), then return (FILE_TIMESTAMP)-1 rather than\n\treturning the timestamp calculated from the value -1.  Fixes PR/1696.\n\tReported by Gilles Bourhis <Gilles.Bourhis@univ-rennes1.fr>.\n\n2000-04-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h.W32.template: Add LOCALEDIR macro resolving to \"\".\n\t* w32/subproc/sub_proc.c (process_begin): Remove reference to\n\tdebug_flag; change it to a DB() call.  Fixes PR/1700.\n\tReported by Jim Smith <jwksmith@attglobal.net>\n\n2000-04-17  Bruno Haible  <haible@clisp.cons.org>\n\n\t* arscan.c [BeOS]: Add replacement for nonexistent <ar.h> from GNU\n\tbinutils.\n\n2000-04-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (expand_builtin_function): If no arguments were\n\tprovided, just quit early rather than changing each function to\n\ttest for this.\n\t(function_table[]): Change the min # of arguments to 0 for all\n\tthose functions for which it makes sense (currently everything\n\tthat used to take a minimum of 1 argument, except $(call ...)).\n\tFixes PR/1689.\n\n2000-04-09  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* README.DOS: Add instructions to install a binary distro.\n\tMention latest versions of Windows.\n\n2000-04-07  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* main.c (main): Rename TMP_TEMPLATE into DEFAULT_TMPDIR, and use\n\tit for the directory of the temporary file.  If P_tmpdir is\n\tdefined, use it in preference to \"/tmp/\".  Try $TMPDIR, $TEMP, and\n\t$TMP in the environment before defaulting to DEFAULT_TMPDIR.\n\t(print_version): Add year 2000 to the Copyright line.\n\n2000-04-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.79 released.\n\n\t* make.texinfo: Update documentation with new features for 3.79.\n\n\t* function.c (func_wordlist): Don't re-order arguments to\n\twordlist.\n\n2000-04-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): Archive member timestamps are stored as\n\ttime_t, without nanoseconds.  But, f_mtime() wants to return\n\tnanosecond info on those systems that support it.  So, convert the\n\treturn value of ar_member_date() into a FILE_TIMESTAMP, using 0 as\n\tthe nanoseconds.\n\n2000-03-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.78.92 released.\n\n\t* build.template: Updates for gettext support; some bugs fixed.\n\n2000-03-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.guess, config.sub: Updated from config CVS archive at\n\t:pserver:anoncvs@subversions.gnu.org:/home/cvs as of today.\n\n\t* read.c (record_files): Check if expanding a static pattern\n\trule's prerequisite pattern leaves an empty string as the\n\tprerequisite, and issue an error if so.  Fixes PR/1670.\n\t(read_makefile): Store the starting linenumber for a rule in\n\tTGTS_STARTED.\n\t(record_waiting_files): Use the TGTS_STARTED value for the file\n\tlocation passed to record_file() instead of the current\n\tlinenumber, so error messages list the line where the target was\n\tdefined instead of the line after the end of the rule definition.\n\n\t* remake.c (start_updating, finish_updating, is_updating): Fix\n\tPR/1671; circular dependencies in double-colon rules are not\n\tdiagnosed.  These macros set the updating flag in the root\n\tdouble-colon file instead of the current one, if it's part of a\n\tdouble-colon list.  This solution provided by Tim Magill\n\t<magill@gate.net>; I just changed the macro names :).\n\t(update_file_1): Call them.\n\t(check_dep): Call them.\n\n\tThe change to not automatically evaluate the $(call ...)\n\tfunction's arguments breaks recursive use of call.  Although using\n\t$(if ...) and $(foreach ...) in $(call ...) macros is important,\n\tthe error conditions generated are simply to obscure for me to\n\tfeel comfortable with.  If a method is devised to get both\n\tworking, we'll revisit.  For now, remove this change.\n\n\t* function.c (function_table): Turn on the expand bit for func_call.\n\t(func_call): Don't expand arguments for builtin functions; that\n\twill have already been done.\n\n2000-03-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (remove_intermediates): Never remove targets explicitly\n\trequested on the command-line by checking the cmd_target flag.\n\tFixed PR/1669.\n\n2000-03-23  Paul Eggert  <eggert@twinsun.com>\n\n\t* filedef.h (FILE_TIMESTAMP_STAT_MODTIME): Use st_mtime instead of\n\tst_mtim.tv_sec; the latter doesn't work on Unixware.\n\n2000-03-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (file_hash_enter): If we're trying to change a file into\n\titself, just return.  We used to assert this wasn't true, but\n\tsomeone came up with a weird case involving archives.  After\n\tplaying with it for a while I decided it was OK to ignore it.\n\n\t* default.c: Define COFLAGS to empty to avoid spurious warnings.\n\n\t* filedef.h: Change #if ST_MTIM_NSEC to #ifdef; this is a macro\n\tcontaining the name of the nsec field, not true/false.\n\t* make.h: Ditto.\n\tReported by Marco Franzen <Marco.Franzen@Thyron.com>.\n\n2000-03-08  Tim Magill  <magill@gate.net>\n\n\t* remake.c (update_file): Return the exit status of the pruned\n\tfile when pruning, not just 0.  Fixes PR/1634.\n\n2000-02-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Close a minor potential security hole; if you're\n\treading makefiles from stdin (who does that?) you could run into a\n\trace condition with the temp file using mktemp() or tmpnam().  Add\n\ta check for mkstemp() and fdopen().\n\t* main.c (open_tmpfile): New function to open a temporary file.\n\tIf we have mkstemp() (and fdopen()), use that.  If not use\n\tmktemp() or tmpnam().  If we have fdopen(), use open() to open the\n\tfile O_CREAT|O_EXCL.  If not, fall back to normal fopen() (insecure).\n\t(main): Call it.\n\t* job.c (child_execute_job) [VMS]: Call it.\n\n\t* variable.c (lookup_variable): If we find a variable which is\n\tbeing expanded, then note it but keep looking through the rest of\n\tthe set list to see if we can find one that isn't.  If we do,\n\treturn that.  If we don't, return the original.  Fix for PR/1610.\n\n\tWhile implementing this I realized that it also solves PR/1380 in\n\ta much more elegant way.  I don't know what I was smoking before.\n\tSo, remove the hackage surrounding the original fix for that (see\n\tbelow).  Change this function back to lookup_variable and remove\n\tthe extra setlist argument.\n\t* variable.h (recursively_expand_setlist): Remove the macro,\n\trename the prototype, and remove the extra setlist argument.\n\t(lookup_variable): Ditto.\n\t* expand.c (recursively_expand): Rename and remove the extra\n\tsetlist argument.\n\t(reference_variable): Use lookup_variable() again.\n\t(allocated_variable_append): Remove the extra setlist argument.\n\n2000-02-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.template: A few updates.\n\n\t* i18n/de.po: New version from the German translation team.\n\n2000-02-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.78.91 released.\n\n2000-02-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): Reset *p2 to ':', not *colonp.  If any\n\tfilenames contained backslashes the resulting output (without\n\tbackslashes) will be shorter, so setting *colonp doesn't change\n\tthe right character.  Fix for PR/1586.\n\n\tFor += target-specific variables we need to remember which\n\tvariable set we found the variable in, so we can start looking\n\tfrom there in the next iteration (otherwise we might see it again\n\tin recursively_expand and fail!).  This is turning into a hack; if\n\tit gets any worse we'll have to rethink this entire algorithm...\n\timplementing expansion of these references separately from the\n\t\"normal\" expansion, say, instead of using the same codepath.\n\tActually, it's already \"worse enough\" :-/.\n\tFix for PR/1380.\n\n\t* variable.h (recursively_expand_setlist): Rename\n\trecursively_expand to add a struct variable_set_list argument, and\n\tmake a macro for recursively_expand.\n\t(lookup_variable_setlist): Rename lookup_variable to add a struct\n\tvariable_set_list argument, and make a macro for lookup_variable.\n\n\t* expand.c (recursively_expand_setlist): Take an extra struct\n\tvariable_set_list argument and pass it to allocated_variable_append().\n\t(reference_variable): Use lookup_variable_setlist() and pass the\n\treturned variable_set_list to recursively_expand_setlist.\n\t(allocated_variable_append): Take an extra setlist argument and\n\tuse this as the starting place when searching for the appended\n\texpansion.  If it's null, use current_variable_set_list as before.\n\n\t* variable.c (lookup_variable_setlist): If the LISTP argument is\n\tnot nil, set it to the list containing the variable we found.\n\n2000-02-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (print_variable): Write out filename/linenumber\n\tinformation for the variable definition if present.\n\t(define_variable_in_set): Store filename information if provided.\n\t(define_variable, define_variable_for_file): Removed.\n\t(try_variable_definition): Use define_variable_loc() to keep\n\tvariable definition location information.\n\t* read.c (read_makefile): Keep variable definition location info.\n\t(do_define): Ditto.\n\t(record_target_var): Ditto.\n\t* variable.h (define_variable_in_set): New fileinfo argument.\n\t(define_variable, define_variable_loc, define_variable_for_file):\n\tDeclare new macros.\n\n\tFix PR/1407:\n\n\t* filedef.h (struct file): Rename patvar to pat_variables and make\n\tit just a variable_set_list; we need our own copy of the pattern\n\tvariable's variable set list here to avoid overwriting the global\n\tone.\n\t* variable.c (initialize_file_variables): Move the instantiation\n\tof the pat_variables pointer here.  Only do the search after we're\n\tdone reading the makefiles so we don't search too early.  If\n\tthere's a pat_variables value, set up the variables next ptr.\n\t* expand.c (variable_expand_for_file): Remove the setup of the\n\tpat_variables info; it's done earlier now to ensure the parent's\n\tpattern variables are set up correctly as well.\n\n2000-02-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (sh_chars_dos) [WINDOWS32]: Add \"&\" as a shell\n\tmetacharacter for the W32 DOS shell.\n\tReported by Warren Jones <wjones@tc.fluke.com>.\n\n2000-02-02  Paul D. Smith  <psmith@gnu.org>\n\n\tFixes for the OpenVMS port from Hartmut Becker <becker@rto.dec.com>\n\n\t* config.h-vms [VMS]: Define LOCALEDIR to something; needed for\n\tthe expansion of bindtextdomain() even though it's a no-op.\n\t* vmsfunctions.c (strcmpi): Remove duplicate definition of strcmpi().\n\t(readdir): Use DB() instead of testing debug_flag.\n\t* dir.c (file_impossible) [VMS]: Search \"p\" not \"name\".\n\t* job.c [VMS]: Switch from debug_flag to the new DB macro.  Add\n\tsome i18n _() macros (even though VMS doesn't yet support it).\n\n\t* function.c (patsubst_expand): Change \"len\" to not be unsigned to\n\tavoid type mismatches.\n\n\t* main.c (main): Declare signame_init() if we're going to call it.\n\n2000-01-29  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS.template: Track changes in Makefile.in\n\t(install-recursive, uninstall-recursive): Add missing targets.\n\t(DESTDIR): Define.\n\t(install-binPROGRAMS, uninstall-binPROGRAMS): Use $(DESTDIR).\n\n\t* default.c (default_variables) [__MSDOS__]: Define CXX to gpp.\n\n2000-01-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* gettext.c: Some warning cleanups, and a fix for systems which\n\tdon't define HAVE_ALLOCA (the workaround code was included\n\ttwice).\n\n2000-01-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.78.90 released.\n\n2000-01-25  Paul D. Smith  <psmith@gnu.org>\n\n\tChange gettext support to use the simplified version in libit 0.7.\n\n\t* getopt.c, make.h: Use gettext.h instead of libintl.h.\n\t* ABOUT-NLS, gettext.h, gettext.c: New files from libit 0.7.\n\tModified to remove some static declarations which aren't defined.\n\t* acconfig.h: Use new gettext #defines.\n\t* acinclude.m4: Add fp_WITH_GETTEXT; remove AM_GNU_GETTEXT.\n\t* configure.in: Call fp_WITH_GETTEXT instead.\n\t* Makefile.am: New gettext stuff.  Also force inclusion of glob\n\tfiles for systems which have LIBC glob.\n\n\t* i18n/Makefile.am, i18n/.cvsignore: New dir for translation files.\n\t* i18n/de.po, i18n/es.po, i18n/fr.po, i18n/ko.po, i18n/nl.po:\n\t* i18n/pl.po, i18n/ru.po: Import translations already done for\n\tearlier versions of GNU make.  Thanks for that work!!\n\n\t* po/Makefile.in.in, po/POTFILES.in: Removed.\n\n2000-01-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (decode_debug_flags): If debug_flag is set, enable all\n\tdebugging levels.\n\t(debug_flag): Resurrect this flag variable.\n\t(switches): Make -d give the old behavior of turning on all\n\tdebugging.  Change --debug alone to emit basic debugging and take\n\toptional arguments to expand debugging.\n\t* NEWS: Document the new debugging options.\n\n\t* remake.c (no_rule_error): Remove this function.  This tries to\n\tfix a real problem--see the description with the introduction of\n\tthis function below.  However, the cure is worse than the disease\n\tand this approach won't work.\n\t(remake_file): Put the code from no_rule_error back here.\n\t(update_file_1): Remove call to no_rule_error.\n\n\t* filedef.h (struct file): Remove mfile_status field.\n\n2000-01-22  Paul D. Smith  <psmith@gnu.org>\n\n\tIntegrate GNU gettext support.\n\n\t* configure.in: Add AM_GNU_GETTEXT.\n\t* Makefile.am: Add options for setting LOCALEDIR, -Iintl, etc.\n\t* acinclude.m4: Add gettext autoconf macros.\n\t* acconfig.h: Add new gettext #defines.\n\t* make.h: Include libintl.h.  Make sure _() and N_() macros are\n\tdeclared.  Make gettext() an empty macro is NLS is disabled.\n\t* main.c (struct command_switch switches[]): Can't initialize\n\tstatic data with _() (gettext calls), so use N_() there then use\n\tgettext() directly when printing the strings.\n\t* remake.c (no_rule_error): The string constants can't be static\n\twhen initializing _() macros.\n\t* file.c (print_file): Reformat a few strings to work better for\n\ttranslation.\n\t* po/POTFILES.in, po/Makefile.in.in: New files.  Take\n\tMakefile.in.in from the latest GNU tar distribution, as that\n\tversion works better than the one that comes with gettext.\n\t* NEWS: Mention i18n ability.\n\n2000-01-21  Paul D. Smith  <psmith@gnu.org>\n\n\tInstalled patches for the VMS port.\n\tPatches provided by: Hartmut Becker <Hartmut.Becker@compaq.com>\n\n\t* readme.vms, arscan.c, config.h-vms, default.c, dir.c, file.c:\n\t* implicit.c, job.c, make.h, makefile.com, makefile.vms, rule.c:\n\t* variable.c, vmsdir.h, vmsfunctions.c, vmsify.c, glob/glob.c:\n\t* glob/glob.h: Installed patches.  See readme.vms for details.\n\n2000-01-14  Andreas Schwab  <schwab@suse.de>\n\n\t* dir.c (read_dirstream): Initialize d_type if it exists.\n\n2000-01-11  Paul D. Smith  <psmith@gnu.org>\n\n\tResolve PR/xxxx: don't automatically evaluate the $(call ...)\n\tfunction's arguments.  While we're here, clean up argument passing\n\tprotocol to always use simple nul-terminated strings, instead of\n\tsometimes using offset pointers to mark the end of arguments.\n\tThis change also fixes PR/1517.\n\tReported by Damien GIBOU <damien.gibou@st.com>.\n\n\t* function.c (struct function_table_entry): Remove the negative\n\trequired_args hack; put in explicit min and max # of arguments.\n\t(function_table): Add in the max value.  Turn off the expand bit\n\tfor func_call.\n\t(expand_builtin_function): Test against minimum_args instead of\n\tthe obsolete required_args.\n\t(handle_function): Rewrite this.  We don't try to be fancy and\n\tpass one style of arguments to expanded functions and another\n\tstyle to non-expanded functions: pass pointers to nul-terminated\n\tstrings to all functions.\n\t(func_call): Rewrite this.  If we are invoking a builtin function\n\tand it's supposed to have its arguments expanded, do that (since\n\tit's not done by handle_function for $(call ...) anymore).  For\n\tnon-builtins, just add the variables as before but mark them as\n\trecursive so they'll be expanded later, as needed.\n\t(func_if): All arguments are vanilla nul-terminated strings:\n\tremove trickery with \"argv[1]-1\".\n\t(func_foreach): Ditto.\n\n\t* expand.c (expand_argument): If the second arg is NULL, expand\n\tthe entire first argument.\n\n\t* job.c (new_job): Zero the child struct.  This change was just\n\tmade to keep some heap checking software happy, not because there\n\twas an actual bug (the important memory was being cleared properly).\n\n1999-12-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (print_variable): Print the variable with += if the\n\tappend flag is set.\n\n\t* implicit.c (pattern_search): Remove the extra check of the\n\timplicit flag added on 8/24/1998.  This causes problems and the\n\treason for the change was better resolved by the change made to\n\tcheck_deps() on 1998-08-26.  This fixes PR/1423.\n\n1999-12-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (dir_setup_glob): On 64 bit ReliantUNIX (5.44 and above)\n\tin LFS mode, stat() is actually a macro for stat64().  Assignment\n\tdoesn't work in that case.  So, stat is a macro, make a local\n\twrapper function to invoke it.\n\t(local_stat): Wrapper function, if needed.\n\tReported by Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>.\n\n1999-12-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file): Move the considered test outside the\n\tdouble-colon loop, _but_ make sure we test the double_colon target\n\tnot the \"current\" target.  If we stop early because one\n\tdouble-colon target is running, mark all the rest considered and\n\ttry to start their prerequisites (so they're marked considered).\n\tFix for PR/1476 suggested by Tim Magill <tim.magill@telops.gte.com>.\n\n1999-11-22  Rob Tulloh  <rob_tulloh@dev.tivoli.com>\n\n\t* function.c (windows32_openpipe, func_shell): Correct Windows32\n\tproblem where $(shell nosuchfile) would incorrectly exit make. The\n\tfix is to print the error and let make continue.\n\tReported by David Masterson <David.Masterson@kla-tencor.com>.\n\n\t* w32/subproc/misc.c (arr2envblk): Memory leak fix.\n\n1999-11-21  Paul D. Smith  <psmith@gnu.org>\n\n\tRework GNU make debugging to provide different levels of output.\n\n\t* NEWS: mention it.\n\t* debug.h: New file.  Define various debugging levels and macros.\n\t* function.c, implicit.c, job.c, main.c, misc.c, read.c, remake.c\n\t* remote-cstms.c, vmsfunctions.c: Replace all code depending on\n\tdebug_flag with invocations of debugging macros.\n\t* make.h: Remove debug_flag and DEBUGPR, add db_level.\n\n1999-11-18  Paul Eggert  <eggert@twinsun.com>\n\n\t* acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): Work around a problem\n\twith the QNX 4.25 shell, which doesn't propagate exit status of\n\tfailed commands inside shell assignments.\n\n1999-11-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_if): Find the end of the arg list by testing\n\tthe next item for NULL; any other test is not correct.\n\tReported by Graham Reed <grahamr@algorithmics.com> (PR/1429).\n\n\tFix += when used in a target-specific variable context.\n\n\t* variable.h: New bitfield APPEND set if we have a +=\n\ttarget-specific variable.\n\n\t* variable.c (try_variable_definition): Add an argument to specify\n\tif we're trying a target-specific variable.  If we are and it's an\n\tappend style, don't append it, record it as normal recursive, but\n\tset the APPEND flag so it'll be expanded later.\n\t* main.c (handle_non_switch_argument): Use new\n\ttry_variable_definition() signature.\n\t* read.c (read_makefile,record_target_var): Ditto.\n\n\t* expand.c (allocated_variable_append): New function: like\n\tallocated_variable_expand(), but we expand the same variable name\n\tin the context of the ``next'' variable set, then we append this\n\texpanded value.\n\t(recursively_expand): Invoke it, if the APPEND bit is set.\n\n1999-11-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (snap_deps): If the .NOTPARALLEL target is defined, turn\n\toff parallel builds for this make only (still allow submakes to be\n\trun in parallel).\n\t* main.c: New variable, ``not_parallel''.\n\t* make.h: Add an extern for it.\n\t* job.c (new_job): Test NOT_PARALLEL as well as JOB_SLOTS.\n\t* NEWS: Add info on .NOTPARALLEL.\n\t* make.texinfo (Special Targets): Document it.\n\n\t* configure.in (GLOBDIR): Set to \"glob\" if we need to build the\n\tglob library.\n\t* Makefile.am (SUBDIRS): Use the GLOBDIR variable instead of\n\t\"glob\" so we don't try to build glob if we don't need to (if we\n\thave GLIBC glob).  Reported by Lars Hecking <lhecking@nmrc.ucc.ie>.\n\n\t* main.c (main): Don't put \"***\" in the clock skew warning\n\tmessage.  Reported by karl@gnu.org.\n\n\t* make.h: Remove unneeded signal setup.\n\n\t* signame.c: Remove extraneous #includes; some versions of Ultrix\n\tdon't protect against multiple inclusions and it causes compile\n\terrors.  Reported by Simon Burge <simonb@thistledown.com.au>.\n\n1999-10-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (quote_for_env): Rename from quote_as_word().\n\n\t* make.h, *.c: Prefer strchr() and strrchr() in the code\n\trather than index() and rindex().  Define strchr/strrchr in terms\n\tof index/rindex if the former aren't supported.\n\n\t* default.c (CHECKOUT,v): Replace the fancy, complicated\n\tpatsubst/filter expression with a simple $(if ...) expression.\n\n\t* main.c (print_usage): Add the bug reporting mailing address to\n\tthe --help output, as per the GNU coding standards.\n\tReported by Paul Eggert <eggert@twinsun.com>.\n\n\t* README.customs: Installed information on running Customs-ized\n\tGNU make and setuid root, collected by Ted Stern <stern@tera.com>.\n\n\t* read.c (read_all_makefiles): PR/1394: Mark the end of the next\n\ttoken in the MAKEFILES value string _before_ we dup it.\n\n1999-10-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in (make_cv_sys_gnu_glob): We used to add the -Iglob\n\tflag to CPPFLAGS, but that loses if the user specifies his own\n\tCPPFLAGS; this one gets added _after_ his and if he happens to\n\thave an old or broken glob.h--boom.  Instead, put it in GLOBINC\n\tand SUBST it.\n\n\t* Makefile.am (INCLUDES): Add @GLOBINC@ to the INCLUDES macro;\n\tthese things get on the compile line well before the user's\n\tCPPFLAGS.\n\n1999-10-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (notice_finished_file): If we get here and -n is set,\n\tsee if all the command lines are marked recursive.  If so, then we\n\tran every command there is, so check the mtime on this file just\n\tlike we would normally.  If not, we assume the command we didn't\n\trun would updates the target and set mtime of the target to \"very new\".\n\n\t* job.c (start_job_command): Update lines_flags in the file's cmds\n\tstructure with any per-line tokens we found (`@', `-', `+').\n\n1999-10-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (initialize_file_variables): Always recurse to\n\tinitialize the parent's file variables: the parent might not have\n\tany rules to run so it might not have been initialized before\n\tthis--we need this to set up the chain properly for\n\ttarget-specific variables.\n\n1999-09-29  Paul Eggert  <eggert@twinsun.com>\n\n\t* main.c (quote_as_word): Always quote for decode_env_switches\n        instead of for the shell, so that arguments with strange\n        characters are are passed to submakes correctly.  Remove\n        double_dollars arg; we always double dollars now.  All callers\n        changed.\n        (decode_env_switches): Don't run off the end of an environment\n        variable whose contents ends in a unescaped backslash.\n\n1999-09-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* commands.c, function.c, job.c, read.c: Cast arguments to\n\tctype.h functions/macros to _unsigned_ char for portability.\n\n\t* remake.c, function.c: Compiler warning fixes: the second\n\targument to find_next_token() should be an _unsigned_ int*.\n\tReported by Han-Wen Nienhuys <hanwen@cs.uu.nl>.\n\n1999-09-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.78.1 released.\n\n\t* make.texinfo: Update version/date stamp.\n\n\t* main.c (main): Argh.  For some reason we were closing _all_ the\n\tjobserver pipes before we re-exec'd due to changed makefiles.\n\tThis means that any re-exec got a \"jobserver unavailable\" error :-/.\n\tI can't believe we didn't notice this before.\n\n1999-09-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.78 released.\n\n\t* main.c (main): Only fail on multiple --jobserver-fds options if\n\tthey aren't all the same.  Some makefiles use things like\n\t$(MAKE) $(MFLAGS) which will cause multiple, identical copies of\n\t--jobserver-fds to show up.\n\n1999-09-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (define_makeflags): Zero out FLAGSTRING to avoid\n\tuninitialized memory reads when checking *p != '-' in the loop.\n\n1999-09-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.97 released.\n\n\t* configure.in (MAKE_HOST): AC_SUBST this so it will go into the\n\tmakefile.\n\t* Makefile.am (check-local): Print a success banner if the check\n\tsucceeds.\n\t(check-regression): A bit of fine-tuning.\n\n1999-09-15  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* README.DOS.template: Document requirements for the test suite.\n\t* Makefile.DOS.template: Updates to allow the test suite to run\n\tfrom \"make check\".\n\n\t* main.c (main): Handle it if argv[0] isn't an absolute path.\n\n1999-09-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.96 released.\n\n\t* Makefile.am (loadavg): Use CPPFLAGS, etc. to make sure we get\n\tall the right #defines to compile.\n\t(check-regression): Look for the regression test suite in the make\n\tpackage itself.  If we're building remotely, use symlinks to make\n\ta local copy.\n\t(dist-hook): Put the test suite into the tar file.\n\n\t* configure.in: Look for perl for the test suite.\n\n1999-09-10  Paul Eggert  <eggert@twinsun.com>\n\n        * acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): If on HP-UX 10.20 or\n        later, and using GCC, define __STDC_EXT__; this works around a\n        bug in GCC 2.95.1.\n\n1999-09-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (print_version): Ugh.  GLIBC's configure tries to check\n\tmake version strings and is too aggressive with their matching\n\texpressions.  I've struck a deal with them to leave the version\n\toutput as-is for 3.78, and they'll change their configure checks\n\tso that I can change this back in the future.\n\n1999-09-07  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* job.c (construct_command_argv_internal) [__MSDOS__]: Add \"echo\"\n\tand \"unset\" to the list of builtin shell commands.\n\n\t* configh.DOS.template (MAKE_HOST): Define to \"i386-pc-msdosdjgpp\"\n\twhich is the canonical name of the DJGPP host.\n\n1999-09-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.95 released.\n\n\t* make.texinfo (Make Errors): Document some new jobserver error\n\tmessages.\n\n1999-09-04  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* make.texinfo (Make Errors): Document the hint about 8 spaces\n\tinstead of a TAB.\n\t(Call Function, Quick Reference): Use @code{$(1)}, not @var.\n\n\t* main.c (main) [__MSDOS__]: Say \"on this platform\" instead of \"on\n\tMS-DOS\", since the MSDOS version could run on Windows.\n\n1999-09-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (notice_finished_file): Always set mtime_before_update\n\tif it's not been set, not just if we ran some rules.  Otherwise we\n\tmay have a situation where a target's prerequisite was rebuilt but\n\tnot changed, so this target's rules weren't run, then\n\tupdate_goal_chain() sees mtime_before_update != last_mtime and\n\tthinks that the top-level target changed when it really didn't.\n\tThis can cause an infinite loop when remaking makefiles.\n\t(update_goal_chain): If we get back to the top and we don't know\n\twhat the goal's last_mtime was, find it now.  We need to know so\n\twe can compare it to mtime_before_update later (this is only\n\tcrucial when remaking makefiles--should we only do it then?)\n\n1999-09-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): If \"override\" appears as the first\n\tprerequisite, look further to ensure this is really a\n\ttarget-specific variable definition, and not just some\n\tprerequisite named \"override\".\n\n1999-09-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (IS_PATHSEP) [WINDOWS32]: Allow backslash separators\n\tfor W32 platforms.\n\t* read.c (record_files) [WINDOWS32]: Allow backslash separators\n\tfor W32 platforms.\n\t* implicit.c (pattern_search) [WINDOWS32]: Allow backslash\n\tseparators for W32 platforms.\n\n\t* configure.in (MAKE_HOST): Define it to be the canonical build\n\thost info, now that we need AC_CANONICAL_HOST anyway (for large\n\tfile support).\n\t* version.c (make_host): Define a variable to MAKE_HOST so we're\n\tsure to get it from the local config.h.\n\t* main.c (print_version): Use it in the version information.\n\t* config.ami.template: Add MAKE_HOST.\n\t* configh.dos.template: Ditto.\n\t* config.h.W32.template: Ditto.\n\t* config.h-vms.template: Ditto.\n\n\t* main.c (main): Close the jobserver file descriptors if we need\n\tto re-exec ourselves.\n\tAlso print more reasonable error if users force -jN for submakes.\n\tThis may be common for a while until people use the jobserver\n\tfeature.  If it happens, we ignore the existing jobserver stuff\n\tand use whatever they specified on the commandline.\n\t(define_makeflags): Fixed a long-standing bug: if a long name\n\tonly option comes immediately after a single letter option with no\n\targument, then the option string is constructed incorrectly.  For\n\texample, with -w and --jobserver-fds you get \"-w-jobserver-fds...\"\n\tinstead of \"-w --jobserver-fds...\"; add in an extra \" -\".\n\n\t* make.texinfo (Phony Targets): Add another example of using\n\t.PHONY with subdirectories/recursive make.\n\n1999-08-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.W32.template: Renamed from README.W32 so it's\n\tautogenerated during the dist.  A few minor modifications.\n\n\t* configure.in: Check for kstat_open before AC_FUNC_GETLOADAVG\n\tsince the latter needs to know whether the former exists to give\n\tan accurate result.\n\n1999-08-26  Rob Tulloh  <rob_tulloh@dev.tivoli.com>\n\n\t* NMakefile [WINDOWS32]: Now more robust. If you change a file\n\tunder w32/subproc, the make.exe will be relinked. Also added some\n\ttests to make sure erase commands won't fail when executed in a\n\tpristine build environment.\n\n\t* w32/subproc/sub_proc.c [WINDOWS32]: Added support for\n\tHAVE_CYGWIN_SHELL. If you are using the Cygwin B20.1 release, it\n\tis now possible to have have native support for this shell without\n\thaving to rely on klutzy BATCH_MODE_ONLY_SHELL.\n\n\t* config.h.W32 [WINDOWS32]: Added HAVE_CYGWIN_SHELL macro which\n\tusers can define if they want to build make to use this shell.\n\n\t* README.W32 [WINDOWS32]: Added informaton about\n\tHAVE_CYGWIN_SHELL. Cleaned up text a bit to make it more current.\n\n1999-08-26  Paul Eggert  <eggert@twinsun.com>\n\n\tSupport large files in AIX, HP-UX, and IRIX.\n\n\t* acinclude.m4 (AC_LFS): Remove.  Superseded by AC_SYS_LARGEFILE.\n\t(AC_SYS_LARGEFILE_FLAGS, AC_SYS_LARGEFILE_SPACE_APPEND,\n\tAC_SYS_LARGEFILE_MACRO_VALUE, AC_SYS_LARGEFILE): New macros.\n\t(jm_AC_TYPE_UINTMAX_T): Check for busted compilers that can't\n\tshift or divide unsigned long long.\n\t(AM_PROG_CC_STDC): New macro; a temporary workaround of a bug in\n\tautomake 1.4.\n\n\t* configure.in (AC_CANONICAL_HOST): Add; required by new\n\tAC_SYS_LARGEFILE.\n\t(AC_SYS_LARGEFILE): Renamed from AC_LFS.\n\t(AM_PROG_CC_STDC): Add.\n\n\t* config.guess, config.sub: New files, needed for AC_CANONICAL_HOST.\n\n1999-08-25  Paul Eggert  <eggert@twinsun.com>\n\n\t* make.h (CHAR_MAX): New macro.\n\t* main.c (struct command_switch): c is now int,\n\tso that it can store values greater than CHAR_MAX.\n\t(switches): Replace small numbers N with CHAR_MAX+N-1,\n\tto avoid problems with non-ASCII character sets.\n\t(short_option): New macro.\n\t(init_switches, print_usage, define_makeflags): Use it instead of\n\tisalnum.\n\n1999-08-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.94 released.\n\n\t* main.c (main) [__MSDOS__]: If the user uses -j, warn that it's\n\tnot supported and reset it.\n\n\t* make.h (ISDIGIT): Obtained this from the textutils distribution.\n\t* main.c (decode_switches): Use it.\n\t* function.c (is_numeric): Use it.\n\n\t* main.c (struct command_switch): Store the switch char in an\n\tunsigned char to shut up GCC about using it with ctype.h macros.\n\tBesides, it _is_ always unsigned.\n\n1999-08-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Change \"dependency\" to \"prerequisite\" and\n\t\"dependencies\" to \"prerequisites\".  Various other cleanups related\n\tto the terminology change.\n\t* file.c: Change debugging and error messages to use\n\t\"prerequisite\" instead of \"dependency\".\n\t* implicit.c: Ditto.\n\t* remake.c: Ditto.\n\t* NEWS: Document it.\n\n1999-08-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file): Move the considered check into the\n\tdouble-colon rule loop, so we consider double-colon rules\n\tindividually (otherwise after the first is pruned, the rest won't\n\tget run).\n\n\t* README.template: Minor changes.\n\n\tRemove the debugging features of the jobserver, so it no longer\n\twrites distinct tokens to the pipe.  Thus, we don't need to store\n\tthe token we get.  A side effect of this is to remove a potential\n\t\"unavailable token\" situation: make-1 invokes make-2 with its\n\tspecial token and make-3 with a normal token; make-2 completes.\n\tNow we're waiting for make-3 but using 2 tokens; our special token\n\tis idle.  In the new version we don't have special tokens per se,\n\twe merely decide if we already have a child or not.  If we don't,\n\twe don't need a token.  If we do, we have to get one to run the\n\tnext child.  Similar for putting tokens back: if we're cleaning up\n\tthe last child, we don't put a token back.  Otherwise, we do.\n\n\t* main.c: Add a new, internal flag --jobserver-fds instead of\n\toverloading the meaning of -j.  Remove job_slots_str and add the\n\tstringlist jobserver_fds.\n\t(struct command_switch): We don't need the int_string type.\n\t(switches[]): Add a new option for --jobserver-fds and remove\n\tconditions around -j.  Make the description for the former 0 so it\n\tdoesn't print during \"make --help\".\n\t(main): Rework jobserver parsing.  If we got --jobserver-fds\n\tmake sure it's valid.  We only get one and job_slots must be 0.\n\tIf we're the toplevel make (-jN without --jobserver-fds) create\n\tthe pipe and write generic tokens.\n\tCreate the stringlist struct for the submakes.\n\tClean up the stringlist where necessary.\n\t(init_switches): Remove int_string handling.\n\t(print_usage): Don't print internal flags (description ptr is 0).\n\t(decode_switches): Remove int_string handling.\n\t(define_makeflags): Remove int_string handling.\n\n\t* job.c: Remove my_job_token flag and all references to the\n\tchild->job_token field.\n\t(free_job_token): Remove this and merge it into free_child().\n\t(reap_children): Rework the \"reaped a child\" logic slightly.\n\tDon't call defunct free_job_token anymore.  Always call\n\tfree_child, even if we're dying.\n\t(free_child): If we're not freeing the only child, put a token\n\tback in the pipe.  Then, if we're dying, don't bother to free.\n\t(new_job): If we are using the jobserver, loop checking to see if\n\ta) there are no children or b) we get a token from the pipe.\n\n\t* job.h (struct child): Remove the job_token field.\n\n1999-08-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (try_variable_definition): Allocate for variable\n\texpansion in f_append with a simple variable: if we're looking at\n\ttarget-specific variables we don't want to trash the buffer.\n\tNoticed by Reiner Beninga <Reiner.Beninga@mchp.siemens.de>.\n\n1999-08-16  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* main.c (main) [__MSDOS__]: Mirror any backslashes in argv[0], to\n\tavoid problems in shell commands that use backslashes as escape\n\tcharacters.\n\n1999-08-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.93 released.\n\n1999-08-13  Paul D. Smith  <psmith@gnu.org\n\n\t* function.c (func_if): New function $(if ...) based on the\n\toriginal by Han-Wen but reworked quite a bit.\n\t(function_table): Add it.\n\t* NEWS: Introduce it.\n\t* make.texinfo (If Function): Document it.\n\n\t* job.c (free_job_token): Check for EINTR when writing tokens to\n\tthe jobserver pipe.\n\n1999-08-12  Paul D. Smith  <psmith@gnu.org>\n\n\tAnother jobserver algorithm change.  We conveniently forgot that\n\tthe blocking bit is shared by all users of the pipe, it's not a\n\tper-process setting.  Since we have many make processes all\n\tsharing the pipe we can't use the blocking bit as a signal handler\n\tflag.  Instead, we'll dup the pipe's read FD and have the SIGCHLD\n\thandler close the dup'd FD.  This will cause the read() to fail\n\twith EBADF the next time we invoke it, so we know we need to reap\n\tchildren.  We then re-dup and reap.\n\n\t* main.c (main): Define the job_rfd variable to hold the dup'd FD.\n\tActually dup the read side of the pipe.  Don't bother setting the\n\tblocking bit on the file descriptor.\n\t* make.h: Declare the job_rfd variable.\n\t* job.c (child_handler): If the dup'd jobserver pipe is open,\n\tclose it and assign -1 to job_rfd to notify the main program that\n\twe got a SIGCHLD.\n\t(start_job_command): Close the dup'd FD before exec'ing children.\n\tSince we open and close this thing so often it doesn't seem\n\tworth it to use the close-on-exec bit.\n\t(new_job): Remove code for testing/setting the blocking bit.\n\tInstead of EAGAIN, test for EBADF.  If the dup'd FD has been\n\tclosed, re-dup it before we reap children.\n\n\t* function.c (func_shell): Be a little more accurate about the\n\tlength of the error string to allocate.\n\n\t* expand.c (variable_expand_for_file): If there's no filenm info\n\t(say, from a builtin command) then reset reading_file to 0.\n\n1999-08-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile: Use g in sed (s///g) to replace >1 variable per\n\tline.\n\n\t* Makefile.DOS.template [__MSDOS__]: Fix mostlyclean-aminfo to\n\tremove the right files.\n\n1999-08-01  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* function.c (msdos_openpipe) [__MSDOS__]: *Really* return a FILE\n\tptr.\n\n1999-08-01  Paul D. Smith  <psmith@gnu.org>\n\n\tNew jobserver algorithm to avoid a possible hole where we could\n\tmiss SIGCHLDs and get into a deadlock.  The original algorithm was\n\tsuggested by Roland McGrath with a nice refinement by Paul Eggert.\n\tMany thanks as well to Tim Magill and Howard Chu, who also\n\tprovided many viable ideas and critiques.  We all had a fun week\n\tdreaming up interesting ways to use and abuse UNIX syscalls :).\n\n\tPreviously we could miss a SIGCHLD if it happened after we reaped\n\tthe children but before we re-entered the blocking read.  If this\n\thappened to all makes and/or all children, make would never wake\n\tup.\n\n\tWe avoid this by having the SIGCHLD handler reset the blocking bit\n\ton the jobserver pipe read FD (normally read does block in this\n\talgorithm).  Now if the handler is called between the time we reap\n\tand the time we read(), and there are no tokens available, the\n\tread will merely return with EAGAIN instead of blocking.\n\n\t* main.c (main): Set the blocking bit explicitly here.\n\t* job.c (child_handler): If we have a jobserver pipe, set the\n\tnon-blocking bit for it.\n\t(start_waiting_job): Move the token stuff back to new_job; if we\n\tdo it here then we're not controlling the number of remote jobs\n\tstarted!\n\t(new_job): Move the check for job slots to _after_ we've created a\n\tchild structure.  If the read returns without getting a token, set\n\tthe blocking bit then try to reap_children.\n\n\t* make.h (EINTR_SET): Define to test errno if EINTR is available,\n\tor 0 otherwise.  Just some code cleanup.\n\t* arscan.c (ar_member_touch): Use it.\n\t* function.c (func_shell): Use it.\n\t* job.c (reap_children): Use it.\n\t* remake.c (touch_file): Use it.\n\n1999-07-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Define _() and N_() macros as passthrough to initiate\n\tNLS support.\n\t* <all>: Add _()/N_() around translatable strings.\n\n1999-07-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c: Make sure make.h comes before other headers.\n\n1999-07-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Quick Reference): Update with the new features.\n\n1999-07-25  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* remake.c [__MSDOS__]: Don't include variables.h, it's already\n\tincluded.\n\n\t* function.c (msdos_openpipe) [__MSDOS__]: Return FILE ptr.\n\t(func_shell) [__MSDOS__]: Fix the argument list.\n\n\t* Makefile.DOS.template: Update from Makefile.in.\n\n\t* README.DOS.template: Configure command fixed.\n\n\t* configh.dos.template: Update to provide definitions for\n\tuintmax_t, fd_set_size_t, and HAVE_SELECT.\n\n1999-07-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.91 released.\n\n\t* configure.in: Changes to the boostrapping code: if build.sh.in\n\tdoesn't exist configure spits an error and generates an empty\n\tbuild.sh file which causes make to be confused.\n\t* maintMakefile: Don't build README early.\n\n1999-07-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (my_job_token): This variable controls whether we've\n\thanded our personal token to a subprocess or not.  Note we could\n\tprobably infer this from the value of job_slots_used, but it's\n\tclearer to just keep it separately.  Job_slots_used isn't really\n\trelevant when running the job server.\n\t(free_job_token): New function: free a job token.  If we don't\n\thave one, no-op.  If we have the personal token, reclaim it.  If\n\twe have another token, write it back to the pipe.\n\t(reap_children): Call free_job_token.\n\t(free_child): Call free_job_token.\n\t(start_job_command): Remove duplicate test for '+' in the command.\n\tIf we don't appear to be running a recursive make, close the\n\tjobserver filedescriptors.\n\t(start_waiting_job): If our personal token is available, use that\n\tinstead of going to the server pipe.\n\t(*): Add the token value to many debugging statements, and print\n\tthe child target name in addition to the ptr hex value.\n\tChange the default \"no token\" value from '\\0' to '-' so it looks\n\tbetter in the output.\n\n\t* main.c (main): Install the child_handler with sigaction()\n\tinstead of signal() if we have it.  On SysV systems, signal() uses\n\tSysV semantics which are a pain.  But sigaction() always does what\n\twe want.\n\t(main): If we got job server FDs from the environment, test them\n\tto see if they're open.  If not, the parent make closed them\n\tbecause it didn't think we were a submake.  Print a warning and\n\tsuggestion to use \"+\" on the submake invocation, and hard-set to\n\t-j1 for this instance of make.\n\t(main): Change the algorithm for assigning slots to be more\n\trobust.  Previously make checked to see if it thought a subprocess\n\twas a submake and if so, didn't give it a token.  Since make's\n\tdon't consume tokens we could spawn many of makes fighting for a\n\tsmall number of tokens.  Plus this is unreliable because submakes\n\tmight not be recognized by the parent (see above) then all the\n\ttokens could be used up by unrecognized makes, and no one could\n\trun.  Now every make consumes a token from its parent.  However,\n\tthe make can also use this token to spawn a child.  If the make\n\twants more than one, it goes to the jobserver pipe.  Thus there\n\twill never be more than N makes running for -jN, and N*2 processes\n\t(N makes and their N children).  Every make can always run at\n\tleast one job, and we'll never deadlock.  (Note the closing of the\n\tpipe for non-submakes also solves this, but this is still a better\n\talgorithm.)  So!  Only put N-1 tokens into the pipe, since the\n\ttopmost make keeps one for itself.\n\n\t* configure.in: Find sigaction.  Disable job server support unless\n\tthe system provides it, in addition to either waitpid() or\n\twait3().\n\n1999-07-22  Rob Tulloh  <rob_tulloh@dev.tivoli.com>\n\n\t* arscan.c (ar_member_touch) [WINDOWS32]: The ar_date field is a\n\tstring on Windows, not a timestamp.\n\n1999-07-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77.90 released.\n\n\t* Makefile.am (AUTOMAKE_OPTIONS): Require automake 1.4.\n\n\t* function.c: Rearrange so we don't need to predeclare the\n\tfunction_table array; K&R C compilers don't like that.\n\n\t* acinclude.m4 (AC_FUNC_SELECT): Ouch; this requires an ANSI C\n\tcompiler!  Change to work with K&R compilers as well.\n\n\t* configure.in (AC_OUTPUT): Put build.sh back.  I don't know how I\n\tthought it would work this way :-/.  We'll have to think of\n\tsomething else.\n\t* Makefile.am: Remove rule to create build.sh.\n\n\t* default.c (default_suffix_rules): Rearrange the default command\n\tlines to conform to POSIX rules (put the filename argument $<\n\t_after_ the OUTPUT_OPTION, not before it).\n\n\t* various: Changed !strncmp() calls to strneq() macros.\n\n\t* misc.c (sindex): Make slightly more efficient.\n\n\t* dir.c (file_impossible): Change savestring(X,strlen(X)) to xstrdup().\n\t* implicit.c (pattern_search): Ditto.\n\t* main.c (enter_command_line_file): Ditto.\n\t(main): Ditto.\n\t* misc.c (copy_dep_chain): Ditto.\n\t* read.c (read_makefile): Ditto.\n\t(parse_file_seq): Ditto.\n\t(tilde_expand): Ditto.\n\t(multi_glob): Ditto.\n\t* rule.c (install_pattern_rule): Ditto.\n\t* variable.c (define_variable_in_set): Ditto.\n\t(define_automatic_variables): Ditto.\n\t* vpath.c (construct_vpath_list): Ditto.\n\n\t* misc.c (xrealloc): Some reallocs are non-standard: work around\n\tthem in xrealloc by calling malloc if PTR is NULL.\n\t* main.c (main): Call xrealloc() directly instead of testing for\n\tNULL.\n\n\t* function.c (func_sort): Don't try to free NULL; some older,\n\tnon-standard versions of free() don't like it.\n\n\t* configure.in (--enable-dmalloc): Install some support for using\n\tdmalloc (https://www.dmalloc.com/) with make.  Use --enable-dmalloc\n\twith configure to enable it.\n\n\t* function.c (function_table_entry): Whoops!  The function.c\n\trewrite breaks backward compatibility: all text to a function is\n\tbroken into arguments, and extras are ignored.  So $(sort a,b,c)\n\treturns \"a\"!  Etc.  Ouch.  Fix it by making a positive value in\n\tthe REQUIRED_ARGS field mean exactly that many arguments to the\n\tfunction; any \"extras\" are considered part of the last argument as\n\tbefore.  A negative value means at least that many, but may be\n\tmore: in this case all text is broken on commas.\n\t(handle_function): Stop when we've seen REQUIRED_ARGS args, if >0.\n\t(expand_builtin_function): Compare number of args to the absolute\n\tvalue of REQUIRED_ARGS.\n\n1999-07-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): Ensure that the state of the target\n\tis cs_running.  It might not be if we skipped all the lines due to\n\t-n (for example).\n\n\t* commands.c (execute_file_commands): If we discover that the\n\tcommand script is empty and succeed early, set cs_running so the\n\tmodtime of the target is still rechecked.\n\n\t* rule.c (freerule): Free the dependency list for the rule.\n\n\t* implicit.c (pattern_search): When turning an intermediate file\n\tinto a real target, keep the also_make list.\n\tFree the dep->name if we didn't use it during enter_file().\n\n1999-07-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): Don't allocate the commands buffer until\n\twe're sure we found a makefile and won't return early (mem leak).\n\n\t* job.c (start_job_command): Broken #ifdef test: look for F_SETFD,\n\tnot FD_SETFD.  Close-on-exec isn't getting set on the bad_stdin\n\tfile descriptor and it's leaking :-/.\n\t* getloadavg.c (getloadavg): Ditto.\n\n1999-07-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): Fix some potential memory stomps parsing\n\t`define' directives where no variable name is given.\n\n\t* function.c (func_call): Rename from func_apply.  Various code\n\tcleanup and tightening.\n\t(function_table): Add \"call\" as a valid builtin function.\n\n\t* make.texinfo (Call Function): Document it.\n\n\t* NEWS: Announce it.\n\n1999-07-09  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* variable.c (try_variable_definition) [__MSDOS__, WINDOWS32]:\n\tTreat \"override SHELL=\" the same as just \"SHELL=\".\n\n1999-07-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_waiting_job): Don't get a second job token if we\n\talready have one; if we're waiting on the load to go down\n\tstart_waiting_job() might get called twice on the same file.\n\n\t* filedef.h (struct file): Add new field, mtime_before_update.\n\tWhen notice_finished_file runs it assigns the cached last_mtime to\n\tthis field.\n\t* remake.c (update_goal_chain): Notice that a file wasn't updated\n\tby asking if it changed (g->changed) and comparing the current\n\tcached time (last_mtime) with the previous one, stored in\n\tmtime_before_update.  The previous check (\"did last_mtime changed\n\tduring the run of update_file?\") fails for parallel builds because\n\tlast_mtime is set during reap_children, before update_file is run.\n\tThis causes update_goal_chain to always return -1 (nothing\n\trebuilt) when running parallel (-jN).  This is OK during \"normal\"\n\tbuilds since our caller (main) treats these cases identically in\n\tthat case, but if when rebuilding makefiles the difference is very\n\timportant, as it controls whether we re-exec or not.\n\t* file.c (file_hash_enter): Copy the mtime_before_update field.\n\t(snap_deps): Initialize mtime_before_update to -1.\n\t* main.c (main): Initialize mtime_before_update on old (-o) and\n\tnew (-W) files.\n\n1999-07-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (switches): Define a new switch -R (or\n\t--no-builtin-variables).  This option disables the defining of all\n\tthe GNU make builtin variables.\n\t(main): If -R was given, force -r as well.\n\t* default.c (define_default_variables): Test the new flag.\n\t* make.h: Declare global flag.\n\t* make.texinfo (Options Summary): Document the new option.\n\t(Implicit Variables): Ditto.\n\n1999-07-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Options Summary): Correct examples in\n\t--print-data-base option summary (problem reported by David Morse\n\t<morse@nichimen.com>).\n\n\t* arscan.c: Add support for archives in Windows (VC++).  Frank\n\tLibbrecht <frankl@abzx.belgium.hp.com> provided info on how to do\n\tthis.\n\t* NMakefile.template (CFLAGS_any): Remove NO_ARCHIVES from the\n\tcompile line.\n\t* build_w32.bat: Ditto.\n\n\t* remake.c (no_rule_error): Fix -include/sinclude so it doesn't\n\tgive errors if you try to -include the same file twice.\n\t(updating_makefiles): New variable: we need to know this info in\n\tno_rule_error() so we know whether to print an error or not.\n\t(update_file_1): Unconditionally call no_rule_error(), don't try\n\tto play games with the dontcare flag.\n\n1999-06-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Remaking Makefiles): Add a description of how to\n\tprevent implicit rule searches for makefiles.\n\n\t* make.1: Remove statement that make continues processing when -v\n\tis given.\n\n1999-06-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): Cast -1 arguments to\n\tvariable_expand_string() to long.  Alexandre Sauve\n\t<Alexandre.SAUVE@ifp.fr> reports that without casts, this breaks\n\ton a NEC SUPER-UX SX-4 system (and it's wrong without a cast\n\tanyway).  Of course, (a) I'd really love to start using function\n\tprototypes, and (b) there's a whole slew of issues related to int\n\tvs. long and signed vs. unsigned in the length handling of\n\tvariable buffers, etc.  Gross.  Needs a complete mucking-out.\n\t* expand.c (variable_expand): Ditto.\n\n\t* acinclude.m4 (AC_FUNC_SELECT): Slight enhancement for AIX 3.2 by\n\tLars Hecking <lhecking@nmrc.ucc.ie>.\n\n\t* read.c (get_next_mword): Allow colons to be escaped in target\n\tnames: fix for regression failure.\n\n1999-04-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Reset read_makefiles to empty after processing so\n\twe get the right error message.\n\n1999-04-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Updates to @dircategory and @direntry suggested by\n\tKarl Berry <karl@cs.umb.edu>.\n\n1999-04-23  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* job.c (start_job_command) [__MSDOS__]: Call unblock_sigs before\n\tturning off dos_command_running, so child's signals produce the\n\tright effect.\n\n\t* commands.c (fatal_error_signal) [__MSDOS__]: Use EXIT_FAILURE\n\tinstead of 1.\n\n1999-04-18  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* configh.dos.template: Update to recognize that version 2.02 of\n\tDJGPP contains sys_siglist stuff.\n\n1999-04-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Options/Recursion): Document the job server.\n\t(Parallel): Tweaks.\n\n1999-04-13  Paul D. Smith  <psmith@gnu.org>\n\n\tImplement a new \"job server\" feature; the implementation was\n\tsuggested by Howard Chu <hyc@highlandsun.com>.\n\n\t* configure.in (job-server): New disable option for job server\n\tsupport--it's enabled by default.  If it works well this will go\n\taway.\n\n\t* NEWS: Summarize the new feature.\n\n\t* acconfig.h: New definition MAKE_JOBSERVER if job server support\n\tis enabled.\n\t* config.h-vms.template: Undef MAKE_JOBSERVER for this port.\n\t* config.h.W32.template: Ditto.\n\t* config.ami.template: Ditto.\n\n\t* main.c (struct command_switch): Add a new type: int_string.\n\t(switches[]) Use int_string for -j if MAKE_JOBSERVER.\n\t(init_switches): Initialize the new int_string switch type.\n\t(print_usage): New function, extracted from decode_switches().\n\t(decode_switches): Call it.  Decode the new int_string switch type.\n\t(define_makeflags): Add new int_string switch data to MAKEFLAGS.\n\t(job_fds[]) Array to contain the pipe file descriptors.\n\t(main): Parse the job_slots_str option results.  If necessary,\n\tcreate the pipe and seed it with tokens.  Set the non-blocking bit\n\tfor the read fd.  Enable the signal handler for SIGCHLD even if we\n\thave a non-hanging wait; it's needed to interrupt the select() in\n\tjob.c:start_waiting_job().\n\n\t* make.h: Declare job_fds[].\n\n\t* job.h (struct child): Add job_token field to store the token for\n\tthis job (if any).\n\n\t* job.c (reap_children): When a child is fully reaped, release the\n\ttoken back into the pipe.\n\t(free_child): If the child to be freed still has a token, put it\n\tback.\n\t(new_job): Initialize the job_token member.\n\t(start_waiting_job): For local jobs, if we're using the pipe, get\n\ta token before we check the load, etc.  We do this by performing a\n\tnon-blocking read in a loop.  If the read fails, no token is\n\tavailable.  Do a select on the fd to wait for a token.  We need to\n\tre-enable the signal handler for SIGCHLD even if we have a\n\tnon-hanging waitpid() or wait3(), so that the signal will\n\tinterrupt the select() and we can wake up to reap children.\n\t(child_handler): Re-enable the signal handler.  The count is still\n\tkept although it's not needed or used unless you don't have\n\twaitpid() or wait3().\n\n1999-04-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Reset the considered bit on all the makefiles if\n\tsomething failed to update; we need to examine them again if they\n\tappear as normal targets in order to get the proper error message.\n\n1999-04-09  Paul D. Smith  <psmith@gnu.org>\n\n\tPerformance enhancement from Tim Magill <tim.magill@telops.gte.com>.\n\n\t* remake.c (update_file): If you have large numbers of\n\tdependencies and you run in parallel, make can spend considerable\n\ttime each pass through the graph looking at branches it has\n\talready seen.  Since we only reap_children() when starting a pass,\n\tnot in the middle, if a branch has been seen already in that pass\n\tnothing interesting can happen until the next pass.  So, we toggle\n\ta bit saying whether we've seen this target in this pass or not.\n\t(update_goal_chain): Initially set the global considered toggle to\n\t1, since all targets initialize their boolean to 0.  At the end of\n\teach pass, toggle the global considered variable.\n\t* filedef.h (struct file): Per-file considered toggle bit.\n\t* file.c: New global toggle variable considered.\n\n1999-04-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* arscan.c (ar_scan): Added support for ARFZMAG (compressed\n\tarchives?) for Digital UNIX C++.  Information provided by\n\tPatrick\tE. Krogel <pekrogel@mtu.edu>.\n\t(ar_member_touch): Ditto.\n\n1999-04-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): If: a) we found a file and b) we didn't\n\tcreate it and c) it's not marked as an implicit target and d) it\n\tis marked as an intermediate target, then it was so marked due to\n\tan .INTERMEDIATE special target, but it already existed in the\n\tdirectory.  In this case, unset the intermediate flag so we won't\n\tdelete it when make is done.  It feels like it would be cleaner to\n\tput this check in update_file_1() but I worry it'll get missed...\n\n1999-04-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Use bcopy() to copy\n\toverlapping strings, rather than strcpy().  ISO C says the latter\n\tis undefined.  Found this in a bug report from 1996!  Ouch!\n\n1999-03-31  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (readline): Ignore carriage returns at the end of the\n\tline, to allow Windows-y CRLF line terminators.\n\n1999-03-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Don't put build.sh here, since build.sh.in doesn't\n\texist initially.  This cause autoreconf and automake to fail when\n\trun on a clean CVS checkout.  Instead, we create build.sh in the\n\tMakefile (see below).\n\n\t* Makefile.am: Remove BUILT_SOURCES; this is no longer relevant.\n\tPut those files directly into EXTRA_DIST so they're distributed.\n\tCreate a local build rule to create build.sh.\n\tCreate a local maintainer-clean rule to delete all the funky\n\tmaintainers files.\n\n\t* maintMakefile: Makefile.in depends on README, since automake\n\tfails if it doesn't exist.  Also don't remove glob/Makefile.in\n\there, as it causes problems.\n\n1999-03-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Substitute GLOBLIB if we need the link the\n\tglob/libglob.a library.\n\t* Makefile.am (make_LDADD): Use the subst variable GLOBLIB so we\n\tdon't link the local libglob.a at all if we don't need it.\n\t* build.template: Don't compile glob/*.o unless we want globlib.\n\t* maintMakefile (build.sh.in): Substitute the glob/*.o files\n\tseparately.\n\n1999-03-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Various typos and additions, pointed out by James\n\tG. Sack <jsack@dornfeld.com>.\n\n1999-03-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Functions): Add a new section documenting the new\n\t$(error ...) and $(warning ...) functions.  Also updated copyright\n\tdates.\n\t* NEWS: Updated for the new functions.\n\t* function.c (func_error): Implement the new $(error ...) and\n\t$(warning ...) functions.\n\t(function_table): Insert new functions into the table.\n\t(func_firstword): Don't call find_next_token() with argv[0]\n\titself, since that function modifies the pointer.\n\t* function.c: Cleanups and slight changes to the new method of\n\tcalling functions.\n\n1999-03-20  Han-Wen Nienhuys  <hanwen@cs.uu.nl>\n\n\t* function.c: Rewrite to use one C function per make function,\n\tinstead of a huge switch statement.  Also allows some cleanup of\n\tmulti-architecture issues, and a cleaner API which makes things\n\tlike func_apply() simple.\n\n\t* function.c (func_apply): Initial implementation.  Expand either\n\ta builtin function or a make variable in the context of some\n\targuments, provided as $1, $2, ... $N.\n\n1999-03-19  Eli Zaretskii  <eliz@is.elta.co.il>\n1999-03-19  Rob Tulloh  <rob_tulloh@dev.tivoli.com>\n\n\t* job.c (construct_command_argv_internal): Don't treat _all_\n\tbackslashes as escapes, only those which really escape a special\n\tcharacter.  This allows most normal \"\\\" directory separators to be\n\ttreated normally.\n\n1999-03-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Check for a system strdup().\n\t* misc.c (xstrdup): Created.  Suggestion by Han-Wen Nienhuys\n\t<hanwen@cs.uu.nl>.\n\t* make.h: Prototype xstrdup().\n\t* remake.c (library_search): Use it.\n\t* main.c (main): Use it.\n\t(find_and_set_default_shell): Use it.\n\t* job.c (construct_command_argv_internal): Use it.\n\t* dir.c (find_directory): Use it.\n\n\t* Makefile.am, configure.in: Use AC_SUBST_FILE to insert the\n\tmaintMakefile instead of \"include\", to avoid automake 1.4\n\tincompatibility.\n\n1999-03-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* amiga.c, amiga.h, ar.c, arscan.c, commands.c, commands.h,\n\t* default.c, dep.h, dir.c, expand.c, file.c, filedef.h, function.c,\n\t* implicit.c, job.c, job.h, main.c, make.h, misc.c, read.c, remake.c\n\t* remote-cstms.c, remote-stub.c, rule.h, variable.c, variable.h,\n\t* vpath.c, Makefile.ami, NMakefile.template, build.template,\n\t* makefile.vms: Updated FSF address in the copyright notice.\n\n\t* variable.c (try_variable_definition): If we see a conditional\n\tvariable and we decide to set it, re-type it as recursive so it\n\twill be expanded properly later.\n\n1999-02-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* NEWS: Mention new .LIBPATTERNS feature.\n\n\t* make.texinfo (Libraries/Search): Describe the use and\n\tramifications of the new .LIBPATTERNS variable.\n\n\t* remake.c (library_search): Instead of searching only for the\n\thardcoded expansion \"libX.a\" for a library reference \"-lX\", we\n\tobtain a list of patterns from the .LIBPATTERNS variable and\n\tsearch those in order.\n\n\t* default.c: Added a new default variable .LIBPATTERNS.  The\n\tdefault for UNIX is \"lib%.so lib%.a\".  Amiga and DOS values are\n\talso provided.\n\n\t* read.c: Remove bogus HAVE_GLOB_H references; always include\n\tvanilla glob.h.\n\n1999-02-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (expand_function): Set value to 0 to avoid freeing it.\n\t* variable.c (pop_variable_scope): Free the value of the variable.\n\t(try_variable_definition): For simple variables, use\n\tallocated_variable_expand() to avoid stomping on the variable\n\tbuffer when we still need it for other things.\n\n\t* arscan.c: Modified to support AIX 4.3 big archives.  The changes\n\tare based on information provided by Phil Adams\n\t<padams@austin.ibm.com>.\n\n1999-02-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Check to see if the GNU glob library is already\n\tinstalled on the system.  If so, _don't_ add -I./glob to the\n\tcompile line.  Using the system glob code with the local headers\n\tis very bad mojo!\n\tRewrite SCCS macros to use more autoconf facilities.\n\n\t* Makefile.am: Move -Iglob out of INCLUDES; it'll get added to\n\tCPPFLAGS by configure now.\n\tAutomake 1.4 introduced its own \"include\" feature which conflicts\n\twith the maintMakefile stuff.  A hack that seems to work is add a\n\tspace before the include :-/.\n\n\t* build.template: Move -Iglob out of the compile line; it'll get\n\tadded to CPPFLAGS by configure now.\n\n1999-02-16  Glenn D. Wolf  <Glenn_Wolf@email.sps.mot.com>\n\n\t* arscan.c (ar_scan) [VMS]: Initialized VMS_member_date before\n\tcalling lbr$get_index since if the archive is empty,\n\tVMS_get_member_info won't get called at all, and any leftover date\n\twill be used.  This bug shows up if any member of any archive is\n\tmade, followed by a dependency check on a different, empty\n\tarchive.\n\n1998-12-13  Martin Zinser  <zinser@decus.decus.de>\n\n\t* config.h-vms [VMS]: Set _POSIX_C_SOURCE.  Redefine the getopt\n\tfunctions so we don't use the broken VMS versions.\n\t* makefile.com [VMS]: Allow debugging.\n\t* dir.c (dir_setup_glob) [VMS]: Don't extern stat() on VMS.\n\n1998-11-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* signame.c (init_sig): Check the sizes of signals being set up to\n\tavoid array overwrites (if the system headers have problems).\n\n1998-11-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (record_files): Clean up some indentation.\n\n1998-11-08  Han-Wen Nienhuys  <hanwen@cs.uu.nl>\n\n\t* rule.c (print_rule_data_base): Fix arguments to fatal() call.\n\n1998-10-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): If the command list resolves to no\n\tchars at all (e.g.: \"foo:;$(empty)\") then command_ptr is NULL;\n\tquit early.\n\n1998-10-12  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>\n\n\t* rule.c (print_rule_data_base): Ignore num_pattern_rules if it is\n\tzero.\n\n1998-10-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): Allow non-empty lines to expand to the\n\tempty string after variable, etc., expansion, and be ignored.\n\n1998-09-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Only add COMMAND.COM\n\t\"@echo off\" line for non-UNIXy shells.\n\n1998-09-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* w32/subproc/sub_proc.c: Add in missing HAVE_MKS_SHELL tests.\n\n1998-09-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): If we hit the \"missing separator\" error,\n\tcheck for the common case of 8 spaces instead of a TAB and give an\n\textra comment to help people out.\n\n1998-08-29  Paul Eggert  <eggert@twinsun.com>\n\n\t* configure.in (AC_STRUCT_ST_MTIM_NSEC):\n\tRenamed from AC_STRUCT_ST_MTIM.\n\n\t* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC):  Likewise.\n\tPort to UnixWare 2.1.2 and pedantic Solaris 2.6.\n\n\t* acconfig.h (ST_MTIM_NSEC):\n\tRenamed from HAVE_ST_MTIM, with a new meaning.\n\n\t* filedef.h (FILE_TIMESTAMP_FROM_S_AND_NS):\n\tUse new ST_MTIM_NSEC macro.\n\n1998-08-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (check_dep): For any intermediate file, not just\n\tsecondary ones, try implicit and default rules if no explicit\n\trules are given.  I'm not sure why this was restricted to\n\tsecondary rules in the first place.\n\n1998-08-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Special Targets): Update documentation for\n\t.INTERMEDIATE: if used with no dependencies, then it does nothing;\n\told docs said it marked all targets as intermediate, which it\n\tdidn't... and which would be silly :).\n\n\t* implicit.c (pattern_search): If we find a dependency in our\n\tinternal tables, make sure it's not marked intermediate before\n\taccepting it as a found_file[].\n\n1998-08-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* ar.c (ar_glob): Use existing alpha_compare() with qsort.\n\t(ar_glob_alphacompare): Remove it.\n\n\tModify Paul Eggert's patch so we don't abandon older systems:\n\n\t* configure.in: Warn the user if neither waitpid() nor wait3() is\n\tavailable.\n\n\t* job.c (WAIT_NOHANG): Don't syntax error on ancient hosts.\n\t(child_handler, dead_children): Define these if WAIT_NOHANG is not\n\tavailable.\n\t(reap_children): Only track the dead_children count if no\n\tWAIT_NOHANG.  Otherwise, it's a boolean.\n\n\t* main.c (main): Add back signal handler if no WAIT_NOHANG is\n\tavailable; only use default signal handler if it is.\n\n1998-08-20  Paul Eggert  <eggert@twinsun.com>\n\n\tInstall a more robust signal handling mechanism for systems which\n\tsupport it.\n\n\t* job.c (WAIT_NOHANG): Define to a syntax error if our host\n\tis truly ancient; this should never happen.\n\t(child_handler, dead_children): Remove.\n\t(reap_children): Don't try to keep separate track of how many\n\tdead children we have, as this is too bug-prone.\n\tJust ask the OS instead.\n\t(vmsHandleChildTerm): Fix typo in error message; don't mention\n\tchild_handler.\n\n\t* main.c (main): Make sure we're not ignoring SIGCHLD/SIGCLD;\n\tdo this early, before we could possibly create a subprocess.\n\tJust use the default behavior; don't have our own handler.\n\n1998-08-18  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* read.c (read_makefile) [__MSDOS__, WINDOWS32]: Add code to\n\trecognize library archive members when dealing with drive spec\n\tmess.  Discovery and initial fix by George Racz <gracz@mincom.com>.\n\n1998-08-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Check for stdlib.h explicitly (some hosts have it\n\tbut don't have STDC_HEADERS).\n\t* make.h: Use HAVE_STDLIB_H.  Clean up some #defines.\n\t* config.ami: Re-compute based on new config.h.in contents.\n\t* config.h-vms: Ditto.\n\t* config.h.W32: Ditto.\n\t* configh.dos: Ditto.\n\n\t* dir.c (find_directory) [WINDOWS32]: Windows stat() fails if\n\tdirectory names end with `\\' so strip it.\n\n1998-08-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Added copyright year to the printed copy.  Removed\n\tthe price from the manual.  Change the top-level reference to\n\trunning make to be \"Invoking make\" instead of \"make Invocation\",\n\tto comply with GNU doc standards.\n\n\t* make.h (__format__, __printf__): Added support for these in\n\t__attribute__ macro.\n\t(message, error, fatal): Use ... prototype form under __STDC__.\n\tAdd __format__ attributes for printf-style functions.\n\n\t* configure.in (AC_FUNC_VPRINTF): Check for vprintf()/_doprnt().\n\n\t* misc.c (message, error, fatal): Add preprocessor stuff to enable\n\tcreation of variable-argument functions with appropriate\n\tprototypes, that works with ANSI, pre-ANSI, varargs.h, stdarg.h,\n\tv*printf(), _doprnt(), or none of the above.  Culled from GNU\n\tfileutils and slightly modified.\n\t(makefile_error, makefile_error): Removed (merged into error() and\n\tfatal(), respectively).\n\t* amiga.c: Use them.\n\t* ar.c: Use them.\n\t* arscan.c: Use them.\n\t* commands.c: Use them.\n\t* expand.c: Use them.\n\t* file.c: Use them.\n\t* function.c: Use them.\n\t* job.c: Use them.\n\t* main.c: Use them.\n\t* misc.c: Use them.\n\t* read.c: Use them.\n\t* remake.c: Use them.\n\t* remote-cstms.c: Use them.\n\t* rule.c: Use them.\n\t* variable.c: Use them.\n\n\t* make.h (struct floc): New structure to store file location\n\tinformation.\n\t* commands.h (struct commands): Use it.\n\t* variable.c (try_variable_definition): Use it.\n\t* commands.c: Use it.\n\t* default.c: Use it.\n\t* file.c: Use it.\n\t* function.c: Use it.\n\t* misc.c: Use it.\n\t* read.c: Use it.\n\t* rule.c: Use it.\n\n1998-08-16  Paul Eggert  <eggert@twinsun.com>\n\n\t* filedef.h (FILE_TIMESTAMP_PRINT_LEN_BOUND): Add 10, for nanoseconds.\n\n1998-08-16  Paul Eggert  <eggert@twinsun.com>\n\n\t* filedef.h (FLOOR_LOG2_SECONDS_PER_YEAR): New macro.\n\t(FILE_TIMESTAMP_PRINT_LEN_BOUND): Tighten bound, and try to\n\tmake it easier to understand.\n\n1998-08-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (read_makefile): We've already unquoted any colon chars\n\tby the time we're done reading the targets, so arrange for\n\tparse_file_seq() on the target list to not do so again.\n\n1998-08-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Added glob/configure.in data.  We'll have the glob\n\tcode include the regular make config.h, rather than creating its\n\town.\n\n\t* getloadavg.c (main): Change return type to int.\n\n1998-08-01  Paul Eggert  <eggert@twinsun.com>\n\n\t* job.c (reap_children): Ignore unknown children.\n\n1998-07-31  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h, filedef.h, dep.h, rule.h, commands.h, remake.c:\n\tAdd prototypes for functions.  Some prototypes needed to be moved\n\tin order to get #include order reasonable.\n\n1998-07-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Added MIN/MAX.\n\t* filedef.h: Use them; remove FILE_TIMESTAMP_MIN.\n\n1998-07-30  Paul Eggert  <eggert@twinsun.com>\n\n        Add support for sub-second timestamp resolution on hosts that\n        support it (just Solaris 2.6, so far).\n\n\t* acconfig.h (HAVE_ST_MTIM, uintmax_t): New undefs.\n\t* acinclude.m4 (jm_AC_HEADER_INTTYPES_H, AC_STRUCT_ST_MTIM,\n        jm_AC_TYPE_UINTMAX_T): New defuns.\n\t* commands.c (delete_target): Convert file timestamp to\n        seconds before comparing to archive timestamp.  Extract mod\n        time from struct stat using FILE_TIMESTAMP_STAT_MODTIME.\n\t* configure.in (C_STRUCT_ST_MTIM, jm_AC_TYPE_UINTMAX_T): Add.\n        (AC_CHECK_LIB, AC_CHECK_FUNCS): Add clock_gettime.\n\t* file.c (snap_deps): Use FILE_TIMESTAMP, not time_t.\n        (file_timestamp_now, file_timestamp_sprintf): New functions.\n        (print_file): Print file timestamps as FILE_TIMESTAMP, not\n        time_t.\n\t* filedef.h: Include <inttypes.h> if available and if HAVE_ST_MTIM.\n        (FILE_TIMESTAMP, FILE_TIMESTAMP_STAT_MODTIME, FILE_TIMESTAMP_MIN,\n        FILE_TIMESTAMPS_PER_S, FILE_TIMESTAMP_FROM_S_AND_NS,\n        FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD, FILE_TIMESTAMP_S,\n        FILE_TIMESTAMP_NS, FILE_TIMESTAMP_PRINT_LEN_BOUND): New macros.\n        (file_timestamp_now, file_timestamp_sprintf): New decls.\n        (struct file.last_mtime, f_mtime, file_mtime_1, NEW_MTIME):\n        time_t -> FILE_TIMESTAMP.\n\t* implicit.c (pattern_search): Likewise.\n\t* vpath.c (vpath_search, selective_vpath_search): Likewise.\n\t* main.c (main): Likewise.\n\t* remake.c (check_dep, name_mtime, library_search, f_mtime): Likewise.\n        (f_mtime): Use file_timestamp_now instead of `time'.\n        Print file timestamp with file_timestamp_sprintf.\n\t* vpath.c (selective_vpath_search): Extract file time stamp from\n        struct stat with FILE_TIMESTAMP_STAT_MODTIME.\n\n1998-07-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.77 released.\n\n\t* dosbuild.bat: Change to DOS CRLF line terminators.\n\n\t* make-stds.texi: Update from latest version.\n\n\t* make.texinfo (Options Summary): Clarify that the -r option\n\taffects only rules, not builtin variables.\n\n1998-07-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Make __attribute__ resolve to empty for non-GCC _and_\n\tfor GCC pre-2.5.x.\n\n\t* misc.c (log_access): Print UID/GID's as unsigned long int for\n\tmaximum portability.\n\n\t* job.c (reap_children): Print PIDs as long int for maximum\n\tportability.\n\n1998-07-24  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS (*_INSTALL, *_UNINSTALL): Replace `true' with `:'.\n\n1998-07-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.76.94 released.\n\n1998-07-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h.W32.template: Make sure all the #defines of macros here\n\thave a value (e.g., use ``#define HAVE_STRING_H 1'' instead of\n\tjust ``#define HAVE_STRING_H''.  Keeps the preprocessor happy in\n\tsome contexts.\n\n\t* make.h: Remove __attribute__((format...)) stuff; using it with\n\tun-prototyped functions causes older GCC's to fail.\n\n\t* Version 3.76.93 released.\n\n1998-07-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (print_file_data_base): Fix average calculation.\n\n1998-07-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (die): Postpone the chdir() until after\n\tremove_intermediates() so that intermediate targets with relative\n\tpathnames are removed properly.\n\n1998-07-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* filedef.h (struct file): New flag: did we print an error or not?\n\n\t* remake.c (no_rule_error): New function to print error messages,\n\textraced from remake_file().\n\n\t* remake.c (remake_file): Invoke the new error print function.\n\t(update_file_1): Invoke the error print function if we see that we\n\talready tried this target and it failed, but that an error wasn't\n\tprinted for it.  This can happen if a file is included with\n\t-include or sinclude and couldn't be built, then later is also\n\tthe dependency of another target.  Without this change, make just\n\tsilently stops :-/.\n\n1998-07-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Removed \"beta\" version designator.\n\tUpdated ISBN for the next printing.\n\n1998-07-13  Paul Eggert  <eggert@twinsun.com>\n\n\t* acinclude.m4: New AC_LFS macro to determine if special compiler\n\tflags are needed to allow access to large files (e.g., Solaris 2.6).\n\t* configure.in: Invoke it.\n\n1998-07-08  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS: track changes in Makefile.in.\n\n1998-07-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* remote-cstms.c (start_remote_job): Move gethostbyaddr() to the\n\ttop so host is initialized early enough.\n\n\t* acinclude.m4: New file.  Need some special autoconf macros to\n\tcheck for network libraries (-lsocket, -lnsl, etc.) when\n\tconfiguring Customs.\n\n\t* configure.in (make_try_customs): Invoke new network libs macro.\n\n1998-07-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.76.92 released.\n\n\t* README.customs: Added to the distribution.\n\n\t* configure.in (make_try_customs): Rewrite to require an installed\n\tCustoms library, rather than looking at the build directory.\n\n\t* Makefile.am (man_MANS): Install make.1.\n\t* make.1: Renamed from make.man.\n\n\t* make.texinfo (Bugs): New mailing list address for GNU make bug\n\treports.\n\n1998-07-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.76.91 released.\n\n\t* default.c: Added default rule for new-style RCS master file\n\tstorage; ``% :: RCS/%''.\n\tAdded default rules for DOS-style C++ files with suffix \".cpp\".\n\tThey use the new LINK.cpp and COMPILE.cpp macros, which are set by\n\tdefault to be equal to LINK.cc and COMPILE.cc.\n\n1998-06-19  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* job.c (start_job_command): Reset execute_by_shell after an empty\n        command was skipped.\n\n1998-06-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Keep track of the temporary filename created when\n\treading a makefile from stdin (-f-) and attempt to remove it\n\tas soon as we know we're not going to re-exec.  If we are, add it\n\tto the exec'd make's cmd line with \"-o\" so the exec'd make doesn't\n\ttry to rebuild it.  We still have a hole: if make re-execs then\n\tthe temporary file will never be removed.  To fix this we'd need\n\ta brand new option that meant \"really delete this\".\n\t* AUTHORS, getopt.c, getopt1.c, getopt.h, main.c (print_version):\n\tUpdated mailing addresses.\n\n1998-06-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Andreas Luik <luik@isa.de> points out that the\n\tcheck for makefile :: rules with commands but no dependencies\n\tcausing a loop terminates incorrectly.\n\n\t* maintMakefile: Make a template for README.DOS to update version\n\tnumbers.\n\n1998-05-30  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>\n\n\t* remake.c (update_file_1): Don't free the memory for the\n\tdependency structure when dropping a circular dependency.\n\n1998-05-30  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* dir.c (file_exists_p, file_impossible_p, file_impossible)\n\t[__MSDOS__, WINDOWS32]: Retain trailing slash in \"d:/\", and make\n\tdirname of \"d:foo\" be \"d:\".\n\n1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>\n\n\t* read.c (read_makefile): Avoid running past EOS when scanning\n\tfile name after `include'.\n\n1998-05-26  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>\n\n\t* make.texinfo (Flavors): Correct description of conditional\n\tassignment, which is not equivalent to ifndef.\n\t(Setting): Likewise.\n\n1998-05-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* arscan.c (ar_name_equal): strncmp() might be implemented as a\n\tmacro, so don't put preprocessor conditions inside the arguments\n\tlist.\n\n1998-05-23  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* read.c (read_makefile) [__MSDOS__, WINDOWS32]: Skip colons in\n\tdrive specs when parsing targets, target-specific variables and\n\tstatic pattern rules.  A colon can only be part of drive spec if\n\tit is after the first letter in a token.\n\n1998-05-22  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* remake.c (f_mtime) [__MSDOS__]: Allow up to 3 sec of skew before\n\tyelling bloody murder.\n\n\t* dosbuild.bat: Use -DINCLUDEDIR= and -DLIBDIR= where appropriate.\n\n\t* read.c (parse_file_seq): Combine the special file-handling code\n\tfor WINDOWS32 and __MSDOS__ into a single snippet.\n\t(get_next_mword) [__MSDOS__, WINDOWS32]: Allow a word to include a\n\tcolon as part of a drive spec.\n\n\t* job.c (batch_mode_shell) [__MSDOS__]: Declare.\n\n1998-05-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* Version 3.76.90 released.\n\n1998-05-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Make Errors): Added a new appendix describing\n\tcommon errors make might generate and how to resolve them (or at\n\tleast more information on what they mean).\n\n\t* maintMakefile (NMAKEFILES): Use the new automake 1.3 feature\n\tto create a dependency file to construct Makefile.DOS, SMakefile,\n\tand NMakefile.\n\t(.dep_segment): Generate the dependency fragment file.\n\n1998-05-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.man: Minor changes.\n\n1998-05-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (pattern_matches,expand_function): Change variables\n\tand types named \"word\" to something else, to avoid compilation\n\tproblems on Cray C90 Unicos.\n\t* variable.h: Modify the function prototype.\n\n1998-05-11  Rob Tulloh  <rob_tulloh@tivoli.com>\n\n\t* job.c (construct_command_argv_internal) [WINDOWS32]: Turn off\n\techo when using a batch file, and make sure the command ends in a\n\tnewline.\n\n1998-05-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in (make_try_customs): Add some customs flags if the\n\tuser configures custom support.\n\n\t* job.c, remote-cstms.c: Merge in changes for custom library.\n\n\t* remote-stub.c: Add option to stub start_remote_job_p().\n\n1998-05-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): Install VPATH+ handling for archives; use\n\tthe hname field instead of the name field, and rehash when\n\tappropriate.\n\n1998-04-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* rule.c (print_rule_data_base): Print out any pattern-specific\n\tvariable values into the rules database.\n\n\t* variable.c (print_variable_set): Make this variable extern, to\n\tbe called by print_rule_data_base() for pattern-specific variables.\n\n\t* make.texinfo (Pattern-specific): Document pattern-specific\n\tvariables.\n\n1998-04-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* expand.c (variable_expand_for_file): Make static; its only\n\tcalled internally.  Look up this target in the list of\n\tpattern-specific variables and insert the variable set into the\n\tqueue to be searched.\n\n\t* filedef.h (struct file): Add a new field to hold the\n\tpreviously-found pattern-specific variable reference.  Add a new\n\tflag to remember whether we already searched for this file.\n\n\t* rule.h (struct pattern_var): New structure for storing\n\tpattern-specific variable values.  Define new function prototypes.\n\n\t* rule.c: New variables pattern_vars and last_pattern_var for\n\tstorage and handling of pattern-specific variable values.\n\t(create_pattern_var): Create a new pattern-specific variable value\n\tstructure.\n\t(lookup_pattern_var): Try to match a target to one of the\n\tpattern-specific variable values.\n\n1998-04-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo (Target-specific): Document target-specific\n\tvariables.\n\n1998-04-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (define_variable_in_set): Made globally visible.\n\t(lookup_variable_in_set): New function: like lookup_variable but\n\tlook only in a specific variable set.\n\t(target_environment): Use lookup_variable_in_set() to get the\n\tcorrect export rules for a target-specific variable.\n\t(create_new_variable_set): Create a new variable set, and just\n\treturn it without installing it anywhere.\n\t(push_new_variable_scope): Reimplement in terms of\n\tcreate_new_variable_set.\n\n\t* read.c (record_target_var): Like record_files, but instead of\n\tfiles create a target-specific variable value for each of the\n\tlisted targets.  Invoked from read_makefile() when the target line\n\tturns out to be a target-specific variable assignment.\n\n1998-04-19  Paul D. Smith <psmith@gnu.org>\n\n\t* read.c (read_makefile): Rewrite the entire target parsing\n\tsection to implement target-specific variables.  In particular, we\n\tcannot expand the entire line as soon as it's read in, since we\n\tmay want to evaluate parts of it with different variable contexts\n\tactive.  Instead, start expanding from the beginning until we find\n\tthe `:' (or `::'), then determine what kind of line this is and\n\tcontinue appropriately.\n\n\t* read.c (get_next_mword): New function to parse a makefile line\n\tby \"words\", considering an entire variable or function as one\n\tword.  Return the type read in, along with its starting position\n\tand length.\n\t(enum make_word_type): The types of words that are recognized by\n\tget_next_mword().\n\n\t* variable.h (struct variable): Add a flag to specify a per-target\n\tvariable.\n\n\t* expand.c: Make variable_buffer global.  We need this during the\n\tnew parsing of the makefile.\n\t(variable_expand_string): New function.  Like variable_expand(),\n\tbut start at a specific point in the buffer, not the beginning.\n\t(variable_expand): Rewrite to simply call variable_expand_string().\n\n1998-04-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_goal_chain): Allow the rebuilding makefiles\n\tstep to use parallel jobs.  Not sure why this was disabled:\n\thopefully we won't find out :-/.\n\n1998-04-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Set the CURDIR makefile variable.\n\t* make.texinfo (Recursion): Document it.\n\n1998-03-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* misc.c (makefile_fatal): If FILE is nil, invoke plain fatal().\n\t* variable.c (try_variable_definition): Use new feature.\n\n1998-03-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Don't pass included, rebuilt makefiles to\n\tre-exec'd makes with -o.  Reopens a possible loop, but it caused\n\ttoo many problems.\n\n1998-03-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (try_variable_definition): Implement ?=.\n\t* make.texinfo (Setting): Document it.\n\n1998-02-28  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* job.c (start_job_command): Reset execute_by_shell after an empty\n        command, like \":\", has been seen.\n\nTue Oct 07 15:00:00 1997  Phil Brooks <phillip_brooks@hp.com>\n\n\t* make.h [WINDOWS32]: make case sensitivity configurable\n\t* dir.c [WINDOWS32]: make case sensitivity configurable\n\t* README.W32: Document case sensitivity\n\t* config.ami: Share case warping code with Windows\n\nMon Oct  6 18:48:45 CDT 1997 Rob Tulloh <rob_tulloh@dev.tivoli.com>\n\n\t* w32/subproc/sub_proc.c: Added support for MKS toolkit shell\n\t(turn on HAVE_MKS_SHELL).\n\t* read.c [WINDOWS32]: Fixed a problem with multiple target rules\n \treported by Gilbert Catipon (gcatipon@tibco.com).  If multiple\n \tpath tokens in a rule did not have drive letters, make would\n \tincorrectly concatenate the 2 tokens together.\n\t* main.c/variable.c [WINDOWS32]: changed SHELL detection code to\n \tfollow what MSDOS did. In addition to watching for SHELL variable\n \tupdates, make's main will attempt to default the value of SHELL\n \tbefore and after makefiles are parsed.\n\t* job.c/job.h [WINDOWS32]: The latest changes made to enable use\n \tof the GNUWIN32 shell from make could cause make to fail due to a\n \tconcurrency condition between parent and child processes.  Make\n \tnow creates a batch file per job instead of trying to reuse the\n \tsame singleton batch file.\n\t* job.c/job.h/function.c/config.h.W32 [WINDOWS32]: Renamed macro\n \tfrom HAVE_CYGNUS_GNUWIN32_TOOLS to BATCH_MODE_ONLY_SHELL. Reworked\n \tlogic to reduce complexity. WINDOWS32 now uses the unixy_shell\n \tvariable to detect Bourne-shell compatible environments. There is\n \talso a batch_mode_shell variable that determines whether not\n \tcommand lines should be executed via script files. A WINDOWS32\n \tsystem with no sh.exe installed would have unixy_shell set to\n \tFALSE and batch_mode_shell set to TRUE. If you have a unixy shell\n \tthat does not behave well when invoking things via 'sh -c xxx',\n \tyou may want to turn on BATCH_MODE_ONLY_SHELL and see if things\n \timprove.\n\t* NMakefile: Added /D DEBUG to debug build flags so that unhandled\n \texceptions could be debugged.\n\nMon Oct  6 00:04:25 1997  Rob Tulloh <rob_tulloh@dev.tivoli.com>\n\n\t* main.c [WINDOWS32]: The function define_variable() does not\n \thandle NULL. Test before calling it to set Path.\n\t* main.c [WINDOWS32]: Search Path again after makefiles have been\n\tparsed to detect sh.exe.\n\t* job.c [WINDOWS32]: Added support for Cygnus GNU WIN32 tools.\n\tTo use, turn on HAVE_CYGNUS_GNUWIN32_TOOLS in config.h.W32.\n\t* config.h.W32: Added HAVE_CYGNUS_GNUWIN32_TOOLS macro.\n\nSun Oct  5 22:43:59 1997  John W. Eaton <jwe@bevo.che.wisc.edu>\n\n\t* glob/glob.c (glob_in_dir) [VMS]: Globbing shouldn't be\n\tcase-sensitive.\n\t* job.c (child_execute_job) [VMS]: Use a VMS .com file if the\n\tcommand contains a newline (e.g. from a define/enddef block).\n\t* vmsify.c (vmsify): Return relative pathnames wherever possible.\n\t* vmsify.c (vmsify): An input string like \"../..\" returns \"[--]\".\n\nWed Oct  1 15:45:09 1997  Rob Tulloh <rob_tulloh@tivoli.com>\n\n\t* NMakefile: Changed nmake to $(MAKE).\n\t* subproc.bat: Take the make command name from the command\n\tline. If no command name was given, default to nmake.\n\t* job.c [MSDOS, WINDOWS32]: Fix memory stomp: temporary file names\n\tare now always created in heap memory.\n\t* w32/subproc/sub_proc.c: New implementation of make_command_line()\n\twhich is more compatible with different Bourne shell implementations.\n\tDeleted the now obsolete fix_command_line() function.\n\t* main.c [WINDOWS32]: Any arbitrary spelling of Path can be\n\tdetected. Make will ensure that the special spelling `Path' is\n\tinserted into the environment when the path variable is propagated\n\twithin itself and to make's children.\n\t* main.c [WINDOWS32]: Detection of sh.exe was occurring too\n\tsoon. The 2nd check for the existence of sh.exe must come after\n\tthe call to read_all_makefiles().\n\nFri Sep 26 01:14:18 1997  <zinser@axp602.gsi.de>\n\n\t* makefile.com [VMS]: Fixed definition of sys.\n\t* readme.vms: Comments on what's changed lately.\n\nFri Sep 26 01:14:18 1997  John W. Eaton <jwe@bevo.che.wisc.edu>\n\n\t* read.c (read_all_makefiles): Allow make to find files named\n\t\"MAKEFILE\" with no extension on VMS.\n\t* file.c (lookup_file): Lowercase filenames on VMS.\n\n1997-09-29  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* read.c (read_makefile): Reworked target detection again; the old\n\tversion had an obscure quirk.\n\nFri Sep 19 09:20:49 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.76.1 released.\n\n\t* Makefile.am: Add loadavg files to clean rules.\n\n\t* configure.in (AC_OUTPUT): Remove stamp-config; no longer needed.\n\t* Makefile.ami (distclean): Ditto.\n\t* SMakefile (distclean): Ditto.\n\n\t* main.c (main): Arg count should be int, not char!  Major braino.\n\nTue Sep 16 10:18:22 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.76 released.\n\nTue Sep  2 10:07:39 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* function.c (expand_function): When processing $(shell...)\n  \ttranslate a CRLF (\\r\\n) sequence as well as a newline (\\n) to a\n \tspace.  Also remove an ending \\r\\n sequence.\n\t* make.texinfo (Shell Function): Document it.\n\nFri Aug 29 12:59:06 1997  Rob Tulloh  <rob_tulloh@tivoli.com>\n\n\t* w32/pathstuff.c (convert_Path_to_windows32): Fix problem where\n \tpaths which contain single character entries like `.' are not\n \thandled correctly.\n\n\t* README.W32: Document path handling issues on Windows systems.\n\nFri Aug 29 02:01:27 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.75.93.\n\nThu Aug 28 19:39:06 1997  Rob Tulloh  <rob_tulloh@tivoli.com>\n\n\t* job.c (exec_command) [WINDOWS32]: If exec_command() is invoked\n \tfrom main() to re-exec make, the call to execvp() would\n \tincorrectly return control to parent shell before the exec'ed\n \tcommand could run to completion. I believe this is a feature of\n \tthe way that execvp() is implemented on top of WINDOWS32 APIs. To\n \talleviate the problem, use the supplied process launch function in\n \tthe sub_proc library and suspend the parent process until the\n \tchild process has run.  When the child exits, exit the parent make\n \twith the exit code of the child make.\n\nThu Aug 28 17:04:47 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Makefile.DOS.template (distdir): Fix a line that got wrapped in\n\temail.\n\n\t* Makefile.am (loadavg): Give the necessary cmdline options when\n\tlinking loadavg.\n\n\t* configure.in: Check for pstat_getdynamic for getloadvg on HP.\n\n\t* job.c (start_job_command) [VMS, _AMIGA]: Don't perform empty\n\tcommand optimization on these systems; it doesn't make sense.\n\nWed Aug 27 17:09:32 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.75.92\n\nTue Aug 26 11:59:15 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* main.c (print_version): Add '97 to copyright years.\n\n\t* read.c (do_define): Check the length of the array before looking\n\tat a particular offset.\n\n\t* job.c (construct_command_argv_internal): Examine the last byte\n\tof the previous arg, not the byte after that.\n\nSat Aug 23 1997  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS.template: New file (converted to Makefile.DOS in\n\tthe distribution).\n\n\t* configure.bat: Rewrite to use Makefile.DOS instead of editing\n        Makefile.in.  Add support for building from outside of the source\n        directory.  Fail if the environment block is too small.\n\n\t* configh.dos: Use <sys/config.h>.\n\n\t* README.DOS: Update instructions.\n\nFri Aug 22 1997  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* job.c (start_job_command) [__MSDOS__]: Don't test for \"/bin/sh\"\n        literally, use value of unixy_shell instead.\n\n\t* filedef.h (NEW_MTIME): Use 1 less than maximum possible value if\n        time_t is unsigned.\n\nSat Aug 16 00:56:15 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* vmsify.c (vmsify, case 11): After translating `..' elements, set\n        nstate to N_OPEN if there are still more elements to process.\n        (vmsify, case 2): After translating `foo/bar' up to the slash,\n        set nstate to N_OPEN, not N_DOT.\n\nFri Aug  8 15:18:09 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* dir.c (vmsstat_dir): Leave name unmodified on exit.\n\t* make.h (PATH_SEPARATOR_CHAR): Set to comma for VMS.\n\t* vpath.c: Fix comments to refer to path separator, not colon.\n        (selective_vpath_search): Avoid Unixy slash handling for VMS.\n\nThu Aug  7 22:24:03 1997  John W. Eaton  <jwe@bevo.che.wisc.edu>\n\n\t* ar.c [VMS]: Don't declare ar_member_touch.\n\tDelete VMS version of ar_member_date.\n\tEnable non-VMS versions of ar_member_date and ar_member_date_1 for\n\tVMS too.\n\t* arscan.c (VMS_get_member_info): New function.\n\t(ar_scan): Provide version for VMS systems.\n\t(ar_name_equal): Simply compare name and mem on VMS systems.\n\tDon't define ar_member_pos or ar_member_touch on VMS systems.\n\n\t* config.h-vms (pid_t, uid_t): Don't define.\n\n\t* remake.c: Delete declaration of vms_stat.\n\t(name_mtime): Don't call vms_stat.\n\t(f_mtime) [VMS]: Funky time value manipulation no longer necessary.\n\n\t* file.c (print_file): [VMS] Use ctime, not cvt_time.\n\n\t* make.h [VMS]: Don't define POSIX.\n\n\t* makefile.com (filelist): Include ar and arscan.\n\tAlso include them in the link commands.\n\tDon't define NO_ARCHIVES in cc command.\n\n\t* makefile.vms (ARCHIVES, ARCHIVES_SRC): Uncomment.\n\t(defines): Delete NO_ARCHIVES from list.\n\n\t* remake.c (f_mtime): Only check to see if intermediate file is\n\tout of date if it also exists (i.e., mtime != (time_t) -1).\n\n\t* vmsdir.h (u_long, u_short): Skip typedefs if using DEC C.\n\nFri Jun 20 23:02:07 1997  Rob Tulloh  <rob_tulloh@tivoli.com>\n\n\t* w32/subproc/sub_proc.c: Get W32 sub_proc to handle shebang\n\t(#!/bin/sh) in script files correctly.\n\tFixed a couple of memory leaks.\n\tFixed search order in find_file() (w32/subproc/sub_proc.c) so that\n\tfiles with extensions are preferred over files without extensions.\n\tAdded search for files with .cmd extension too.\n\t* w32/subproc/misc.c (arr2envblk): Fixed memory leak.\n\nMon Aug 18 09:41:08 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.75.91\n\nFri Aug 15 13:50:54 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* read.c (do_define): Remember to count the newline after the endef.\n\nThu Aug 14 23:14:37 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* many: Rewrote builds to use Automake 1.2.\n\n\t* AUTHORS: New file.\n\t* maintMakefile: Contains maintainer-only make snippets.\n\t* GNUmakefile: This now only runs the initial auto* tools.\n\t* COPYING,texinfo.tex,mkinstalldirs,install-sh: Removed (obtained\n\tautomatically by automake).\n\t* compatMakefile: Removed (not needed anymore).\n\t* README,build.sh.in: Removed (built from templates).\n\t* config.h.in,Makefile.in: Removed (built by tools).\n\nWed Aug 13 02:22:08 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* make.texinfo: Updates for DOS/Windows information (Eli Zaretskii)\n\t* README,README.DOS: Ditto.\n\n\t* remake.c (update_file_1,f_mtime): Fix GPATH handling.\n\t* vpath.c (gpath_search): Ditto.\n\n\t* file.c (rename_file): New function: rehash, but also rename to\n\tthe hashname.\n\t* filedef.h: Declare it.\n\n\t* variable.c (merge_variable_set_lists): Remove free() of variable\n\tset; since various files can share variable sets we don't want to\n\tfree them here.\n\nTue Aug 12 10:51:54 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* configure.in: Require autoconf 2.12\n\n\t* make.texinfo: Replace all \"cd subdir; $(MAKE)\" examples with a\n\tmore stylistically correct \"cd subdir && $(MAKE)\".\n\n\t* main.c: Global variable `clock_skew_detected' defined.\n\t(main): Print final warning if it's set.\n\t* make.h: Declare it.\n\t* remake.c (f_mtime): Test and set it.\n\n\t* job.c (start_job_command): Add special optimizations for\n \t\"do-nothing\" rules, containing just the shell no-op \":\".  This is\n \tuseful for timestamp files and can make a real difference if you\n \thave a lot of them (requested by Fergus Henderson <fjh@cs.mu.oz.au>).\n\n\t* configure.in,Makefile.in: Rewrote to use the new autoconf\n\tprogram_transform_name macro.\n\n\t* function.c (function_strip): Strip newlines as well as spaces\n\tand TABs.\n\nFri Jun  6 23:41:04 1997  Rob Tulloh <rob_tulloh@tivoli.com>\n\n\t* remake.c (f_mtime): Datestamps on FAT-based files are rounded to\n\teven seconds when stored, so if the date check fails on WINDOWS32\n\t systems, see if this \"off-by-one\" error is the problem.\n\n\t* General: If your TZ environment variable is not set correctly\n\tthen all your timestamps will be off by hours.  So, set it!\n\nMon Apr  7 02:06:22 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* Version 3.75.1\n\n\t* compatMakefile (objs): Define & use the $(GLOB) variable so\n\tthat it's removed correctly from build.sh.in when it's built.\n\n\t* configure.in: On Solaris we can use the kstat_*() functions to\n\tget load averages without needing special permissions.  Add a\n\tcheck for -lkstat to see if we have it.\n\n\t* getloadavg.c (getloadavg): Use HAVE_LIBKSTAT instead of SUN5 as\n\tthe test to enable kstat_open(), etc. processing.\n\nFri Apr  4 20:21:18 1997  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* <lots>: Fixes to work in the DJGPP DOS environment.\n\nMon Mar 31 02:42:52 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* function.c (expand_function): Added new function $(wordlist).\n\n\t* make.texinfo (Filename Functions): Document $(wordlist) function.\n\n\t* vpath.c (build_vpath_lists): Construct the GPATH variable\n\tinformation in the same manner we used to construct VPATH.\n\t(gpath_search): New function to search GPATH.\n\n\t* make.h: Declare the new function.\n\n\t* remake.c (update_file_1): Call it, and keep VPATH if it's found.\n\n\t* make.texinfo (Search Algorithm): Document GPATH variable.\n\nSun Mar 30 20:57:16 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* main.c (handle_non_switch_argument): Defined the MAKECMDGOALS\n\tvariable to contain the user options passed in on the cmd line.\n\n\t* make.texinfo (Goals): Document MAKECMDGOALS variable.\n\n\t* remake.c (f_mtime): Print a warning if we detect a clock skew\n\terror, rather than failing.\n\n\t* main.c (main): If we rebuild any makefiles and need to re-exec,\n\tadd \"-o<mkfile>\" options for each makefile rebuilt to avoid\n\tinfinite looping.\n\nFri Mar 28 15:26:05 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* job.c (construct_command_argv_internal): Track whether the last\n\targ in the cmd string was empty or not (Roland).\n\t(construct_command_argv_internal): If the shell line is empty,\n\tdon't do anything (Roland).\n\n\t* glob/glob.h,glob/glob.c,glob/fnmatch.c,glob/fnmatch.h: Install\n\tthe latest changes from the GLIBC version of glob (Ulrich Drepper).\n\n\t* getloadavg.c,make-stds.texi: New version (Roland).\n\n\t* (ALL): Changed WIN32 to W32 or WINDOWS32 (RMS).\n\nMon Mar 24 15:33:34 1997  Rob Tulloh  <rob_tulloh@tivoli.com>\n\n\t* README.W32: Describe preliminary FAT support.\n\n\t* build_w32.bat: Use a variable for the final exe name.\n\n\t* dir.c (find_directory): W32: Find the filesystem type.\n\t(dir_contents_file_exists_p): W32: for FAT filesystems, always\n\trehash since FAT doesn't change directory mtime on change.\n\n\t* main.c (handle_runtime_exceptions): W32: Add an\n \tUnhandledExceptionFilter so that when make bombs due to ^C or a\n \tbug, it won't cause a GUI requestor to pop up unless debug is\n \tturned on.\n\t(main): Call it.\n\nMon Mar 24 00:57:34 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* configure.in, config.h.in, config.ami, config.h-vms, config.h.w32:\n \tCheck for memmove() function.\n\n\t* make.h (bcopy): If memmove() available, define bcopy() to use it.\n\tOtherwise just use bcopy().  Don't use memcpy(); it's not guaranteed\n\tto handle overlapping moves.\n\n\t* read.c (read_makefile): Fix some uninitialized memory reads\n\t(reported by Purify).\n\n\t* job.c (construct_command_argv_internal): Use bcopy() not\n\tstrcpy(); strcpy() isn't guaranteed to handle overlapping moves.\n\n\t* Makefile.in: Change install-info option ``--infodir'' to\n\t``--info-dir'' for use with new texinfo.\n\n\t* function.c (expand_function): $(basename) and $(suffix) should\n\tonly search for suffixes as far back as the last directory (e.g.,\n\tonly the final filename in the path).\n\nSun Mar 23 00:13:05 1997  Paul D. Smith  <psmith@baynetworks.com>\n\n\t* make.texinfo: Add @dircategory/@direntry information.\n\t(Top): Remove previous reference to (dir) (from RMS).\n\t(Static Usage): Add \"all:\" rule to example.\n\t(Automatic Dependencies): fix .d file creation example.\n\n\t* Install VPATH+ patch:\n\n\t* filedef.h (struct file): Add in hname field to store the hashed\n        filename, and a flag to remember if we're using the vpath filename\n\tor not.  Renamed a few functions for more clarity.\n\n\t* file.c (lookup_file,enter_file,file_hash_enter): Store filenames\n\tin the hash table based on their \"hash name\".  We can change this\n\twhile keeping the original target in \"name\".\n\t(rehash_file): Renamed from \"rename_file\" to be more accurate.\n\tChanges the hash name, but not the target name.\n\n\t* remake.c (update_file_1): Modify -d output for more detailed\n \tVPATH info.  If we don't need to rebuild, use the VPATH name.\n\t(f_mtime): Don't search for vpath if we're ignoring it.  Call\n \trenamed function rehash_file.  Call name_mtime instead of\n \tfile_mtime, to avoid infinite recursion since the file wasn't\n \tactually renamed.\n\n\t* implicit.c (pattern_search): if we find an implicit file in\n\tVPATH, save the original name not the VPATH name.\n\n\t* make.texinfo (Directory Search): Add a section on the new VPATH\n\tfunctionality.\n\nSun Dec  1 18:36:04 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>\n\n\t* dir.c (file_exists_p, file_impossible, file_impossible_p): If\n\tdirname is empty replace it by the name of the root directory.\n\tNote that this doesn't work (yet) for W32, Amiga, or VMS.\n\nTue Oct 08 13:57:03 1996  Rob Tulloh  <tulloh@tivoli.com>\n\n\t* main.c (main): W32 bug fix for PATH vars.\n\nTue Sep 17 1996  Paul Eggert  <eggert@twinsun.com>\n\n\t* filedef.h (NEW_MTIME): Don't assume that time_t is a signed\n \t32-bit quantity.\n\n\t* make.h: (CHAR_BIT, INTEGER_TYPE_SIGNED, INTEGER_TYPE_MAXIMUM,\n \tINTEGER_TYPE_MINIMUM): New macros.\n\nTue Aug 27 01:06:34 1996  Roland McGrath  <roland@baalperazim.frob.com>\n\n\t* Version 3.75 released.\n\n\t* main.c (print_version): Print out bug-reporting address.\n\nMon Aug 26 19:55:47 1996  Roland McGrath  <roland@baalperazim.frob.com>\n\n\t* main.c (print_data_base): Don't declare ctime; headers do it for us\n \talready.\n\nSun Jul 28 15:37:09 1996  Rob Tulloh (tulloh@tivoli.com)\n\n\t* w32/pathstuff.c: Turned convert_vpath_to_w32() into a\n\treal function. This was done so that VPATH could contain\n\twhite space separated pathnames. Please note that directory\n\tpaths (in VPATH/vpath context) containing white space are not\n\tsupported (just as they are not under Unix). See README.W32\n\tfor suggestions.\n\n\t* w32/include/pathstuff.h: Added prototype for the new\n\tfunction convert_vpath_to_w32. Deleted macro for same.\n\n\t* README.W32: Added some notes about why I chose not to try\n\tand support pathnames which contain white space and some\n\tworkaround suggestions.\n\nThu Jul 25 19:53:31 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* GNUmakefile (mkdep-nolib): Use -MM option unconditionally.\n\n\t* Version 3.74.7.\n\n\t* main.c (define_makeflags): Back up P to point at null terminator\n\twhen killing final space and dash before setting MFLAGS.\n\n\tFrom Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE>:\n\t* dir.c [__MSDOS__ && DJGPP > 1]: Include <libc/dosio.h> and defin\n\t`__opendir_flags' initialized to 0.\n\t(dosify) [__MSDOS__ && DJGPP > 1]: Return name unchanged if _USE_LFN.\n\t(find_directory) [__MSDOS__ && DJGPP > 1]: If _USE_LGN, set\n\t__opendir_flags to __OPENDIR_PRESERVE_CASE.\n\n\t* vmsfunctions.c (vms_stat): `sys$dassgn (DevChan);' added by kkaempf.\n\n\t* GNUmakefile (w32files): Add NMakefile.\n\n\t* NMakefile (LDFLAGS_debug): Value fixed by tulloh.\n\nSat Jul 20 12:32:10 1996  Klaus Kmpf (kkaempf@progis.de)\n\n\t* remake.c (f_mtime) [VMS]: Add missing `if' conditional for future\n\tmodtime check.\n\t* config.h-vms, makefile.vms, readme.vms, vmsify.c: Update address.\n\nSat Jul 20 05:29:43 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* configure.in: Require autoconf 2.10 or later.\n\nFri Jul 19 16:57:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* Version 3.74.6.\n\n\t* GNUmakefile (w32files): New variable.\n\t(distfiles): Add it.\n\t* w32: Updated by Rob Tulloh.\n\n\t* makefile.vms (LOADLIBES): Fix typo.\n\nSun Jul 14 12:59:27 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* job.c (construct_command_argv_internal): Fix up #else, #endifs.\n\n\t* configh.dos: Define HAVE_DIRENT_H instead of DIRENT.\n\n\t* remake.c (f_mtime): Don't compare MTIME to NOW if MTIME == -1.\n\n\t* Version 3.74.5.\n\n\t* main.c (main): Exit with status 2 when update_goal_chain returns 2.\n\nSat Jun 22 14:56:05 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* configure.in: Don't check for _sys_siglist.\n\t* make.h [HAVE__SYS_SIGLIST]: Don't test this; just punt if there is\n\tno strsignal or sys_siglist.\n\n\t* read.c (conditional_line): Strip ws in `ifeq (a , b)' so it is the\n\tsame as `ifeq (a, b)'.\n\n\t* job.c (reap_children): Don't call die if handling_fatal_signal.\n\n\t* file.c (file_hash_enter): Allow renaming :: to : when latter is\n\tnon-target, or : to :: when former is non-target.\n\n\t* job.c (start_job_command): Call block_sigs.\n\t(block_sigs): New function, broken out of start_job_command.\n\t(reap_children): Block fatal signals around removing dead child from\n\tchain and adjusting job_slots_used.\n\t* job.h: Declare block_sigs.\n\n\t* remote-stub.c (remote_setup, remote_cleanup): New (empty) functions.\n\t* main.c (main): Call remote_setup.\n\t(die): Call remote_cleanup.\n\n\t* job.c (reap_children): Quiescent value of shell_function_pid is\n\tzero, not -1.\n\n\t* main.c (print_version): Add 96 to copyright years.\n\nSat Jun 15 20:30:01 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>\n\n\t* read.c (find_char_unquote): Avoid calling strlen on every call\n\tjust to throw away the value most of the time.\n\nSun Jun  2 12:24:01 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* main.c (decode_env_switches): Prepend '-' to ARGV[1] if it contains\n\tno '=', regardless of ARGC.\n\t(define_makeflags): Elide leading '-' from MAKEFLAGS value if first\n\tword is short option, regardless of WORDS.\n\nWed May 22 17:24:51 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* makefile.vms: Set LOADLIBES.\n\t* makefile.com (link_using_library): Fix typo.\n\nWed May 15 17:37:26 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* dir.c (print_dir_data_base): Use %ld dev and ino and cast them to\n\tlong.\n\nWed May 15 10:14:14 CDT 1996  Rob Tulloh  <tulloh@tivoli.com>\n\n\t* dir.c: W32 does not support inode. For now, fully qualified\n\tpathname along with st_mtime will be keys for files.\n\tFixed problem where vpath can be confused when files\n\tare added to a directory after the directory has already been\n\tread in. The code now attempts to reread the directory if it\n\tdiscovers that the datestamp on the directory has changed since\n\tit was cached by make. This problem only seems to occur on W32\n\tright now so it is lumped under port #ifdef WINDOWS32.\n\n\t* function.c: W32: call subproc library (CreateProcess()) instead of\n\tfork/exec.\n\n\t* job.c: W32: Added the code to do fork/exec/waitpid style processing\n\ton W32 systems via calls to subproc library.\n\n\t* main.c: W32: Several things added here. First, there is code\n\tfor dealing with PATH and SHELL defaults. Make tries to figure\n\tout if the user has %PATH% set in the environment and sets it to\n\t%Path% if it is not set already. Make also looks to see if sh.exe\n\tis anywhere to be found. Code path through job.c will change\n\tbased on existence of a working Bourne shell. The checking for\n\tdefault shell is done twice: once before makefiles are read in\n\tand again after. Fall back to MSDOS style execution mode if no sh.exe\n\tis found. Also added some debug support that allows user to pause make\n\twith -D switch and attach a debugger. This is especially useful for\n\tdebugging recursive calls to make where problems appear only in the\n\tsub-make.\n\n\t* make.h: W32: A few macros and header files for W32 support.\n\n\t* misc.c: W32: Added a function end_of_token_w32() to assist\n\tin parsing code in read.c.\n\n\t* read.c: W32: Fixes similar to MSDOS which allow colon to\n\tappear in filenames. Use of colon in filenames would otherwise\n\tconfuse make.\n\n\t* remake.c: W32: Added include of io.h to eliminate compiler\n\twarnings. Added some code to default LIBDIR if it is not set\n\ton W32.\n\n\t* variable.c: W32: Added support for detecting Path/PATH\n\tand converting them to semicolon separated lists for make's\n\tinternal use. New function sync_Path_environment()\n\twhich is called in job.c and function.c before creating a new\n\tprocess. Caller must set Path in environment since we don't\n\thave fork() to do this for us.\n\n\t* vpath.c: W32: Added detection for filenames containing\n\tforward or backward slashes.\n\n\t* NMakefile: W32: Visual C compatible makefile for use with nmake.\n\tUse this to build GNU make the first time on Windows NT or Windows 95.\n\n\t* README.W32: W32: Contains some helpful notes.\n\n\t* build_w32.bat: W32: If you don't like nmake, use this the first\n\ttime you build GNU make on Windows NT or Windows 95.\n\n\t* config.h.W32: W32 version of config.h\n\n\t* subproc.bat: W32: A bat file used to build the\n\tsubproc library from the top-level NMakefile. Needed because\n\tWIndows 95 (nmake) doesn't allow you to cd in a make rule.\n\n\t* w32/include/dirent.h\n\t* w32/compat/dirent.c: W32: opendir, readdir, closedir, etc.\n\n\t* w32/include/pathstuff.h: W32: used by files needed functions\n\tdefined in pathstuff.c (prototypes).\n\n\t* w32/include/sub_proc.h: W32: prototypes for subproc.lib functions.\n\n\t* w32/include/w32err.h: W32: prototypes for w32err.c.\n\n\t* w32/pathstuff.c: W32: File and Path/Path conversion functions.\n\n\t* w32/subproc/build.bat: W32: build script for subproc library\n\tif you don't wish to use nmake.\n\n\t* w32/subproc/NMakefile: W32: Visual C compatible makefile for use\n\twith nmake. Used to build subproc library.\n\n\t* w32/subproc/misc.c: W32: subproc library support code\n\t* w32/subproc/proc.h: W32: subproc library support code\n\t* w32/subproc/sub_proc.c: W32: subproc library source code\n\t* w32/subproc/w32err.c: W32: subproc library support code\n\nMon May 13 14:37:42 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* Version 3.74.4.\n\n\t* GNUmakefile (vmsfiles): Fix typo.\n\n\t* GNUmakefile (amigafiles): Add amiga.h.\n\nSun May 12 19:19:43 1996  Aaron Digulla   <digulla@fh-konstanz.de>\n\n\t* dir.c: New function: amigafy() to fold filenames\n\tChanges HASH() to HASHI() to fold filenames on Amiga.\n\tStringcompares use strieq() instead of streq()\n\tThe current directory on Amiga is \"\" instead of \".\"\n\t* file.c: Likewise.\n\n\t* amiga.c: New function wildcard_expansion(). Allows to use\n\tAmiga wildcards with $(wildcard )\n\n\t* amiga.h: New file. Prototypes for amiga.c\n\n\t* function.c: Use special function wildcard_expansion() for\n\t$(wildcard ) to allow Amiga wildcards\n\tThe current directory on Amiga is \"\" instead of \".\"\n\n\t* job.c: No Pipes on Amiga, too\n\t(load_too_high) Neither on Amiga\n\tENV variable on Amiga are in a special directory and are not\n\tpassed as third argument to main().\n\n\t* job.h: No envp on Amiga\n\n\t* make.h: Added HASHI(). This is the same as HASH() but converts\n\tit's second parameter to lowercase on Amiga to fold filenames.\n\n\t* main.c: (main), variable.c Changed handling of ENV-vars. Make\n\tstores now the names of the variables only and reads their contents\n\twhen they are accessed to reflect that these variables are really\n\tglobal (i.e., they CAN change WHILE make runs !) This handling is\n\tmade in lookup_variable()\n\n\t* Makefile.ami: renamed file.h to filedep.h\n\tUpdated dependencies\n\n\t* read.c: \"find_semicolon\" is declared as static but never defined.\n\tNo difference between Makefile and makefile on Amiga; added\n\tSMakefile to *default_makefiles[].\n\t(read_makefile) SAS/C want's two_colon and pattern_percent be set\n\tbefore use.\n\tThe current directory on Amiga is \"\" instead of \".\"\n\tStrange #endif moved.\n\n\t* README.Amiga: updated feature list\n\n\t* SMakefile: Updated dependencies\n\n\t* variable.c: Handling of ENV variable happens inside lookup_variable()\n\nSat May 11 17:58:32 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* variable.c (try_variable_definition): Count parens in lhs variable\n\trefs to avoid seeing =/:=/+= inside a ref.\n\nThu May  9 13:54:49 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* commands.c (fatal_error_signal) [SIGQUIT]: Make SIGQUIT check\n\tconditional.\n\n\t* main.c (main): Use unsigned for fread return.\n\n\t* read.c (parse_file_seq): Use `int' for char arg to avoid widening\n\tconflict issues.\n\t* dep.h: Fix prototype.\n\n\t* function.c (expand_function) [_AMIGA]: Fix some typos.\n\t(patsubst_expand): Make len vars unsigned.\n\n\t* GNUmakefile (globfiles): Add AmigaDOS support files.\n\t(distfiles): Add $(amigafiles).\n\t(amigafiles): New variable.\n\nThu Nov  7 10:18:16 1995  Aaron Digulla   <digulla@fh-konstanz.de>\n\n\t* Added Amiga support in commands.c, dir.c, function.c,\n\tjob.c, main.c, make.h, read.c, remake.c\n\t* commands.c: Amiga has neither SIGHUP nor SIGQUIT\n\t* dir.c: Amiga has filenames with Upper- and Lowercase,\n\tbut \"FileName\" is the same as \"filename\". Added strieq()\n\twhich is use to compare filenames. This is like streq()\n\ton all other systems. Also there is no such thing as\n\t\".\" under AmigaDOS.\n\t* function.c: On Amiga, the environment is not passed as envp,\n\tthere are no pipes and Amiga can't fork. Use my own function\n\tto create a new child.\n\t* job.c: default_shell is \"\" (The system automatically chooses\n\ta shell for me). Have to use the same workaround as MSDOS for\n\trunning batch commands. Added HAVE_SYS_PARAM_H. NOFILE isn't\n\tknown on Amiga. Cloned code to run children from MSDOS. Own\n\tversion of sh_chars[] and sh_cmds[]. No dup2() or dup() on Amiga.\n\t* main.c: Force stack to 20000 bytes. Read environment from ENV:\n\tdevice. On Amiga, exec_command() does return, so I exit()\n\tafterwards.\n\t* make.h: Added strieq() to compare filenames.\n\t* read.c: Amiga needs special extension to have passwd. Only\n\tone include-dir. \"Makefile\" and \"makefile\" are the same.\n\tAdded \"SMakefile\".  Added special code to handle device names (xxx:)\n\tand \"./\" in rules.\n\t* remake.c: Only one lib-dir. Amiga link-libs are named \"%s.lib\"\n\tinstead of \"lib%s.a\".\n\t* main.c, rule.c, variable.c: Avoid floats at all costs.\n\t* vpath.c: Get rid of as many alloca()s as possible.\n\nThu May  9 13:20:43 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>\n\n\t* read.c (read_makefile): Grok `sinclude' as alias for `-include'.\n\nWed Mar 20 09:52:27 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>\n\n\t* GNUmakefile (vmsfiles): New variable.\n\t(distfiles): Include $(vmsfiles).\n\nTue Mar 19 20:21:34 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>\n\n\tMerged VMS port from Klaus Kaempf <kkaempf@didymus.rmi.de>.\n\t* make.h (PARAMS): New macro.\n\t* config.h-vms: New file.\n\t* makefile.com: New file.\n\t* makefile.vms: New file.\n\t* readme.vms: New file.\n\t* vmsdir.h: New file.\n\t* vmsfunctions.c: New file.\n\t* vmsify.c: New file.\n\t* file.h: Renamed to filedef.h to avoid conflict with VMS system hdr.\n\t* ar.c: Added prototypes and changes for VMS.\n\t* commands.c: Likewise.\n\t* commands.h: Likewise.\n\t* default.c: Likewise.\n\t* dep.h: Likewise.\n\t* dir.c: Likewise.\n\t* expand.c: Likewise.\n\t* file.c: Likewise.\n\t* function.c: Likewise.\n\t* implicit.c: Likewise.\n\t* job.c: Likewise.\n\t* job.h: Likewise.\n\t* main.c: Likewise.\n\t* make.h: Likewise.\n\t* misc.c: Likewise.\n\t* read.c: Likewise.\n\t* remake.c: Likewise.\n\t* remote-stub.c: Likewise.\n\t* rule.c: Likewise.\n\t* rule.h: Likewise.\n\t* variable.c: Likewise.\n\t* variable.h: Likewise.\n\t* vpath.c: Likewise.\n\t* compatMakefile (srcs): Rename file.h to filedef.h.\n\nSat Aug 19 23:11:00 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>\n\n\t* remake.c (check_dep): For a secondary file, try implicit and\n\tdefault rules if appropriate.\n\nWed Aug  2 04:29:42 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>\n\n\t* remake.c (check_dep): If an intermediate file exists,\n\tdo consider its actual date.\n\nSun Jul 30 00:49:53 1995  Richard Stallman  <rms@mole.gnu.ai.mit.edu>\n\n\t* file.h (struct file): New field `secondary'.\n\t* file.c (snap_deps): Check for .INTERMEDIATE and .SECONDARY.\n\t(remove_intermediates): Don't delete .SECONDARY files.\n\nSat Mar  2 16:26:52 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>\n\n\t* compatMakefile (srcs): Add getopt.h; prepend $(srcdir)/ to getopt*.\n\nFri Mar  1 12:04:47 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>\n\n\t* Version 3.74.3.\n\n\t* remake.c (f_mtime): Move future modtime check before FILE is\n\tclobbered by :: loop.\n\n\t* dir.c: Use canonical code from autoconf manual for dirent include.\n\t[_D_NAMLEN]: Redefine NAMLEN using this.\n\t(dir_contents_file_exists_p): Use NAMLEN macro.\n\t(read_dirstream) [_DIRENT_HAVE_D_NAMLEN]: Only set d_namlen #if this.\n\n\t* compatMakefile (objs): Add missing backslash.\n\nWed Feb 28 03:56:20 1996  Roland McGrath  <roland@charlie-brown.gnu.ai.mit.edu>\n\n\t* default.c (default_terminal_rules): Remove + prefix from RCS cmds.\n\t(default_variables): Put + prefix in $(CHECKOUT,v) value instead.\n\n\t* remake.c (f_mtime): Check for future timestamps; give error and mark\n\tfile as \"failed to update\".\n\nFri Jan 12 18:09:36 1996  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c: Don't declare unblock_sigs; job.h already does.\n\nSat Jan  6 16:24:44 1996  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* acconfig.h (HAVE_SYSCONF_OPEN_MAX): #undef removed.\n\n\t* job.c (NGROUPS_MAX): Don't try to define this macro.\n\nFri Dec 22 18:44:44 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* compatMakefile (GETOPT, GETOPT_SRC, GLOB): Variables removed.\n\t(objs, srcs): Include their values here instead of references.\n\nThu Dec 14 06:21:29 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.74.2.\n\n\t* job.c (reap_children): Call unblock_sigs after start_job_command.\n\nThu Dec 14 07:22:03 1995  Roland McGrath  <roland@duality.gnu.ai.mit.edu>\n\n\t* dir.c (dir_setup_glob): Don't use lstat; glob never calls it anyway.\n\tAvoid & before function names to silence bogus sunos4 compiler.\n\n\t* configure.in: Remove check for `sysconf (_SC_OPEN_MAX)'.\n\nTue Dec 12 00:48:42 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.74.1.\n\n\t* dir.c (read_dirstream): Fix braino: fill in the buffer when not\n\treallocating it!\n\nMon Dec 11 22:26:15 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* misc.c (collapse_continuations): Fix skipping of trailing \\s so\n\tit can never dereference before the beginning of the array.\n\n\t* read.c (find_semicolon): Function removed.\n\t(read_makefile): Don't use find_semicolon or remove_comments for\n\trule lines.  Use find_char_unquote directly and handle quoted comments\n\tproperly.\n\n\t* default.c: Remove all [M_XENIX] code.\n\n\t* dir.c [HAVE_D_NAMLEN]: Define this for __GNU_LIBRARY__ > 1.\n\t(D_NAMLEN): Macro removed.\n\t(FAKE_DIR_ENTRY): New macro.\n\t(dir_contents_file_exists_p): Test HAVE_D_NAMLEN instead of using\n\tD_NAMLEN.\n\t(read_dirstream): Return a struct dirent * for new glob interface.\n\t(init_dir): Function removed.\n\t(dir_setup_glob): New function.\n\t* main.c (main): Don't call init_dir.\n\t* read.c (multi_glob): Call dir_setup_glob on our glob_t and use\n\tGLOB_ALTDIRFUNC flag.\n\n\t* misc.c (safe_stat): Function removed.\n\t* read.c, commands.c, remake.c, vpath.c: Use plain stat instead of\n\tsafe_stat.\n\nSat Nov 25 20:35:18 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c [HAVE_UNION_WAIT]: Include sys/wait.h.\n\n\t* main.c (log_working_directory): Made global.\n\tPrint entering msg only once.\n\t* make.h (log_working_directory): Declare it.\n\t* misc.c (message): Take new arg PREFIX.  Print \"make: \" only if\n\tnonzero.  Call log_working_directory.\n\t* remake.c: Pass new arg in `message' calls.\n\t* job.c (start_job_command): Pass new arg to `message'; fix\n\tinverted test in that call.\n\nTue Nov 21 19:01:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c (start_job_command): Use `message' to print the command,\n\tand call it with null if the command is silent.\n\t* remake.c (touch_file): Use message instead of printf.\n\nTue Oct 10 14:59:30 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (enter_command_line_file): Barf if NAME is \"\".\n\nSat Sep  9 06:33:20 1995  Roland McGrath  <roland@whiz-bang.gnu.ai.mit.edu>\n\n\t* commands.c (delete_target): Ignore unlink failure if it is ENOENT.\n\nThu Aug 17 15:08:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* configure.in: Don't check for getdtablesize.\n\t* job.c (getdtablesize): Remove decls and macros.\n\nThu Aug 10 19:10:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (define_makeflags): Omit command line variable\n \tdefinitions from MFLAGS value.\n\n\t* arscan.c (ar_scan) [AIAMAG]: Check for zero MEMBER_OFFSET,\n \tindicating a valid, but empty, archive.\n\nMon Aug  7 15:40:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* dir.c (file_impossible_p): Correctly reset FILENAME to name\n \twithin directory before hash search.\n\n\t* job.c (child_error): Do nothing if IGNORED under -s.\n\n\t* job.c (exec_command): Correctly use ARGV[0] for script name when\n \trunning shell directly.\n\nTue Aug  1 14:39:14 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c (child_execute_job): Close STDIN_FD and STDOUT_FD after\n \tdup'ing from them.  Don't try to close all excess descriptors;\n \tgetdtablesize might return a huge value.  Any open descriptors in\n \tthe parent should have FD_CLOEXEC set.\n\t(start_job_command): Set FD_CLOEXEC flag on BAD_STDIN descriptor.\n\nTue Jun 20 03:47:15 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* read.c (read_all_makefiles): Properly append default makefiles\n \tto the end of the `read_makefiles' chain.\n\nFri May 19 16:36:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.74 released.\n\nWed May 10 17:43:34 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.73.3.\n\nTue May  9 17:15:23 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* compatMakefile ($(infodir)/make.info): Make sure $$dir is set in\n \tinstall-info cmd.\n\nWed May  3 15:56:06 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* file.c (print_file): Grok update_status of 1 for -q.\n\nThu Apr 27 12:39:35 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.73.2.\n\nWed Apr 26 17:15:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* file.c (remove_intermediates): Fix inverted test to bail under\n \t-n for signal case.  Bail under -q or -t.\n\tSkip files with update_status==-1.\n\n\t* job.c (job_next_command): Skip empty lines.\n\t(new_job): Don't test the return of job_next_command.\n\tJust let start_waiting_job handle the case of empty commands.\n\nWed Apr 19 03:25:54 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* function.c [__MSDOS__]: Include <fcntl.h>.  From DJ Delorie.\n\n\t* Version 3.73.1.\n\nSat Apr  8 14:53:24 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* remake.c (notice_finished_file): Set FILE->update_status to zero\n \tif it's -1.\n\nWed Apr  5 00:20:24 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.73 released.\n\nTue Mar 28 13:25:46 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (main): Fixed braino in assert.\n\n\t* Version 3.72.13.\n\nMon Mar 27 05:29:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c: Avoid string in assert expression.  Some systems are broken.\n\nFri Mar 24 00:32:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (main): Handle 1 and 2 returns from update_goal_chain\n \tmakefile run properly.\n\n\t* Version 3.72.12.\n\n\t* main.c (handle_non_switch_argument): New function, broken out of\n \tdecode_switches.\n\t(decode_switches): Set optind to 0 to reinitialize getopt, not to 1.\n\tWhen getopt_long returns EOF, break the loop and handle remaining args\n \twith a simple second loop.\n\n\t* remake.c (remake_file): Set update_status to 2 instead of 1 for\n \tno rule to make.  Mention parent (dependent) in error message.\n\t(update_file_1): Handle FILE->update_status == 2 in -d printout.\n\t* job.c (start_job_command, reap_children): Set update_status to 2\n \tinstead of 1 for failed commands.\n\nTue Mar 21 16:23:38 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c (search_path): Function removed (was already #if 0'd out).\n\t* configure.in: Remove AC_TYPE_GETGROUPS; nothing needs it any more.\n\nFri Mar 17 15:57:40 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* configure.bat: Write @CPPFLAGS@ translation.\n\nMon Mar 13 00:45:59 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* read.c (parse_file_seq): Rearranged `l(a b)' -> `l(a) l(b)' loop\n \tto not skip the elt immediately preceding `l(...'.\n\nFri Mar 10 13:56:49 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.11.\n\n\t* read.c (find_char_unquote): Make second arg a string of stop\n \tchars instead of a single stop char.  Stop when any char in the\n \tstring is hit.  All callers changed.\n\t(find_semicolon): Pass stop chars \"#;\" to one find_char_unquote call,\n\tinstead of using two calls.  If the match is not a ; but a #,\n \treturn zero.\n\t* misc.c: Changed find_char_unquote callers here too.\n\n\t* Version 3.72.10.\n\n\t* read.c (read_makefile, parse_file_seq): Fix typo __MS_DOS__ ->\n \t__MSDOS__.\n\n\t* GNUmakefile (globfiles): Add glob/configure.bat.\n\t(distfiles): Add configh.dos, configure.bat.\n\nWed Mar  8 13:10:57 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\tFixes for MS-DOS from DJ Delorie.\n\t* read.c (read_makefile, parse_file_seq) [__MS_DOS__]: Don't see :\n \tas separator in \"C:\\...\".\n\t* configh.dos (STDC_HEADERS): Define only if undefined.\n\t(HAVE_SYS_PARAM_H): Don't define this.\n\t(HAVE_STRERROR): Define this.\n\t* job.c (construct_command_argv_internal) [__MSDOS__]: Fix typos.\n\n\t* Version 3.72.9.\n\n\t* main.c (decode_switches): Reset optind to 1 instead of 0.\n\nTue Mar  7 17:31:06 1995  Roland McGrath  <roland@geech.gnu.ai.mit.edu>\n\n\t* main.c (decode_switches): If non-option arg is \"-\", ignore it.\n\nMon Mar  6 23:57:38 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.8.\n\nWed Feb 22 21:26:36 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.7.\n\nTue Feb 21 22:10:43 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (main): Pass missing arg to tmpnam.\n\n\t* configure.in: Check for strsignal.\n\t* job.c (child_error): Use strsignal.\n\t* main.c (main): Don't call signame_init #ifdef HAVE_STRSIGNAL.\n\n\t* misc.c (strerror): Fix swapped args in sprintf.\n\nMon Feb 13 11:50:08 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* configure.in (CFLAGS, LDFLAGS): Don't set these variables.\n\nFri Feb 10 18:44:12 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (print_version): Add 95 to copyright years.\n\n\t* Version 3.72.6.\n\n\t* job.c (start_job_command): Remember to call notice_finished_file\n \tunder -n when not recursing.  To do this, consolidate that code\n \tunder the empty command case and goto there for the -n case.\n\nTue Feb  7 13:36:03 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* make.h [! STDC_HEADERS]: Don't declare qsort.  Sun headers\n \tdeclare it int.\n\nMon Feb  6 17:37:01 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* read.c (read_makefile): For bogus line starting with tab, ignore\n \tit if blank after removing comments.\n\n\t* main.c: Cast results of `alloca' to `char *'.\n\t* expand.c: Likewise.\n\nSun Feb  5 18:35:46 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.5.\n\n\t* configure.in: Check for mktemp.\n\t* main.c (main) [! HAVE_MKTEMP]: Use tmpnam instead of mktemp.\n\n\t* configure.in (make_cv_sysconf_open_max): New check for `sysconf\n \t(_SC_OPEN_MAX)'.\n\t* acconfig.h: Added #undef HAVE_SYSCONF_OPEN_MAX.\n\t* job.c [HAVE_SYSCONF_OPEN_MAX] (getdtablesize): Define as macro\n \tusing sysconf.\n\nFri Jan 27 04:42:09 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* remake.c (update_file_1): When !MUST_MAKE, don't set\n \tFILE->update_status to zero before calling notice_finished_file.\n\t(notice_finished_file): Touch only when FILE->update_status is zero.\n\t(remake_file): Set FILE->update_status to zero after not calling\n\texecute_file_command and deciding to touch instead.\n\nThu Jan 26 01:29:32 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (debug_signal_handler): New function; toggles debug_flag.\n\t(main): Handle SIGUSR1 with that.\n\nMon Jan 16 15:46:56 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* compatMakefile (realclean): Remove Info files.\n\nSun Jan 15 08:23:09 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.4.\n\n\t* job.c (start_job_command): Save and restore environ around vfork\n        call.\n\t(search_path): Function #if 0'd out.\n\t(exec_command): Use execvp instead of search_path.\n\n\t* expand.c (variable_expand): Rewrote computed variable name and\n\tsubstitution reference handling to be simpler.  First expand the\n\tentire text between the parens if it contains any $s, then examine\n\tthe result of that for subtitution references and do no further\n\texpansion while parsing them.\n\n\t* job.c (construct_command_argv_internal): Handle \" quoting too,\n\twhen no backslash, $ or ` characters appear inside the quotes.\n\n\t* configure.in (union wait check): If WEXITSTATUS and WTERMSIG are\n        defined, just use int.\n\nTue Jan 10 06:27:27 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* default.c (default_variables) [__hpux]: Remove special\n\tdefinition of ARFLAGS.  Existence of the `f' flag is not\n\tconsistent across HPUX versions; and one might be using GNU ar\n\tanyway.\n\n\t* compatMakefile (clean): Don't remove Info files.\n\n\t* compatMakefile (check): Remove gratuitous target declaration.\n\nSat Jan  7 11:38:23 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* compatMakefile (ETAGS, CTAGS): Don't use -t.\n\n\t* arscan.c (ar_name_equal) [cray]: Subtract 1 like [__hpux].\n\n\t* main.c (decode_switches): For --help, print usage to stdout.\n\nMon Dec  5 12:42:18 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.3.\n\n\t* remake.c (update_file_1): Do set_command_state (FILE,\n\tcs_not_started) only if old state was deps_running.\n\nMon Nov 28 14:24:03 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c (start_waiting_job): Use set_command_state.\n\n\t* build.template (CPPFLAGS): New variable.\n\t(prefix, exec_prefix): Set from @...@.\n\t(compilation loop): Pass $CPPFLAGS to compiler.\n\n\t* GNUmakefile (build.sh.in): Make it executable.\n\n\t* GNUmakefile (globfiles): Add configure.in, configure.\n\n\t* Version 3.72.2.\n\n\t* configure.in (AC_OUTPUT): Don't write glob/Makefile.\n\n\t* configure.in (AC_CHECK_SYMBOL): Use AC_DEFINE_UNQUOTED.\n\n\t* configure.in: Don't check for ranlib.\n\nTue Nov 22 22:42:40 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* remake.c (notice_finished_file): Only mark also_make's as\n\tupdated if really ran cmds.\n\nTue Nov 15 06:32:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* configure.in: Put dnls before random whitespace.\n\nSun Nov 13 05:02:25 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* compatMakefile (CPPFLAGS): New variable, set from @CPPFLAGS@.\n\t(RANLIB): Variable removed.\n\t(prefix, exec_prefix): Set these from @...@.\n\t(.c.o): Use $(CPPFLAGS).\n\t(glob/libglob.a): Don't pass down variables to sub-make.\n\tglob/Makefile should be configured properly by configure.\n\t(distclean): Remove config.log and config.cache (autoconf stuff).\n\nMon Nov  7 13:58:06 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* acconfig.h: Add #undef HAVE_UNION_WAIT.\n\t* configure.in: Converted to Autoconf v2.\n\t* dir.c: Test HAVE_DIRENT_H, HAVE_SYS_DIR_H, HAVE_NDIR_H instead\n\tof DIRENT, SYSDIR, NDIR.\n\t* build.sh.in (prefix, exec_prefix): Set these from @...@.\n\t(CPPFLAGS): New variable, set from @CPPFLAGS@.\n\t(compiling loop): Pass $CPPFLAGS before $CFLAGS.\n\t* install.sh: File renamed to install-sh.\n\n\t* main.c (define_makeflags): When no flags, set WORDS to zero.\n\nSun Nov  6 18:34:01 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.1.\n\n\t* main.c (define_makeflags): Terminate properly when FLAGSTRING is\n        empty.\n\nFri Nov  4 16:02:51 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.72.\n\nTue Nov  1 01:18:10 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.71.5.\n\n\t* job.c (start_job_command): When ARGV is nil, only set\n\tupdate_state and call notice_finished_file if job_next_command\n\treturns zero.\n\n\t* job.c (start_job_command): Call notice_finished_file for empty\n        command line.\n\nThu Oct 27 02:02:45 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* file.c (snap_deps): Set COMMANDS_SILENT for .SILENT, not\n        COMMANDS_NOERROR.\n\nWed Oct 26 02:14:10 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.71.4.\n\nTue Oct 25 22:49:24 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* file.c (snap_deps): Set command_flags bits in all :: entries.\n\nMon Oct 24 18:47:50 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* make.h (posix_pedantic): Declare it.\n\t* main.c (main): Move checks .IGNORE, .SILENT, .POSIX to\n        snap_deps.\n\t* file.c (snap_deps): Check .IGNORE, .SILENT, .POSIX here instead\n\tof in main.  If .IGNORE has deps, OR COMMANDS_NOERROR into their\n\tcommand_flags and don't set -i.  Likewise .SILENT.\n\t* job.c (start_job_command): In FLAGS initialization, OR in\n\tCHILD->file->command_flags.\n\t* file.h (struct file): New member `command_flags'.\n\nSun Oct 16 01:01:51 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (switches): Bump flag values for --no-print-directory and\n\t--warn-undefined-variables, so neither is 1 (which indicates a\n\tnonoption argument).\n\nSat Oct 15 23:39:48 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (main): Add missing code in .IGNORE test.\n\nMon Oct 10 04:09:03 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* variable.c (define_automatic_variables): Define +D and +F.\n\nSat Oct  1 04:07:48 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (main): Define hidden automatic variable with command\n\tvars, and MAKEOVERRIDES to a reference to that.\n\t(define_makeflags): If posix_pedantic, write a reference to that\n\tinstead.\n\nThu Sep 29 00:14:26 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* main.c (posix_pedantic): New variable.\n\t(main): Set posix_pedantic if .POSIX is a target.\n\tFix .IGNORE and .SILENT checks to require is_target.\n\n\t* commands.c (set_file_variables): Define new automatic variable\n\t$+, like $^ but before calling uniquize_deps.\n\n\t* job.c (reap_children): Call delete_child_targets for non-signal\n\terror if .DELETE_ON_ERROR is a target.\n\nTue Sep 27 01:57:14 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.71.3.\n\nMon Sep 26 18:16:55 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* job.c (reap_children): Don't change C->file->command_state when\n\tdying.  Test it only after calling start_job_command for a new\n\tcommand line.  When no more cmds, just set C->file->update_status.\n\t(start_job_command): When the last line is empty or under -n, set\n\tC->file->update_status.\n\t(start_waiting_job): Grok cs_not_started after start_job_command\n\tas success.\n\t(new_job): Set C->file->update_status when there are no cmds.\n\t(job_next_command): When out of lines, don't set\n\tCHILD->file->update_status or CHILD->file->command_state.\n\n\t* main.c (quote_as_word): Renamed from shell_quote.  Take new arg;\n\tif nonzero, also double $s.\n\t(main): Define MAKEOVERRIDES from command_variables here.\n\t(define_makeflags): Don't use command_variables here; instead write a\n\treference $(MAKEOVERRIDES) in MAKEFLAGS.  Make vars recursive.\n\n\t* dir.c [__MSDOS__]: Fixed typo.\n\n\t* vpath.c (selective_vpath_search): Reset EXISTS when stat fails.\n\nSat Sep 10 03:01:35 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* remake.c: Include <assert.h> and use assert instead of printfs\n        and abort.\n\n\t* main.c (decode_switches): Loop until optind hits ARGC, not just\n\tuntil getopt_long returns EOF.  Initialize C to zero before loop;\n\tin loop if C is EOF, set optarg from ARGV[optind++], else call\n\tgetopt_long.\n\t(decode_env_switches): Use variable_expand instead of\n\tallocated_variable_expand.  Allocate a fresh buffer to copy split\n\twords into; scan characters by hand to break words and\n\tdebackslashify.\n\t(shell_quote): New function.\n\t(define_makeflags): Allocate doubled space for switch args, and command\n\tvariable names and values; use shell_quote to quote those things.\n\nFri Sep  9 01:37:47 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* Version 3.71.2.\n\n\t* acconfig.h: Add HAVE_SYS_SIGLIST and HAVE__SYS_SIGLIST.\n\n\t* main.c (decode_switches): The non-option return from getopt is\n\t1, not 0.\n\t(command_variables): New type and variable.\n\t(decode_switches, decode_env_switches): After making a variable\n\tdefinition, record the struct variable pointer in the\n\tcommand_variables chain.\n\t(define_makeflags): If ALL, write variable definitions for\n\tcommand_variables.\n\n\t* main.c (other_args): Variable removed.\n\t(goals, lastgoal): New static variables (moved from auto in main).\n\t(main): Don't process OTHER_ARGS at all.\n\tDon't set variable MAKEOVERRIDES at all; define MAKE to just\n        $(MAKE_COMMAND).\n\t(init_switches): Prepend a - {return in order} instead of a +\n\t{require order}.\n\t(decode_switches): Don't set OTHER_ARGS at all.\n\tGrok '\\0' return from getopt_long as non-option argument; try\n\tvariable definition and (if !ENV) enter goal targets here.\n\t(decode_env_switches): Use allocated_variable_expand to store value.\n\tUse find_next_token to simplify word-splitting loop.  Don't\n\tprepend a dash to uninterpreted value.  Instead, if split into\n\tonly one word, try variable definition and failing that prepend a\n\tdash to the word and pass it to decode_switches as a single arg.\n\nWed Sep  7 03:02:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\t* remake.c (notice_finished_file): Only recheck modtimes if\n\tFILE->command_state was cs_running on entry (meaning the commands\n\tactually just ran).\n\t(update_file_1): Whenever we set FILE->update_status, call\n\tnotice_finished_file instead of just set_command_state.\n\t* job.c (start_job_command): Whenever we set\n\tCHILD->file->update_status, call notice_finished_file instead of\n\tjust set_command_state.\n\nTue Sep  6 19:13:54 1994  Roland McGrath  <roland@geech.gnu.ai.mit.edu>\n\n\t* default.c: Add missing \".\n\n\t* job.c: Changed all assignments of command_state members to calls\n\tto set_command_state.\n\t* remake.c: Likewise.\n\t* file.c (set_command_state): New function.\n\t* file.h: Declare set_command_state.\n\n\t* main.c (init_switches): Put a + first in options.\n\nMon Jul 25 18:07:46 1994  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>\n\n\tMerge MSDOS/GO32 port from DJ Delorie <dj@ctron.com>.\n\t* vpath.c: Changed all uses of ':' to PATH_SEPARATOR_CHAR.\n\t* main.c (directory_before_chdir): New variable, moved out of main\n        (was local).\n\t(main) [__MSDOS__]: Look for \\ or : to delimit last component of\n\tPROGRAM.  Don't frob ARGV[0] before setting MAKE_COMMAND variable.\n\t(die): Change back to `directory_before_chdir' before dying.\n\t* make.h (PATH_SEPARATOR_CHAR): New macro; differing defns for\n        [__MSDOS__] and not.\n\t* job.c [__MSDOS__]: Include <process.h>.\n\t[__MSDOS__] (dos_pid, dos_status, dos_bname, dos_bename,\n\tdos_batch_file): New variables.\n\t(reap_children) [__MSDOS__]: Don't call wait; just examine those vars.\n\t(unblock_sigs) [__MSDOS__]: Do nothing.\n\t(start_job_command) [__MSDOS__]: Use spawnvpe instead of vfork & exec.\n\t(load_too_high) [__MSDOS__]: Always return true.\n\t(search_path) [__MSDOS__]: Check for : or / in FILE to punt.\n\tUse PATH_SEPARATOR_CHAR instead of ':'.\n\t(construct_command_argv_internal) [__MSDOS__]: Wholly different\n\tvalues for sh_chars and sh_cmds.  Wholly new code to handle shell\n\tscripts.\n\t* function.c (expand_function: `shell') [__MSDOS__]: Wholly new\n        implementation.\n\t* dir.c [__MSDOS__] (dosify): New function.\n\t(dir_contents_file_exists_p) [__MSDOS__]: Call it on FILENAME and\n\tprocess the result instead of FILENAME itself.\n\t(file_impossible_p) [__MSDOS__]: Likewise.\n\t* default.c [__MSDOS__]: Define GCC_IS_NATIVE.\n\t(default_suffix_rules) [__MSDOS__]: Use `y_tab.c' instead of `y.tab.c'.\n\t(default_variables) [GCC_IS_NATIVE]: Set CC and CXX to `gcc', YACC to\n\t`bison -y', and LEX to `flex'.\n\t* configure.bat, configh.dos: New files.\n\t* commands.c (fatal_error_signal) [__MSDOS__]: Just remove\n\tintermediates and exit.\n\n\t* commands.c (set_file_variables): Add parens in length\n\tcomputation in .SUFFIXES dep loop to quiet compiler warning.  From\n\tJim Meyering.\n\n\t* read.c (read_makefile): Free FILENAME if we allocated it.  From\n        Jim Meyering.\n\nMon Jul  4 17:47:08 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* misc.c (safe_stat): New function, EINTR-safe wrapper around stat.\n\t* vpath.c (selective_vpath_search): Use safe_stat in place of stat.\n\t* read.c (construct_include_path): Use safe_stat in place of stat.\n\t* job.c (search_path): Use safe_stat in place of stat.\n\t* dir.c (find_directory): Use safe_stat in place of stat.\n\t* commands.c (delete_target): Use safe_stat in place of stat.\n\t* arscan.c (ar_member_touch) [EINTR]: Do EINTR looping around fstat.\n\t* remake.c (name_mtime): Use safe_stat in place of stat.\n\t(touch_file) [EINTR]: Do EINTR looping around fstat.\n\nFri Jun 24 05:40:24 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Check for a shell command first, and\n\tthen strip leading tabs before further checking if it's not a\n\tshell command line.\n\n\t* make.h [__arm]: Undefine POSIX.\n\t[!__GNU_LIBRARY__ && !POSIX && !_POSIX_VERSION]: Don't declare system\n\tfunctions that return int.\n\n\t* job.c (construct_command_argv_internal): After swallowing a\n\tbackslash-newline combination, if INSTRING is set goto string_char\n\t(new label) for normal INSTRING handling code.\n\nSat Jun  4 01:11:20 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* configure.in: Don't check for sys_siglist and _sys_siglist with\n\tAC_HAVE_FUNCS.  Instead use two AC_COMPILE_CHECKs.\n\nMon May 23 18:20:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.71.1 released.\n\n\t* make.h [!__GNU_LIBRARY__ && !POSIX]: Also test #ifndef\n\t_POSIX_VERSION for these declarations.\n\n\t* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Remove bogus #ifndefs\n\taround #undefs of HAVE_SETREUID and HAVE_SETREGID.\n\nSat May 21 16:26:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.71 released.\n\n\t* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Don't test [HAVE_SETUID]\n\tand [HAVE_SETGID].  Every system has those, and configure doesn't\n\tcheck for them.\n\n\t* make.h [_POSIX_VERSION]: Don't #define POSIX #ifdef ultrix.\n\n\t* compatMakefile (loadavg): Depend on and use loadavg.c instead of\n\tgetloadavg.c.\n\t(loadavg.c): Link or copy it from getloadavg.c.\n\t(distclean): Remove loadavg.c.\n\nMon May 16 22:59:04 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.70.4.\n\n\t* misc.c [GETLOADAVG_PRIVILEGED] [! POSIX]: Undefine HAVE_SETEUID\n\tand HAVE_SETEGID.\n\n\t* default.c (default_terminal_rules): In SCCS rules, put\n\t$(SCCS_OUTPUT_OPTION) before $<.  On some systems -G is grokked\n\tonly before the file name.\n\t* configure.in (SCCS_GET_MINUS_G check): Put -G flag before file name.\n\nTue May 10 16:27:38 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Swallow\n\tbackslash-newline combinations inside '' strings too.\n\nThu May  5 04:15:10 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (do_define): Call collapse_continuations on each line\n\tbefore all else.\n\nMon Apr 25 19:32:02 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Notice newline inside\n\t'' string when RESTP is non-null.\n\nFri Apr 22 17:33:30 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.70.3.\n\n\t* remake.c (update_goal_chain): Reset FILE to G->file after the\n\tdouble-colon loop so it is never null for following code.\n\n\t* read.c (read_makefile): Fix `override define' parsing to skip\n\twhitespace after `define' properly.\n\n\t* compatMakefile (srcdir): Define as @srcdir@; don't reference\n\t$(VPATH).\n\t(glob/Makefile): New target.\n\nThu Apr 21 16:16:55 1994  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.70.2.\n\n\t* misc.c (remove_comments): Use find_char_unquote.\n\t* make.h (find_char_unquote): Declare it.\n\t* read.c (find_char_unquote): New function, generalized from\n\tfind_percent.\n\t(find_percent, find_semicolon, parse_file_seq): Use that.\n\nWed Apr 20 18:42:39 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* implicit.c (pattern_search): Always allocate new storage for\n\tFILE->stem.  It is not safe to store STEM's address because it\n\tmight be auto storage.\n\n\t* configure.in: Check for seteuid and setegid.\n\t* misc.c [HAVE_SETEUID]: Declare seteuid.\n\t[HAVE_SETEGID]: Declare setegid.\n\t(make_access, user_access) [HAVE_SETEUID]: Use seteuid.\n\t[HAVE_SETEGID]: Use setegid.\n\n\t* remake.c (update_goal_chain): Set STATUS to FILE->update_status,\n\tto preserve whether it's 2 for error or 1 for -q trigger.  When\n\tSTATUS gets nonzero and -q is set, always stop immediately.\n\t* main.c (main, decode_switches): Die with 2 for errors.\n\t(main): Accept 2 return from update_goal_chain and die with that.\n\t* misc.c (fatal, makefile_fatal): Die with 2; 1 is reserved for -q\n\tanswer.\n\t* job.c (reap_children): Die with 2 for error.\n\t(start_job_command): Set update_status to 2 for error.  Set it to\n\t1 when we would run a command and question_flag is set.\n\n\t* read.c (read_makefile): Don't mark makefiles as precious.  Just\n\tlike other targets, they can be left inconsistent and in need of\n\tremaking by aborted commands.\n\n\t* read.c (read_makefile): Write no error msg for -include file.\n\nTue Apr  5 05:22:19 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* commands.c (fatal_error_signal): Don't unblock signals.\n\n\t* file.h (struct file): Change member `double_colon' from flag to\n\t`struct file *'.\n\t* read.c (record_files): Set double_colon pointer instead of flag.\n\t* main.c (main): When disqualifying makefiles for updating, use\n\tdouble_colon pointer to find all entries for a file.\n\t* file.c (enter_file): If there is already a double-colon entry\n\tfor the file, set NEW->double_colon to that pointer.\n\t(file_hash_enter): Use FILE->double_colon to find all entries to\n\tset name.\n\t* remake.c (update_goal_chain): Do inner loop on double-colon entries.\n\t(update_file): Use FILE->double_colon pointer to find all entries.\n\t(f_mtime): Likewise.\n\t(notice_finished_file): Propagate mtime change to all entries.\n\n\t* variable.c (try_variable_definition): Return after abort.\n\nFri Apr  1 18:44:15 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Remove unused variable.\n\t(parse_file_seq): When removing an elt that is just `)', properly\n\tfix up the previous elt's next pointer.\n\nMon Mar 28 18:31:49 1994  Roland McGrath  (roland@mole.gnu.ai.mit.edu)\n\n\t* configure.in: Do AC_SET_MAKE.\n\t* GNUmakefile (Makefile.in): Edit MAKE assignment into @SET_MAKE@.\n\nFri Mar  4 00:02:32 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* function.c (subst_expand): If BY_WORD or SUFFIX_ONLY is set and\n\tthe search string is the empty string, find a match at the end of\n\teach word (using end_of_token in place of sindex).\n\n\t* misc.c (end_of_token): Don't treat backslashes specially; you\n\tcan no longer escape blanks with backslashes in export, unexport,\n\tand vpath.  This was never documented anyway.\n\nThu Mar  3 23:53:46 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Variable name for `define' is not just\n\tfirst token; use whole rest of line and strip trailing blanks.\n\nWed Feb 16 16:03:45 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.70.1.\n\n\t* read.c (read_makefile): Add -d msg stating args.\n\n\t* read.c (read_makefile): Use isspace to skip over leading\n\twhitespace, and explicitly avoid skipping over tabs.  Don't want\n\tto skip just spaces though; formfeeds et al should be skipped.\n\n\t* default.c (default_variables) [__hpux]: Add f in ARFLAGS.\n\n\t* arscan.c (ar_name_equal) [__hpux]: Subtract 2 instead of 1 from\n\tsizeof ar_name for max length to compare.\n\n\t* misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Undefine HAVE_SETREUID\n\t#ifdef HAVE_SETUID; likewise HAVE_SETREGID and HAVE_SETGID.\n\n\t* main.c (main): Call user_access after setting `program', in case\n\tit needs to use it in an error message.\n\n\t* read.c (read_makefile): Ignore an empty line starting with a tab.\n\nThu Feb 10 21:45:31 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in (AC_SYS_SIGLIST_DECLARED): Use this instead of\n\tAC_COMPILE_CHECK that is now its contents.\n\nFri Feb  4 16:28:54 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h: #undef strerror after #include <string.h>.\n\t[! ANSI_STRING]: Declare strerror.\n\nThu Feb  3 02:21:22 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* misc.c (strerror): #undef any macro before function definition.\n\nMon Jan 31 19:07:23 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (try_variable_definition): Calculate BEG before loop\n\tto strip blanks by decrementing END.  Don't decr END to before BEG.\n\n\t* read.c (read_makefile): Skip over leading space characters, but\n\tnot tabs, after removing continuations and comments (it used to\n\tuse isspace).\n\nTue Jan 25 16:45:05 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (define_automatic_variables): In $(@D) et al, use\n\tpatsubst to remove trailing slash.\n\n\t* commands.c (delete_target): New function, broken out of\n\tdelete_child_targets.  Check for archive members and give special msg.\n\t(delete_child_targets): Use delete_target.\n\nMon Jan 17 17:03:22 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (default_suffix_rules): Use $(TEXI2DVI_FLAGS) in\n\ttexi2dvi rules.\tUse $(MAKEINFO_FLAGS) in makeinfo rules.\n\nTue Jan 11 19:29:55 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* GNUmakefile (tarfiles): Omit make-doc.\n\t(make-$(version).tar): Include make.info*.\n\nFri Jan  7 16:27:00 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (configure, config.h.in): Comment out rules.\n\nThu Jan  6 18:08:08 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (binprefix, manprefix): New variables.\n\t(instname): Variable removed.\n\t(install): Use $({bin,man}prefix)make in place of $(instname).\n\tFile targets likewised renamed.\n\nMon Jan  3 17:50:25 1994  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.70 released.\n\nThu Dec 23 14:46:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.69.3.\n\n\t* read.c (parse_file_seq): Inside multi-word archive ref\n\ttranslation loop, check NEW1==0 at end and break out of the loop.\n\n\t* GNUmakefile (make-$(version).tar): Distribute install.sh.\n\t* install.sh: New file.\n\n\t* configure.in (SCCS_GET_MINUS_G check): Put redirection for admin\n\tcmds outside subshell parens, to avoid \"command not found\" msgs\n\tfrom the shell.\n\nWed Dec 22 17:00:43 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in (SCCS_GET_MINUS_G check): Put -G flag last in get cmd.\n\tRedirect output & error from get to /dev/null.\n\tFix reversed sense of test.\n\nFri Dec 17 15:31:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in (SCCS_GET_MINUS_G check): Use parens instead of\n\tbraces inside if condition command; some shells lose.\n\nThu Dec 16 15:10:23 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.69.2.\n\n\t* arscan.c [M_UNIX]: Move #undef M_XENIX for PORTAR stuff.\n\t(PORTAR) [M_XENIX]: Define to 0 instead of 1.\n\n\t* main.c (define_makeflags): Only export MAKEFLAGS if !ALL.\n\nWed Dec 15 17:47:48 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): Cast result of pointer arith to unsigned int\n\tbefore passing to define_variable for envars.  Matters when\n\tsizeof(unsigned)!=sizeof(ptrdiff_t).\n\nTue Dec 14 14:21:16 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in: Add new check for SCCS_GET_MINUS_G.\n\t* config.h.in: Add #undef SCCS_GET_MINUS_G.\n\t* default.c (default_terminal_rules): Use `$(SCCS_OUTPUT_OPTION)' in\n\tplace of `-G $@' in SCCS commands.\n\t(default_variables) [SCCS_GET_MINUS_G]: Define SCCS_OUTPUT_OPTION\n\tto \"-G$@\".\n\n\t* configure.in (AC_OUTPUT): Put touch stamp-config in second arg\n\t(so it goes in config.status), rather than afterward.\n\n\t* ar.c (ar_member_date): Don't call enter_file on the archive file\n\tif it doesn't exist (by file_exists_p).\n\n\t* compatMakefile ($(infodir)/make.info): Replace `$$d/foo.info'\n\twith `$$dir/make.info' in install-info invocation (oops).\n\n\t* vpath.c (construct_vpath_list): Only set LASTPATH set PATH when\n\twe do not unlink and free PATH.\n\n\t* file.c (print_file_data_base): Fix inverted calculation for\n\taverage files per hash bucket.\n\n\t* read.c (readline): When we see a NUL, give only a warning and\n\tsynthesize a newline to terminate the building line (used to\n\tfatal).  Move fgets call into the loop condition, and after the\n\tloop test ferror (used to test !feof in the loop).\n\nFri Dec  3 16:40:31 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in: Check for strerror in AC_HAVE_FUNCS.\n\nThu Dec  2 15:37:50 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\tDifferentiate different flavors of missing makefile error msgs,\n\tremoving gratuitous `fopen: ' and giving caller for included makefiles.\n\t* misc.c [! HAVE_STRERROR]: Define our own strerror here.\n\t(perror_with_name, pfatal_with_name): Use strerror instead of\n\treplicating its functionality.\n\t* read.c (read_makefile): Return int instead of void.\n\t(read_all_makefiles, read_makefile): Change callers to notice zero\n\treturn and give error msg.\n\nThu Nov 11 11:47:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.69.1.\n\n\t* default.c: Put `-G $@' before $< in SCCS cmds.\n\nWed Nov 10 06:06:14 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): After trying a variable defn, notice if\n\tthe line begins with a tab, and diagnose an error.\n\nSun Nov  7 08:07:37 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.69.\n\nWed Nov  3 06:54:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.10.\n\n\t* implicit.c (try_implicit_rule): Look for a normal rule before an\n\tarchive rule.\n\nFri Oct 29 16:45:28 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* function.c (expand_function: `sort'): Double NWORDS when it\n\toverflows, instead of adding five.\n\n\t* compatMakefile (clean): Remove loadavg.\n\nWed Oct 27 17:58:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.9.\n\n\t* file.h (NEW_MTIME): Define new macro.\n\t* main.c (main): Set time of NEW_FILES to NEW_MTIME, not to\n\tcurrent time returned from system.  Removed variable NOW.\n\t* remake.c (notice_finished_file): Use NEW_MTIME in place of\n\tcurrent time here too.\n\nTue Oct 26 19:45:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.8.\n\n\t* remake.c (update_file_1): Don't clear MUST_MAKE when FILE has no\n\tcmds and !DEPS_CHANGED unless also !NOEXIST.\n\nMon Oct 25 15:25:21 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (parse_file_seq): When converting multi-word archive\n\trefs, ignore a word beginning with a '('.\n\nFri Oct 22 02:53:38 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in: Check for sys/timeb.h.\n\t* make.h [HAVE_SYS_TIMEB_H]: Test this before including it.\n\nThu Oct 21 16:48:17 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.7.\n\n\t* rule.c (convert_suffix_rule): New local TARGPERCENT.  Set it to\n\tTARGNAME+1 for \"(%.o)\", to TARGNAME for \"%.?\".  Use it in place of\n\tTARGNAME to initialize PERCENTS[0].\n\nMon Oct 18 06:49:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in: Use AC_HAVE_HEADERS(unistd.h) instead of AC_UNISTD_H.\n\tRemove AC_USG; it is no longer used.\n\n\t* file.c (print_file): New function, broken out of\n\tprint_file_data_base.\n\t(print_file_data_base): Call it.\n\t* rule.c (print_rule): New function, broken out of\n\tprint_rule_data_base.\n\t(print_rule_data_base): Call it.\n\nThu Oct 14 14:54:03 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (install_default_suffix_rules): New function, broken\n\tout of install_default_implicit_rules.\n\t(install_default_implicit_rules): Move suffix rule code there.\n\t* make.h: Declare install_default_suffix_rules.\n\t* main.c (main): Call install_default_suffix_rules before reading\n\tmakefiles.  Move convert_to_pattern call before\n\tinstall_default_implicit_rules.\n\n\t* job.h (struct child): Make `pid' member type `pid_t' instead of\n\t`int'.\n\n\t* compatMakefile (RANLIB): New variable, set by configure.\n\t(glob/libglob.a): Pass RANLIB value down to submake.\n\n\tFixes for SCO 3.2 \"devsys 4.2\" from pss@tfn.com (Peter Salvitti).\n\t* make.h: Include <sys/timeb.h> before <time.h> for SCO lossage.\n\t* job.c [! getdtablesize] [! HAVE_GETDTABLESIZE]: If NOFILE is not\n\tdefined but NOFILES_MAX is, define it to be that.\n\nMon Oct 11 19:47:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* GNUmakefile (make-$(version).tar): Depend on acconfig.h, so it\n\tis distributed.\n\nSun Oct  3 15:15:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (default_terminal_rules): Add `-G $@' to SCCS get cmds.\n\nTue Sep 28 14:18:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Add ^ to SH_CHARS; it\n\tis another symbol for | in some shells.\n\t* main.c (main): Add it to CMD_DEFS quoting list as well.\n\nMon Sep 20 18:05:24 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Remove '=' from\n\tSH_CHARS.  Only punt on '=' if it is unquoted in a word before the\n\tfirst word without an unquoted '='.\n\n\t* main.c (define_makeflags): Set v_export for MAKEFLAGS.\n\nFri Sep 17 00:37:18 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (update_file_1): Use .DEFAULT cmds for phony targets.\n\n\t* make.h [_AIX && _POSIX_SOURCE]: Define POSIX.\n\n\t* commands.c (delete_child_targets): Don't delete phony files.\n\n\t* job.c (start_job_command): Set COMMANDS_RECURSE in FLAGS if we\n\tsee a `+' at the beginning of the command line.\n\nThu Sep  9 17:57:14 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.6.\n\nWed Sep  8 20:14:21 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (define_makeflags): Define MAKEFLAGS with o_file, not o_env.\n\nMon Aug 30 12:31:58 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* expand.c (variable_expand): Fatal on an unterminated reference.\n\nThu Aug 19 16:27:53 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.5.\n\n\t* variable.c (define_automatic_variables): Define new o_default\n\tvariable `MAKE_VERSION' from version_string and remote_description.\n\n\t* make.h (version_string, remote_description): Declare these here.\n\t* main.c: Don't declare version_string.\n\t(print_version): Don't declare remote_description.\n\nWed Aug 18 15:01:24 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Free space pointed to by CONDITIONALS\n\tbefore restoring the old pointer.\n\nMon Aug 16 17:33:36 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile ($(objs)): Depend on config.h.\n\n\t* GNUmakefile (build.sh.in): Depend on compatMakefile.\n\n\t* configure.in: Touch stamp-config after AC_OUTPUT.\n\nFri Aug 13 16:04:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.4.\n\nThu Aug 12 17:18:57 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h: Include <config.h> instead of \"config.h\".\n\nWed Aug 11 02:35:25 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): Make all variables interned from ENVP be v_export.\n\t* variable.c (try_variable_definition): In v_default case, don't\n\tcheck for an o_file variable that `getenv' finds.\n\n\t* job.c (reap_children): New local variable ANY_LOCAL; set it\n\twhile setting ANY_REMOTE.  If !ANY_LOCAL, don't wait for local kids.\n\n\t* main.c (main): Don't call decode_env_switches on MFLAGS.  DOC THIS.\n\n\t* function.c (expand_function): #if 0 out freeing of ENVP since it\n\tis environ.\n\nMon Aug  9 17:37:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.3.\n\n\t* remote-stub.c (remote_status): Set errno to ECHILD before return.\n\t* job.c (reap_children): Scan the chain for remote children and\n\tnever call remote_status if there are none.\n\n\t* function.c (expand_function: `shell'): #if 0 out calling\n\ttarget_environment; just set ENVP to environ instead.\n\n\t* job.c (reap_children): Check for negative return from\n\tremote_status and fatal for it.\n\tWhen blocking local child wait returns 0, then try a blocking call\n\tto remote_status.\n\nTue Aug  3 00:19:00 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (clean): Delete make.info* and make.dvi here.\n\t(distclean): Not here.\n\n\t* dep.h (RM_*): Use #defines instead of enum to avoid lossage from\n\tcompilers that don't like enum values used as ints.\n\nMon Aug  2 16:46:34 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (loadavg): Add $(LOADLIBES).\n\nSun Aug  1 16:01:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.2.\n\n\t* compatMakefile (loadavg, check-loadavg): New targets.\n\t(check): Depend on check-loadavg.\n\n\t* compatMakefile (glob/libglob.a): Depend on config.h.\n\n\t* misc.c (log_access): Write to stderr instead of stdout.\n\nFri Jul 30 00:07:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.1.\n\nThu Jul 29 23:26:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in (SYS_SIGLIST_DECLARED): In test program include\n\t<unistd.h> #ifdef HAVE_UNISTD_H.\n\n\t* compatMakefile (.PHONY): Put after `all' et al.\n\n\t* configure.in: Add AC_IRIX_SUN.\n\nWed Jul 28 17:41:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.68.\n\nMon Jul 26 14:36:49 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.8.\n\nSun Jul 25 22:09:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.7.\n\n\t* compatMakefile ($(infodir)/make.info): Don't use $(instname).\n\tRun install-info script if present.\n\nFri Jul 23 16:03:50 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h [STAT_MACROS_BROKEN]: Test this instead of [uts].\n\n\t* configure.in: Add AC_STAT_MACROS_BROKEN.\n\nWed Jul 14 18:48:11 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.6.\n\n\t* read.c (read_makefile): Recognize directive `-include', like\n\t`include' but sets RM_DONTCARE flag.\n\n\t* variable.c (target_environment): If FILE is nil, use\n\tcurrent_variable_set_list in place of FILE->variables.\n\t* function.c (expand_function: `shell'): Get an environment for\n\tthe child from target_environment instead of using environ.\n\n\t* dep.h: Declare read_all_makefiles here.\n\t(RM_*): Define new enum constants.\n\t* read.c (read_makefile): Second arg is FLAGS instead of TYPE.\n\tTreat it as a bit mask containing RM_*.\n\t(read_all_makefiles): For default makefiles, set D->changed to\n\tRM_DONTCARE instead of 1.\n\t* main.c: Don't declare read_all_makefiles here.\n\t(main): Check `changed' member of read_makefiles elts for RM_*\n\tflags instead of specific integer values.\n\nMon Jul 12 22:42:17 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h [sequent && i386]: #undef POSIX.  From trost@cse.ogi.edu.\n\nThu Jul  8 19:51:23 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* vpath.c (construct_vpath_list): If ELEM is zero 0, free PATTERN\n\tas well as VPATH.\n\t(build_vpath_lists): Empty `vpaths' around construct_vpath_list\n\tcall for $(VPATH).  Expand $(strip $(VPATH)), not just $(VPATH).\n\n\t* rule.c (convert_suffix_rule): Use alloca instead of xmalloc for\n\tPERCENTS, whose storage is not consumed by create_pattern_rule.\n\n\t* make.h [__mips && _SYSTYPE_SVR3]: #undef POSIX.\n\nWed Jun 30 18:11:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.5.\n\n\t* rule.c (max_pattern_targets): New variable.\n\t(count_implicit_rule_limits): Compute its value.\n\t* rule.h: Declare it.\n\t* implicit.c (pattern_search): Make TRYRULES max_target_patterns\n\ttimes bigger.  Move adding new TRYRULES elt inside the inner\n\ttargets loop, so each matching target gets its own elt in MATCHES\n\tand CHECKED_LASTSLASH.\n\n\t* file.c (remove_intermediates): If SIG!=0 say `intermediate file'\n\tinstead of just `file' in error msg.\n\nFri Jun 25 14:55:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv): Turn off\n\t--warn-undefined-variables around expansion of SHELL and IFS.\n\t* read.c (tilde_expand): Likewise for HOME.\n\t(read_all_makefiles): Likewise for MAKEFILES.\n\t* vpath.c (build_vpath_lists): Likewise for VPATH.\n\n\t* main.c (warn_undefined_variables_flag): New flag variable.\n\t(switches): Add --warn-undefined-variables.\n\t* make.h (warn_undefined_variables_flag): Declare it.\n\t* expand.c (warn_undefined): New function.\n\t(reference_variable): Call it if the variable is undefined.\n\t(variable_expand): In substitution ref, call warn_undefined if the\n\tvariable is undefined.\n\n\t* default.c (default_pattern_rules): Add `%.c: %.w %.ch' and\n\t`%.tex: %.w %.ch' rules.\n\t(default_suffix_rules: .w.c, .w.tex): Pass three args: $< - $@.\n\t(default_suffixes): Add `.ch'.\n\nMon Jun 21 17:55:39 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (default_suffixes): Replace `.cweb' with `.w'.\n\t(default_suffix_rules): Rename `.cweb.c' and `.cweb.tex' to `.w.c'\n\tand `.w.tex'.\n\nFri Jun 11 14:42:09 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile ($(bindir)/$(instname)): Add missing backslash.\n\nThu Jun 10 18:14:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.4.\n\n\t* read.c (multi_glob): Don't free OLD and OLD->name in the\n\tFOUND!=0 fork.  Use new block-local variable F instead of\n\tclobbering OLD.\n\n\t* ar.c (glob_pattern_p): New function, snarfed from glob/glob.c.\n\t(ar_glob): Call it; return nil immediately if MEMBER_PATTERN\n\tcontains no metacharacters.\n\nWed Jun  9 16:25:35 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* ar.c (ar_glob{_match,_alphacompare}): New function.\n\n\t* dep.h [! NO_ARCHIVES]: Declare it.\n\t* read.c (multi_glob) [! NO_ARCHIVES]: Use it on archive member elts.\n\n\t* read.c (read_makefile): Pass flag (1) to parse_file_seq, not to\n\tmulti_glob (which doesn't take a 3rd arg).\n\t* rule.c (install_pattern_rule): Likewise.\n\t* default.c (set_default_suffixes): Here too.\n\t* function.c (string_glob): Don't pass gratuitous arg to multi_glob.\n\n\t* read.c (parse_file_seq) [! NO_ARCHIVES]: Add post-processing\n\tloop to translate archive refs \"lib(a b)\" into \"lib(a) lib(b)\".\n\nMon Jun  7 19:26:51 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (installdirs): Actually pass directory names.\n\t($(bindir)/$(instname)): Test chgrp&&chmod exit status with `if';\n\tif it fails, echo a warning msg, but don't make the rule fail.\n\n\t* read.c (tilde_expand): New function, broken out of tilde_expand.\n\t(multi_glob): Call it.\n\t(construct_include_path): Expand ~ in directory names.\n\t* dep.h: Declare tilde_expand.\n\t* main.c (enter_command_line_file): Expand ~ at the start of NAME.\n\t(main): Expand ~ in -C args.\n\t* read.c (read_makefile): Expand ~ in FILENAME unless TYPE==2.\n\nFri Jun  4 13:34:47 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (decode_env_switches): Use xmalloc instead of alloca for ARGS.\n\n\t* main.c (main): Put result of alloca in temporary variable with\n\tsimple assignment, to make SGI compiler happy.\n\nThu Jun  3 20:15:46 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.3.\n\n\t* main.c (main): Before re-execing, remove intermediate files, and\n\tprint the data base under -p.  Sexier debugging message.\n\n\t* implicit.c (pattern_search): Allocate an extra copy of the name\n\tof a winning intermediate file when putting it in FOUND_FILES.\n\nWed Jun  2 16:38:08 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Pass flag (1) to parse_file_seq, not to\n\tmulti_glob (which doesn't take a 3rd arg).\n\n\t* dir.c (dir_contents_file_exists_p): When reading dirents, ignore\n\tchars within D_NAMLEN that are NULs.\n\n\t* main.c (decode_switches): Don't savestring ARGV[0] to put it\n\tinto `other_args'.\n\tFor string switch, don't savestring `optarg'.\n\t(main): Don't free elts of makefiles->list that are \"-\".\n\tUse alloca'd rather than savestring'd storage for elts of\n\tmakefiles->list that are temporary file names.\n\t* read.c (read_all_makefiles): Don't free *MAKEFILES.\n\t* file.c (enter_file): Don't strip `./'s.\n\t* main.c (enter_command_line_file): New function.\n\t(main): Use it in place of enter_file for command-line goals from\n\tother_files, and for old_files and new_files.\n\nMon May 31 18:41:40 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.2.\n\n\t* compatMakefile (.SUFFIXES): Add .info.\n\t($(infodir)/$(instname).info): Find make.info* in cwd if there,\n\telse in $srcdir.  Use basename to remove dir name from installed name.\n\nThu May 27 17:35:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* implicit.c (pattern_search): When interning FOUND_FILES, try\n\tlookup_file first; if found, free the storage for our copy of the name.\n\nWed May 26 14:31:20 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.1.\n\n\t* main.c (decode_switches): In usage msg, write `--switch=ARG' or\n\t`--switch[=OPTARG]' rather than `--switch ARG' or `--switch [ARG]'.\n\nMon May 24 16:17:31 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* rule.c (convert_suffix_rule): New function.\n\t(convert_to_pattern): Use it instead of doing all the work here\n\tseveral times.\n\tFor target suffix `.a', generate both the archive magic rule and\n\tthe normal rule.\n\n\t* compatMakefile (distclean): Remove stamp-config.\n\nSat May 22 16:15:18 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.67.\n\n\t* file.c (remove_intermediates): Don't write extra space after `rm'.\n\n\t* main.c (struct command_switch.type): Remove `usage_and_exit'.\n\t(print_usage_flag): New variable.\n\t(switches: --help): Make type `flag', to set print_usage_flag.\n\t(init_switches): Remove `usage_and_exit' case.\n\t(decode_switches): Likewise.\n\t(decode_switches): Print usage if print_usage_flag is set.\n\tWhen printing usage, die with status of BAD.\n\t(main): Die with 0 if print_version_flag.\n\nFri May 21 16:09:28 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.66.\n\nWed May 19 21:30:44 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (installdirs): New target.\n\t(install): Depend on it.\n\nSun May 16 20:15:07 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.65.2.\n\nFri May 14 16:40:09 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* vpath.c (construct_vpath_list): In removal loop for DIRPATH==0,\n\tset LASTPATH to PATH, not NEXT.\n\n\t* dir.c (read_dirstream): Break out of loop after incrementing\n\tDS->buckets such that it reaches DIRFILE_BUCKETS; avoid trying to\n\tdereference DS->contents->files[DIRFILE_BUCKETS].\n\n\t* read.c (read_makefile): Clear no_targets after reading a\n\ttargetful rule line.\n\n\t* main.c (main): If print_version_flag is set, exit after printing\n\tthe version.\n\t(switches): Change --version docstring to say it exits.\n\n\t* make.h [butterfly]: #undef POSIX.\n\nWed May 12 15:20:21 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.65.1.\n\n\t* arscan.c (ar_scan) [! AIAMAG]: Don't declare LONG_NAME.\n\t[AIAMAG]: Pass TRUNCATE flag arg to (*FUNCTION), always zero.\n\n\t* function.c (handle_function): Use fatal instead of\n\tmakefile_fatal when reading_filename is nil.\n\n\t* configure.in: Add AC_GETGROUPS_T.\n\t* job.c (search_path): Use GETGROUPS_T in place of gid_t.\n\nSun May  9 15:41:25 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.65.\n\nFri May  7 18:34:56 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* function.c (handle_function): Fatal for unmatched paren.\n\nThu May  6 16:13:41 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.64.3.\n\n\t* commands.c (handling_fatal_signal): New variable.\n\t(fatal_error_signal): Set it.\n\t* job.c (reap_children): Avoid nonreentrant operations if that is set.\n\t* make.h: Declare handling_fatal_signal.\n\n\t* expand.c (reference_variable): New function, snippet of code\n\tbroken out of simple-reference case of variable_expand.\n\t(variable_expand): Use it for simple refs.\n\t(variable_expand): When checking for a computed variable name,\n\tnotice a colon that comes before the final CLOSEPAREN.  Expand\n\tonly up to the colon, and then replace the pending text with a\n\tcopy containing the expanded name and fall through to subst ref\n\thandling.\n\t(variable_expand): Don't bother expanding the name if a colon\n\tappears before the first $.\n\t(expand_argument): Use alloca instead of savestring.\n\t(variable_expand): For subst ref, expand both sides of = before\n\tpassing to [pat]subst_expand.  Use find_percent instead of lindex\n\tto check the lhs for a %.\n\nWed May  5 14:45:52 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.64.2.\n\nMon May  3 17:00:32 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* arscan.c (ar_name_equal) [AIAMAG]: Abort if TRUNCATED is nonzero.\n\n\t* read.c (read_makefile): Pass extra arg of 1 to parse_file_seq,\n\tnot to multi_glob.\n\nThu Apr 29 19:47:33 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.64.1.\n\n\t* arscan.c (ar_scan): New local flag var LONG_NAME.  Set it when\n\twe read the member name in any of the fashions that allow it to be\n\tarbitrarily long.  Pass its negation to FUNCTION.\n\t(describe_member): Take TRUNCATED from ar_scan and print it.\n\t(ar_name_equal): Take new arg TRUNCATED; if nonzero, compare only\n\tthe first sizeof (struct ar_hdr.ar_name) chars.\n\t(ar_member_pos): Take TRUNCATED from ar_scan, pass to ar_name_equal.\n\t* ar.c (ar_member_date_1): Likewise.\n\nWed Apr 28 21:18:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (reap_children): Before calling start_job_command to start\n\tthe next command line, reset C->remote by calling start_remote_job_p.\n\nMon Apr 26 15:56:15 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* arscan.c (ar_scan): New local var NAMEMAP.\n\tIn loop, rename NAME to NAMEBUF; new var NAME is a pointer; new\n\tflag IS_NAMEMAP.  When extracting the member name, always put a\n\tnull at its end first.  If the name is \"//\" or \"/ARFILENAMES\", set\n\tIS_NAMEMAP.  If we have already read in NAMEMAP, and NAME looks\n\tlike \" /N\", get full name from NAMEMAP+N.\n\tElse if NAME looks like \"#1/N\", read N chars from the\n\telt data to be the full name.  At end of loop, if IS_NAMEMAP, read\n\tthe elt's data into alloca'd NAMEMAP.\n\t(ar_name_equal): #if 0 truncating code.\n\n\t* make.h: Don't declare vfork at all.  It returns int anyway,\n\tunless <unistd.h> declared it; and we conflicted with some systems.\n\n\t* main.c (define_makeflags): If FLAGSTRING[1] is '-', define\n\tMAKEFLAGS to all of FLAGSTRING, not &FLAGSTRING[1].  Don't want to\n\tdefine it to something like \"-no-print-directory\".\n\tUse %g format instead of %f for floating-valued things.\n\nThu Apr 22 18:40:58 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* GNUmakefile (Makefile.in): Use a substitution ref on nolib-deps\n\tto change remote-%.dep to remote-stub.dep.\n\nWed Apr 21 15:17:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.64.\n\nFri Apr 16 14:22:22 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (install): Remove - prefix from chgrp+chmod.\n\n\t* Version 3.63.8.\n\nThu Apr 15 18:24:07 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* acconfig.h: New file; contains \"#undef SCCS_GET\" for autoheader.\n\t* configure.in: If /usr/sccs/get exists, define SCCS_GET to that,\n\telse to \"get\".\n\t* default.c (default_variables): Set GET to macro SCCS_GET.\n\n\t* read.c (parse_file_seq): Take extra arg STRIP; strip `./' only\n\tif nonzero.  I hope this is the last time this argument is added\n\tor removed.\n\t(read_makefile): Pass it 1 when parsing include file names.\n\tPass it 1 when parsing target file names.\n\tPass it 1 when parsing static pattern target pattern names.\n\t* rule.c (install_pattern_rule): Pass it 1 when parsing rule deps.\n\t* default.c (set_default_suffixes): Pass it 1 when parsing\n\tdefault_suffixes.\n\t* function.c (string_glob): Pass it 0 here.\n\nWed Apr 14 11:32:05 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* misc.c (log_access): New function.\n\t({init,user,make,child}_access): Call it.\n\t(child_access): Abort if !access_inited.\n\n\t* main.c (switches: --no-print-directory): Use 1 instead of -1 for\n\tsingle-letter option.\n\t(init_switches, decode_switches, define_makeflags): An option with\n\tno single-letter version is no longer indicated by a value of -1;\n\tinstead a value that is !isalnum.\n\t(init_switches): Don't put such switches into the string, only\n\tinto the long_option table.\n\n\t* make.h [!NSIG] [!_NSIG]: #define NSIG 32.\n\n\t* job.c [HAVE_WAITPID]: Remove #undef HAVE_UNION_WAIT.  AIX's\n\tbsdcc defined WIF* to use union wait.\n\n\t* main.c (struct command_switch): Change member `c' to type int.\n\t(switches): Make const.\n\t(decode_switches): Use `const struct command_switch *'.\n\t(define_makeflags): Likewise.\n\n\t* default.c (default_suffix_rules): Add `-o $@' to makeinfo rules.\n\nMon Apr 12 12:30:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.63.7.\n\n\t* configure.in (AC_HAVE_HEADERS): Check for string.h and memory.h.\n\tRemoved AC_MEMORY_H.\n\t* make.h [USG, NeXT]: Don't test these.\n\t[HAVE_STRING_H]: Test this to include string.h and define ANSI_STRING.\n\t[HAVE_MEMORY_H]: Test this instead of NEED_MEMORY_H.\n\t[! ANSI_STRING]: Put decls of bcopy et al here.\n\t[sparc]: Don't test this for alloca.h; HAVE_ALLOCA_H is sufficient.\n\t[HAVE_SIGSETMASK]: Test this rather than USG.\n\t[__GNU_LIBRARY__ || POSIX]: Don't #include <unistd.h> again.\n\t* main.c (main): Handle SIGCHLD if defined, and SIGCLD if defined.\n\tIt doesn't hurt to do both if they are both defined, and testing\n\tUSG is useless.\n\t* dir.c: Rationalize directory header conditionals.\n\t* arscan.c [HAVE_FCNTL_H]: Test this rather than USG || POSIX.\n\n\t* default.c (default_suffixes): Add `.txinfo'.\n\t(default_suffix_rules): Add `.txinfo.info' and `.txinfo.dvi' rules.\n\n\t* variable.c (try_variable_definition): Replace RECURSIVE flag\n\twith enum FLAVOR, which can be simple, recursive, or append.\n\tRecognize += as append flavor.  Set new variable VALUE in a switch\n\ton FLAVOR.  For append flavor, prepend the variable's old value.\n\tIf the variable was previously defined recursive, set FLAVOR to\n\trecursive; if it was defined simple, expand the new value before\n\tappending it to the old value.  Pass RECURSIVE flag to\n\tdefine_variable iff FLAVOR == recursive.\n\n\t* variable.c (try_variable_definition): Use alloca and bcopy for\n\tNAME, instead of savestring.  Might as well use stack storage\n\tsince we free it immediately anyway.\n\nThu Apr  8 18:04:43 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (start_waiting_jobs): Move decl of JOB outside of loop.\n\n\t* main.c (define_makeflags): Rename `struct flag' member `switch'\n\tto `cs', which is not a reserved word.\n\nWed Apr  7 15:30:51 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (new_job): Call start_waiting_jobs first thing.\n\t(start_waiting_job): Changed return type from void to int.\n\tReturn 0 when putting the child on the waiting_jobs chain.\n\t(start_waiting_jobs): Don't check load and job_slots here.\n\tAlways take a job off the chain and call start_waiting_job on it;\n\tgive up and return when start_waiting_job returns zero.\n\n\t* main.c (define_makeflags: struct flag): Change member `char c' to\n\t`struct command_switch *switch'.\n\t(ADD_FLAG): Set that to CS instead of CS->c.\n\tIf CS->c is -1, increment FLAGSLEN for the long name.\n\tWhen writing out FLAGS, handle FLAGS->switch->c == -1 and write\n\tthe long name instead.\n\n\t* compatMakefile (stamp-config): New target of old config.h rule.\n\tTouch stamp-config after running config.status.\n\t(config.h): Just depend on stamp-config, and have empty commands.\n\nMon Apr  5 20:14:02 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c [HAVE_WAITPID]: #undef HAVE_UNION_WAIT.\n\n\t* configure.in (AC_HAVE_FUNCS): Check for psignal.\n\nFri Apr  2 17:15:46 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (long_option_aliases): Remove \"new\"; it is already an\n\tunambiguous prefix of \"new-file\".\n\nSun Mar 28 16:57:17 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.63.6.\n\nWed Mar 24 14:26:19 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* vpath.c (selective_vpath_search): When adding the\n\tname-within-directory at the end of NAME, and we don't add a\n\tslash, don't copy FILENAME in one char too far into NAME.\n\n\t* variable.c (define_automatic_variables): Find default_shell's\n\tlength with strlen, not numerology.\n\nWed Mar 17 20:02:27 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (define_makeflags): Add the elts of a string option in\n\treverse order, so they come out right when reversed again.\n\nFri Mar 12 15:38:45 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (make.info): Use `-o make.info'.\n\nThu Mar 11 14:13:00 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (REMOTE): Set to @REMOTE@; change comments to\n\treflect new use.\n\t(objs): Replace remote.o with remote-$(REMOTE).o.\n\t(srcs): Replace remote.c with remote-$(REMOTE).c.\n\t(remote.o): Rule removed.\n\n\t* configure.in (REMOTE): Subst this in Makefile et al; default \"stub\".\n\tUse AC_WITH to grok --with-customs arg to set REMOTE=cstms.\n\t* GNUmakefile (build.sh.in): Filter out remote-% from objs list.\n\t* build.template (REMOTE): New var; set to @REMOTE@.\n\t(objs): Add remote-${REMOTE}.o.\n\nWed Mar 10 15:12:24 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.63.5.\n\n\t* implicit.c (pattern_search): Fix \"dependent\"->\"dependency\" in\n\t\"Rejecting impossible\" -d msg.\n\n\t* file.c (file_hash_enter): New local vars {OLD,NEW}BUCKET.  Store\n\tmod'd values there; never mod {OLD,NEW}HASH.\n\nMon Mar  8 13:32:48 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* remake.c [eta10]: Include <fcntl.h> instead of <sys/file.h>.\n\n\t* compatMakefile (VPATH): Set this to @srcdir@.\n\t(srcdir): Set this to $(VPATH).\n\n\t* main.c (main): New local var DIRECTORY_BEFORE_CHDIR.  Save in it\n\ta copy of CURRENT_DIRECTORY after the first getcwd.  Use it\n\tinstead of CURRENT_DIRECTORY when chdir'ing back before re-execing.\n\n\t* remake.c (notice_finished_file): Pass missing SEARCH arg to f_mtime.\n\n\t* read.c (read_makefile): Remove extraneous arg to parse_file_seq.\n\nMon Feb 22 14:19:38 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile ($(infodir)/$(instname).info): Use , instead of /\n\tas the sed delimiter char.\n\nSun Feb 21 14:11:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.63.4.\n\n\t* rule.h (struct rule): Removed `subdir' member.\n\t* rule.c (new_pattern_rule): No need to clear it.\n\t(count_implicit_rule_limits): Set the `changed' flag in each dep\n\tthat refers to a nonexistent directory.  No longer set rule-global\n\t`subdir' flag with that information.\n\t(print_rule_data_base): Don't record info on `subdir' flags.\n\n\t* implicit.c (pattern_search): Check the DEP->changed flag rather\n\tthan the (now gone) RULE->subdir flag.  Also test CHECK_LASTSLASH;\n\tif it is set, the file might exist even though the DEP->changed\n\tflag is set.\n\n\t* rule.c (count_implicit_rule_limits): Pass \"\", not \".\", as file\n\tname arg to dir_file_exists_p to check for existence of directory.\n\n\t* implicit.c (pattern_search): Inside dep-finding loop, set\n\tCHECK_LASTSLASH from the value recorded in CHECKED_LASTSLASH[I],\n\trather than computing it anew.\n\n\t* commands.c (set_file_variables): Must alloca space for PERCENT\n\tand copy it, to avoid leaving the trailing `)' in the value.\n\n\t* misc.c (remove_comments): Fixed backslash-checking loop\n\tcondition to allow it to look at the first char on the line.\n\tP2 >= LINE, not P2 > LINE.\n\n\t* compatMakefile ($(bindir)/$(instname)): Before moving $@.new to\n\t$@, rm $@.old and mv $@ to $@.old.\n\n\t* variable.c (try_variable_definition): Take new args FILENAME and\n\tLINENO.  Fatal if the variable name is empty.\n\t* read.c (read_makefile): Change callers.\n\t* main.c (main): Likewise.\n\n\t* compatMakefile (group): Define to @KMEM_GROUP@, autoconf magic\n\tthat configure will replace with the group owning /dev/kmem.\n\nMon Feb  8 14:26:43 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* vpath.c (vpath_search): Take second arg MTIME_PTR, pass thru to\n\tselective_vpath_search.\n\t(selective_vpath_search): Take second arg MTIME_PTR.\n\tIf the dir cache thinks a file exists, stat it to make sure, and\n\tput the modtime in *MTIME_PTR.\n\t* remake.c (library_search): Take second arg MTIME_PTR.\n\tWhen we find a match, record its mtime there.\n\tPass MTIME_PTR through to vpath_search to do same.\n\t(f_mtime): Pass &MTIME as new 2nd arg to {vpath,library}_search;\n\tstore it in FILE->last_mtime if set nonzero.\n\t* implicit.c (pattern_search): Pass nil 2nd arg to vpath_search.\n\n\t* compatMakefile (remote.o): Prepend `$(srcdir)/' to `remote-*.c',\n\tso globbing looks somewhere it will find things.\n\n\t* compatMakefile ($(infodir)/$(instname).info): Install `make.info*'\n\tnot `$(srcdir)/make.info*'; no need to use basename.\n\nFri Feb  5 12:52:43 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.63.3.\n\n\t* compatMakefile (install): Add missing ;\\s.\n\n\tMake -, @, and + prefixes on a pre-expanded command line affect\n\tall lines in the expansion, not just the first.\n\t* commands.h (struct commands): Replace `lines_recurse' member\n\twith `lines_flags'.\n\t(COMMANDS_{RECURSE,SILENT,NOERROR}): New macros, bits to set in\n\tthat flag byte.\n\t* commands.c (chop_commands): Set `lines_flags' instead of\n\t`lines_recurse'.  Record not only + but also @ and - prefixes.\n\t* remake.c (notice_finished_file): Check the COMMANDS_RECURSE bit\n\tin FILE->cmds->lines_flags, rather than FILE->cmds->lines_recurse.\n\t* job.c (start_job_command): Replaced RECURSIVE and NOPRINT local\n\tvar with FLAGS; initialize it to the appropriate `lines_flags' byte.\n\tSet CHILD->noerror if the COMMANDS_NOERROR bit is set in FLAGS.\n\tSet the COMMANDS_SILENT bit in FLAGS for a @ prefix.\n\n\t* remake.c (update_goal_chain): Set G->file to its prev after\n\tchecking for G being finished, since that check needs to examine\n\tG->file.\n\n\t* configure.in (union wait check) [HAVE_WAITPID]: Try using\n\twaitpid with a `union wait' STATUS arg.  If waitpid and union wait\n\tdon't work together, we should not use union wait.\n\n\t* Version 3.63.2.\n\n\t* remake.c (update_goal_chain): When G->file->updated, move\n\tG->file to its prev.  We aren't finished until G->file is nil.\n\nThu Feb  4 12:53:04 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (starting_directory): New global variable.\n\t(main): Set it to cwd after doing -Cs.\n\t(log_working_directory): Use it, rather than computing each time.\n\t* make.h: Declare it.\n\n\t* compatMakefile (SHELL): Define to /bin/sh for losing Unix makes.\n\n\t* main.c (decode_env_switches): Allocate (1 + LEN + 1) words for\n\tARGV, rather than LEN words plus one byte.\n\nWed Feb  3 18:13:52 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile ($(bindir)/$(instname)): Put - before\n\tinstall_setgid command line, so its failure won't be an error.\n\t(infodir): New variable.\n\t(install): Depend on $(infodir)/$(instname).info.\n\t($(infodir)/$(instname).info): New target.\n\n\t* read.c (read_makefile): If FILENAMES is nil when we see a line\n\tstarting with a tab, don't treat it as a command.  Just fall\n\tthrough, rather than giving an error.\n\n\t* read.c (read_makefile): If the NO_TARGETS flag is set when we see a\n\tcommand line, don't clear it before continuing.  We want\n\tsubsequent command lines to be ignored as well.\n\n\t* job.c (new_job): Before expanding each command line, collapse\n\tbackslash-newline combinations that are inside var or fn references.\n\nMon Feb  1 16:00:13 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (exec_prefix): Default to $(prefix), not /usr/local.\n\n\t* compatMakefile (make.info): Pass -I$(srcdir) to makeinfo.\n\n\t* job.c [POSIX] (unblock_sigs): Made global.\n\t[!POSIX] (unblock_sigs): Move defns to job.h.\n\t* job.h [POSIX] (unblock_sigs): Declare.\n\nSun Jan 31 19:11:05 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): In vpath parsing, after finding the\n\tpattern token, take entire rest of line as the search path, not\n\tjust the next token.\n\n\t* compatMakefile (remote.o): Depend on remote-*.c.\n\nThu Jan 28 16:40:29 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* commands.c (set_file_variables): Don't define any F or D versions.\n\t* variable.c (define_automatic_variables): Define them here as\n\trecursively-expanded variables that use the dir and notdir funcs.\n\n\t* variable.c (target_environment): In v_default case, don't export\n\to_default or o_automatic variables.\n\n\t* configure.in (union wait check): Remove ` and ' inside C code;\n\tthey confuse the shell script.\n\nMon Jan 25 13:10:42 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.63.1.\n\n\t* vpath.c (construct_vpath_list): When skipping further processing\n\tof an elt that is \".\", don't also skip the code that pushes P past\n\tthe next separator.\n\n\t* compatMakefile (distclean): Don't remove make-*.\n\n\t* configure.in (HAVE_UNION_WAIT): Try to use WEXITSTATUS if it's\n\tdefined.  If one cannot use WEXITSTATUS with a `union wait'\n\targument, we don't want to believe the system has `union wait' at all.\n\n\t* remake.c (update_file): Do nothing to print \"up to date\" msgs.\n\t(update_goal_chain): Do it here instead.\n\tUse the `changed' flag of each goal's `struct dep' to keep track\n\tof whether files_remade (now commands_started) changed around a\n\tcall to update_file for that goal.\n\tWhen a goal is finished, and its file's update_status is zero (i.e.,\n\tsuccess or nothing done), test the `changed' flag and give an \"up\n\tto date\" msg iff it is clear.\n\t* make.h (files_remade): Renamed to commands_started.\n\t* remake.c: Changed defn.\n\t(update_goal_chain): Changed uses.\n\t* job.c (start_job_command): Increment commands_started here.\n\t(reap_children): Not here.\n\n\t* remake.c (update_goal_chain): Don't do anything with files'\n\t`prev' members.  update_file now completely handles this.\n\n\t* variable.c (target_environment): Don't expand recursive\n\tvariables if they came from the environment.\n\n\t* main.c (define_makeflags): For flags with omitted optional args,\n\tstore {\"\", 0} with ADD_FLAG.  When constructing FLAGSTRING, a flag\n\tso stored cannot have more flags appended to the same word.\n\nFri Jan 22 14:46:16 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (print_variable_set): In vars/bucket calculation,\n\tdon't spuriously multiply by 100.\n\n\t* Version 3.63.\n\n\t* job.c [!HAVE_UNION_WAIT] (WTERMSIG, WCOREDUMP, WEXITSTATUS):\n\tDon't define if already defined.\n\n\t* remake.c (update_file): Don't keep track of the command_state before\n\tcalling update_file_1.  Remove local variable COMMANDS_FINISHED,\n\tand don't test it to decide to print the \"is up to date\" msg.\n\tTesting for files_remade having changed should always be sufficient.\n\tThe old method lost when we are called in the goal chain run on a\n\tmakefile, because the makefile's command_state is already\n\t`cs_finished' from the makefile chain run.\n\n\t* misc.c [HAVE_SETRE[GU]ID]: Test these to decl setre[gu]id.\n\n\t* configure.in: Rewrote wait checking.\n\tUse AC_HAVE_HEADERS to check for <sys/wait.h>.\n\tUse AC_HAVE_FUNCS to check for waitpid and wait3.\n\tUse a compile check to test just for `union wait'.\n\t* job.c: Rewrote conditionals accordingly.\n\t[HAVE_WAITPID]: Test this only to define WAIT_NOHANG.\n\t[HAVE_WAIT3]: Likewise.\n\t[HAVE_UNION_WAIT]: Test this to define WAIT_T and W*.\n\n\t* configure.in: Set CFLAGS and LDFLAGS before all checks.\n\n\t* dir.c: Add static forward decls of {open,read}_dirstream.\n\nThu Jan 21 17:18:00 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.31.\n\n\t* job.c [NGROUPS_MAX && NGROUPS_MAX==0]: #undef NGROUPS_MAX.\n\n\t* compatMakefile (CFLAGS, LDFLAGS): Set to @CFLAGS@/@LDFLAGS@.\n\t* build.template (CFLAGS, LDFLAGS): Same here.\n\t* configure.in: AC_SUBST(CFLAGS) and LDFLAGS.\n\tSet them to -g if not defined in the environment.\n\n\t* remake.c (library_search): Use LIBNAME consistently, setting it\n\tonly once, to be the passed name sans `-l'.\n\tPass new var FILE to be modified by vpath_search.\n\nMon Jan 18 14:53:54 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.30.\n\n\t* job.c (start_waiting_jobs): Return when job_slots_used is equal to\n\tjob_slots.\n\n\t* configure.in: Add AC_CONST for the sake of getopt.\n\n\t* read.c (read_makefile): Continue after parsing `override'\n\tdirective, rather than falling through to lossage.\n\tCheck for EOL or blank after \"override define\".\n\n\t* compatMakefile (.c.o, remote.o): Put $(CFLAGS) after other switches.\n\nFri Jan 15 12:52:52 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.29.\n\n\t* main.c (define_makeflags): After writing everything into\n\tFLAGSTRING, only back up two chars if [-1] is a dash, meaning we\n\tjust wrote \" -\".  Always terminate the string at *P.\n\n\t* remake.c (library_search): When constructing names in std dirs,\n\tuse &(*LIB)[2] for the stem, not LIBNAME (which points at the\n\tbuffer we are writing into!).\n\nThu Jan 14 13:50:06 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Set IN_IGNORED_DEFINE for \"override\n\tdefine\" when IGNORING is true.\n\n\t* compatMakefile (distclean): Remove config.status and build.sh.\n\nWed Jan 13 16:01:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.28.\n\n\t* misc.c (xmalloc, xrealloc): Cast result of malloc/realloc to\n\t(char *).\n\n\t* arscan.c (ar_scan) [AIAMAG]: Cast read arg to (char *).\n\n\t* variable.c (define_automatic_variables): Override SHELL value for\n\torigin o_env_override as well as o_env.\n\n\t* GNUmakefile (build.sh.in): Don't replace %globobjs%.  Instead,\n\tadd the names of the glob objects (w/subdir) to %objs%.\n\t* build.template (globobjs): Removed.\n\tTake basename of $objs before linking.\n\nTue Jan 12 12:31:06 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.27.\n\n\t* configure.in (AC_OUTPUT): Also edit build.sh.\n\t* build.template: New file.\n\t* GNUmakefile (build.sh.in): New rule to create it from build.template.\n\t(make-$(version).tar.Z): Depend on build.sh.in.\n\n\t* main.c (die): Call print_data_base if -p.\n\t(main): Don't call it here.\n\n\t* compatMakefile (defines): Add @DEFS@.  configure should turn this\n\tinto -DHAVE_CONFIG_H.\n\nMon Jan 11 14:39:23 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.26.\n\n\t* misc.c (init_access): Surround with #ifdef GETLOADAVG_PRIVILEGED.\n\t({make,user,child}_access) [! GETLOADAVG_PRIVILEGED]: Make no-op.\n\t* compatMakefile (install_setgid): New var, set by configure.\n\t(install): Install setgid $(group) only if $(install_setgid) is true.\n\nFri Jan  8 15:31:55 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (load_too_high): If getloadavg fails with errno==0, give a\n\tmessage saying that load limits are not supported.\n\n\t* vpath.c (construct_vpath_list): Rewrote path deletion code to\n\tnot try to use PATH's next link after freeing PATH.\n\n\t* main.c (define_makeflags): Rewritten; now handles string-valued\n\toption, and has no arbitrary limits.\n\t(switches): Set `toenv' flag for -I and -v.\n\n\t* main.c (decode_env_switches): Cast return value of alloca to char *.\n\n\t* misc.c (child_access) [HAVE_SETREUID, HAVE_SETREGID]: Use\n\tsetre[gu]id in place of set[gu]id.\n\nWed Jan  6 15:06:12 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): Define MAKEOVERRIDES, MAKE, and MAKE_COMMAND with\n\torigin o_default.\n\n\t* make.h [POSIX]: Don't test this to use ANSI_STRING.\n\tTesting STDC_HEADERS should be sufficient.\n\n\t* job.h: Declare start_waiting_jobs.\n\n\t* read.c (read_makefile): Add missing parens in if stmt that find\n\tconditional directives.\n\n\t* main.c (main): Declare init_dir.\n\t* implicit.c (pattern_search): Always use two % specs in a\n\tDEBUGP2, and always pass two non-nil args.\n\tCast field width args to int.\n\tAdd missing parens in !RULE->subdir if stmt.\n\t* function.c (expand_function, patsubst_expand): Add parens around\n\tassignments inside `while' stmts.\n\t* commands.c (print_commands): Cast field width args to int.\n\n\t* read.c (do_define): Cast return value of alloca to (char *).\n\n\t* main.c (init_switches): New function, broken out of decode_switches.\n\t(decode_switches): Take new arg ENV.  If set, ignore non-option\n\targs; print no error msgs; ignore options with clear `env' flags.\n\t(decode_env_switches): Rewritten to chop envar value into words\n\tand pass them to decode_switches.\n\t(switches): Set `env' flag for -I and -v.\n\n\t* dir.c (init_dir): Cast free to __glob_closedir_hook's type.\n\nTue Jan  5 14:52:15 1993  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.25.\n\n\t* job.c [HAVE_SYS_WAIT || !USG]: Don't #include <sys/time.h> and\n\t<sys/resource.h>.  <sys/time.h> interacts badly with <time.h>, and\n\twe don't need these anyway.\n\n\t* configure.in (AC_HAVE_FUNCS): Check for setre[gu]id.\n\t* misc.c ({user,make}_access): Test #ifndef HAVE_SETRE[GU]ID, not\n\t#ifdef POSIX || USG.  SunOS 4.1 is supposedly POSIX.1 compliant,\n\tbut its set[gu]id functions aren't; its setre[gu]id functions work.\n\n\t* misc.c ({user,make,child}_access): Give name of caller in error msgs.\n\n\t* job.c (load_too_high): Say \"cannot enforce load limit\" in error msg.\n\n\t* configure.in: Call AC_PROG_CC.\n\t* compatMakefile (CC): Define to @CC@ (autoconf magic).\n\n\t* compatMakefile: Add .NOEXPORT magic target.\n\nMon Jan  4 17:00:03 1993  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (print_version): Updated copyright to include 93.\n\nThu Dec 31 12:26:15 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* make.h [_AIX]: Don't declare alloca.\n\nTue Dec 29 13:45:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.24.\n\n\t* compatMakefile (objs): Add signame.o.\n\t(srcs): Add signame.[ch].\n\n\t* compatMakefile (srcs): Add config.h.in.\n\t(remote.o): Add -I. before -I$(srcdir).\n\nMon Dec 28 15:51:26 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.23.\n\n\t* read.c (readline): Fatal when LEN==0, indicating a line starting\n\twith a NUL.\n\t(readline): Take new arg LINENO, for use in error msg.\n\t(read_makefile, do_define): Pass it.\n\n\t* compatMakefile (glob/libglob.a): Pass -DHAVE_CONFIG_H in CPPFLAGS.\n\t(.c.o): Add -I. before -I$(srcdir).\n\nWed Dec 23 12:12:04 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Accept and ignore a rule with no targets.\n\n\t* compatMakefile (ALLOCA_SRC): New variable.\n\t(srcs): Include its value.\n\n\t* read.c (struct conditional): Renamed member `max_ignoring' to\n\t`allocated'; added new member `seen_else'.\n\t(conditional_line): Initialize seen_else flag when starting an `if...';\n\tset it when we see an `else'; fatal if set when we see `else'.\n\t(read_makefile): Fatal \"missing `endif'\" if there are any pending\n\tconditionals, not just if we are still ignoring.\n\nTue Dec 22 15:36:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (manext): Set to 1, not l.\n\t($(mandir)/$(instname).$(manext)): Use $(srcdir) for make.man in cmds.\n\n\t* file.c (file_hash_enter): Don't call uniquize_deps here.\n\t* read.c (record_files): Likewise.\n\t* implicit.c (pattern_search): Likewise.\n\t* commands.c (set_file_variables): Call it only here.\n\n\t* default.c (default_variables) [__convex__]: FC=fc.\n\n\t* variable.c (target_environment): Expand the values of recursively\n\texpanded variables when putting them into the environment.\n\t* expand.c (recursively_expand): Made global.\n\t* make.h (recursively_expand): Declare it.\n\n\t* remake.c (check_dep): Set FILE->command_state to cs_deps_running\n\twhen a dep's command_state is cs_running or cs_deps_running.\n\n\t* read.c (read_makefile): Changed error msg for spurious cmds to\n\tnot say \"first target\".\n\nSun Dec 20 17:56:09 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* configure.in: Do AC_CONFIG_HEADER right after AC_INIT.\n\t* make.h (HAVE_CONFIG_H): #include \"config.h\", then #define this.\n\t* compatMakefile (config.h, configure, config.h.in): New rules.\n\t(defines): Removed @DEFS@.\n\nThu Dec 17 16:11:40 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (realclean): Just depend on distclean; no cmds.\n\t(distclean): Do what realclean did before; also remove Makefile and\n\tconfig.h; don't remove configure.\n\t(info, dvi): New targets; depend on make.{info,dvi}.\n\t(doc): Removed target.\n\t(MAKEINFO, TEXI2DVI): New vars.\n\t(make.info, make.dvi): Use them instead of explicit cmds.\n\nWed Dec 16 16:25:24 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* configure.in: Added fcntl.h to AC_HAVE_HEADERS.  getloadavg cares.\n\nWed Dec  9 15:21:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (long_option_aliases): Add --new-file alias for -W.\n\n\t* default.c (default_variables): Change all C++ to CXX and C++FLAGS\n\tto CXXFLAGS.\n\n\t* read.c (do_define): Expand the variable name before using it.\n\n\t* main.c (main): Define variable \"MAKE_COMMAND\" to argv[0];\n\tdefine \"MAKE=$(MAKE_COMMAND) $(MAKEOVERRIDES)\" always.\n\n\t* remake.c (library_search): Search for libNAME.a in cwd; look in\n\tvpath before looking in standard dirs, not after.\n\tChanged order of std dirs to: /lib, /usr/lib, ${prefix}/lib.\n\nMon Nov 23 14:57:34 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* default.c (default_pattern_rules, default_terminal_rules): Added\n\tbrackets around initializers.\n\n\t* variable.c (try_variable_definition): Don't check for LINE[0]=='\\t'.\n\t(try_variable_definition): Expand the name before defining the var.\n\n\t* job.c (init_siglist): Removed function.\n\tRemoved decl of `sys_siglist'.\n\t* make.h [! HAVE_SYS_SIGLIST]: #include \"signame.h\".\n\t[HAVE_SYS_SIGLIST && !SYS_SIGLIST_DECLARED]: Declare sys_siglist\n\tonly under these conditions.\n\t* main.c (main): Don't declare init_siglist.\n\t(main) [! HAVE_SYS_SIGLIST]: Call signame_init instead of init_siglist.\n\nWed Nov 18 14:52:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (record_files): Don't try to append to FIRSTDEPS if it's\n\tnil; instead just set it to MOREDEPS.\n\nMon Nov 16 17:49:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* vpath.c (construct_vpath_list): Initialize P to DIRPATH before\n\tloop that sets MAXELEM.\n\nFri Nov 13 18:23:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.22.\n\nThu Nov 12 15:45:31 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (start_job_command): Under -n, increment files_remade after\n\tprocessing (i.e., printing) all command lines.\n\nTue Nov 10 15:33:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* read.c (record_files): Append new deps if this rule has no\n\tcommands; prepend them to existing deps if this rule has no commands.\n\n\t* dir.c (open_dirstream): Return nil if DIR->contents->files is nil.\n\n\t* read.c (parse_file_seq): Removed last arg STRIP.  Always strip `./'s.\n\t(read_makefile): Changed callers.\n\t* function.c (string_glob): Likewise.\n\t* rule.c (install_pattern_rule): Likewise.\n\nMon Nov  9 17:50:16 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (files_remade): Made global.\n\t(notice_finished_file): Don't increment files_remade here; this\n\tfunction gets called in many situations where no remaking was in\n\tfact done.\n\t* job.c (reap_children): Do it here instead, when we know that\n\tactual commands have been run for the file.\n\t* make.h (files_remade): Declare it.\n\nThu Nov  5 18:26:10 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* vpath.c (construct_vpath_list): Allow blanks as well as colons to\n\tseparate elts in the search path.\n\n\t* read.c (read_makefile): Don't fatal on extra tokens in `vpath'.\n\tThe search path can contain spaces now.\n\nTue Nov  3 20:44:32 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (check): New target; no-op.\n\n\t* file.c (file_hash_enter): Mod OLDHASH by FILE_BUCKETS after\n\ttesting for OLDHASH==0 but before using the value.\n\t(rename_file): Don't mod OLDHASH by FILE_BUCKETS before passing it\n\tto file_hash_enter.\n\n\t* file.c (rename_file): Notice when OLDFILE->cmds came from\n\tdefault.c, and don't try to print ->filename in that case.\n\nSun Oct 25 01:48:23 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (update_file): Don't process F->also_make here.\n\t(notice_finished_file): Don't process FILE->also_make if no attempt\n\tto update FILE was actually made.\n\tFixed to call f_mtime directly to refresh their modtimes.\n\nSat Oct 24 22:08:59 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (find_percent): Don't increment P again after skipping\n\tan escaped %.\n\n\t* expand.c (variable_expand): In call to patsubst_expand, don't\n\tfind `%'s ourselves; let that function do it.\n\n\t* read.c (read_makefile: record_waiting_files): Don't call\n\trecord_files if FILENAMES is nil.\n\t(read_makefile): All alternatives in the parsing, except for rule\n\tlines, fall through to the end of the loop.  At the end of the\n\tloop, do record_waiting_files so we notice later spurious cmds.\n\nFri Oct 23 15:57:37 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (define_automatic_variables): Free old value of SHELL\n\tbefore replacing it.\n\nThu Oct 15 18:57:56 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (.c.o): Add -I$(srcdir)/glob to flags.\n\n\t* dir.c (open_dirstream): Cast return value to __ptr_t.\n\n\t* default.c (default_variables: \"GET\") [_IBMR2]: Use USG defn.\n\n\t* make.h (MAXPATHLEN): Moved out of #ifndef POSIX.\n\t(GET_PATH_MAX): Moved from #ifdef POSIX to #ifdef PATH_MAX #else.\n\tDefine as (get_path_max ()).\n\t[! PATH_MAX] (NEED_GET_PATH_MAX): Define.\n\t[! PATH_MAX] (get_path_max): Declare fn.\n\t* misc.c [NEED_GET_PATH_MAX] (get_path_max): New function.\n\nMon Oct 12 13:34:45 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.21.\n\n\t* job.c (sys_siglist): Only declare #ifndef SYS_SIGLIST_DECLARED.\n\t* make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define\n\tSYS_SIGLIST_DECLARED.\n\n\t* dir.c (file_impossible): When initializing DIR->contents, set\n\tDIR->contents->dirstream to nil.\n\n\t* compatMakefile (GLOB): Define new variable.\n\t(objs): Use it, rather than glob/libglob.a explicitly.\n\n\t* read.c (parse_file_seq): When stripping \"./\", handle cases like\n\t\".///foo\" and \"./////\".\n\t* file.c (lookup_file, enter_file): Likewise.\n\nSun Oct 11 17:00:35 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* dir.c (struct dirstream, {open,read}_dirstream): New\n\tdata type and functions to read a directory sequentially.\n\t(init_dir): New function to hook it into glob.\n\t* main.c (main): Call init_dir.\n\n\t* compatMakefile (objs): Added glob/libglob.a.\n\t* configure.in: Remove code to test for glob.\n\nFri Oct  9 12:08:30 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (record_files): Generalized test for NAME pointing\n\tsomewhere into F->name.\n\n\t* variable.c (define_variable_in_set): Free old value when replacing.\n\n\t* read.c (do_define): Free the linebuffer before returning.\n\t(record_files): When clearing .SUFFIXES deps, free their data.\n\t(multi_glob): Free OLD and its data when replacing it with results\n\tof glob run.\n\n\t* commands.c (set_file_variables): Use alloca in place of xmalloc\n\tfor temp space for $^, $?, et al.\n\n\t* dir.c (struct directory): New member `contents' replaces `files'\n\tand `dirstream'.\n\t(struct directory_contents): New type.\n\t(directories_contents): New hash table.\n\t(dir_struct_file_exists_p): Take a struct directory_contents.\n\t(dir_file_exists_p): Pass it the `contents' member of the dir found.\n\t(dir_struct_file_exists_p): Renamed to dir_contents_file_exists_p;\n\tmade static.  Return 0 if DIR is nil (meaning it couldn't be stat'd).\n\t(dir_file_exists_p, find_directory): Change all callers.\n\t(file_impossible): Use DIR->contents, initializing it if nil.\n\t(print_dir_data_base): Use DIR->contents, and print out device and\n\tinode numbers with each directory.\n\n\t* Changes for performance win from John Gilmore <gnu@cygnus.com>:\n\t* dir.c (DIRECTORY_BUCKETS): Increase to 199.\n\t(DIRFILE_BUCKETS): Decrease to 107.\n\t(find_directory): Allocate and zero a multiple of\n\tsizeof (struct dirfile *), not of sizeof (struct dirfile).\n\t(dir_struct_file_exists_p): New function, nearly all code from\n\tdir_file_exists_p.\n\t(dir_file_exists_p): Just call find_directory+dir_struct_file_exists_p.\n\t* vpath.c (selective_vpath_search): Remove redundant\n\tdir_file_exists_p call.\n\n\t* configure.in: Comment out glob check; always use our code.\n\nFri Oct  2 19:41:20 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define\n\tHAVE_SYS_SIGLIST; after doing #define sys_siglist _sys_siglist, we\n\tdo have it.\n\nWed Sep 30 19:21:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (main): Don't do -w automatically if -s.\n\nTue Sep 29 21:07:55 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (printed_version): Move variable inside print_version.\n\t(print_version): Return immediately if printed_version is set.\n\t(die): Don't test printed_version here.\n\t(decode_switches): Under -v, do print_version before giving usage.\n\t(DESCRIPTION_COLUMN): New macro.\n\t(decode_switches): Use it when printing the usage message.\n\tLeave at least two spaces between options and their descriptions.\n\nFri Sep 25 13:12:42 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.20.\n\nWed Sep 16 16:15:22 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Save errno value from trying to open\n\tFILENAME, and restore it before erring; otherwise we get the errno\n\tvalue from the last elt of the search path.\n\nTue Sep 15 15:12:47 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (long_option_aliases): Add --stop for -S.\n\n\t* read.c (word1eq): Do strncmp before dereferencing someplace that\n\tmay be out in space.\n\nWed Sep  9 15:50:41 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (notice_finished_file): If all the command lines were\n\trecursive, don't do the touching.\n\n\t* job.c (start_job_command): Don't check for + here.\n\t* commands.c (chop_commands): Do it here instead.\n\n\t* default.c (default_terminal_rules): Prepend + to cmds for RCS.\n\nWed Sep  2 17:53:08 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (objs): Include $(ALLOCA).\n\n\t* make.h [CRAY]: Move #define signal bsdsignal to before #includes.\n\nThu Aug 27 17:45:43 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* read.c (default_include_directories): Add INCLUDEDIR first.\n\t* compatMakefile (includedir): Define.\n\t(defines): Add -D for INCLUDEDIR=\"$(includedir)\".\n\n\t* read.c (read_makefile): Grok multiple files in `include';\n\tglobbing too.\n\n\t* remake.c (library_search): New function.\n\t(library_file_mtime): Remove function.\n\t(f_mtime): Use library_search instead of library_file_mtime.\n\t* compatMakefile (libdir): Define.\n\t(defines): Add -D for LIBDIR=\"$(libdir)\".\n\t* make.texinfo (Libraries/Search): Document change.\n\n\t* file.c (rename_file): Fix file_hash_enter call with missing arg.\n\nWed Aug 26 17:10:46 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.19.\n\n\t* main.c (main): Set command_state to cs_finished for temp files\n\tmade for stdin makefiles.\n\n\t* main.c (decode_switches): Don't tell getopt to return non-option\n\targs in order.\n\tIgnore an argument of `-'.\n\nThu Aug 20 13:36:04 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c (start_job_command): If (touch_flag && !RECURSIVE), ignore\n\tthe command line and go to the next.\n\t(notice_finished_file): Under -t, touch FILE.\n\t* remake.c (remake_file): Don't touch it here.\n\nWed Aug 19 16:06:09 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* function.c (pattern_matches): Use temporary for strlen (WORD)\n\tinstead of two function calls.\n\n\t* compatMakefile (LOAD_AVG): Remove variable and comments.\n\nTue Aug 18 14:58:58 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* make.texinfo (Running): Node renamed to `make Invocation'.\n\nFri Aug 14 12:27:10 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* arscan.c (ar_name_equal): Don't compare [MAX-3..MAX] if\n\tNAMELEN != MEMLEN.\n\nThu Aug 13 17:50:09 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.18.\n\n\t* main.c: Don't #include <time.h>; make.h already does.\n\nMon Aug 10 17:03:01 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* implicit.c (pattern_search): Fixed copying of suffix when building\n\talso_make elts.\n\n\t* function.c (expand_function: `shell'): Make sure BUFFER is\n\tnull-terminated before replacing newlines.\n\n\t* compatMakefile (mandir): Use man$(manext), not always manl.\n\nSun Aug  2 01:42:50 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* rule.c (new_pattern_rule): Not static.\n\t* rule.h: Declare it.\n\n\t* file.c (file_hash_enter): New function, most code from rename_file.\n\t(rename_file): Call it.\n\t* file.h (file_hash_enter): Declare it.\n\n\t* dep.h: Doc fix.\n\nThu Jul 30 15:40:48 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (decode_switches): Handle usage_and_exit when building\n\tlong options vector.\n\n\t* default.c (default_terminal_rules): Make RCS rules use $(CHECKOUT,v).\n\t(default_variables): Define CHECKOUT,v (hairy).\n\n\t* make.h [!HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define\n\tsys_siglist to _sys_siglist.\n\nSun Jul 26 16:56:32 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* NEWS: Add header and tail copyright info like Emacs NEWS.\n\n\t* make.h [ANSI_STRING]: Don't #define index, rindex, bcmp, bzero,\n\tbcopy if already #define'd.\n\t[STDC_HEADERS] (qsort, abort, exit): Declare here.\n\t[! __GNU_LIBRARY__ && !POSIX]: Not here.\n\n\t* make.h [_AIX]: #pragma alloca first thing.\n\n\t* job.c (start_waiting_job): Set the command_state to cs_running\n\twhen we queue a job on waiting_jobs.\n\nFri Jul 24 02:16:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.c (define_automatic_variables): Use \"\" instead of nil\n\tfor empty value.\n\nThu Jul 23 22:31:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.17.\n\n\t* main.c (struct command_switch.type): Add alternative usage_and_exit.\n\t(command_switches): Add -h/--help.\n\nThu Jul 16 14:27:50 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* GNUmakefile (make-$(version).tar.Z): Include NEWS, not CHANGES.\n\t* README.template: Mention NEWS.\n\t* CHANGES: Renamed to NEWS.\n\n\t* main.c [! STDC_HEADERS] [sun]: Don't declare exit.\n\nTue Jul 14 18:48:41 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): Set -o files' command_states to cs_finished.\n\n\t* rule.c (count_implicit_rule_limits): Decrement num_pattern_rules\n\twhen tossing a rule.\n\n\t* main.c (main): Use alloca only in simple local var assignment,\n\tfor braindead SGI compiler.\n\n\t* rule.c (print_rule_data_base): Barf if num_pattern_rules is\n\tinconsistent with the number computed when listing them.\n\nMon Jul 13 17:51:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* commands.c (set_file_variables): For $? and $^ elts that are archive\n\tmember refs, use member name only.\n\nFri Jul 10 00:05:04 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* variable.h (struct variable.export): Add new alternative v_ifset.\n\t* variable.c (target_environment): Check for it.\n\t(define_automatic_variables): Set it for MAKEFILES.\n\nThu Jul  9 21:24:28 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (objs): Remove getloadavg.o; $(extras) gets it.\n\t(remote.o): Use $(srcdir)/remote.c, not $remote.c<.\n\t(distclean, mostlyclean): New targets.\n\nTue Jul  7 19:12:49 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.16.\n\n\t* compatMakefile (config.status): Remove rule.\n\n\t* job.c (start_waiting_job): Free C after using C->file, not before.\n\nSat Jul  4 20:51:49 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* commands.c, job.c, main.c, make.h, remote-cstms.c: Use #ifdef\n\tHAVE_* instead of #ifndef *_MISSING.\n\t* configure.in: Use AC_HAVE_FUNCS instead of AC_MISSING_FUNCS (gone).\n\nThu Jul  2 18:47:52 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* main.c (main): makelevel>0 or -C implies -w.\n\nTue Jun 30 20:50:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* file.c, job.c, function.c: Don't #include <errno.h>.\n\tmake.h: Do it here instead.\n\t* arscan.c (ar_member_touch): Don't declare errno.\n\nThu Jun 25 17:06:55 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* GNUmakefile (make-$(version).tar.Z): Depend on INSTALL, configure.in.\n\n\t* remake.c (update_file): If commands or deps are running after\n\tupdate_file_1 returns, break out of the :: rule (->prev) loop and\n\tjust return.\n\n\t* job.c\t(job_next_command): New function; code from start_job.\n\t(start_job_command): Renamed from start_job.  Call job_next_command\n\tand recurse for empty command lines and -n.\n\t(start_waiting_job): Call start_job_command, not start_job.\n\t(new_job): Call job_next_command to prime the child structure, and\n\tthen call start_waiting_job.\n\t(reap_children): Use job_next_command and start_job_command.\n\t(start_waiting_job): Call start_remote_job_p here, and store its\n\tresult in C->remote.  If zero, check the load average and\n\tmaybe put C on waiting_jobs.\n\t(start_job_command): Test CHILD->remote rather than calling\n\tstart_remote_job_p.  Don't do load avg checking at all here.\n\n\t* main.c (main): Don't handle SIGILL, SIGIOT, SIGEMT, SIGBUS,\n\tSIGSEGV, SIGFPE or SIGTRAP.\n\n\t* compatMakefile (glob/libglob.a): Don't pass srcdir to sub-make.\n\tconfigure will set it in glob/Makefile.\n\nWed Jun 24 19:40:34 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* dir.c [DIRENT] (direct): Don't define to dirent.\n\t[! DIRENT] (direct): Define to dirent.\n\t(dir_file_exists_p): Use struct dirent instead of struct direct.\n\n\t* make.h (getcwd): No space between macro and ( for args!\n\n\t* job.c (start_job): Don't put the job on waiting_jobs if\n\tjob_slots_used==0.\n\n\t* make.texinfo (Missing): Shortened title.\n\nTue Jun 23 18:42:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* file.c (remove_intermediates): Print \"rm\" commands under -n.\n\nMon Jun 22 16:20:02 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.15.\n\nFri Jun 19 16:20:26 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* arscan.c [M_UNIX]: #undef M_XENIX.\n\nWed Jun 17 17:59:28 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* default.c (default_terminal_rules): Put @ prefix on RCS cmds.\n\nTue Jun 16 19:24:17 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile (getloadavg.o): Removed special rule.\n\t(CFLAGS): Don't include $(defines).\n\t(.c.o): Define suffix rule.\n\t(glob/libglob.a): Pass CPPFLAGS=$(defines) to submake.\n\t(GETOPT_SRC, srcs, tagsrcs): Prefix files with $(srcdir)/.\n\n\t* arscan.c (ar_name_equal): Moved local vars inside #if'd block.\n\n\t* make.h (max): Removed.\n\t* expand.c (variable_buffer_output): Don't use it.\n\n\t* compatMakefile (INSTALL): Define.\n\t(Makefile): New rule to make from Makefile.in.\n\t(srcdir): Define.\n\t(VPATH): Define.\n\t(getloadavg.o, remote.o): Use autoconf $foo< hack.\n\n\t* commands.c (fatal_error_signal): Removed return.\n\nMon Jun 15 17:42:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.14.\n\n\t* make.texinfo (Summary): New node.\n\t(Special Targets): Mention .EXPORT_ALL_VARIABLES here.\n\n\t* variable.c (max): Moved to make.h.\n\n\t* compatMakefile (objs, srcs): Added ar & arscan.\n\n\t* job.c (start_waiting_job): New function, 2nd half of new_job.\n\t(new_job): Call it.\n\t(start_waiting_jobs): New function.\n\t* remake.c (update_goal_chain): Call start_waiting_jobs at the top\n\tof the main loop.\n\t* compatMakefile (objs, srcs): Removed load, added getloadavg.\n\nFri Jun 12 19:33:16 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c (load_too_high): New function.  Uses getloadavg.\n\t(waiting_jobs): New variable.\n\t(start_job): Don't call wait_to_start_job.  Instead, if\n\tload_too_high returns nonzero, add the child to the\n\t`waiting_jobs' chain and return without starting the job.\n\nThu Jun 11 00:05:28 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* expand.c (variable_buffer_output): Made global again.\n\t* variable.h: And declare it.\n\n\t* arscan.c (PORTAR): Define for all systems if PORT5AR is not defined.\n\t(AR_NAMELEN, AR_TRAILING_SLASH): Removed.\n\t(ar_scan): Don't use it.  Don't #ifdef AR_TRAILING_SLASH; just look\n\tfor a slash in the archive at run time.\n\t(ar_name_equal): Rewrote .o hacking to not use AR_NAMELEN, and to\n\tcope with trailing-slash and non-trailing-slash archives.\n\n\t* main.c (main) [! SETVBUF_REVERSED]: Test this instead of USGr3 et al.\n\t[SETVBUF_REVERSED]: Always allocate a buffer ourselves.\n\n\t* load.c (load_average) [sgi]: Use sysmp call.\n\n\t* compatMakefile (INSTALL_DATA, INSTALL_PROGRAM): Define.\n\t($(bindir)/$(instname), $(mandir)/make.$(manext)): Use them.\n\n\t* make.h [HAVE_VFORK_H]: #include <vfork.h>.\n\t(vfork, VFORK_NAME): Don't define.\n\t* job.c (start_job): Use \"vfork\" in place of VFORK_NAME.\n\n\t* make.h [HAVE_LIMITS_H, HAVE_SYS_PARAM_H]: If #define'd, #include\n\tthe each file.  Rearranged PATH_MAX hacking.\n\t* job.c: Rearranged NGROUPS_MAX hacking.\n\n\t* remake.c (fstat, time): Don't declare.\n\n\t* compatMakefile (defines): Value is @DEFS@.\n\t(LOADLIBES): Value is @LIBS@.\n\t(extras): Value is @LIBOBJS@.\n\t(ARCHIVES, ARCHIVES_SRC, ALLOCASRC): Removed.\n\t* arscan.c, ar.c: Surround body with #ifndef NO_ARCHIVES.\n\n\t* misc.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl get*id.\n\n\t* make.h [GETCWD_MISSING]: Test instead of !USG && !POSIX et al.\n\t(getcwd): Just declare if present.  If not, declare as a macro\n\tusing getwd, and declare getwd.\n\t[PATH_MAX] (GET_PATH_MAX): #define to PATH_MAX.\n\t* main.c (main,\tlog_working_directory): Use getcwd instead of getwd.\n\n\t* main.c (main) [SETLINEBUF_MISSING]: Test this instead of USG.\n\n\t* make.h (SIGHANDLER, SIGNAL): Removed.\n\t(RETSIGTYPE): Define if not #define'd.\n\t* main.c (main): Use signal in place of SIGNAL.\n\n\t* main.c [SYS_SIGLIST_MISSING]: Test instead of USG.\n\n\t* job.c (search_path) [GETGROUPS_MISSING]: Test instead of USG.\n\t[HAVE_UNISTD_H]: Test instead of POSIX to not decl getgroups.\n\n\t* main.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl chdir.\n\t[! STDC_HEADERS]: Test instead of !POSIX to decl exit & atof.\n\n\t* job.c (child_handler), commands.c (fatal_error_signal): Return\n\tRETSIGTYPE instead of int.\n\t* main.c (main): Declare fatal_error_signal and child_handler here\n\tto return RETSIGTYPE; removed top-level decl of former.\n\n\t* commands.c (fatal_error_signal), job.c (unblock_sigs, start_job),\n\tmain.c [SIGSETMASK_MISSING]: Test this instead of USG.\n\nWed Jun 10 22:06:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c [HAVE_WAITPID]: Test this instead of USG.\n\t[! HAVE_UNISTD_H]: Test this instead of !POSIX to declare misc fns.\n\t(GID_T): Don't #define.\n\t(search_path): Use gid_t instead of GID_T.\n\t[GETDTABLESIZE_MISSING, SYS_SIGLIST_MISSING, DUP2_MISSING]: Test\n\tthese individually instead of USG for all.\n\t* make.h (ctime): Don't declare.  #include time.h instead.\n\t[HAVE_UNISTD_H]: #include <unistd.h> and #define POSIX #ifdef\n\t_POSIX_VERSION.\n\t* dir.c [__GNU_LIBRARY__] (D_NAMLEN): Define to use d_namlen member.\n\t* make.h [NEED_MEMORY_H]: Only include memory.h #ifdef this.\n\n\t* arscan.c: Removed #ifdef mess about string.h et al.\n\tJust #include make.h instead.\n\t* make.h (fstat, atol): Declare.\n\n\t* commands.c (fatal_error_signal): Don't use sigmask to check for\n\tpropagated signals; use ||s instead.\n\t(PROPAGATED_SIGNAL_MASK): Removed.\n\t(fatal_error_signal) [POSIX]: Use sigprocmask in place of sigsetmask.\n\n\t* variable.c (variable_buffer, variable_buffer_length,\n\tinitialize_variable_output, variable_output): Moved to expand.c;\n\tmade all static.\n\t(struct output_state, save_variable_output,\n\trestore_variable_output): Removed.\n\t* expand.c (initialize_variable_output): Put a NUL at the beginning\n\tof the new buffer after allocating it.\n\t(allocated_variable_expand_for_file): Don't use\n\t{save,restore}_variable_output.  Do it by hand instead, keeping\n\tstate on the stack instead of malloc'ing it.\n\t(allocated_variable_expand): Removed.\n\t* variable.h (allocated_variable_expand): Define here as macro.\n\t(variable_buffer_output, initialize_variable_output,\n\tsave_variable_output, restore_variable_output): Removed decls.\n\n\t* read.c (conditional_line): For an if cmd, if any elt of the\n\tconditionals stack is ignoring, just push a new level that ignores\n\tand return 1; don't evaluate the condition.\n\nThu Jun  4 21:01:20 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (main): Put #ifdef's around frobbing SIGSYS and SIGBUS.\n\n\t* job.c (getdtablesize): Don't declare or #define if already #define'd.\n\nWed Jun  3 23:42:36 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* file.c (snap_deps): If `.EXPORT_ALL_VARIABLES' is a target, set\n\texport_all_variables.\n\t* make.texinfo (Variables/Recursion): Document .EXPORT_ALL_VARIABLES.\n\nTue Jun  2 21:08:35 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.13.\n\n\t* commands.c (set_file_variables): Calculate length for ^D and ?D\n\tindividually, making sure to give them at least enough space for \"./\".\n\n\t* make.h [CRAY]: #define signal to bsdsignal.\n\n\t* default.c (default_variables) [CRAY]: Define PC, SEGLDR,\n\tCF77PPFLAGS, CF77PP, CFT, CF, and FC.\n\n\t* arscan.c (AR_HDR_SIZE): Define to sizeof (struct ar_hdr), if it\n\twasn't defined by <ar.h>.\n\nThu May 28 00:56:53 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.12.\n\nTue May 26 01:26:30 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* rule.c (new_pattern_rule): Initialize LASTRULE to nil, not\n\tpattern_rules.\n\nMon May 25 19:02:15 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (decode_switches): Initialize all the long_option elt members.\n\nThu May 21 16:34:24 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* make.texinfo (Text Functions): Correct filter-out description.\n\nTue May 19 20:50:01 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* compatMakefile (realclean): Don't remove backup files.\n\n\t* main.c (decode_switches): Allocate ARGC+1 elts in `other_args'.\n\nSun May 17 16:38:48 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.62.11.\n\nThu May 14 16:42:33 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* job.c (reap_children): Don't die if wait returns EINTR.\n\nWed May 13 18:28:25 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c (reap_children): Always run the next command for a\n\tsuccessful target.  If we are going to die, we don't want to leave\n\tthe target partially made.\n\nTue May 12 00:39:19 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): After loop, if we only\n\thave one word, check it for being a shell command.\n\n\t* main.c (decode_switches): Allocate ARGC slots in other_args to\n\tbegin with, so we never need to worry about growing it.\n\tIf we get a non-option arg and POSIXLY_CORRECT is in the\n\tenvironment, break out of the loop.  After the loop, add all remaining\n\targs to other_args list.\n\n\t* main.c (decode_switches): For positive_int and floating switches\n\twhen optarg is nil, use next arg if it looks right (start with a\n\tdigit, or maybe decimal point for floating).\n\n\t* variable.c (define_automatic_variables): Always set SHELL to\n\tdefault if it comes from the environment.  Set its export bit.\n\t* make.texinfo (Environment): Document change.\n\nMon May 11 00:32:46 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.62.10.\n\n\t* compatMakefile (tags, TAGS): Use vars for cmds.\n\t(ETAGS, CTAGS): Define.\n\n\t* main.c (decode_switches): If a switches elt has a nil long_name,\n\tmake the long option name elt be \"\".\n\tFixed loop to not ignore all the options.\n\n\t* make.texinfo (Option Summary): Added long options.\n\n\t* main.c (switches): Changed -m's description to \"-b\".\n\t(decode_switches): When printing the usage message, don't print\n\tswitches whose descriptions start with -.\n\tWhen constructing the list of names for switch -C, search the\n\tswitches vector for switches whose descriptions are \"-C\".\n\n\t* main.c (switches): Call -S --no-keep-going, not --dont-keep-going.\n\tCall -I --include-dir, not --include-path.\n\t(long_option_aliases): Added --new == -W, --assume-new == -W,\n\t--assume-old == -o, --max-load == -l, --dry-run == -n, --recon == -n,\n\t--makefile == -f.\n\n\t* main.c (switches): Removed bogus \"silent\" elt.\n\t(long_option_aliases): Define new var.\n\t(decode_switches): Add long_option_aliases onto the end of the long\n\toptions vector created for getopt_long.\n\tLook through long_option_aliases for extra names to list\n\tin usage message.\n\nSat May  9 00:21:05 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (log_working_directory): Fixed to properly not print the\n\tleaving message when we haven't printed the entering message.\n\nFri May  8 21:55:35 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* main.c (struct command_switch): Added elts `long_name',\n\t`description', and `argdesc'.\n\t(switches): Added initializers for new members.\n\t(decode_switches): Rewritten to use getopt_long.\n\t* compatMakefile (GETOPT, GETOPT_SRC): Define.\n\t(objs, srcs): Include them.\n\n\t* job.c (child_died): Renamed to dead_children; made static.\n\t(child_handler): Increment dead_children instead of setting child_died.\n\t(reap_children): Decrement dead_children instead of clearing\n\tchild_died.  The point of all this is to avoid printing \"waiting\n\tfor unfinished jobs\" when we don't actually need to block.\n\tThis happened when multiple SIGCHLDs before reap_children was called.\n\n\t* job.c (reap_children): If ERR is set, so we don't call start_job\n\ton the child being reaped, instead set its command_state to\n\tcs_finished.\n\t(reap_children, child_handler, new_job): I added several\n\tdebugging printf's while fixing this.  I left them in if (debug_flag)\n\tbecause they may be useful for debugging this stuff again.\n\nWed May  6 22:02:37 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): v_export is not 1.\n\nMon May  4 17:27:37 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.9.\n\n\t* variable.c (export_all_variables): New variable.\n\t(target_environment): Export variables whose `export' member is\n\tv_default if export_all_variables is set and their names are benign.\n\t* variable.h: Declare export_all_variables.\n\t* read.c (read_makefile): If export or unexport is given with no\n\targs, set or clear export_all_variables, respectively.\n\n\t* variable.c (target_environment): Exclude MAKELEVEL in the loop,\n\tso it isn't duplicated when we add it at the end.\n\nSun May  3 17:44:48 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.8.\n\n\t* variable.h (struct variable): Added new member `export'.\n\t* variable.c (define_variable_in_set): Initialize it to v_default.\n\t(target_environment): Don't check for .NOEXPORT.\n\tExport variables whose `export' member is v_default and that would\n\thave been exported under .NOEXPORT, and variables whose `export'\n\tmember is v_export.\n\t(try_variable_definition): Return the variable defined.\n\t* variable.h (try_variable_definition): Changed decl.\n\t* read.c (read_makefile): Recognize `export' and `unexport' directives.\n\nFri May  1 11:39:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* main.c (main) [POSIX]: Reversed args to sigaddset.\n\nThu Apr 30 17:33:32 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c [POSIX || !USG] (unblock_sigs): New fn.\n\t(start_job): Block signals before forking.\n\t(new_job): Unblock signals after putting the new child on the chain.\n\t* main.c (main) [POSIX]: Use sigset_t fatal_signal_set instead of\n\tint fatal_signal_mask.\n\n\t* load.c [sgi] (LDAV_CVT): Define.\n\nWed Apr 29 17:15:59 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.62.7.\n\n\t* load.c (load_average) [sgi]: Clear the high bit of the address\n\tfrom the symbol table before looking it up in kmem.\n\n\t* misc.c (fatal, makefile_fatal): Put *** in fatal error messages.\n\t(remake_file): No longer needed in message here.\n\n\t* main.c (die): Call reap_children with BLOCK==1.\n\nTue Apr 28 20:44:35 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* rule.c (freerule): Don't set LASTRULE->next if LASTRULE is nil.\n\nSun Apr 26 15:09:51 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* rule.c (count_implicit_rule_limits): Initialize LASTRULE to nil,\n\tnot to head of chain.  Extract next ptr before we might do\n\tfreerule, and use that for next iteration.\n\t(freerule): Still do next ptr frobbing if LASTRULE is nil.\n\nTue Apr 21 03:16:29 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* job.c (child_error): Removed extra %s from error msg format.\n\n\t* Version 3.62.6.\n\n\t* job.c (reap_children): Don't start later commands in a sequence\n\tif ERR is nonzero.\n\n\t* job.c (new_job): Always call reap_children with BLOCK==0 first thing.\n\n\t* job.c (reap_children): New function; work that used to be done in\n\tchild_handler.\n\t(child_died): New global var.\n\t(child_handler): Now just sets child_died.\n\t(wait_for_children): Removed.\n\t(unknown_children_possible, block_signals, unblock_signals,\n\tpush_signals_blocked_p, pop_signals_blocked_p): Removed.\n\t(child_execute_job): Removed call to unblock_signals.\n\t(new_job): Removed calls to push_signals_blocked_p and\n\tpop_signals_blocked_p.\n\t* job.h: Declare reap_children, not wait_for_children.\n\t* commands.c (fatal_error_signal), job.c (new_job),\n\tload.c [LDAV_BASED] (wait_to_start_job), main.c (die),\n\tremake.c (update_goal_chain), function.c (expand_function: `shell'):\n\tChanged wait_for_children calls to reap_children.\n\tSome needed to be loops to wait for all children to die.\n\t* commands.c (fatal_error_signal), main.c (main,\n\tlog_working_directory), function.c (expand_function): Removed calls\n\tto push_signals_blocked_p and pop_signals_blocked_p.\n\t* job.h: Removed decls.\n\n\t* job.h: Added copyright notice.\n\nWed Apr 15 02:02:40 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (child_error): No *** for ignored error.\n\nTue Apr 14 18:31:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* implicit.c (DEBUGP2): Use do ... while (0) instead of if ... else to\n\tavoid compiler warnings.\n\n\t* read.c (parse_file_seq): Don't remove ./ when it is followed by a\n\tblank.\n\nMon Apr 13 21:56:15 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h (DEBUGPR): Use do ... while (0) instead of if ... else to\n\tavoid compiler warnings.\n\n\t* remake.c (notice_finished_file): Run file_mtime on the also_make\n\tfiles, so vpath_search can happen.\n\n\t* GNUmakefile (tests): Use perl test suite from csa@sw.stratus.com.\n\t(alpha-files): Include test suite tar file.\n\nFri Apr  3 00:50:13 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* Version 3.62.5.\n\nWed Apr  1 05:31:18 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* remake.c (update_file, update_file_1): Do check_renamed on elts\n\tof dep chains when traversing them.  Something unrelated might have\n\trenamed one of the files the dep chain points to.\n\n\t* file.c (rename_file): If FILE has been renamed, follow its\n\t`renamed' ptr, so we get to the final real FILE.  Using the renamed\n\tones loses because they are not in the hash table, so the removal\n\tcode loops infinitely.\n\n\t* read.c (read_all_makefiles): Clobber null terminator into\n\tMAKEFILES expansion, so string passed to read_makefile is properly\n\tterminated.\n\nMon Mar 30 20:18:02 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* commands.c (set_file_variables): $* for archive member with\n\texplicit cmds is stem of member, not of whole `lib(member)'.\n\nThu Mar 26 15:24:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.62.4.\n\nTue Mar 24 05:20:51 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* rule.c (new_pattern_rule): Rules are identical only if all their\n\ttargets match (regardless of order).\n\nWed Mar 11 13:49:54 1992  Roland McGrath  (roland@geech.gnu.ai.mit.edu)\n\n\t* remake.c (remake_file): Changed error \"no way to make\" to \"no\n\trule to make\".  Fiat Hugh.\n\n\t* make.texinfo (Last Resort): Describe %:: rules and new .DEFAULT\n\tbehavior.\n\n\t* remake.c (update_file_1): Only use .DEFAULT cmds if FILE is not a\n\ttarget.\n\nTue Mar 10 18:13:13 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* remote-stub.c, remote-cstms.c (start_remote_job): Take new arg,\n\tenvironment to pass to child.\n\t* job.c (start_job): Pass it.\n\nMon Mar  9 19:00:11 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* file.c (enter_file): Also strip ./s here, to get command-line\n\ttarget names.\n\n\t* remote-cstms.c: Add comment telling people to leave me alone.\n\n\t* compatMakefile (manpage install): Remove target before copying.\n\nTue Mar  3 18:43:21 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.texinfo (Missing): Renamed to \"Incompatibilities and ...\".\n\tAdded paragraph describing $? incompatibility with Unix and POSIX.2.\n\nSun Mar  1 15:50:54 1992  Roland McGrath  (roland@nutrimat.gnu.ai.mit.edu)\n\n\t* function.c (expand_function: `shell'): Don't declare fork or pipe.\n\tUse vfork instead of fork.\n\nTue Feb 25 22:05:32 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* make.texinfo (Chained Rules): Clarify .PRECIOUS to save\n\tintermediate files.\n\n\t* load.c [sun] (LDAV_CVT): Define to divide by FSCALE.\n\nSun Feb 16 02:05:16 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* Version 3.62.3.\n\nSat Feb 15 17:12:20 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* compatMakefile (makeinfo): Use emacs batch-texinfo-format fn.\n\nFri Feb 14 00:11:55 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Correctly handle define & endef in ifdefs.\n\n\t* read.c (record_files): Pass arg for %s in error msg.\n\n\t* main.c (main) [__IBMR2, POSIX]: Use correct (a la USGr3) setvbuf\n\tcall.\n\nWed Feb 12 12:07:39 1992  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* make.texinfo (Libraries/Search): Say it does /usr/local/lib too.\n\nSun Feb  9 23:06:24 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* read.c (read_makefile): Check for extraneous `endef' when ignoring.\n\nThu Feb  6 16:15:48 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* Version 3.62.2.\n\nTue Feb  4 20:04:46 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Correctly ignore\n\twhitespace after backslash-NL.\n\nFri Jan 31 18:30:05 1992  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* compatMakefile: Ignore errors from chgrp and chmod when installing.\n\nWed Jan 29 18:13:30 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* main.c (main): When setting MAKELEVEL in the env to re-exec,\n\tallocate space so as not to clobber past the end of the old string.\n\n\t* make.h [HAVE_ALLOCA_H]: Include <alloca.h>\n\t* compatMakefile (defines): Document HAVE_ALLOCA_H.\n\nMon Jan 20 13:40:05 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* make.h [VFORK_MISSING]: Use fork instead.\n\t* compatMakefile (defines): Document same.\n\n\t* job.c (construct_command_argv_internal): Don't create an empty\n\targ if backslash-NL is at beginning of word.\n\nSun Jan 19 16:26:53 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* main.c [DGUX]: Call setvbuf as for USGr3.\n\n\t* job.c (construct_command_argv_internal): Notice correctly that\n\tbackslash-NL is the end of the arg (because it is replaced with a\n\tspace).\n\nThu Jan 16 18:42:38 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): If SHELL is nil, set it\n\tto default_shell before proceeding.\n\n\t* make.h [sgi]: No alloca.h, after all.\n\nWed Jan 15 12:30:04 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* read.c (multi_glob): Cons up the chain of the results of glob\n\tfrom back to front, so it comes out in forward order.\n\n\t* job.c (construct_command_argv_internal): Don't eat char following\n\tbackslash-NL.\n\nMon Jan 13 19:16:56 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* Version 3.62.1.\n\n\t* default.c (default_variables) [ultrix]: GET=get, like USG.\n\n\t* job.c (construct_command_argv_internal): Remove tabs following\n\tbackslash-NL combos in the input line, so they don't show up when\n\tthat line is printed.\n\n\t* read.c (read_makefile): Don't collapse_continuations the line on\n\tinput; do it on the copy we do remove_comments on.\n\tFor rule lines, collapse_continuations the line after chopping\n\t\";cmds\" off the end, so we don't eat conts in the cmds.\n\tGive error for \";cmds\" with no rule.\n\t* job.c (construct_command_argv_internal): Eat backslash-NL combos\n\twhen constructing the line to recurse on for slow, too.\n\nSat Jan 11 02:20:27 1992  Roland McGrath  (roland@albert.gnu.ai.mit.edu)\n\n\t* file.c (enter_file): Don't strip leading `./'s.\n\t* read.c (parse_file_seq): Take new arg STRIP; if nonzero, do it here.\n\t* default.c (set_default_suffixes), function.c (string_glob),\n\tread.c (read_makefile), rule.c (install_pattern_rule): Change callers.\n\n\t* default.c (default_variables) [_IBMR2]: FC=xlf\n\n\t* job.c (construct_command_argv_internal): Turn backslash-NL and\n\tfollowing whitespace into a single space, rather than just eating\n\tthe backslash.\n\n\t* make.texinfo (Copying): @include gpl.texinfo, rather than\n\tduplicating its contents.\n\nFri Nov  8 20:06:03 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Make sure not to bother\n\tprocessing an empty line.\n\n\t* Version 3.62.0.\n\n\t* job.c (construct_command_argv_internal): Always recurse for slow;\n\tsimple case didn't handle finding newlines.\n\nTue Nov  5 18:51:10 1991  Roland McGrath  (roland@wookumz.gnu.ai.mit.edu)\n\n\t* job.c (construct_command_argv_internal): Set RESTP properly when\n\tslow; don't \\ify past a newline.\n\nFri Nov  1 19:34:28 1991  Roland McGrath  (roland@churchy.gnu.ai.mit.edu)\n\n\t* make.h [sgi]: #include <alloca.h>.\n\n\f\n\nSee ChangeLog.1, available in the Git repository at:\n\n\thttps://git.savannah.gnu.org/cgit/make.git/tree/\n\nfor earlier changes.\n\n\nCopyright (C) 1991-2007 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "ChangeLog.3",
    "content": "2013-10-09  Paul Smith  <psmith@gnu.org>\n\n\tVersion 4.0 released.\n\n\t* configure.ac: Updated for the release.\n\t* NEWS: Updated for the release.\n\n\t* maintMakefile (tag-release): New target to add a Git tag.\n\t* read.c (eval): Typo fix.\n\t* ChangeLog.1: Typo fixes.\n\t* w32/subproc/sub_proc.c (process_cleanup): Typo fix.\n\n2013-10-07  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/compat/posixfcn.c (tmpfile): Move declaration of h before\n\tthe first executable statement.  Reported by Gisle Vanem\n\t<gvanem@yahoo.no>.\n\n2013-10-05  Paul Smith  <psmith@gnu.org>\n\n\t* makeint.h (MAP_USERFUNC): A new map type for function names.\n\t* main.c (initialize_stopchar_map): Set up the function name map.\n\n\t* gnumake.h (gmk_func_ptr): Define a type for function pointers.\n\t(gmk_add_function): Convert the last argument to FLAGS.\n\t(GMK_FUNC_*): Define flags for the function.  Change the default\n\tbehavior to \"expand\" since that's the most common one.\n\n\t* function.c (function_table_entry): Use new function pointer type.\n\t(lookup_function): Accept any valid function name character based\n\ton the MAP_USERFUNC values.\n\t(define_new_function): Use the new calling signature.  Verify that\n\tregistered functions have valid names.\n\n\t* guile.c (guile_gmake_setup): Use new calling signatures.\n\t* loadapi.c (gmk_add_function): Ditto.\n\t* variable.h (define_new_function): Ditto.\n\n\t* doc/make.texi (Loaded Object API): Make the registered function\n\tAPI documentation more clear.\n\n2013-10-03  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (abspath): Reset root_len to one for Cygwin only when\n\tHAVE_DOS_PATHS is defined.  Suggested by Christopher Faylor.\n\n2013-10-02  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/compat/posixfcn.c (tmpfile): New function, a replacement for\n\tthe Windows libc version.\n\n\tFix $abspath on Cygwin when HAVE_DOS_PATHS is in effect.\n\t* function.c (IS_ABSOLUTE) [__CYGWIN__]: Special definition for\n\tCygwin.\n\t(abspath) [__CYGWIN__]: Reset root_len to 1 if the absolute file\n\tname has the Posix /foo/bar form.\n\t[HAVE_DOS_PATHS]: Use root_len instead of hard-coded 2.\n\n2013-10-01  Paul Smith  <psmith@gnu.org>\n\n\t* configure.ac: Update version to 3.99.93.\n\t* NEWS: Ditto.\n\n2013-09-30  Paul Smith  <psmith@gnu.org>\n\n\t* guile.c: Portability fixes for Guile 1.8.\n\n2013-09-29  Paul Smith  <psmith@gnu.org>\n\n\t* output.c (output_dump): Always write Enter/Leave messages to stdio.\n\t(log_working_directory): This now always writes to stdio, so we\n\tdon't need the struct output parameter anymore.\n\t(output_start): Show the working directory when output_sync is not\n\tset or is recursive.\n\t* main.c (main): Ensure the special \"already shown Enter message\"\n\ttoken is removed from MAKE_RESTARTS before the user can see it.\n\t* function.c (func_shell_base): If the output_context stderr\n\texists but is invalid, write to the real stderr.\n\tFixes suggested by Frank Heckenbach <f.heckenbach@fh-soft.de>.\n\n\t* output.c: Guard unistd.h inclusion, add io.h.\n\t* gnumake.h: Move GMK_EXPORT before the declarations.\n\t* make_msvc_net2003.vcproj: Add missing files.\n\tChanges for MSVC suggested by Gerte Hoogewerf <g.hoogewerf@gmail.com>\n\n\t* function.c (func_shell_base) [EMX]: Fix EMX support for output-sync.\n\t* job.c (child_execute_job) [EMX]: Ditto.\n\t* job.h (child_execute_job) [EMX]: Ditto.\n\t* w32/compat/posixfcn.c: Invert the test for NO_OUTPUT_SYNC.\n\n\t* guile.c (GSUBR_TYPE): Pre-2.0 Guile doesn't provide a typedef\n\tfor gsubr pointers.  Create one.\n\t(guile_define_module): Use it.\n\t(internal_guile_eval): Force UTF-8 encoding for Guile strings.\n\n\t* main.c (main): Clear GNUMAKEFLAGS after parsing, to avoid\n\tproliferation of options.\n\t* NEWS: Document it.\n\t* doc/make.texi (Options/Recursion): Ditto.\n\n2013-09-23  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/compat/posixfcn.c: Fix the forgotten OUTPUT_SYNC conditional.\n\n\t* job.h: Ditto, but in a comment.\n\n2013-09-22  Paul Smith  <psmith@gnu.org>\n\n\t* configure.ac: Update version to 3.99.92.\n\t* NEWS: Ditto.\n\n\t* implicit.c (pattern_search): After second expansion be sure to\n\thandle order-only markers inside the expansion properly.\n\tFixes Savannah bug #31155.\n\n\t* guile.c (guile_define_module): Technically a void* cannot\n\tcontain a pointer-to-function and some compilers warn about this.\n\tCast the function pointers.\n\t* load.c (load_object): Ditto.\n\n\t* read.c (eval): If load_file() returns -1, don't add this to the\n\t\"to be rebuilt\" list.\n\t* doc/make.texi (load Directive): Document it.\n\n\t* guile.c (guile_gmake_setup): Don't initialize Guile so early.\n\t(func_guile): Lazily initialize Guile the first time the $(guile ..)\n\tfunction is invoked.  Guile can steal file descriptors which\n\tconfuses our jobserver FD checking, so we don't want to initialize\n\tit before we have to.\n\n\tVMS port updates by Hartmut Becker <becker.ismaning@freenet.de>\n\n\t* makefile.com: Add output to the filelist.\n\t* output.c (va_copy): Add an implementation of this macro for VMS.\n\t* commands.c: Ensure filedef.h is #included before dep.h.\n\t* dir.c: Ditto.\n\t* file.c: Ditto.\n\t* guile.c: Ditto.\n\t* main.c: Ditto.\n\t* misc.c: Ditto.\n\t* read.c: Ditto.\n\t* rule.c: Ditto.\n\t* variable.c: Ditto.\n\t* readme.vms: Renamed to README.VMS and updates for this release.\n\t* Makefile.am: Ditto.\n\t* NEWS: Ditto.\n\t* README.template: Ditto.\n\t* Makefile.DOS.template: Ditto.\n\n2013-09-21  Paul Smith  <psmith@gnu.org>\n\n\t* maintMakefile (check-alt-config): Create a target to test\n\talternative configurations.  Each one will build make with a\n\tdifferent configuration then run the test suite.\n\n\tInvert the output-sync #define to NO_OUTPUT_SYNC\n\n\t* configure.ac: Don't set OUTPUT_SYNC.\n\t* makeint.h: Ditto.\n\t* main.c: Use NO_OUTPUT_SYNC instead of OUTPUT_SYNC.\n\t* output.c: Ditto.\n\t* output.h: Ditto.\n\t* job.h: Ditto.\n\t* job.c: Ditto.\n\t* config.ami.template: Set NO_OUTPUT_SYNC.\n\t* config.h-vms.template: Ditto.\n\t* config.h.W32.template: Ditto.\n\t* configh.dos.template: Ditto.\n\n\tOutput generated while reading makefiles should be synced.\n\n\t* main.c (make_sync): Define a context for syncing while reading\n\tmakefiles and other top-level operations.\n\t(main): If we request syncing, enable it while we are parsing\n\toptions, reading makefiles, etc. to capture that output.  Just\n\tbefore we start to run rules, dump the output if any.\n\t(die): Dump any output we've been syncing before we die\n\t* output.h (OUTPUT_SET): Disable output_context if not syncout.\n\n\tStderr generated from shell functions in recipes should be synced.\n\n\t* job.h (FD_STDIN, FD_STDOUT, FD_STDERR): Create new macros to\n\tavoid magic numbers.\n\t(child_execute_job): Take a FD for stderr.\n\t* job.c (child_execute_job): Handle STDERR FD's in addition to\n\tstdin and stdout.\n\t(start_job_command): Call child_execute_job() with the new STDERR\n\tparameter.  Instead of performing the dup() here, send it to\n\tchild_execute_job() where it's already being done.\n\t* function.c (func_shell_base): Pass the OUTPUT_CONTEXT stderr to\n\tchild_execute_job() if it's set, otherwise FD_STDERR.\n\t* main.c (main): Pass FD_STDERR to child_execute_job().\n\n2013-09-19  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Set MAKE_RESTARTS to negative before re-exec if\n\twe've already generated an \"Entering\" message.  If we are started\n\tand notice that MAKE_RESTARTS is negative, assume we already wrote\n\t\"Entering\" and don't write it again.\n\n2013-09-18  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Set starting_directory before we write any\n\terrors.  Fixes Savannah bug #40043.\n\n2013-09-16  Eli Zaretskii  <eliz@gnu.org>\n\n\t* output.c [WINDOWS32]: Include windows.h and sub_proc.h, to avoid\n\tcompiler warnings for CLOSE_ON_EXEC.\n\n2013-09-16  Paul Smith  <psmith@gnu.org>\n\n\t* configure.ac: Update version to 3.99.91.\n\t* NEWS: Ditto.\n\n2013-09-15  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Error Messages): Add a bit more info to the\n\tsection on static pattern errors, since they're common.\n\tFixes Savannah bug #31326.\n\n\t* read.c (eval_makefile): If the file open fails with an\n\tunrecoverable error, stop now rather than trying to make it.\n\tFixes Savannah bug #27374.\n\n\t* main.c (main): Perform the validation of the jobserver FDs\n\tearly, before we read makefiles, to ensure that something hasn't\n\topened and used those FDs for some other reason.\n\tFixes Savannah bug #39934.\n\n\t* main.c (main): Don't set MAKEFLAGS in the environment when we\n\trestart.  We have the original command line flags so keep the\n\toriginal MAKEFLAGS settings as well.\n\tFixes Savannah bug #39203.\n\n2013-09-14  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (decode_debug_flags): Add support for the \"n\" flag to\n\tdisable all debugging.\n\t* make.1: Document the \"n\" (none) flag.\n\t* doc/make.texi (Options Summary): Ditto.\n\t* NEWS: Ditto.\n\tFixes Savannah bug #35248.\n\n\t* misc.c (close_stdout): Move to output.c.\n\t* main.c (main): Move atexit call to output_init().\n\t* makeint.h: Remove close_stdout() declaration.\n\t* output.c (output_init): Add close_stdout at exit only if it's\topen.\n\tFixes Savannah bug #33134.  Suggested by David Boyce <dsb@boyski.com>.\n\n2013-09-14  Paul Smith  <psmith@gnu.org>\n\n\t* misc.c (set_append_mode, open_tmpfd, open_tmpfile): Move to output.c.\n\t* misc.h: Ditto.\n\t* output.h: Ditto.\n\t* main.c (main): Move stdio init into output.c:output_init().\n\tChange open_tmpfile() to output_tmpfile().\n\t* output.c: Rename open_*() to output_*().  set_append_mode() and\n\topen_tmpfd() are static.\n\t(_outputs, log_working_directory): Accept a struct output and\n\tprint to that rather than the global context.\n\t(output_dump): In recurse mode print enter/leave once for the\n\twhole makefile.\n\t(output_init): Initialize this processes stdio as well as child's.\n\n\t* vmsjobs.c: Reformat to be closer to convention.\n\n2013-09-12  Paul Smith  <psmith@gnu.org>\n\n\tRework output to handle synchronization and directory logging more\n\treliably.\n\n\t* output.c: New file.  Implement lazy synchronization and\n\tdirectory logging so that we manage them \"just in time\", and the\n\tdestination of the output is set via a global state variable.\n\t* output.h: New file.\n\t* function.c (func_shell_base): Ensure the output is set up before\n\trunning a shell command, in case it writes to stderr.\n\t(func_error): Use outputs() to generate output.\n\t* job.h (struct child): Add struct output to track the child's output.\n\t* job.c: Use struct output in the child structure to track output.\n\t(child_out, sync_init, assign_child_tempfiles, pump_from_tmp)\n\t(acquire_semaphore, release_semaphore, sync_output): Move most of\n\tthe output_sync handling to output.c.\n\t(child_error): Set output, then use simple message() and error()\n\tnot _s versions.\n\t* main.c (log_working_directory): Moved to output.c\n\t(trace_option, decode_trace_flags) Remove.  Remove support for\n\tdifferent trace modes; we don't use it anymore.\n\t(die) Invoke output_close() before we exit.\n\t* misc.c (message_s, error_s): Removed; no longer needed.\n\t(message, error, fatal, perror_with_name, pfatal_with_name): Moved\n\tto output.c.\n\t* makeint.h: Remove message_s(), error_s(), and\n\tlog_working_directory().  Remove the TRACE_* macros.\n\t* doc/make.texi: Enhance documentation for output sync, and remove\n\tMODE assignment for --trace.\n\t* make.1: Remove MODE assignment for --trace.\n\t* Makefile.am: Add new files.\n\t* NMakefile.template: Ditto.\n\t* SMakefile.template: Ditto.\n\t* build_w32.bat: Ditto.\n\t* dosbuild.bat: Ditto.\n\t* make.lnk: Ditto.\n\t* make_nsvc_net2003.vcproj: Ditto.\n\t* makefile.vms: Ditto.\n\t* po/POTFILES.in: Ditto.\n\n2013-08-22  Petr Machata  <pmachata@redhat.com>\n\n\t* function.c (func_shell_base): Get rid of any avoidable limit on\n\tstack size for processes spawned via $(shell).\n\n2013-07-22  Paul Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Use PARSE_SIMPLE_SEQ() even for\n\tnon-second expansion prerequisites, to handle globbing in patterns.\n\tFixes Savannah bug #39310.\n\n\t* dep.h (PARSE_SIMPLE_SEQ): Macro for simple file sequence parsing.\n\t* default.c (set_default_suffixes): Use it.\n\t* file.c (split_prereqs): Ditto.\n\t* main.c (main): Ditto.\n\t* read.c (eval): Ditto.\n\t* rule.c (install_pattern_rule): Ditto.\n\t* file.c (split_prereqs): Use PARSEFS_NONE instead of 0.\n\n2013-07-21  Paul Smith  <psmith@gnu.org>\n\n\tCleanups detected by cppcheck.  Fixes Savannah bug #39158.\n\t* arscan.c (ar_scan): Reduce the scope of local variables.\n\t* dir.c (vms_hash): Ditto.\n\t(find_directory): Ditto.\n\t(file_impossible_p): Ditto.\n\t* expand.c (variable_expand_string): Ditto.\n\t* function.c (func_sort): Ditto.\n\t(func_and): Ditto.\n\t* job.c (reap_children): Ditto.\n\t(exec_command): Ditto.\n\t* main.c (main): Ditto.\n\t* misc.c (collapse_continuations): Ditto.\n\t* read.c (eval): Ditto.\n\t(parse_file_seq): Ditto.\n\t* vpath.c (gpath_search): Ditto.\n\t(selective_vpath_search): Ditto.\n\t* job.c (is_bourne_compatible_shell): Simplify for non-Windows systems.\n\t* remake.c (f_mtime): Remove duplicate test.\n\t* signame.c (strsignal): Fix bogus conditional.\n\n\t* job.c (assign_child_tempfiles): Assign OUTFD to -1 for safety.\n\t(start_job_command): Don't test output_sync and sync_cmd: redundant.\n\tChanges suggested by Frank Heckenbach <f.heckenbach@fh-soft.de>.\n\n2013-07-14  Paul Smith  <psmith@gnu.org>\n\n\t* filedef.h (update_status): Convert UPDATE_STATUS from a char to\n\tan enumeration.  Some systems declare \"char\" to be \"unsigned\"\n\twhich broke the code (which expected to be able to use -1 as a\n\tflag).  Using magic values was unpleasant, so rather than just\n\tforce \"signed char\" I reworked it to use an enum.\n\n\t* dep.h (update_goal_chain): Return an update_status value not int.\n\t* remake.c (touch_file): Ditto.\n\t(update_goal_chain): Track the update_status enum.\n\n\t* file.c (enter_file): Use new enumeration values with update_status.\n\t(remove_intermediates): Ditto.\n\t(print_file): Ditto.\n\t* commands.c (execute_file_commands): Ditto.\n\t* job.c (reap_children): Ditto.\n\t(start_job_command): Ditto.\n\t(start_waiting_job): Ditto.\n\t* main.c (main): Ditto.\n\t* remake.c (update_file): Ditto.\n\t(complain): Ditto.\n\t(update_file_1): Ditto.\n\t(notice_finished_file): Ditto.\n\t(remake_file): Ditto.\n\t* vmsjobs.c (vmsHandleChildTerm): Ditto.\n\n2013-07-09  Paul Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Keep a local copy of the number of\n\tdeps in deplist: the global max might change due to recursion.\n\tFixes a bug reported by Martin d'Anjou <martin.danjou14@gmail.com>.\n\n2013-06-28  Paul Smith  <psmith@gnu.org>\n\n\t* misc.c (set_append_mode): Set the O_APPEND flag on a file descriptor.\n\t(open_tmpfd): Set append mode on the temporary file descriptor.\n\t* main.c (main): Set append mode on stdout and stderr.\n\t* makeint.h (set_append_mode): Declare it.\n\n2013-06-22  Eli Zaretskii  <eliz@gnu.org>\n\n\t* build_w32.bat (LinkGCC): Prevent a comment from being displayed\n\tat build time.\n\n\t* job.c (construct_command_argv_internal) [WINDOWS32]: Use\n\tcase-insensitive comparison with internal commands of non-Unix\n\tshells.\n\n\t* main.c (find_and_set_default_shell): Don't use file_exists_p or\n\tdir_file_exists_p, as those call readdir, which can fail if PATH\n\tincludes directories with non-ASCII characters, and that would\n\tcause Make to fail at startup with confusing diagnostics.  See\n\thttps://sourceforge.net/mailarchive/message.php?msg_id=30846737\n\tfor the details.\n\n2013-06-22  Paul Smith  <psmith@gnu.org>\n\n\tImprove performance by using a character map to determine where we\n\twant to stop searching strings, rather than discrete comparisons.\n\n\t* read.c (find_char_unquote): Pass a stop map instead of various\n\tflags and use that to check when to stop parsing the string.\n\t(eval): Use the new find_char_unquote() calling signature.\n\t(remove_comments): Ditto.\n\t(unescape_char): Ditto.\n\t(find_percent_cached): Ditto.\n\t(parse_file_seq): Use a stop-map flag.\n\t* main.c (stopchar_map): Character map definition.\n\t(initialize_stopchar_map): Initialize the map definition.\n\t(main): Invoke the map initialization function.\n\t* misc.c (end_of_token_w32): Remove unused function.\n\t* dir.c (dosify): Use STOP_SET to check for stop chars.\n\t* main.c (main): Ditto.\n\t* misc.c (end_of_token): Ditto.\n\t* function.c (subst_expand): Ditto.\n\t(func_notdir_suffix): Ditto.\n\t(func_basename_dir): Ditto.\n\t(abspath): Ditto.\n\t* job.c (is_bourne_compatible_shell): Ditto.\n\t* variable.c (parse_variable_definition): Ditto.\n\t* read.c (eval): Ditto.\n\t(conditional_line): Ditto.\n\t(find_percent_cached): Ditto.\n\t* dep.h (PARSE_FILE_SEQ): Update function declaration.\n\t* default.c (set_default_suffixes): Update PARSE_FILE_SEQ() call.\n\t* file.c (split_prereqs): Ditto.\n\t* function.c (string_glob): Ditto.\n\t* implicit.c (pattern_search): Ditto.\n\t* rule.c (install_pattern_rule): Ditto.\n\t* main.c (main): Ditto.\n\n2013-06-21  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (verify_flag): Global variable to determine whether to\n\tverify the database or not.\n\t(decode_debug_flags): If debug mode, enable verify_flag.\n\t(main): If MAKE_MAINTAINER_MODE, enable verify_flag, otherwise not.\n\t(die): Only verify the database if verify_flag is set.\n\t* file.c (enter_file): Don't check caching unless verify_flag.\n\t* makeint.h: Export verify_flag.\n\n2013-05-27  Paul Smith  <psmith@gnu.org>\n\n\t* variable.c (define_automatic_variables): Create a new variable\n\tMAKE_HOST.\n\n2013-05-27  Hartmut Becker  <becker.ismaning@freenet.de>\n\n\t* function.c (func_shell_base) [VMS]: Support VMS.\n\t* makefile.com [VMS]: Ditto.\n\t* makefile.vms [VMS]: Ditto.\n\t* makeint.h [VMS]: Ditto.\n\t* vmsjobs.c [VMS]: Ditto.\n\t* job.h: Define RECORD_SYNC_MUTEX() when OUTPUT_SYNC is not set.\n\t* load.c (unload_file): Fix signature if MAKE_LOAD is not set.\n\n2013-05-26  Paul Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): Ensure that archive file names are in the\n\tstring cache.  Fixes Savannah bug #38442.\n\n\t* read.c (readline): To be safe, move the entire buffer if we\n\tdetect a CR.  Fixes Savannah bug #38945.\n\n\t* job.c (new_job): Compare OUT to the beginning of the OUT\n\tvar/function, not IN.  Fixes Savannah bug #39035.\n\n2013-05-22  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (switches[]): Order switches so simple flags all come first.\n\t(define_makeflags): Rework to make option passing more\n\treliable and the code less tricksy.  Ensure simple flags are kept\n\tin the initial batch of flags.  Do not allow any flags with\n\toptions in that batch.  If there are only non-simple flags MAKEFLAGS\n\tbegins with ' '.\n\t(print_data_base): Print the version.  Fixes part of Savannah #35336.\n\n\t* read.c (eval_buffer): Initialize lineno.\n\n2013-05-18  Alexey Pavlov  <alexpux@gmail.com>  (tiny change)\n\n\t* w32/Makefile.am (libw32_a_SOURCES): Add compat/posixfcn.c.\n\n\t* configure.ac (OUTPUT_SYNC): Define for mingw32 target.\n\n\t* job.c (construct_command_argv_internal) <sh_cmds_dos>\n\t[WINDOWS32]: Add \"move\".  Fixes Savannah bug #30714.\n\n\t* guile.c: Move inclusion of makeint.h before gnumake.h.  This\n\torder must be observed when building Make, because gnumake.h must\n\tbe included with GMK_BUILDING_MAKE defined, which makeint.h\n\talready does.  Otherwise, the linker will look for, and fail to\n\tfind, gmk_* functions in some external dynamic library.\n\n2013-05-17  Benno Schulenberg  <bensberg@justemail.net>\n\n\t* main.c (decode_output_sync_flags): Fix output message.\n\t* read.c (EXTRANEOUS): Ditto.\n\t(record_files): Ditto.\n\t* remake.c (update_file_1): Ditto.\n\n2013-05-17  Eli Zaretskii  <eliz@gnu.org>\n\n\t* main.c (prepare_mutex_handle_string): Define conditioned on\n\tOUTPUT_SYNC.\n\n\t* build_w32.bat: Copy config.h.W32 to config.h regardless of\n\twhether or not we are building from SCM.\n\n2013-05-17  Paul Smith  <psmith@gnu.org>\n\n\t* configure.ac: Update version to 3.99.90.\n\t* NEWS: Ditto.\n\n\t* Source (*.[ch]): Remove TABs, use GNU coding styles.\n\n\t* ALL: Update copyright.\n\n\t* hash.c (CALLOC): Use xcalloc() to handle out of memory errors.\n\n\t* makeint.h: Prototype new unload_file() function.\n\t* load.c (unload_file): Create a function to unload a file.\n\t(struct load_list): Type to remember loaded objects.\n\t(loaded_syms): Global variable of remembered loaded objects so we\n\tcan unload them later.  We don't have to remove from the list\n\tbecause the only time we unload is if we're about to re-exec.\n\t(load_object): Remove unneeded extra DLP argument.\n\t(load_file): Remove unneeded extra DLP argument.\n\t* filedef.h (struct file): Remove the DLP pointer and add the\n\tLOADED bit flag.  Saves 32/64 bytes per file, as this pointer is\n\talmost never needed.\n\t* read.c (eval): Set the new LOADED bit flag on the file.\n\t* file.c (rehash_file): Merge the loaded bitfield.\n\t* commands.c (execute_file_commands): Call unload_file() instead\n\tof dlclose() directly.\n\n2013-05-14  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Loaded Object API): Document the requirement for\n\tthe plugin_is_GPL_compatible symbol.\n\t* load.c (load_object): Check for plugin_is_GPL_compatible symbol.\n\n2013-05-13  Paul Smith  <psmith@gnu.org>\n\n\t* filedef.h (struct file): Add a builtin flag.\n\t* file.c (enter_file): Unset the builtin flag.\n\t(rehash_file): Ditto.\n\t(print_file): Don't print builtin files if we've omitted them.\n\t* default.c (undefine_default_variables): New function: go through\n\tthe default variables and undefine them.\n\t(set_default_suffixes): Mark these suffix rules as builtin.\n\t* makeint.h: Prototype.\n\t* main.c (main): Handle addition of -r and -R to MAKEFLAGS in the\n\tmakefile.  Fixes Savannah bug #20501.\n\n\t* main.c (define_makeflags): Assign o_env_override level to\n\tMAKEFLAGS to ensure it's set even in the presence of -e.\n\tFixes Savannah bug #2216.\n\n\t* makeint.h (TRACE_NONE, TRACE_RULE, TRACE_DIRECTORY): Define\n\tconstants for the trace mode.\n\t* main.c: Add new --trace mode parsing.\n\t(decode_trace_flags): New function.\n\t(decode_switches): Call it.\n\t(define_makeflags): Fix a bug with long-name options.\n\t* misc.c (fatal): Remove special output-sync handling.\n\t* make.1: Document new --trace mode flags.\n\t* doc/make.texi (Options Summary): Ditto.\n\n2013-05-11  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (child_out): Output the newline following the message\n\tbefore fllush-ing the stream.  Avoids displaying the following\n\tfailure message, which goes to stderr, on the same line.\n\n2013-05-06  Eli Zaretskii  <eliz@gnu.org>\n\n\t* gnumake.h (GMK_EXPORT) [_WIN32]: Move the dllexport declaration\n\there from makeint.h.\n\n\t* makeint.h (GMK_BUILDING_MAKE) [WINDOWS32]: Define before\n\tincluding gnumake.h.\n\n\t* doc/make.texi (Loaded Object Example): Add a note about building\n\tshared objects on MS-Windows.\n\n2013-05-05  Paul Smith  <psmith@gnu.org>\n\n\t* makeint.h (OUTPUT_SYNC_LINE, OUTPUT_SYNC_RECURSE): Rename\n\toutput-sync options \"job\" to \"line\" and \"make\" to \"recurse\".\n\t* main.c (decode_output_sync_flags): Ditto.\n\t* job.c (reap_children): Ditto.\n\t(start_job_command): Ditto.\n\t* make.1: Ditto.\n\t* doc/make.texi (Parallel Output): Ditto.\n\n\t* job.c (child_out): Write newlines explicitly, and don't do\n\tanything if the message is empty.\n\t(sync_output): Put working dir messages around stdout AND stderr.\n\t(start_job_command): Move the tmp file assignment earlier.  After\n\twe do it, write the command line to the temp file to get the order\n\tcorrect.\n\n\t* misc.c (message): Remove special handling for output_sync.\n\t(error): Ditto.\n\n2013-05-04  Paul Smith  <psmith@gnu.org>\n\n\t* loadapi.c (gmk_alloc): New function.\n\t* gnumake.h: Add gmk_alloc().  Clean GMK_EXPORT a bit to avoid MAIN.\n\t* makeint.h (GMK_EXPORT): New handling, vs. MAIN.\n\t* doc/make.texi (Loaded Object API): Add information on the memory\n\thandling functions.\n\t(Loaded Object Example): Create an example.\n\n\t* job.c (pump_from_tmp): (Rename) Write to stdout/stderr using\n\tFILE* rather than fd.  It's not a good idea to mix and match.\n\n2013-05-04  Eli Zaretskii  <eliz@gnu.org>\n\n\t* makeint.h (ftruncate) [_MSC_VER]: Redirect to _chsize.\n\t(_S_ISDIR): If not defined (MinGW64), define to S_ISDIR.\n\n2013-05-04  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (child_out): Handle EINTR and incomplete write scenarios.\n\t(sync_init): New function: separate the initialization code.\n\t(assign_child_tempfiles): Remove truncation from this function,\n\t(sync_output): and add it here after output is generated.\n\t(reap_children): Always call sync_output() in case output_sync was\n\treset after the child started, due to error.\n\t(start_job_command): Create new sync_cmd variable.  Use new method\n\tfor initializing the handle.\n\tIf we're not syncing the output be sure any output we've saved is\n\tdumped immediately before starting the child.\n\n2013-05-04  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (start_job_command): Make the condition for creating a\n\ttemporary output file be identical to the Posix code branch.\n\tSuggested by Frank Heckenbach <f.heckenbach@fh-soft.de>.\n\n2013-05-03  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/sub_proc.c: Include makeint.h.  Remove a private\n\tincompatible prototype of xmalloc.\n\t(batch_file_with_spaces): New function, detects Windows batch\n\tfiles whose names include whitespace characters.\n\t(process_begin): If exec_name is a batch file with whitespace\n\tcharacters in its name, pass NULL as the first argument to\n\tCreateProcess.  This avoids weird failures due to buggy quoting by\n\tCreateProcess.  For the details, see the discussion starting at\n\thttps://lists.gnu.org/archive/html/make-w32/2013-04/msg00008.html.\n\n\t* load.c (load_object, load_file): Accept an additional argument\n\tDLP and return in it a pointer that can be used to unload the\n\tdynamic object.\n\n\t* read.c (eval): Call load_file with an additional argument, and\n\trecord the pointer returned there in the 'struct file' object of\n\tdynamic objects in that object's 'struct file'.\n\n\t* commands.c (execute_file_commands): Unload dynamic objects\n\tbefore remaking them, to avoid failure to remake if the OS doesn't\n\tallow overwriting objects that are in use.\n\n\t* filedef.h (struct file): New member dlopen_ptr.\n\n\t* gnumake.h (GMK_EXPORT): Define to dllexport/dllimport\n\tdecorations for Windows and to nothing on other platforms.\n\t(gmk_eval, gmk_expand, gmk_add_function): Add GMK_EXPORT qualifier\n\tto prototypes.\n\n\t* makeint.h (MAIN): Define before including gnumake.h, to give\n\tcorrect dllexport decorations to exported functions.\n\t(load_file): Adjust prototype.\n\n\t* loadapi.c: Don't include gnumake.h, since makeint.h already\n\tincludes it, and takes care of defining MAIN before doing so.\n\n\t* build_w32.bat (LinkGCC): Produce an import library for functions\n\texported by Make for loadable dynamic objects.\n\n\t* w32/compat/posixfcn.c (dlclose): New function.\n\n\t* w32/include/dlfcn.h (dlclose): Add prototype.\n\n2013-05-01  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (start_job_command) [WINDOWS32]: Make the same fix for\n\tMS-Windows as the previous commit did for Posix platforms.\n\t(construct_command_argv_internal): Don't treat a backslash as an\n\tescape character before whitespace, if the shell is not a Posix\n\tshell.   For the description of the problem, see\n\thttps://lists.gnu.org/archive/html/make-w32/2013-04/msg00014.html.\n\n2013-05-01  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): Don't redirect output for recursive\n\tmake jobs, unless we're in makefile synchronization mode.\n\n2013-04-30  Stefano Lattarini <stefano.lattarini@gmail.com>  (tiny change)\n\n\tbuild: enable the 'silent-rules' automake options\n\n\t* configure.ac (AM_INIT_AUTOMAKE): Here.  The future major Automake\n\tversion 2.0 (ETA about one, one and half year from now) will enable\n\tit by default, so better prepare ourselves.\n\n2013-04-30  Stefano Lattarini <stefano.lattarini@gmail.com>  (tiny change)\n\n\tbuild: require Autoconf >= 2.62 and Automake >= 1.11.1\n\n\tOlder versions of those tools should be considered fully obsolete.\n\tAlso, GNU make already requires Gettext >= 0.18.1, which has been\n\treleased six months after Automake 1.11.1 and two years after\n\tAutoconf 2.62; so the new requirement shouldn't be problematic\n\tfor people already bootstrapping GNU make from the Git repository.\n\n\t* configure.ac (AC_PREREQ): Require Autoconf 2.62 or later.\n\t(AM_INIT_AUTOMAKE): Require Automake 1.11.1 or later (1.11 had\n\tsome serious bugs, and should not be used).\n\n2013-04-30  Stefano Lattarini <stefano.lattarini@gmail.com>  (tiny change)\n\n\tbuild: get rid of 'HAVE_ANSI_COMPILER' C preprocessor conditional\n\n\tGNU make already assume C89 or later throughout the codebase, and\n\tthat preprocessor conditional was no longer used anyway.\n\n\t* configure.ac: Remove AC_DEFINE of HAVE_ANSI_COMPILER.\n\t* config.ami.template: Remove #define of HAVE_ANSI_COMPILER.\n\t* config.h-vms.template: Likewise.\n\t* config.h.W32.template: Likewise.\n\t* configh.dos.template: Likewise.\n\n2013-04-30  Stefano Lattarini <stefano.lattarini@gmail.com>  (tiny change)\n\n\tcosmetics: fix few innocuous typos\n\n\tMost of these were found using Lucas De Marchi's 'codespell' tool.\n\n\t* ChangeLog: Fix minor typos.\n\t* ChangeLog.2: Likewise.\n\t* README.Amiga: Likewise.\n\t* TODO.private: Likewise.\n\t* function.c: Likewise.\n\t* glob/glob.h: Likewise.\n\t* job.c: Likewise.\n\t* main.c: Likewise.\n\t* readme.vms: Likewise.\n\t* remake.c: Likewise.\n\t* tests/ChangeLog: Likewise.\n\t* tests/NEWS: Likewise.\n\t* tests/README: Likewise.\n\t* tests/scripts/variables/private: Likewise.\n\t* vmsdir.h: Likewise.\n\t* signame.c: Likewise.  While at it, improve line wrapping in the\n\ttouched comment.\n\n2013-04-29  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/include/dlfcn.h: New file.\n\n\t* w32/compat/posixfcn.c: Include dlfcn.h.\n\t(dlopen, dlerror, dlsym) [MAKE_LOAD]: New functions, in support of\n\tdynamic loading.\n\n\t* config.h.W32.template (MAKE_LOAD): Define.\n\n\t* load.c (load_object) [HAVE_DOS_PATHS]: Support backslashes and\n\tdrive letters in file names of dynamic objects.\n\n\t* job.c (construct_command_argv_internal) [WINDOWS32]: Return\n\tright after generating new_argv for one_shell case.  This fixes\n\tthe Windows build for both Unixy shell and stock Windows shells.\n\n2013-04-28  Eli Zaretskii  <eliz@gnu.org>\n\n\t* dir.c (local_stat) [WINDOWS32]: Use the wrapper on MS-Windows.\n\tIf the argument ends in \"dir/.\", make sure the parent dir exists\n\tand is indeed a directory.  Fixes Savannah bug #37065.\n\n2013-04-28  Paul Smith  <psmith@gnu.org>\n\n\t* makeint.h (message_s, error_s): Functions that print to strings\n\trather than directly to files.\n\t* misc.c (message_s, error_s): Create them.\n\t* job.c (child_error): Print error messages to the output sync\n\tlogs, if one exists, rather then directly to the terminal.\n\t(reap_children): Move the per-line sync after child_error().\n\n\t* configure.ac: Remove support for pre-ANSI variadic function calls.\n\t* makeint.h: Ditto.\n\t* misc.c: Ditto.\n\t* config.ami.template: Ditto.\n\t* config.h-vms.template: Ditto.\n\t* config.h.W32.template: Ditto.\n\t* configh.dos.template: Ditto.\n\n\tImplement a \"per-job\" output synchronization option.\n\n\t* main.c (decode_output_sync_flags): Recognize the new option.\n\t* makeint.h (OUTPUT_SYNC_JOB): Add new values for \"job\"\n\t* job.c (assign_child_tempfiles): In per-job mode, truncate the\n\ttemp file for re-use by the next job.\n\t(sync_output): Don't close the temp files as we may still use them.\n\t(free_child): Close the temp files here as we definitely don't\n\tneed them.\n\t(new_job): In per-job output mode, sync_output() after each job.\n\t* job.h (struct child): Avoid ifdefs.\n\t* make.1: Add new options to the man page.\n\t* doc/make.texi (Parallel Output): Break documentation on input\n\tand output into separate sections for readability.  Document the\n\tnew \"job\" and \"none\" modes.\n\n2013-04-27  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Fix oneshell support\n\tfor non-POSIX-sh shells.\n\n\t* load.c (load_object): Extract all POSIX-isms into a separate\n\tfunction for portability.\n\t(load_file): Check the .LOADED variable first and don't invoke\n\tload_object() if it's already been loaded.\n\n2013-04-27  Eli Zaretskii  <eliz@gnu.org>\n\n\t* read.c (record_files): Pay attention to .ONESHELL in MS-Windows.\n\n\t* job.c (construct_command_argv_internal): Support .ONESHELL on\n\tMS-Windows, when the shell is not a Unixy shell.\n\n2013-04-27  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c: Fix compilation error on GNU/Linux due to \"label at end\n\tof compound statement\".\n\n2013-04-27  Frank Heckenbach <f.heckenbach@fh-soft.de>  (tiny change)\n\n\t* job.c (sync_output): Don't discard the output if\n\tacquire_semaphore fails; instead, dump the output unsynchronized.\n\n2013-04-27  Eli Zaretskii  <eliz@gnu.org>\n\n\tSupport --output-sync on MS-Windows.\n\t* w32/compat/posixfcn.c: New file, with emulations of Posix\n\tfunctions and Posix functionality for MS-Windows.\n\n\t* w32/subproc/sub_proc.c: Include io.h.\n\t(process_noinherit): New function, forces a file descriptor to not\n\tbe inherited by child processes.\n\t(process_easy): Accept two additional arguments, and use them to\n\tset up the standard output and standard error handles of the child\n\tprocess.\n\n\t* w32/include/sub_proc.h (process_easy): Adjust prototype.\n\t(process_noinherit): Add prototype.\n\n\t* read.c [WINDOWS32]: Include windows.h and sub_proc.h.\n\n\t* makeint.h (LOCALEDIR) [WINDOWS32}: Define to NULL if not\n\tdefined.  This is needed because the MS-Windows build doesn't have\n\ta canonical place for LOCALEDIR.\n\t(WIN32_LEAN_AND_MEAN) [WINDOWS32]: Define, to avoid getting from\n\twindows.h header too much stuff that could conflict with the code.\n\n\t* main.c <sync_mutex>: New static variable.\n\t<switches>: Add support for \"--sync-mutex\" switch.\n\t(decode_output_sync_flags): Decode the --sync-mutex= switch.\n\t(prepare_mutex_handle_string) [WINDOWS32]: New function.\n\t(main): Add \"output-sync\" to .FEATURES.\n\n\t* job.h (CLOSE_ON_EXEC) [WINDOWS32]: Define to call\n\tprocess_noinherit.\n\t(F_GETFD, F_SETLKW, F_WRLCK, F_UNLCK, struct flock) [WINDOWS32]:\n\tNew macros.\n\t(RECORD_SYNC_MUTEX): New macro, a no-op for Posix platforms.\n\t(sync_handle_t): New typedef.\n\n\t* job.c <sync_handle>: Change type to sync_handle_t.\n\t(FD_NOT_EMPTY): Seek to the file's end.  Suggested by Frank\n\tHeckenbach <f.heckenbach@fh-soft.de>.\n\t(pump_from_tmp_fd) [WINDOWS32]: Switch to_fd to binary mode for\n\tthe duration of this function, and then change back before\n\treturning.\n\t(start_job_command) [WINDOWS32]: Support output_sync mode on\n\tMS-Windows.  Use a system-wide mutex instead of locking\n\tstdout/stderr.  Call process_easy with two additional arguments:\n\tchild->outfd and child->errfd.\n\t(exec_command) [WINDOWS32]: Pass two additional arguments, both\n\t-1, to process_easy, to adjust for the changed function signature.\n\n\t* function.c (windows32_openpipe) [WINDOWS32]: This function now\n\treturns an int, which is -1 if it fails and zero otherwise.  It\n\talso calls 'error' instead of 'fatal', to avoid exiting\n\tprematurely.\n\t(func_shell_base) [WINDOWS32]: Call perror_with_name if\n\twindows32_openpipe fails, now that it always returns.  This avoids\n\ta compiler warning that error_prefix is not used in the MS-Windows\n\tbuild.\n\n\t* config.h.W32.template (OUTPUT_SYNC): Define.\n\n\t* build_w32.bat: Add w32/compat/posixfcn.c to compilation and\n\tlinking commands.\n\n2013-04-20  Stefano Lattarini <stefano.lattarini@gmail.com>  (tiny change)\n\n\t* README.git: Our autoconf input file is 'configure.ac', not\n\t'configure.in'.  Adjust accordingly.\n\t* build_w32.bat: Likewise.\n\t* config.h-vms.template: Likewise.\n\t* Makefile.DOS.template: Likewise.\n\n2013-04-16  Paul Smith  <psmith@gnu.org>\n\n\t* misc.c (open_tmpfd): Add a new function that returns a temporary\n\tfile by file descriptor.\n\t(open_tmpfile): Move here from main.c.\n\t* job.c (assign_child_tempfiles): Use the new open_tmpfd().\n\n2013-04-15  Paul Smith  <psmith@gnu.org>\n\n\t* makeint.h (OUTPUT_SYNC_TARGET, OUTPUT_SYNC_MAKE): Rename.\n\t* job.c (start_job_command): Use new constants.\n\t* main.c: New -O argument format.\n\n\t* doc/make.texi (Options Summary): Document the argument to -O.\n\t* make.1: Ditto.\n\n\t* main.c (define_makeflags): Don't add space between a single-char\n\toption and its argument.\n\n2013-04-06  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Implicit Variables): Clarify LDFLAGS vs. LDLIBS.\n\tFixes Savannah bug #37970.\n\n\t* remake.c (check_dep): Reconsider files waiting on prerequisites,\n\tas they may have finished.  Fixes Savannah bug #37703.\n\n2013-02-28  Paul Smith  <psmith@gnu.org>\n\n\t* function.c (func_realpath): On Solaris (at least) realpath() can\n\tfail due to EINTR, so loop it.  Fixes Savannah bug #38420.\n\n2013-02-25  Paul Smith  <psmith@gnu.org>\n\n\tAdd a proposed supported API for GNU make loaded objects.\n\n\t* doc/make.texi (Loaded Object API): Document it.\n\t* Makefile.am (make_SOURCES): Add new loadapi.c.\n\t* dep.h: Remove eval_buffer(); moved to loadapi.c:gmk_eval().\n\t* read.c (eval_buffer): Change eval_buffer() signature.\n\t* main.c (main): Change eval_buffer() signature.\n\t* variable.h (define_new_function): Change func_ptr signature.\n\t* load.c (SYMBOL_EXTENSION): Change the extension.\n\t* loadapi.c: Implement the new API.\n\t* gnumake.h (gmk_eval): New function prototype.\n\t(gmk_expand) Ditto.\n\t(gmk_add_function) Ditto.\n\t* gmk-default.scm (gmk-eval): Remove: now implemented in guile.c.\n\t* guile.c (guile_expand_wrapper): Use gmk_expand()\n\t(guile_eval_wrapper): Implement eval here to avoid double-expansion.\n\t(guile_define_module): Define gmk-eval.\n\t(func_guile): Use new func_ptr calling model.\n\t(guile_gmake_setup): Use gmk_add_function() to declare $(guile ...)\n\t* function.c (function_table_entry): Provide alternative func_ptr.\n\t(func_eval): New signature for eval_buffer();\n\t(function_table_init): New initialization for function_table_entry.\n\t(expand_builtin_function): Support alternative invocation signature.\n\t(define_new_function): Ditto.\n\n2013-01-20  Paul Smith  <psmith@gnu.org>\n\n\t* gnumake.h: New file to contain externally-visible content.\n\t* makeint.h: Include gnumake.h.  Move gmk_floc type to gnumake.h.\n\t* Makefile.am (include_HEADERS): Install the gnumake.h header.\n\n\t* makeint.h: Change struct floc to gmk_floc typedef.\n\t* Many: Use the new typedef.\n\n\t* make.h: Rename to makeint.h.\n\t* Many: Use the new name makeint.h.\n\n2013-01-19  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (load Directive): Update to discuss location of\n\tloaded object file.\n\t(Remaking Loaded Objects): Document remaking of loaded objects.\n\n\t* main.c (main): Rename READ_MAKEFILES to READ_FILES.\n\t* read.c: Change READ_MAKEFILES to READ_FILES since it now\n\tcontains loaded object files as well.\n\t(read_all_makefiles): Ditto.\n\t(eval_makefile): Ditto.\n\t(eval): Add any loaded file to the READ_FILES list, so that it\n\twill be considered for re-build.\n\n\t* load.c (load_file): Return the simple filename (no symbol) in\n\tthe LDNAME argument (now a const char **).\n\tThis filename should no longer have \"./\" prepended: modify the\n\tfunction to always check the current directory if the name has no\n\t\"/\", before using the normal methods.\n\t* make.h: Change the load_file() prototype.\n\n\t* README.git: Add a bit more documentation on Git workflow & rules.\n\n2013-01-13  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Restore all make flags after re-exec is complete.\n\tFixes Savannah bug #38051.\n\n2013-01-12  Paul Smith  <psmith@gnu.org>\n\n\tConvert CVS archive to Git.\n\n\t* configure.in: Rename to configure.ac.\n\t* README.cvs: Rename to README.git and rework for Git.\n\t* maintMakefile: Use git clean for cleanup.\n\t* ChangeLog: Use new Git repository URL.\n\t* ChangeLog.2: Ditto.\n\t* Makefile.am: Change documentation for Git\n\t* Makefile.DOS.template: Ditto.\n\t* README.template: Ditto.\n\t* build_w32.bat: Ditto.\n\t* prepare_w32.bat: Ditto.\n\t* .cvsignore: Rename to .gitignore, and change to Git format.\n\n2012-12-08  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (create_batch_file): Fix last change: always increment the\n\tcounter of batch files before trying to use it.\n\n2012-12-07  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Remove \" from\n\tsh_chars_dos[].  Ignore an escaped backslash inside a string\n\tquoted with \"..\".  This lifts the 4KB or 8KB command-line length\n\tlimitation imposed by the Windows shells when a command uses quoted\n\tstrings, because we now don't call the shell in that case.\n\n\t* job.c (create_batch_file): Declare the counter of batch files\n\tstatic, to avoid having 2 jobs using the same file name and\n\tstepping on each other's toes.  When all 64K names are used up,\n\tmake one more loop looking for slots that became vacant.  This\n\tavoids leaving behind temporary batch files in the temporary\n\tdirectory, which happens frequently on a fast machine when using\n\tparallel builds.\n\t(reap_children): Add debug message for when removal of a temporary\n\tbatch file fails.\n\n2012-10-29  Paul Smith  <psmith@gnu.org>\n\n\tNew feature: \"load\" directive for dynamically-loaded objects.\n\n\t* NEWS: Document new \"load\" directive.\n\t* doc/make.texi (Extending make): New chapter on extensions to make.\n\t* configure.in: Check for dlopen/dlsym/dlerror and -ldl.\n\t* Makefile.am (make_SOURCES): Add new file load.c.\n\t* make.h: Prototype for load_file().\n\t* main.c (main): Add \"load\" to .FEATURES if it's available.\n\t* read.c (eval): Parse \"load\" and \"-load\" directives.\n\n2012-09-29  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Require a new version of gettext (1.18.1).\n\tFixes Savannah bug #37307.\n\n2012-09-09  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in (bsd_signal): Define _GNU_SOURCE, a la make.h.\n\tFixes Savannah bug #32247.\n\n\t* remake.c (update_file_1): Force intermediate files to be\n\tconsidered, not pruned, if their non-intermediate parent needs to\n\tbe remade.  Fixes Savannah bug #30653.\n\n\t* job.c (construct_command_argv_internal): Keep the command line\n\ton the heap for very long lines.  Fixes Savannah bug #36451.\n\n\t* function.c (func_realpath): BSD realpath(3) doesn't fail if the\n\tfile does not exist: use stat.  Fixes Savannah bug #35919.\n\n\t* file.c (expand_deps): Duplicate the current variable buffer, not\n\tthe old pointer.  Fixes Savannah bug #36925.\n\n\t* read.c (eval): If we detect an initial UTF-8 BOM, skip it.\n\tFixes Savannah bug #36529.\n\t(record_target_var): Remove unused variable \"fname\".\n\t(eval): Use the correct pointer when adding to the variable buffer.\n\tFixes Savannah bug #36106.\n\n2012-09-09  Eli Zaretskii  <eliz@gnu.org>\n\n\t* read.c (unescape_char): Fix a thinko in the last change.\n\n2012-09-09  Paul Smith  <psmith@gnu.org>\n\n\t* default.c (default_variables): Use a correct default LIBPPATERNS\n\tfor MacOS.  Fixes Savannah bug #37197.\n\n\t* read.c (record_files): Reset the default macro values if .POSIX\n\tis set.  Fixes Savannah bug #37069.\n\t(parse_file_seq): Break out of an infinite loop if we're not\n\tmaking progress when parsing archive references.\n\n2012-09-01  Eli Zaretskii  <eliz@gnu.org>\n\n\t* README.W32.template: Update for job-server and Guile support.\n\n\t* read.c (unescape_char): Advance 'p' after copying the unescaped\n\tcharacters.  Otherwise the backslashes are incorrectly erased from\n\tthe original string.\n\n2012-03-05  Paul Smith  <psmith@gnu.org>\n\n\tUpdate copyright notices to use year ranges, as allowed by\n\tclarifications in the GNU Maintainer's Manual.\n\n2012-03-04  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (unescape_char): New function to remove escapes from a char.\n\t(record_files): Call it on the dependency string to unescape \":\".\n\tFixes Savannah bug #12126 and bug #16545.\n\n\t* make.h (CSTRLEN): Determine the length of a constant string.\n\t* main.c: Use the new macro.\n\t* read.c: Ditto.\n\t* variable.h: Ditto.\n\t* function.c: Simplify checks for function alternatives.\n\n\t* expand.c (variable_append): If the current set is local and the\n\tnext one is not a parent, then treat the next set as\n\tlocal as well.  Fixes Savannah bug #35468.\n\n2012-03-03  Paul Smith  <psmith@gnu.org>\n\n\t* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Add support for AIX 5.2+\n\tnanosecond timestamps.  Fixes Savannah bug #32485.\n\n\tConvert uses of `foo' for quoting to 'foo' to reflect changes in\n\tthe GNU Coding Standards.  Fixes Savannah bug #34530.\n\n\t* job.c (construct_command_argv_internal): In oneshell we need to\n\tbreak the SHELLFLAGS up for argv.  Fixes Savannah bug #35397.\n\n\t* function.c (func_filter_filterout): Recompute the length of each\n\tfilter word in case it was compressed due to escape chars.  Don't\n\treset the string as it's freed.  Fixes Savannah bug #35410.\n\n\t* misc.c (collapse_continuations): Only use POSIX-style\n\tbackslash/newline handling if the .POSIX target is set.\n\tAddresses Savannah bug #16670 without backward-incompatibility.\n\t* NEWS: Document behavior change.\n\t* doc/make.texi (Splitting Lines): New section describing how to\n\tuse backslash/newline to split long lines.\n\n2012-02-26  Paul Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Check the stem length to avoid\n\tstack overflows in stem_str.  Fixes Savannah bug #35525.\n\n2012-02-03  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/sub_proc.c (proc_stdin_thread, proc_stdout_thread)\n\t(proc_stderr_thread, process_pipe_io): Ifdef away unused\n\tfunctions.\n\n\t* w32/subproc/w32err.c (map_windows32_error_to_string) [_MSC_VER]:\n\tDon't use TLS storage for szMessageBuffer.  Ifdef away special\n\tcode for handling Winsock error codes.  Make the function return a\n\t`const char *'.  Suggested by Ozkan Sezer.  Fixes Savannah bug #34832.\n\n2012-01-29  Paul Smith  <psmith@gnu.org>\n\n\t* gmk-default.scm (to-string-maybe): Variables map to empty strings.\n\tIn Guile 2.0, (define ...) results in a variable object so make\n\tsure that maps to an empty string in make.\n\n\t* variable.c (parse_variable_definition): New POSIX assignment ::=\n\tTake a struct variable to return more information after parsing.\n\t(assign_variable_definition): New parse_variable_definition() call.\n\t* variable.h: New declaration of parse_variable_definition().\n\t* read.c (do_define): New parse_variable_definition() call.\n\t(parse_var_assignment): Ditto.\n\t(get_next_mword): Parse ::= as a variable assignment.\n\t* doc/make.texi (Flavors): Describe the new ::= syntax.\n\t* NEWS: Mention the ::= operator.\n\n\t* variable.h (struct variable): Rearrange elts to reduce struct size.\n\n\t* function.c (func_file): Create a new function, $(file ...)\n\t* doc/make.texi (File Function): Document the $(file ..) function.\n\t* NEWS: Announce it.\n\n\t* gmk-default.scm (to-string-maybe): Use a more portable way to\n\ttest for unprintable characters.\n\t* configure.in [GUILE]: Guile 1.6 doesn't have pkg-config\n\t* build_w32.bat: Ditto.\n\n2012-01-28  Eli Zaretskii  <eliz@gnu.org>\n\n\t* config.h.W32.template: Update from config.h.in.\n\n\tSupport a Windows build with Guile.\n\n\t* README.W32.template: Update with instructions for building with\n\tGuile.\n\n\t* build_w32.bat: Support building with Guile.\n\n\t* make.h [HAVE_STDINT_H]: Include stdint.h.\n\n\t* main.c (main, clean_jobserver): Move declarations of variables\n\tnot used in the WINDOWS32 build to the #else branch, to avoid\n\tcompiler warnings.\n\n\tFix failures on MS-Windows when Make's standard handles are invalid.\n\tThis can happen when Make is invoked from a GUI application.\n\n\t* w32/subproc/sub_proc.c (process_init_fd): Don't dereference\n\tpproc if it is a NULL pointer.\n\t(process_begin, process_cleanup): Don't try to close pipe handles\n\twhose value is INVALID_HANDLE_VALUE.\n\t(process_easy): Initialize hIn, hOut, and hErr to\n\tINVALID_HANDLE_VALUE.  If DuplicateHandle fails with\n\tERROR_INVALID_HANDLE, duplicate a handle for the null device\n\tinstead of STD_INPUT_HANDLE, STD_OUTPUT_HANDLE or\n\tSTD_ERROR_HANDLE.  Don't try to close pipe handles whose value is\n\tINVALID_HANDLE_VALUE.\n\n\t* function.c (windows32_openpipe): Initialize hIn and hErr to\n\tINVALID_HANDLE_VALUE.  If DuplicateHandle fails with\n\tERROR_INVALID_HANDLE, duplicate a handle for the null device\n\tinstead of STD_INPUT_HANDLE or STD_ERROR_HANDLE.  Fix indentation.\n\tDon't try to close handles whose value is INVALID_HANDLE_VALUE.\n\n2012-01-25  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (define_new_function): Fix format strings in calls to\n\t`fatal'.\n\n2012-01-17  Paul Smith  <psmith@gnu.org>\n\n\t* guile.c (func_guile): Handle NULL returns from Guile.\n\n2012-01-16  Paul Smith  <psmith@gnu.org>\n\n\t* make.h (PATH_SEPARATOR_CHAR): Allow resetting for crosscompiling\n\tfor Windows.  Patch by Chris Sutcliffe <ir0nh34d@gmail.com>\n\tFixes Savannah bug #34818.\n\n2012-01-15  Paul Smith  <psmith@gnu.org>\n\n\t* variable.h: Prototype an interface for defining new make functions.\n\t* function.c (define_new_function): Define it.\n\t(func_guile): Remove the \"guile\" function.\n\t(function_table_init): Ditto.\n\t* guile.c (func_guile): Add the \"guile\" function here.\n\t(setup_guile): Call define_new_function() to define it.\n\t(guile_eval_string): Obsolete.\n\n\t* all: Update copyright notices.\n\n2012-01-12  Paul Smith  <psmith@gnu.org>\n\n\tSupport GNU Guile as an embedded extension language for GNU make.\n\n\t* NEWS: Note the new Guile capability.\n\t* Makefile.am (EXTRA_DIST, make_SOURCES): Add new guile source files.\n\t(AM_CFLAGS): Add Guile compiler flags.\n\t(guile): Add a rule for converting default SCM into a C header.\n\t* configure.in: Add support for --with-guile.\n\tAlso, convert the entire file to properly escaped autoconf m4, and\n\tutilize newer features such as AS_IF() and AS_CASE().\n\t* doc/make.texi (Guile Function): Document the GNU guile integration.\n\t* make.h (guile_eval_string, guile_boot): Prototypes for Guile.\n\t* main.c (main): Run guile_boot() to handle main().\n\t(real_main): All the previous content of main() is here.\n\t(real_main): Add \"guile\" to the .FEATURES variable.\n\t* function.c (func_guile): Call Guile.\n\t* guile.c: New file implementing GNU make integration with GNU Guile.\n\t* gmk-default.scm: The integration of GNU make with Guile uses\n\tGuile itself for much of the parsing and conversion of return\n\ttypes, etc.  This implementation is embedded into GNU make.\n\t* config.h-vms.template: Disable Guile support.\n\t* config.h.W32.template: Ditto.\n\t* configh.dos.template: Ditto.\n\t* config.ami.template: Ditto.\n\t* makefile.vms: Add new Guile files.\n\t* Makefile.DOS.template: Ditto.\n\t* Makefile.ami: Ditto.\n\t* NMakefile.template: Ditto.\n\t* SMakefile.template: Ditto.\n\t* build_w32.bat: Ditto.\n\t* dosbuild.bat: Ditto.\n\t* make_msvc_net2001.vcproj: Ditto.\n\n2011-11-15  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Use %ld when printing DWORD values.\n\t* job.c (new_job): Ditto.\n\t* w32/include/sub_proc.h: Use const.\n\t* w32/subproc/sub_proc.c (open_jobserver_semaphore): Use const.\n\tFixes Savannah bug #34830.  Changes suggested by Ozkan Sezer.\n\n\t* configure.in (MAKE_JOBSERVER): Enable jobserver on W32 systems.\n\t* config.h.W32.template (MAKE_JOBSERVER): Ditto.\n\n2011-11-14  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (eval): parse_file_seq() might shorten the string due to\n\tbackslash removal.  Start parsing again at the colon.\n\tFixes Savannah bug #33399.\n\n2011-11-13  Paul Smith  <psmith@gnu.org>\n\n\t* file.c (file_timestamp_cons): Match up data types to avoid warnings.\n\t* filedef.h: Ditto.\n\t* misc.c (concat): Ditto.\n\t* read.c (eval): Assign value to avoid warnings.\n\t* function.c (func_shell_base): Use fork() instead of vfork() to\n\tavoid warnings.\n\t* make.h (INTEGER_TYPE_SIGNED): Use <=0 to avoid warnings.\n\tFixes Savannah bug #34608.\n\n\t* job.c (construct_command_argv): Remove _p.\n\t(construct_command_argv_internal): Remove _ptr.\n\tFixes Savannah bug #32567.\n\n\t* main.c (clean_jobserver): Don't write the free token to the pipe.\n\tChange suggested by Tim Newsome <tnewsome@aristanetworks.com>\n\n\t* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Add support for Darwin.\n\t* filedef.h (FILE_TIMESTAMP_STAT_MODTIME): Ditto.\n\tPatch provided by Troy Runkel <Troy.Runkel@mathworks.com>\n\n2011-10-11  Troy Runkel  <Troy.Runkel@mathworks.com>\n\n\t* config.h.W32: Enable job server support for Windows.\n\t* main.c [WINDOWS32]: Include sub_proc.h\n\t(main): Create a named semaphore to implement the job server.\n\t(clean_jobserver): Free the job server semaphore when make is finished.\n\t* job.c [WINDOWS32]: Define WAIT_NOHANG\n\t(reap_children): Support non-blocking wait for child processes.\n\t(free_child): Release job server semaphore when child process finished.\n\t(job_noop): Don't define function on Windows.\n\t(set_child_handler_action_flags): Don't define function on Windows.\n\t(new_job): Wait for job server semaphore or child process termination.\n\t(exec_command): Pass new parameters to process_wait_for_any.\n\t* w32/include/sub_proc.h [WINDOWS32]: New/updated EXTERN_DECL entries.\n\t* w32/subproc/sub_proc.c [WINDOWS32]: Added job server implementation.\n\t(open_jobserver_semaphore): Open existing job server semaphore by name.\n\t(create_jobserver_semaphore): Create new job server named semaphore.\n\t(free_jobserver_semaphore): Close existing job server semaphore.\n\t(acquire_jobserver_semaphore): Decrement job server semaphore count.\n\t(release_jobserver_semaphore): Increment job server semaphore count.\n\t(has_jobserver_semaphore): Returns whether job server semaphore exists.\n\t(get_jobserver_semaphore_name): Returns name of job server semaphore.\n\t(wait_for_semaphore_or_child_process): Wait for either the job server\n\tsemaphore to become signalled or a child process to terminate.\n\t(process_wait_for_any_private): Support for non-blocking wait for child.\n\t(process_wait_for_any): Added support for non-blocking wait for child.\n\t(process_file_io): Pass new parameters to process_wait_for_any_private.\n\n2011-09-18  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): If we're re-exec'ing and we're the master make,\n\tthen restore the job_slots value so it goes back into MAKEFLAGS\n\tproperly.  See Savannah bug #33873.\n\n\t* remake.c (library_search): STD_DIRS is computed when other\n\tstatic vars like buflen etc. are computed, so it must be static\n\tas well.  See Savannah bug #32511.\n\n2011-09-16  Paul Smith  <psmith@gnu.org>\n\n\t* maintMakefile (do-po-update): Apparently we have to avoid\n\tcertificate checks on the https://translationproject.org site now.\n\n2011-09-12  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Ensure exported variables are defined in the\n\tglobal scope.  Fixes Savannah bug #32498.\n\n2011-09-11  Paul Smith  <psmith@gnu.org>\n\n\t* Makefile.am (dist-hook): Remove w32/Makefile and .deps/ from the\n\tdist file.  Fixes Savannah bug #31489.\n\n\t* doc/make.texi (Complex Makefile): Add a hint about using\n\t#!/usr/bin/make (for Savannah support request #106459)\n\n2011-09-02  Paul Smith  <psmith@gnu.org>\n\n\t* remake.c (touch_file): If we have both -n and -t, -n takes\n\tprecedence.  Patch from Michael Witten <mfwitten@gmail.com>\n\n2011-08-29  Paul Smith  <psmith@gnu.org>\n\n\t* expand.c (variable_expand_string): Always allocate a new buffer\n\tfor a string we're expanding.  The string we're working on can get\n\tfreed while we work on it (for example if it's the value of a\n\tvariable which modifies itself using an eval operation).\n\tSee Savannah patch #7534 for the original report by Lubomir Rintel.\n\n2011-06-12  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (parse_file_seq): Move the check for empty members out of\n\tthe loop so we can go to the next member properly.\n\tAnother fix for Savannah bug #30612.\n\n\t* config.h-vms.template: Newer versions of VMS have strncasecmp()\n\tPatch provided by: Hartmut Becker <becker.ismaning@freenet.de>\n\n2011-05-07  Paul Smith  <psmith@gnu.org>\n\n\t* expand.c (variable_append): Add a LOCAL argument to track\n\twhether this is the first invocation or not.  If it's not and\n\tprivate_var is set, then skip this variable and try the next one.\n\tFixes Savannah bug #32872.\n\n\t* read.c (parse_file_seq): Ensure existence checks use glob().\n\n2011-05-07  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Don't assume shellflags\n\tis always non-NULL.  Escape-protect characters special to the\n\tshell when copying the value of SHELL into new_line.  Fixes\n\tSavannah bug #23922.\n\n2011-05-02  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Special Variables): Add documentation for the new\n\twords in .FEATURES.  Fixes Savannah bug #32058.\n\t(Flavor Function): Rewrite the section on the flavor function.\n\tFixes Savannah bug #31582.\n\n\t* function.c (func_sort): Use the same algorithm to count the\n\tnumber of words we will get after the split, as we use to split.\n\tBased on a patch from Matthias Hopf.  Fixes Savannah bug #33125.\n\n\t* make.h: Make global variable stack_limit extern.\n\tFixes Savannah bug #32753.\n\n2011-05-01  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (parse_file_seq): Don't try to invoke glob() unless there\n\tare potential wildcard characters in the filename.  Performance\n\tenhancement suggested by Michael Meeks <michael.meeks@novell.com>\n\n2011-04-29 Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* read.c (eval_makefile): Delay caching of the file name until after\n\tall the expansions and searches.\n\n2011-04-17  David A. Wheeler  <dwheeler@dwheeler.com>\n\n\t* doc/make.texi (Reading Makefiles): Document \"!=\".\n\t(Setting): Ditto.\n\t(Features): Ditto.\n\t* variable.h (enum variable_flavor): New type \"f_shell\".\n\t* variable.c (shell_result): Send a string to the shell and store\n\tthe output.\n\t(do_variable_definition): Handle f_shell variables: expand the\n\tvalue, then send it to the shell and store the result.\n\t(parse_variable_definition): Parse \"!=\" shell assignments.\n\t* read.c (get_next_mword): Treat \"!=\" as a varassign word.\n\t* function.c (fold_newlines): If trim_newlines is set remove all\n\ttrailing newlines; otherwise remove only the last newline.\n\t(func_shell_base): Move the guts of the shell function here.\n\t(func_shell): Call func_shell_base().\n\n2011-02-21  Paul Smith  <psmith@gnu.org>\n\n\t* strcache.c (various): Increase performance based on comments\n\tfrom Ralf Wildenhues <Ralf.Wildenhues@gmx.de>.  Stop looking for\n\ta buffer when we find the first one that fits, not the best fit.\n\tIf there is not enough free space in a buffer move it to a\n\tseparate list so we don't have to walk it again.\n\t* make.h (NDEBUG): Turn off asserts unless maintainer mode is set.\n\t(strcache_add_len, strcache_setbufsize): Use unsigned length/size.\n\t* maintMakefile (AM_CPPFLAGS): Enable MAKE_MAINTAINER_MODE.\n\n\t* remake.c (complain): Move translation lookups closer to use.\n\n2011-02-13  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi: Clean up references to \"static\" variables and\n\tsemicolon errors.  Patch from Michael Witten <mfwitten@gmail.com>.\n\n2010-12-27  Paul Smith  <psmith@gnu.org>\n\n\t* make.1: Update the header/footer info in the man page.\n\n2010-11-28  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (record_target_var): Don't reset v if it's the same as\n\tthe global version.  Fixes Savannah bug #31743.\n\n2010-11-06  Paul Smith  <psmith@gnu.org>\n\n\t* variable.c (print_auto_variable): Print auto variables; ignore others.\n\t(print_noauto_variable): Print non-auto variables; ignore others.\n\t(print_variable_set): Allow the caller to select which type to print.\n\t(print_target_variables): Show all the non-auto variables for a target.\n\n\t* default.c (install_default_suffix_rules): Initialize recipe_prefix.\n\t* rule.c (install_pattern_rule): Ditto.\n\t* read.c (record_files): Pass in the current recipe prefix.  Remember\n\tit in the struct command for these targets.\n\t(eval): Remember the value of RECIPEPREFIX when we start parsing.\n\tDo not remove recipe prefixes from the recipe here: we'll do it later.\n\t* job.c (start_job_command): Remove recipe prefix characters early,\n\tbefore we print the output or chop it up.\n\t* file.c (print_file): If recipe_prefix is not standard, reset it\n\tin -p output.  Assign target variables in -p output as well.\n\n\t* commands.c (chop_commands): Max command lines is USHRT_MAX.\n\tSet any_recurse as a bitfield.\n\t* make.h (USHRT_MAX): Define if not set.\n\n2010-10-27  Paul Smith  <psmith@gnu.org>\n\n\t* commands.h (struct commands): Rearrange to make better use of\n\tmemory.  Add new recipe_prefix value.\n\n2010-10-26  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Setting): Document the treatment of\n\tbackslash-newline in variable values.\n\t* misc.c (collapse_continuations): Do not collapse multiple\n\tbackslash-newlines into a single space.  Fixes Savannah bug #16670.\n\n2010-08-29  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Implicit Variables): Document LDLIBS and LOADLIBES.\n\tFixes Savannah bug #30807.\n\t(Instead of Execution): Mention that included makefiles are still\n\trebuilt even with -n.  Fixes Savannah bug #30762.\n\n\t* configure.in: Bump to 3.82.90.\n\n\t* make.h: Add trace_flag variable.\n\t* main.c (switches): Add --trace option.\n\t(trace_flag): Declare variable.\n\t* job.c (start_job_command): Show recipe if trace_flag is set.\n\t(new_job): Show trace messages if trace_flag is set.\n\t* doc/make.texi (Options Summary): Document the new --trace option.\n\t* make.1: Add --trace documentation.\n\t* NEWS: Mention --trace.\n\n\t* job.c\t(child_error): Show recipe filename/linenumber on error.\n\tAlso show \"(ignored)\" when appropriate even for signals/coredumps.\n\t* NEWS: Mention file/linenumber change.\n\n\t* main.c (main): Print version info when DB_BASIC is set.\n\n\t* job.c (construct_command_argv_internal): If shellflags is not\n\tset, choose an appropriate default value.  Fixes Savannah bug #30748.\n\n2010-08-27  Eli Zaretskii  <eliz@gnu.org>\n\n\t* variable.c (define_automatic_variables) [__MSDOS__ || WINDOWS32]:\n\tRemove trailing backslashes in $(@D), $(<D), etc., for consistency\n\twith forward slashes.  Fixes Savannah bug #30795.\n\n2010-08-13  Paul Smith  <psmith@gnu.org>\n\n\t* NEWS: Accidentally forgot to back out the sorted wildcard\n\tenhancement in 3.82, so update NEWS.\n\tAlso add NEWS about the error check for explicit and pattern\n\ttargets in the same rule, added to 3.82.\n\n\t* main.c (main): Add \"oneshell\" to $(.FEATURES) (forgot to add\n\tthis in 3.82!)\n\n\t* read.c (parse_file_seq): Fix various errors parsing archives\n\twith multiple objects in the parenthesis, as well as wildcards.\n\tFixes Savannah bug #30612.\n\n2010-08-10  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Expand MAKEFLAGS before adding it to the\n\tenvironment when re-exec'ing.  Fixes Savannah bug #30723.\n\n2010-08-07  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/build.bat: Make all 3 cl.exe compile command lines\n\tuse the same /I switches.  Fixes Savannah bug #30662.\n\n\t* function.c (func_shell) [WINDOWS32]: Reset just_print_flag\n\taround the call to construct_command_argv, so that a temporary\n\tbatch file _is_ created when needed for $(shell).\n\tFixes Savannah bug #16362.\n\n2010-08-07 Juan Manuel Guerrero  <juan.guerrero@gmx.de>\n\n\t* configh.dos.template (HAVE_STRNCASECMP): Define.\n\n2010-07-28  Paul Smith  <psmith@gnu.org>\n\n\tVersion 3.82 released.\n\n\t* configure.in: Change release version.\n\t* NEWS: Change the date.\n\n\t* read.c (parse_file_seq): Remove GLOB_NOSORT for\n\tbackward-compatibility.  We'll add it back in next release.\n\t* NEWS: Note it.\n\n2010-07-24  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (pid2str) [WINDOWS32]: Fix CPP conditionals for using %Id\n\tformat.\n\n2010-07-18  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Switch bsd_signal to AC_CHECK_DECLS() to make sure\n\twe have a declaration.  Fixes Savannah bug #25713 (maybe?)\n\t* doc/make.texi (Complex Makefile): Cleanup variable assignments.\n\t(One Shell): New subsection for the .ONESHELL special target.\n\n\tPatches by Ozkan Sezer <sezeroz@gmail.com>:\n\n\t* misc.c (strncasecmp): Local implementation for systems without.\n\t* config.h.W32.template (HAVE_STRNICMP): Define on Windows.\n\t* configure.in: Check for strncasecmp/strncmpi/strnicmp.\n\t* job.c [WINDOWS32]: Don't define dup2 on Windows.\n\t(pid2str): Use \"%Id\" even with MSVC\n\t(exec_command): Cast to pid_t when calling pid2str().\n\t* w32/subproc/sub_proc.c [WINDOWS32]: Include config.h first.\n\tUse stddef.h on MSVC to get intptr_t.\n\t* w32/subproc/misc.c [WINDOWS32]: Include config.h first.\n\t* w32/compat/dirent.c [WINDOWS32]: Include config.h first.\n\t(readdir): Cast -1 to correct type for d_ino.\n\t* w32/pathstuff.c [WINDOWS32]: Ensure make.h is included first.\n\t* make.h [WINDOWS32]: Don't prototype alloca() on Windows.\n\tAdd configuration for strncasecmp().\n\t* main.c (ADD_SIG) [WINDOWS32]: Avoid warnings in MSVC.\n\t* config.h.W32.template [WINDOWS32]: Don't warn on unsafe\n\tfunctions or variables.\n\t* NMakefile.template [WINDOWS32]: Remove /MACHINE:I386.\n\t* main.c (clean_jobserver): Cast due to MSVC brokenness.\n\t(decode_switches): Ditto.\n\t* vpath.c (construct_vpath_list): Ditto.\n\t* rule.c (freerule): Ditto.\n\t* ar.c (ar_glob): Ditto.\n\n2010-07-16  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* misc.c (concat): Fix buffer overrun.\n\n2010-07-12  Paul Smith  <psmith@gnu.org>\n\n\tUpdate copyrights to add 2010.\n\n\t* build_w32.bat: Support for MSVC Windows x86_64 builds.\n\t* job.c: Don't define execve() on MSVC/64bit.\n\tPatch by Viktor Szakats.  Fixes Savannah bug #27590.\n\n2010-07-12  Eli Zaretskii  <eliz@gnu.org>\n\n\t* make.h (alloca) [!__GNUC__]: Don't define prototype.\n\t(int w32_kill): Use pid_t for process ID argument.\n\tFixes Savannah bug #27809.\n\n2010-07-12  Paul Smith  <psmith@gnu.org>\n\n\tIntegrated new .ONESHELL feature.\n\tPatch by David Boyce <dsb@boyski.com>.  Modified by me.\n\n\t* NEWS: Add a note about the new feature.\n\t* job.c (is_bourne_compatible_shell): Determine whether we're\n\tusing a standard POSIX shell or not.\n\t(start_job_command): Accept '-ec' as POSIX shell flags.\n\t(construct_command_argv_internal): If one_shell is set and we are\n\tusing a POSIX shell, remove \"interior\" prefix characters such as\n\t\"@\", \"+\", \"-\".  Also treat \"\\n\" as a special character when\n\tchoosing the slow path, if ONESHELL is set.\n\t* job.h (is_bourne_compatible_argv): Define the new function.\n\n\t* make.h (one_shell): New global variable to remember setting.\n\t* main.c: Declare it.\n\t* read.c (record_files): Set it.\n\t* commands.c (chop_commands): If one_shell is set, don't chop\n\tcommands into multiple lines; just keep one line.\n\n2010-07-09  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/sub_proc.c: Include stdint.h.\n\t(sub_process_t): Use intptr_t for file handles and pid_t for\n\tprocess ID.\n\t(process_pipes, process_init_fd, process_begin): Use intptr_t for\n\tfile handles and pid_t for process ID.  Fixes Savannah bug #27809.\n\tPatch by Ozkan Sezer <sezeroz@gmail.com>\n\n\t* function.c (abspath): Support absolute file names in UNC format.\n\tFixes Savannah bug #30312.\n\n\t* job.c (pid2str) [WINDOWS32]: Don't use %Id with GCC < 4.x.\n\t(exec_command) [WINDOWS32]: Use pid2str instead of non-portable\n\t%Id.\n\n\t* main.c (handle_runtime_exceptions): Use %p to print addresses,\n\tto DTRT on both 32-bit and 64-bit hosts.  Savannah bug #27809.\n\n\t* job.c (w32_kill, start_job_command, create_batch_file): Use\n\tpid_t for process IDs and intptr_t for the 1st arg of\n\t_open_osfhandle.\n\t* function.c (windows32_openpipe): Use pid_t for process IDs and\n\tintptr_t for the 1st arg of _open_osfhandle.\n\t(func_shell): Use pid_t for process IDs.\n\t* main.c (main) [WINDOWS32]: Pacify the compiler.\n\t* config.h.W32.template (pid_t): Add a definition for 64-bit\n\tWindows builds that don't use GCC.  Fixes Savannah bug #27809.\n\tPatch by Ozkan Sezer <sezeroz@gmail.com>\n\n2010-07-07  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Bump to a new prerelease version 3.81.91.\n\n2010-07-06  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Set a default value of \"-c\" for .SHELLFLAGS.\n\t* NEWS: Mention the new behavior of .POSIX and the new .SHELLFLAGS\n\tvariable.\n\t* job.c (construct_command_argv): Retrieve the .SHELLFLAGS value\n\tand pass it to construct_command_argv_internal().\n\t(construct_command_argv_internal): If .SHELLFLAGS is non-standard\n\tuse the slow path.  Use that value instead of hard-coded \"-c\".\n\n2010-07-05  Paul Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): lastslash can be const.\n\t* dir.c (downcase): Remove unused variable.\n\t* hash.c (hash_init): Cast sizeof for error message.\n\t* arscan.c (ar_scan): Cast to char* for WINDOWS32.\n\t(ar_member_touch): Ditto.\n\t* ar.c (glob_pattern_p): Avoid symbol collision: open -> opened\n\t* signame.c (strsignal): Ditto: signal -> sig\n\t* job.c (create_batch_file): Ditto: error -> error_string\n\t(pid2str): Portably convert a pid_t into a string\n\t(reap_children): Use it.\n\t(start_waiting_job): Use it.\n\tSavannah bug #27809.  Patch by Ozkan Sezer <sezeroz@gmail.com>\n\n2010-07-03  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (parse_file_seq): All archive groups must end with ')' as\n\tthe LAST character in a word.  If there is no word ending in ')'\n\tthen it's not an archive group.  Fixes Savannah bug #28525.\n\n2010-07-01  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Append optional features using separate calls.\n\tNot as efficient but not all compilers allow conditionals inside\n\tmacro calls.  Fixes Savannah bug #29244.\n\n2010-01-10  Paul Smith  <psmith@gnu.org>\n\n\t* make.h (patheq): Rename strieq() to patheq() for clarity.\n\t* dir.c (dir_contents_file_exists_p): Use it.\n\n\t* dir.c (file_impossible): Convert xmalloc/memset to xcalloc.\n\t* file.c (enter_file): Ditto.\n\t* job.c (new_job): Ditto.\n\n2009-12-11  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (construct_command_argv_internal) <sh_cmds_dos>\n\t[WINDOWS32]: Add \"echo.\" and a few more commands that are built\n\tinto cmd.exe.  Fixes Savannah bug #28126.\n\n\t* file.c (lookup_file) [HAVE_DOS_PATHS]: Treat '\\\\' like we do\n\twith '/'.\n\n2009-11-15  Paul Smith  <psmith@gnu.org>\n\n\tPatches for VMS provided by Hartmut Becker <Hartmut.Becker@hp.com>\n\n\t* vmsjobs.c (ctrlYPressed) [VMS]: Deal with CTRL-Y.\n\t(vmsHandleChildTerm) [VMS]: Ditto.\n\t(astYHandler) [VMS]: Ditto.\n\t(tryToSetupYAst) [VMS]: Ditto.\n\t(child_execute_job) [VMS]: Ditto.\n\n\t* vmsify.c (trnlog) [VMS]: Fix const errors.\n\t(vmsify) [VMS]: Ditto.\n\n\t* readme.vms [VMS]: Update with notes for 3.82.\n\n\t* job.h (comname) [VMS]: Remember the temporary command filename\n\n\t* dir.c (vmsify) [VMS]: Fix const errors.\n\t(vms_hash) [VMS]: Ditto.\n\t(vmsstat_dir) [VMS]: Ditto.\n\t(find_directory) [VMS]: Fix case-insensitive option for VMS\n\t(dir_contents_file_exists_p) [VMS]: Ditto.\n\t(file_impossible) [VMS]: Ditto.\n\n\t* config.h-vms.template (HAVE_FDOPEN) [VMS]: Have it.\n\t(HAVE_STRCASECMP) [VMS]: Ditto.\n\n\t* arscan.c (VMS_get_member_info) [VMS]: Fix timezone computation.\n\t(ar_scan) [VMS]: Fix const error.\n\n2009-11-12  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* vpath.c (vpath_search, selective_vpath_search): Add index arguments\n\twhich allows the caller to get the index of the matching directory.\n\n\t* make.h (vpath_search): Update prototype.\n\n\t* remake.c (library_search): Implement linker-compatible library\n\tsearch. Use the new VPATH_SEARCH index functionality to keep track\n\tof the directory index for each match. Select the match with the\n\tlowest directory index.\n\n\t* implicit.c (pattern_search): Pass NULL for the index arguments in\n\tthe VPATH_SEARCH call.\n\n\t* doc/make.texi (Directory Search for Link Libraries): Describe the\n\tnew search behavior.\n\n\t* NEWS: Add a note about the new behavior.\n\n2009-10-25  Paul Smith  <psmith@gnu.org>\n\n\t* AUTHORS, et.al.: Update copyright years.\n\n\t* implicit.c (stemlen_compare): Fix qsort() compare bug that\n\tcaused implicit rules with equal stem lengths to be sorted\n\tindeterminately.\n\n2009-10-24  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (usage): Add --eval to the usage string.\n\t(switches): Add the --eval switch.\n\t(main): If --eval is given, add them to the simply-expanded variable\n\t-*-eval-flags-*- (necessary to allow recursion to work properly).\n\t(define_makeflags): Add -*-eval-flags-*- to MAKEFLAGS.\n\n\t* NEWS: Describe the new --eval command line argument.\n\t* doc/make.texi (Options Summary): Document --eval.\n\n\t* dep.h: eval_buffer() returns void.\n\t* read.c (eval_buffer): Ditto.\n\t(eval): Ditto.\n\n\t* variable.h (define_variable_cname): New macro for constant\n\tvariable names.\n\t* default.c (set_default_suffixes): Use it.\n\t* main.c (main): Ditto.\n\t(handle_non_switch_argument): Ditto.\n\t(define_makeflags): Ditto.\n\t* read.c (read_all_makefiles): Ditto.\n\t* variable.c (define_automatic_variables): Ditto.\n\n\t* commands.c (dep_hash_cmp): Avoid casts.\n\t(dep_hash_1): Ditto.\n\t(dep_hash_2): Ditto.\n\n2009-10-22  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* read.c (read_all_makefiles): Mark the default makefile dependency\n\tdontcare.\n\n2009-10-07  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* read.c (do_undefine): Free the expanded variable name.\n\n\t* commands.c (dep_hash_cmp, set_file_variables): Move the order-only\n\tto normal upgrade logic from  dep_hash_cmp to set_file_variables.\n\n2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* dep.h (uniquize_deps): Remove.\n\n\t* read.c (uniquize_deps): Merge into set_file_variables in\n\tcommands.c.\n\t(dep_hash_1, dep_hash_2, dep_hash_cmp): Move to commands.c.\n\n\t* commands.c (set_file_variables): Avoid modifying the dep\n\tchain to achieve uniqueness. Fixes savannah bug 25780.\n\n\t* implicit.c (pattern_search): Instead of re-setting all automatic\n\tvariables for each rule we try, just update $*.\n\n2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* variable.h (undefine_variable_in_set): New function declaration.\n\t(undefine_variable_global): New macro.\n\n\t* variable.c (undefine_variable_in_set): New function implementation.\n\n\t* read.c (vmodifiers): Add undefine_v modifier.\n\t(parse_var_assignment): Parse undefine.\n\t(do_undefine): Handle the undefine directive.\n\t(eval): Call do_undefine if undefine_v is set.\n\n\t* main.c (.FEATURES): Add a keyword to indicate the new feature.\n\n\t* doc/make.texi (Undefine Directive): Describe the new directive.\n\n\t* NEWS: Add a note about the new directive.\n\n2009-10-05  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* implicit.c (pattern_search): Initialize file variables only\n\tif we need to parse a rule that requires the second expansion.\n\n2009-10-03  Paul Smith  <psmith@gnu.org>\n\n\t* make.h: Include <alloca.h> even on systems where __GNUC__ is\n\tdefined.  Not sure why it was done the other way.\n\tRequested by David Boyce <dsb@boyski.com>.\n\n2009-09-30  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* dep.h (dep): Add the DONTCARE bitfield.\n\n\t* filedef.h (file):Add the NO_DIAG bitfield.\n\n        * read.c (eval_makefile): Set the DONTCARE flag in struct dep,\n\tnot struct file (a file can be a dependency of many targets,\n\tsome don't care, some do).\n\n\t* remake.c (update_goal_chain): Propagate DONTCARE from struct\n\tdep to struct file before updating the goal and restore it\n\tafterwards.\n\t(update_file): Don't prune the dependency graph if this target\n\thas failed but the diagnostics hasn't been issued.\n\t(complain): Scan the file's dependency graph to find the file\n\tthat caused the failure.\n\t(update_file_1): Use NO_DIAG instead of DONTCARE to decide\n\twhether to print diagnostics.\n\n\tFixes Savannah bugs #15110, #25493, #12686, and #17740.\n\n2009-09-28  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Pattern Intro): Move the match algorithm\n\tdiscussion into the \"Pattern Match\" node.\n\t(Pattern Match): Expand on the pattern rule matching algorithm.\n\n2009-09-28  Andreas Buening  <andreas.buening@nexgo.de>\n\n\t* job.c (construct_command_argv_internal) [OS2]: Don't eat too\n\tmuch of the command line on a single pass.\n\n2009-09-28  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* varible.c (create_pattern_var): Insert variables into the\n\tPATTERN_VARS list in the shortest patterns first order.\n\n\t* implicit.c (tryrule): Add STEMLEN and ORDER members. These are\n\tused to sort the rules.\n\t(stemlen_compare): Compare two tryrule elements.\n\t(pattern_search): Sort the rules so that they are in the shortest\n\tstem first order.\n\n\t* main.c (.FEATURES): Add a keyword to indicate the new behavior.\n\n\t* doc/make.texi (Pattern-specific Variable Values): Describe the\n\tnew pattern-specific variables application order.\n\t(Introduction to Pattern Rules): Describe the new pattern rules\n\tsearch order.\n\n\t* NEWS: Add a note about the new behavior.\n\n2009-09-27  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Double-Colon): Mention that pattern rules with\n\tdouble-colons have a different meaning.  Savannah bug #27497.\n\n2009-09-27  Juan Manuel Guerrero  <juan.guerrero@gmx.de>\n\n\t* configh.dos.template: Remove unconditional definition of\n\tSYS_SIGLIST_DECLARED.\n\tInclude <sys/version.h> because ports of GCC 4.3.0 and later no\n\tlonger include it, so macros like __DJGPP_MINOR__ are no longer\n\tdefined automatically.\n\n\t* Makefile.DOS.template (INCLUDES): Use $(prefix) and the\n\tcorresponding variables to define LIBDIR, INCLUDEDIR and LOCALEDIR\n\tinstead of using the hardcoded ones.\n\t(SUBDIRS): doc subdir added.\n\t(INFO_DEPS, DVIS): Values changed to 'make.info' and 'make.dvi'.\n\t(TEXI2HTML, TEXI2HTML_FLAGS): Removed.  Use makeinfo --html to\n\tcreate html formated docs.  texi2html may not be ported to DOS.\n\t(make.info, make.dvi, make.ps, make.html): Make targets depend on\n\t'make.texi'.\n\t(.texi.info, .texi, .texi.dvi): Now invoked recursively.  Change\n\t-I switch to look in ./ instead of ./doc.\n\t(html): Target depend on html-recursive instead of make_1.html.\n\t(make_1.html): Removed.\n\t(mostlyclean-aminfo): Use $(srcdir)/doc instead of ./ as prefix.\n\t(all-recursive): Allow for more than one subdir in the build\n\tprocess.\n\t(mostlyclean-recursive, clean-recursive, distclean-recursive)\n\t(maintainer-clean-recursive, check-recursive): Enter in doc/ too.\n\t(tags-recursive): Allow for more than one subdir in the build\n\tprocess.\n\t(info-recursive, dvi-recursive, ps-recursive, html-recursive): New\n\ttargets.  Enter into doc/ to produce the targets.\n\t(all-am): $(INFO_DEPS) replaced by info.\n\n2009-09-26  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (record_files): Use free_ns() to free struct nameseq.\n\t(eval): Ditto.\n\n\t* rule.c (freerule): Use free_dep_chain().\n\n\t* read.c (record_files): Free FILENAMES chain for implicit rules.\n\t(eval): Static pattern targets go into the string cache.\n\n\t* function.c (string_glob): Free NAME in the nameseq chain.\n\n2009-09-25  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* implicit.c (pattern_search): Terminate early if we haven't\n\tfound any rules to try (performance improvement).\n\n2009-09-25  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* implicit.c (pattern_search): Merge three parallel arrays,\n\tTRYRULES, MATCHES, and CHECKED_LASTSLASH, into one array\n\tof struct TRYRULE. In the old version the latter two arrays\n\thad insufficient length.\n\n2009-09-24  Paul Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Add back support for order-only\n\tprerequisites for secondary expansion implicit rules, that were\n\taccidentally dropped.  If we find a \"|\", enable order-only mode\n\tand set IGNORE_MTIME on all deps that are seen afterward.\n\t(pattern_search): Fix memory leaks: for intermediate files where\n\twe've already set the file variable and pattern variable sets, be\n\tsure to either save or free them as appropriate.\n\n2009-09-23  Paul Smith  <psmith@gnu.org>\n\n\tRework the way secondary expansion is stored, for efficiency.\n\tThis changes secondary expansion so that ONLY WHEN we know we have\n\ta possibility of needing secondary expansion, do we defer the\n\tsecondary expansion.  This means more parsing the deps but we use\n\ta lot less memory (due to the strcache).  Also, this fixes\n\tSavannah bug #18622.\n\n\t* read.c (eval): Don't parse the dep string here anymore.\n\t(record_files): Take the dep argument as an unparsed string.  If\n\tsecondary expansion is enabled AND the prereq string has a '$' in\n\tit, then set NEED_2ND_EXPANSION and keep the entire string.\n\tOtherwise, parse the dep string here to construct the dep list\n\twith the names in the strcache.\n\n\t* misc.c (copy_dep_chain): For NEED_2ND_EXPANSION, we need to\n\tduplicate the name string (others are in the strcache).\n\n\t* implicit.c: Remove struct idep and free_idep_chain(): unused.\n\t(struct patdeps): New structure to store prereq information.\n\t(pattern_search): Use the NEED_2ND_EXPANSION flag to determine\n\twhich prerequisites need expansion, and expand only those.\n\n\t* file.c (split_prereqs): Break parse_prereqs() into two parts: this\n\tand enter_prereqs().  split_prereqs() takes a fully-expanded string\n\tand splits it into a DEP list, handling order-only prereqs.\n\t(enter_prereqs): This function enters a list of DEPs into the file\n\tdatabase.  If there's a stem defined, expand any pattern chars.\n\t(expand_deps): Only try to expand DEPs which have NEED_2ND_EXPANSION\n\tset.  Use the above functions.\n\t(snap_deps): Only perform second expansion on prereqs that need it,\n\tas defined by the NEED_2ND_EXPANSION flag.\n\t(print_prereqs): New function to print the prereqs\n\t(print_file): Call print_prereqs() rather than print inline.\n\n\t* hash.h (STRING_COMPARE): Take advantage of strcache() by\n\tcomparing pointers.\n\t(STRING_N_COMPARE): Ditto.\n\t(ISTRING_COMPARE): Ditto.\n\n\t* dep.h (PARSE_FILE_SEQ): New macro to reduce casts.\n\t(parse_file_seq): Return void*\n\t* read.c (parse_file_seq): Return void*.\n\t(eval): Invoke macroized version of parse_file_seq()\n\t* default.c (set_default_suffixes): Ditto.\n\t* file.c (split_prereqs): Ditto.\n\t* function.c (string_glob): Ditto.\n\t* main.c (main): Ditto.\n\t* rule.c (install_pattern_rule): Ditto.\n\n\t* filedef.h: Add split_prereqs(), enter_prereqs(), etc.\n\n2009-09-16  Paul Smith  <psmith@gnu.org>\n\n\t* misc.c (alloc_dep, free_dep): Now that we have xcalloc(),\n\tconvert to macros.\n\t* dep.h: Create alloc_dep() / free_dep() macros.\n\n\t* implicit.c (pattern_search): Take advantage of the new\n\tparse_file_seq() to add the directory prefix to each prereq.\n\n\t* dep.h: Remove multi_glob() and enhance parse_file_seq() to do it\n\tall.  Avoid reversing chains.  Support adding prefixes.\n\t* read.c (parse_file_seq): Rewrite to support globbing.  Allow for\n\tcached/non-cached results.\n\t(eval): Remove multi_glob() & invoke new parse_file_seq().\n\t* rule.c (install_pattern_rule): Ditto.\n\t* main.c (main): Ditto.\n\t* implicit.c (pattern_search): Ditto.\n\t* function.c (string_glob): Ditto.\n\t* file.c (parse_prereqs): Ditto.\n\t* default.c (set_default_suffixes): Ditto.\n\n\t* variable.c (parse_variable_definition): Don't run off the end of\n\tthe string if it ends in whitespace (found with valgrind).\n\n\t* commands.c (set_file_variables): Keep space for all targets in\n\t$? if -B is given (found with valgrind).\n\n2009-09-15  Paul Smith  <psmith@gnu.org>\n\n\t* misc.c (concat): Make concat() variadic so it takes >3 arguments.\n\t(xcalloc): Add new function.\n\t* make.h: New declarations.\n\n\t* ar.c (ar_glob_match): New calling method for concat().\n\t* main.c (main): Ditto.\n\t(decode_env_switches): Ditto.\n\t* read.c (eval_makefile): Ditto.\n\t(tilde_expand): Ditto.\n\t(parse_file_seq): Ditto.\n\t* variable.c (target_environment): Ditto.\n\t(sync_Path_environment): Ditto.\n\n\t* ar.c (ar_glob_match): Use xcalloc().\n\t* dir.c (file_impossible): Ditto.\n\t* file.c (enter_file): Ditto.\n\t* job.c (new_job): Ditto.\n\t* read.c (parse_file_seq): Ditto.\n\t* vmsfunctions.c (opendir): Ditto.\n\n2009-09-14  Rafi Einstein  <rafi.einstein@gmail.com>  (tiny patch)\n\n\t* w32/subproc/sub_proc.c (process_begin): Check *ep non-NULL\n\tinside the loop that looks up environment for PATH.\n\n2009-08-31  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (windows32_openpipe): Update envp after calling\n\tsync_Path_environment.\n\n2009-08-02  Paul Smith  <psmith@gnu.org>\n\n\t* remake.c (notice_finished_file): Ensure file->cmds is not null\n\tbefore looping through them.  Fixes Savannah bug #21824.\n\n\t* doc/make.texi (Wildcard Examples): Clarify when objects is\n\twildcard-expanded.  Fixes Savannah bug #24509.  Patch by Martin Dorey.\n\t(Include): Clarify the behavior of -include.\n\tFixes Savannah bug #18963.\n\n2009-08-01  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Catalogue of Rules): Clarify where -c, -F,\n\tetc. come on the command line.  Fixes Savannah bug #27093.\n\n\t* expand.c (expand_argument): If the argument is large enough use\n\txmalloc() instead of alloca().  Fixes Savannah bug #27143.\n\n\t* variable.c (do_variable_definition): Avoid using alloca() to\n\thold values, which can be large.  Fixes Savannah bug #23960.\n\n\t* job.c (new_job): Use memmove() instead of strcpy() since both\n\tpointers are in the same memory block.  Fixes Savannah bug #27148.\n\tPatch by Petr Machata.\n\n2009-07-29  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>\n\n        * job.c (construct_command_argv_internal): Add \"ulimit\" and\n        \"unset\" to the sh_cmds for Unixy shells.\n\n2009-07-29  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>\n\n        * configure.in: Move side-effects outside AC_CACHE_VAL arguments\n        that set make_cv_sys_gnu_glob, so they are also correctly set\n        when the cache has been populated before.\n\n2009-07-04  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (func_realpath) [!HAVE_REALPATH]: Require the file to\n\texist, as realpath(3) does where it's supported.\n\n2006-07-04  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (IS_ABSOLUTE, ROOT_LEN): New macros.\n\t(abspath): Support systems that define HAVE_DOS_PATHS (have\n\tdrive letters in their file names).  Use IS_PATHSEP instead of a\n\tliteral '/' comparison.  Fixes Savannah bug #26886.\n\n2009-06-14  Paul Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file_1): Remember the original file we marked\n\tas updating, so we can clear that flag again.  If we find a target\n\tvia vpath, FILE might change.\n\t(check_dep): Ditto.  Fixes Savannah bug #13529.\n\tPatch by Reid Madsen <reid.madsen@tek.com>.\n\n2009-06-13  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (MAKEFILES Variable): Be explicit that files\n\tincluded by MAKEFILES cannot give default goals.\n\t* read.c (eval): If set_default is not set, pass the no-default-goal\n\tvalue when we read included makefiles.  Fixes Savannah bug #13401.\n\n\t* ar.c (ar_name): Ensure that targets with empty parens aren't\n\tconsidered archive member references: archive members must have a\n\tnon-empty \"member\" string.  Fixes Savannah bug #18435.\n\n\t* function.c (string_glob): Rely on multi_glob() to determine\n\twhether files exist or not.  Remove call to file_exists_p() which\n\tis not always correct.  Fixes Savannah bug #21231.\n\t* read.c (multi_glob): Add a new argument EXISTS_ONLY; if true\n\tthen only files that really exist will be returned.\n\t* dep.h: Add new argument to multi_glob().\n\t* rule.c (install_pattern_rule): Ditto.\n\t* read.c (eval): Ditto.\n\t* main.c (main): Ditto.\n\t* implicit.c (pattern_search): Ditto.\n\t* file.c (parse_prereqs): Ditto.\n\t* default.c (set_default_suffixes): Ditto.\n\n2009-06-09  Paul Smith  <psmith@gnu.org>\n\n\t* commands.c (set_file_variables): If always_make_flag is set,\n\talways add the prereq to $?.  Fixes Savannah bug #17825.\n\n\t* remake.c (update_file_1): When rebuilding deps of FILE, also try\n\tto rebuild the deps of all the also_make targets for that file.\n\tFixes Savannah bug #19108.\n\n\t* implicit.c (pattern_search): Undo test for is_target, added by\n\tBorisK on 21 Sep 2004.  This goes against step 5c in the \"Implicit\n\tRule Search Algorithm\".  Fixes Savannah bug #17752.\n\n\t* main.c (clean_jobserver): Clear the jobserver_fds options and\n\tset job_slots to the default when we clean up.\n\t(define_makeflags): Return the new MAKEFLAGS value.\n\t(main): Reset MAKEFLAGS in the environment when we re-exec.\n\tFixes Savannah bug #18124.\n\n2009-06-08  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Collapse continuations post-semicolon on target-\n\tspecific variables.  Fixes Savannah bug #17521.\n\n2009-06-07  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (reap_children): For older systems without waitpid() (are\n\tthere any of these left?) run wait(2) inside EINTRLOOP to handle\n\tEINTR errors.  Fixes Savannah bug #16401.\n\n\t* (various): Debug message cleanup.  Fixes Savannah bug #16469.\n\n\t* main.c: Fix bsd_signal() typedef.  Fixes Savannah bug #16473.\n\n\t* file.c (snap_deps): Set SNAPPED_DEPS at the start of snapping,\n\tnot the end, to catch second expansion $(eval ...) defining new\n\ttarget/prereq relationships during snap_deps.\n\tFixes Savannah bug #24622.\n\n\t* read.c (record_files): The second-expansion \"f->updating\" hack\n\twas not completely correct: if assumed that the target with\n\tcommands always had prerequisites; if one didn't then the ordering\n\twas messed up.  Fixed for now to use f->updating to decide whether\n\tto preserve the last element in the deps list... but this whole\n\tarea of constructing and reversing the deps list is too confusing\n\tand needs to be reworked.  Fixes Savannah bug #21198.\n\n2009-06-06  Paul Smith  <psmith@gnu.org>\n\n\t* hash.c (hash_insert): Remove useless test for NULL.\n\tFixes Savannah bug #21823.\n\n\t* make.h: Move SET_STACK_SIZE determination to make.h.\n\t* main.c (main): New global variable, STACK_LIMIT, holds the\n\toriginal stack limit when make was started.\n\t* job.c (start_job_command): Reset the stack limit, if we changed it.\n\tFixes Savannah bug #22010.\n\n\t* remake.c (check_dep): Only set the target's state to not-started\n\tif it's not already running.  Found this while testing -j10 builds\n\tof glibc: various targets were being rebuilt multiple times.\n\tFix from Knut St. Osmundsen; fixes a problem reported in Savannah\n\tbug #15919.\n\n\t* read.c (multi_glob): Don't pass GLOB_NOCHECK to glob(3); instead\n\thandle the GLOB_NOMATCH error.  This is to work around Sourceware.org\n\tBugzilla bug 10246.\n\n2009-06-04  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Skip initial whitespace (ffeed, vtab, etc.)\n\n\t* maintMakefile: Modify access of config and gnulib Savannah\n\tmodules to use GIT instead of CVS.\n\n\t* main.c (main): Initialize the LENGTH field in SHELL_VAR.\n\tFixes Savannah bug #24655.\n\n\t* read.c (eval_buffer): Don't dereference reading_file if it's NULL;\n\tthis can happen during some invocations of $(eval ...) for example.\n\tFixes Savannah bug #24588.  Patch by Lars Jessen <ljessen@ljessen.dk>\n\n2009-06-02  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Check for fileno()\n\t* read.c (eval_makefile): If fileno() is available, set CLOSE_ON_EXEC\n\tfor the makefile file so invocations of $(shell ...) don't inherit it.\n\tFixes Savannah bug #24277.\n\n2009-06-01  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): The previous fix for .DEFAULT_GOAL had issues;\n\texpansion was handled incorrectly.  Rework the default goal\n\thandling to save the variable only.  Remove default_goal_file and\n\tdefault_goal_name.\n\t* read.c (eval): Check default_goal_var, not default_goal_name.\n\t* read.c (record_target_var): Don't check default_goal_file here.\n\n2009-05-31  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (main): Expand the .DEFAULT_GOAL variable before using\n\tit, and if the multi_glob() returns nothing (say it expanded to\n\tnothing but spaces) then don't crash.  Fixes Savannah bug #25697.\n\n\t* doc/make.texi (Quick Reference): Add $(if ..), $(or ..), and\n\t$(and ..) to the reference.  Fixes Savannah bug #25694.\n\n\t* make.1: Be clear that some recipes will be executed even with -n.\n\t* doc/make.texi: Ditto.  Fixes Savannah bug #25460.\n\n\t* doc/make.texi (Override Directive): Make more clear how\n\toverrides and appends interact.\n\tElucidates part of Savannah bug #26207.\n\n\t* read.c (record_target_var): Don't reset the origin on\n\ttarget-specific variables; try_variable_definition() will handle\n\tthis correctly.  Fixes Savannah bug #26207.\n\n\t* maintMakefile (do-po-update): Copy PO files into $(top_srcdir).\n\tFixes Savannah bug #25712.\n\n\t* implicit.c (pattern_search): Keep a pointer to the beginning of\n\tthe filename and save that instead of the constructed pointer.\n\tFixes Savannah bug #26593.\n\tPatch by Mark Seaborn <mrs@mythic-beasts.com>\n\n2009-05-30  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Multi-Line): Add a description of the new abilities\n\tof define/endef.  Rename \"Sequences\" to \"Multi-Line\" and fix some\n\t\"command sequence\" vs. \"recipe\" syntax.\n\t* read.c (do_define): Modify to allow assignment tokens (=, :=, etc.)\n\tafter a define, to create variables with those flavors.\n\n2009-05-25  Paul Smith  <psmith@gnu.org>\n\n\tReworked the parser for variable assignments to allow multiple\n\tmodifiers, and in any order.  Also allows variable and\n\tprerequisites to be modifier names ('export', 'private', etc.)\n\n\t* NEWS: Add notes about user-visible changes.\n\n\t* read.c (struct vmodifiers): Remember what modifiers were seen.\n\t(parse_var_assignment): New function to parse variable assignments.\n\t(eval): Call the new function.  Handle variable assignments earlier.\n\n\t* variable.c (parse_variable_definition): Only parse; don't create var.\n\t(assign_variable_definition): Call parse, then create the var.\n\n2009-05-24  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi: Fix the ISBN for the GNU make manual.  Incorrect\n\tvalue noticed by Hans Stol <hans.stol@nc3a.nato.int>.\n\n2009-03-14  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/pathstuff.c (convert_Path_to_windows32): Fix last change.\n\tFixes Savannah bug #25412.\n\n\t* w32/subproc/sub_proc.c <top level>: Update Copyright years.  Add\n\tprototype for xmalloc.\n\t(find_file): Accept 3 arguments PATH_VAR, FULL_FNAME, and FULL_LEN\n\tinstead of an LPOFSTRUCT pointer.  Use xmalloc instead of malloc.\n\tLoop over an array of extensions, instead of duplicating the same\n\tcode inline.  Use SearchPath followed by CreateFile, instead of\n\tthe obsolete OpenFile.  Fixes Savannah bug #17277.\n\t(process_begin): Find $(PATH) in `envp', and pass a pointer to it\n\tto `find_file'.  Fixes Savannah bug #25662.\n\n2009-03-07  Eli Zaretskii  <eliz@gnu.org>\n\n\t* function.c (func_shell): Don't close pipedes[1] if it is -1.\n\tFixes Savannah bug #20495.\n\n2009-02-28  Ralf Wildenhues  <address@hidden>\n\n        * doc/make.texi (Instead of Execution): Document interaction of\n        -t with phony targets.\n\n2009-02-23  Ramon Garcia  <ramon.garcia.f@gmail.com>\n\n\tIntroduce a new keyword \"private\" which applies to target-specific\n\tvariables and prevents their values from being inherited.\n\n\t* variable.h (struct variable): Add private_var flag to each variable.\n\tAdd a flag to specify which list entry switches to the parent target.\n\t* variable.c (define_variable_in_set): Initialize private_var flag.\n\t(lookup_variable): Skip private variables in parent contexts.\n\t(initialize_file_variables): Set next_is_parent appropriately.\n\t(print_variable): Show the private_var flag.\n\t* read.c (eval): Recognize the private keyword.\n\t(record_target_var): Set private_var.\n\t* doc/make.texi (Suppressing Inheritance): Add documentation.\n\n2008-10-26  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Check for strndup().\n\t* misc.c (xstrndup): Rename savestring to xstrndup.  Use strndup\n\tif it's available.\n\t* make.h: Rename savestring to xstrndup.\n\t* commands.c (chop_commands): Ditto.\n\t* function.c (func_foreach): Ditto.\n\t* read.c (eval, record_files): Ditto.\n\t* variable.c (define_variable_in_set): Ditto.\n\n2008-09-30  Eli Zaretskii  <eliz@gnu.org>\n\n\t* build_w32.bat (GCCBuild): Use \"-gdwarf-2 -g3\" instead of\n\t\"-gstabs+ -ggdb3\".\n\n\t* w32/subproc/build.bat (GCCBuild): Likewise.\n\n2008-09-30  David Russo  <d-russo@ti.com>  (tiny change)\n\n\t* job.c (construct_command_argv_internal): Avoid extra backslash\n\tin batch-mode Unixy shells.  Under DB_JOBS, display the contents\n\tof the batch file.\n\n2008-05-31  Eli Zaretskii  <eliz@gnu.org>\n\n\t* README.W32.template: Remove obsolete text about non-support for\n\t-jN without Unixy shell.  Remove obsolete text about not supplying\n\tVisual Studio project files (we do supply them).  Modify text to\n\tprefer GCC builds to MSC builds.\n\n2008-04-02  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>\n\n\t* doc/make.texi (Empty Targets): Fix typo.\n\n2008-03-27  Paul Smith  <psmith@gnu.org>\n\n\tFix Savannah bug #22379:\n\t* ar.c (ar_glob_match): Zero the allocated structure.\n\t* read.c (parse_file_seq): Ditto.\n\n2008-03-08  Brian Dessent  <brian@dessent.net>\n\n\t* maintMakefile: Update Translation Project location.\n\n2008-01-26  Eli Zaretskii  <eliz@gnu.org>\n\n\t* variable.c (target_environment): Don't use shell_var if its\n\t`value' field is NULL.\n\n2007-12-22  Eli Zaretskii  <eliz@gnu.org>\n\n\tSuggested by Juan Manuel Guerrero <juan.guerrero@gmx.de>:\n\n\t* Makefile.DOS.template (info_TEXINFOS): Remove unused variable.\n\t(TEXINFOS): Value changed to `doc/make.texi'.\n\t(.SUFFIXES): Use .texi instead of .texinfo.\n\t(make.info, make.dvi): Depend on doc/make.texi.\n\t(.texi.info): New target, instead of \".texinfo.info\".  Change -I\n\tswitch to $(MAKEINFO) to look in doc/.  Use --no-split.\n\t(.texi): New target, instead of \".texinfo\".  Change -I switch to\n\t$(MAKEINFO) to look in doc/.  Use --no-split.\n\t(.texi.dvi): New target, instead of \".texinfo.dvi\".  Change -I\n\tswitch to $(MAKEINFO) to look in doc/.\n\t(install-info-am, uninstall-info): Don't look for \"*.i[0-9]\" and\n\t\"*.i[0-9][0-9]\" (due to --no-split above).\n\t(noinst_TEXINFOS, TEXI2HTML, TEXI2HTML_FLAGS): New variables.\n\t(html, make_1.html): New targets.\n\t(.PHONY): Add \"html\".\n\t(.SUFFIXES): Add .html.\n\n2007-12-22  Juan Manuel Guerrero  <juan.guerrero@gmx.de>  (tiny change)\n\n\t* configh.dos.template [__DJGPP__]: Replace HAVE_SYS_SIGLIST with\n\tHAVE_DECL_SYS_SIGLIST.\n\n\t* job.c (child_execute_job): Remove __MSDOS__ because MSDOS/DJGPP\n\tbuild does not use child_execute_job.\n\n\t* variable.c (define_automatic_variables) [__MSDOS__]: Always\n\texport the SHELL environment variable to the child.\n\n2007-12-22  Eli Zaretskii  <eliz@gnu.org>\n\n\t* config.h.W32: Include sys/types.h.\n\t[!_PID_T_] (pid_t): Define only if not already defined by sys/types.h.\n\n\t* vpath.c (construct_vpath_list) [HAVE_DOS_PATHS]: Support VPATH\n\tvalues that use `:' in drive letters, when PATH_SEPARATOR_CHAR is\n\talso `:'.\n\n2007-11-04  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi: Convert references to \"commands\", \"command\n\tlines\", and \"command script\" to \"recipe\".\n\t* NEWS: Ditto.\n\t* commands.c, file.c, job.c, remake.c, read.c, variable.c, main.c:\n\tDitto.\n\n2007-10-27  Bruno Haible  <bruno@clisp.org>\n\n\t* remake.c (f_mtime): Print time difference values between 100 and\n\tULONG_MAX in fixed-point notation rather than in exponention notation.\n\n2007-10-12  Eli Zaretskii  <eliz@gnu.org>\n\n\t* variable.c (do_variable_definition): Allow $(SHELL) to expand to\n\ta more complex value than a simple shell: if it's not a default\n\tshell now then expand it and see if is a default shell then.\n\n2007-10-10  Eli Zaretskii  <eliz@gnu.org>\n\n\t* dir.c (find_directory) [WINDOWS32]: Remove trailing slashes from\n\tpathnames, with const strings.\n\t* build_w32.bat [WINDOWS32]: If no config.h.W32 exists, create one\n\tfrom the template (used for building from CVS, not a dist).\n\n2007-10-10  Paul Smith  <psmith@gnu.org>\n\n\t* make.h: Add a prototype for w32_kill() (change suggested by\n\tYongwei Wu <wuyongwei@gmail.com>).\n\n2007-09-21  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/pathstuff.c (convert_Path_to_windows32): Handle quoted\n\tdirectories in Path.\n\n2007-09-12  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi: Applied wording cleanups from Savannah patch #6195.\n\tProvided by Diego Biurrun <diego@biurrun.de>\n\t(Complex Makefile): Remove .PHONY setting for tar: patch #6196.\n\tProvided by Diego Biurrun <diego@biurrun.de>\n\n2007-09-11  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Special Variables): Moved this into the \"How to\n\tUse Variables\" chapter.  Added a table entry for .RECIPEPREFIX.\n\t(MAKEFILE_LIST) No longer a section; this was added into the\n\t\"Special Variables\" section.\n\t(Rule Introduction): Reference .RECIPEPREFIX.\n\t(Simple Makefile): Ditto.\n\t(Rule Syntax): Ditto.\n\t(Command Syntax): Ditto.\n\t(Error Messages): Ditto.\n\n2007-09-10  Paul Smith  <psmith@gnu.org>\n\n\t* commands.c (print_commands): Don't print an extra line in the\n\tcommand scripts.  Prefix the command scripts with cmd_prefix, not \\t.\n\n\t* read.c (construct_include_path): Add the full string to the cache; we\n\twere chopping the last char.\n\n\t* NEWS: Announce the .RECIPEPREFIX special variable.\n\t* variable.c (lookup_special_var): Rename from handle_special_var().\n\t(lookup_variable): Call the new name.\n\t(set_special_var): New function: handle setting of special variables.\n\tWhen setting .RECIPEPREFIX, reset the cmd_prefix global variable.\n\t(do_variable_definition): Call it.\n\t* make.h (RECIPEPREFIX_DEFAULT): Define the default command prefix char.\n\t(RECIPEPREFIX_NAME): Define the command prefix special variable name.\n\t* main.c (main): Create the .RECIPEPREFIX special variable.\n\t* read.c (eval): Remove the cmd_prefix characters from the command\n\tscripts here, so they're not stored in the commands array at all,\n\trather than waiting and stripping them out during command construction.\n\t* job.c (construct_command_argv_internal): Don't skip cmd_prefix here.\n\n2007-08-15  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (GNU Free Documentation License): The fdl.texi\n\tfile has had the section info removed, so add some to make.texi\n\tbefore we include it.\n\n2007-08-15  Icarus Sparry  <savannah@icarus.freeuk.com>\n\n\t* remake.c (check_dep): Reset the target state for intermediate\n\tfiles.  They might have been considered before but not updated\n\tthen (order-only for example) but they will be this time.\n\tFixes Savannah bug #'s 3330 and 15919.\n\n2007-07-21  Eli Zaretskii  <eliz@gnu.org>\n\n\tFix Savannah bug #20549:\n\t* function.c (func_shell): Call construct_command_argv with zero\n\tvalue of FLAGS.\n\t* job.c (construct_command_argv_internal): New argument FLAGS; all\n\tcallers changed.\n\t[WINDOWS32]: If FLAGS has the COMMANDS_RECURSE bit set, ignore\n\tjust_print_flag.\n\t* job.h (construct_command_argv_internal): Update prototype.\n\n2007-07-13  Paul Smith  <psmith@gnu.org>\n\n\t* file.c (expand_deps): Use variable_buffer as the start of the\n\tbuffer, not the original pointer (in case it was reallocated).\n\tFix suggested by Rafi Einstein <rafi.einstein@formalism-labs.com>.\n\tFixes Savannah bug #20452.\n\n2007-07-04  Paul Smith  <psmith@gnu.org>\n\n\t* (ALL FILES): Update to GPLv3.\n\t* (ALL FILES): Update copyright for 2007.\n\n\t* main.c (print_version): Move the host type info to the second line.\n\n2007-06-29  Thiemo Seufer  <ths@mips.com>\n\n\t* maintMakefile: Update Translation Project location.\n\n2007-06-13  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Reading Makefiles): \"Expansion of deferred\" ->\n\t\"Expansion of a deferred\"\n\tFixes Savannah bug #20018.\n\n\t* expand.c (variable_expand_for_file): Preserve the value of\n\treading_file rather than setting it to 0 at the end.\n\tFixes Savannah bug #20033.\n\n2007-05-11  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (new_job): Add debug info to specify where make found the\n\tcommand script it is running to build a target.\n\tFixes Savannah bug #18617.\n\n\t* default.c (default_suffixes,default_suffix_rules,default_variables):\n\tAdd support for Objective C.  Fixes Savannah bug #16389.\n\tBased on a patch provided by Peter O'Gorman <peter@pogma.com>.\n\n\t* function.c (func_lastword): Initialize p.\n\n\t* doc/make.texi (Eval Function, Implicit Variables, Special Targets):\n\tDoc fixes noticed by Bob <twobanjobob@sbcglobal.net>.  Patch from\n\tDave Korn <dave.korn@artimi.com>\n\n2007-05-08  Paul Smith  <psmith@gnu.org>\n\n\tFix Savannah bug #19656:\n\n\t* configure.in: Check for strcasecmp(), strcmpi(), and stricmp().\n\n\t* make.h: Change all case-insensitive string compares to use\n\tstrcasecmp() (from POSIX).  If we don't have that but do have one\n\tof the others, define strcasecmp to be one of those instead.  If\n\twe don't have any, declare a prototype for our own version.\n\n\t* misc.c (strcasecmp): Use this if we can't find any native\n\tcase-insensitive string comparison function.\n\t* vmsfunctions.c: Remove strcmpi(); we'll use misc.c:strcasecmp().\n\t* main.c (find_and_set_default_shell): Use strcasecmp() instead of\n\tstrcmpi().\n\t* job.c (_is_unixy_shell, construct_command_argv_internal): Use\n\tstrcasecmp() instead of stricmp().\n\t* hash.h (ISTRING_COMPARE, return_ISTRING_COMPARE): Use strcasecmp()\n\tinstead of strcmpi().\n\t* acinclude.m4: Remove the strcasecmp() check from here.\n\n2007-03-21  Paul Smith  <psmith@gnu.org>\n\n\t* configure.in: Don't turn on case-insensitive file system support\n\tif --disable-... is given.  Fixes Savannah bug #19348.\n\n2007-03-19  Paul Smith  <psmith@gnu.org>\n\n\t* ALL: Use the strcache for all file name strings, or other\n\tstrings which we will never free.  The goal is to save memory by\n\tavoiding duplicate copies of strings.  However, at the moment this\n\tdoesn't save much memory in most situations: due to secondary\n\texpansion we actually save prerequisite lists twice (once before\n\tthe secondary expansion, and then again after it's been parsed\n\tinto individual file names in the dep list).  We will resolve this\n\tin a future change, by doing the parsing up-front for targets\n\twhere secondary expansion is not set.\n\n\tMoving things into the strcache also allows us to use const\n\tpointers in many more places.\n\n2007-01-03  Paul Smith  <psmith@gnu.org>\n\n\t* make.h (ENULLLOOP): Reset errno after each failed invocation of\n\tthe function, not just the first.  Fixes Savannah bug #18680.\n\n2006-11-18  Paul Smith  <psmith@gnu.org>\n\n\t* strcache.c (strcache_add_len): Don't allocate a new buffer\n\tunless the string is not already nil-terminated.  Technically this\n\tis a violation of the standard, since we may be passed an array\n\tthat is not long enough to test one past.  However, in make this\n\tis never true since we only use nil-terminated strings or\n\tsub-strings thereof.\n\n\t* read.c (eval, do_define): Use cmd_prefix instead of '\\t'.\n\n\t* main.c: New global cmd_prefix, defaults to '\\t'.\n\t* job.c (construct_command_argv_internal): Use cmd_prefix instead\n\tof '\\t'.\n\n\t* dir.c: Constified.\n\t(dir_contents_file_exists_p): Check for an error return\tfrom\n\treaddir(), just in case.\n\n\t* commands.c: Constified.\n\t* default.c: Constified.\n\t* expand.c: Constified.\n\t* function.c: Partial constification.\n\t* variable.c: Partial constification.\n\t* vmsify.c: Constification.  Hard to test this but I hope I didn't\n\tscrew it up!\n\t* vpath.c: Partial constification.\n\t* w32/pathstuff.c: Partial constification.\n\n2006-11-16  Eli Zaretskii  <eliz@gnu.org>\n\n\t* main.c (main) [HAVE_DOS_PATHS]: Treat DOS style argv[0] with\n\tbackslashes and drive letters as absolute.\n\n2006-10-22  Paul Smith  <psmith@gnu.org>\n\n\t* main.c (struct command_switch): Use const and void*.\n\n2006-10-21  Paul Smith  <psmith@gnu.org>\n\n\t* ar.c: Constified.\n\t* arscan.c: Constified.\n\n2006-09-30  Paul Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (MAKEFILE_LIST Variable): Modify reference to\n\tpoint to lastword since the example was updated.\n\tFixes Savannah bug #16304.\n\t(Secondary Expansion): Correct example description.\n\tFixes Savannah bug #16468.\n\t(Makefile Contents): Clarify that comments cannot appear within\n\tvariable references or function calls.\n\tFixes Savannah bug #16577.\n\t(Special Targets): Clarify how .NOTPARALLEL works in recursion.\n\tFixes Savannah bug #17701.\n\tReported by Ralf Wildenhues <Ralf.Wildenhues@gmx.de>:\n\t(Prerequisite Types): Added an example of using\torder-only\n\tprerequisites.  Fixes Savannah bug #17880.\n\t(Rule Syntax): \"lise\" -> \"list\"\n\t(Multiple Rules): ... -> @dots{}\n\t(Splitting Lines): ditto.\n\n\t* remake.c (update_file_1): Prereqs that don't exist should be\n\tconsidered changed, for the purposes of $?.\n\tFixes Savannah bug #16051.\n\n\t* make.1: Remove extraneous \"+\".\n\tFixes Savannah bug #16652.\n\n2006-09-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Include sys/types.h when checking for sys/wait.h.\n\n2006-08-18  Eli Zaretskii  <eliz@gnu.org>\n\n\t* configure.in (PATH_SEPARATOR_CHAR): Define to the value of\n\t$PATH_SEPARATOR.\n\n\t* make.h (PATH_SEPARATOR_CHAR): Define only if still undefined.\n\tNormally, it is defined in config.h.\n\n\t* config/dospaths.m4 <ac_cv_dos_paths>: Define to yes on Cygwin as\n\twell.\n\n\t* job.c (construct_command_argv_internal) [HAVE_DOS_PATHS]: Define\n\tsh_chars_sh for Windows platforms that emulate Unix.\n\n2006-05-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.OS2.template: Updates provided by Andreas Buening\n\t<andreas.buening@nexgo.de>.\n\n2006-04-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Include <direct.h> if HAVE_DIRECT_H.\n\t* config.h.W32.template (HAVE_DIRECT_H): Set it if it's available.\n\n2006-04-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.cvs: Add a reminder to notify the GNU translation robot.\n\n\t* doc/make.texi: Change @direcategory (requested by Karl Berry).\n\n2006-04-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile (po-check): Use Perl instead of grep -E, for systems\n\tthat don't have extended grep.\n\t(cvsclean): Use $(PERL) instead of perl.\n\n2006-04-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile: Add some extra warning options (GCC 4.1 only?)\n\n\t* expand.c, implicit.c, main.c, read.c: Rename variables so that\n\tinner-scope variables don't mask outer-scope variables.\n\n\t* ar.c, arscan.c, commands.c, default.c, dir.c, expand.c, file.c:\n\t* function.c, getloadavg.c, implicit.c, job.c, main.c, misc.c, read.c:\n\t* remake.c, remote-cstms.c, rule.c, strcache.c, variable.c:\n\t* vmsfunctions.c, vmsify.c, vpath.c: Remove all casts of returned\n\tvalues from memory allocation functions: they return void* and so\n\tdon't need to be cast.  Also remove (char *) casts of arguments to\n\txrealloc().\n\n\t* configure.in: Remove checks for memcpy/memmove/strchr.\n\n\t* make.h: Remove bcmp/bcopy/bzero/strchr/strrchr macros.\n\n\t* ar.c, arscan.c, commands.c, dir.c: Convert all bzero/bcopy/bcmp\n\tcalls to memset/memcpy/memmove/memcmp calls.\n\t* expand.c, file.c, function.c, getloadavg.c, implicit.c: Ditto.\n\t* job.c, main.c, misc.c, read.c, remake.c, rule.c: Ditto.\n\t* variable.c, vpath.c: Ditto.\n\n\t* make.h (EXIT_FAILURE): Should be 1, not 0.\n\n2006-04-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Removed AM_C_PROTOTYPES.  Starting now on we\n\trequire an ISO C 1989 standard compiler and runtime library.\n\n\t* Makefile.am: Remove the ansi2knr feature.\n\n\t* make.h: Remove the PARAMS() macro definition and all uses of it.\n\n\t* amiga.h, ar.c, arscan.c: Remove all uses of the PARAMS() macro.\n\t* commands.c, commands.h, config.h-vms.template: Ditto.\n\t* dep.h, dir.c, expand.c, filedef.h, function.c: Ditto.\n\t* implicit.c, job.c, job.h, main.c, read.c, remake.c: Ditto.\n\t* rule.c, rule.h, variable.h, vmsdir.h, vmsjobs.c, vpath.c: Ditto.\n\n\t* NEWS: Update.\n\n2006-04-01  Paul D. Smith  <psmith@gnu.org>\n\n\tVersion 3.81 released.\n\n\t* NEWS: Updated for 3.81.\n\n\t* README.cvs: Mention that vpath builds are not supported out of\n\tCVS.  Fixes Savannah bug #16236.\n\tRemove update of make.texi from the list of things to do; we use\n\tversion.texi now.\n\n2006-03-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* doc/make.texi: Clean up licensing.  Use @copying and version.texi\n\tsupport from automake, as described in the Texinfo manual.\n\n2006-03-25  Eli Zaretskii  <eliz@gnu.org>\n\n\t* implicit.c (pattern_search) [HAVE_DOS_PATHS]: Don't compare b\n\twith lastslash, since the latter points to filename, not to\n\ttarget.\n\t* job.c (construct_command_argv_internal) [HAVE_DOS_PATHS]:\n\tDeclare and define sh_chars_sh[].\n\n2006-03-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Look for build.sh.in in $srcdir so it will be\n\tbuilt for remote configurations as well.\n\n\t* Makefile.am: Make sure to clean up build.sh during distclean.\n\tFixes Savannah bug #16166.\n\n\t* misc.c (log_access): Takes a const char *.\n\t* function.c (fold_newlines): Takes an unsigned int *.\n\tBoth fixes for Savannah bug #16170.\n\n2006-03-22  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* implicit.c (pattern_search): Call set_file_variables only\n\tif we have prerequisites that need second expansion. Fixes\n\tSavannah bug #16140.\n\n2006-03-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file): Add alloca(0) to clean up alloca'd\n\tmemory on hosts that don't support it directly.\n\n\t* README.cvs: Add information on steps for making a release (to\n\tmake sure I don't forget any).\n\n\t* main.c (clean_jobserver): Move jobserver cleanup code into a new\n\tfunction.\n\t(die): Cleanup code was removed from here; call the new function.\n\t(main): If we are re-execing, clean up the jobserver first so we\n\tdon't leak file descriptors.\n\tReported by Craig Fithian <craig.fithian@citigroup.com>\n\n2006-03-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile (do-po-update): Rewrite this rule to clean up and\n\tallow multiple concurrent runs.\n\tPatch from Joseph Myers <joseph@codesourcery.com>\n\n2006-03-17  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* dep.h (struct dep): Add the stem field.\n\t* misc.c (alloc_dep, free_dep): New functions.\n\t(copy_dep_chain): Copy stem.\n\t(free_dep_chain): Use free_dep.\n\t* read.c (record_files): Store stem in the dependency line.\n\t* file.c (expand_deps): Use stem stored in the dependency line. Use\n\tfree_dep_chain instead of free_ns_chain.\n\t* implicit.c (pattern_search): Use alloc_dep and free_dep.\n\t* read.c (read_all_makefiles, eval_makefile, eval): Ditto.\n\t* main.c (main, handle_non_switch_argument): Ditto.\n\t* remake.c (check_dep): Ditto.\n\t* rule.c (convert_suffix_rule, freerule): Ditto.\n\n2006-03-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* expand.c (variable_append): Instead of appending everything then\n\texpanding the result, we expand (or not, if it's simple) each part\n\tas we add it.\n\t(allocated_variable_append): Don't expand the final result.\n\tFixes Savannah bug #15913.\n\n2006-03-09  Paul Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file_1): Revert the change of 3 Jan 2006 which\n\tlisted non-existent files as changed.  Turns out there's a bug in\n\tthe Linux kernel builds which means that this change causes\n\teverything to rebuild every time.  We will re-introduce this fix\n\tin the next release, to give them time to fix their build system.\n\tFixes Savannah bug #16002.\n\tIntroduces Savannah bug #16051.\n\n\t* implicit.c (pattern_search) [DOS_PATHS]: Look for DOS paths if\n\twe *don't* find UNIX \"/\".\n\tReported by David Ergo <david.ergo@alterface.com>\n\n2006-03-04  Eli Zaretskii  <eliz@gnu.org>\n\n\t* variable.c (do_variable_definition) [WINDOWS32]: Call the shell\n\tlocator function find_and_set_default_shell if SHELL came from the\n\tcommand line.\n\n2006-02-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (merge_variable_set_lists): It's legal for *setlist0\n\tto be null; don't core in that case.\n\n2006-02-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* commands.c (set_file_variables): Realloc, not malloc, the static\n\tstring values to avoid memory leaks.\n\n\t* expand.c (recursively_expand_for_file): Only set reading_file to\n\tan initialized value.\n\n\t* implicit.c (pattern_search): We need to make a copy of the stem\n\tif we get it from an intermediate dep, since those get freed.\n\n\t* file.c (lookup_file) [VMS]: Don't lowercase special targets that\n\tbegin with \".\".\n\t(enter_file) [VMS]: Ditto.\n\tPatch provided by Hartmut Becker <Hartmut.Becker@hp.com>.\n\n2006-02-24  Eli Zaretskii  <eliz@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Fix last change.\n\n\t* w32/subproc/sub_proc.c (process_pipe_io): Make dwStdin,\n        dwStdout, and dwStderr unsigned int: avoids compiler warnings in\n        the calls to _beginthreadex.\n\n\t* expand.c (recursively_expand_for_file): Initialize `save' to\n        prevent compiler warnings.\n\n2006-02-18  Eli Zaretskii  <eliz@gnu.org>\n\n        * job.c (construct_command_argv_internal): Don't create a temporary\n\tscript/batch file if we are under -n.  Call _setmode to switch the\n\tscript file stream to text mode.\n\n2006-02-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (merge_variable_set_lists): Don't try to merge the\n\tglobal_setlist.  Not only is this useless, but it can lead to\n\tcircularities in the linked list, if global_setlist->next in one\n\tlist gets set to point to another list which also ends in\n\tglobal_setlist.\n\tFixes Savannah bug #15757.\n\n2006-02-15  Paul D. Smith  <psmith@gnu.org>\n\n\tFix for Savannah bug #106.\n\n\t* expand.c (expanding_var): Keep track of which variable we're\n\texpanding.  If no variable is being expanded, it's the same as\n\treading_file.\n\t* make.h (expanding_var): Declare it.\n\t* expand.c (recursively_expand_for_file): Set expanding_var to the\n\tcurrent variable we're expanding, unless there's no file info in\n\tit (could happen if it comes from the command line or a default\n\tvariable).  Restore it before we exit.\n\t* expand.c (variable_expand_string): Use the expanding_var file\n\tinfo instead of the reading_file info.\n\t* function.c (check_numeric): Ditto.\n\t(func_word): Ditto.\n\t(func_wordlist): Ditto.\n\t(func_error): Ditto.\n\t(expand_builtin_function): Ditto.\n\t(handle_function): Ditto.\n\n2006-02-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Even if the included filenames expands to the\n\tempty string we still need to free the allocated buffer.\n\n\t* implicit.c (pattern_search): If we allocated a variable set for\n\tan impossible file, free it.\n\t* variable.c (free_variable_set): New function.\n\t* variable.h: Declare it.\n\n\t* read.c (read_all_makefiles): Makefile names are kept in the\n\tstrcache, so there's never any need to alloc/free them.\n\t(eval): Ditto.\n\n\t* main.c (main): Add \"archives\" to the .FEATURES variable if\n\tarchive support is enabled.\n\t* doc/make.texi (Special Variables): Document it.\n\n2006-02-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Add checking for DOS pathnames to\n\tthe pattern rule target LASTSLASH manipulation.\n\tFixes Savannah bug #11183.\n\n2006-02-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* (ALL FILES): Updated copyright and license notices.\n\n2006-02-10  Paul D. Smith  <psmith@gnu.org>\n\n\tA new internal capability: the string cache is a read-only cache\n\tof strings, with a hash table interface for fast lookup.  Nothing\n\tin the cache will ever be freed, so there's no need for reference\n\tcounting, etc.  This is the beginning of a full solution for\n\tSavannah bug #15182, but for now we only store makefile names here.\n\n\t* strcache.c: New file.  Implement a read-only string cache.\n\t* make.h: Add prototypes for new functions.\n\t* main.c (initialize_global_hash_tables): Initialize the string cache.\n\t(print_data_base): Print string cache stats.\n\t* read.c (eval_makefile): Use the string cache to store makefile\n\tnames.  Rewrite the string allocation to be sure we free everything.\n\n2006-02-10  Eli Zaretskii  <eliz@gnu.org>\n\n\t* dir.c (dir_contents_file_exists_p): Don't opendir if the\n\tdirectory time stamp didn't change, except on FAT filesystems.\n\tSuggested by J. David Bryan <jdbryan@acm.org>.\n\n2006-02-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_or): Implement a short-circuiting OR function.\n\t(func_and): Implement a short-circuiting AND function.\n\t(function_table_init): Update the table with the new functions.\n\t* doc/make.texi (Conditional Functions): Changed the \"if\" section\n\tto one on general conditional functions.  Added documentation for\n\t$(and ...) and $(or ...) functions.\n\t* NEWS: Note new $(and ...) and $(or ...) functions.\n\n2006-02-08  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* job.h (struct child): Add the dontcare bitfield.\n\t* job.c (new_job): Cache dontcare flag.\n\t* job.c (reap_children): Use cached dontcare flag instead of the\n\tone in struct file. Fixes Savannah bug #15641.\n\n2006-02-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* vpath.c (selective_vpath_search): If the file we find has a\n\ttimestamp from -o or -W, use that instead of the real time.\n\t* remake.c (f_mtime): If the mtime is a special token from -o or\n\t-W, don't overwrite it with the real mtime.\n\tFixes Savannah bug #15341.\n\n\tUpdates from Markus Mauhart <qwe123@chello.at>:\n\n\t* w32/subproc/sub_proc.c (process_begin): Remove no-op tests.\n\t(process_signal, process_last_err, process_exit_code): Manage\n\tinvalid handle values.\n\t(process_{outbuf,errbuf,outcnt,errcnt,pipes}): Unused and don't\n\tmanage invalid handles; remove them.\n\t* job.c (start_job_command) [WINDOWS32]: Jump out on error.\n\t* config.h.W32.template [WINDOWS32]: Set flags for Windows builds.\n\t* README.cvs: Updates for building from CVS.\n\n2006-02-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (enter_file): Keep track of the last double_colon entry,\n\tto avoid walking the list every time we want to add a new one.\n\tFixes Savannah bug #15533.\n\t* filedef.h (struct file): Add a new LAST pointer.\n\n\t* dir.c (directory_contents_hash_cmp): Don't use subtraction to do\n\tthe comparison.  For 64-bits systems the result of the subtraction\n\tmight not fit into an int.  Use comparison instead.\n\tFixes Savannah bug #15534.\n\n\t* doc/make.texi: Update the chapter on writing commands to reflect\n\tthe changes made in 3.81 for backslash/newline and SHELL handling.\n\n2006-02-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (dir_contents_file_exists_p) [WINDOWS32]: Make sure\n\tvariable st is not used when it's not initialized.\n\tPatch from Eli Zaretskii <eliz@gnu.org>.\n\n2006-01-31  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.W32.template: Applied patch #4785 from\n\tMarkus Mauhart <qwe123@chello.at>.\n\t* README.cvs: Applied patch #4786 from\n\tMarkus Mauhart <qwe123@chello.at>.\n\t* make_msvc_net2003.vcproj [WINDOWS32]: New version from\n\tJ. Grant <jg@jguk.org>.\n\n\t* main.c: Update the copyright year in the version output.\n\t* prepare_w32.bat: Remove this file from the distribution.\n\n2006-01-21  Eli Zaretskii  <eliz@gnu.org>\n\n\t* remake.c (update_goal_chain): Set g->changed instead of\n\tincrementing it, as it is only 8-bit wide, and could overflow if\n\tmany commands got started in update_file.\n\n\t* w32/include/sub_proc.h: Add a prototype for process_used_slots.\n\n\t* w32/subproc/sub_proc.c: Change dimension of proc_array[] to\n\tMAXIMUM_WAIT_OBJECTS.\n\t(process_wait_for_any_private): Change dimension of handles[]\n\tarray to MAXIMUM_WAIT_OBJECTS.\n\t(process_used_slots): New function.\n\t(process_register): Don't register more processes than the\n\tavailable number of slots.\n\t(process_easy): Don't start new processes if all slots are used\tup.\n\n\t* job.c (load_too_high, start_waiting_jobs) [WINDOWS32]: If there\n\tare already more children than sub_proc.c can handle, behave as if\n\tthe load were too high.\n\t(start_job_command): Fix a typo in error message when process_easy\n\tfails.\n\n2006-01-14  Eli Zaretskii  <eliz@gnu.org>\n\n\t* main.c (main) [WINDOWS32]: Don't refuse to run with -jN, even if\n\tthe shell is not sh.exe.\n\n\t* job.c (create_batch_file): Renamed from create_batch_filename;\n\tall callers changed.  Don't close the temporary file; return its\n\tfile descriptor instead.  New arg FD allows to return the file\n\tdescriptor.\n\t(construct_command_argv_internal): Use _fdopen instead of fopen to\n\topen the batch file.\n\n2006-01-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* readme.vms: Updates for case-insensitive VMS file systems from\n\tHartmut Becker <Hartmut.Becker@hp.com>.\n\t* dir.c (vms_hash): Ditto.\n\t* vmsify.c (copyto): Ditto.\n\t* vmsfunctions.c (readdir): Ditto.\n\n\t* make.1: Add a section on the exit codes for make.\n\n\t* doc/make.texi: A number of minor updates to the documentation.\n\n2006-01-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file_1): Mark a prerequisite changed if it\n\tdoesn't exist.\n\n\t* read.c (eval): Be sure to strip off trailing whitespace from the\n\tprerequisites list properly.  Also, initialize all fields in\n\tstruct dep when creating a new one.\n\n2005-12-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h.W32.template [WINDOWS32]: Add in some pragmas to\n\tdisable warnings for MSC.\n\tPatch by Rob Tulloh <rtulloh@yahoo.com>.\n\n2005-12-17  Eli Zaretskii  <eliz@gnu.org>\n\n\t* doc/make.texi (Execution): Add a footnote about changes in\n\thandling of backslash-newline sequences.  Mention the differences\n\ton MS-DOS and MS-Windows.\n\n\t* NEWS: More details about building the MinGW port and a pointer\n\tto README.W32.  Fix the section name that describes the new\n\tbackward-incompatible processing of backslash-newline sequences.\n\tThe special processing of SHELL set to \"cmd\" is only relevant to\n\tMS-Windows, not MS-DOS.\n\n2005-12-17  Eli Zaretskii  <eliz@gnu.org>\n\n\t* main.c (handle_runtime_exceptions): Cast exrec->ExceptionAddress\n\tto DWORD, to avoid compiler warnings.\n\t* job.c (exec_command): Cast hWaitPID and hPID to DWORD, and\n\tuse %ld in format, to avoid compiler warnings.\n\n\t* doc/make.texi (Special Targets): Fix a typo.\n\t(Appending): Fix cross-reference to Setting.\n\t(Special Variables, Secondary Expansion, File Name Functions)\n\t(Flavor Function, Pattern Match, Quick Reference): Ensure two\n\tperiods after a sentence.\n\t(Execution): Add @: after \"e.g.\".\n\t(Environment): Fix punctuation.\n\t(Target-specific, Call Function, Quick Reference): Add @: after \"etc.\"\n\t(Shell Function, Target-specific): Add @: after \"vs.\"\n\n2005-12-14  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (record_target_var): Initialize variable's export field\n\twith v_default instead of leaving it \"initialized\" by whatever\n\tgarbage happened to be on the heap.\n\n2005-12-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.1: Fix some display errors and document all existing options.\n\tPatch by Mike Frysinger <vapier@gentoo.org>.\n\n2005-12-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): If 2nd expansion is not set for\n\tthis implicit rule, replace the pattern with the stem directly,\n\tand don't re-expand the variable list.  Along with the other\n\t.SECONDEXPANSION changes below, fixes bug #13781.\n\n2005-12-09  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* implicit.c (pattern_search): Mark other files that this rule\n\tbuilds as targets so that they are not treated as intermediates\n\tby the pattern rule search algorithm. Fixes bug #13022.\n\n2005-12-07  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* remake.c (notice_finished_file): Propagate the change of\n\tmodification time to all the double-colon entries only if\n\tit is the last one to be updated. Fixes bug #14334.\n\n2005-11-17  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* function.c (func_flavor): Implement the flavor function which\n\treturns the flavor of a variable.\n\t* doc/make.texi (Functions for Transforming Text): Document it.\n\t* NEWS: Add it to the list of new functions.\n\n2005-11-14  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (construct_include_path): Set the .INCLUDE_DIRS special\n\tvariable.\n\t* doc/make.texi (Special Variables): Document .INCLUDE_DIRS.\n\t* NEWS: Add .INCLUDE_DIRS to the list of new special variables.\n\n2005-10-26  Paul Smith  <psmith@gnu.org>\n\n\t* read.c (record_files): Don't set deps flags if there are no deps.\n\t* maintMakefile: We only need to build the templates when we are\n\tcreating a distribution, so don't do it for \"all\".\n\n2005-10-24  Paul D. Smith  <psmith@gnu.org>\n\n\tMake secondary expansion optional: its enabled by declaring the\n\tspecial target .SECONDEXPANSION.\n\n\t* NEWS: Update information on second expansion capabilities.\n\t* doc/make.texi (Secondary Expansion): Document the\n\t.SECONDEXPANSION special target and its behavior.\n\t* dep.h (struct dep): Add a flag STATICPATTERN, set to true if the\n\tprerequisite list was found in a static pattern rule.\n\t(free_dep_chain): Declare a prototype.\n\t* file.c (parse_prereqs): New function: break out some complexity\n\tfrom expand_deps().\n\t(expand_deps): If we aren't doing second expansion, replace % with\n\tthe stem for static pattern rules.  Call the new function.\n\t* filedef.h (parse_prereqs): Declare a prototype.\n\t* implicit.c (pattern_search): Initialize the new staticpattern\n\tfield.\n\t* main.c (second_expansion): Declare a global variable to remember\n\tif the special target has been seen.  Initialize the new\n\tstaticpattern field for prerequisites.\n\t* make.h: Extern for second_expansion.\n\t* misc.c (free_dep_chain): New function: frees a struct dep list.\n\t* read.c (read_all_makefiles): Initialize the staticpattern field.\n\t(eval_makefile): Ditto.\n\t(record_files): Check for the .SECONDEXPANSION target and set\n\tsecond_expansion global if it's found.\n\tUse the new free_dep_chain() instead of doing it by hand.\n\tSet the staticpattern field for prereqs of static pattern targets.\n\n2005-10-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Set CURDIR to be a file variable instead of a\n\tdefault, so that values of CURDIR inherited from the environment\n\twon't override the make value.\n\n2005-09-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): If the line is empty\n\tremember to free the temporary argv strings.\n\tFixes bug # 14527.\n\n2005-09-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): The noerror flag is a boolean (single\n\tbit); set it appropriately.\n\tReported by Mark Eichin <eichin@metacarta.com>\n\n2005-08-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_error): On Windows, output from $(info ...)\n\tseems to come in the wrong order.  Try to force it with fflush().\n\n2005-08-10  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (record_files): Move code that sets stem for static\n\tpattern rules out of the if (!two_colon) condition so it is\n\talso executed for two-colon rules. Fixes Savannah bug #13881.\n\n2005-08-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Don't test that __STDC__ is non-0.  Some compilers\n\t(Windows for example) set it to 0 to denote \"ISO C + extensions\".\n\tFixes bug # 13594.\n\n2005-08-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* w32/pathstuff.c (getcwd_fs): Fix warning about assignment in a\n\tconditional (slightly different version of a fix from Eli).\n\n\tFix a bug reported by Michael Matz <matz@suse.de>: patch included.\n\tIf make is running in parallel without -k and two jobs die in a\n\trow, but not too close to each other, then make will quit without\n\twaiting for the rest of the jobs to die.\n\n\t* main.c (die): Don't reset err before calling reap_children() the\n\tsecond time: we still want it to be in the error condition.\n\t* job.c (reap_children): Use a static variable, rather than err,\n\tto control whether or not the error message should be printed.\n\n2005-08-06  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/sub_proc.c: Include signal.h.\n\t(process_pipe_io, process_file_io): Pass a pointer to a local\n\tDWORD variable to GetExitCodeProcess.  If the exit code is\n\tCONTROL_C_EXIT, put SIGINT into pproc->signal.\n\n\t* job.c [WINDOWS32]: Include windows.h.\n\t(main_thread) [WINDOWS32]: New global variable.\n\t(reap_children) [WINDOWS32]: Get the handle for the main thread\n\tand store it in main_thread.\n\n\t* commands.c [WINDOWS32]: Include windows.h and w32err.h.\n\t(fatal_error_signal) [WINDOWS32]: Suspend the main thread before\n\tdoing anything else.  When we are done, close the main thread\n\thandle and exit with status 130.\n\n2005-07-30  Eli Zaretskii  <eliz@gnu.org>\n\n\t* w32/subproc/sub_proc.c (process_begin): Don't pass a NULL\n\tpointer to fprintf.\n\n\t* main.c (find_and_set_default_shell): If found a DOSish shell,\n\tset sh_found and the value of default_shell, and report the\n\tfindings in debug mode.\n\n\t* job.c (construct_command_argv_internal): Check unixy_shell, not\n\tno_default_sh_exe, to decide whether to use Unixy or DOSish\n\tbuiltin commands.\n\n\t* README.W32: Update with info about the MinGW build.\n\n\t* build_w32.bat: Support MinGW.\n\n\t* w32/subproc/build.bat: Likewise.\n\n\t* w32/subproc/sub_proc.c (process_easy): Fix format strings for\n\tprinting DWORD args.\n\n\t* function.c (windows32_openpipe): Fix format strings for printing\n\tDWORD args.\n\n\t* job.c (reap_children) [WINDOWS32]: Don't declare 'status' and\n\t'reap_mode'.\n\t(start_job_command): Fix format string for printing the result of\n\tprocess_easy.\n\t(start_job_command) [WINDOWS32]: Do not define.\n\t(exec_command): Fix format string for printing HANDLE args.\n\n\t* main.c (handle_runtime_exceptions): Fix sprintf format strings\n\tto avoid compiler warnings.\n\t(open_tmpfile): Declare fd only if HAVE_FDOPEN is defined.\n\t(Note: some of these fixes were submitted independently by J. Grant)\n\n2005-07-30  J. Grant <jg@jguk.org>\n\n\t* prepare_w32.bat: Copy config.h.w32 to config.h if not exist.\n\t* make_msvc_net2003.vcproj, make_msvc_net2003.sln: MSVC Project files.\n\t* Makefile.am (EXTRA_DIST): Add MSVC Project files.\n\n2005-07-15  Paul Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal) [DOS,WINDOWS32,OS/2]: If\n\twe don't have a POSIX shell, then revert to the old\n\tbackslash-newline behavior (where they are stripped).\n\tFixes bug #13665.\n\n2005-07-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h.W32.template: Reorder to match the standard config.h,\n\tfor easier comparisons.\n\tFrom J. Grant <jg@jguk.org>\n\n\t* maintMakefile: Remove .dep_segment before overwriting it, in\n\tcase it's not writable or noclobber is set.\n\t* expand.c (variable_expand_string): Cast result of pointer\n\tarithmetic to avoid a warning.\n\t* main.c (switches): Add full-fledged final initializer.\n\n2005-07-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: IRIX has _sys_siglist.  Tru64 UNIX has __sys_siglist.\n\t* signame.c (strsignal): If we found _sys_siglist[] or\n\t__sys_siglist[] use those instead of sys_siglist[].\n\tFrom Albert Chin <china@thewrittenword.com>\n\n2005-07-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h-vms.template [VMS]: Latest VMS has its own glob() and\n\tglobfree(); set up to use the GNU versions.\n\tFrom Martin Zinser <zinser@zinser.no-ip.info>\n\n2005-07-03  Paul D. Smith  <psmith@gnu.org>\n\n\tFrom J. Grant <jg@jguk.org>:\n\n\t* README.W32.template: Update the Windows and tested MSVC versions.\n\t* NMakefile.template (CFLAGS_any): Change warning level from W3 to W4.\n\t* w32/subproc/NMakefile (CFLAGS_any): Ditto.\n\t* build_w32.bat: Ditto.\n\t* w32/subproc/build.bat: Ditto.\n\n2005-06-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* signame.c: HAVE_DECL_* macros are set to 0, not undef, if the\n\tdeclaration was checked but not present.\n\n2005-06-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (find_directory): Change type of fs_serno/fs_flags/fs_len\n\tto unsigned long.  Fixes Savannah bug #13550.\n\n\t* w32/subproc/sub_proc.c: Remove (HANDLE) casts on lvalues.\n\t(process_pipe_io): Initialize tStdin/tStdout/tStderr variables.\n\tFixes Savannah bug #13551.\n\n2005-06-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Fix bug in ANSI_STRING/strerror() handling; only define\n\tit if ANSI_STRING is not set.\n\n2005-06-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval): If no filenames are passed to any of the\n\t\"include\" variants, don't print an error.\n\t* doc/make.texi (Include): Document this.\n\tFixes Savannah bug #1761.\n\n\t* job.c (construct_command_argv_internal): Sanitize handling of\n\tbackslash/newline pairs according to POSIX: that is, keep the\n\tbackslash-newline in the command script, but remove a following\n\tTAB character, if present.  In the fast path, make sure that the\n\tbehavior matches what the shell would do both inside and outside\n\tof quotes.  In the slow path, quote the backslash and put a\n\tliteral newline in the string.\n\tFixes Savannah bug #1332.\n\t* doc/make.texi (Execution): Document the new behavior and give\n\tsome examples.\n\t* NEWS: Make a note of the new behavior.\n\n\t* make.h [WINDOWS32]: #include <direct.h>.\n\tFixes Savannah bug #13478.\n\n\t* remake.c (name_mtime): If the stat() of a file fails and the -L\n\toption was given and the file is a symlink, take the best mtime of\n\tthe symlink we can get as the mtime of the file and don't fail.\n\tFixes Savannah bug #13280.\n\n\t* read.c (find_char_unquote): Accept a new argument IGNOREVARS.\n\tIf it's set, then don't\tstop on STOPCHARs or BLANKs if they're\n\tinside a variable reference.  Make this function static as it's\n\tonly used here.\n\t(eval): Call find_char_unquote() with IGNOREVARS set when we're\n\tparsing an unexpanded line looking for semicolons.\n\tFixes Savannah bug #1454.\n\t* misc.c (remove_comments): Move this to read.c and make it static\n\tas it's only used there.  Call find_char_unquote() with new arg.\n\t* make.h: Remove prototypes for find_char_unquote() and\n\tremove_comments() since they're static now.\n\n\t* main.c (main): If we see MAKE_RESTARTS in the environment, unset\n\tits export flag and obtain its value.  When we need to re-exec,\n\tincrement the value and add it into the environment.\n\t* doc/make.texi (Special Variables): Document MAKE_RESTARTS.\n\t* NEWS: Mention MAKE_RESTARTS.\n\t* main.c (always_make_set): New variable.  Change the -B option to\n\tset this one instead.\n\t(main): When checking makefiles, only set always_make_flag if\n\talways_make_set is set AND the restarts flag is 0.  When building\n\tnormal targets, set it IFF always_make_set is set.\n\t(main): Avoid infinite recursion with -W, too: only set what-if\n\tfiles to NEW before we check makefiles if we've never restarted\n\tbefore.  If we have restarted, set what-if files to NEW _after_ we\n\tcheck makefiles.\n\tFixes Savannah bug #7566:\n\n2005-06-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* default.c: Change VMS implicit rules to use $$$$ instead of $$\n\tin the prerequisites list.\n\n2005-06-12  Paul D. Smith  <psmith@gnu.org>\n\n\tFix Savannah bug # 1328.\n\n\t* configure.in: Check for atexit().\n\t* misc.c (close_stdout): Test stdout to see if writes to it have\n\tfailed.  If so, be sure to exit with a non-0 error code.  Based on\n\tcode found in gnulib.\n\t* make.h: Prototype.\n\t* main.c (main): Install close_stdout() with atexit().\n\n2005-06-10  Paul D. Smith  <psmith@gnu.org>\n\n\tVMS build updates from Hartmut Becker <Hartmut.Becker@hp.com>:\n\n\t* vmsjobs.c [VMS]: Updates to compile on VMS: add some missing\n\theaders; make vmsWaitForChildren() static; extern vmsify().\n\t* job.c [VMS]: Move vmsWaitForChildren() prototype to be global.\n\tDon't create child_execute_job() here (it's in vmsjobs.c).\n\t* makefile.vms (job.obj) [VMS]: Add vmsjobs.c as a prerequisite.\n\n2005-06-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (push_new_variable_scope): File variables point\n\tdirectly to the global_setlist variable.  So, inserting a new\n\tscope in front of that has no effect on those variables: they\n\tdon't go through current_variable_set_list.  If we're pushing a\n\tscope and the current scope is global, push it \"the other way\" so\n\tthat the new setlist is in the global_setlist variable, and\n\tnext points to a new setlist with the global variable set.\n\t(pop_variable_scope): Properly undo a push with the new\n\tsemantics.\n\tFixes Savannah bug #11913.\n\n2005-05-31  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* job.c (reap_children): Don't die of the command failed but\n\tthe dontcare flag is set. Fixes Savannah bug #13216.\n\n\t* implicit.c (pattern_search): When creating a target from\n\tan implicit rule match, lookup pattern target and set precious\n\tflag in a newly created target. Fixes Savannah bug #13218.\n\n2005-05-13  Paul D. Smith  <psmith@gnu.org>\n\n\tImplement \"if... else if... endif\" syntax.\n\n\t* read.c (eval): Push all checks for conditional words (\"ifeq\",\n\t\"else\", etc.) down into the conditional_line() function.\n\t(conditional_line): Rework to allow \"else if...\" clause.  New\n\treturn value -2 for lines which are not conditionals.  The\n\tignoring flag can now also be 2, which means \"already parsed a\n\ttrue branch\".  If that value is seen no other branch of this\n\tconditional can be considered true.  In the else parsing if there\n\tis extra text after the else, invoke conditional_line()\n\trecursively to see if it's another conditional.  If not, it's an\n\terror.  If so, raise the conditional value to this level instead\n\tof creating a new conditional nesting level.  Special check for\n\t\"else\" and \"endif\", which aren't allowed on the \"else\" line.\n\t* doc/make.texi (Conditional Syntax): Document the new syntax.\n\n2005-05-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* Makefile.am (EXTRA_make_SOURCES): Add vmsjobs.c\n\t(MAYBE_W32): Rework how SUBDIRS are handled so that \"make dist\"\n\trecurses to the w32 directory, even on non-Windows systems.  Use\n\tthe method suggested in the automake manual.\n\t* configure.in: Add w32/Makefile to AC_CONFIG_FILES.\n\t* maintMakefile (gnulib-url): They moved the texinfo.tex files.\n\n2005-05-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (die): If we're dying with a fatal error (not that a\n\tcommand has failed), write back any leftover tokens before we go.\n\n\t* job.c (set_child_handler_action_flags): If there are jobs\n\twaiting for the load to go down, set an alarm to go off in 1\n\tsecond.  This allows us to wake up from a potentially long-lasting\n\tread() and start a new job if the load has gone down.  Turn it off\n\tafter the read.\n\t(job_noop): Dummy signal handler function.\n\t(new_job): Invoke it with the new semantics.\n\n\t* docs/make.texi: Document secondary expansion.  Various cleanups\n\tand random work.\n\n2005-05-03  Paul D. Smith  <psmith@gnu.org>\n\n\tRename .DEFAULT_TARGET to .DEFAULT_GOAL: in GNU make terminology\n\tthe targets which are to ultimately be made are called \"goals\";\n\tsee the GNU make manual.  Also, MAKECMDGOALS, etc.\n\n\t* filedef.h, read.c, main.c: Change .DEFAULT_TARGET to\n\t.DEFAULT_GOAL, and default_target_name to default_goal_name.\n\t* doc/make.texi (Special Variables): Document .DEFAULT_GOAL.\n\n2005-05-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c, vmsjobs.c (vmsWaitForChildren, vms_redirect,\n\tvms_handle_apos, vmsHandleChildTerm, reEnableAst, astHandler,\n\ttryToSetupYAst, child_execute_job) [VMS]: Move VMS-specific\n\tfunctions to vmsjobs.c.  #include it into jobs.c.\n\n\tGrant Taylor <gtaylor@picante.com> reports that -j# can lose\n\tjobserver tokens.  I found that this happens when an exported\n\trecursive variable contains a $(shell ...) function reference: in\n\tthis situation we could \"forget\" to write back a token.\n\n\t* job.c, job.h: Add variable jobserver_tokens: counts the tokens\n\twe have.  It's not reliable to depend on the number of children in\n\tour linked list so keep a separate count.\n\t(new_job): Check jobserver_tokens rather than children &&\n\twaiting_jobs.  Increment jobserver_tokens when we get one.\n\t(free_child): If jobserver_tokens is 0, internal error.  If it's\n\t>1, write a token back to the jobserver pipe (we don't write a\n\ttoken for the \"free\" job).  Decrement jobserver_tokens.\n\n\t* main.c: Add variable master_job_slots.\n\t(main): Set it to hold the number of jobs requested if we're the\n\tmaster process, when using the jobserver.\n\t(die): Sanity checks: first test jobserver_tokens to make sure\n\tthis process isn't holding any tokens we didn't write back.\n\tSecond, if master_job_slots is set count the tokens left in the\n\tjobserver pipe and ensure it's the same as master_job_slots (- 1).\n\n2005-04-24  Paul D. Smith  <psmith@gnu.org>\n\n\tGrant Taylor <gtaylor@picante.com> reports that -j# in conjunction\n\twith -l# can lose jobserver tokens, because waiting jobs are not\n\tconsulted properly when checking for the \"free\" token.\n\n\t* job.c (free_child): Count waiting_jobs as having tokens.\n\t* job.c (new_job): Ditto.  Plus, call start_waiting_jobs() here to\n\thandle jobs waiting for the load to drop.\n\n2005-04-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Be careful to not core if a variable setting in\n\tthe environment doesn't contain an '='.  This is illegal but can\n\thappen in broken setups.\n\tReported by Joerg Schilling <schilling@fokus.fraunhofer.de>.\n\n2005-04-12  Paul D. Smith  <psmith@gnu.org>\n\n\tThe second expansion feature causes significant slowdown.  Timing\n\ta complex makefile (GCC 4.1) shows a slowdown from .25s to just\n\tread the makefile before the feature, to 11+s to do the same\n\toperations after the feature.  Additionally, memory usage\n\tincreased drastically.  To fix this I added some intelligence that\n\tavoids the overhead of the second expansion unless it's required.\n\n\t* dep.h: Add a new boolean field, need_2nd_expansion.\n\n\t* read.c (eval): When creating the struct dep for the target,\n\tcheck if the name contains a \"$\"; if so set need_2nd_expansion to 1.\n\t(record_files): If there's a \"%\" in a static pattern rule, it gets\n\tconverted to \"$*\" so set need_2nd_expansion to 1.\n\n\t* file.c (expand_deps): Rework to be more efficient.  Only perform\n\tinitialize_file_variables(), set_file_variables(), and\n\tvariable_expand_for_file() if the need_2nd_expansion is set.\n\n\t* implicit.c (pattern_search): Default need_2nd_expansion to 0.\n\t(pattern_search): Ditto.\n\t* main.c (handle_non_switch_argument): Ditto.\n\t(main): Ditto.\n\t* read.c (read_all_makefiles): Ditto.\n\t(eval_makefile): Ditto.\n\n2005-04-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main) [WINDOWS32]: Export PATH to sub-shells, not Path.\n\t* variable.c (sync_Path_environment): Ditto.\n\tPatch by Alessandro Vesely.  Fixes Savannah bug #12209.\n\n\t* main.c (main): Define the .FEATURES variable.\n\t* NEWS: Announce .FEATURES.\n\t* doc/make.texi (Special Variables): Document .FEATURES.\n\n\t* remake.c (check_dep): If a file is .PHONY, update it even if\n\tit's marked intermediate.  Fixes Savannah bug #12331.\n\n2005-03-15  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* file.c (expand_deps): Factor out the second expansion and\n\tprerequisite line parsing logic from snap_deps().\n\n\t* file.c (snap_deps): Use expand_deps(). Expand and parse\n\tprerequisites of the .SUFFIXES special target first. Fixes\n\tSavannah bug #12320.\n\n2005-03-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main) [MSDOS]: Export SHELL in MSDOS.  Requested by Eli\n\tZaretskii.\n\n2005-03-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* signame.c (strsignal): HAVE_DECL_SYS_SIGLIST is 0 when not\n\tavailable, not undefined (from Earnie Boyd).\n\n2005-03-10  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* implicit.c (pattern_search): Mark an intermediate target as\n\tprecious if it happened to be a prerequisite of some (other)\n\ttarget. Fixes Savannah bug #12267.\n\n2005-03-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval_makefile): Add alloca(0).\n\t(eval_buffer): Ditto.\n\n2005-03-09  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* main.c (main): Use o_file instead of o_default when defining\n\tthe .DEFAULT_TARGET special variable.\n\t* read.c (eval): Use define_variable_global() instead of\n\tdefine_variable() when setting new value for the .DEFAULT_TARGET\n\tspecial variable.  Fixes Savannah bug #12266.\n\n2005-03-04  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* imlicit.c (pattern_search): Mark files for which an implicit\n\trule has been found as targets. Fixes Savannah bug #12202.\n\n2005-03-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* AUTHORS: Update.\n\t* doc/make.texi (Automatic Variables): Document $|.\n\n2005-03-03  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (record_files): Instead of substituting % with\n\tactual stem value in dependency list replace it with $*.\n\tThis fixes stem triple expansion bug.\n\n\t* implicit.c (pattern_search): Copy stem to a separate\n\tbuffer and make it a properly terminated string. Assign\n\tthis buffer instead of STEM (which is not terminated) to\n\tf->stem. Instead of substituting % with actual stem value\n\tin dependency list replace it with $*. This fixes stem\n\ttriple expansion bug.\n\n2005-03-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* commands.c (fatal_error_signal) [WINDOWS32]: Don't call kill()\n\ton Windows, as it takes a handle not a pid.  Just exit.\n\tFix from patch #3679, provided by Alessandro Vesely.\n\n\t* configure.in: Update check for sys_siglist[] from autoconf manual.\n\t* signame.c (strsignal): Update to use the new autoconf macro.\n\n2005-03-01  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (record_files): Add a check for the list of prerequisites\n\tof a static pattern rule being empty. Fixes Savannah bug #12180.\n\n2005-02-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Text Functions): Update docs to allow the end\n\tordinal for $(wordlist ...) to be 0.\n\t* function.c (func_wordlist): Fail if the start ordinal for\n\t$(wordlist ...) is <1.  Matches documentation.\n\tResolves Savannah support request #103195.\n\n\t* remake.c (update_goal_chain): Fix logic for stopping in -q:\n\tpreviously we were stopping when !-q, exactly the opposite.  This\n\thas been wrong since version 1.34, in 1994!\n\t(update_file): If we got an error don't break out to run more\n\tdouble-colon rules: just return immediately.\n\tFixes Savannah bug #7144.\n\n2005-02-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* misc.c (end_of_token): Make argument const.\n\t* make.h: Update prototype.\n\n\t* function.c (abspath, func_realpath, func_abspath): Use\n\tPATH_VAR() and GET_PATH_MAX instead of PATH_MAX.\n\t* dir.c (downcase): Use PATH_VAR() instead of PATH_MAX.\n\t* read.c (record_files): Ditto.\n\t* variable.c (do_variable_definition): Ditto.\n\n\t* function.c (func_error): Create a new function $(info ...) that\n\tsimply prints the message to stdout with no extras.\n\t(function_table_init): Add new function to the table.\n\t* NEWS: Add $(info ...) reference.\n\t* doc/make.texi (Make Control Functions): Document it.\n\n\tNew feature: if the system supports symbolic links, and the user\n\tprovides the -L/--check-symlink-time flag, then use the latest\n\tmtime between the symlink(s) and the target file.\n\n\t* configure.in (MAKE_SYMLINKS): Check for lstat() and\n\treadlink().  If both are available, define MAKE_SYMLINKS.\n\t* main.c: New variable: check_symlink_flag.\n\t(usage): Add a line for -L/--check-symlink-times to the help string.\n\t(switches): Add -L/--check-symlink-times command line argument.\n\t(main): If MAKE_SYMLINKS is not defined but the user specified -L,\n\tprint a warning and disable it again.\n\t* make.h: Declare check_symlink_flag.\n\t* remake.c (name_mtime): If MAKE_SYMLINKS and check_symlink_flag,\n\tif the file is a symlink then check each link in the chain and\n\tchoose the NEWEST mtime we find as the mtime for the file.  The\n\tnewest mtime might be the file itself!\n\t* NEWS: Add information about this new feature.\n\t* doc/make.texi (Options Summary): Add -L/--check-symlink-times docs.\n\n\tAvoid core dumps described in Savannah bug # 12124:\n\n\t* file.c: New variable snapped_deps remember whether we've run\n\tsnap_deps().\n\t(snap_deps): Set it.\n\t* filedef.h: Extern it.\n\t* read.c (record_files): Check snapped_deps; if it's set then\n\twe're trying to eval a new target/prerequisite relationship from\n\twithin a command script, which we don't support.  Fatal.\n\n2005-02-28  Boris Kolpackov  <boris@kolpackov.net>\n\n\tImplementation of the .DEFAULT_TARGET special variable.\n\n\t* read.c (eval): If necessary, update default_target_name when\n\treading rules.\n\t* read.c (record_files): Update default_target_file if\n\tdefault_target_name has changed.\n\t* main.c (default_target_name): Define.\n\t* main.c (main): Enter .DEFAULT_TARGET as make variable. If\n\tdefault_target_name is set use default_target_file as a root\n\ttarget to make.\n\t* filedef.h (default_target_name): Declare.\n\t* dep.h (free_dep_chain):\n\t* misc.c (free_dep_chain): Change to operate on struct nameseq\n\tand change name to free_ns_chain.\n\t* file.c (snap_deps): Update to use free_ns_chain.\n\n2005-02-27  Boris Kolpackov  <boris@kolpackov.net>\n\n\tImplementation of the second expansion in explicit rules,\n\tstatic pattern rules and implicit rules.\n\n\t* read.c (eval): Refrain from chopping up rule's dependencies.\n\tStore them in a struct dep as a single dependency line. Remove\n\tthe code that implements SySV-style automatic variables.\n\n\t* read.c (record_files): Adjust the code that handles static\n\tpattern rules to expand all percents instead of only the first\n\tone. Reverse the order in which dependencies are stored so that\n\twhen the second expansion reverses them again they appear in\n\tthe makefile order (with some exceptions, see comments in\n\tthe code). Remove the code that implements SySV-style automatic\n\tvariables.\n\n\t* file.c (snap_deps): Implement the second expansion and chopping\n\tof dependency lines for explicit rules.\n\n\t* implicit.c (struct idep): Define an auxiliary data type to hold\n\timplicit rule's dependencies after stem substitution and\n\texpansion.\n\n\t* implicit.c (free_idep_chain): Implement.\n\n\t* implicit.c (get_next_word): Implement helper function for\n\tparsing implicit rule's dependency lines into words taking\n\tinto account variable expansion requests. Used in the stem\n\tsplitting code.\n\n\t* implicit.c (pattern_search): Implement the second expansion\n\tfor implicit rules. Also fixes bug #12091.\n\n\t* commands.h (set_file_variables): Declare.\n\t* commands.c (set_file_variables): Remove static specifier.\n\n\t* dep.h (free_dep_chain): Declare.\n\t* misc.c (free_dep_chain): Implement.\n\n\t* variable.h (variable_expand_for_file): Declare.\n\t* expand.c (variable_expand_for_file): Remove static specifier.\n\n\t* make.h (strip_whitespace): Declare.\n\t* function.c (strip_whitespace): Remove static specifier.\n\n2005-02-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Check for ferror() when reading makefiles from stdin.\n\tApparently some shells in Windows don't close pipes properly and\n\trequire this check.\n\n2005-02-24  Jonathan Grant  <jg@jguk.org>\n\n\t* configure.in: Add MinGW configuration options, and extra w32 code\n\tdirectory.\n\t* Makefile.am: Add MinGW configuration options, and extra w32 code\n\tdirectory.\n\t* main.c: Determine correct program string (after last \\ without .exe).\n\t* subproc/sub_proc.c: `GetExitCodeProcess' from incompatible pointer\n\ttype fix x2\n\t* w32/Makefile.am: Import to build win32 lib of sub_proc etc.\n\t* subproc/w32err.c: MSVC thread directive not applied to MinGW builds.\n\t* tests/run_make_tests.pl, tests/test_driver.pl: MSYS testing\n\tenvironment support.\n\n2004-04-16  Dmitry V. Levin  <ldv@altlinux.org>\n\n\t* function.c (func_shell): When initializing error_prefix, check\n\tthat reading file name is not null.  This fixes long-standing\n\tsegfault in cases like \"make 'a1=$(shell :)' 'a2:=$(a1)'\".\n\n2005-02-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile: Update the CVS download URL to simplify them.\n\tAlso, the ftp://ftp.gnu.org/GNUinfo site was removed so I'm\n\tdownloading the .texi files from Savannah now.\n\n\tFixed these issues reported by Markus Mauhart <qwe123@chello.at>:\n\n\t* main.c (handle_non_switch_argument): Only add variables to\n\tcommand_variables if they're not already there: duplicate settings\n\twaste space and can be confusing to read.\n\n\t* w32/include/sub_proc.h: Remove WINDOWS32.  It's not needed since\n\tthis header is never included by non-WINDOWS32 code, and it\n\trequires <config.h> to define which isn't always included first.\n\n\t* dir.c (read_dirstream) [MINGW]: Use proper macro names when\n\ttesting MINGW32 versions.\n\n\t* main.c (log_working_directory): flush stdout to be sure the WD\n\tchange is printed before any stderr messages show up.\n\n2005-02-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile (po_repo): Update the GNU translation site URL.\n\n2004-12-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Change char* env_shell to struct variable shell_var.\n\t* variable.c (target_environment): Use new shell_var.\n\n2004-11-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: The old way we avoided creating build.sh from\n\tbuild.sh.in before build.sh.in exists doesn't work anymore; we\n\thave to use raw M4 (thanks to Andreas Schwab <schwab@suse.de> for\n\tthe help!).  This also keeps automake from complaining.\n\t* Makefile.am (README): Add a dummy target so automake won't\n\tcomplain that this file doesn't exist when we checkout from CVS.\n\t* maintMakefile (.dep_segment): Rewrite this rule since newer\n\tversions of automake don't provide DEP_FILES.\n\n2004-11-30  Boris Kolpackov  <boris@kolpackov.net>\n\n\tImplementation of `realpath' and `abspath' built-in functions.\n\n\t* configure.in: Check for realpath.\n\t* function.c (abspath): Return an absolute file name that does\n\tnot contain any `.' or `..' components, nor repeated `/'.\n\t* function.c (func_abspath): For each name call abspath.\n\t* function.c (func_realpath): For each name call realpath\n\tfrom libc or delegate to abspath if realpath is not available.\n\t* doc/make.texi (Functions for File Names): Document new functions.\n\t* doc/make.texi (Quick Reference): Ditto.\n\n2004-11-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main) [WINDOWS32]: Remove any trailing slashes from -C\n\targuments.  Fixes bug #10252.\n\n\tFix for bug #1276: Handle SHELL according to POSIX requirements.\n\n\t* main.c (main): Set SHELL to v_noexport by default.  Remember the\n\toriginal environment setting of SHELL in the env_shell variable.\n\t* main.h: Export new env_shell variable.\n\t* variable.c (target_environment): If we find a v_noexport\n\tvariable for SHELL, add a SHELL variable with the env_shell value.\n\t* doc/make.texi (Quick Reference): Document the POSIX behavior.\n\t* doc/make.texi (Variables/Recursion): Ditto.\n\n2004-11-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (find_and_set_default_shell) [WINDOWS32]: check for\n\tequality of \"cmd\"/\"cmd.exe\", not inequality.  Fixes bug #11155.\n\tPatch by Alessandro Vesely.\n\n2004-11-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (child_execute_job) [VMS]: Don't treat \"#\" as a comment on\n\tthe command line if it's inside a string.\n\tPatch by: Hartmut Becker <Hartmut.Becker@hp.com>\n\n2004-10-21  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* function.c (func_lastword): New function: return last word\n\tfrom the list of words.\n\t* doc/make.texi: Document $(lastword ). Fix broken links in\n\tQuick Reference section.\n\n2004-10-06  Paul D. Smith  <psmith@gnu.org>\n\n\tApply patch from Alessandro Vesely, provided with bug # 9748.\n\tFix use of tmpnam() to work with Borland C.\n\n\t* job.c (construct_command_argv_internal) [WINDOWS32]: Remove\n\tconstruction of a temporary filename, and call new function\n\tcreate_batch_filename().\n\t(create_batch_filename) [WINDOWS32]: New function to create a\n\ttemporary filename.\n\n2004-10-05  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* read.c (record_target_var): Expand simple pattern-specific\n\tvariable.\n\t* variable.c (initialize_file_variables): Do not expand simple\n\tpattern-specific variable.\n\n2004-09-28  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* remake.c (update_file_1): When rebuilding makefiles inherit\n\tdontcare flag from a target that triggered update.\n\n2004-09-27  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* variable.c (initialize_file_variables): Mark pattern-specific\n\tvariable as a per-target and copy export status.\n\n2004-09-21  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* file.c (snap_deps): Mark .PHONY prerequisites as targets.\n\n\t* implicit.c (pattern_search): When considering an implicit rule's\n\tprerequisite check that it is actually a target rather then\n\tjust an entry in the file hashtable.\n\n2004-09-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (readstring): Fix some logic errors in backslash handling.\n\t(eval): Remove some unnecessary processing in buffer handling.\n\t(record_target_var): Assert that parse_variable_definition() succeeded.\n\tReported by: Markus Mauhart <qwe123@chello.at>.\n\n\t* misc.c: Removed the sindex() function.  All instances of this\n\tfunction were trivially replaceable by the standard strstr()\n\tfunction, and that function will always have better (or certainly\n\tno worse) performance than the very simple-minded algorithm\n\tsindex() used.  This can matter with complex makefiles.\n\t* make.h: Remove the prototype for sindex().\n\t* function.c (subst_expand): Convert sindex() call to strstr().\n\tThis means we no longer need to track the TLEN value so remove that.\n\t(func_findstring): Convert sindex() to strstr().\n\t* commands.c (chop_commands): Convert sindex() calls to strstr().\n\tSuggested by: Markus Mauhart <qwe123@chello.at>.\n\n\t* main.c (find_and_set_default_shell) [WINDOWS32]: Implement the\n\tidea behind Savannah Patch #3144 from david.baird@homemail.com.\n\tIf SHELL is set to CMD.EXE then assume it's batch-mode and\n\tnon-unixy.  I wrote the code differently from the patch, though,\n\tto make it safer.  This also resolves bug #9174.\n\n2004-09-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* expand.c (variable_expand_string): Modify to invoke\n\tpatsubst_expand() instead of subst_expand(); the latter didn't\n\thandle suffix patterns correctly.\n\t* function.c (subst_expand): Remove the SUFFIX_ONLY parameter; it\n\twas used only from variable_expand_string() and is no longer used\n\tthere.\n\t(func_subst): Ditto, on call to subst_expand().\n\t(patsubst_expand): Require the percent pointers to point to the\n\tcharacter after the %, not to the % itself.\n\t* read.c (record_files): New call criteria for patsubst_expand().\n\t* variable.h: Remove SUFFIX_ONLY from subst_expand() prototype.\n\tThis is to fix a bug reported by Markus Mauhart <qwe123@chello.at>.\n\n2004-09-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (subst_expand): Fix a check in by_word: look for a\n\tprevious blank if we're beyond the beginning of the string, not\n\tthe beginning of the word.\n\tBugs reported by Markus Mauhart <qwe123@chello.at>.\n\n2004-05-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_goal_chain): Change the argument specifying\n\twhether we're rebuilding makefiles to be a global variable,\n\tREBUILDING_MAKEFILES.\n\t(complain): Extract the code that complains about no rules to make\n\ta target into a separate function.\n\t(update_file_1): If we tried to rebuild a file during the makefile\n\trebuild phase and it was dontcare, then no message was printed.\n\tIf we then try to build the same file during the normal build,\n\tprint a message this time.\n\t(remake_file): Don't complain about un-remake-able files when\n\twe're rebuilding makefiles.\n\n2004-05-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): OS/2 patches from\n\tAndreas Buening <andreas.buening@nexgo.de>.\n\n2004-05-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (update_file): Don't walk the double-colon chain unless\n\tthis is a double-colon rule.  Fix suggested by Boris Kolpackov\n\t<boris@kolpackov.net>.\n\n\t* makefile.vms (CFLAGS): Remove glob/globfree (see readme.vms docs)\n\t* readme.vms: New section describing OpenVMS support and issues.\n\t* default.c (default_variables): Add support for IA64.\n\t* job.c (tryToSetupYAst) [VMS]: On VMS running make in batch mode\n\twithout some privilege aborts make with the error\n\t%SYSTEM-F-NOPRIV. It happens when setting up a handler for\n\tpressing Ctrl+Y and the input device is no terminal. The change\n\tcatches this error and just continues.\n\n\tPatches by Hartmut Becker <Hartmut.Becker@hp.com>\n\n2004-04-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* commands.c (set_file_variables): Set $< properly in the face of\n\torder-only prerequisites.\n\tPatch from Boris Kolpackov <boris@kolpackov.net>\n\n2004-04-21  Bob Byrnes  <byrnes@curl.com>\n\n\t* main.c (main): Notice failures to remake makefiles.\n\n2004-03-28  Paul D. Smith  <psmith@gnu.org>\n\n\tPatches for Acorn RISC OS by Peter Naulls <peter@chocky.org>\n\n\t* job.c: No default shell for RISC OS.\n\t(load_too_high): Hard-code the return to 1.\n\t(construct_command_argv_internal): No sh_chars or sh_cmds.\n\t* getloadavg.c: Don't set LOAD_AVE_TYPE on RISC OS.\n\n2004-03-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (do_variable_definition): Don't append from the\n\tglobal set if a previous non-appending target-specific variable\n\tdefinition exists.  Reported by Oliver Schmidt <oschmidt@gmx.net>\n\t(with fix).\n\n\t* expand.c (reference_variable): Don't give up on variables with\n\tno value that have the target-specific append flag set: they might\n\thave a value after all.  Reported by Oliver Schmidt\n\t<oschmidt@gmx.net> (with fix) and also by Maksim A. Nikulin\n\t<nikulin@dx1cmd.inp.nsk.su>.\n\n\t* rule.c (count_implicit_rule_limits): Don't delete patterns which\n\trefer to absolute pathnames in directories that don't exist: some\n\tportion of the makefile could create those directories before we\n\tmatch the pattern.  Fixes bugs #775 and #108.\n\n\tFixes from Jonathan R. Grant  <jg-make@jguk.org>:\n\n\t* main.c (main): Free makefile_mtimes if we have any.\n\t* README.W32.template: Update documentation for the current status\n\tof the MS-Windows port.\n\t* NMakefile.template (MAKE): Add \"MAKE = nmake\".  A conflicting\n\tenvironment variable is sometimes already defined which causes the\n\tbuild to fail.\n\t* main.c (debug_signal_handler): Only define this function if\n\tSIGUSR1 is available.\n\n\tFixes for OS/2 from Andreas Beuning <andreas.buening@nexgo.de>:\n\n\t* configure.in [OS/2]: Relocate setting of HAVE_SA_RESTART for OS/2.\n\t* README.OS2.template: Documentation updates.\n\t* build.template: Add LIBINTL into LOADLIBES.  Add $CFLAGS to the\n\tlink line for safety.\n\t* maintMakefile (build.sh.in): Remove an extraneous \")\".\n\t* job.c (child_execute_job): Close saved FDs.\n\t* job.c (exec_command) [OS/2]: exec_command(): If the command\n\tcan't be exec'ed and if the shell is not Unix-sh, then try again\n\twith argv = { \"cmd\", \"/c\", ... }. Normally, this code is never\n\treached for the cmd shell unless the command really doesn't exist.\n\t(construct_command_argv_internal) [OS/2]: The code for cmd\n\thandling now uses new_argv = { \"cmd\", \"/c\", \"original line\", NULL}.\n\tThe CMD builtin commands are case insensitive so use strcasecmp().\n\n2004-03-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (do_define): Re-order line counter increment so the count\n\tis accurate (we were losing one line per define).  Reported by\n\tDave Yost <Dave@Yost.com>.\n\n2004-03-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in (HAVE_ANSI_COMPILER): Define if we have an ANSI/ISO\n\tcompiler.\n\t* make.h: Convert uses of __STDC__ to HAVE_ANSI_COMPILER.\n\t* misc.c (message,error,fatal): Ditto.\n\t* configh.dos.template: Define HAVE_ANSI_COMPILER.\n\t* config.h.W32.template: Ditto.\n\t* config.h-vms.template: Ditto.\n\t* config.ami.template: Ditto.\n\n2004-03-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.template: Add a note about broken /bin/sh on SunOS\n\t4.1.3_U1 & 4.1.4.  Fix up Savannah links.\n\n\t* misc.c (message, error, fatal): Don't use \"...\" if we're using\n\tvarargs.  ansi2knr should handle this but it doesn't work: it\n\ttranslates \"...\" to va_dcl etc. but _AFTER_ the preprocessor is\n\tdone.  On many systems (SunOS for example) va_dcl is a #define.\n\tSo, force the use of the non-\"...\" version on pre-ANSI compilers.\n\n\t* maintMakefile (sign-dist): Create some rules to help automate\n\tthe new GNU ftp upload method.\n\n2004-02-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h.W32.template: Add HAVE_STDARG_H\n\t* config.h-vms.template: Ditto.\n\t* config.ami.template: Ditto.\n\n2004-02-23  Jonathan Grant  <jg-make@jguk.org>\n\n\t* README.W32.template: Add a notation about -j with BATCH_MODE_ONLY.\n\t* build_w32.bat: Remove extra \"+\".\n\n2004-02-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.h: Create an UNUSED macro to mark unused parameters.\n\t* (many): Clean up warnings by applying UNUSED, fixing\n\tsigned/unsigned incompatibilities, etc.\n\n\t* acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Add quoting to silence\n\tautoconf warnings.\n\t* filedef.h: Name the command_state enumeration.\n\t* file.c (set_command_state): Use the enumeration in the function\n\targument.\n\n\t* configure.in: Explicitly set SET_MAKE to empty, to disable\n\tMAKE=make even when no make already exists.  Fix bug #3823.\n\n2004-02-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* maintMakefile: Perl script to clean up all non-CVS files.  Use\n\tit on all the subdirectories for the cvs-clean target.\n\n\t* main.c (decode_switches): Require non-empty strings for all our\n\tstring command-line options.  Fixes Debian bug # 164165.\n\n\t* configure.in: Check for stdarg.h and varargs.h.\n\t* make.h (USE_VARIADIC): Set this if we can use variadic functions\n\tfor printing messages.\n\t* misc.c: Check USE_VARIADIC instead of (obsolete) HAVE_STDVARARGS.\n\t(message): Ditto.\n\t(error): Ditto.\n\t(fatal): Ditto.\n\n\tA number of patches for OS/2 support from Andreas Buening\n\t<andreas.buening@nexgo.de>:\n\n\t* job.c (child_handler) [OS/2]: Allow this on OS/2 but we have to\n\tdisable the SIGCHLD handler.\n\t(reap_children) [OS/2]: Remove special handling of job_rfd.\n\t(set_child_handler_action_flags) [OS/2]: Use this function in OS/2.\n\t(new_job) [OS/2]: Disable the SIGCHLD handler on OS/2.\n\t* main.c (main) [OS/2]: Special handling for paths in OS/2.\n\t* configure.in [OS/2]: Force SA_RESTART for OS/2.\n\t* Makefile.am (check-regression): Use $(EXEEXT) for Windows-type\n\tsystems.\n\n2004-02-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* w32/subproc/sub_proc.c (process_easy) [W32]: Christoph Schulz\n\t<mail@kristov.de> reports that if process_begin() fails we don't\n\thandle the error condition correctly in all cases.\n\t* w32/subproc/w32err.c (map_windows32_error_to_string): Make sure\n\tto have a newline on the message.\n\n\t* job.c (construct_command_argv_internal): Add \"test\" to UNIX\n\tsh_cmds[].  Fixes Savannah bug # 7606.\n\n2004-02-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (vms_handle_apos) [VMS]: Fix various string handling\n\tsituations in VMS DCL.  Fixes Savannah bug #5533.  Fix provided by\n\tHartmut Becker <Hartmut.Becker@hp.com>.\n\n2004-01-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (load_too_high): Implement an algorithm to control the\n\t\"thundering herd\" problem when using -l to control job creation\n\tvia the load average.  The system only recomputes the load once a\n\tsecond but we can start many jobs in a second.  To solve this we\n\tkeep track of the number of jobs started in the last second and\n\tapply a weight to try to guess what a correct load would be.\n\tThe algorithm was provided by Thomas Riedl <thomas.riedl@siemens.com>.\n\tAlso fixes bug #4693.\n\t(reap_children): Decrease the job count for this second.\n\t(start_job_command): Increase the job count for this second.\n\n\t* read.c (conditional_line): Expand the text after ifn?def before\n\tchecking to see if it's a single word.  Fixes bug #7257.\n\n2004-01-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (print_file): Recurse to print all targets in\n\tdouble-colon rules.  Fixes bug #4518, reported (with patch) by\n\tAndrew Chatham <chatham@google.com>.\n\n2004-01-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* acinclude.m4: Remove make_FUNC_SETVBUF_REVERSED.\n\t* configure.in: Change make_FUNC_SETVBUF_REVERSED to\n\tAC_FUNC_SETVBUF_REVERSED.\n\n\t* doc/make.texi (Target-specific): Fix Savannah bug #1772.\n\t(MAKE Variable): Fix Savannah bug #4898.\n\n\t* job.c (construct_command_argv_internal): Add \"!\" to the list of\n\tshell escape chars.  POSIX sh allows it to appear before a\n\tcommand, to negate the exit code.  Fixes bug #6404.\n\n\t* implicit.c (pattern_search): When matching an implicit rule,\n\tremember which dependencies have the ignore_mtime flag set.\n\tOriginal fix provided in Savannah patch #2349, by Benoit\n\tPoulot-Cazajous <Benoit.Poulot-Cazajous@jaluna.com>.\n\n2003-11-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.W32.template (Outputs): Clarification on -j with\n\tBATCH_MODE_ONLY_SEHLL suggested by Jonathan R. Grant\n\t<jg-make@jguk.org>.\n\n2003-11-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_if): Strip all the trailing whitespace from the\n\tcondition, then don't expand it.  Fixed bug # 5798.\n\n\t* expand.c (recursively_expand_for_file): If we're expanding a\n\tvariable with no file context, then use the variable's context.\n\tFixes bug # 6195.\n\n2003-10-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (log_working_directory): Add newlines to printf()s.\n\n\t* README.cvs: Add a note to ignore warnings during autoreconf.\n\n\t* maintMakefile (po_repo): Set a new URL for PO file updates.\n\t(get-config/config.guess get-config/config.sub): Get these files\n\tfrom the Savannah config project instead of ftp.gnu.org.\n\n2003-10-05  Paul Eggert  <eggert@twinsun.com>\n\n\t* main.c (main): Avoid potential subscript error if environ has\n\tshort strings.\n\n2003-08-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* misc.c (xmalloc, xrealloc): Add one to 0 sizes, to cater to\n\tsystems which don't yet implement the C89 standard :-/.\n\n2003-07-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (directory_contents_hash_1, directory_contents_hash_1)\n\t[WINDOWS32]: Initialize hash.\n\n2003-06-19  Earnie Boyd  <earnie@uses.sf.net>\n\n\t* dir.c (read_dirstream): Provide a workaround for broken versions of\n\tthe MinGW dirent structure.\n\n2003-05-30  Earnie Boyd  <earnie@users.sf.net>\n\n\t* w32/include/dirent.h: Add __MINGW32__ filter.\n\n2003-05-30  Earnie Boyd  <earnie@users.sf.net>\n\n\t* make.h: Add global declaration of *make_host.\n\t* main.c (print_usage): Remove local declaration of *make_host.\n\t(print_version): Display \"This program built for ...\" after Copyright\n\tnotice.\n\n2003-05-30  Earnie Boyd  <earnie@users.sf.net>\n\n\t* doc/make.texi: Change \"ifinfo\" to \"ifnottex\" as suggested by the\n\texecution of \"makeinfo --html make.texi\".\n\n2003-04-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* build.template: Make some changes to maybe allow this script to\n\twork on DOS/Windows/OS2 systems.  Suggested by Andreas Buening.\n\n\t* README.OS2.template: New file for OS/2 support.  Original\n\tcontributed by Andreas Buening.\n\t* configure.in: Invoke new pds_AC_DOS_PATHS macro to test for\n\tDOS-style paths.\n\n2003-04-19  Paul D. Smith  <psmith@gnu.org>\n\n\tFix bug #1405: allow a target to match multiple pattern-specific\n\tvariables.\n\n\t* rule.c (create_pattern_var, lookup_pattern_var): Move these to\n\tvariable.c, where they've always belonged.\n\t* rule.h: Move the prototypes and struct pattern_var as well.\n\t* variable.c (initialize_file_variables): Invoke\n\tlookup_pattern_var() in a loop, until no more matches are found.\n\tIf a match is found, create a new variable set for the target's\n\tpattern variables.  Then merge the contents of each matching\n\tpattern variable set into the target's pattern variable set.\n\t(lookup_pattern_var): Change this function to be usable\n\tin a loop.  It takes a starting position: if NULL, start at the\n\tbeginning; if non-NULL, start with the pattern variable after that\n\tposition, and return the next matching pattern.\n\t(create_pattern_var): Create a unique instance of\n\tpattern-specific variables for every definition in the makefile.\n\tDon't combine the same pattern together.  This allows us to\n\tprocess the variable handling properly even when the same pattern\n\tis used multiple times.\n\t(parse_variable_definition): New function: break out the parsing\n\tof a variable definition line from try_variable_definition.\n\t(try_variable_definition): Call parse_variable_definition to\n\tparse.\n\t(print_variable_data_base): Print out pattern-specific variables.\n\t* variable.h (struct variable): Remember when a variable is\n\tconditional.  Also remember its flavor.\n\t(struct pattern_var): Instead of keeping a variable set, we just\n\tkeep a single variable for each pattern.\n\t* read.c (record_target_var): Each pattern variable contains only a\n\tsingle variable, not a set, so create it properly.\n\t* doc/make.texi (Pattern-specific): Document the new behavior.\n\n2003-04-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* dir.c (file_exists_p) [VMS]: Patch provided with Bug #3018 by\n\tJean-Pierre Portier <portierjp2@free.fr>.  I don't understand the\n\tfile/directory naming rules for VMS so I can't tell whether this\n\tis correct or not.\n\n2003-04-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in (HAVE_DOS_PATHS): Define this on systems that need\n\tDOS-style pathnames: backslash separators and drive specifiers.\n\n2003-03-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (snap_deps): If .SECONDARY with no targets is given, set\n\tthe intermediate flag on all targets.  Fixes bug #2515.\n\n2003-03-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in, Makefile.am, glob/Makefile.am, doc/Makefile.am:\n\tUpgrade to autoconf 2.57 and automake 1.7.3.\n\n\t* job.c: More OS/2 changes from Andreas Buening.\n\n\t* file.c (print_file): Fix variable initialization.\n\tFixes bug #2892.\n\n\t* remake.c (notice_finished_file):\n\n\t* make.h (ENULLLOOP): Set errno = 0 before invoking the command;\n\tsome calls (like readdir()) return NULL in valid situations\n\twithout resetting errno.  Fixes bug #2846.\n\n2003-02-25  Paul D. Smith  <psmith@gnu.org>\n\n\tPort to OS/2 (__EMX__) by Andreas Buening <andreas.buening@nexgo.de>.\n\n\t* job.c (_is_unixy_shell) [OS/2]: New function.\n\tSet default shell to /bin/sh.\n\t(reap_children): Close the job_rfd pipe here since we don't use a\n\tSIGCHLD handler.\n\t(set_child_handler_action_flags): define this to empty on OS/2.\n\t(start_job_command): Close the jobserver pipe and use\n\tchild_execute_job() instead of fork/exec.\n\t(child_execute_job): Rewrite to handle stdin/stdout FDs and spawn\n\trather than exec'ing, then reconfigure stdin/stdout.\n\t(exec_command): Rewrite to use spawn instead of exec.  Return the\n\tPID of the child.\n\n\t* main.c (main) [OS/2]: Call initialize_main().  Handle argv[0] as\n\tin DOS.  Handle the TEMP environment variable as in DOS.  Don't\n\tuse a SIGCHLD handler on OS/2.  Choose a shell as in DOS.  Don't\n\tuse -j in DOS mode.  Use child_execute_job() instead of\n\texec_command().\n\n\t* function.c (func_shell) [OS/2]: Can't use fork/exec on OS/2: use\n\tspawn() instead.\n\n\t* job.h [OS/2]: Move CLOSE_ON_EXEC here from job.c.  Add\n\tprototypes that return values.\n\n\t* remake.c (f_mtime) [OS/2]: Handle FAT timestamp offsets for OS/2.\n\n\t* read.c (readline) [OS/2]: Don't handle CRLF specially on OS/2.\n\t* default.c (default_suffixes) [OS/2]: Set proper default suffixes\n\tfor OS/2.\n\t* vpath.c (construct_vpath_list) [OS/2]: Handle OS/2 paths like\n\tDOS paths.\n\n2003-02-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* default.c [VMS]: New default rules for .cxx -> .obj compiles.\n\t* job.c (child_execute_job) [VMS]: New code for handling spawn().\n\t(child_execute_job) [VMS]: Handle error status properly.\n\tPatches provided by Hartmut Becker <Hartmut.Becker@compaq.com>.\n\n\t* function.c (func_shell): Use EINTRLOOP() while reading from the\n\tsubshell pipe (Fixes bug #2502).\n\t* job.c (free_child): Use EINTRLOOP() while writing tokens to the\n\tjobserver pipe.\n\t* main.c (main): Ditto.\n\n2003-01-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval): eval() was not fully reentrant, because the\n\tcollapsed buffer was static.  Change it to be an automatic\n\tvariable so that eval() can be invoked recursively.\n\tFixes bug # 2238.\n\t(eval): Apply patch # 1022: fix memory reference error on long\n\ttarget-specific variable lines.\n\tPatch provided by Steve Brown <Steve.Brown@macquarie.com>.\n\n\t* function.c (check_numeric): Combine the is_numeric() function\n\tinto this function, since it's only called from one place.\n\tConstify this function.  Have it print the incorrect string in the\n\terror message.  Fixes bug #2407.\n\t(strip_whitespace): Constify.\n\t(func_if): Constify.\n\t* expand.c (expand_argument): Constify.\n\n2003-01-29  Paul D. Smith  <psmith@gnu.org>\n\n\tFix bug # 2169, also reported by other people on various systems.\n\n\t* make.h: Some systems, such as Solaris and PTX, do not fully\n\timplement POSIX-compliant SA_RESTART functionality; important\n\tsystem calls like stat() and readdir() can still fail with EINTR\n\teven if SA_RESTART has been set on the signal handler.  So,\n\tintroduce macros EINTRLOOP() and ENULLLOOP() which can loop on\n\tEINTR for system calls which return -1 or 0 (NULL), respectively,\n\ton error.\n\tAlso, remove the old atomic_stat()/atomic_readdir() and\n\tHAVE_BROKEN_RESTART handling.\n\n\t* configure.in: Remove setting of HAVE_BROKEN_RESTART.\n\n\t* arscan.c (ar_member_touch): Use EINTRLOOP() to wrap fstat().\n\t* remake.c (touch_file): Ditto.\n\n\t* commands.c (delete_target): Use EINTRLOOP() to wrap stat().\n\t* read.c (construct_include_path): Ditto.\n\t* remake.c (name_mtime): Ditto.\n\t* vpath.c (selective_vpath_search): Ditto.\n\t* dir.c (find_directory): Ditto.\n\t(local_stat): Ditto.\n\t(find_directory): Use ENULLLOOP() to wrap opendir().\n\t(dir_contents_file_exists_p): Use ENULLLOOP() to wrap readdir().\n\n\t* misc.c: Remove HAVE_BROKEN_RESTART, atomic_stat(), and\n\tatomic_readdir() handling.\n\n2003-01-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_call): Fix Bug #1744.  If we're inside a\n\trecursive invocation of $(call ...), mask any of the outer\n\tinvocation's arguments that aren't used by this one, so that this\n\tinvocation doesn't \"inherit\" them accidentally.\n\n2002-12-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (subst_expand): Valery Khamenia reported a\n\tpathological performance hit when doing substitutions on very\n\tlarge values with lots of words: turns out we were invoking\n\tstrlen() a ridiculous number of times.  Instead of having each\n\tcall to sindex() call strlen() again, keep track of how much of\n\tthe text we've seen and pass the length to sindex().\n\n2002-11-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* README.cvs, configure.in: Upgrade to require autoconf 2.56.\n\n\n2002-11-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* NMakefile.template (OBJS): Add hash.c object file.\n\t* SMakefile.template (srcs): Ditto.\n\t* Makefile.ami (objs): Ditto.\n\t* build_w32.bat: Ditto.\n\n\t* Makefile.DOS.template: Remove extra dependencies.\n\n2002-10-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* expand.c (install_variable_buffer): New function.  Install a new\n\tvariable_buffer context and return the previous one.\n\t(restore_variable_buffer): New function.  Free the current\n\tvariable_buffer context and put a previously saved one back.\n\t* variable.h: Prototypes for {install,restore}_variable_buffer.\n\t* function.c (func_eval): Push a new variable_buffer context\n\tbefore we eval, then restore the old one when we're done.\n\tFixes Bug #1517.\n\n\t* read.c (install_conditionals): New function.  Install a new\n\tconditional context and return the previous one.\n\t(restore_conditionals): New function.  Free the current\n\tconditional context and put a previously saved one back.\n\t(eval): Use the {install,restore}_conditionals for \"include\"\n\thandling.\n\t(eval_buffer): Use {install,restore}_conditionals to preserve the\n\tpresent conditional state before we evaluate the buffer.\n\tFixes Bug #1516.\n\n\t* doc/make.texi (Quick Reference): Add references to $(eval ...)\n\tand $(value ...).\n\t(Recursion): Add a variable index entry for CURDIR.\n\n\t* README.cvs: Update to appropriate versions.\n\t* Makefile.am (nodist_loadavg_SOURCES): automake gurus point out I\n\tdon't need to copy loadavg.c: automake is smart enough to create\n\tit for me.  Still have a bug in automake related to ansi2knr tho.\n\n2002-10-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (notice_finished_file): Only touch targets if they have\n\tat least one command (as per POSIX).  Resolve Bug #1418.\n\n\t* *.c: Convert to using ANSI C-style function definitions.\n\t* Makefile.am: Enable the ansi2knr feature of automake.\n\t* configure.in: ditto.\n\n2002-10-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* commands.c (set_file_variables): Bug #1379: Don't use alloca()\n\tfor automatic variable values like $^, etc.  In the case of very\n\tlarge lists of prerequisites this causes problems.  Instead reuse\n\ta static buffer (resizeable) for each variable.\n\n\t* read.c (eval): Fix Bug #1391: allow \"export\" keyword in\n\ttarget-specific variable definitions.  Check for it and set an\n\t\"exported\" flag.\n\t(record_target_var): Set the export field to v_export if the\n\t\"exported\" flag is set.\n\t* doc/make.texi (Target-specific): Document the ability to use\n\t\"export\".\n\n\t* doc/make.texi: Change the name of the section on automatic\n\tvariables from \"Automatic\" to \"Automatic Variables\".  Added text\n\tclarifying the scope of automatic variables.\n\n2002-10-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Allow SysV $$@ variables to use {} braces as well\n\tas () braces.\n\t(record_files): Ditto.\n\n\t* expand.c (variable_expand_string): In $(A:x=y) expansion limit\n\tthe search for the '=' to only within the enclosing parens.\n\n2002-10-03  Paul D. Smith  <psmith@gnu.org>\n\n\tVersion 3.80 released.\n\n\t* dir.c: Change hash functions to use K&R function definition style.\n\t* function.c: Ditto.\n\t* read.c: Ditto.\n\t* variable.c: Ditto.\n\n\tUpdate to automake 1.7.\n\n\t* Makefile.am (AUTOMAKE_OPTIONS): Update to require 1.7.\n\t(pdf): Remove this target as automake now provides one.\n\n\t* configure.in: Change AM_CONFIG_HEADER to AC_CONFIG_HEADERS.\n\n2002-09-30  Martin P.J. Zinser  <zinser@decus.de>\n\n\t* makefile.com: Updates for GNU make 3.80.\n\t* makefile.vms: Ditto.\n\n2002-09-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (enum make_word_type): Remove w_comment.\n\t(get_next_mword): Don't treat comment characters as special; where\n\tthis function is used we will never see a comment (it's stripped\n\tbefore we get here) and treating comments specially means that\n\ttargets like \"foo\\#bar\" aren't handled properly.\n\n2002-09-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Bugs): Update with some info on Savannah, etc.\n\n\t* read.c (eval): Expansion of arguments to export/unexport was\n\tignoring all arguments after the first one.  Change the algorithm\n\tto expand the whole line once, then parse the results.\n\n2002-09-17  Paul D. Smith  <psmith@gnu.org>\n\n\tFix Bug #940 (plus another bug I found while looking at this):\n\n\t* read.c (record_target_var): enter_file() will add a new entry if\n\tit's a double-colon target: we don't want to do that in this\n\tsituation.  Invoke lookup_file() and only enter_file() if it does\n\tnot already exist.  If the file we get back is a double-colon then\n\tadd this variable to the \"root\" double-colon target.\n\n\t* variable.c (initialize_file_variables): If this file is a\n\tdouble-colon target but is not the \"root\" target, then initialize\n\tthe root and make the root's variable list the parent of our\n\tvariable list.\n\n2002-09-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (MAKE Variable): Add some indexing for \"+\".\n\n\t* hash.c (round_up_2): Get rid of a warning.\n\n2002-09-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* Makefile.am (loadavg_SOURCES, loadavg.c): Tiptoe around automake\n\tso it doesn't complain about getloadavg.c.\n\n\t* commands.c (set_file_variables): Make sure we always alloca() at\n\tleast 1 character for the value of $? (for '\\0').\n\n2002-09-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* hash.h (STRING_COMPARE, ISTRING_COMPARE, STRING_N_COMPARE): Fix\n\tmacro to use RESULT instead of the incorrect _RESULT_.\n\n\t* make.h (HAVE_BROKEN_RESTART): Add prototypes for atomic_stat()\n\tand atomic_readdir().  We need to #include dirent.h to get this to\n\twork.\n\t* misc.c (atomic_readdir): Fix typos.\n\n2002-09-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (eval): Expand variable lists given to export and\n\tunexport, so that \"export $(LIST_OF_VARIABLES)\" (etc.) works.\n\t(conditional_line): Ditto for \"ifdef\".  Fixes bug #103.\n\n\t* doc/make.texi (Variables/Recursion): Document this.\n\t(Conditional Syntax): And here.\n\n2002-09-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Check for memmove().\n\n2002-09-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in (HAVE_BROKEN_RESTART): Define this on PTX systems;\n\tMichael Sterrett <msterret@coat.com> reports that while it has\n\tSA_RESTART, it does not work properly.\n\n\t* misc.c (atomic_stat): If HAVE_BROKEN_RESTART, create a function\n\tthat invokes stat() and loops to do it again if it returns EINTR.\n\t(atomic_readdir): Ditto, with readdir().\n\n\t* make.h (stat, readdir): If HAVE_BROKEN_RESTART, alias stat()\n\tand readdir() to atomic_stat() and atomic_readdir().\n\n2002-09-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* implicit.c (pattern_search): Daniel <barkalow@reputation.com>\n\treports that GNU make sometimes doesn't recognize that targets can\n\tbe made, when directories can be created as prerequisites.  He\n\treports that changing the order of predicates in the DEP->changed\n\tflag test so that lookup_file() is always performed, solves this\n\tproblem.\n\n2002-08-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* configure.in: Require a newer version of gettext.\n\n\t* misc.c (perror_with_name): Translate the format string (for\n\tright-to-left language support).\n\t(pfatal_with_name): Ditto.\n\n\t* main.c: Create a static array of strings to store the usage\n\ttext.  This is done to facilitate translations.\n\t(struct command_switch): Remove argdesc and description fields.\n\t(switches): Remove values for obsolete fields.\n\t(print_usage): Print each element of the usage array.\n\n\t* hash.c: Change function definitions to be K&R style.\n\n2002-08-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* NEWS: Remove the mention of .TARGETS; we aren't going to publish\n\tthis one because it's too hard to get right.  We'll look at it for\n\ta future release.\n\t* main.c (main): Don't create the .TARGETS variable.\n\t* variable.c (handle_special_var): Don't handle .TARGETS.\n\n2002-08-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (switches): Add a new option, -B (--always-make).  If\n\tspecified, make will rebuild all targets that it encounters even\n\tif they don't appear to be out of date.\n\t(always_make_flag): New flag.\n\t* make.h: Extern always_make_flag.\n\t* remake.c (update_file_1): Check always_make_flag; if it's set we\n\twill always rebuild any target we can, even if none of its\n\tprerequisites are newer.\n\t* NEWS: Mention it.\n\n\t* doc/make.texi (Shell Function): Make it clear that make\n\tvariables marked as \"export\" are not passed to instances of the\n\tshell function.\n\n\tAdd new introspection variable .VARIABLES and .TARGETS.\n\n\t* variable.c (handle_special_var): New function.  If the variable\n\treference passed in is \"special\" (.VARIABLES or .TARGETS),\n\tcalculate the new value if necessary.  .VARIABLES is handled here:\n\twalk through the hash of defined variables and construct a value\n\twhich is a list of the names.  .TARGETS is handled by\n\tbuild_target_list().\n\t(lookup_variable): Invoke handle_special_var().\n\t* file.c (build_target_list): Walk through the hask of known files\n\tand construct a list of the names of all the ones marked as\n\ttargets.\n\t* main.c (main): Initialize them to empty (and as simple variables).\n\t* doc/make.texi (Special Variables): Document them.\n\t* NEWS: Mention them.\n\n\t* variable.h (struct variable): Add a new flag \"exportable\" which\n\tis true if the variable name is valid for export.\n\t* variable.c (define_variable_in_set): Set \"exportable\" when a new\n\tvariable is defined.\n\t(target_environment): Use the \"exportable\" flag\tinstead of\n\tre-checking the name here... an efficiency improvement.\n\n2002-07-31  Paul D. Smith  <psmith@gnu.org>\n\n\t* config.h-vms.template: Updates to build on VMS.  Thanks to\n\tBrian_Benning@aksteel.com for helping verify the build.\n\t* makefile.com: Build the new hash.c file.\n\t* hash.h: Use strcpmi(), not stricmp(), in the\n\tHAVE_CASE_INSENSITIVE_FS case.\n\n2002-07-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* hash.h (ISTRING_COMPARE, return_ISTRING_COMPARE): Add missing\n\tbackslashes to the HAVE_CASE_INSENSITIVE_FS case.\n\tReported by <Brian_Benning@aksteel.com>.\n\n2002-07-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (pop_variable_scope): Remove variable made unused by\n\tnew hash infrastructure.\n\t* read.c (dep_hash_cmp): Rewrite this to handle ignore_mtime\n\tcomparisons as well as name comparisons.\n\t* variable.h: Add a prototype for new hash_init_function_table().\n\t* file.c (lookup_file): Remove variables made unused by new hash\n\tinfrastructure.\n\t* dir.c (directory_contents_hash_2): Missing return of hash value.\n\t(dir_contents_file_exists_p): Remove variables made unused by new\n\thash infrastructure.\n\n\n\tInstalled Greg McGary's integration of the hash functions from the\n\tGNU id-utils package:\n\n2002-07-10  Greg McGary  <greg@mcgary.org>\n\n\t* scripts/functions/filter-out: Add literals to to the\n\tpattern space in order to add complexity, and trigger\n\tuse of an internal hash table.  Fix documentation strings.\n\t* scripts/targets/INTERMEDIATE: Reverse order of files\n\tpassed to expected `rm' command.\n\n2002-07-10  Greg McGary  <greg@mcgary.org>\n\n\t* Makefile.am (SRCS): Add hash.c (noinst_HEADERS): Add hash.h\n\t* hash.c: New file, taken from id-utils.\n\t* hash.h: New file, taken from id-utils.\n\n\t* make.h (HASH, HASHI): Remove macros.\n\t(find_char_unquote): Change arglist in decl.\n\t(hash_init_directories): New function decl.\n\t* variable.h (hash.h): New #include.\n\t(MAKELEVEL_NAME, MAKELEVEL_LENGTH): New constants.\n\t* filedef.h (hash.h): New #include.\n\t(struct file) [next]: Remove member.\n\t(file_hash_enter): Remove function decl.\n\t(init_hash_files): New function decl.\n\n\t* ar.c (ar_name): Delay call to strlen until needed.\n\t* main.c (initialize_global_hash_tables): New function.\n\t(main): Call it.  Use MAKELEVEL_NAME & MAKELEVEL_LENGTH.\n\t* misc.c (remove_comments): Pass char constants to find_char_unquote.\n\t* remake.c (notice_finished_file): Update last_mtime on `prev' chain.\n\n\t* dir.c (hash.h): New #include.\n\t(struct directory_contents) [next, files]: Remove members.\n\t[ctime]: Add member for VMS.  [dirfiles]: Add hash-table member.\n\t(directory_contents_hash_1, directory_contents_hash_2,\n\tdirectory_contents_hash_cmp): New functions.\n\t(directories_contents): Change type to `struct hash_table'.\n\t(struct directory) [next]: Remove member.\n\t(directory_hash_1, directory_hash_2, directory_hash_cmp): New funcs.\n\t(directory): Change type to `struct hash_table'.\n\t(struct dirfile) [next]: Remove member.\n\t[length]: Add member.  [impossible]: widen type to fill alignment gap.\n\t(dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp): New functions.\n\t(find_directory): Use new hash table package.\n\t(dir_contents_file_exists_p): Likewise.\n\t(file_impossible): Likewise.\n\t(file_impossible_p): Likewise.\n\t(print_dir_data_base): Likewise.\n\t(open_dirstream): Likewise.\n\t(read_dirstream): Likewise.\n\t(hash_init_directories): New function.\n\n\t* file.c (hash.h): New #include.\n\t(file_hash_1, file_hash_2, file_hash_cmp): New functions.\n\t(files): Change type to `struct hash_table'.\n\t(lookup_file): Use new hash table package.\n\t(enter_file): Likewise.\n\t(remove_intermediates): Likewise.\n\t(snap_deps): Likewise.\n\t(print_file_data_base): Likewise.\n\n\t* function.c\n\t(function_table_entry_hash_1, function_table_entry_hash_2,\n\tfunction_table_entry_hash_cmp): New functions.\n\t(lookup_function): Remove `table' argument.\n\tUse new hash table package.\n\t(struct a_word) [chain, length]: New members.\n\t(a_word_hash_1, a_word_hash_2, a_word_hash_cmp): New functions.\n\t(struct a_pattern): New struct.\n\t(func_filter_filterout): Pass through patterns noting boundaries\n\tand '%', if present.  Note a_word length.  Use a hash table if\n\targlists are large enough to justify cost.\n\t(function_table_init): Renamed from function_table.\n\t(function_table): Declare as `struct hash_table'.\n\t(FUNCTION_TABLE_ENTRIES): New constant.\n\t(hash_init_function_table): New function.\n\n\t* read.c (hash.h): New #include.\n\t(read_makefile): Pass char constants to find_char_unquote.\n\t(dep_hash_1, dep_hash_2, dep_hash_cmp): New functions.\n\t(uniquize_deps): Use hash table to efficiently identify duplicates.\n\t(find_char_unquote): Accept two char-constant stop chars, rather\n\tthan a string constant, avoiding zillions of calls to strchr.\n\tTighten inner search loops to test only for desired delimiters.\n\n\t* variable.c (variable_hash_1, variable_hash_2,\n\tvariable_hash_cmp): New functions.\n\t(variable_table): Declare as `struct hash_table'.\n\t(global_variable_set): Remove initialization.\n\t(init_hash_global_variable_set): New function.\n\t(define_variable_in_set): Use new hash table package.\n\t(lookup_variable): Likewise.\n\t(lookup_variable_in_set): Likewise.\n\t(initialize_file_variables): Likewise.\n\t(pop_variable_scope): Likewise.\n\t(create_new_variable_set): Likewise.\n\t(merge_variable_sets): Likewise.\n\t(define_automatic_variables): Likewise.\n\t(target_environment): Likewise.\n\t(print_variable_set): Likewise.\n\n2002-07-10  Paul D. Smith  <psmith@gnu.org>\n\n\tImplement the SysV make syntax $$@, $$(@D), and $$(@F) in the\n\tprerequisite list.  A real SysV make will expand the entire\n\tprerequisites list _twice_: we don't do that as it's a big\n\tbackward-compatibility problem.  We only replace those specific\n\tvariables.\n\n\t* read.c (record_files): Replace any $@, $(@D), and $(@F) variable\n\treferences left in the list of prerequisites.  Check for .POSIX as\n\twe record targets, so we can disable non-POSIX behavior while\n\treading makefiles as well as running them.\n\t(eval): Check the prerequisite list to see if we have anything\n\tthat looks like a SysV prerequisite variable reference.\n\n2002-07-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* doc/make.texi (Prerequisite Types): Add a new section describing\n\torder-only prerequisites.\n\n\t* read.c (uniquize_deps): If we have the same file as both a\n\tnormal and order-only prereq, get rid of the order-only prereq,\n\tsince the normal one supersedes it.\n\n2002-07-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* AUTHORS: Added Greg McGary to the AUTHORS file.\n\t* NEWS: Blurbed order-only prerequisites.\n\t* file.c (print_file): Show order-only deps properly when printing\n\tthe database.\n\n\t* maintMakefile: Add \"update\" targets for wget'ing the latest\n\tversions of various external files.  Taken from Makefile.maint in\n\tautoconf, etc.\n\n\t* dosbuild.bat: Somehow we got _double_ ^M's.  Remove them.\n\tReported by Eli Zaretskii <eliz@is.elta.co.il>.\n\n2002-07-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* po/*.po: Remove.  We'll use wget to retrieve them at release\n\ttime.\n\n\t* variable.c (do_variable_definition) [W32]: On W32 using cmd\n\trather than a shell you get an exception.  Make sure we look up\n\tthe variable.  Patch provided by Eli Zaretskii <eliz@is.elta.co.il>.\n\n\t* remake.c (notice_finished_file): Fix handling of -t flag.\n\tPatch provided by Henning Makholm <henning@makholm.net>.\n\n\t* implicit.c (pattern_search): Some systems apparently run short\n\tof stack space, and using alloca() in this function caused an\n\toverrun.  I modified it to use xmalloc() on the two variables\n\twhich seemed like they might get large.  Fixes Bug #476.\n\n\t* main.c (print_version): Update copyright notice to conform with\n\tGNU standards.\n\t(print_usage): Update help output.\n\n\t* function.c (func_eval): Create a new make function, $(eval\n\t...).  Expand the arguments, put them into a buffer, then invoke\n\teval_buffer() on the resulting string.\n\t(func_quote): Create a new function, $(quote VARNAME).  Inserts\n\tthe value of the variable VARNAME without expanding it any\n\tfurther.\n\n\t* read.c (struct ebuffer): Change the linebuffer structure to an\n\t\"eval buffer\", which can be either a file or a buffer.\n\t(eval_makefile): Move the code in the old read_makefile() which\n\tlocated a makefile into here: create a struct ebuffer with that\n\tinformation.  Have it invoke the new function eval() with that\n\tebuffer.\n\t(eval_buffer): Create a new function that creates a struct ebuffer\n\tthat holds a string buffer instead of a file.  Have it invoke\n\teval() with that ebuffer.\n\t(eval): New function that contains the guts of the old\n\tread_makefile() function: this function parses makefiles.  Obtains\n\tdata to parse from the provided ebuffer.  Some modifications to\n\tmake the flow of the function cleaner and clearer.  Still could\n\tuse some work here...\n\t(do_define): Takes a struct ebuffer instead of a FILE*.  Read the\n\tcontents of the define/endef variable from the ebuffer.\n\t(readstring): Read the next line from a string-style ebuffer.\n\t(readline): Read the next line from an ebuffer.  If it's a string\n\tebuffer, invoke readstring().  If it's a FILE* ebuffer, read it\n\tfrom the file.\n\n\t* dep.h (eval_buffer): Prototype eval_buffer();\n\n\t* variable.c (do_variable_definition): Make sure that all\n\tnon-target-specific variables are registered in the global set.\n\tIf we're invoked from an $(eval ...) we might be inside a $(call\n\t...) or other function which has pushed a variable scope; we still\n\twant to define our variables from evaluated makefile code in the\n\tglobal scope.\n\n2002-07-03  Greg McGary  <greg@mcgary.org>\n\n\t* dep.h (struct dep) [ignore_mtime]: New member.\n\t[changed]: convert to a bitfield.\n\t* implicit.c (pattern_search): Zero ignore_mtime.\n\t* main.c (main, handle_non_switch_argument): Likewise.\n\t* rule.c (convert_suffix_rule): Likewise.\n\t* read.c (read_all_makefiles, read_makefile, multi_glob): Likewise.\n\t(read_makefile): Parse '|' in prerequisite list.\n\t(uniquize_deps): Consider ignore_mtime when comparing deps.\n\t* remake.c (update_file_1, check_dep): Don't force remake for\n\tdependencies that have d->ignore_mtime.\n\t* commands.c (FILE_LIST_SEPARATOR): New constant.\n\t(set_file_variables): Don't include a\n\tprerequisite in $+, $^ or $? if d->ignore_mtime.\n\tDefine $|.\n\n2002-06-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* make.texinfo: Updates for next revision.  New date/rev/etc.\n\tRecreate all Info menus.  Change license on the manual to the GNU\n\tFree Documentation License.  A number of typos.\n\t(Variables Simplify): Don't use \"-\" before it's defined.\n\t(Automatic Prerequisites): Rewrite the target example to work\n\tproperly if the compile fails.  Remove incorrect comments about\n\thow \"set -e\" behaves.\n\t(Text Functions): Move the \"word\", \"wordlist\", \"words\", and\n\t\"firstword\" functions here, from \"File Name Functions\".\n\t* make-stds.texi: Update from latest GNU version.\n\t* fdl.texi: (created) Import the latest GNU version.\n\n2002-06-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (do_variable_definition): New function: extract the\n\tpart of try_variable_definition() that actually sets the value\n\tinto a separate function.\n\t(try_variable_definition): Call do_variable_definition() after\n\tparsing the variable definition string.\n\t(define_variable_in_set): Make the name argument const.\n\n\t* variable.h (enum variable_flavor): Make public.\n\t(do_variable_definition): Create prototype.\n\n\t* read.c (read_all_makefiles): Create a new built-in variable,\n\tMAKEFILE_LIST.\n\t(read_makefile): Add each makefile read in to this variable value.\n\n2002-05-18  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* Makefile.DOS.template: Tweak according to changes in the\n\tdistribution.  Add back the dependencies of *.o files.\n\n\t* configh.dos.template: Synchronize with config.h.in.\n\n2002-05-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (file_timestamp_now): Use K&R function declaration.\n\n\t* getloadavg.c (getloadavg): Merge setlocale() fix from sh-utils\n\tgetloadavg.c.  Autoconf thinks QNX is SVR4-like, but it isn't, so\n\t#undef it.  Remove predefined setup of NLIST_STRUCT.  Decide\n\twhether to include nlist.h based on HAVE_NLIST_H.  Change obsolete\n\tNLIST_NAME_UNION to new HAVE_STRUCT_NLIST_N_UN_N_NAME.\n\t* configure.in (NLIST_STRUCT): Define this if we have nlist.h and\n\tnlist.n_name is a pointer rather than an array.\n\n\t* acinclude.m4 (make_FUNC_SETVBUF_REVERSED): Grab the latest\n\tversion of AC_FUNC_SETVBUF_REVERSED from autoconf CVS.\n\t* configure.in: Use it instead of the old version.\n\n\t* main.c (main): Prefer setvbuf() to setlinebuf().\n\n2002-05-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* Makefile.am (make_LDADD): Add GETLOADAVG_LIBS.\n\t(loadavg_LDADD): Ditto.\n\n2002-04-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* expand.c (recursively_expand_for_file): Rename\n\trecursively_expand() to recursively_expand_for_file() and provide\n\tan extra argument, struct file.  If the argument is provided, set\n\tthe variable scope to that of the file before expanding.\n\t* variable.h (recursively_expand): Make this a macro that invokes\n\trecursively_expand_for_file() with a NULL file pointer.\n\t* variable.c (target_environment): Call the renamed function and\n\tprovide the current file context.\n\tFixes Debian bug #144306.\n\n2002-04-28  Paul D. Smith  <psmith@gnu.org>\n\n\tAllow $(call ...) user-defined variables to be self-referencing\n\twithout throwing an error.  Allows implementation of transitive\n\tclosures, among other possibly useful things.\n\tRequested by: Philip Guenther <guenther@sendmail.com>\n\n\t* variable.h (struct variable): Add a new field: exp_count, and\n\tnew macros to hold its size and maximum value.\n\t(warn_undefined): Make this a macro.\n\t* variable.c (define_variable_in_set): Initialize it.\n\t* expand.c (recursively_expand): If we detect recursive expansion\n\tof a variable, check the exp_count field.  If it's greater than 0\n\tallow the recursion and decrement the count.\n\t(warn_undefined): Remove this (now a macro in variable.h).\n\t* function.c (func_call): Before we expand the user-defined\n\tfunction, modify its exp_count field to contain the maximum\n\tnumber of recursive calls we'll allow.  After the call, reset it\n\tto 0.\n\n2002-04-21  Paul D. Smith  <psmith@gnu.org>\n\n\tModified to use latest autoconf (2.53), automake (1.6.1), and\n\tgettext (0.11.1).  We're using gettext's new \"external\" support,\n\tto avoid including libintl source with GNU make.\n\n\t* README.cvs: New file.  Explain how to build GNU make from CVS.\n\n\t* configure.in: Modify checking for the system glob library.\n\tUse AC_EGREP_CPP instead of AC_TRY_CPP.  Remove the setting of\n\tGLOBDIR (we will always put \"glob\" in SUBDIRS, so automake\n\tetc. will manage it correctly).  Set an automake conditional\n\tUSE_LOCAL_GLOB to decide whether to compile the glob library.\n\n\t* getloadavg.c (main): Include make.h in the \"TEST\" program to\n\tavoid warnings.\n\n\t* Makefile.am: Remove special rules for loadavg.  Replace them\n\twith Automake capabilities for building extra programs.\n\n\t* signame.c: This file does nothing if the system provide\n\tstrsignal().  If not, it implements strsignal().  If the system\n\tdoesn't define sys_siglist, then we make our own; otherwise we use\n\tthe system version.\n\t* signame.h: Removed.\n\n\t* main.c (main): No need to invoke signame_init().  Update copyright.\n\n\t* ABOUT-NLS: Removed.\n\t* gettext.c: Removed.\n\t* gettext.h: Get a simplified copy from the gettext package.\n\t* po/*: Created.\n\t* i18n/*.po: Moved to po/.\n\t* i18n/: Removed.\n\n\t* config/*: Created.  Contains package configuration helper files.\n\t* config.guess, config.sub: Moved to config directory.\n\n\t* configure.in (AC_CONFIG_FILES): Add po/Makefile.in, config/Makefile.\n\tRework to use new-style autoconf features.  Use the \"external\"\n\tmode for gettext.  Make the build.sh config file conditional on\n\twhether build.sh.in exists, to avoid autoconf errors.\n\t* acinclude.m4: Removed almost all macros as being obsolete.\n\tRewrote remaining macros to use AC_DEFINE.\n\t* acconfig.h: Removed.\n\n\t* Makefile.am (EXTRA_DIST): Add config/config.rpath.  Use a\n\tconditional to handle customs support.  Remove special handling\n\tfor i18n features.\n\n2002-04-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_call): Don't mark the argument variables $1,\n\tetc. as recursive.  They've already been fully expanded so\n\tthere's no need to do it again, and doing so strips escaped $'s.\n\tReported by Sebastian Glita <glseba@yahoo.com>.\n\n\t* remake.c (notice_finished_file): Walk through double-colon\n\tentries via the prev field, not the next field!\n\tReported by Greg McGary <greg@mcgary.org>.\n\n\t* main.c (main): If the user specifies -q and asks for a specific\n\ttarget which is a makefile, we got an assert.  In that case it\n\tturns out we should continue normally instead.\n\n\t* i18n/de.po, i18n/fr.po: Installed an updated translation.\n\n\t* i18n/he.po: Installed a new translation.\n\n2002-01-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/es.po, i18n/ru.po: Installed an updated translation.\n\n2001-12-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/ja.po: Installed an updated translation.\n\n2001-09-06  Paul Eggert  <eggert@twinsun.com>\n\n\t* configure.in (AC_CHECK_HEADERS): Add sys/resource.h.\n\t(AC_CHECK_FUNCS): Add getrlimit, setrlimit.\n\n\t* main.c: Include <sys/resource.h> if it, getrlimit, and setrlimit\n\tare available.\n\t(main): Get rid of any avoidable limit on stack size.\n\n2001-09-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/da.po: Installed an updated translation.\n\n2001-08-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/fr.po: Installed an updated translation.\n\tResolves Debian\tbug #106720.\n\n2001-06-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/da.po, configure.in (ALL_LINGUAS): Installed a new\n\ttranslation.\n\n2001-06-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/ko.po: Installed a new translation.\n\n2001-05-06  Paul D. Smith  <psmith@gnu.org>\n\n\tModify the EINTR handling.\n\n\t* job.c (new_job): Reorganize the jobserver algorithm.  Reorder\n\tthe way in which we manage the file descriptor/signal handler race\n\ttrap to be more efficient.\n\n2001-05-06  Paul Eggert  <eggert@twinsun.com>\n\n\tRestart almost all system calls that are interrupted, instead\n\tof worrying about EINTR.  The lone exception is the read() for\n\tjob tokens.\n\n\t* configure.in (HAVE_SA_RESTART): New macro.\n\t(MAKE_JOBSERVER): Define to 1 only if HAVE_SA_RESTART.\n\t* main.c (main): Use SA_RESTART instead of the old,\n\tnonstandard SA_INTERRUPT.\n\n\t* configure.in (AC_CHECK_FUNCS): Add bsd_signal.\n\t* main.c (bsd_signal): New function or macro,\n\tif the implementation doesn't supply it.\n\t(The bsd_signal function will be in POSIX 1003.1-200x.)\n\t(HANDLESIG): Remove.\n\t(main, FATAL_SIG): Use bsd_signal instead of signal or HANDLESIG.\n\n\t* make.h (EINTR_SET): Remove.\n\t(SA_RESTART): New macro.\n\n\t* arscan.c (ar_member_touch): Don't worry about EINTR.\n\t* function.c (func_shell): Likewise.\n\t* job.c (reap_children, free_child, new_job): Likewise.\n\t* main.c (main): Likewise.\n\t* remake.c (touch_file, name_mtime): Likewise.\n\n\t* arscan.c (ar_member_touch): Fix bug uncovered by EINTR removal;\n\tif fstat failed with errno!=EINTR, the error was ignored.\n\n\t* job.c (set_child_handler_action_flags): New function.\n\t(new_job): Use it to temporarily clear the SIGCHLD action flags\n\twhile reading the token.\n\n2001-05-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (start_job_command): Don't add define/endef per-line flags\n\tto the top-level flags setting.\n\n2001-04-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* arscan.c (VMS_get_member_info,ar_scan) [VMS]: VMS sets the low\n\tbit on error, so check for odd return values, not non-0 return\n\tvalues.\n\t(VMS_get_member_info): Calculate the timezone differences correctly.\n\tReported by John Fowler <jfowler@nyx.net>.\n\n\n2001-03-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (lookup_variable) [VMS]: Null-terminate the variable\n\tvalue before invoking define_variable().\n\tReported by John Fowler <jfowler@nyx.net>.\n\n2001-02-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (record_target_var): If we reset the variable due to a\n\tcommand-line variable setting overriding it, turn off the \"append\"\n\tflag.\n\n2001-01-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (lookup_variable) [VMS]: When getting values from the\n\tenvironment, allocate enough space for the _value_ plus escapes,\n\tnot enough space for the name plus escapes :-/.\n\tReported by John Fowler <jfowler@nyx.net>.\n\n\t* remake.c (f_mtime): Removed the \"***\" prefix from the mod time\n\twarnings that make generates, so it doesn't look like an error.\n\tReported by Karl Berry <karl@gnu.org>.\n\n\n\tFix for PR/2020:  Rework appended target-specific variables.  I'm\n\tfairly confident this algorithm is finally correct.\n\n\t* expand.c (allocated_variable_append): Rewrite.  Instead of\n\texpanding each appended variable then adding all the expanded\n\tstrings together, we append all the unexpanded values going up\n\tthrough the variable set contexts, then expand the final result.\n\tThis behaves just like non-target-specific appended variable\n\tvalues, while the old way didn't in various corner cases.\n\t(variable_append): New function: recursively append the unexpanded\n\tvalue of a variable, walking from the outermost variable scope to\n\tthe innermost.\n\t* variable.c (lookup_variable): Remove the code that looked up the\n\tvariable set list if the found variable was \"append\".  We don't\n\tneed this anymore.\n\t(lookup_variable_in_set): Make this non-static so we can use it\n\telsewhere.\n\t(try_variable_definition): Use lookup_variable_in_set() rather\n\tthan faking out current_variable_set_list by hand (cleanup).\n\t* variable.h: Add a prototype for the now non-static\n\tlookup_variable_in_set().\n\n2000-11-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime) [WINDOWS32]: On various advice, I changed the\n\tWINDOWS32 port to assume timestamps can be up to 3 seconds away\n\tbefore throwing a fit.\n\n2000-11-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* read.c (readline): CRLF calculations had a hole, if you hit the\n\tbuffer grow scenario just right.  Reworked the algorithm to avoid\n\tthe need for len or lastlen at all.  Problem description with\n\tsample code chages provided by Chris Faylor <cgf@redhat.com>.\n\n2000-10-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* gettext.c (SWAP): Declare this with the prototype, otherwise\n\tsome systems don't work (non-32-bit?  Reported for Cray T3E).\n\tReported by Thorstein Thorsteinsson <thor@signe.teokem.lu.se>.\n\n2000-10-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* acinclude.m4 (AM_LC_MESSAGES): Remove undefined macro\n\tAM_LC_MESSAGES; it doesn't seem to do anything anyway??\n\n\t* i18n/gl.po, configure.in (ALL_LINGUAS): New Galician translation.\n\n2000-09-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* gettext.c: Don't #define _GETTEXT_H here; we only include some\n\tparts of the real gettext.h here, and we expect to really include\n\tthe real gettext.h later.  If we keep this #define, it's ignored.\n\n2000-09-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (log_working_directory): Rework the text to use complete\n\tsentences, to make life simpler for the translators.\n\n2000-08-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* file.c (remove_intermediates): Print a debug message before we\n\tremove intermediate files, so the user (if she uses -d) knows\n\twhat's going on.\n\n2000-08-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (try_variable_definition): Change how we handle\n\ttarget-specific append variable defns: instead of just setting the\n\tvalue, expand it as an append _but_ only within the current\n\ttarget's context.  Otherwise we lose all but the last value if the\n\tvariable is appended more than once within the current target\n\tcontext.  Fixes PR/1831.\n\n2000-08-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* function.c (func_shell): Nul-terminate the buffer before\n\tprinting an exec error message (just in case it's not!).\n\tFixes PR/1860, reported by Joey Hess <joey@valinux.com>.\n\n2000-07-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* job.c (construct_command_argv_internal): Add \"~\" to the list of\n\tsh_chars[] which disallow optimizing out the shell call.\n\n2000-07-23  Paul Eggert  <eggert@twinsun.com>\n\n\t* NEWS, make.texinfo: Document .LOW_RESOLUTION_TIME, which\n\tsupersedes --disable-nsec-timestamps.\n\t* make.texinfo: Consistently use \"time stamp\" instead of \"timestamp\".\n\t* README: Remove --disable-nsec-timestamps.\n\n\t* filedef.h (struct file.low_resolution_time): New member.\n\t* file.c (snap_deps): Add support for .LOW_RESOLUTION_TIME.\n\t* remake.c (update_file_1):\n\tAvoid spurious rebuilds due to low resolution time stamps,\n\tgeneralizing the earlier code that applied only to archive members.\n\t(f_mtime): Archive members always have low resolution time stamps.\n\n\t* configure.in: Remove --disable-nsec-timestamps, as this has\n\tbeen superseded by .LOW_RESOLUTION_TIME.\n\n2000-07-23  Paul Eggert  <eggert@twinsun.com>\n\n\t* configure.in (enable_nsec_timestamps): Renamed from\n\tmake_cv_nsec_timestamps, since enable/disable options\n\tshouldn't be cached.\n\n2000-07-23  Bruno Haible  <haible@clisp.cons.org>\n       and  Paul Eggert  <eggert@twinsun.com>\n\n\t* file.c (file_timestamp_now):\n\tUse preprocessor-time check for FILE_TIMESTAMP_HI_RES\n\tso that clock_gettime is not linked unless needed.\n\n\t* filedef.h (FILE_TIMESTAMP_HI_RES):\n\tRemove definition; \"configure\" now does this.\n\n\t* configure.in (jm_AC_TYPE_UINTMAX_T): Move up,\n\tto before high resolution file timestamp check,\n\tsince that check now uses uintmax_t.\n\t(FILE_TIMESTAMP_HI_RES): Define to nonzero if the code should use\n\thigh resolution file timestamps.\n\t(HAVE_CLOCK_GETTIME): Do not define if !FILE_TIMESTAMP_HI_RES,\n\tso that we don't link in clock_gettime unnecessarily.\n\n2000-07-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* i18n/ja.po: New version of the translation file.\n\n2000-07-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* remake.c (f_mtime): If NO_FLOAT is defined, don't bother with\n\tthe offset calculation.\n\t(name_mtime): Replace EINTR test with EINTR_SET macro.\n\n2000-07-07  Paul Eggert  <eggert@twinsun.com>\n\n\tFix for PR/1811:\n\n\t* remake.c (update_file_1):\n\tAvoid spurious rebuilds of archive members due to their\n\ttimestamp resolution being only one second.\n\t(f_mtime): Avoid spurious warnings of timestamps in the future due to\n\tthe clock's resolution being lower than file timestamps'.\n\tWhen warning about future timestamps, report only the discrepancy,\n\tnot the absolute value of the timestamp and the current time.\n\n\t* file.c (file_timestamp_now): New arg RESOLUTION.\n\t* filedef.h (file_timestamp_now): Likewise.\n\t(FILE_TIMESTAMP_NS): Now returns int.  All uses changed.\n\n2000-07-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* variable.c (lookup_variable) [VMS]: Remove vestigial references\n\tto listp.  Fixes PR/1793.\n\n2000-06-26  Paul Eggert  <eggert@twinsun.com>\n\n\t* Makefile.am (MAINTAINERCLEANFILES): New macro, with stamp-pot in it.\n\n\t* dir.c (vms_hash): Ensure ctype macro args are nonnegative.\n\n\t* remake.c (f_mtime): Remove unused var memtime.\n\n2000-06-25  Martin Buchholz  <martin@xemacs.org>\n\n\t* make.texinfo, NEWS, TODO.private: Minor spelling corrections.\n\tRan spell-check\ton make.texinfo.\n\n2000-06-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* main.c (main): Replace EXIT_SUCCESS, EXIT_FAILURE, and\n\tEXIT_TROUBLE with MAKE_SUCCESS, MAKE_FAILURE, and MAKE_TROUBLE.\n\t* make.h: Define these macros.\n\n\t* Version 3.79.1 released.\n\n\t* configure.in: Add a new option, --disable-nsec-timestamps, to\n\tavoid using sub-second timestamps on systems that support it.  It\n\tcan lead to problems, e.g. if your makefile relies on \"cp -p\".\n\t* README.template: Document the issue with \"cp -p\".\n\n\t* config.guess, config.sub: Updated.\n\n\f\n\nSee ChangeLog.2, available in the Git repository at:\n\n\thttps://git.savannah.gnu.org/cgit/make.git/tree/\n\nfor earlier changes.\n\n\nCopyright (C) 2000-2013 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "Makefile.am",
    "content": "# This is a -*-Makefile-*-, or close enough\n#\n# Copyright (C) 1997-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAUTOMAKE_OPTIONS = dist-lzip silent-rules std-options subdir-objects nostdinc\nACLOCAL_AMFLAGS = -I m4\n\nMAKE_HOST =\t@MAKE_HOST@\n\nSUBDIRS =\tlib po doc\n\nbin_PROGRAMS =\tmake\ninclude_HEADERS = src/gnumake.h\n\nman_MANS =\tdoc/make.1\n\nmake_SRCS =\tsrc/ar.c src/arscan.c src/commands.c src/commands.h \\\n\t\tsrc/debug.h src/default.c src/dep.h src/dir.c src/expand.c \\\n\t\tsrc/file.c src/filedef.h src/function.c src/getopt.c \\\n\t\tsrc/getopt.h src/getopt1.c src/gettext.h src/guile.c \\\n\t\tsrc/hash.c src/hash.h src/implicit.c src/job.c src/job.h \\\n\t\tsrc/load.c src/loadapi.c src/main.c src/makeint.h src/misc.c \\\n\t\tsrc/mkcustom.h src/os.h src/output.c src/output.h src/read.c \\\n\t\tsrc/remake.c src/rule.c src/rule.h src/shuffle.h src/shuffle.c \\\n\t\tsrc/signame.c src/strcache.c src/variable.c src/variable.h \\\n\t\tsrc/version.c src/vpath.c src/warning.c src/warning.h\n\nw32_SRCS =\tsrc/w32/pathstuff.c src/w32/w32os.c src/w32/compat/dirent.c \\\n\t\tsrc/w32/compat/posixfcn.c src/w32/include/dirent.h \\\n\t\tsrc/w32/include/dlfcn.h src/w32/include/pathstuff.h \\\n\t\tsrc/w32/include/sub_proc.h src/w32/include/w32err.h \\\n\t\tsrc/w32/subproc/misc.c src/w32/subproc/proc.h \\\n\t\tsrc/w32/subproc/sub_proc.c src/w32/subproc/w32err.c\n\nw32_utf8_SRCS = src/w32/utf8.rc src/w32/utf8.manifest\n\nvms_SRCS =\tsrc/vms_exit.c src/vms_export_symbol.c src/vms_progname.c \\\n\t\tsrc/vmsdir.h src/vmsfunctions.c src/vmsify.c\n\nglob_SRCS =\tlib/fnmatch.c lib/fnmatch.h lib/glob.c lib/glob.h\n\nalloca_SRCS =\tlib/alloca.c\n\nloadavg_SRCS =\tlib/getloadavg.c\n\nmake_SOURCES =\t$(make_SRCS)\nEXTRA_make_SOURCES = $(vms_SRCS)\n\nif HAVE_GUILE\n  _GUILE_CFLAGS = $(GUILE_CFLAGS)\n  _GUILE_LIBS = $(GUILE_LIBS)\nelse\n  _GUILE_CFLAGS =\n  _GUILE_LIBS =\nendif\n\nmake_LDADD =\t$(LIBOBJS) $(_GUILE_LIBS) lib/libgnu.a $(GETLOADAVG_LIBS) \\\n\t\t@LIBINTL@\n\nlocaledir =\t$(datadir)/locale\n\nAM_CPPFLAGS =\t-Isrc -I$(top_srcdir)/src -Ilib -I$(top_srcdir)/lib \\\n\t\t-DLIBDIR=\\\"$(libdir)\\\" -DLOCALEDIR=\\\"$(localedir)\\\"\n\n# If prefix is not a standard location, look in prefix as well\nif !KNOWN_PREFIX\n  AM_CPPFLAGS += -DINCLUDEDIR=\\\"$(includedir)\\\"\nendif\n\nAM_CFLAGS =\t$(_GUILE_CFLAGS)\n\nif WINDOWSENV\n  make_SOURCES += $(w32_SRCS)\n  AM_CPPFLAGS  += -I $(top_srcdir)/src/w32/include\nelse\n  make_SOURCES += src/posixos.c\nendif\n\nUTF8OBJ = src/w32/utf8.$(OBJEXT)\n\nif HAVE_WINDRES\n  make_LDADD += $(UTF8OBJ)\nendif\n\n$(UTF8OBJ) : $(w32_utf8_SRCS)\n\t$(WINDRES) -o $@ -i $<\n\nif USE_CUSTOMS\n  make_SOURCES += src/remote-cstms.c\nelse\n  make_SOURCES += src/remote-stub.c\nendif\n\n# Extra stuff to include in the distribution.\n\nmk_FILES =\tBasic.mk mk/msdosdjgpp.mk mk/VMS.mk mk/Windows32.mk\n# We don't need this, since the standard automake output will do.\n#mk/Posix.mk.in\n\nm4_FILES =\tm4/gnulib-cache.m4\n\ntest_FILES =\ttests/run_make_tests tests/run_make_tests.bat \\\n\t\ttests/run_make_tests.pl tests/test_driver.pl \\\n\t\ttests/config-flags.pm.in tests/config_flags_pm.com \\\n\t\ttests/config-flags.pm.W32 \\\n\t\ttests/mkshadow tests/thelp.pl tests/guile.supp tests/README\n# test/scripts are added via dist-hook below.\n\nEXTRA_DIST =\tChangeLog INSTALL README build.sh build.cfg.in $(man_MANS) \\\n\t\tsrc/mkconfig.h README.customs README.OS2 README.zOS \\\n\t\tREADME.DOS builddos.bat src/configh.dos \\\n\t\tREADME.W32 build_w32.bat src/config.h.W32 \\\n\t\tREADME.VMS makefile.com src/config.h-vms src/vmsjobs.c \\\n\t\tvms_export_symbol_test.com \\\n\t\tsrc/gmk-default.scm src/gmk-default.h \\\n\t\t$(mk_FILES) $(m4_FILES) $(test_FILES) $(w32_utf8_SRCS)\n\n# --------------- Generate the Guile default module content\n\nsrc/guile.$(OBJEXT): src/gmk-default.h\nsrc/gmk-default.h: $(top_srcdir)/src/gmk-default.scm\n\t(echo 'static const char *const GUILE_module_defn = \" '\\\\ \\\n\t  && sed -e 's/;.*//' -e '/^[ \\t]*$$/d' -e 's/\"/\\\\\"/g' -e 's/$$/ \\\\/' \\\n\t\t $(top_srcdir)/src/gmk-default.scm \\\n\t  && echo '\";') > src/gmk-default.h\n\n# --------------- Local DIST Section\n\n# Install the mk and tests subdirectories\n#\ndist-hook:\n\t(cd $(top_srcdir); \\\n\t sub=`find tests/scripts -follow \\( -name .git -o -name .deps -o -name work -o -name .gitignore -o -name \\*.orig -o -name \\*.rej -o -name \\*~ -o -name \\*.out -o -name Makefile \\) -prune -o -type f -print`; \\\n\t $(AMTAR) chf - $$sub) \\\n\t| (cd $(distdir); $(AMTAR) xfBp -)\n\n\n# --------------- Local CHECK Section\n\ncheck-local: check-regression\n\t@banner=\" Regression PASSED: $(PACKAGE_STRING) ($(MAKE_HOST)) built with $(CC) \"; \\\n\tdashes=`echo \"$$banner\" | sed s/./=/g`; \\\n\techo; \\\n\techo \"$$dashes\"; \\\n\techo \"$$banner\"; \\\n\techo \"$$dashes\"; \\\n\techo\n\n# > check-regression\n#\n# Look for the make test suite, and run it if found and we can find perl.\n#\nMAKETESTFLAGS =\n\n.PHONY: check-regression\n\nGMK_OUTDIR = ..\n\ntestlog = test-suite.log\ntestresult = tests/.test-result\nerrorpre = makeerror-$(PACKAGE_VERSION)-$(host_triplet)\n\ntestfiles = $(testlog) $(testresult) $(errorfile)\nMOSTLYCLEANFILES = $(testfiles)\n\nerrordetails =\tconfig.status config.log src/config.h src/mkconfig.h \\\n\t\t$(testlog) tests/work\n\n# Create a 4-letter random sequence\nrand_value = c = \"abcdefghijklmnopqrstuvwxyz0123456789\"\nrand_char  = substr(c,int(rand()*36),1)\nrand_string = $(AWK) 'BEGIN{srand(); $(rand_value); print $(rand_char) \"\" $(rand_char) \"\" $(rand_char) \"\" $(rand_char);}'\n\ncheck-regression: tests/config-flags.pm\n\t$(AM_V_at) rm -f $(testfiles)\n\t$(AM_V_at) if test -f '$(top_srcdir)/tests/run_make_tests.pl'; then \\\n\t  ulimit -n 128; \\\n\t  if $(PERL) -v >/dev/null 2>&1; then \\\n\t    echo \"cd tests && $(PERL) $(PERLFLAGS) $(abs_top_srcdir)/tests/run_make_tests.pl -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)\"; \\\n\t    (cd tests && $(PERL) $(PERLFLAGS) '$(abs_top_srcdir)/tests/run_make_tests.pl' -make '$(GMK_OUTDIR)/make$(EXEEXT)' $(MAKETESTFLAGS); echo $$? >.test-result) 2>&1 | tee $(testlog); \\\n\t    export TAR_OPTIONS='$(filter-out --sort%,$(TAR_OPTIONS))'; \\\n\t    er=$$(cat $(testresult)); if test \"$$er\" -ne 0; then \\\n\t      dirnm=\"$(errorpre)-$$($(rand_string))\"; fnm=\"$$dirnm.tar.gz\"; \\\n\t      rm -rf \"$$dirnm\"; mkdir \"$$dirnm\"; \\\n\t      $(AMTAR) chf - $(errordetails) | (cd \"$$dirnm\"; $(AMTAR) xf -); \\\n\t      $(AMTAR) chf - \"$$dirnm\" | eval GZIP= gzip $(GZIP_ENV) -c >\"$$fnm\"; \\\n\t      echo \"*** Testing FAILED!  Details: $$fnm\"; \\\n\t      echo '*** Please report to <$(PACKAGE_BUGREPORT)>'; echo; \\\n\t      exit $$er; \\\n\t    fi; \\\n\t  else \\\n\t    echo \"Can't find a working Perl ($(PERL)); the test suite requires Perl.\"; \\\n\t  fi; \\\n\telse \\\n\t  echo \"Can't find the $(PACKAGE_NAME) test suite ($(top_srcdir)/tests).\"; \\\n\tfi\n\n\n# --------------- Maintainer's Section\n\n# Tell automake that I haven't forgotten about this file and it will be\n# created before we build a distribution (see maintMakefile in the Git\n# distribution).\n\nREADME:\n\n@MAINT_MAKEFILE@\n"
  },
  {
    "path": "NEWS",
    "content": "GNU Make NEWS                                               -*-indented-text-*-\n  History of user-visible changes.\n  26 February 2023\n\nSee the end of this file for copyrights and conditions.\n\nAll user-visible changes are more fully described in the GNU Make manual,\nwhich is contained in this distribution as the file doc/make.texi.\nSee the README file and the GNU Make manual for instructions for\nreporting bugs.\n\n\f\nVersion 4.4.90 (26 Feb 2023)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=111&set=custom\n\n* WARNING: Removed AmigaOS support!\n  This version of GNU Make no longer supports AmigaOS.  If you need support\n  for AmigaOS please use one of the older versions of GNU Make.\n\n* WARNING: Loaded Object ABI incompatibility!\n  This release changes the loaded object feature from \"technology preview\" to\n  fully-supported feature.  However, it introduces an ABI incompatibility with\n  previous releases: the setup function now takes an ABI version as its first\n  argument.  At compile time you can test the GMK_ABI_VERSION constant to\n  detect which ABI should be used.  At runtime your initialization function\n  can check the provided ABI version to verify it's being loaded correctly.\n\n* WARNING: Backward-incompatibility!\n  Parsing of the first argument in ifeq/ifneq with () has been cleaned up.\n  When locating the separating \",\" any variable reference (single char as well\n  as using $() or ${}) is skipped.  However parentheses that are not part of\n  or contained in variable references will not be counted.  This means that\n  things like \"ifeq ((foo,bar),)\" are now syntax errors.  Use a variable to\n  hide the comma if needed: \"COMMA = ,\" / \"ifeq ((foo$(COMMA)bar),)\".\n  See https://savannah.gnu.org/bugs/index.php?64402\n\n* WARNING: Backward-incompatibility!\n  If -e is given all environment variables will now have an origin of\n  \"environment override\" even if they are not otherwise set in the makefile.\n  See https://savannah.gnu.org/bugs/index.php?64803\n\n* WARNING: Backward-incompatibility!\n  The behavior of appending to pattern-specific variables has been clarified\n  when combined with command-line settings or -e overrides.\n  See https://savannah.gnu.org/bugs/index.php?64822\n\n* NOTE: Deprecated behavior.\n  The check in GNU Make 4.3 for suffix rules with prerequisites didn't check\n  single-suffix rules, only double-suffix rules.  Add the missing check.\n\n* New feature: Any assignment operator can be made conditional\n  GNU Make has long supported the conditional operator \"?=\" which creates a\n  recursive variable set to a value if and only if the variable is not already\n  defined.  In this release, the \"?\" can precede any assignment operator to\n  make it conditional.  For example, \"?:=\" creates a simply-expanded variable\n  and expands the right-hand side if and only if the variable is not already\n  defined.  The constructs \"?::=\", \"?:::=\", and \"?!=\" also behave as expected.\n\n* New feature: Unload function for loaded objects\n  When a loaded object needs to be unloaded by GNU Make, it will invoke an\n  unload function (if one is defined) beforehand that allows the object to\n  perform cleanup operations.\n  Original idea and implementation: Dmitry Goncharov <dgoncharov@users.sf.net>\n\n* New feature: Makefile warning reporting control\n  A new option \"--warn\" controls reporting of warnings for makefiles.  Actions\n  can be set to \"ignore\", \"warn\", or \"error\".  Two new warnings are reported:\n  assigning to invalid variable names, and referencing invalid variable names\n  (both set to \"warn\" by default), in addition to the existing warning for\n  undefined variables (defaults to \"ignore\"). \"--warn-undefined-variables\" is\n  deprecated, and is translated to \"--warn=undefined-vars\" internally.\n\n* New feature: Control warnings with the .WARNINGS variable\n  In addition to --warn from the command line, which takes effect for make\n  invoked recursively, warnings can be controlled only for the current\n  instance of make using the .WARNINGS variable.\n\n* New feature: Printing targets defined by the makefile\n  A new option \"--print-targets\" will print all explicit, non-special targets\n  defined in the makefiles, one per line, then exit with success.  No recipes\n  are invoked and no makefiles are re-built.\n\n* Warnings for detecting circular dependencies are controllable via warning\n  reporting, with the name \"circular-dep\".\n\n* 'make --print-data-base' (or 'make -p') now outputs time of day\n  using the same form as for file timestamps, e.g., \"2023-05-10\n  10:43:57.570558743\".  Previously it used the form \"Wed May 10\n  10:43:57 2023\", which has less detail and is harder to compare.\n\n* Conditional statements starting with the recipe prefix were sometimes\n  interpreted in previous versions.  As per the documentation, lines starting\n  with the recipe prefix are now never considered conditional statements.\n\n* Tests in the regression test suite now are run in their own directory to\n  avoid cross-contamination and allow cleanup if the tests are interrupted.\n  More information is printed about failing tests.\n\n\f\nVersion 4.4.1 (26 Feb 2023)\n\nThis release is primarily a bug-fix release.\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=110&set=custom\n\n* WARNING: Backward-incompatibility!\n  In previous releases it was not well-defined when updates to MAKEFLAGS made\n  inside a makefile would be visible.  This release ensures they are visible\n  immediately, even when invoking $(shell ...) functions.  Also, command line\n  variable assignments are now always present in MAKEFLAGS, even when parsing\n  makefiles.\n  Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>\n\n* New feature: Parallel builds of archives\n  Previously it was not possible to use parallel builds with archives.  It is\n  still not possible using the built-in rules, however you can now override\n  the built-in rules with a slightly different set of rules and use parallel\n  builds with archive creation.  See the \"Dangers When Using Archives\" section\n  of the GNU Make manual, and https://savannah.gnu.org/bugs/index.php?14927\n\n* Previously target-specific variables would inherit their \"export\" capability\n  from parent target-specific variables even if they were marked private.  Now\n  private parent target-specific variables have no affect.  For more details\n  see https://savannah.gnu.org/bugs/index.php?61463\n\n* Disable FIFO jobserver on GNU/Hurd and Cygwin\n  Experimentation shows that the new FIFO-based jobserver doesn't work well on\n  GNU/Hurd or Cygwin: revert these systems to use the pipe-based jobserver.\n\n* Updates to allow building on OS/2\n  Provided by KO Myung-Hun <komh78@gmail.com>\n\n* New platform: GNU Make is supported on z/OS\n  Thanks to Igor Todorovski <itodorov@ca.ibm.com> for the patches and testing\n  assistance.\n\n\f\nVersion 4.4 (31 Oct 2022)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&set=custom\n\n* WARNING: Deprecation!\n  The following systems are deprecated in this release:\n    - OS/2 (EMX)\n    - AmigaOS\n    - Xenix\n    - Cray\n  In the NEXT release of GNU Make, support for these systems will be removed.\n  If you want to see them continue to be supported, contact <bug-make@gnu.org>.\n\n* WARNING: Future backward-incompatibility!\n  In the NEXT release of GNU Make, pattern rules will implement the same\n  behavior change for multiple targets as explicit grouped targets, below: if\n  any target of the rule is needed by the build, the recipe will be invoked if\n  any target of the rule is missing or out of date.  During testing some\n  makefiles were found to contain pattern rules that do not build all targets;\n  this can cause issues so we are delaying this change for one release cycle\n  to allow these makefiles to be updated.  GNU Make shows a warning if it\n  detects this situation: \"pattern recipe did not update peer target\".\n\n* WARNING: Backward-incompatibility!\n  GNU Make now uses temporary files in more situations than previous releases.\n  If your build system sets TMPDIR (or TMP or TEMP on Windows) and deletes the\n  contents during the build, or uses restrictive permissions, this may cause\n  problems.  You can choose an alternative temporary directory only for use by\n  GNU Make by setting the new MAKE_TMPDIR environment variable before invoking\n  make.  Note that this value CANNOT be set inside the makefile, since make\n  needs to find its temporary directory before the makefiles are parsed.\n\n* WARNING: Backward-incompatibility!\n  Previously each target in a explicit grouped target rule was considered\n  individually: if the targets needed by the build were not out of date the\n  recipe was not run even if other targets in the group were out of date.  Now\n  if any of the grouped targets are needed by the build, then if any of the\n  grouped targets are out of date the recipe is run and all targets in the\n  group are considered updated.\n\n* WARNING: Backward-incompatibility!\n  Previously if --no-print-directory was seen anywhere in the environment or\n  command line it would take precedence over any --print-directory.  Now, the\n  last setting of directory printing options seen will be used, so a command\n  line such as \"--no-print-directory -w\" _will_ show directory entry/exits.\n\n* WARNING: Backward-incompatibility!\n  Previously the order in which makefiles were remade was not explicitly\n  stated, but it was (roughly) the inverse of the order in which they were\n  processed by make.  In this release, the order in which makefiles are\n  rebuilt is the same order in which make processed them, and this is defined\n  to be true in the GNU Make manual.\n\n* WARNING: Backward-incompatibility!\n  Previously only simple (one-letter) options were added to the MAKEFLAGS\n  variable that was visible while parsing makefiles.  Now, all options are\n  available in MAKEFLAGS.  If you want to check MAKEFLAGS for a one-letter\n  option, expanding \"$(firstword -$(MAKEFLAGS))\" is a reliable way to return\n  the set of one-letter options which can be examined via findstring, etc.\n\n* WARNING: Backward-incompatibility!\n  Previously makefile variables marked as export were not exported to commands\n  started by the $(shell ...) function.  Now, all exported variables are\n  exported to $(shell ...).  If this leads to recursion during expansion, then\n  for backward-compatibility the value from the original environment is used.\n  To detect this change search for 'shell-export' in the .FEATURES variable.\n\n* WARNING: New build requirement\n  GNU Make utilizes facilities from GNU Gnulib: Gnulib requires certain C99\n  features in the C compiler and so these features are required by GNU Make:\n  https://www.gnu.org/software/gnulib/manual/html_node/C99-features-assumed.html\n  The configure script should verify the compiler has these features.\n\n* New feature: The .WAIT special target\n  If the .WAIT target appears between two prerequisites of a target, then\n  GNU Make will wait for all of the targets to the left of .WAIT in the list\n  to complete before starting any of the targets to the right of .WAIT.\n  This feature is available in some other versions of make, and it will be\n  required by an upcoming version of the POSIX standard for make.\n  Different patches were made by Alexey Neyman <alex.neyman@auriga.ru> (2005)\n  and Steffen Nurpmeso <steffen@sdaoden.eu> (2020) that were useful but the\n  result is a different implementation (closer to Alexey's idea).\n\n* New feature: .NOTPARALLEL accepts prerequisites\n  If the .NOTPARALLEL special target has prerequisites then all prerequisites\n  of those targets will be run serially (as if .WAIT was specified between\n  each prerequisite).\n\n* New feature: The .NOTINTERMEDIATE special target\n  .NOTINTERMEDIATE disables intermediate behavior for specific files, for all\n  files built using a pattern, or for the entire makefile.\n  Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>\n\n* New feature: The $(let ...) function\n  This function allows user-defined functions to define a set of local\n  variables: values can be assigned to these variables from within the\n  user-defined function and they will not impact global variable assignments.\n  Implementation provided by Jouke Witteveen <j.witteveen@gmail.com>\n\n* New feature: The $(intcmp ...) function\n  This function allows conditional evaluation controlled by a numerical\n  comparison.\n  Implementation provided by Jouke Witteveen <j.witteveen@gmail.com>\n\n* New feature: Improved support for -l / --load-average\n  On systems that provide /proc/loadavg (Linux), GNU Make will use it to\n  determine the number of runnable jobs and use this as the current load,\n  avoiding the need for heuristics.\n  Implementation provided by Sven C. Dack <sdack@gmx.com>\n\n* New feature: The --shuffle command line option\n  This option reorders goals and prerequisites to simulate non-determinism\n  that may be seen using parallel build.  Shuffle mode allows a form of \"fuzz\n  testing\" of parallel builds to verify that all prerequisites are correctly\n  described in the makefile.\n  Implementation provided by Sergei Trofimovich <siarheit@google.com>\n\n* New feature: The --jobserver-style command line option and named pipes\n  A new jobserver method is used on systems where mkfifo(3) is supported.\n  This solves a number of obscure issues related to using the jobserver\n  and recursive invocations of GNU Make.  This change means that sub-makes\n  will connect to the jobserver even if they are not marked as recursive.\n  It also means that other tools that want to participate in the jobserver\n  will need to be enhanced as described in the GNU Make manual.\n  You can force GNU Make to use the simple pipe-based jobserver (perhaps if\n  you are integrating with other tools or older versions of GNU Make) by\n  adding the '--jobserver-style=pipe' option to the command line of the\n  top-level invocation of GNU Make, or via MAKEFLAGS or GNUMAKEFLAGS.\n  To detect this change search for 'jobserver-fifo' in the .FEATURES variable.\n\n* Some POSIX systems (*BSD) do not allow locks to be taken on pipes, which\n  caused the output sync feature to not work properly there.  Also multiple\n  invocations of make redirecting to the same output file (e.g., /dev/null)\n  would cause hangs.  Instead of locking stdout (which does have some useful\n  performance characteristics, but is not portable) create a temporary file\n  and lock that.  Windows continues to use a mutex as before.\n\n* GNU Make has sometimes chosen unexpected, and sub-optimal, chains of\n  implicit rules due to the definition of \"ought to exist\" in the implicit\n  rule search algorithm, which considered any prerequisite mentioned in the\n  makefile as \"ought to exist\".  This algorithm has been modified to prefer\n  prerequisites mentioned explicitly in the target being built and only if\n  that results in no matching rule, will GNU Make consider prerequisites\n  mentioned in other targets as \"ought to exist\".\n  Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>\n\n* GNU Make was performing secondary expansion of all targets, even targets\n  which didn't need to be considered during the build.  In this release\n  only targets which are considered will be secondarily expanded.\n  Implementation provided by Dmitry Goncharov <dgoncharov@users.sf.net>\n\n* If the MAKEFLAGS variable is modified in a makefile, it will be re-parsed\n  immediately rather than after all makefiles have been read.  Note that\n  although all options are parsed immediately, some special effects won't\n  appear until after all makefiles are read.\n\n* The -I option accepts an argument \"-\" (e.g., \"-I-\") which means \"reset the\n  list of search directories to empty\".  Among other things this can be used\n  to prevent GNU Make from searching in its default list of directories.\n\n* New debug option \"print\" will show the recipe to be run, even when silent\n  mode is set, and new debug option \"why\" will show why a target is rebuilt\n  (which prerequisites caused the target to be considered out of date).\n  Implementation provided by David Boyce <David.S.Boyce@gmail.com>\n\n* The existing --trace option is made equivalent to --debug=print,why\n\n* Target-specific variables can now be marked \"unexport\".\n\n* Exporting / unexporting target-specific variables is handled correctly, so\n  that the attribute of the most specific variable setting is used.\n\n* Special targets like .POSIX are detected upon definition, ensuring that any\n  change in behavior takes effect immediately, before the next line is parsed.\n\n* When the pipe-based jobserver is enabled and GNU Make decides it is invoking\n  a non-make sub-process and closes the jobserver pipes, it will now add a new\n  option to the MAKEFLAGS environment variable that disables the jobserver.\n  This prevents sub-processes that invoke make from accidentally using other\n  open file descriptors as jobserver pipes.  For more information see\n  https://savannah.gnu.org/bugs/?57242 and https://savannah.gnu.org/bugs/?62397\n\n* A long-standing issue with the directory cache has been resolved: changes\n  made as a side-effect of some other target's recipe are now noticed as\n  expected.\n\n* GNU Make can now be built for MS-Windows using the Tiny C tcc compiler.\n  Port provided by Christian Jullien <eligis@orange.fr>\n\n\f\nVersion 4.3 (19 Jan 2020)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=108&set=custom\n\n* WARNING: Backward-incompatibility!\n  Number signs (#) appearing inside a macro reference or function invocation\n  no longer introduce comments and should not be escaped with backslashes:\n  thus a call such as:\n    foo := $(shell echo '#')\n  is legal.  Previously the number sign needed to be escaped, for example:\n    foo := $(shell echo '\\#')\n  Now this latter will resolve to \"\\#\".  If you want to write makefiles\n  portable to both versions, assign the number sign to a variable:\n    H := \\#\n    foo := $(shell echo '$H')\n  This was claimed to be fixed in 3.81, but wasn't, for some reason.\n  To detect this change search for 'nocomment' in the .FEATURES variable.\n\n* WARNING: Backward-incompatibility!\n  Previously appending using '+=' to an empty variable would result in a value\n  starting with a space.  Now the initial space is only added if the variable\n  already contains some value.  Similarly, appending an empty string does not\n  add a trailing space.\n\n* WARNING: Backward-incompatibility!\n  Previously using the .SILENT pseudo-target in a makefile would force all\n  sub-makes to be invoked with the '-s' option, effectively making all\n  sub-makes silent as well.  In this release .SILENT only affects the current\n  invocation of make.  A side-effect of this is that .SILENT will no longer\n  enable the --no-print-directory option, which using -s will do.\n\n* NOTE: Deprecated behavior.\n  Contrary to the documentation, suffix rules with prerequisites are being\n  treated BOTH as simple targets AND as pattern rules.  Further, the\n  prerequisites are ignored by the pattern rules.  POSIX specifies that in\n  order to be a suffix rule there can be no prerequisites defined.  In this\n  release if POSIX mode is enabled then rules with prerequisites cannot be\n  suffix rules.  If POSIX mode is not enabled then the previous behavior is\n  preserved (a pattern rule with no extra prerequisites is created) AND a\n  warning about this behavior is generated:\n    warning: ignoring prerequisites on suffix rule definition\n  The POSIX behavior will be adopted as the only behavior in a future release\n  of GNU Make so please resolve any warnings.\n\n* New feature: Grouped explicit targets\n  Pattern rules have always had the ability to generate multiple targets with\n  a single invocation of the recipe.  It's now possible to declare that an\n  explicit rule generates multiple targets with a single invocation.  To use\n  this, replace the \":\" token with \"&:\" in the rule.  To detect this feature\n  search for 'grouped-target' in the .FEATURES special variable.\n  Implementation contributed by Kaz Kylheku <kaz@kylheku.com>\n\n* New feature: .EXTRA_PREREQS variable\n  Words in this variable are considered prerequisites of targets but they are\n  not added to any of the automatic variable values when expanding the\n  recipe.  This variable can either be global (applies to all targets) or\n  a target-specific variable.  To detect this feature search for 'extra-prereqs'\n  in the .FEATURES special variable.\n  Implementation contributed by Christof Warlich <cwarlich@gmx.de>\n\n* Makefiles can now specify the '-j' option in their MAKEFLAGS variable and\n  this will cause make to enable that parallelism mode.\n\n* GNU Make will now use posix_spawn() on systems where it is available.\n  If you prefer to use fork/exec even on systems where posix_spawn() is\n  present, you can use the --disable-posix-spawn option to configure.\n  Implementation contributed by Aron Barath <baratharon@caesar.elte.hu>\n\n* Error messages printed when invoking non-existent commands have been cleaned\n  up and made consistent.\n\n* The previous limit of 63 jobs under -jN on MS-Windows is now\n  increased to 4095.  That limit includes the subprocess started by\n  the $(shell) function.\n\n* A new option --no-silent has been added, that cancels the effect of the\n  -s/--silent/--quiet flag.\n\n* A new option -E has been added as a short alias for --eval.\n\n* All wildcard expansion within GNU Make, including $(wildcard ...), will sort\n  the results.  See https://savannah.gnu.org/bugs/index.php?52076\n\n* Interoperate with newer GNU libc and musl C runtime libraries.\n\n* Performance improvements provided by Paolo Bonzini <pbonzini@redhat.com>\n\nGNU Make Developer News\n\n* Import the GNU standard bootstrap script to replace the hand-rolled\n  \"make update\" method for building code from a GNU Make Git repository.\n\n* Rework the source distribution to move source files into the src/*\n  subdirectory.  This aligns with modern best practices in GNU.\n\n* Replace local portability code with Gnulib content.  Unfortunately due to a\n  problem with Gnulib support for getloadavg, this forces a requirement on\n  Automake 1.16 or above in order to build from Git.  See README.git.\n\n\f\nVersion 4.2.1 (10 Jun 2016)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=107&set=custom\n\nThis release is a bug-fix release.\n\n\f\nVersion 4.2 (22 May 2016)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=106&set=custom\n\n* New variable: $(.SHELLSTATUS) is set to the exit status of the last != or\n  $(shell ...) function invoked in this instance of make.  This will be \"0\" if\n  successful or not \"0\" if not successful.  The variable value is unset if no\n  != or $(shell ...) function has been invoked.\n\n* The $(file ...) function can now read from a file with $(file <FILE).\n  The function is expanded to the contents of the file.  The contents are\n  expanded verbatim except that the final newline, if any, is stripped.\n\n* The makefile line numbers shown by GNU Make now point directly to the\n  specific line in the recipe where the failure or warning occurred.\n  Sample changes suggested by Brian Vandenberg <phantall@gmail.com>\n\n* The interface to GNU Make's \"jobserver\" is stable as documented in the\n  manual, for tools which may want to access it.\n\n  WARNING: Backward-incompatibility! The internal-only command line option\n  --jobserver-fds has been renamed for publishing, to --jobserver-auth.\n\n* The amount of parallelism can be determined by querying MAKEFLAGS, even when\n  the job server is enabled (previously MAKEFLAGS would always contain only\n  \"-j\", with no number, when job server was enabled).\n\n* VMS-specific changes:\n\n  * Perl test harness now works.\n\n  * Full support for converting Unix exit status codes to VMS exit status\n    codes.  BACKWARD INCOMPATIBILITY Notice: On a child failure the VMS exit\n    code is now the encoded Unix exit status that Make usually generates, not\n    the VMS exit status of the child.\n\n\f\nVersion 4.1 (05 Oct 2014)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=105&set=custom\n\n* New variables: $(MAKE_TERMOUT) and $(MAKE_TERMERR) are set to non-empty\n  values if stdout or stderr, respectively, are believed to be writing to a\n  terminal.  These variables are exported by default.\n\n* Allow a no-text-argument form of the $(file ...) function.  Without a text\n  argument nothing is written to the file: it is simply opened in the\n  requested mode, then closed again.\n\n* Change the fatal error for mixed explicit and implicit rules, that was\n  introduced in GNU Make 3.82, to a non-fatal error.  However, this syntax is\n  still deprecated and may return to being illegal in a future version of GNU\n  make.  Makefiles that rely on this syntax should be fixed.\n  See https://savannah.gnu.org/bugs/?33034\n\n* VMS-specific changes:\n\n  * Support for library files added, including support for using the GNV ar\n    utility.\n\n  * Partial support for properly encoding Unix exit status codes into VMS exit\n    status codes.\n\n    WARNING: Backward-incompatibility! These are different exit status codes\n    than Make exited with in the past.\n\n  * Macros to hold the current make command are set up to translate the\n    argv[0] string to a VMS format path name and prefix it with \"MCR \" so that\n    the macro has a space in it.\n\n    WARNING: Backward-incompatibility!  This may break complex makefiles that\n    do processing on those macros.  This is unlikely because so much in that\n    area was not and is still not currently working on VMS, it is unlikely to\n    find such a complex makefile, so this is more likely to impact\n    construction of a future makefile.\n\n  * A command file is always used to run the commands for a recipe.\n\n    WARNING: Backward-incompatibility!  Running the make self tests has\n    exposed that there are significant differences in behavior when running\n    with the command file mode.  It is unknown if this will be noticed by most\n    existing VMS makefiles.\n\f\nVersion 4.0 (09 Oct 2013)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set=custom\n\n* WARNING: Backward-incompatibility!\n  If .POSIX is specified, then make adheres to the POSIX backslash/newline\n  handling requirements, which introduces the following changes to the\n  standard backslash/newline handling in non-recipe lines:\n  * Any trailing space before the backslash is preserved\n  * Each backslash/newline (plus subsequent whitespace) is converted to a\n    single space\n\n* New feature: GNU Guile integration\n  This version of GNU Make can be compiled with GNU Guile integration.\n  GNU Guile serves as an embedded extension language for make.\n  See the \"Guile Function\" section in the GNU Make manual for details.\n  Currently GNU Guile 1.8 and 2.0+ are supported.  In Guile 1.8 there is no\n  support for internationalized character sets.  In Guile 2.0+, scripts can be\n  encoded in UTF-8.\n\n* New command line option: --output-sync (-O) enables grouping of output by\n  target or by recursive make.  This is useful during parallel builds to avoid\n  mixing output from different jobs together giving hard-to-understand\n  results.  Original implementation by David Boyce <dsb@boyski.com>.\n  Reworked and enhanced by Frank Heckenbach <f.heckenbach@fh-soft.de>.\n  Windows support by Eli Zaretskii <eliz@gnu.org>.\n\n* New command line option: --trace enables tracing of targets.  When enabled\n  the recipe to be invoked is printed even if it would otherwise be suppressed\n  by .SILENT or a \"@\" prefix character.  Also before each recipe is run the\n  makefile name and linenumber where it was defined are shown as well as the\n  prerequisites that caused the target to be considered out of date.\n\n* New command line option argument: --debug now accepts a \"n\" (none) flag\n  which disables all debugging settings that are currently enabled.\n\n* New feature: The \"job server\" capability is now supported on Windows.\n  Implementation contributed by Troy Runkel <Troy.Runkel@mathworks.com>\n\n* New feature: The .ONESHELL capability is now supported on Windows.  Support\n  added by Eli Zaretskii <eliz@gnu.org>.\n\n* New feature: \"!=\" shell assignment operator as an alternative to the\n  $(shell ...) function.  Implemented for compatibility with BSD makefiles.\n  Note there are subtle differences between \"!=\" and $(shell ...).  See the\n  description in the GNU Make manual.\n  WARNING: Backward-incompatibility!\n  Variables ending in \"!\" previously defined as \"variable!= value\" will now be\n  interpreted as shell assignment.  Change your assignment to add whitespace\n  between the \"!\" and \"=\": \"variable! = value\"\n\n* New feature: \"::=\" simple assignment operator as defined by POSIX in 2012.\n  This operator has identical functionality to \":=\" in GNU Make, but will be\n  portable to any implementation of make conforming to a sufficiently new\n  version of POSIX (see https://austingroupbugs.net/view.php?id=330).  It is\n  not necessary to define the .POSIX target to access this operator.\n\n* New feature: Loadable objects\n  This version of GNU Make contains a \"technology preview\": the ability to\n  load dynamic objects into the make runtime.  These objects can be created by\n  the user and can add extended functionality, usable by makefiles.\n\n* New function: $(file ...) writes to a file.\n\n* New variable: $(GNUMAKEFLAGS) will be parsed for make flags, just like\n  MAKEFLAGS is.  It can be set in the environment or the makefile, containing\n  GNU Make-specific flags to allow your makefile to be portable to other\n  versions of make.  Once this variable is parsed, GNU Make will set it to the\n  empty string so that flags will not be duplicated on recursion.\n\n* New variable: `MAKE_HOST' gives the name of the host architecture\n  make was compiled for.  This is the same value you see after 'Built for'\n  when running 'make --version'.\n\n* Behavior of MAKEFLAGS and MFLAGS is more rigorously defined.  All simple\n  flags are grouped together in the first word of MAKEFLAGS.  No options that\n  accept arguments appear in the first word.  If no simple flags are present\n  MAKEFLAGS begins with a space.  Flags with both short and long versions\n  always use the short versions in MAKEFLAGS.  Flags are listed in\n  alphabetical order using ASCII ordering.  MFLAGS never begins with \"- \".\n\n* Setting the -r and -R options in MAKEFLAGS inside a makefile now works as\n  expected, removing all built-in rules and variables, respectively.\n\n* If a recipe fails, the makefile name and linenumber of the recipe are shown.\n\n* A .RECIPEPREFIX setting is remembered per-recipe and variables expanded\n  in that recipe also use that recipe prefix setting.\n\n* In -p output, .RECIPEPREFIX settings are shown and all target-specific\n  variables are output as if in a makefile, instead of as comments.\n\n* On MS-Windows, recipes that use \"..\" quoting will no longer force\n  invocation of commands via temporary batch files and stock Windows\n  shells, they will be short-circuited and invoked directly.  (In\n  other words, \" is no longer a special character for stock Windows\n  shells.)  This avoids hitting shell limits for command length when\n  quotes are used, but nothing else in the command requires the shell.\n  This change could potentially mean some minor incompatibilities in\n  behavior when the recipe uses quoted string on shell command lines.\n\n\f\nVersion 3.82 (28 Jul 2010)\n\nA complete list of bugs fixed in this version is available here:\n\nhttps://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&set=custom\n\n* Compiling GNU Make now requires a conforming ISO C 1989 compiler and\n  standard runtime library.\n\n* WARNING: Backward-incompatibility!\n  The POSIX standard for make was changed in the 2008 version in a\n  fundamentally incompatible way: make is required to invoke the shell as if\n  the '-e' flag were provided.  Because this would break many makefiles that\n  have been written to conform to the original text of the standard, the\n  default behavior of GNU Make remains to invoke the shell with simply '-c'.\n  However, any makefile specifying the .POSIX special target will follow the\n  new POSIX standard and pass '-e' to the shell.  See also .SHELLFLAGS\n  below.\n\n* WARNING: Backward-incompatibility!\n  The '$?' variable now contains all prerequisites that caused the target to\n  be considered out of date, even if they do not exist (previously only\n  existing targets were provided in $?).\n\n* WARNING: Backward-incompatibility!\n  Wildcards were not documented as returning sorted values, but the results\n  have been sorted up until this release..  If your makefiles require sorted\n  results from wildcard expansions, use the $(sort ...)  function to request\n  it explicitly.\n\n* WARNING: Backward-incompatibility!\n  As a result of parser enhancements, three backward-compatibility issues\n  exist: first, a prerequisite containing an \"=\" cannot be escaped with a\n  backslash any longer.  You must create a variable containing an \"=\" and\n  use that variable in the prerequisite.  Second, variable names can no\n  longer contain whitespace, unless you put the whitespace in a variable and\n  use the variable.  Third, in previous versions of make it was sometimes\n  not flagged as an error for explicit and pattern targets to appear in the\n  same rule.  Now this is always reported as an error.\n\n* WARNING: Backward-incompatibility!\n  The pattern-specific variables and pattern rules are now applied in the\n  shortest stem first order instead of the definition order (variables\n  and rules with the same stem length are still applied in the definition\n  order). This produces the usually-desired behavior where more specific\n  patterns are preferred. To detect this feature search for 'shortest-stem'\n  in the .FEATURES special variable.\n\n* WARNING: Backward-incompatibility!\n  The library search behavior has changed to be compatible with the standard\n  linker behavior. Prior to this version for prerequisites specified using\n  the -lfoo syntax make first searched for libfoo.so in the current\n  directory, vpath directories, and system directories. If that didn't yield\n  a match, make then searched for libfoo.a in these directories. Starting\n  with this version make searches first for libfoo.so and then for libfoo.a\n  in each of these directories in order.\n\n* New command line option: --eval=STRING causes STRING to be evaluated as\n  makefile syntax (akin to using the $(eval ...) function).  The evaluation\n  is performed after all default rules and variables are defined, but before\n  any makefiles are read.\n\n* New special variable: .RECIPEPREFIX allows you to reset the recipe\n  introduction character from the default (TAB) to something else.  The\n  first character of this variable value is the new recipe introduction\n  character.  If the variable is set to the empty string, TAB is used again.\n  It can be set and reset at will; recipes will use the value active when\n  they were first parsed.  To detect this feature check the value of\n  $(.RECIPEPREFIX).\n\n* New special variable: .SHELLFLAGS allows you to change the options passed\n  to the shell when it invokes recipes.  By default the value will be \"-c\"\n  (or \"-ec\" if .POSIX is set).\n\n* New special target: .ONESHELL instructs make to invoke a single instance\n  of the shell and provide it with the entire recipe, regardless of how many\n  lines it contains.  As a special feature to allow more straightforward\n  conversion of makefiles to use .ONESHELL, any recipe line control\n  characters ('@', '+', or '-') will be removed from the second and\n  subsequent recipe lines.  This happens _only_ if the SHELL value is deemed\n  to be a standard POSIX-style shell.  If not, then no interior line control\n  characters are removed (as they may be part of the scripting language used\n  with the alternate SHELL).\n\n* New variable modifier 'private': prefixing a variable assignment with the\n  modifier 'private' suppresses inheritance of that variable by\n  prerequisites.  This is most useful for target- and pattern-specific\n  variables.\n\n* New make directive: 'undefine' allows you to undefine a variable so that\n  it appears as if it was never set. Both $(flavor) and $(origin) functions\n  will return 'undefined' for such a variable. To detect this feature search\n  for 'undefine' in the .FEATURES special variable.\n\n* The parser for variable assignments has been enhanced to allow multiple\n  modifiers ('export', 'override', 'private') on the same line as variables,\n  including define/endef variables, and in any order.  Also, it is possible\n  to create variables and targets named as these modifiers.\n\n* The 'define' make directive now allows a variable assignment operator\n  after the variable name, to allow for simple, conditional, or appending\n  multi-line variable assignment.\n\n* VMS-specific changes:\n\n  * Michael Gehre (at VISTEC-SEMI dot COM) supplied a fix for a problem with\n    timestamps of object modules in OLBs. The timestamps were not correctly\n    adjusted to GMT based time, if the local VMS time was using a daylight\n    saving algorithm and if daylight saving was switched off.\n\n  * John Eisenbraun (at HP dot COM) supplied fixes and and an enhancement to\n    append output redirection in action lines.\n\n  * Rework of ctrl+c and ctrl+y handling.\n\n  * Fix a problem with cached strings, which showed on case-insensitive file\n    systems.\n\n  * Build fixes for const-ified code in VMS specific sources.\n\n  * A note on appending the redirected output. With this change, a simple\n    mechanism is implemented to make \">>\" work in action lines. In VMS\n    there is no simple feature like \">>\" to have DCL command or program\n    output redirected and appended to a file. GNU Make for VMS already\n    implements the redirection of output. If such a redirection is detected,\n    an \">\" on the action line, GNU Make creates a DCL command procedure to\n    execute the action and to redirect its output. Based on that, now \">>\"\n    is also recognized and a similar but different command procedure is\n    created to implement the append. The main idea here is to create a\n    temporary file which collects the output and which is appended to the\n    wanted output file. Then the temporary file is deleted. This is all done\n    in the command procedure to keep changes in make small and simple. This\n    obviously has some limitations but it seems good enough compared with\n    the current \">\" implementation. (And in my opinion, redirection is not\n    really what GNU Make has to do.) With this approach, it may happen that\n    the temporary file is not yet appended and is left in SYS$SCRATCH.\n    The temporary file names look like \"CMDxxxxx.\". Any time the created\n    command procedure can not complete, this happens. Pressing Ctrl+Y to\n    abort make is one case. In case of Ctrl+Y the associated command\n    procedure is left in SYS$SCRATCH as well. Its name is CMDxxxxx.COM.\n\n  * Change in the Ctrl+Y handling. The CtrlY handler now uses $delprc to\n    delete all children. This way also actions with DCL commands will be\n    stopped. As before the CtrlY handler then sends SIGQUIT to itself,\n    which is handled in common code.\n\n  * Change in deleteing temporary command files. Temporary command files\n    are now deleted in the vms child termination handler. That deletes\n    them even if a Ctrl+C was pressed.\n\n  * The behavior of pressing Ctrl+C is not changed. It still has only an\n    effect, after the current action is terminated. If that doesn't happen\n    or takes too long, Ctrl+Y should be used instead.\n\n\f\nVersion 3.81 (01 Apr 2006)\n\n* GNU Make is ported to OS/2.\n\n* GNU Make is ported to MinGW.  The MinGW build is only supported by\n  the build_w32.bat batch file; see the file README.W32 for more\n  details.\n\n* WARNING: Future backward-incompatibility!\n  Up to and including this release, the '$?' variable does not contain\n  any prerequisite that does not exist, even though that prerequisite\n  might have caused the target to rebuild.  Starting with the _next_\n  release of GNU Make, '$?' will contain all prerequisites that caused\n  the target to be considered out of date.\n  See https://savannah.gnu.org/bugs/?16051\n\n* WARNING: Backward-incompatibility!\n  GNU Make now implements a generic \"second expansion\" feature on the\n  prerequisites of both explicit and implicit (pattern) rules.  In order\n  to enable this feature, the special target '.SECONDEXPANSION' must be\n  defined before the first target which takes advantage of it.  If this\n  feature is enabled then after all rules have been parsed the\n  prerequisites are expanded again, this time with all the automatic\n  variables in scope.  This means that in addition to using standard\n  SysV $$@ in prerequisites lists, you can also use complex functions\n  such as $$(notdir $$@) etc.  This behavior applies to implicit rules,\n  as well, where the second expansion occurs when the rule is matched.\n  However, this means that when '.SECONDEXPANSION' is enabled you must\n  double-quote any \"$\" in your filenames; instead of \"foo: boo$$bar\" you\n  now must write \"foo: foo$$$$bar\".  Note that the SysV $$@ etc. feature,\n  which used to be available by default, is now ONLY available when the\n  .SECONDEXPANSION target is defined.  If your makefiles take advantage\n  of this SysV feature you will need to update them.\n\n* WARNING: Backward-incompatibility!\n  In order to comply with POSIX, the way in which GNU Make processes\n  backslash-newline sequences in recipes has changed.  If your makefiles\n  use backslash-newline sequences inside of single-quoted strings in\n  recipes you will be impacted by this change.  See the GNU Make manual\n  subsection \"Splitting Recipe Lines\" (node \"Splitting Lines\"), in\n  section \"Recipe Syntax\", chapter \"Writing Recipe in Rules\", for\n  details.\n\n* WARNING: Backward-incompatibility!\n  Some previous versions of GNU Make had a bug where \"#\" in a function\n  invocation such as $(shell ...) was treated as a make comment.  A\n  workaround was to escape these with backslashes.  This bug has been\n  fixed: if your makefile uses \"\\#\" in a function invocation the\n  backslash is now preserved, so you'll need to remove it.\n\n* New command line option: -L (--check-symlink-times).  On systems that\n  support symbolic links, if this option is given then GNU Make will\n  use the most recent modification time of any symbolic links that are\n  used to resolve target files.  The default behavior remains as it\n  always has: use the modification time of the actual target file only.\n\n* The \"else\" conditional line can now be followed by any other valid\n  conditional on the same line: this does not increase the depth of the\n  conditional nesting, so only one \"endif\" is required to close the\n  conditional.\n\n* All pattern-specific variables that match a given target are now used\n  (previously only the first match was used).\n\n* Target-specific variables can be marked as exportable using the\n  \"export\" keyword.\n\n* In a recursive $(call ...) context, any extra arguments from the outer\n  call are now masked in the context of the inner call.\n\n* Implemented a solution for the \"thundering herd\" problem with \"-j -l\".\n  This version of GNU Make uses an algorithm suggested by Thomas Riedl\n  <thomas.riedl@siemens.com> to track the number of jobs started in the\n  last second and artificially adjust GNU Make's view of the system's\n  load average accordingly.\n\n* New special variables available in this release:\n   - .INCLUDE_DIRS: Expands to a list of directories that make searches\n     for included makefiles.\n   - .FEATURES: Contains a list of special features available in this\n     version of GNU Make.\n   - .DEFAULT_GOAL: Set the name of the default goal make will\n     use if no goals are provided on the command line.\n   - MAKE_RESTARTS: If set, then this is the number of times this\n     instance of make has been restarted (see \"How Makefiles Are Remade\"\n     in the manual).\n   - New automatic variable: $| (added in 3.80, actually): contains all\n     the order-only prerequisites defined for the target.\n\n* New functions available in this release:\n   - $(lastword ...) returns the last word in the list.  This gives\n     identical results as $(word $(words ...) ...), but is much faster.\n   - $(abspath ...) returns the absolute path (all \".\" and \"..\"\n     directories resolved, and any duplicate \"/\" characters removed) for\n     each path provided.\n   - $(realpath ...) returns the canonical pathname for each path\n     provided.  The canonical pathname is the absolute pathname, with\n     all symbolic links resolved as well.\n   - $(info ...) prints its arguments to stdout.  No makefile name or\n     line number info, etc. is printed.\n   - $(flavor ...) returns the flavor of a variable.\n   - $(or ...) provides a short-circuiting OR conditional: each argument\n     is expanded.  The first true (non-empty) argument is returned; no\n     further arguments are expanded.  Expands to empty if there are no\n     true arguments.\n   - $(and ...) provides a short-circuiting AND conditional: each\n     argument is expanded.  The first false (empty) argument is\n     returned; no further arguments are expanded.  Expands to the last\n     argument if all arguments are true.\n\n* Changes made for POSIX compatibility:\n   - Only touch targets (under -t) if they have a recipe.\n   - Setting the SHELL make variable does NOT change the value of the\n     SHELL environment variable given to programs invoked by make.  As\n     an enhancement to POSIX, if you export the make variable SHELL then\n     it will be set in the environment, just as before.\n\n* On MS Windows systems, explicitly setting SHELL to a pathname ending\n  in \"cmd\" or \"cmd.exe\" (case-insensitive) will force GNU Make to use\n  the DOS command interpreter in batch mode even if a UNIX-like shell\n  could be found on the system.\n\n* On VMS there is now support for case-sensitive filesystems such as ODS5.\n  See the README.VMS file for information.\n\n* Parallel builds (-jN) no longer require a working Bourne shell on\n  Windows platforms.  They work even with the stock Windows shells, such\n  as cmd.exe and command.com.\n\n* Updated to autoconf 2.59, automake 1.9.5, and gettext 0.14.1.  Users\n  should not be impacted.\n\n* New translations for Swedish, Chinese (simplified), Ukrainian,\n  Belarusian, Finnish, Kinyarwandan, and Irish.  Many updated\n  translations.\n\nA complete list of bugs fixed in this version is available here:\n\n  https://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=103\n\n\f\nVersion 3.80 (03 Oct 2002)\n\n* A new feature exists: order-only prerequisites.  These prerequisites\n  affect the order in which targets are built, but they do not impact\n  the rebuild/no-rebuild decision of their dependents.  That is to say,\n  they allow you to require target B be built before target A, without\n  requiring that target A will always be rebuilt if target B is updated.\n  Patch for this feature provided by Greg McGary <greg@mcgary.org>.\n\n* For compatibility with SysV make, GNU Make now supports the peculiar\n  syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.\n  This syntax is only valid within explicit and static pattern rules: it\n  cannot be used in implicit (suffix or pattern) rules.  Edouard G. Parmelan\n  <egp@free.fr> provided a patch implementing this feature; however, I\n  decided to implement it in a different way.\n\n* The argument to the \"ifdef\" conditional is now expanded before it's\n  tested, so it can be a constructed variable name.\n\n  Similarly, the arguments to \"export\" (when not used in a variable\n  definition context) and \"unexport\" are also now expanded.\n\n* A new function is defined: $(value ...).  The argument to this\n  function is the _name_ of a variable.  The result of the function is\n  the value of the variable, without having been expanded.\n\n* A new function is defined: $(eval ...).  The arguments to this\n  function should expand to makefile commands, which will then be\n  evaluated as if they had appeared in the makefile.  In combination\n  with define/endef multiline variable definitions this is an extremely\n  powerful capability.  The $(value ...) function is also sometimes\n  useful here.\n\n* A new built-in variable is defined, $(MAKEFILE_LIST).  It contains a\n  list of each makefile GNU Make has read, or started to read, in the\n  order in which they were encountered.  So, the last filename in the\n  list when a makefile is just being read (before any includes) is the\n  name of the current makefile.\n\n* A new built-in variable is defined: $(.VARIABLES).  When it is\n  expanded it returns a complete list of variable names defined by all\n  makefiles at that moment.\n\n* A new command line option is defined, -B or --always-make.  If\n  specified GNU Make will consider all targets out-of-date even if they\n  would otherwise not be.\n\n* The arguments to $(call ...) functions were being stored in $1, $2,\n  etc. as recursive variables, even though they are fully expanded\n  before assignment.  This means that escaped dollar signs ($$ etc.)\n  were not behaving properly.  Now the arguments are stored as simple\n  variables.  This may mean that if you added extra escaping to your\n  $(call ...) function arguments you will need to undo it now.\n\n* The variable invoked by $(call ...) can now be recursive: unlike other\n  variables it can reference itself and this will not produce an error\n  when it is used as the first argument to $(call ...) (but only then).\n\n* New pseudo-target .LOW_RESOLUTION_TIME, superseding the configure\n  option --disable-nsec-timestamps.  You might need this if your build\n  process depends on tools like \"cp -p\" preserving time stamps, since\n  \"cp -p\" (right now) doesn't preserve the subsecond portion of a time\n  stamp.\n\n* Updated translations for French, Galician, German, Japanese, Korean,\n  and Russian.  New translations for Croatian, Danish, Hebrew, and\n  Turkish.\n\n* Updated internationalization support to Gettext 0.11.5.\n  GNU Make now uses Gettext's \"external\" feature, and does not include\n  any internationalization code itself.  Configure will search your\n  system for an existing implementation of GNU Gettext (only GNU Gettext\n  is acceptable) and use it if it exists.  If not, NLS will be disabled.\n  See ABOUT-NLS for more information.\n\n* Updated to autoconf 2.54 and automake 1.7.  Users should not be impacted.\n\n* VMS-specific changes:\n\n  * In default.c define variable ARCH as IA64 for VMS on Itanium systems.\n\n  * In makefile.vms avoid name collision for glob and globfree.\n\n  * This is the VMS port of GNU Make done by Hartmut.Becker@compaq.com.\n\n    It is based on the specific version 3.77k and on 3.78.1. 3.77k was done\n    by Klaus Kämpf <kkaempf@rmi.de>, the code was based on the VMS port of\n    GNU Make 3.60 by Mike Moretti.\n\n    It was ported on OpenVMS/Alpha V7.1, DECC V5.7-006. It was re-build and\n    tested on OpenVMS/Alpha V7.2, OpenVMS/VAX 7.1 and 5.5-2. Different\n    versions of DECC were used. VAXC was tried: it fails; but it doesn't\n    seem worth to get it working. There are still some PTRMISMATCH warnings\n    during the compile. Although perl is working on VMS the test scripts\n    don't work. The function $shell is still missing.\n\n    There is a known bug in some of the VMS CRTLs. It is in the shipped\n    versions of VMS V7.2 and V7.2-1 and in the currently (October 1999)\n    available ECOs for VMS V7.1 and newer versions. It is fixed in versions\n    shipped with newer VMS versions and all ECO kits after October 1999. It\n    only shows up during the daylight saving time period (DST): stat()\n    returns a modification time 1 hour ahead. This results in GNU Make\n    warning messages. For a just created source you will see:\n\n     $ gmake x.exe\n     gmake.exe;1: *** Warning: File 'x.c' has modification time in the future\n     (940582863 > 940579269)\n     cc    /obj=x.obj x.c\n     link  x.obj    /exe=x.exe\n     gmake.exe;1: *** Warning:  Clock skew detected.  Your build may be\n     incomplete.\n\n\nA complete list of bugs fixed in this version is available here:\n\n  https://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=102\n\n\f\nVersion 3.79.1 (23 Jun 2000)\n\n* .SECONDARY with no prerequisites now prevents any target from being\n  removed because make thinks it's an intermediate file, not just those\n  listed in the makefile.\n\n* New configure option --disable-nsec-timestamps, but this was\n  superseded in later versions by the .LOW_RESOLUTION_TIME pseudo-target.\n\f\nVersion 3.79 (04 Apr 2000)\n\n* GNU Make optionally supports internationalization and locales via the\n  GNU gettext (or local gettext if suitable) package.  See the ABOUT-NLS\n  file for more information on configuring GNU Make for NLS.\n\n* Previously, GNU Make quoted variables such as MAKEFLAGS and\n  MAKEOVERRIDES for proper parsing by the shell.  This allowed them to\n  be used within make build scripts.  However, using them there is not\n  proper behavior: they are meant to be passed to subshells via the\n  environment.  Unfortunately the values were not quoted properly to be\n  passed through the environment.  This meant that make didn't properly\n  pass some types of command line values to submakes.\n\n  With this version we change that behavior: now these variables are\n  quoted properly for passing through the environment, which is the\n  correct way to do it.  If you previously used these variables\n  explicitly within a make rule you may need to re-examine your use for\n  correctness given this change.\n\n* A new pseudo-target .NOTPARALLEL is available.  If defined, the\n  current makefile is run serially regardless of the value of -j.\n  However, submakes are still eligible for parallel execution.\n\n* The --debug option has changed: it now allows optional flags\n  controlling the amount and type of debugging output.  By default only\n  a minimal amount information is generated, displaying the names of\n  \"normal\" targets (not makefiles) that were deemed out of date and in\n  need of being rebuilt.\n\n  Note that the -d option behaves as before: it takes no arguments and\n  all debugging information is generated.\n\n* The `-p' (print database) output now includes filename and linenumber\n  information for variable definitions, to aid debugging.\n\n* The wordlist function no longer reverses its arguments if the \"start\"\n  value is greater than the \"end\" value.  If that's true, nothing is\n  returned.\n\n* Hartmut Becker provided many updates for the VMS port of GNU Make.\n  See the README.VMS file for more details.\n\n* VMS-specific changes:\n\n  * Fix a problem with automatically remaking makefiles. GNU Make uses an\n    execve to restart itself after a successful remake of the makefile. On\n    UNIX systems execve replaces the running program with a new one and\n    resets all signal handling to the default. On VMS execve creates a child\n    process, signal and exit handlers of the parent are still active, and,\n    unfortunately, corrupt the exit code from the child. Fix in job.c:\n    ignore SIGCHLD.\n\n  * Added some switches to reflect latest features of DECC. Modifications in\n    makefile.vms.\n\n  * Set some definitions to reflect latest features of DECC. Modifications in\n    config.h-vms (which is copied to config.h).\n\n  * Added extern strcmpi declaration to avoid 'implicitly declared' messages.\n    Modification in make.h.\n\n  * Default rule for C++, conditionals for gcc (GCC_IS_NATIVE) or DEC/Digital/\n    Compaq c/c++ compilers. Modifications in default.c.\n\n  * Usage of opendir() and friends, suppress file version. Modifications in\n    dir.c.\n\n  * Added VMS specific code to handle ctrl+c and ctrl+y to abort make.\n    Modifications in job.c.\n\n  * Added support to have case sensitive targets and dependencies but to\n    still use case blind file names. This is especially useful for Java\n    makefiles on VMS:\n\n        .SUFFIXES :\n        .SUFFIXES : .class .java\n        .java.class :\n                javac \"$<\n        HelloWorld.class :      HelloWorld.java\n\n  * A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced.\n    It needs to be enabled to get this feature; default is disabled.  The\n    macro HAVE_CASE_INSENSITIVE_FS must not be touched: it is still enabled.\n    Modifications in file.c and config.h-vms.\n\n  * Bootstrap make to start building make is still makefile.com, but make\n    needs to be re-made with a make to make a correct version: ignore all\n    possible warnings, delete all objects, rename make.exe to a different\n    name and run it.\n\n  * Made some minor modifications to the bootstrap build makefile.com.\n\f\nVersion 3.78 (22 Sep 1999)\n\n* Two new functions, $(error ...) and $(warning ...) are available.  The\n  former will cause make to fail and exit immediately upon expansion of\n  the function, with the text provided as the error message.  The latter\n  causes the text provided to be printed as a warning message, but make\n  proceeds normally.\n\n* A new function $(call ...) is available.  This allows users to create\n  their own parameterized macros and invoke them later.  Original\n  implementation of this function was provided by Han-Wen Nienhuys\n  <hanwen@cs.uu.nl>.\n\n* A new function $(if ...) is available.  It provides if-then-else\n  capabilities in a builtin function.  Original implementation of this\n  function was provided by Han-Wen Nienhuys <hanwen@cs.uu.nl>.\n\n* Make defines a new variable, .LIBPATTERNS.  This variable controls how\n  library dependency expansion (dependencies like ``-lfoo'') is performed.\n\n* Make accepts CRLF sequences as well as traditional LF, for\n  compatibility with makefiles created on other operating systems.\n\n* Make accepts a new option: -R, or --no-builtin-variables.  This option\n  disables the definition of the rule-specific builtin variables (CC,\n  LD, AR, etc.).  Specifying this option forces -r (--no-builtin-rules)\n  as well.\n\n* A \"job server\" feature, suggested by Howard Chu <hyc@highlandsun.com>.\n\n  On systems that support POSIX pipe(2) semantics, GNU Make can now pass\n  -jN options to submakes rather than forcing them all to use -j1.  The\n  top make and all its sub-make processes use a pipe to communicate with\n  each other to ensure that no more than N jobs are started across all\n  makes.  To get the old behavior of -j back, you can configure make\n  with the --disable-job-server option.\n\n* The confusing term \"dependency\" has been replaced by the more accurate\n  and standard term \"prerequisite\", both in the manual and in all GNU Make\n  output.\n\n* GNU Make supports the \"big archive\" library format introduced in AIX 4.3.\n\n* GNU Make supports large files on AIX, HP-UX, and IRIX.  These changes\n  were provided by Paul Eggert <eggert@twinsun.com>.  (Large file\n  support for Solaris and Linux was introduced in 3.77, but the\n  configuration had issues: these have also been resolved).\n\n* The Windows 95/98/NT (W32) version of GNU Make now has native support\n  for the Cygnus Cygwin release B20.1 shell (bash).\n\n* The GNU Make regression test suite, long available separately \"under\n  the table\", has been integrated into the release.  You can invoke it\n  by running \"make check\" in the distribution.  Note that it requires\n  Perl (either Perl 4 or Perl 5) to run.\n\f\nVersion 3.77 (28 Jul 1998)\n\n* Implement BSD make's \"?=\" variable assignment operator.  The variable\n  is assigned the specified value only if that variable is not already\n  defined.\n\n* Make defines a new variable, \"CURDIR\", to contain the current working\n  directory (after the -C option, if any, has been processed).\n  Modifying this variable has no effect on the operation of make.\n\n* Make defines a new default RCS rule, for new-style master file\n  storage: ``% :: RCS/%'' (note no ``,v'' suffix).\n\n  Make defines new default rules for DOS-style C++ file naming\n  conventions, with ``.cpp'' suffixes.  All the same rules as for\n  ``.cc'' and ``.C'' suffixes are provided, along with LINK.cpp and\n  COMPILE.cpp macros (which default to the same value as LINK.cc and\n  COMPILE.cc).  Note CPPFLAGS is still C preprocessor flags!  You should\n  use CXXFLAGS to change C++ compiler flags.\n\n* A new feature, \"target-specific variable values\", has been added.\n  This is a large change so please see the appropriate sections of the\n  manual for full details.  Briefly, syntax like this:\n\n    TARGET: VARIABLE = VALUE\n\n  defines VARIABLE as VALUE within the context of TARGET.  This is\n  similar to SunOS make's \"TARGET := VARIABLE = VALUE\" feature.  Note\n  that the assignment may be of any type, not just recursive, and that\n  the override keyword is available.\n\n  COMPATIBILITY: This new syntax means that if you have any rules where\n  the first or second dependency has an equal sign (=) in its name,\n  you'll have to escape them with a backslash: \"foo : bar\\=baz\".\n  Further, if you have any dependencies which already contain \"\\=\",\n  you'll have to escape both of them: \"foo : bar\\\\\\=baz\".\n\n* A new appendix listing the most common error and warning messages\n  generated by GNU Make, with some explanation, has been added to the\n  GNU Make User's Manual.\n\n* Updates to the GNU Make Customs library support (see README.customs).\n\n* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32),\n  and to the DOS port from Eli Zaretski (see README.DOS).\n\n* VMS-specific changes:\n\n  * This is the VMS port of GNU Make.\n    It is based on the VMS port of GNU Make 3.60 by Mike Moretti.\n    This port was done by Klaus Kämpf <kkaempf@rmi.de>\n\n  * There is first-level support available from proGIS Software, Germany.\n    Visit their web-site at https://www.progis.de to get information\n    about other vms software and forthcoming updates to gnu make.\n\n  * /bin/sh style I/O redirection is supported. You can now write lines like\n        mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt\n\n  * Makefile variables are looked up in the current environment. You can set\n    symbols or logicals in DCL and evaluate them in the Makefile via\n    $(<name-of-symbol-or-logical>).  Variables defined in the Makefile\n    override VMS symbols/logicals !\n\n  * Functions for file names are working now. See the GNU Make manual for\n    $(dir ...)  and $(wildcard ...).  Unix-style and VMS-style names are\n    supported as arguments.\n\n  * The default rules are set up for GNU C. Building an executable from a\n    single source file is as easy as 'make file.exe'.\n\n  * The variable $(ARCH) is predefined as ALPHA or VAX resp. Makefiles for\n    different VMS systems can now be written by checking $(ARCH) as in\n      ifeq ($(ARCH),ALPHA)\n        $(ECHO) \"On the Alpha\"\n      else\n        $(ECHO) \"On the VAX\"\n      endif\n\n  * Command lines of excessive length are correctly broken and written to a\n    batch file in sys$scratch for later execution. There's no limit to the\n    lengths of commands (and no need for .opt files :-) any more.\n\n  * Empty commands are handled correctly and don't end in a new DCL process.\n\f\nVersion 3.76.1 (19 Sep 1997)\n\n* Small (but serious) bug fix.  Quick rollout to get into the GNU source CD.\n\f\nVersion 3.76 (16 Sep 1997)\n\n* GNU Make now uses automake to control Makefile.in generation.  This\n  should make it more consistent with the GNU standards.\n\n* VPATH functionality has been changed to incorporate the VPATH+ patch,\n  previously maintained by Paul Smith <psmith@baynetworks.com>.  See the\n  manual.\n\n* Make defines a new variable, `MAKECMDGOALS', to contain the goals that\n  were specified on the command line, if any.  Modifying this variable\n  has no effect on the operation of make.\n\n* A new function, `$(wordlist S,E,TEXT)', is available: it returns a\n  list of words from number S to number E (inclusive) of TEXT.\n\n* Instead of an error, detection of future modification times gives a\n  warning and continues.  The warning is repeated just before GNU Make\n  exits, so it is less likely to be lost.\n\n* Fix the $(basename) and $(suffix) functions so they only operate on\n  the last filename, not the entire string:\n\n      Command              Old Result             New Result\n      -------              ----------             ----------\n    $(basename a.b)        a                      a\n    $(basename a.b/c)      a                      a.b/c\n    $(suffix a.b)          b                      b\n    $(suffix a.b/c)        b/c                    <empty>\n\n* The $(strip) function now removes newlines as well as TABs and spaces.\n\n* The $(shell) function now changes CRLF (\\r\\n) pairs to a space as well\n  as newlines (\\n).\n\n* Updates to the Windows 95/NT port from Rob Tulloh (see README.W32).\n\n* Eli Zaretskii has updated the port to 32-bit protected mode on MSDOS\n  and MS-Windows, building with the DJGPP v2 port of GNU C/C++ compiler\n  and utilities.  See README.DOS for details, and direct all questions\n  concerning this port to Eli Zaretskii <eliz@is.elta.co.il> or DJ\n  Delorie <dj@delorie.com>.\n\n* VMS-specific changes:\n\n  * John W. Eaton has updated the VMS port to support libraries and VPATH.\n\n  * The cd command is supported if it's called as $(CD). This invokes\n    the 'builtin_cd' command which changes the directory.\n    Calling 'set def' doesn't do the trick, since a sub-shell is\n    spawned for this command, the directory is changed *in this sub-shell*\n    and the sub-shell ends.\n\n  * Libraries are not supported. They were in GNU Make 3.60 but somehow I\n    didn't care porting the code. If there is enough interest, I'll do it at\n    some later time.\n\n  * The variable $^ separates files with commas instead of spaces (It's the\n    natural thing to do for VMS).\n\n  * See defaults.c for VMS default suffixes and my definitions for default\n    rules and variables.\n\n  * The shell function is not implemented yet.\n\n  * Load average routines haven't been implemented for VMS yet.\n\n  * The default include directory for including other makefiles is\n    SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use\n    SYS$LIBRARY: instead; maybe it wouldn't work that way).\n\n  * The default makefiles make looks for are: makefile.vms, gnumakefile,\n    makefile., and gnumakefile. .\n\n  * The stat() function and handling of time stamps in VMS is broken, so I\n    replaced it with a hack in vmsfunctions.c. I will provide a full rewrite\n    somewhere in the future. Be warned, the time resolution inside make is\n    less than what vms provides. This might be a problem on the faster Alphas.\n\n  * You can use a : in a filename only if you precede it with a backslash ('\\').\n    E.g.- hobbes\\:[bogas.files]\n\n  * Make ignores success, informational, or warning errors (-S-, -I-, or -W-).\n    But it will stop on -E- and -F- errors. (unless you do something\n    to override this in your makefile, or whatever).\n\n  * Remote stuff isn't implemented yet.\n\n  * Multiple line DCL commands, such as \"if\" statements, must be put inside\n    command files.  You can run a command file by using \\@.\n\nVersion 3.75 (27 Aug 1996)\n\n* The directory messages printed by `-w' and implicitly in sub-makes,\n  are now omitted if Make runs no commands and has no other messages to print.\n\n* Make now detects files that for whatever reason have modification times\n  in the future and gives an error.  Files with such impossible timestamps\n  can result from unsynchronized clocks, or archived distributions\n  containing bogus timestamps; they confuse Make's dependency engine\n  thoroughly.\n\n* The new directive `sinclude' is now recognized as another name for\n  `-include', for compatibility with some other Makes.\n\n* Aaron Digulla has contributed a port to AmigaDOS.  See README.Amiga for\n  details, and direct all Amiga-related questions to <digulla@fh-konstanz.de>.\n\n* Rob Tulloh of Tivoli Systems has contributed a port to Windows NT or 95.\n  See README.W32 for details, and direct all Windows-related questions to\n  <rob_tulloh@tivoli.com>.\n\n* VMS-specific changes:\n\n  * Lots of default settings are adapted for VMS. See default.c.\n\n  * Long command lines are now converted to command files.\n\n  * Comma (',') as a separator is now allowed. See makefile.vms for an example.\n\f\nVersion 3.73 (05 Apr 1995)\n\n* Converted to use Autoconf version 2, so `configure' has some new options.\n  See INSTALL for details.\n\n* You can now send a SIGUSR1 signal to Make to toggle printing of debugging\n  output enabled by -d, at any time during the run.\n\f\nVersion 3.72 (04 Nov 1994)\n\n* DJ Delorie has ported Make to MS-DOS using the GO32 extender.\n  He is maintaining the DOS port, not the GNU Make maintainer;\n  please direct bugs and questions for DOS to <djgpp@sun.soe.clarkson.edu>.\n  MS-DOS binaries are available for FTP from ftp.simtel.net in\n  /pub/simtelnet/gnu/djgpp/.\n\n* The `MAKEFLAGS' variable (in the environment or in a makefile) can now\n  contain variable definitions itself; these are treated just like\n  command line variable definitions.  Make will automatically insert any\n  variable definitions from the environment value of `MAKEFLAGS' or from\n  the command line, into the `MAKEFLAGS' value exported to children.  The\n  `MAKEOVERRIDES' variable previously included in the value of `$(MAKE)'\n  for sub-makes is now included in `MAKEFLAGS' instead.  As before, you can\n  reset `MAKEOVERRIDES' in your makefile to avoid putting all the variables\n  in the environment when its size is limited.\n\n* If `.DELETE_ON_ERROR' appears as a target, Make will delete the target of\n  a rule if it has changed when its recipe exits with a nonzero status,\n  just as when the recipe gets a signal.\n\n* The automatic variable `$+' is new.  It lists all the dependencies like\n  `$^', but preserves duplicates listed in the makefile.  This is useful\n  for linking rules, where library files sometimes need to be listed twice\n  in the link order.\n\n* You can now specify the `.IGNORE' and `.SILENT' special targets with\n  dependencies to limit their effects to those files.  If a file appears as\n  a dependency of `.IGNORE', then errors will be ignored while running the\n  recipe to update that file.  Likewise if a file appears as a dependency\n  of `.SILENT', then the recipe to update that file will not be printed\n  before it is run.  (This change was made to conform to POSIX.2.)\n\f\nVersion 3.71 (21 May 1994)\n\n* The automatic variables `$(@D)', `$(%D)', `$(*D)', `$(<D)', `$(?D)', and\n  `$(^D)' now omit the trailing slash from the directory name.  (This change\n  was made to comply with POSIX.2.)\n\n* The source distribution now includes the Info files for the Make manual.\n  There is no longer a separate distribution containing Info and DVI files.\n\n* You can now set the variables `binprefix' and/or `manprefix' in\n  Makefile.in (or on the command line when installing) to install GNU Make\n  under a name other than `make' (i.e., ``make binprefix=g install''\n  installs GNU Make as `gmake').\n\n* The built-in Texinfo rules use the new variables `TEXI2DVI_FLAGS' for\n  flags to the `texi2dvi' script, and `MAKEINFO_FLAGS' for flags to the\n  Makeinfo program.\n\n* The exit status of Make when it runs into errors is now 2 instead of 1.\n  The exit status is 1 only when using -q and some target is not up to date.\n  (This change was made to comply with POSIX.2.)\n\f\nVersion 3.70 (03 Jan 1994)\n\n* It is no longer a fatal error to have a NUL character in a makefile.\n  You should never put a NUL in a makefile because it can have strange\n  results, but otherwise empty lines full of NULs (such as produced by\n  the `xmkmf' program) will always work fine.\n\n* The error messages for nonexistent included makefiles now refer to the\n  makefile name and line number where the `include' appeared, so Emacs's\n  C-x ` command takes you there (in case it's a typo you need to fix).\n\f\nVersion 3.69 (07 Nov 1993)\n\n* Implicit rule search for archive member references is now done in the\n  opposite order from previous versions: the whole target name `LIB(MEM)'\n  first, and just the member name and parentheses `(MEM)' second.\n\n* Make now gives an error for an unterminated variable or function reference.\n  For example, `$(foo' with no matching `)' or `${bar' with no matching `}'.\n\n* The new default variable `MAKE_VERSION' gives the version number of\n  Make, and a string describing the remote job support compiled in (if any).\n  Thus the value (in this release) is something like `3.69' or `3.69-Customs'.\n\n* Commands in an invocation of the `shell' function are no longer run\n  with a modified environment like recipes are.  As in versions before\n  3.68, they now run with the environment that `make' started with.  We\n  have reversed the change made in version 3.68 because it turned out to\n  cause a paradoxical situation in cases like:\n\n        export variable = $(shell echo value)\n\n  When Make attempted to put this variable in the environment for a\n  recipe, it would try expand the value by running the shell command\n  `echo value'.  In version 3.68, because it constructed an environment\n  for that shell command in the same way, Make would begin to go into an\n  infinite loop and then get a fatal error when it detected the loop.\n\n* The recipe given for `.DEFAULT' is now used for phony targets with no\n  recipe.\n\f\nVersion 3.68 (28 Jul 1993)\n\n* You can list several archive member names inside parenthesis:\n  `lib(mem1 mem2 mem3)' is equivalent to `lib(mem1) lib(mem2) lib(mem3)'.\n\n* You can use wildcards inside archive member references.  For example,\n  `lib(*.o)' expands to all existing members of `lib' whose names end in\n  `.o' (e.g. `lib(a.o) lib(b.o)'); `*.a(*.o)' expands to all such members\n  of all existing files whose names end in `.a' (e.g. `foo.a(a.o)\n  foo.a(b.o) bar.a(c.o) bar.a(d.o)'.\n\n* A suffix rule `.X.a' now produces two pattern rules:\n        (%.o): %.X\t# Previous versions produced only this.\n        %.a: %.X\t# Now produces this as well, just like other suffixes.\n\n* The new flag `--warn-undefined-variables' says to issue a warning message\n  whenever Make expands a reference to an undefined variable.\n\n* The new `-include' directive is just like `include' except that there is\n  no error (not even a warning) for a nonexistent makefile.\n\n* Commands in an invocation of the `shell' function are now run with a\n  modified environment like recipes are, so you can use `export' et al\n  to set up variables for them.  They used to run with the environment\n  that `make' started with.\n\f\nVersion 3.66 (21 May 1993)\n\n* `make --version' (or `make -v') now exits immediately after printing\n  the version number.\n\f\nVersion 3.65 (09 May 1993)\n\n* Make now supports long-named members in `ar' archive files.\n\f\nVersion 3.64 (21 Apr 1993)\n\n* Make now supports the `+=' syntax for a variable definition which appends\n  to the variable's previous value.  See the section `Appending More Text\n  to Variables' in the manual for full details.\n\n* The new option `--no-print-directory' inhibits the `-w' or\n  `--print-directory' feature.  Make turns on `--print-directory'\n  automatically if you use `-C' or `--directory', and in sub-makes; some\n  users have found this behavior undesirable.\n\n* The built-in implicit rules now support the alternative extension\n  `.txinfo' for Texinfo files, just like `.texinfo' and `.texi'.\n\f\nVersion 3.63 (22 Jan 1993)\n\n* Make now uses a standard GNU `configure' script.  See the new file\n  INSTALL for the new (and much simpler) installation procedure.\n\n* There is now a shell script to build Make the first time, if you have no\n  other `make' program.  `build.sh' is created by `configure'; see README.\n\n* GNU Make now completely conforms to the POSIX.2 specification for `make'.\n\n* Elements of the `$^' and `$?' automatic variables that are archive\n  member references now list only the member name, as in Unix and POSIX.2.\n\n* You should no longer ever need to specify the `-w' switch, which prints\n  the current directory before and after Make runs.  The `-C' switch to\n  change directory, and recursive use of Make, now set `-w' automatically.\n\n* Multiple double-colon rules for the same target will no longer have their\n  recipes run simultaneously under -j, as this could result in the two\n  recipes trying to change the file at the same time and interfering with\n  one another.\n\n* The `SHELL' variable is now never taken from the environment.\n  Each makefile that wants a shell other than the default (/bin/sh) must\n  set SHELL itself.  SHELL is always exported to child processes.\n  This change was made for compatibility with POSIX.2.\n\n* Make now accepts long options.  There is now an informative usage message\n  that tells you what all the options are and what they do.  Try `make --help'.\n\n* There are two new directives: `export' and `unexport'.  All variables are\n  no longer automatically put into the environments of the recipe lines that\n  Make runs.  Instead, only variables specified on the command line or in\n  the environment are exported by default.  To export others, use:\n        export VARIABLE\n  or you can define variables with:\n        export VARIABLE = VALUE\n  or:\n        export VARIABLE := VALUE\n  You can use just:\n        export\n  or:\n        .EXPORT_ALL_VARIABLES:\n  to get the old behavior.  See the node `Variables/Recursion' in the manual\n  for a full description.\n\n* The recipe from the `.DEFAULT' special target is only applied to\n  targets which have no rules at all, not all targets with no recipe.\n  This change was made for compatibility with Unix make.\n\n* All fatal error messages now contain `***', so they are easy to find in\n  compilation logs.\n\n* Dependency file names like `-lNAME' are now replaced with the actual file\n  name found, as with files found by normal directory search (VPATH).\n  The library file `libNAME.a' may now be found in the current directory,\n  which is checked before VPATH; the standard set of directories (/lib,\n  /usr/lib, /usr/local/lib) is now checked last.\n  See the node `Libraries/Search' in the manual for full details.\n\n* A single `include' directive can now specify more than one makefile to\n  include, like this:\n        include file1 file2\n  You can also use shell file name patterns in an `include' directive:\n        include *.mk\n\n* The default directories to search for included makefiles, and for\n  libraries specified with `-lNAME', are now set by configuration.\n\n* You can now use blanks as well as colons to separate the directories in a\n  search path for the `vpath' directive or the `VPATH' variable.\n\n* You can now use variables and functions in the left hand side of a\n  variable assignment, as in \"$(foo)bar = value\".\n\n* The `MAKE' variable is always defined as `$(MAKE_COMMAND) $(MAKEOVERRIDES)'.\n  The `MAKE_COMMAND' variable is now defined to the name with which make\n  was invoked.\n\n* The built-in rules for C++ compilation now use the variables `$(CXX)' and\n  `$(CXXFLAGS)' instead of `$(C++)' and `$(C++FLAGS)'.  The old names had\n  problems with shells that cannot have `+' in environment variable names.\n\n* The value of a recursively expanded variable is now expanded when putting\n  it into the environment for child processes.  This change was made for\n  compatibility with Unix make.\n\n* A rule with no targets before the `:' is now accepted and ignored.\n  This change was made for compatibility with SunOS 4 make.\n  We do not recommend that you write your makefiles to take advantage of this.\n\n* The `-I' switch can now be used in MAKEFLAGS, and are put there\n  automatically just like other switches.\n\f\nVersion 3.61\n\n* Built-in rules for C++ source files with the `.C' suffix.\n  We still recommend that you use `.cc' instead.\n\n* If a recipe is given too many times for a single target, the last one\n  given is used, and a warning message is printed.\n\n* Error messages about makefiles are in standard GNU error format,\n  so C-x ` in Emacs works on them.\n\n* Dependencies of pattern rules which contain no % need not actually exist\n  if they can be created (just like dependencies which do have a %).\n\f\nVersion 3.60\n\n* A message is always printed when Make decides there is nothing to be done.\n  It used to be that no message was printed for top-level phony targets\n  (because \"`phony' is up to date\" isn't quite right).  Now a different\n  message \"Nothing to be done for `phony'\" is printed in that case.\n\n* Archives on AIX now supposedly work.\n\n* When the recipes specified for .DEFAULT are used to update a target,\n  the $< automatic variable is given the same value as $@ for that target.\n  This is how Unix make behaves, and this behavior is mandated by POSIX.2.\n\f\nVersion 3.59\n\n* The -n, -q, and -t options are not put in the `MAKEFLAGS' and `MFLAG'\n  variables while remaking makefiles, so recursive makes done while remaking\n  makefiles will behave properly.\n\n* If the special target `.NOEXPORT' is specified in a makefile,\n  only variables that came from the environment and variables\n  defined on the command line are exported.\n\f\nVersion 3.58\n\n* Suffix rules may have dependencies (which are ignored).\n\f\nVersion 3.57\n\n* Dependencies of the form `-lLIB' are searched for as /usr/local/lib/libLIB.a\n  as well as libLIB.a in /usr/lib, /lib, the current directory, and VPATH.\n\f\nVersion 3.55\n\n* There is now a Unix man page for GNU Make.  It is certainly not a\n  replacement for the Texinfo manual, but it documents the basic\n  functionality and the switches.  For full documentation, you should\n  still read the Texinfo manual.  Thanks to Dennis Morse of Stanford\n  University for contributing the initial version of this.\n\n* Variables which are defined by default (e.g., `CC') will no longer be\n  put into the environment for child processes.  (If these variables are\n  reset by the environment, makefiles, or the command line, they will\n  still go into the environment.)\n\n* Makefiles which have recipes but no dependencies (and thus are always\n  considered out of date and in need of remaking), will not be remade (if they\n  were being remade only because they were makefiles).  This means that GNU\n  Make will no longer go into an infinite loop when fed the makefiles that\n  `imake' (necessary to build X Windows) produces.\n\n* There is no longer a warning for using the `vpath' directive with an explicit\npathname (instead of a `%' pattern).\n\f\nVersion 3.51\n\n* When removing intermediate files, only one `rm' command line is printed,\n  listing all file names.\n\n* There are now automatic variables `$(^D)', `$(^F)', `$(?D)', and `$(?F)'.\n  These are the directory-only and file-only versions of `$^' and `$?'.\n\n* Library dependencies given as `-lNAME' will use \"libNAME.a\" in the current\n  directory if it exists.\n\n* The automatic variable `$($/)' is no longer defined.\n\n* Leading `+' characters on a recipe line make that line be executed even\n  under -n, -t, or -q (as if the line contained `$(MAKE)').\n\n* For recipe lines containing `$(MAKE)', `${MAKE}', or leading `+' characters,\n  only those lines are executed, not the entire recipe.\n  (This is how Unix make behaves for lines containing `$(MAKE)' or `${MAKE}'.)\n\f\nVersion 3.50\n\n* Filenames in rules will now have ~ and ~USER expanded.\n\n* The `-p' output has been changed so it can be used as a makefile.\n  (All information that isn't specified by makefiles is prefaced with comment\n  characters.)\n\f\nVersion 3.49\n\n* The % character can be quoted with backslash in implicit pattern rules,\n  static pattern rules, `vpath' directives, and `patsubst', `filter', and\n  `filter-out' functions.  A warning is issued if a `vpath' directive's\n  pattern contains no %.\n\n* The `wildcard' variable expansion function now expands ~ and ~USER.\n\n* Messages indicating failed recipe lines now contain the target name:\n        make: *** [target] Error 1\n\n* The `-p' output format has been changed somewhat to look more like\n  makefile rules and to give all information that Make has about files.\n\f\nVersion 3.48\n\f\nVersion 3.47\n\n* The `-l' switch with no argument removes any previous load-average limit.\n\n* When the `-w' switch is in effect, and Make has updated makefiles,\n  it will write a `Leaving directory' message before re-executing itself.\n  This makes the `directory change tracking' changes to Emacs's compilation\n  commands work properly.\n\f\nVersion 3.46\n\n* The automatic variable `$*' is now defined for explicit rules,\n  as it is in Unix make.\n\f\nVersion 3.45\n\n* The `-j' switch is now put in the MAKEFLAGS and MFLAGS variables when\n  specified without an argument (indicating infinite jobs).\n  The `-l' switch is not always put in the MAKEFLAGS and MFLAGS variables.\n\n* Make no longer checks hashed directories after running recipes.\n  The behavior implemented in 3.41 caused too much slowdown.\n\f\nVersion 3.44\n\n* A dependency is NOT considered newer than its dependent if\n  they have the same modification time.  The behavior implemented\n  in 3.43 conflicts with RCS.\n\f\nVersion 3.43\n\n* Dependency loops are no longer fatal errors.\n\n* A dependency is considered newer than its dependent if\n  they have the same modification time.\n\f\nVersion 3.42\n\n* The variables F77 and F77FLAGS are now set by default to $(FC) and\n  $(FFLAGS).  Makefiles designed for System V make may use these variables in\n  explicit rules and expect them to be set.  Unfortunately, there is no way to\n  make setting these affect the Fortran implicit rules unless FC and FFLAGS\n  are not used (and these are used by BSD make).\n\f\nVersion 3.41\n\n* Make now checks to see if its hashed directories are changed by recipes.\n  Other makes that hash directories (Sun, 4.3 BSD) don't do this.\n\f\nVersion 3.39\n\n* The `shell' function no longer captures standard error output.\n\f\nVersion 3.32\n\n* A file beginning with a dot can be the default target if it also contains\n  a slash (e.g., `../bin/foo').  (Unix make allows this as well.)\n\f\nVersion 3.31\n\n* Archive member names are truncated to 15 characters.\n\n* Yet more USG stuff.\n\n* Minimal support for Microport System V (a 16-bit machine and a\n  brain-damaged compiler).  This has even lower priority than other USG\n  support, so if it gets beyond trivial, I will take it out completely.\n\n* Revamped default implicit rules (not much visible change).\n\n* The -d and -p options can come from the environment.\n\f\nVersion 3.30\n\n* Improved support for USG and HPUX (hopefully).\n\n* A variable reference like `$(foo:a=b)', if `a' contains a `%', is\n  equivalent to `$(patsubst a,b,$(foo))'.\n\n* Defining .DEFAULT with no deps or recipe clears its recipe.\n\n* New default implicit rules for .S (cpp, then as), and .sh (copy and\n  make executable).  All default implicit rules that use cpp (even\n  indirectly), use $(CPPFLAGS).\n\f\nVersion 3.29\n\n* Giving the -j option with no arguments gives you infinite jobs.\n\f\nVersion 3.28\n\n* New option: \"-l LOAD\" says not to start any new jobs while others are\n  running if the load average is not below LOAD (a floating-point number).\n\n* There is support in place for implementations of remote command execution\n  in Make.  See the file remote.c.\n\f\nVersion 3.26\n\n* No more than 10 directories will be kept open at once.\n  (This number can be changed by redefining MAX_OPEN_DIRECTORIES in dir.c.)\n\f\nVersion 3.25\n\n* Archive files will have their modification times recorded before doing\n  anything that might change their modification times by updating an archive\n  member.\n\f\nVersion 3.20\n\n* The `MAKELEVEL' variable is defined for use by makefiles.\n\f\nVersion 3.19\n\n* The recursion level indications in error messages are much shorter than\n  they were in version 3.14.\n\f\nVersion 3.18\n\n* Leading spaces before directives are ignored (as documented).\n\n* Included makefiles can determine the default goal target.\n  (System V Make does it this way, so we are being compatible).\n\f\nVersion 3.14.\n\n* Variables that are defaults built into Make will not be put in the\n  environment for children.  This just saves some environment space and,\n  except under -e, will be transparent to sub-makes.\n\n* Error messages from sub-makes will indicate the level of recursion.\n\n* Hopefully some speed-up for large directories due to a change in the\n  directory hashing scheme.\n\n* One child will always get a standard input that is usable.\n\n* Default makefiles that don't exist will be remade and read in.\n\f\nVersion 3.13.\n\n* Count parentheses inside expansion function calls so you can\n  have nested calls: `$(sort $(foreach x,a b,$(x)))'.\n\f\nVersion 3.12.\n\n* Several bug fixes, including USG and Sun386i support.\n\n* `shell' function to expand shell commands a la `\n\n* If the `-d' flag is given, version information will be printed.\n\n* The `-c' option has been renamed to `-C' for compatibility with tar.\n\n* The `-p' option no longer inhibits other normal operation.\n\n* Makefiles will be updated and re-read if necessary.\n\n* Can now run several recipes at once (parallelism), -j option.\n\n* Error messages will contain the level of Make recursion, if any.\n\n* The `MAKEFLAGS' and `MFLAGS' variables will be scanned for options after\n  makefiles are read.\n\n* A double-colon rule with no dependencies will always have its recipe run.\n  (This is how both the BSD and System V versions of Make do it.)\n\f\nVersion 3.05\n\n(Changes from versions 1 through 3.05 were never recorded.  Sorry.)\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.DOS",
    "content": "Port of GNU Make to 32-bit protected mode on MSDOS and MS-Windows.\n\nBuilds with DJGPP v2 port of GNU C/C++ compiler and utilities.\n\n\nNew (since 3.74) DOS-specific features:\n\n   1. Supports long filenames when run from DOS box on Windows 9x.\n\n   2. Supports both stock DOS COMMAND.COM and Unix-style shells\n      (details in 'Notes' below).\n\n   3. Supports DOS drive letters in dependencies and pattern rules.\n\n   4. Better support for DOS-style backslashes in pathnames (but see\n      'Notes' below).\n\n   5. The $(shell) built-in can run arbitrary complex commands,\n      including pipes and redirection, even when COMMAND.COM is your\n      shell.\n\n   6. Can be built without floating-point code (see below).\n\n   7. Supports signals in child programs and restores the original\n      directory if the child was interrupted.\n\n   8. Can be built without (a previous version of) Make.\n\n   9. The build process requires only standard tools.  (Optional\n      targets like \"check:\" still need additional programs, though,\n      see below.)\n\n  10. Beginning with v3.78, the test suite works in the DJGPP\n      environment (requires Perl and auxiliary tools; see below).\n\n\nTo install a binary distribution:\n\n   Simply unzip the makNNNb.zip file (where NNN is the version number)\n   preserving the directory structure (-d switch if you use PKUNZIP).\n   If you are installing Make on Windows 9X or Windows 2000, use an\n   unzip program that supports long filenames in zip files.  After\n   unzipping, make sure the directory with make.exe is on your PATH,\n   and that's all you need to use Make.\n\n\nTo build from sources:\n\n   1. Unzip the archive, preserving the directory structure (-d switch\n      if you use PKUNZIP).  If you build Make on Windows 9X or Windows\n      2000, use an unzip program that supports long filenames in zip\n      files.\n\n      If you are unpacking an official GNU source distribution, use\n      either DJTAR (which is part of the DJGPP development\n      environment), or the DJGPP port of GNU Tar.\n\n   2. If you have a working Make already, you can run:\n\n          make -f Basic.mk\n\n   3. If you don't have a working Make already you can bootstrap one\n      by running:\n\n          .\\builddos.bat\n\n   4. If you are building from outside of the source directory, you\n      need to tell Make where the sources are, like this:\n\n          make -f c:/djgpp/gnu/make/Basic.mk SRCDIR=c:/djgpp/gnu/make\n\n      or:\n\n          c:/djgpp/gnu/make/builddos.bat c:/djgpp/gnu/make\n\n   5. To run the test suite, type \"make check\".  This requires a Unix\n      shell (I used the DJGPP port of Bash 2.03), Perl, Sed, Fileutils\n      and Sh-utils.\n\n   6. To install copy make.exe to the preferred location.\n\n      Since GNU Make 4.3, support for customized platform installations\n      has been removed.  If you'd like to collaborate on reinstating\n      these capabilities, contact bug-make@gnu.org.\n\n\nNotes:\n-----\n\n   1. The shell issue.\n\n      This is probably the most significant improvement, first\n      introduced in the port of GNU Make 3.75.\n\n      The original behavior of GNU Make is to invoke commands\n      directly, as long as they don't include characters special to\n      the shell or internal shell commands, because that is faster.\n      When shell features like redirection or filename wildcards are\n      involved, Make calls the shell.\n\n      This port supports both DOS shells (the stock COMMAND.COM and its\n      4DOS/NDOS replacements), and Unix-style shells (tested with the\n      venerable Stewartson's 'ms_sh' 2.3 and the DJGPP port of 'bash' by\n      Daisuke Aoyama <jack@st.rim.or.jp>).\n\n      When the $SHELL variable points to a Unix-style shell, Make\n      works just like you'd expect on Unix, calling the shell for any\n      command that involves characters special to the shell or\n      internal shell commands.  The only difference is that, since\n      there is no standard way to pass command lines longer than the\n      infamous DOS 126-character limit, this port of Make writes the\n      command line to a temporary disk file and then invokes the shell\n      on that file.\n\n      If $SHELL points to a DOS-style shell, however, Make will not\n      call it automatically, as it does with Unix shells.  Stock\n      COMMAND.COM is too dumb and would unnecessarily limit the\n      functionality of Make.  For example, you would not be able to\n      use long command lines in commands that use redirection or\n      pipes.  Therefore, when presented with a DOS shell, this port of\n      Make will emulate most of the shell functionality, like\n      redirection and pipes, and shall only call the shell when a\n      batch file or a command internal to the shell is invoked.  (Even\n      when a command is an internal shell command, Make will first\n      search the $PATH for it, so that if a Makefile calls 'mkdir',\n      you can install, say, a port of GNU 'mkdir' and have it called\n      in that case.)\n\n      The key to all this is the extended functionality of 'spawn' and\n      'system' functions from the DJGPP library; this port just calls\n      'system' where it would invoke the shell on Unix.  The most\n      important aspect of these functions is that they use a special\n      mechanism to pass long (up to 16KB) command lines to DJGPP\n      programs.  In addition, 'system' emulates some internal\n      commands, like 'cd' (so that you can now use forward slashes\n      with it, and can also change the drive if the directory is on\n      another drive).  Another aspect worth mentioning is that you can\n      call Unix shell scripts directly, provided that the shell whose\n      name is mentioned on the first line of the script is installed\n      anywhere along the $PATH.  It is impossible to tell here\n      everything about these functions; refer to the DJGPP library\n      reference for more details.\n\n      The $(shell) built-in is implemented in this port by calling\n      'popen'.  Since 'popen' calls 'system', the above considerations\n      are valid for $(shell) as well.  In particular, you can put\n      arbitrary complex commands, including pipes and redirection,\n      inside $(shell), which is in many cases a valid substitute for\n      the Unix-style command substitution (`command`) feature.\n\n\n   2. \"SHELL=/bin/sh\" -- or is it?\n\n      Many Unix Makefiles include a line which sets the SHELL, for\n      those versions of Make which don't have this as the default.\n      Since many DOS systems don't have 'sh' installed (in fact, most\n      of them don't even have a '/bin' directory), this port takes\n      such directives with a grain of salt.  It will only honor such a\n      directive if the basename of the shell name (like 'sh' in the\n      above example) can indeed be found in the directory that is\n      mentioned in the SHELL= line ('/bin' in the above example), or\n      in the current working directory, or anywhere on the $PATH (in\n      that order).  If the basename doesn't include a filename\n      extension, Make will look for any known extension that indicates\n      an executable file (.exe, .com, .bat, .btm, .sh, and even .sed\n      and .pl).  If any such file is found, then $SHELL will be\n      defined to the exact pathname of that file, and that shell will\n      hence be used for the rest of processing.  But if the named\n      shell is *not* found, the line which sets it will be effectively\n      ignored, leaving the value of $SHELL as it was before.  Since a\n      lot of decisions that this port makes depend on the gender of\n      the shell, I feel it doesn't make any sense to tailor Make's\n      behavior to a shell which is nowhere to be found.\n\n      Note that the above special handling of \"SHELL=\" only happens\n      for Makefiles; if you set $SHELL in the environment or on the\n      Make command line, you are expected to give the complete\n      pathname of the shell, including the filename extension.\n\n      The default value of $SHELL is computed as on Unix (see the Make\n      manual for details), except that if $SHELL is not defined in the\n      environment, $COMSPEC is used.  Also, if an environment variable\n      named $MAKESHELL is defined, it takes precedence over both\n      $COMSPEC and $SHELL.  Note that, unlike Unix, $SHELL in the\n      environment *is* used to set the shell (since on MSDOS, it's\n      unlikely that the interactive shell will not be suitable for\n      Makefile processing).\n\n      The bottom line is that you can now write Makefiles where some\n      of the targets require a real (i.e. Unix-like) shell, which will\n      nevertheless work when such shell is not available (provided, of\n      course, that the commands which should always work, don't\n      require such a shell).  More important, you can convert Unix\n      Makefiles to MSDOS and leave the line which sets the shell\n      intact, so that people who do have Unixy shell could use it for\n      targets which aren't converted to DOS (like 'install' and\n      'uninstall', for example).\n\n\n   3. Default directories.\n\n      GNU Make knows about standard directories where it searches for\n      library and include files mentioned in the Makefile.  Since\n      MSDOS machines don't have standard places for these, this port\n      will search ${DJDIR}/lib and ${DJDIR}/include respectively.\n      $DJDIR is defined automatically by the DJGPP startup code as the\n      root of the DJGPP installation tree (unless you've tampered with\n      the DJGPP.ENV file).  This should provide reasonable default\n      values, unless you moved parts of DJGPP to other directories.\n\n\n   4. Letter-case in filenames.\n\n      If you run Make on Windows 9x, you should be aware of the\n      letter-case issue.  Make is internally case-sensitive, but all\n      file operations are case-insensitive on Windows 9x, so\n      e.g. files 'FAQ', 'faq' and 'Faq' all refer to the same file, as\n      far as Windows is concerned.  The underlying DJGPP C library\n      functions honor the letter-case of the filenames they get from\n      the OS, except that by default, they down-case 8+3 DOS filenames\n      which are stored in upper case in the directory and would break\n      many Makefiles otherwise.  (The details of which filenames are\n      converted to lower case are explained in the DJGPP libc docs,\n      under the '_preserve_fncase' and '_lfn_gen_short_fname'\n      functions, but as a thumb rule, any filename that is stored in\n      upper case in the directory, is a valid DOS 8+3 filename and\n      doesn't include characters invalid on MSDOS FAT filesystems,\n      will be automatically down-cased.)  User reports that I have\n      indicate that this default behavior is generally what you'd\n      expect; however, your input is most welcome.\n\n      In any case, if you hit a situation where you must force Make to\n      get the 8+3 DOS filenames in upper case, set FNCASE=y in the\n      environment or in the Makefile.\n\n\n   5. DOS-style pathnames.\n\n      There are a lot of places throughout the program sources which\n      make implicit assumptions about the pathname syntax.  In\n      particular, the directories are assumed to be separated by '/',\n      and any pathname which doesn't begin with a '/' is assumed to be\n      relative to the current directory.  This port attempts to\n      support DOS-style pathnames which might include the drive letter\n      and use backslashes instead of forward slashes.  However, this\n      support is not complete; I feel that pursuing this support too\n      far might break some more important features, particularly if\n      you use a Unix-style shell (where a backslash is a quote\n      character).  I only consider support of backslashes desirable\n      because some Makefiles invoke non-DJGPP programs which don't\n      understand forward slashes.  A notable example of such programs\n      is the standard programs which come with MSDOS.  Otherwise, you\n      are advised to stay away from backslashes whenever possible.  In\n      particular, filename globbing won't work on pathnames with\n      backslashes, because the GNU 'glob' library doesn't support them\n      (backslash is special in filename wildcards, and I didn't want\n      to break that).\n\n      One feature which *does* work with backslashes is the filename-\n      related built-in functions such as $(dir), $(notdir), etc.\n      Drive letters in pathnames are also fully supported.\n\n\n\nBug reports:\n-----------\n\n   Bugs that are clearly related to the MSDOS/DJGPP port should be\n   reported first on the comp.os.msdos.djgpp news group (if you cannot\n   post to Usenet groups, write to the DJGPP mailing list,\n   <djgpp@delorie.com>, which is an email gateway into the above news\n   group).  For other bugs, please follow the procedure explained in\n   the \"Bugs\" chapter of the Info docs.  If you don't have an Info\n   reader, look up that chapter in the 'make.i1' file with any text\n   browser/editor.\n\n\n   Enjoy,\n                        Eli Zaretskii <eliz@is.elta.co.il>\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.OS2",
    "content": "Port of GNU Make to OS/2.\n\nFeatures of GNU Make that do not work under OS/2:\n  - remote job execution\n  - dynamic load balancing\n\n\nSpecial features of the OS/2 version:\n\nDue to the fact that some people might want to use sh syntax in\nMakefiles while others might want to use OS/2's native shell cmd.exe,\nGNU Make supports both shell types. The following list defines the order\nthat is used to determine the shell:\n\n 1. The shell specified by the environment variable MAKESHELL.\n 2. The shell specified by the SHELL variable within a Makefile. Like\n    Unix, SHELL is NOT taken from the environment.\n 3. The shell specified by the COMSPEC environment variable.\n 4. The shell specified by the OS2_SHELL environment variable.\n 5. If none of the above is defined /bin/sh is used as default.  This\n    happens e.g. in the make testsuite.\n\nNote: - Points 3 and 4 can be turned off at compile time by adding\n        -DNO_CMD_DEFAULT to the CPPFLAGS.\n      - DOS support is not tested for EMX and therefore might not work.\n      - The UNIXROOT environment variable is supported to find /bin/sh\n        if it is not on the current drive.\n\n\nCOMPILATION OF GNU MAKE FOR OS/2:\n\nI. ***** SPECIAL OPTIONS *****\n\n - At compile time you can turn off that cmd is used as default shell\n   (but only /bin/sh). Simply set CPPFLAGS=\"-DNO_CMD_DEFAULT\" and make\n   will not use cmd unless you cause it to do so by setting MAKESHELL to\n   cmd or by specifying SHELL=cmd in your Makefile.\n\n - At compile time you can set CPPFLAGS=\"-DNO_CHDIR2\" to turn off that\n   GNU Make prints drive letters. This is necessary if you want to run\n   the testsuite.\n\n\nII. ***** REQUIREMENTS FOR THE COMPILATION *****\n\nA standard Unix like build environment:\n\n - sh compatible shell (ksh, bash, ash, but tested only with pdksh 5.2.14\n   release 2)\n   If you use pdksh it is recommended to update to 5.2.14 release 2. Older\n   versions may not work! You can get this version at\n   https://www.math.ohio-state.edu/~ilya/software/os2/pdksh-5.2.14-bin-2.zip\n - GNU file utilities (make sure that install.exe from the file utilities\n   is in front of your PATH before X:\\OS2\\INSTALL\\INSTALL.EXE. I recommend\n   also to change the filename to ginstall.exe instead of install.exe\n   to avoid confusion with X:\\OS2\\INSTALL\\INSTALL.EXE)\n - GNU shell utilities\n - GNU text utilities\n - gawk\n - grep\n - sed\n - GNU Make 3.79.1 (special OS/2 patched version) or higher\n - perl 5.005 or higher\n - GNU texinfo (you can use 3.1 (gnuinfo.zip), but I recommend 4.0)\n\nIf you want to recreate the configuration files (developers only!)\nyou need also: GNU m4 1.4, autoconf 2.59, automake 1.9.6 (or compatible)\n\n\nIII. ***** COMPILATION AND INSTALLATION *****\n\n a) ** Developers only - Everyone else should skip this section **\n    To recreate the configuration files use:\n\n      export EMXSHELL=ksh\n      aclocal -I m4\n      automake\n      autoconf\n      autoheader\n\n\nb) Installation into x:/usr\n\n   Note: Although it is possible to compile make using \"./configure\",\n         \"make\", \"make install\" this is not recommended.  In particular,\n         you must ALWAYS use LDFLAGS=\"-Zstack 0x6000\" because the default\n         stack size is far to small and make will not work properly!\n\nRecommended environment variables and installation options:\n\n    export ac_executable_extensions=\".exe\"\n    export CPPFLAGS=\"-D__ST_MT_ERRNO__\"\n    export CFLAGS=\"-O2 -Zomf -Zmt\"\n    export LDFLAGS=\"-Zcrtdll -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000\"\n    export RANLIB=\"echo\"\n    ./configure --prefix=x:/usr --infodir=x:/usr/share/info --mandir=x:/usr/share/man\n    make AR=emxomfar\n    make install\n\nNote: If you use gcc 2.9.x I recommend to set also LIBS=\"-lgcc\"\n\nNote: You can add -DNO_CMD_DEFAULT and -DNO_CHDIR2 to CPPFLAGS.\n      See section I. for details.\n\nNote: If you use Open Watcom Linker instead of IBM Linker, remove\n      '-Zlinker /exepack:2' from LDFLAGS.\n\n\nIV. ***** NLS support *****\n\nGNU Make has NLS (National Language Support), with the following\ncaveats:\n\n a) It will only work with GNU gettext, and\n b) GNU gettext support is not included in the GNU Make package.\n\nTherefore, if you wish to enable the internationalization features of\nGNU Make you must install GNU gettext on your system before configuring\nGNU Make.\n\nYou can choose the languages to be installed. To install support for\nEnglish, German and French only enter:\n\n  export LINGUAS=\"en de fr\"\n\nIf you don't specify LINGUAS all languages are installed.\n\nIf you don't want NLS support (English only) use the option\n--disable-nls for the configure script.  Note if GNU gettext is not\ninstalled then NLS will not be enabled regardless of this flag.\n\n\nV. ***** Running the make test suite *****\n\nTo run the included make test suite you have to set\n\n  CPPFLAGS=\"-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2\"\n\nbefore you compile make. This is due to some restrictions of the\ntestsuite itself. -DNO_CMD_DEFAULT causes make to use /bin/sh as default\nshell in every case. Normally you could simply set MAKESHELL=\"/bin/sh\"\nto do this but the testsuite ignores the environment. -DNO_CHDIR2 causes\nmake not to use drive letters for directory names (i.e. _chdir2() and\n_getcwd2() are NOT used).  The testsuite interprets the whole output of\nmake, especially statements like make[1]: Entering directory\n'C:/somewhere/make-3.79.1/tests' where the testsuite does not expect the\ndrive letter. This would be interpreted as an error even if there is\nnone.\n\nTo run the testsuite do the following:\n\n  export CPPFLAGS=\"-D__ST_MT_ERRNO__ -DNO_CMD_DEFAULT -DNO_CHDIR2\"\n  export CFLAGS=\"-Zomf -O2 -Zmt\"\n  export LDFLAGS=\"-Zcrtdll -s -Zlinker /exepack:2 -Zlinker /pm:vio -Zstack 0x6000\"\n  export RANLIB=\"echo\"\n  ./configure --prefix=x:/usr --disable-nls\n  make AR=emxomfar\n  make check\n\nAll tests should work fine with the exception of one of the \"INCLUDE_DIRS\"\ntests which will fail if your /usr/include directory is on a drive different\nfrom the make source tree.\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 2003-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.VMS",
    "content": "Overview:                                                       -*-text-mode-*-\n---------\n\n  This version of GNU Make has been tested on:\n  OpenVMS V8.3/V8.4 (Alpha) and V8.4 (Integrity) AND V7.3 (VAX)\n\n  This version of GNU Make is intended to be run from DCL to run\n  make scripts with a special syntax that is described below.  It\n  likely will not be able to run unmodified Unix makefiles.\n\n  There is an older implementation of GNU Make that was ported to GNV.\n  Work is now in progress to merge that port to get a single version\n  of GNU Make available.  When that merge is done, GNU Make will auto\n  detect that it is running under a POSIX shell and then operate as close to\n  GNU Make on Unix as possible.\n\n  The descriptions below are for running GNU Make from DCL or equivalent.\n\nRecipe differences:\n-------------------\n\n  GNU Make for OpenVMS can not currently run native Unix make files because of\n  differences in the implementation.\n\n  I am trying to document the current behavior in this section.  This is based\n  on the information in the file NEWS. and running the test suite.\n  TODO: More tests are needed to validate and demonstrate the OpenVMS\n  expected behavior.\n\n  In some cases the older behavior of GNU Make when run from DCL is not\n  compatible with standard makefile behavior.\n\n  This behavior can be changed when running GNU Make from DCL by setting\n  either DCL symbols or logical names of the format GNV$.  The settings\n  are enabled with a string starting with one of '1', 'T', or 'E' for \"1\",\n  \"TRUE\", or \"ENABLE\".  They are disabled with a '0', 'F', or 'D' for \"1\",\n  \"FALSE\", or \"DISABLE\".  If they are not explicitly set to one of these\n  values, then they will be set to their default values.\n\n  The value of the setting DECC$FILENAME_UNIX_REPORT or\n  DECC$FILENAME_UNIX_ONLY will now cause the $(dir x) function to return\n  './' or '[]' as appropriate.\n\n  The name GNV$MAKE_OLD_VMS when enabled will cause GNU Make to behave as\n  much as the older method as can be done with out disabling VMS features.\n  When it is disabled GNU Make have the new behavior which more closely\n  matches Unix Make behavior.\n\n  The default is currently the old behavior when running GNU Make from DCL.\n  In the future this may change.  When running make from GNV Bash the new\n  behavior is the default.\n\n  This is a global setting that sets the default behavior for several other\n  options that can be individually changed.  Many of the individual settings\n  are to make it so that the self tests for GNU Make need less VMS specific\n  modifications.\n\n  The name GNV$MAKE_COMMA when enabled will cause GNU Make to expect a comma\n  for a path separator and use a comma for the separator for a list of files.\n  When disabled, it will cause GNU Make to use a colon for a path separator\n  and a space for the separator for a list of files.  The default is to be\n  enabled if the GNU Make is set to the older behavior.\n\n  The name GNV$MAKE_SHELL_SIM when enabled will cause GNU Make to try to\n  simulate a POSIX shell more closely.  The following behaviors occur:\n\n    * Single quotes are converted to double quotes and any double\n      quotes inside of them are doubled.  No environment variable expansion\n      is simulated.\n    * A exit command status will be converted to a POSIX Exit\n      where 0 is success and non-zero is failure.\n    * The $ character will cause environment variable expansion.\n    * Environment variables can be set on the command line before a command.\n\n  VMS generally uses logical name search lists instead of path variables\n  where the resolution is handled by VMS independent of the program.  Which\n  means that it is likely that nothing will notice if the default path\n  specifier is changed in the future.\n\n  Currently the built in VMS specific macros and recipes depend on the comma\n  being used as a file list separator.\n  TODO: Remove this dependency as other functions in GNU Make depend on a\n  space being used as a separator.\n\n  The format for recipes are a combination of Unix macros, a subset of\n  simulated UNIX commands, some shell emulation, and OpenVMS commands.\n  This makes the resulting makefiles unique to the OpenVMS port of GNU Make.\n\n  If you are creating a OpenVMS specific makefile from scratch, you should also\n  look at MMK (Madgoat Make) available at https://github.com/endlesssoftware/mmk\n  MMK uses full OpenVMS syntax and a persistent sub-process is used for the\n  recipe lines, allowing multiple line rules.\n\n  The default makefile search order is \"makefile.vms\", \"gnumakefile\",\n  \"makefile\".  TODO: See if that lookup is case sensitive.\n\n  When Make is invoked from DCL, it will create a foreign command\n  using the name of executable image, with any facility prefix removed,\n  for the duration of the make program, so it can be used internally\n  to recursively run make().  The macro MAKE_COMMAND will be set to\n  this foreign command.\n\n  When make is launched from an exec*() command from a C program,\n  the foreign command is not created.  The macro MAKE_COMMAND will be\n  set to the actual command passed as argv[0] to the exec*() function.\n\n  If the DCL symbol or logical name GNV$MAKE_USE_MCR exists, then\n  the macro MAKE_COMMAND will be set to be an \"MCR\" command with the\n  absolute path used by DCL to launch make.  The foreign command\n  will not be created.\n\n  The macro MAKE is set to be the same value as the macro MAKE_COMMAND\n  on all platforms.\n\n  Each recipe command is normally run as a separate spawned processes,\n  except for the cases documented below where a temporary DCL command\n  file may be used.\n\n  BUG: Testing has shown that the commands in the temporary command files\n  are not always created properly.  This issue is still under investigation.\n\n  Any macros marked as exported are temporarily created as DCL symbols\n  for child images to use.  DCL symbol substitution is not done with these\n  commands.\n  Untested: Symbol substitution.\n\n  When a temporary DCL command file is used, DCL symbol substitution\n  will work.\n\n  For VMS 7.3-1 and earlier, command lines are limited to 255 characters\n  or 1024 characters in a command file.\n  For VMS 7.3-2 and later, command lines are limited to 4059 characters\n  or 8192 characters in a command file.\n\n  VMS limits each token of a command line to 256 characters, and limits\n  a command line to 127 tokens.\n\n  Command lines above the limit length are written to a command file\n  in sys$scratch:.\n\n  In order to handle Unix style extensions to VMS DCL, GNU Make has\n  parsed the recipe commands and them modified them as needed.  The\n  parser has been re-written to resolve numerous bugs in handling\n  valid VMS syntax and potential buffer overruns.\n\n  The new parser may need whitespace characters where DCL does not require\n  it, and also may require that quotes are matched were DCL forgives if\n  they are not.  There is a small chance that existing VMS specific makefiles\n  will be affected.\n\n  The '<', '>' was previously implemented using command files.  Now\n  GNU Make will check to see if the is already a VMS \"PIPE\" command and\n  if it is not, will convert the command to a VMS \"PIPE\" command.\n\n  The '>>' redirection has been implemented by using a temporary command file.\n  This will be described later.\n\n  The DCL symbol or logical name GNV$MAKE_USE_CMD_FILE when set to a\n  string starting with one of '1','T', or 'E' for \"1\", \"TRUE\", or \"ENABLE\",\n  then temporary DCL command files are always used for running commands.\n\n  Some recipe strings with embedded new lines will not be handled correctly\n  when a command file is used.\n\n  GNU Make generally does text comparisons for the targets and sources.  The\n  make program itself can handle either Unix or OpenVMS format filenames, but\n  normally does not do any conversions from one format to another.\n  TODO: The OpenVMS format syntax handling is incomplete.\n  TODO: ODS-5 EFS support is missing.\n  BUG: The internal routines to convert filenames to and from OpenVMS format\n  do not work correctly.\n\n  Note: In the examples below, line continuations such as a backslash may have\n  been added to make the examples easier to read in this format.\n  BUG: That feature does not completely work at this time.\n\n  Since the OpenVMS utilities generally expect OpenVMS format paths, you will\n  usually have to use OpenVMS format paths for rules and targets.\n  BUG: Relative OpenVMS paths may not work in targets, especially combined\n  with vpaths.  This is because GNU Make will just concatenate the directories\n  as it does on Unix.\n\n  The variables $^ and $@ separate files with commas instead of spaces.\n  This is controlled by the name GNV$MAKE_COMMA as documented in the\n  previous section.\n\n  While this may seem the natural thing to do with OpenVMS, it actually\n  causes problems when trying to use other make functions that expect the\n  files to be separated by spaces.  If you run into this, you need the\n  following workaround to convert the output.\n  TODO: Look at have the $^ and $@ use spaces like on Unix and have\n  and easy to use function to do the conversions and have the built\n  in OpenVMS specific recipes and macros use it.\n\n  Example:\n\ncomma := ,\nempty :=\nspace := $(empty) $(empty)\n\nfoo: $(addsuffix .3,$(subs $(comma),$(space),$^)\n\n\n  Makefile variables are looked up in the current environment. You can set\n  symbols or logicals in DCL and evaluate them in the Makefile via\n  $(<name-of-symbol-or-logical>).  Variables defined in the Makefile\n  override OpenVMS symbols/logicals.\n\n  OpenVMS logical and symbols names show up as \"environment\" using the\n  origin function.  when the \"-e\" option is specified, the origin function\n  shows them as \"environment override\".  On POSIX the test scripts indicate\n  that they should show up just as \"environment\".\n\n  When GNU Make reads in a symbol or logical name into the environment, it\n  converts any dollar signs found to double dollar signs for convenience in\n  using DCL symbols and logical names in recipes.  When GNU Make exports a\n  DCL symbol for a child process, if the first dollar sign found is followed\n  by second dollar sign, then all double dollar signs will be converted to\n  single dollar signs.\n\n  The variable $(ARCH) is predefined as IA64, ALPHA or VAX respectively.\n  Makefiles for different OpenVMS systems can now be written by checking\n  $(ARCH).  Since IA64 and ALPHA are similar, usually just a check for\n  VAX or not VAX is sufficient.\n\n  You may have to update makefiles that assume VAX if not ALPHA.\n\nifeq ($(ARCH),VAX)\n  $(ECHO) \"On the VAX\"\nelse\n  $(ECHO) \"On the ALPHA  or IA64\"\nendif\n\n  Empty commands are handled correctly and don't end in a new DCL process.\n\n  The exit command needs to have OpenVMS exit codes.  To pass a POSIX code\n  back to the make script, you need to encode it by multiplying it by 8\n  and then adding %x1035a002 for a failure code and %x1035a001 for a\n  success.  Make will interpret any POSIX code other than 0 as a failure.\n  TODO: Add an option have simulate POSIX exit commands in recipes.\n\n  Lexical functions can be used in pipes to simulate shell file test rules.\n\n  Example:\n\n  POSIX:\nb : c ; [ -f $@ ] || echo >> $@\n\n  OpenVMS:\nb : c ; if f$$search(\"$@\") then pipe open/append xx $@ ; write xx \"\" ; close xx\n\n\n  You can also use pipes and turning messages off to silently test for a\n  failure.\n\nx = %x1035a00a\n\n%.b : %.c\n<tab>pipe set mess/nofac/noiden/nosev/notext ; type $^/output=$@ || exit $(x)\n\n\nRuntime issues:\n\n  The OpenVMS C Runtime has a convention for encoding a POSIX exit status into\n  to OpenVMS exit codes.  These status codes will have the hex value of\n  0x35a000.  OpenVMS exit code may also have a hex value of %x10000000 set on\n  them.  This is a flag to tell DCL not to write out the exit code.\n\n  To convert an OpenVMS encoded POSIX exit status code to the original code\n  You subtract %x35a000 and any flags from the OpenVMS code and divide it by 8.\n\n  WARNING: Backward-incompatibility!\n  The make program exit now returns the same encoded POSIX exit code as on\n  Unix. Previous versions returned the OpenVMS exit status code if that is what\n  caused the recipe to fail.\n  TODO: Provide a way for scripts calling make to obtain that OpenVMS status\n  code.\n\n  Make internally has two error codes, MAKE_FAILURE and MAKE_TROUBLE.  These\n  will have the error \"-E-\" severity set on exit.\n\n  MAKE_TROUBLE is returned only if the option \"-q\" or \"--question\" is used and\n  has a POSIX value of 1 and an OpenVMS status of %x1035a00a.\n\n  MAKE_FAILURE has a POSIX value of 2 and an OpenVMS status of %x1035a012.\n\n  Output from GNU Make may have single quotes around some values where on\n  other platforms it does not.  Also output that would be in double quotes\n  on some platforms may show up as single quotes on VMS.\n\n  There may be extra blank lines in the output on VMS.\n  https://savannah.gnu.org/bugs/?func=detailitem&item_id=41760\n\n  There may be a \"Waiting for unfinished jobs...\" show up in the output.\n\n  Error messages generated by Make or Unix utilities may slightly vary from\n  POSIX platforms.  Typically the case may be different.\n\n  When make deletes files, on POSIX platforms it writes out 'rm' and the list\n  of files.  On VMS, only the files are written out, one per line.\n  TODO: VMS\n\n  There may be extra leading white space or additional or missing whitespace\n  in the output of recipes.\n\n  GNU Make uses sys$scratch: for the tempfiles that it creates.\n\n  The OpenVMS CRTL library maps /tmp to sys$scratch if the TMP: logical name\n  does not exist.  As the CRTL may use both sys$scratch: and /tmp internally,\n  if you define the TMP logical name to be different than SYS$SCRATCH:,\n  you may end up with only some temporary files in TMP: and some in SYS$SCRATCH:\n\n  The default include directory for including other makefiles is\n  SYS$SYSROOT:[SYSLIB] (I don't remember why I didn't just use\n  SYS$LIBRARY: instead; maybe it wouldn't work that way).\n  TODO:  A better default may be desired.\n\n  If the device for a file in a recipe does not exist, on OpenVMS an error\n  message of \"stat: <file>: no such device or address\" will be output.\n\n  Make ignores success, informational, or warning errors (-S-, -I-, or\n  -W-).  But it will stop on -E- and -F- errors. (unless you do something\n  to override this in your makefile, or whatever).\n\n\nUnix compatibility features:\n----------------------------\n\n  If the command 'echo' is seen, any single quotes on the line will be\n  converted to double quotes.\n\n  The variable $(CD) is implemented as a built in Change Directory\n  command. This invokes the 'builtin_cd'  Executing a 'set default'\n  recipe doesn't do the trick, since it only affects the sub-process\n  spawned for that command.\n\n  The 'builtin_cd' is generally expected to be on its own line.\n  The 'builtin_cd' either from the expansion of $(CD) or directly\n  put in a recipe line will be executed before any other commands in\n  that recipe line.  DCL parameter substitution will not work for the\n  'builtin_cd' command.\n\n  Putting a 'builtin_cd' in a pipeline or an IF-THEN line should not be\n  done because the 'builtin_cd' is always executed\n  and executed first.  The directory change is persistent.\n\n  Unix shell style I/O redirection is supported. You can now write lines like:\n  \"<tab>mcr sys$disk:[]program.exe < input.txt > output.txt &> error.txt\"\n\n  POSIX shells have \":\" as a null command.  These are now handled.\n  https://savannah.gnu.org/bugs/index.php?41761\n\n  A note on appending the redirected output.  A simple mechanism is\n  implemented to make \">>\" work in action lines. In OpenVMS there is no simple\n  feature like \">>\" to have DCL command or program output redirected and\n  appended to a file. GNU Make for OpenVMS implements the redirection\n  of \">>\" by using a command procedure.\n\n  The current algorithm creates the output file if it does not exist and\n  then uses the DCL open/append to extend it.  SYS$OUTPUT is then directed\n  to that file.\n\n  The implementation supports only one redirected append output to a file\n  and that redirection is done before any other commands in that line\n  are executed, so it redirects all output for that command.\n\n  The older implementation wrote the output to a temporary file in\n  in sys$scratch: and then attempted to append the file to the existing file.\n  The temporary file names looked like \"CMDxxxxx.\". Any time the created\n  command procedure can not complete, this happens. Pressing CTRL+Y to\n  abort make is one case.\n\n  In case of CTRL+Y the associated command procedure is left in SYS$SCRATCH:.\n  The command procedures will be named gnv$make_cmd*.com.\n\n  The CtrlY handler now uses $delprc to delete all children. This way also\n  actions with DCL commands will be stopped. As before the CtrlY handler\n  then sends SIGQUIT to itself, which is handled in common code.\n\n  Temporary command files are now deleted in the OpenVMS child termination\n  handler. That deletes them even if a CTRL+C was pressed.\n  TODO: Does the previous section about >> leaving files still apply?\n\n  The behavior of pressing CTRL+C is not changed. It still has only an effect,\n  after the current action is terminated. If that doesn't happen or takes too\n  long, CTRL+Y should be used instead.\n\n\nBuild Options:\n\n  Added support to have case sensitive targets and dependencies but to\n  still use case blind file names. This is especially useful for Java\n  makefiles on VMS:\n\n<TAB>.SUFFIXES :\n<TAB>.SUFFIXES : .class .java\n<TAB>.java.class :\n<TAB><TAB>javac \"$<\"\n<TAB>HelloWorld.class :      HelloWorld.java\n\n  A new macro WANT_CASE_SENSITIVE_TARGETS in config.h-vms was introduced.\n  It needs to be enabled to get this feature; default is disabled.\n  TODO: This should be a run-time setting based on if the process\n  has been set to case sensitive.\n\n\nUnimplemented functionality:\n\n  The new feature \"Loadable objects\" is not yet supported. If you need it,\n  please send a change request or submit a bug report.\n\n  The new option --output-sync (-O) is accepted but has no effect: GNU Make\n  for OpenVMS does not support running multiple commands simultaneously.\n\n\nSelf test failures and todos:\n-----------------------------\n\n  The test harness can not handle testing some of the VMS specific modes\n  because of the features needed for to be set for the Perl to run.\n  Need to find a way to set the VMS features before running make as a\n  child.\n\n  GNU Make was not currently translating the OpenVMS encoded POSIX values\n  returned to it back to the POSIX values.  I have temporarily modified the\n  Perl test script to compensate for it.  This should be being handled\n  internally to Make.\n  TODO: Verify and update the Perl test script.\n\n  The features/parallelism test was failing. OpenVMS is executing the rules\n  in sequence not in parallel as this feature was not implemented.\n  GNU Make on VMS no longer claims it is implemented.\n  TODO: Implement it.\n\n  Symlink support is not present.  Symlinks are supported by OpenVMS 8.3 and\n  later.\n\n  Error messages should be suppressed with the \"-\" at the beginning of a line.\n  On openVMS they were showing up.  TODO: Is this still an issue?\n\n  The internal vmsify and unixify OpenVMS to/from UNIX are not handling logical\n  names correctly.\n\n\nBuild instructions:\n-------------------\n\n  Don't use the HP C V7.2-001 compiler, which has an incompatible change\n  how __STDC__ is defined. This results at least in compile time warnings.\n\nMake a 1st version\n       $ @makefile.com  ! ignore any compiler and/or linker warning\n       $ copy make.exe 1st-make.exe\n\n  Use the 1st version to generate a 2nd version as a test.\n       $ mc sys$disk:[]1st-make clean  ! ignore any file not found messages\n       $ mc sys$disk:[]1st-make\n\n  Verify your 2nd version by building Make again.\n       $ copy make.exe 2nd-make.exe\n       $ mc sys$disk:[]2nd-make clean\n       $ mc sys$disk:[]2nd-make\n\n\nRunning the tests:\n------------------\n\n  Running the tests on OpenVMS requires the following software to be installed\n  as most of the tests are Unix oriented.\n\n  * Perl 5.18 or later.\n    https://sourceforge.net/projects/vmsperlkit/files/\n  * GNV 2.1.3 + Updates including a minimum of:\n    * Bash 4.3.30\n    * ld_tools 3.0.2\n    * coreutils 8.21\n   https://sourceforge.net/p/gnv/wiki/InstallingGNVPackages/\n   https://sourceforge.net/projects/gnv/files/\n\n   As the test scripts need to create some foreign commands that persist\n   after the test is run, it is recommend that either you use a sub-process or\n   a dedicated login to run the tests.\n\n   To get detailed information for running the tests:\n\n   $ set default [.tests]\n   $ @run_make_tests help\n\n   Running the script with no parameters will run all the tests.\n\n   After the the test script has been run once in a session, assuming\n   that you built make in sys$disk:[make], you can redefined the\n   \"bin\" logical name as follows:\n\n   $ define bin sys$disk:[make],gnv$gnu:[bin]\n\n   Then you can use Perl to run the scripts.\n\n   $ perl run_make_tests.pl\n\n\nAcknowledgments:\n----------------\n\nSee NEWS. for details of past changes.\n\n  These are the currently known contributors to this port.\n\n  Hartmut Becker\n  John Malmberg\n  Michael Gehre\n  John Eisenbraun\n  Klaus Kaempf\n  Mike Moretti\n  John W. Eaton\n"
  },
  {
    "path": "README.W32",
    "content": "This version of GNU Make has been tested on:\n  Microsoft Windows 2000/XP/2003/Vista/7/8/10/11\nIt has also been used on Windows 95/98/NT, and on OS/2.\n\nIt builds with the MinGW port of GCC (tested with GCC 3.4.2, 4.8.1,\nand 4.9.3).\n\nIt also builds with MSVC 2.x, 4.x, 5.x, 6.x, 2005, 2008, 2010, 2012,\n2013, and 2015 as well as with .NET 7.x and .NET 2003.\n\nBuilding with Guile is supported (tested with Guile 2.0.x).  To build\nwith Guile, you will need, in addition to Guile itself, its dependency\nlibraries and the pkg-config program.  The latter is used to figure out\nwhich compilation and link switches and libraries need to be mentioned\non the compiler command lines to correctly link with Guile.  A Windows\nport of pkg-config can be found on ezwinports site:\n\n  https://sourceforge.net/projects/ezwinports/\n\nThe libraries on which Guile depends can vary depending on your\nversion and build of Guile.  At the very least, the Boehm's GC library\nwill be needed, and typically also GNU MP, libffi, libunistring, and\nlibtool's libltdl.  Whoever built the port of Guile you have should\nalso provide you with these dependencies or a URL where to download\nthem.  A precompiled 32-bit Windows build of Guile is available from\nthe ezwinports site mentioned above.\n\nThe Windows port of GNU Make is maintained jointly by various people.\nIt was originally made by Rob Tulloh.\nIt is currently maintained by Eli Zaretskii.\n\n\nDo this first, regardless of the build method you choose:\n---------------------------------------------------------\n\n 1. If you have special requirements, edit config.h.W32 to your liking\n    (especially the shell-related defines, or HAVE_CASE_INSENSITIVE_FS which\n    corresponds to './configure --enable-case-insensitive-file-system').  We\n    don't recommend to define HAVE_CASE_INSENSITIVE_FS, but you may wish to\n    consider that if you have a lot of files whose names are in upper case,\n    while Makefile rules are written for lower-case versions.\n\n    If you don't have special requirements no changes are needed.\n\n\nBuilding with (MinGW-)GCC using build_w32.bat\n---------------------------------------------\n\n 2. Open a W32 command prompt for your installed (MinGW-)GCC, setup a\n    correct PATH and other environment variables for it, then execute ...\n\n        .\\build_w32.bat gcc\n\n    This produces gnumake.exe in the GccRel directory.\n\n    If you want a version of GNU Make built with debugging enabled,\n    add the --debug option.  Output goes into the GccDebug directory.\n\n    The batch file will probe for Guile installation, and will build\n    gnumake.exe with Guile if it finds it.  If you have Guile\n    installed, but want to build Make without Guile support, type\n\n        .\\build_w32.bat --without-guile gcc\n\n\nBuilding with (MSVC++-)cl using build_w32.bat\n---------------------------------------------\n\n 2. Open a command shell, then execute ...\n\n        .\\build_w32.bat\n\n    This produces a 64bit Release build of gnumake.exe in .\\WinRel, using\n    the compiler found on the %Path%.  If no compiler is found, the batch\n    file will probe your system and choose the newest MSVC version it can\n    find.\n\n    If you want a 32bit version of GNU Make, add the --x86 option.\n\n    If you want a Debug build of GNU Make, add the --debug option.  Output\n    will go into the .\\WinDebug directory.\n\n    The batch file will probe for Guile installation, and will build\n    gnumake.exe with Guile if it finds it.  If Guile is installed,\n    but you prefer to build GNU Make without Guile support, add the\n    --without-guile option.\n\n\nBuilding with (MinGW-)GCC using GNU Make\n----------------------------------------\n\n 2. If you already have a version of GNU Make available you can use it\n    to build this version.  Open a W32 command prompt for your installed\n    (MinGW-)GCC, setup a correct PATH and other environment variables\n    for it, then execute ...\n\n        make -f Basic.mk TOOLCHAIN=gcc\n\n    This produces GccRel\\gnumake.exe.\n    If you want a version of GNU Make built with debugging enabled,\n    add the TARGET_TYPE=debug option:\n\n        make -f Basic.mk TOOLCHAIN=gcc TARGET_TYPE=debug\n\n    The makefile doesn't support Guile integration.  Use build_w32.bat\n    if you want to build with Guile support.\n\n\nBuilding with (MSVC++-)cl using GNU Make\n----------------------------------------\n\n 2. If you already have a version of GNU Make available you can use it\n    to build this version.  Open a W32 command prompt for your installed\n    (MSVC++-)cl, setup a correct PATH and other environment variables\n    for it (usually via executing vcvars32.bat or vsvars32.bat from the\n    cl-installation, or using a corresponding start menu entry from the\n    cl-installation), then execute ...\n\n        make -f Basic.mk\n\n    This produces an optimized WinRel/gnumake.exe.\n    If you want a version of GNU Make built with debugging enabled,\n    add the TARGET_TYPE=debug option:\n\n        make -f Basic.mk TARGET_TYPE=debug\n\n    The makefile doesn't support Guile integration.  Use build_w32.bat\n    if you want to build with Guile support.\n\n\nRunning the test suite\n----------------------\n\n 3. You will need an installation of Perl.  Be sure to use a relatively\n    modern version: older versions will sometimes throw spurious errors.\n\n    To run the suite after building using GNU Make, use:\n\n        make -f Basic.mk check\n\n    Alternatively if you'd like to run tests by hand, use:\n\n        cd tests\n        .\\run_make_tests.bat -make <path-to-make>\n\n    I've found <path-to-make> seems to want forward-slashes in the path.\n    For example if building with .\\build_w32.bat non-debug, use:\n\n        cd tests\n        .\\run_make_tests.bat -make ../WinRel/gnumake.exe\n\n    I've tested this with the MSYS2 shell and POSIX tools installation\n    that you get by installing Git for Windows.\n\n\n\n-------------------\n-- Notes/Caveats --\n-------------------\n\nGNU Make on Windows 32-bit platforms:\n\n        This version of make is ported natively to Windows32 platforms\n        (Windows NT 3.51, Windows NT 4.0, Windows 2000, Windows XP,\n        Windows 95, and Windows 98). It does not rely on any 3rd party\n        software or add-on packages for building. The only thing\n        needed is a Windows compiler.  Two compilers supported\n        officially are the MinGW port of GNU GCC, and the various\n        versions of the Microsoft C compiler.\n\n        Do not confuse this port of GNU Make with other Windows32 projects\n        which provide a GNU Make binary. These are separate projects\n        and are not connected to this port effort.\n\nGNU Make and sh.exe:\n\n        This port prefers if you have a working sh.exe somewhere on\n        your system. If you don't have sh.exe, the port falls back to\n        MSDOS mode for launching programs (via a batch file).  The\n        MSDOS mode style execution has not been tested that carefully\n        though (The author uses GNU bash as sh.exe).\n\n        There are very few true ports of Bourne shell for NT right now.\n        There is a version of GNU bash available from Cygnus \"Cygwin\"\n        porting effort (https://www.cygwin.com/).\n        Other possibilities are the MKS version of sh.exe, or building\n        your own with a package like NutCracker (DataFocus) or Portage\n        (Consensys).  Also MinGW includes sh.\n\nGNU Make and brain-dead shells (BATCH_MODE_ONLY_SHELL):\n\n        Some versions of Bourne shell do not behave well when invoked\n        as 'sh -c' from CreateProcess().  The main problem is they seem\n        to have a hard time handling quoted strings correctly. This can\n        be circumvented by writing commands to be executed to a batch\n        file and then executing the command by calling 'sh file'.\n\n        To work around this difficulty, this version of make supports\n        a batch mode.  When BATCH_MODE_ONLY_SHELL is defined at compile\n        time, make forces all command lines to be executed via script\n        files instead of by command line.  In this mode you must have a\n        working sh.exe in order to use parallel builds (-j).\n\n        A native Windows32 system with no Bourne shell will also run\n        in batch mode.  All command lines will be put into batch files\n        and executed via $(COMSPEC) (%COMSPEC%).  However, parallel\n        builds ARE supported with Windows shells (cmd.exe and\n        command.com).  See the next section about some peculiarities\n        of parallel builds on Windows.\n\nSupport for parallel builds\n\n        Parallel builds (-jN) are supported in this port.  The number of\n        concurrent processes has a hard limit of 4095.\n\nGNU Make and Cygnus GNU Windows32 tools:\n\n        Good news! Make now has native support for Cygwin sh. To enable,\n        define the HAVE_CYGWIN_SHELL in config.h and rebuild make\n        from scratch. This version of make tested with B20.1 of Cygwin.\n        Do not define BATCH_MODE_ONLY_SHELL if you use HAVE_CYGWIN_SHELL.\n\nGNU Make and the MKS shell:\n\n        There is now semi-official support for the MKS shell. To turn this\n        support on, define HAVE_MKS_SHELL in the config.h.W32 before you\n        build make.  Do not define BATCH_MODE_ONLY_SHELL if you turn\n        on HAVE_MKS_SHELL.\n\nGNU Make handling of drive letters in pathnames (PATH, vpath, VPATH):\n\n        There is a caveat that should be noted with respect to handling\n        single character pathnames on Windows systems.  When colon is\n        used in PATH variables, make tries to be smart about knowing when\n        you are using colon as a separator versus colon as a drive\n        letter.  Unfortunately, something as simple as the string 'x:/'\n        could be interpreted 2 ways: (x and /) or (x:/).\n\n        Make chooses to interpret a letter plus colon (e.g. x:/) as a\n        drive letter pathname.  If it is necessary to use single\n        character directories in paths (VPATH, vpath, Path, PATH), the\n        user must do one of two things:\n\n         a. Use semicolon as the separator to disambiguate colon. For\n            example use 'x;/' if you want to say 'x' and '/' are\n            separate components.\n\n         b. Qualify the directory name so that there is more than\n            one character in the path(s) used. For example, none\n            of these settings are ambiguous:\n\n              ./x:./y\n              /some/path/x:/some/path/y\n              x:/some/path/x:x:/some/path/y\n\n        Please note that you are free to mix colon and semi-colon in the\n        specification of paths.  Make is able to figure out the intended\n        result and convert the paths internally to the format needed\n        when interacting with the operating system, providing the path\n        is not within quotes, e.g. \"x:/test/test.c\".\n\n        You are encouraged to use colon as the separator character.\n        This should ease the pain of deciding how to handle various path\n        problems which exist between platforms.  If colon is used on\n        both Unix and Windows systems, then no ifdef'ing will be\n        necessary in the makefile source.\n\nPathnames and white space:\n\n        Unlike Unix, Windows 95/NT systems encourage pathnames which\n        contain white space (e.g. C:\\Program Files\\). These sorts of\n        pathnames are valid on Unix too, but are never encouraged.\n        There is at least one place in make (VPATH/vpath handling) where\n        paths containing white space will simply not work. There may be\n        others too. I chose to not try and port make in such a way so\n        that these sorts of paths could be handled. I offer these\n        suggestions as workarounds:\n\n                1. Use 8.3 notation. i.e. \"x:/long~1/\", which is actually\n                   \"x:\\longpathtest\".  Type \"dir /x\" to view these filenames\n                   within the cmd.exe shell.\n                2. Rename the directory so it does not contain white space.\n\n        If you are unhappy with this choice, this is free software\n        and you are free to take a crack at making this work. The code\n        in w32/pathstuff.c and vpath.c would be the places to start.\n\nPathnames and Case insensitivity:\n\n        Unlike Unix, Windows 95/NT systems are case insensitive but case\n        preserving.  For example if you tell the file system to create a\n        file named \"Target\", it will preserve the case.  Subsequent access to\n        the file with other case permutations will succeed (i.e. opening a\n        file named \"target\" or \"TARGET\" will open the file \"Target\").\n\n        By default, GNU Make retains its case sensitivity when comparing\n        target names and existing files or directories.  It can be\n        configured, however, into a case preserving and case insensitive\n        mode by adding a define for HAVE_CASE_INSENSITIVE_FS to\n        config.h.W32.\n\n        For example, the following makefile will create a file named\n        Target in the directory subdir which will subsequently be used\n        to satisfy the dependency of SUBDIR/DepTarget on SubDir/TARGET.\n        Without HAVE_CASE_INSENSITIVE_FS configured, the dependency link\n        will not be made:\n\n        subdir/Target:\n                touch $@\n\n        SUBDIR/DepTarget: SubDir/TARGET\n                cp $^ $@\n\n        Reliance on this behavior also eliminates the ability of GNU Make\n        to use case in comparison of matching rules.  For example, it is\n        not possible to set up a C++ rule using %.C that is different\n        than a C rule using %.c.  GNU Make will consider these to be the\n        same rule and will issue a warning.\n\nSAMBA/NTFS/VFAT:\n\n        I have not had any success building the debug version of this\n        package using SAMBA as my file server. The reason seems to be\n        related to the way VC++ 4.0 changes the case name of the pdb\n        filename it is passed on the command line. It seems to change\n        the name always to to lower case. I contend that the VC++\n        compiler should not change the casename of files that are passed\n        as arguments on the command line. I don't think this was a\n        problem in MSVC 2.x, but I know it is a problem in MSVC 4.x.\n\n        The package builds fine on VFAT and NTFS filesystems.\n\n        Most all of the development I have done to date has been using\n        NTFS and long file names. I have not done any considerable work\n        under VFAT. VFAT users may wish to be aware that this port of\n        make does respect case sensitivity.\n\nFAT:\n\n        Version 3.76 added support for FAT filesystems. Make works\n        around some difficulties with stat'ing of files and caching of\n        filenames and directories internally.\n\nBug reports:\n\n        Please submit bugs via the normal bug reporting mechanism which\n        is described in the GNU Make manual and the base README.\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.customs",
    "content": "                                                            -*-indented-text-*-\n\nGNU Make can utilize the Customs library, distributed with Pmake, to\nprovide builds distributed across multiple hosts.\n\nIn order to utilize this capability, you must first download and build\nthe Customs library.  It is contained in the Pmake distribution, which\ncan be obtained at:\n\n  ftp://ftp.icsi.berkeley.edu/pub/ai/stolcke/software/\n\nThis integration was tested (superficially) with Pmake 2.1.33.\n\n\nBUILDING CUSTOMS\n----------------\n\nFirst, build pmake and Customs.  You need to build pmake first, because\nCustoms require pmake to build.  Unfortunately, this is not trivial;\nplease see the pmake and Customs documentation for details.  The best\nplace to look for instructions is in the pmake-2.1.33/INSTALL file.\n\nNote that the 2.1.33 Pmake distribution comes with a set of patches to\nGNU Make, distributed in the pmake-2.1.33/etc/gnumake/ directory.  These\npatches are based on GNU Make 3.75 (there are patches for earlier\nversions of GNU Make, also).  The parts of this patchfile which relate\ndirectly to Customs support have already been incorporated into this\nversion of GNU Make, so you should _NOT_ apply the patch file.\n\nHowever, there are a few non-Customs specific (as far as I could tell)\nchanges here which are not incorporated (for example, the modification\nto try expanding -lfoo to libfoo.so).  If you rely on these changes\nyou'll need to re-apply them by hand.\n\nInstall the Customs library and header files according to the\ndocumentation.  You should also install the man pages (contrary to\ncomments in the documentation, they weren't installed automatically for\nme; I had to cd to the 'pmake-2.1.33/doc' directory and run 'pmake\ninstall' there directly).\n\n\nBUILDING GNU MAKE\n-----------------\n\nOnce you've installed Customs, you can build GNU Make to use it.  When\nconfiguring GNU Make, merely use the '--with-customs=DIR' option.\nProvide the directory containing the 'lib' and 'include/customs'\nsubdirectories as DIR.  For example, if you installed the customs\nlibrary in /usr/local/lib and the headers in /usr/local/include/customs,\nthen you'd pass '--with-customs=/usr/local' as an option to configure.\n\nRun make (or use build.sh) normally to build GNU Make as described in\nthe INSTALL file.\n\nSee the documentation for Customs for information on starting and\nconfiguring Customs.\n\n\nINVOKING CUSTOMS-IZED GNU MAKE\n-----------------------------\n\nOne thing you should be aware of is that the default build environment\nfor Customs requires root permissions.  Practically, this means that GNU\nmake must be installed setuid root to use Customs.\n\nIf you don't want to do this, you can build Customs such that root\npermissions are not necessary.  Andreas Stolcke <stolcke@speech.sri.com>\nwrites:\n\n > pmake, gnumake or any other customs client program is not required to\n > be suid root if customs was compiled WITHOUT the USE_RESERVED_PORTS\n > option in customs/config.h.  Make sure the \"customs\" service in\n > /etc/services is defined accordingly (port 8231 instead of 1001).\n\n > Not using USE_RESERVED_PORTS means that a user with programming\n > skills could impersonate another user by writing a fake customs\n > client that pretends to be someone other than himself.  See the\n > discussion in etc/SECURITY.\n\n\nPROBLEMS\n--------\n\nSunOS 4.1.x:\n  The customs/sprite.h header file #includes the <malloc.h> header\n  files; this conflicts with GNU Make's configuration so you'll get a\n  compile error if you use GCC (or any other ANSI-capable C compiler).\n\n  I commented out the #include in sprite.h:107:\n\n    #if defined(sun) || defined(ultrix) || defined(hpux) || defined(sgi)\n    /* #include <malloc.h> */\n    #else\n\n  YMMV.\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1998-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.git",
    "content": "                                                                     -*-text-*-\n\n-------------------------------------------------------------------------------\nCopyright (C) 2002-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n-------------------------------------------------------------------------------\n\nObtaining Git Code\n------------------\n\nThis seems redundant, since if you're reading this you most likely have\nalready performed this step; however, for completeness, you can obtain the GNU\nmake source code via Git from the FSF's Savannah project\n<https://savannah.gnu.org/projects/make/>:\n\n  $ git clone git://git.savannah.gnu.org/make.git\n\n\nChanges using Git\n-----------------\n\nIf you do not have push privileges to the GNU Make Git repository, see the\nREADME file section \"Submitting Patches\" for information.\n\nIf you have push privileges to the GNU Make Git repository keep this\ninformation in mind:\n\nStarting with GNU Make 4.0 we no longer keep a separate ChangeLog file in\nsource control.  We use the Gnulib git-to-changelog conversion script to\nconvert the Git comments into ChangeLog-style entries for release.  As a\nresult, please format your Git comments carefully so they will look clean\nafter conversion.  In particular, each line of your comment will have a TAB\nadded before it so be sure your comment lines are not longer than 72\ncharacters; prefer 70 or less.  Please use standard ChangeLog formats for\nyour commit messages (sans the leading TAB of course).\n\nRule #1: Don't rewrite pushed history on master (no \"git push --force\").\nRule #2: Feel free to rewrite pushed history on personal branches.\nRule #3: Squash-merge or rebase + merge --ff-only, rather than merging from\n         personal branches into master.\n\nTypical simple workflow might be:\n\n  * Edit files / make / make check\n  * Use \"git status\" and \"git diff\" to verify your changes\n  * Use \"git add\" to stage the changes you want to make\n  * Use \"git commit\" to commit the staged changes to your local repository\n  * Use \"git pull -r\" to accept new changes from the upstream repository\n  * Use \"git push\" to push your commits back to the upstream repository\n\nFor Emacs users, there are many options for Git integration but I strongly\nrecommend Magit: https://magit.vc/  It makes the workflow much clearer, and\nhas advanced features such as constructing multiple commits from various files\nand even from different diff chunks in the same file.  There is a video\navailable which helps a lot.\n\n\nCoding Standards\n----------------\n\nGNU Make code adheres to the GNU Coding Standards.  Please use only spaces and\nno TAB characters in source code.\n\nAdditionally, GNU Make is a foundational bootstrap package for the GNU\nproject; as such it is conservative about language features it expects.\nHowever, GNU Make does rely on the Gnulib portability library, and Gnulib\ncurrently requires a ISO C99 compiler.  So features in ISO C99 can be\nassumed.\n\n\nBuilding From Git for POSIX\n---------------------------\n\nTo build GNU Make from Git on POSIX systems such as GNU/Linux, you will\nneed to install the following extra software:\n\n* autoconf >= 2.69\n* automake >= 1.16.1\n* autopoint\n* texinfo (for makeinfo)\n* gettext\n* pkg-config\n* GCC\n* GNU Make (POSIX make is not sufficient)\n\nAnd any tools that those utilities require (GNU m4, etc.)\n\nTo run the tests you must install Perl.\n\nTo create dist files you will additionally need:\n\n* lzip (to create tar.lz dist files)\n* texlive (or some other TeX package)\n\nGNU Make requires Gnulib to provide some facilities.  If you want to maintain\na local installation of gnulib you can set GNULIB_SRCDIR to point to it.\nOtherwise, ./bootstrap will obtain a clone for you.\n\nDue to issues with gnulib's getloadavg, you must have automake 1.16.1 or\nabove.  This version may not yet be available through GNU/Linux package\nmanagers.  If you need to install from source be sure to set ACLOCAL_PATH to\npoint to the pkg-config location (e.g., /usr/share/aclocal).\n\nIf you want to build from Git with a non-GCC compiler, add \"MAKE_CFLAGS=\" to\nyour make command line (or at least remove any flags your compiler does not\nsupport).\n\nWhen building from Git you must build in the source directory: \"VPATH\nbuilds\" from remote directories are not supported.  Once you've created\na distribution, of course, you can unpack it and do a VPATH build from\nthere.\n\nAfter checking out the code, you will need to run the bootstrap script:\n\n $ ./bootstrap\n\nAlternatively you can just pull content from remote locations with:\n\n $ ./bootstrap --pull\n\nAnd/or just re-generate auto-generatable files with:\n\n $ ./bootstrap --gen\n\n(Running ./bootstrap does both in one step.)\n\nAt this point you have successfully brought your Git copy of the GNU\nmake source directory up to the point where it can be treated\nmore-or-less like the official package you would get from ftp.gnu.org.\nThat is, you can just run:\n\n  $ ./configure\n  $ make check\n\nto build and test GNU Make.\n\nNOTE! This method builds GNU Make in \"maintainer mode\".  Make programs built\n      in this mode will be slower, possibly MUCH slower: there are various\n      sanity checks enabled.  Further this mode assumes a modern GCC, GNU\n      libc, and well-formed system headers and enables a high level of\n      warnings AND enables -Werror to turn warnings into failures.\n\n      If you want to build from Git with \"maintainer mode\" disabled, add\n      \"MAKE_MAINTAINER_MODE=\" to the make command line.  If you want to turn\n      off the extra warning flags, add \"MAKE_CFLAGS=\" to the make command\n      line.  If you want to keep the warnings but not fail, add\n      \"EXTRA_CFLAGS=-Wno-error\" to the make command line.\n\n      For example:\n        $ ./configure\n        $ make check MAKE_MAINTAINER_MODE= MAKE_CFLAGS=\n        $ make install\n\n\nBuilding From Git for Windows\n-----------------------------\n\nIf you have a UNIX emulation like CYGWIN you can opt to run the general build\nprocedure above; it will work.  Consult README.W32 for information on options\nyou might want to use when running ./configure.\n\nIf you can't or don't want to do that, then first run the .\\bootstrap.bat\nscript to \"prime\" your Git workspace:\n\n  > .\\bootstrap.bat\n\nNext, follow the instructions in the README.W32 file.\n\nNote, neither of these methods are tested regularly by the GNU Make\nmaintainers.  Building for Windows from a distribution tarball IS tested\nregularly.\n\nNOTE! \"Maintainer mode\" (see above) IS ENABLED when building from Git using\n      the build_w32.bat file.\n\n\nDebugging and Testing\n---------------------\n\nThese instructions have been tested on GNU systems.  I have no idea if they\nwork on non-GNU systems (Windows, MacOS, etc.)\n\n* Alternate Configurations:\n  The maintMakefile has a rule for running configure with various different\n  options, with and without packages.  Run:\n\n    make check-alt-config\n\n* Valgrind:\n  You can run all tests under valgrind by passing the -memcheck option:\n\n    (cd tests && ./run_make_tests -make ../make -memcheck)\n\n  Note, this is slow!  Also some tests will fail because of invoking valgrind.\n\n* ASAN:\n  You can build with ASAN and run tests, like this:\n\n    make clean\n    make -j8 CFLAGS='-ggdb3 -fsanitize=address' LDFLAGS='-ggdb3 -fsanitize=address'\n\n  Then to check for corruption only but not memory leaks run:\n\n    ASAN_OPTIONS='detect_stack_after_use_return=true:detect_leaks=false' make check\n\n  To check for leaks too run:\n\n    make check\n\n  Note that ASAN is reporting many more errors than valgrind.  I don't know\n  which one is wrong: I haven't looked at them closely.\n\n\nCreating a Package\n------------------\n\nOnce you have performed the above steps (including the configuration and\nbuild) you can create a GNU Make package.  This is very simple, just\nrun:\n\n  $ make dist-gzip\n\nand, if you like:\n\n  $ make dist-lzip\n\nEven better, you should run this:\n\n  $ make distcheck\n\nWhich will build both .gz and .lz package files, then unpack one into a\ntemporary location, try to build it and repack it, then verifying that\neverything works, you get the same results, _and_ no extraneous files are\nleft over after the \"distclean\" rule.\n\nThis package can be unpacked and built to give a \"normal\" (non-maintainer\nmode) result.\n\n\nSteps to Release\n----------------\n\nHere are the things that need to be done (in more or less this order)\nbefore making an official release.  If something breaks such that you need to\nchange code, be sure to start over again sufficiently that everything is\nconsistent (that's why we don't finalize the Git tag, etc. until the end).\n\n  * Update the configure.ac file with the new release number.\n  * Update the EDITION value in the doc/make.texi file.\n  * Update the doc/make.1 file with the release date.\n  * Update the NEWS file with the release number and date.\n  * Ensure the Savannah bug list URL in the NEWS file uses the correct\n    \"Fixed Release\" ID number.\n  * Run \"make distcheck\" to be sure it all works.\n  * Run \"make check-alt-config\" to be sure alternative configurations work\n  * run \"make tag-release\" to create a Git tag for the release\n  * Push everything:\n    git push --tags origin master\n\nThe safest thing is to create an entirely new repository and build the final\npackage from there:\n\n  git clone git://git.savannah.gnu.org/make.git make-release\n  cd make-release\n\nIf you don't want to create a new repository then run \"git clean -fdx\".\nThen:\n\n  ./bootstrap\n  ./configure\n  make distcheck\n\nPerform test builds on whichever systems you have access to.\n\nUse a previous announcement as a template to create an announcement in a text\nfile then sign it with GPG:\n\n  gpg --clearsign <announcement.txt>\n\nOr, use your mail client's PGP/GPG signing capabilities.\n\nNOTE! In order to publish a package on the FSF FTP site you need to have my\n      GPG private key, and my passphrase to unlock it.\n\n      Depending on your distribution (whether GnuPG is integrated with your\n      keyring etc.) the upload operation will either pop up a window asking\n      for the GPG key passphrase one time, or else it will use the CLI to ask\n      for the GPG passphrase _THREE_ times.  Sigh.\n\n\nPublishing a Release Candidate\n------------------------------\n\nUsually I publish one or two release candidates for people to test before\nmaking an official release.  Release candidates use a GNU numbering scheme,\nwhich add a \".9x\" release number to the PREVIOUS major release.  So the first\nrelease candidate for GNU Make 4.4 would be GNU Make 4.3.90, the second\nrelease candidate would be 4.3.91, etc.\n\nUpload a release candidate using:\n\n  make upload-alpha\n\nAnnounce a release candidate to these mailing lists:\n\n    To:  bug-make@gnu.org\n    BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org\n\nYou will have to approve the BCC's on the mailing list admin sites.  Send\nseparate copies to (don't use CC as replies will go to these lists):\n\n  * coordinator@translationproject.org\n  * platform-testers@gnu.org\n\n\nPublishing a Release\n--------------------\n\nWhen publishing a final release there are extra steps that need to be taken:\n\n  * Run \"make update-makeweb\" to get a copy of the GNU Make web pages\n  * Run \"make update-gnuweb\" to get a copy of the GNU website boilerplate pages\n  * Update the web page boilerplate if necessary:\n      ( cd ~/src/make/make-web \\\n         && ~/src/gnu-www/www/server/standards/patch-from-parent \\\n                make.html \\\n                ~/src/gnu-www/www/server/standards/boilerplate.html )\n  * Run \"make gendocs\" (requires gnulib) to generate the manual files for\n    the GNU Make web pages.\n  * Follow the directions from gendocs for the web page repository\n\nManage the Savannah project for GNU Make:\n\n  * In Savannah edit the \"Component Version\" field and choose the \"SCM\" entry.\n    Modify the \"Value\", \"Rank\", and \"Description\" values for the to refer to\n    the new release.  The \"Rank\" field should be 10 less than the previous\n    release so it orders properly.\n\n  * In Savannah edit the \"Fixed Release\" field and choose the \"SCM\" entry.\n    Modify the \"Value\", \"Rank\", and \"Description\" values for the to refer to\n    the new release.  The \"Rank\" field should be 10 less than the previous\n    release so it orders properly.\n\n  * In Savannah create a new entry for the \"Component Version\" field:\n      - Value: SCM\n      - Rank:  20\n      - Descr: Issues found in code retrieved from Source Code Management (Git), rather than a distributed version. Please include the SHA you are working with.\n\n  * In Savannah create a new entry for the \"Fix Release\" field:\n      - Value: SCM\n      - Rank:  20\n      - Descr: Fixed in Source Code Management (Git). The fix will be included in the next release of GNU Make.\n\nUpload a release using:\n\n  make upload-ftp\n\nAnnounce a release to these mailing lists:\n\n    To:  info-gnu@gnu.org, bug-make@gnu.org\n    BCC: help-make@gnu.org, make-w32@gnu.org, make-alpha@gnu.org\n\nYou will have to approve the BCC's on the mailing list admin sites.  Send\nseparate copies to (don't use CC as replies will go to these lists):\n\n  * coordinator@translationproject.org\n  * platform-testers@gnu.org\n\nAnnounce on Savannah:\n\n  * Add a news item to the Savannah project site.\n\nStart the next release:\n\n  * Update configure.ac and add a \".90\" to the release number.\n  * Update the NEWS file with a new section for the release / date.\n  * Update the Savannah URL for the bugs fixed in the NEWS section.\n\n\nAppendix A - For The Brave\n--------------------------\n\nFor those of you who trust me implicitly, or are just brave (or\nfoolhardy), here is a canned sequence of commands to build a GNU Make\ndistribution package from a virgin Git source checkout (assuming all the\nprerequisites are available of course).\n\nThis list is eminently suitable for a quick swipe o' the mouse and a\nswift click o' mouse-2 into an xterm.  Go for it!\n\nFor a debugging version:\n\n./bootstrap && ./configure CFLAGS=-g && make check\n\nFor an optimized version\n\n./bootstrap && ./configure && make check\n"
  },
  {
    "path": "README.in",
    "content": "This directory contains the @PACKAGE_VERSION@ release of @PACKAGE_NAME@.\n\nSee the file NEWS for the user-visible changes from previous releases.\nIn addition, there have been bugs fixed.\n\n>> If you are trying to build GNU Make from a Git clone rather than a\n>> downloaded source distribution, see the README.git file for instructions.\n\nPlease check the system-specific notes below for any caveats related to your\noperating system.\n\nThis README assumes you are building on a POSIX-based operating system.\nFor ports to other operating systems please see the system-specific README\nfiles, as described in the \"Ports\" section below.\n\nFor source distribution building and installation instructions, see the file\nINSTALL.\n\nIf you need to build GNU Make and have no other 'make' program to use, you can\nuse the shell script 'build.sh' instead.  To do this, first run 'configure' as\ndescribed in INSTALL.  Then, instead of typing 'make' to build the program,\ntype 'sh build.sh'.  This will compile the program in the current directory.\nThen you will have a 'make' program that you can use for './make install', or\nwhatever else.\n\nSome systems' 'make' programs cannot process the Makefile for GNU Make.\nIf you get errors from your system's 'make' when building GNU Make, try using\n'build.sh' instead.\n\n\nGNU Make is free software.  See the file COPYING for copying conditions.\nGNU Make is copyright by the Free Software Foundation.  Copyright notices\ncondense sequential years into a range; e.g. \"1987-1994\" means all years\nfrom 1987 to 1994 inclusive.\n\n\nDownloading\n-----------\n\nGNU Make can be obtained in many different ways.  See a description here:\n\n  https://www.gnu.org/software/software.html\n\n\nDocumentation\n-------------\n\nGNU Make is fully documented in the GNU Make manual, which is contained in\nthis distribution as the file make.texi.  You can also find on-line and\npreformatted (PostScript and DVI) versions at the FSF's web site.  There is\ninformation there about ordering hardcopy documentation.\n\n  https://www.gnu.org/\n  https://www.gnu.org/doc/doc.html\n  https://www.gnu.org/manual/manual.html\n\n\nDevelopment\n-----------\n\nGNU Make development is hosted by Savannah, the FSF's online development\nmanagement tool.  Savannah is here:\n\n  https://savannah.gnu.org\n\nAnd the GNU Make development page is here:\n\n  https://savannah.gnu.org/projects/make/\n\nYou can find most information concerning the development of GNU Make at\nthis site.\n\n\nRegression Tests\n----------------\n\nGNU Make contains a suite of regression tests.  To run them use \"make check\"\nafter building GNU Make.  If they fail a tar package will be created\ncontaining useful information, which can be emailed (as an attachment) to\nthe <bug-make@gnu.org> mailing list.\n\nPlease note that since these tests rely on known-good-output comparisons,\nthey can show spurious failures on some systems (particularly non-POSIX systems\nsuch as Windows).\n\n\nBug Reporting\n-------------\n\nIf you need help using GNU Make, try asking on <help-make@gnu.org>.\n\nIf you found a bug, you can send a bug reports to <bug-make@gnu.org>.\nPlease see the section of the GNU Make manual entitled 'Problems and Bugs'\nfor information on submitting useful and complete bug reports.\n\nYou do not need to subscribe to these lists first.\n\nYou can also use the online bug tracking system in the Savannah GNU Make\nproject to submit new problem reports or search for existing ones:\n\n  https://savannah.gnu.org/bugs/?group=make\n\nWe prefer to use the bug tracking system ONLY for bugs or enhancements,\nnot for help requests: please use the mailing lists to get help.\n\n\nSubmitting Patches\n------------------\n\nIf you'd like to propose a change to GNU Make, you can provide a patch with\nyour changes.  If you are making your changes in a Git workspace you can run\n\"git format-patch\" to create a patch file.  If not, you can use the diff(1)\nutility to create a patch file; please use \"diff -u\".\n\nOnce you have a patch you can submit it in any of these ways:\n\n  * Create a bug on Savannah and add the patch as an attachment:\n      https://savannah.gnu.org/bugs/?group=make&func=additem\n\n  * Send the patch via email to <bug-make@gnu.org>: be sure to add it as an\n    attachment to avoid interference by email processors.\n\nAll non-trivial changes require FSF copyright paperwork to be completed\nbefore they can be accepted.  Contact <bug-make@gnu.org> for help.\n\n\nGit Access\n----------\n\nThe GNU Make source repository is available via Git from the GNU Savannah Git\nserver; look here for details:\n\n  https://savannah.gnu.org/git/?group=make\n\nPlease note: you won't be able to build GNU Make from Git without installing\nappropriate maintainer's tools, such as GNU m4, automake, autoconf, Perl, GNU\nmake, and GCC.\n\nSee the README.git file for instructions on how to build GNU Make once these\ntools are available.  We make no guarantees about the contents or quality of\nthe latest code in the Git repository: it is not unheard of for code that is\nknown to be broken to be checked in.  Use at your own risk.\n\n\nSystem-specific Notes\n---------------------\n\nOne area that is often a problem in configuration and porting is the code\nto check the system's current load average.  To make it easier to test and\ndebug this code, you can do 'make check-loadavg' to see if it works\nproperly on your system.  (You must run 'configure' beforehand, but you\nneed not build 'make' itself to run this test.)\n\nAnother potential source of porting problems is the support for large\nfiles (LFS) in configure for those operating systems that provide it.\nPlease report any bugs that you find in this area.  If you run into\ndifficulties, then as a workaround you should be able to disable LFS by\nadding the '--disable-largefile' option to the 'configure' script.\n\nOn systems that support micro- and nano-second timestamp values and\nwhere stat(2) provides this information, GNU Make will use it when\ncomparing timestamps to get the most accurate possible result.  However,\nnote that many current implementations of tools that *set* timestamps do\nnot preserve micro- or nano-second granularity.  This means that \"cp -p\"\nand other similar tools (tar, etc.) may not exactly duplicate timestamps\nwith micro- and nano-second granularity on some systems.  If your build\nsystem contains rules that depend on proper behavior of tools like \"cp\n-p\", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to\nforce make to treat them properly.  See the manual for details.\n\n\nPorts\n-----\n\n  - See README.customs for details on integrating GNU Make with the\n    Customs distributed build environment from the Pmake distribution.\n\n  - See README.VMS for details about GNU Make on OpenVMS.\n\n  - See README.zOS for details about GNU Make on z/OS.\n\n  - See README.W32 for details about GNU Make on Windows NT, 95, or 98.\n\n  - See README.DOS for compilation instructions on MS-DOS and MS-Windows\n    using DJGPP tools.\n\n    A precompiled binary of the MSDOS port of GNU Make is available as part\n    of DJGPP; see the WWW page https://www.delorie.com/djgpp/ for more\n    information.\n\n    The Cygwin project maintains its own port of GNU Make.  That port may have\n    patches which are not present in this version.  If you are using Cygwin\n    you should use their version of GNU Make, and if you have questions about\n    it you should start by asking on those mailing lists and forums.\n\nPlease note there are two _separate_ ports of GNU Make for Microsoft\nsystems: a native Windows port built with (for example) MSVC or MinGW,\nand a DOS-based port built with DJGPP.  Please be sure you are looking\nat the right README!\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.zOS",
    "content": "                                                                     -*-text-*-\nGNU Make has been ported to z/OS, tested on z/OS V2R4.\n\n\nPREREQUISITES\n-------------\nBuilding GNU Make requires certain tools be installed on your z/OS system.\nThese tools can be downloaded from: https://github.com/ZOSOpenTools\nFor detailed instructions on how to set up these tools, visit\nhttps://zosopentools.github.io/meta/#/Guides/Pre-req\n\nYou will need curl, tar, and gzip to download and unpack the GNU Make release\npackage, but presumably you've already worked this out if you're reading this\ndocument!\n\nYou will need the IBM C/C++ compiler.  You can download a web deliverable\nadd-on feature to your XL C/C++ compiler here:\nhttps://www-40.ibm.com/servers/resourcelink/svc00100.nsf/pages/xlCC++V241ForZOsV24\n\nAlternatively, you can install and manage C/C++ for Open Enterprise Languages\non z/OS using RedHat OpenShift Container Platform and IBM Z and Cloud\nModernization Stack.\n\nGNU Make has a dependency on the ZOSLIB library, which is documented here:\nhttps://zosopentools.github.io/meta/#/Guides/Zoslib.\n\nTo obtain the latest release of zoslib, you can download it from here:\nhttps://github.com/ZOSOpenTools/zoslibport/releases.\n\n\nBUILDING\n--------\nIf you are trying to build from a checked-out Git workspace, see README.git.\n\nBefore building GNU Make, you will need to ensure that the following\nenvironment variables are set, to turn on z/OS enhanced ASCII support:\n\n  export _BPXK_AUTOCVT=ON\n  export _CEE_RUNOPTS=\"$_CEE_RUNOPTS FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)\"\n  export _TAG_REDIR_ERR=txt\n  export _TAG_REDIR_IN=txt\n  export _TAG_REDIR_OUT=txt\n\nTo ensure proper functioning of xlclang, set the following environment\nvariables before building:\n\n  export _CC_CCMODE=1\n  export _C89_CCMODE=1\n  export _CXX_CCMODE=1\n\nSet PATH_TO_ZOSLIB to the location of your zoslib installation; e.g.:\n\n  PATH_TO_ZOSLIB=$HOME/zopen/prod/zoslib\n\nInvoke ./configure as follows:\n\n  ./configure \\\n      CC=xlclang \\\n      CPPFLAGS=\"-DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFF -DZOSLIB_OVERRIDE_CLIB=1\" \\\n      CFLAGS=\"-qascii -std=gnu11 -qnocsect -qenum=int -I$PATH_TO_ZOSLIB/include\" \\\n      LDFLAGS=\"-L$PATH_TO_ZOSLIB/lib\" \\\n      LIBS=\"-lzoslib $PATH_TO_ZOSLIB/lib/CXXRT64.x\"\n\nIf you have an instance of make already available you can build with:\n\n  make\n\nIf not, you can build with:\n\n  ./build.sh\n\n\nTESTING\n-------\nTo run the regression tests you'll need to install Perl and enable it.\nThen you can run:\n\n  ./make check\n\n\nINSTALLING\n----------\nCopy the \"make\" program to wherever you want it to be installed, on your PATH.\n"
  },
  {
    "path": "TODO.private",
    "content": "                                                            -*-Indented-Text-*-\nGNU Make TODO List\n------------------\n\nThis list comes both from the authors and from users of GNU make.\n\nThey are listed in no particular order!\n\nAlso, I don't guarantee that all of them will be ultimately deemed \"good\nideas\" and implemented.  These are just the ones that, at first blush,\nseem to have some merit (and that I can remember).\n\nHowever, if you see something here you really, really want, speak up.\nAll other things being equal, I will tend to implement things that seem\nto maximize user satisfaction.\n\nIf you want to implement some of them yourself, barring the ones I've\nmarked below, have at it!  Please contact me first to let me know you're\nworking on it, and give me some info about the design--and, critically,\ninformation about any user-visible syntax change, etc.\n\n\nThe Top Item\n------------\n\nIf you know perl (or want to learn DejaGNU or similar), the number one\npriority on my list of things I don't have time to do right now is\nfixing up the GNU make test suite.  Most importantly it needs to be made\n\"parallelizable\", so more than one regression can run at the same time\n(essentially, make the \"work\" directory local).  Also, the CWD during\nthe test should be in the work directory or, better, a test-specific\ntemporary directory so each test gets a new directory; right now\nsometimes tests leak files into the main directory which causes\nsubsequent tests to fail (some tests may need to be tweaked).  Beyond\nthat, any cleanup done to make writing, reading, or handling tests\nsimpler would be great!  Please feel free to make whatever changes you\nlike to the current tests, given some high-level goals, and that you'll\nport the current tests to whatever you do :).\n\n\nThe Rest of the List\n--------------------\n\n 1) Option to check more than timestamps to determine if targets have\n    changed.  This is also a very big one.  It's _close_ to my plate :),\n    and I have very definite ideas about how I would like it done.\n    Please pick something else unless you must have this feature.  If\n    you try it, please work _extremely_ closely with me on it.\n\n 1a) Possibly a special case of this is the .KEEP_STATE feature of Sun's\n     make.  Some great folks at W U. in Canada did an implementation of\n     this for a class project.  Their approach is reasonable and\n     workable, but doesn't really fit into my ideas for #2.  Maybe\n     that's OK.  I have paperwork for their work so if you want to do\n     this one talk to me to get what they've already done.\n\n     [K R Praveen <praveen@cair.res.in>]\n\n 2) Currently you can use \"%.foo %.bar : %.baz\" to mean that one\n    invocation of the rule builds both targets.  GNU make needs a way to\n    do that for explicit rules, too.  I heard a rumor that some versions\n    of make all you to say \"a.foo + a.bar : a.baz\" to do this (i.e., a\n    \"+\" means one invocation builds both).  Don't know if this is the\n    best syntax or not... what if you say \"a.foo + a.bar a.bam : a.baz\";\n    what does that mean?\n\n 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o,\n    etc., or something like that).  Maybe using regex?\n\n 4) Provide a .TARGETS variable, containing the names of the targets\n    defined in the makefile.\n\n    Actually, I now think a $(targets ...) function, at least, might be\n    better than a MAKETARGETS variable.  The argument would be types of\n    targets to list: \"phony\" is the most useful one.  I suppose\n    \"default\" might also be useful.  Maybe some others; check the\n    bitfields to see what might be handy.\n\n 5) Some sort of operating-system independent way of handling paths\n    would be outstanding, so makefiles can be written for UNIX, VMS,\n    DOS, MS-Windows, Amiga, etc. with a minimum of specialization.\n\n    Or, perhaps related/instead of, some sort of meta-quoting syntax so\n    make can deal with filenames containing spaces, colons, etc.  I\n    dunno, maybe something like $[...]?  This may well not be worth\n    doing until #1 is done.\n\n 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY\n    pseudo-targets have different capabilities.  For example, .PRECIOUS\n    can take a \"%\", the others can't.  Etc.  These should all work the\n    same, insofar as that makes sense.\n\n 7) Improved debugging/logging/etc. capabilities.  Part of this is done:\n    I introduced a number of debugging enhancements.  Tim Magill is (I\n    think) looking into options to control output more selectively.\n    One thing I want to do in debugging is add a flag to allow debugging\n    of variables as they're expanded (!).  This would be incredibly\n    verbose, but could be invaluable when nothing else seems to work and\n    you just can't figure it out.  The way variables are expanded now\n    means this isn't 100% trivial, but it probably won't be hard.\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1997-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "autogen.sh",
    "content": "#!/bin/sh\n# Convenience script for regenerating all autogeneratable files that are\n# omitted from the version control repository. In particular, this script\n# also regenerates all aclocal.m4, config.h.in, Makefile.in, configure files\n# with new versions of autoconf or automake.\n\n# Copyright (C) 2003-2024 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/autogen.sh in gnulib.  However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n#\n# Alternatively, you can use an autogen.sh script that is specific\n# to your package.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nautogen \"$@\"\n"
  },
  {
    "path": "autopull.sh",
    "content": "#!/bin/sh\n# Convenience script for fetching auxiliary files that are omitted from\n# the version control repository of this package.\n\n# Copyright (C) 2003-2024 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/autopull.sh in gnulib.  However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n#\n# Alternatively, you can use an autopull.sh script that is specific\n# to your package.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nautopull \"$@\"\n"
  },
  {
    "path": "bootstrap",
    "content": "#! /bin/sh\n# Bootstrap this package from checked-out sources.\n\nscriptversion=2022-12-27.07; # UTC\n\n# Copyright (C) 2003-2023 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/bootstrap in gnulib. However, to be\n# useful to your package, you should place a copy of it under version\n# control in the top-level directory of your package.  The intent is\n# that all customization can be done with a bootstrap.conf file also\n# maintained in your version control; gnulib comes with a template\n# build-aux/bootstrap.conf to get you started.\n\n# Please report bugs or propose patches to bug-gnulib@gnu.org.\n\nme=\"$0\"\nmedir=`dirname \"$me\"`\n\n# Read the function library and the configuration.\n. \"$medir\"/bootstrap-funclib.sh\n\nusage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources.\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           do not want to waste your bandwidth downloading\n                           them again.\n  GNULIB_URL               Cloneable URL of the gnulib repository.\n\nOptions:\n\n  --pull                   Do phase 1: pull files from network\n  --gen                    Do phase 2: generate from local files.\n                           (The default is to do both phases.)\n\n  --gnulib-srcdir=DIRNAME  specify the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.  Defaults\n                           to \\$GNULIB_SRCDIR\n  --gnulib-refdir=DIRNAME  specify the local directory where a gnulib\n                           repository (with a .git subdirectory) resides.\n                           Use this if you already have gnulib sources\n                           and history on your machine, and do not want\n                           to waste your bandwidth downloading them again.\n                           Defaults to \\$GNULIB_REFDIR\n\n  --bootstrap-sync         if this bootstrap script is not identical to\n                           the version in the local gnulib sources,\n                           update this script, and then restart it with\n                           /bin/sh or the shell \\$CONFIG_SHELL\n  --no-bootstrap-sync      do not check whether bootstrap is out of sync\n\n  --copy                   copy files instead of creating symbolic links\n  --force                  attempt to bootstrap even if the sources seem\n                           not to have been checked out\n  --no-git                 do not use git to update gnulib.  Requires that\n                           \\$GNULIB_SRCDIR or the --gnulib-srcdir option\n                           points to a gnulib repository with the correct\n                           revision\n  --skip-po                do not download po files\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources can be fetched in various ways:\n\n * If the environment variable GNULIB_SRCDIR is set (either as an\n   environment variable or via the --gnulib-srcdir option), then sources\n   are fetched from that local directory.  If it is a git repository and\n   the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, if this package is in a git repository with a 'gnulib'\n   submodule configured, then that submodule is initialized and updated\n   and sources are fetched from there.  If GNULIB_REFDIR is set (either\n   as an environment variable or via the --gnulib-refdir option) and is\n   a git repository, then it is used as a reference.\n\n * Otherwise, if the 'gnulib' directory does not exist, Gnulib sources\n   are cloned into that directory using git from \\$GNULIB_URL, defaulting\n   to $default_gnulib_url.\n   If the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, the existing Gnulib sources in the 'gnulib' directory are\n   used.  If it is a git repository and the configuration variable\n   GNULIB_REVISION is set in bootstrap.conf, then that revision is\n   checked out.\n\nIf you maintain a package and want to pin a particular revision of the\nGnulib sources that has been tested with your package, then there are\ntwo possible approaches: either configure a 'gnulib' submodule with the\nappropriate revision, or set GNULIB_REVISION (and if necessary\nGNULIB_URL) in bootstrap.conf.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n# Parse options.\n\n# Whether to pull and generate.\npull=false\ngen=false\n\n# Whether to use copies instead of symlinks.\ncopy=false\n\n# Use git to update gnulib sources\nuse_git=true\n\nfor option\ndo\n  case $option in\n  --help)\n    usage\n    exit;;\n  --version)\n    set -e\n    echo \"bootstrap $scriptversion lib $scriptlibversion\"\n    echo \"$copyright\"\n    exit 0\n    ;;\n  --pull)\n    pull=true;;\n  --gen)\n    gen=true;;\n  --gnulib-srcdir=*)\n    GNULIB_SRCDIR=${option#--gnulib-srcdir=};;\n  --gnulib-refdir=*)\n    GNULIB_REFDIR=${option#--gnulib-refdir=};;\n  --skip-po)\n    SKIP_PO=t;;\n  --force)\n    checkout_only_file=;;\n  --copy)\n    copy=true;;\n  --bootstrap-sync)\n    bootstrap_sync=true;;\n  --no-bootstrap-sync)\n    bootstrap_sync=false;;\n  --no-git)\n    use_git=false;;\n  *)\n    bootstrap_option_hook $option || die \"$option: unknown option\";;\n  esac\ndone\n\n# Default is to do both.\n$pull || $gen || pull=true gen=true\n\n$use_git || test -n \"$GNULIB_SRCDIR\" \\\n  || die \"Error: --no-git requires \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir option\"\ntest -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n  || die \"Error: \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory\"\n\nif test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n  die \"Bootstrapping from a non-checked-out distribution is risky.\"\nfi\n\ncheck_build_prerequisites $use_git\n\nif $bootstrap_sync; then\n  prepare_GNULIB_SRCDIR\n  upgrade_bootstrap\n  # Since we have now upgraded if needed, no need to try it a second time below.\n  bootstrap_sync=false\nfi\n\necho \"$0: Bootstrapping from checked-out $package sources...\"\n\n# Pass GNULIB_SRCDIR and GNULIB_REFDIR to any subsidiary commands that care.\nexport GNULIB_SRCDIR\nexport GNULIB_REFDIR\n\nif $pull && { $use_git || test -z \"$SKIP_PO\"; }; then\n  autopull \\\n      `if $bootstrap_sync; then echo ' --bootstrap-sync'; else echo ' --no-bootstrap-sync'; fi` \\\n      `if test -z \"$checkout_only_file\"; then echo ' --force'; fi` \\\n      `if ! $use_git; then echo ' --no-git'; fi` \\\n      `if test -n \"$SKIP_PO\"; then echo ' --skip-po'; fi` \\\n    || die \"could not fetch auxiliary files\"\nfi\n\nif $gen; then\n autogen \\\n    `if $copy; then echo ' --copy'; fi` \\\n    `if test -z \"$checkout_only_file\"; then echo ' --force'; fi` \\\n  || die \"could not generate auxiliary files\"\nfi\n\n# ----------------------------------------------------------------------------\n\n# Local Variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"scriptversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "bootstrap-funclib.sh",
    "content": "# A library of shell functions for autopull.sh, autogen.sh, and bootstrap.\n\nscriptlibversion=2022-12-27.16; # UTC\n\n# Copyright (C) 2003-2024 Free Software Foundation, Inc.\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Originally written by Paul Eggert.  The canonical version of this\n# script is maintained as top/bootstrap-funclib.sh in gnulib.  However,\n# to be useful to your package, you should place a copy of it under\n# version control in the top-level directory of your package.  The\n# intent is that all customization can be done with a bootstrap.conf\n# file also maintained in your version control; gnulib comes with a\n# template build-aux/bootstrap.conf to get you started.\n\nnl='\n'\n\n# Ensure file names are sorted consistently across platforms.\nLC_ALL=C\nexport LC_ALL\n\n# Honor $PERL, but work even if there is none.\nPERL=\"${PERL-perl}\"\n\ndefault_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git\n\n# Copyright year, for the --version output.\ncopyright_year=`echo \"$scriptlibversion\" | sed -e 's/[^0-9].*//'`\ncopyright=\"Copyright (C) ${copyright_year} Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\"\n\n# warnf_ FORMAT-STRING ARG1...\nwarnf_ ()\n{\n  warnf_format_=$1\n  shift\n  nl='\n'\n  case $* in\n    *$nl*) me_=$(printf \"$me\"|tr \"$nl|\" '??')\n       printf \"$warnf_format_\" \"$@\" | sed \"s|^|$me_: |\" ;;\n    *) printf \"$me: $warnf_format_\" \"$@\" ;;\n  esac >&2\n}\n\n# warn_ WORD1...\nwarn_ ()\n{\n  # If IFS does not start with ' ', set it and emit the warning in a subshell.\n  case $IFS in\n    ' '*) warnf_ '%s\\n' \"$*\";;\n    *)    (IFS=' '; warn_ \"$@\");;\n  esac\n}\n\n# die WORD1...\ndie() { warn_ \"$@\"; exit 1; }\n\n# ------------------------------ Configuration. ------------------------------\n\n# Directory that contains package-specific gnulib modules and/or overrides.\nlocal_gl_dir=gl\n\n# Name of the Makefile.am\n# XXX Not used.\ngnulib_mk=gnulib.mk\n\n# List of gnulib modules needed.\ngnulib_modules=\n\n# Any gnulib files needed that are not in modules.\ngnulib_files=\n\n# A function to be called for each unrecognized option.  Returns 0 if\n# the option in $1 has been processed by the function.  Returns 1 if\n# the option has not been processed by the function.  Override it via\n# your own definition in bootstrap.conf\nbootstrap_option_hook() { return 1; }\n\n# A function to be called in order to print the --help information\n# corresponding to user-defined command-line options.\nbootstrap_print_option_usage_hook() { :; }\n\n# A function to be called at the end of autopull.sh.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_post_pull_hook() { :; }\n\n# A function to be called right after gnulib-tool is run.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_post_import_hook() { :; }\n\n# A function to be called after everything else in this script.\n# Override it via your own definition in bootstrap.conf.\nbootstrap_epilogue() { :; }\n\n# The command to download all .po files for a specified domain into a\n# specified directory.  Fill in the first %s with the destination\n# directory and the second with the domain name.\npo_download_command_format=\\\n\"wget --mirror --level=1 -nd -nv -A.po -P '%s' \\\n https://translationproject.org/latest/%s/\"\n\n# Prefer a non-empty tarname (4th argument of AC_INIT if given), else\n# fall back to the package name (1st argument with munging).\nextract_package_name='\n  /^AC_INIT(\\[*/{\n     s///\n     /^[^,]*,[^,]*,[^,]*,[ []*\\([^][ ,)]\\)/{\n       s//\\1/\n       s/[],)].*//\n       p\n       q\n     }\n     s/[],)].*//\n     s/^GNU //\n     y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/\n     s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g\n     p\n  }\n'\npackage=$(${AUTOCONF:-autoconf} --trace AC_INIT:\\$4 configure.ac 2>/dev/null)\nif test -z \"$package\"; then\n  package=$(sed -n \"$extract_package_name\" configure.ac) \\\n      || die 'cannot find package name in configure.ac'\nfi\ngnulib_name=lib$package\n\nbuild_aux=build-aux\nsource_base=lib\nm4_base=m4\ndoc_base=doc\ntests_base=tests\ngnulib_extra_files=\"\n        build-aux/install-sh\n        build-aux/mdate-sh\n        build-aux/texinfo.tex\n        build-aux/depcomp\n        build-aux/config.guess\n        build-aux/config.sub\n        doc/INSTALL\n\"\n\n# Additional gnulib-tool options to use.  Use \"\\newline\" to break lines.\ngnulib_tool_option_extras=\n\n# Other locale categories that need message catalogs.\nEXTRA_LOCALE_CATEGORIES=\n\n# Additional xgettext options to use.  Use \"\\\\\\newline\" to break lines.\nXGETTEXT_OPTIONS='\\\\\\\n --flag=_:1:pass-c-format\\\\\\\n --flag=N_:1:pass-c-format\\\\\\\n --flag=error:3:c-format --flag=error_at_line:5:c-format\\\\\\\n'\n\n# Package bug report address and copyright holder for gettext files\nCOPYRIGHT_HOLDER='Free Software Foundation, Inc.'\nMSGID_BUGS_ADDRESS=bug-$package@gnu.org\n\n# Files we don't want to import.\n# XXX Not used.\nexcluded_files=\n\n# File that should exist in the top directory of a checked out hierarchy,\n# but not in a distribution tarball.\ncheckout_only_file=README-hacking\n\n# Set this to '.cvsignore .gitignore' in bootstrap.conf if you want\n# those files to be generated in directories like lib/, m4/, and po/.\n# Or set it to 'auto' to make this script select which to use based\n# on which version control system (if any) is used in the source directory.\nvc_ignore=auto\n\n# Set this to true in bootstrap.conf to enable --bootstrap-sync by\n# default.\nbootstrap_sync=false\n\n# Override the default configuration, if necessary.\n# Make sure that bootstrap.conf is sourced from the current directory\n# if we were invoked as \"sh bootstrap\".\nconffile=`dirname \"$me\"`/bootstrap.conf\ntest -r \"$conffile\" && . \"$conffile\"\n\n# ------------------------- Build-time prerequisites -------------------------\n\ncheck_exists() {\n  if test \"$1\" = \"--verbose\"; then\n    ($2 --version </dev/null) >/dev/null 2>&1\n    if test $? -ge 126; then\n      # If not found, run with diagnostics as one may be\n      # presented with env variables to set to find the right version\n      ($2 --version </dev/null)\n    fi\n  else\n    ($1 --version </dev/null) >/dev/null 2>&1\n  fi\n\n  test $? -lt 126\n}\n\n# Note this deviates from the version comparison in automake\n# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a\n# but this should suffice as we won't be specifying old\n# version formats or redundant trailing .0 in bootstrap.conf.\n# If we did want full compatibility then we should probably\n# use m4_version_compare from autoconf.\nsort_ver() { # sort -V is not generally available\n  ver1=\"$1\"\n  ver2=\"$2\"\n\n  # split on '.' and compare each component\n  i=1\n  while : ; do\n    p1=$(echo \"$ver1\" | cut -d. -f$i)\n    p2=$(echo \"$ver2\" | cut -d. -f$i)\n    if [ ! \"$p1\" ]; then\n      echo \"$1 $2\"\n      break\n    elif [ ! \"$p2\" ]; then\n      echo \"$2 $1\"\n      break\n    elif [ ! \"$p1\" = \"$p2\" ]; then\n      if [ \"$p1\" -gt \"$p2\" ] 2>/dev/null; then # numeric comparison\n        echo \"$2 $1\"\n      elif [ \"$p2\" -gt \"$p1\" ] 2>/dev/null; then # numeric comparison\n        echo \"$1 $2\"\n      else # numeric, then lexicographic comparison\n        lp=$(printf \"%s\\n%s\\n\" \"$p1\" \"$p2\" | LANG=C sort -n | tail -n1)\n        if [ \"$lp\" = \"$p2\" ]; then\n          echo \"$1 $2\"\n        else\n          echo \"$2 $1\"\n        fi\n      fi\n      break\n    fi\n    i=$(($i+1))\n  done\n}\n\nget_version_sed='\n# Move version to start of line.\ns/.*[v ]\\([0-9]\\)/\\1/\n\n# Skip lines that do not start with version.\n/^[0-9]/!d\n\n# Remove characters after the version.\ns/[^.a-z0-9-].*//\n\n# The first component must be digits only.\ns/^\\([0-9]*\\)[a-z-].*/\\1/\n\n#the following essentially does s/5.005/5.5/\ns/\\.0*\\([1-9]\\)/.\\1/g\np\nq'\n\nget_version() {\n  app=$1\n\n  $app --version >/dev/null 2>&1 || { $app --version; return 1; }\n\n  $app --version 2>&1 | sed -n \"$get_version_sed\"\n}\n\ncheck_versions() {\n  ret=0\n\n  while read app req_ver; do\n    # We only need libtoolize from the libtool package.\n    if test \"$app\" = libtool; then\n      app=libtoolize\n    fi\n    # Exempt git if git is not needed.\n    if test \"$app\" = git; then\n      $check_git || continue\n    fi\n    # Honor $APP variables ($TAR, $AUTOCONF, etc.)\n    appvar=$(echo $app | LC_ALL=C tr '[a-z]-' '[A-Z]_')\n    test \"$appvar\" = TAR && appvar=AMTAR\n    case $appvar in\n        GZIP) ;; # Do not use $GZIP:  it contains gzip options.\n        PERL::*) ;; # Keep perl modules as-is\n        *) eval \"app=\\${$appvar-$app}\" ;;\n    esac\n\n    # Handle the still-experimental Automake-NG programs specially.\n    # They remain named as the mainstream Automake programs (\"automake\",\n    # and \"aclocal\") to avoid gratuitous incompatibilities with\n    # pre-existing usages (by, say, autoreconf, or custom autogen.sh\n    # scripts), but correctly identify themselves (as being part of\n    # \"GNU automake-ng\") when asked their version.\n    case $app in\n      automake-ng|aclocal-ng)\n        app=${app%-ng}\n        ($app --version | grep '(GNU automake-ng)') >/dev/null 2>&1 || {\n          warn_ \"Error: '$app' not found or not from Automake-NG\"\n          ret=1\n          continue\n        } ;;\n      # Another check is for perl modules.  These can be written as\n      # e.g. perl::XML::XPath in case of XML::XPath module, etc.\n      perl::*)\n        # Extract module name\n        app=\"${app#perl::}\"\n        if ! $PERL -m\"$app\" -e 'exit 0' >/dev/null 2>&1; then\n          warn_ \"Error: perl module '$app' not found\"\n          ret=1\n        fi\n        continue\n        ;;\n    esac\n    if [ \"$req_ver\" = \"-\" ]; then\n      # Merely require app to exist; not all prereq apps are well-behaved\n      # so we have to rely on $? rather than get_version.\n      if ! check_exists --verbose $app; then\n        warn_ \"Error: '$app' not found\"\n        ret=1\n      fi\n    else\n      # Require app to produce a new enough version string.\n      inst_ver=$(get_version $app)\n      if [ ! \"$inst_ver\" ]; then\n        warn_ \"Error: '$app' not found\"\n        ret=1\n      else\n        latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2)\n        if [ ! \"$latest_ver\" = \"$inst_ver\" ]; then\n          warnf_ '%s\\n'                                        \\\n              \"Error: '$app' version == $inst_ver is too old\"  \\\n              \"       '$app' version >= $req_ver is required\"\n          ret=1\n        fi\n      fi\n    fi\n  done\n\n  return $ret\n}\n\nprint_versions() {\n  echo \"Program    Min_version\"\n  echo \"----------------------\"\n  printf %s \"$buildreq\"\n  echo \"----------------------\"\n  # can't depend on column -t\n}\n\n# check_build_prerequisites check_git\ncheck_build_prerequisites()\n{\n  check_git=\"$1\"\n\n  # gnulib-tool requires at least automake and autoconf.\n  # If either is not listed, add it (with minimum version) as a prerequisite.\n  case $buildreq in\n    *automake*) ;;\n    *) buildreq=\"automake 1.9\n$buildreq\" ;;\n  esac\n  case $buildreq in\n    *autoconf*) ;;\n    *) buildreq=\"autoconf 2.59\n$buildreq\" ;;\n  esac\n\n  # When we can deduce that gnulib-tool will require patch,\n  # and when patch is not already listed as a prerequisite, add it, too.\n  if test -d \"$local_gl_dir\" \\\n     && ! find \"$local_gl_dir\" -name '*.diff' -exec false {} +; then\n    case $buildreq in\n      *patch*) ;;\n      *) buildreq=\"patch -\n$buildreq\" ;;\n    esac\n  fi\n\n  if ! printf '%s' \"$buildreq\" | check_versions; then\n    echo >&2\n    if test -f README-prereq; then\n      die \"See README-prereq for how to get the prerequisite programs\"\n    else\n      die \"Please install the prerequisite programs\"\n    fi\n  fi\n\n  # Warn the user if autom4te appears to be broken; this causes known\n  # issues with at least gettext 0.18.3.\n  probe=$(echo 'm4_quote([hi])' | autom4te -l M4sugar -t 'm4_quote:$%' -)\n  if test \"x$probe\" != xhi; then\n    warn_ \"WARNING: your autom4te wrapper eats stdin;\"\n    warn_ \"if bootstrap fails, consider upgrading your autotools\"\n  fi\n}\n\n# find_tool ENVVAR NAMES...\n# -------------------------\n# Search for a required program.  Use the value of ENVVAR, if set,\n# otherwise find the first of the NAMES that can be run.\n# If found, set ENVVAR to the program name, die otherwise.\n#\n# FIXME: code duplication, see also gnu-web-doc-update.\nfind_tool ()\n{\n  find_tool_envvar=$1\n  shift\n  find_tool_names=$@\n  eval \"find_tool_res=\\$$find_tool_envvar\"\n  if test x\"$find_tool_res\" = x; then\n    for i; do\n      if check_exists $i; then\n        find_tool_res=$i\n        break\n      fi\n    done\n  fi\n  if test x\"$find_tool_res\" = x; then\n    warn_ \"one of these is required: $find_tool_names;\"\n    die   \"alternatively set $find_tool_envvar to a compatible tool\"\n  fi\n  eval \"$find_tool_envvar=\\$find_tool_res\"\n  eval \"export $find_tool_envvar\"\n}\n\n# --------------------- Preparing GNULIB_SRCDIR for use. ---------------------\n# This is part of autopull.sh, but bootstrap needs it too, for self-upgrading.\n\ncleanup_gnulib() {\n  status=$?\n  # XXX It's a bad idea to erase the submodule directory if it contains local\n  #     modifications.\n  rm -fr \"$gnulib_path\"\n  exit $status\n}\n\ngit_modules_config () {\n  test -f .gitmodules && git config --file .gitmodules \"$@\"\n}\n\nprepare_GNULIB_SRCDIR ()\n{\n  if test -n \"$GNULIB_SRCDIR\"; then\n    # Use GNULIB_SRCDIR directly.\n    # We already checked that $GNULIB_SRCDIR references a directory.\n    # Verify that it contains a gnulib checkout.\n    test -f \"$GNULIB_SRCDIR/gnulib-tool\" \\\n      || die \"Error: --gnulib-srcdir or \\$GNULIB_SRCDIR is specified, but does not contain gnulib-tool\"\n  elif $use_git; then\n    gnulib_path=$(git_modules_config submodule.gnulib.path)\n    test -z \"$gnulib_path\" && gnulib_path=gnulib\n\n    # Get gnulib files.  Populate $gnulib_path, possibly updating a\n    # submodule, for use in the rest of the script.\n\n    if test -n \"$GNULIB_REFDIR\" && test -d \"$GNULIB_REFDIR\"/.git \\\n       && git_modules_config submodule.gnulib.url >/dev/null; then\n      # Use GNULIB_REFDIR as a reference.\n      echo \"$0: getting gnulib files...\"\n      if git submodule -h|grep -- --reference > /dev/null; then\n        # Prefer the one-liner available in git 1.6.4 or newer.\n        git submodule update --init --reference \"$GNULIB_REFDIR\" \\\n          \"$gnulib_path\" || exit $?\n      else\n        # This fallback allows at least git 1.5.5.\n        if test -f \"$gnulib_path\"/gnulib-tool; then\n          # Since file already exists, assume submodule init already complete.\n          git submodule update -- \"$gnulib_path\" || exit $?\n        else\n          # Older git can't clone into an empty directory.\n          rmdir \"$gnulib_path\" 2>/dev/null\n          git clone --reference \"$GNULIB_REFDIR\" \\\n            \"$(git_modules_config submodule.gnulib.url)\" \"$gnulib_path\" \\\n            && git submodule init -- \"$gnulib_path\" \\\n            && git submodule update -- \"$gnulib_path\" \\\n            || exit $?\n        fi\n      fi\n    else\n      # GNULIB_REFDIR is not set or not usable. Ignore it.\n      if git_modules_config submodule.gnulib.url >/dev/null; then\n        echo \"$0: getting gnulib files...\"\n        git submodule init -- \"$gnulib_path\" || exit $?\n        git submodule update -- \"$gnulib_path\" || exit $?\n\n      elif [ ! -d \"$gnulib_path\" ]; then\n        echo \"$0: getting gnulib files...\"\n\n        trap cleanup_gnulib HUP INT PIPE TERM\n\n        shallow=\n        if test -z \"$GNULIB_REVISION\"; then\n          if git clone -h 2>&1 | grep -- --depth > /dev/null; then\n            shallow='--depth 2'\n          fi\n          git clone $shallow ${GNULIB_URL:-$default_gnulib_url} \"$gnulib_path\" \\\n            || cleanup_gnulib\n        else\n          if git fetch -h 2>&1 | grep -- --depth > /dev/null; then\n            shallow='--depth 2'\n          fi\n          mkdir -p \"$gnulib_path\"\n          # Only want a shallow checkout of $GNULIB_REVISION, but git does not\n          # support cloning by commit hash. So attempt a shallow fetch by commit\n          # hash to minimize the amount of data downloaded and changes needed to\n          # be processed, which can drastically reduce download and processing\n          # time for checkout. If the fetch by commit fails, a shallow fetch can\n          # not be performed because we do not know what the depth of the commit\n          # is without fetching all commits. So fallback to fetching all commits.\n          git -C \"$gnulib_path\" init\n          git -C \"$gnulib_path\" remote add origin \\\n              ${GNULIB_URL:-$default_gnulib_url}\n          git -C \"$gnulib_path\" fetch $shallow origin \"$GNULIB_REVISION\" \\\n            || git -C \"$gnulib_path\" fetch origin \\\n            || cleanup_gnulib\n          git -C \"$gnulib_path\" reset --hard FETCH_HEAD\n        fi\n\n        trap - HUP INT PIPE TERM\n      fi\n    fi\n    GNULIB_SRCDIR=$gnulib_path\n    # Verify that the submodule contains a gnulib checkout.\n    test -f \"$gnulib_path/gnulib-tool\" \\\n      || die \"Error: $gnulib_path is supposed to contain a gnulib checkout, but does not contain gnulib-tool\"\n  fi\n\n  # XXX Should this be done if $use_git is false?\n  if test -d \"$GNULIB_SRCDIR\"/.git && test -n \"$GNULIB_REVISION\" \\\n     && ! git_modules_config submodule.gnulib.url >/dev/null; then\n    (cd \"$GNULIB_SRCDIR\" && git checkout \"$GNULIB_REVISION\") || cleanup_gnulib\n  fi\n\n  # $GNULIB_SRCDIR now points to the version of gnulib to use, and\n  # we no longer need to use git or $gnulib_path below here.\n}\n\n# -------- Upgrading bootstrap to the version found in GNULIB_SRCDIR. --------\n\nupgrade_bootstrap ()\n{\n  if test -f \"$medir\"/bootstrap-funclib.sh; then\n    update_lib=true\n    { cmp -s \"$medir\"/bootstrap \"$GNULIB_SRCDIR/top/bootstrap\" \\\n      && cmp -s \"$medir\"/bootstrap-funclib.sh \"$GNULIB_SRCDIR/top/bootstrap-funclib.sh\" \\\n      && cmp -s \"$medir\"/autopull.sh \"$GNULIB_SRCDIR/top/autopull.sh\" \\\n      && cmp -s \"$medir\"/autogen.sh \"$GNULIB_SRCDIR/top/autogen.sh\"; \\\n    }\n  else\n    update_lib=false\n    cmp -s \"$medir\"/bootstrap \"$GNULIB_SRCDIR/build-aux/bootstrap\"\n  fi || {\n    if $update_lib; then\n      echo \"$0: updating bootstrap & companions and restarting...\"\n    else\n      echo \"$0: updating bootstrap and restarting...\"\n    fi\n    case $(sh -c 'echo \"$1\"' -- a) in\n      a) ignored=--;;\n      *) ignored=ignored;;\n    esac\n    exec sh -c \\\n      '{ if '$update_lib' && test -f \"$1\"; then cp \"$1\" \"$3\"; else cp \"$2\" \"$3\"; fi; } && { if '$update_lib' && test -f \"$4\"; then cp \"$4\" \"$5\"; else rm -f \"$5\"; fi; } && { if '$update_lib' && test -f \"$6\"; then cp \"$6\" \"$7\"; else rm -f \"$7\"; fi; } && { if '$update_lib' && test -f \"$8\"; then cp \"$8\" \"$9\"; else rm -f \"$9\"; fi; } && shift && shift && shift && shift && shift && shift && shift && shift && shift && exec \"${CONFIG_SHELL-/bin/sh}\" \"$@\"' \\\n      $ignored \\\n      \"$GNULIB_SRCDIR/top/bootstrap\" \"$GNULIB_SRCDIR/build-aux/bootstrap\" \"$medir/bootstrap\" \\\n      \"$GNULIB_SRCDIR/top/bootstrap-funclib.sh\" \"$medir/bootstrap-funclib.sh\" \\\n      \"$GNULIB_SRCDIR/top/autopull.sh\" \"$medir/autopull.sh\" \\\n      \"$GNULIB_SRCDIR/top/autogen.sh\" \"$medir/autogen.sh\" \\\n      \"$0\" \"$@\" --no-bootstrap-sync\n  }\n}\n\n# ----------------------------------------------------------------------------\n\nif test x\"$gnulib_modules$gnulib_files$gnulib_extra_files\" = x; then\n  use_gnulib=false\nelse\n  use_gnulib=true\nfi\n\n# -------- Fetch auxiliary files from the network.  --------------------------\n\nautopull_usage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources.\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.\n  GNULIB_REFDIR            Specifies the local directory where a gnulib\n                           repository (with a .git subdirectory) resides.\n                           Use this if you already have gnulib sources\n                           and history on your machine, and do not want\n                           to waste your bandwidth downloading them again.\n  GNULIB_URL               Cloneable URL of the gnulib repository.\n\nOptions:\n  --bootstrap-sync         if this bootstrap script is not identical to\n                           the version in the local gnulib sources,\n                           update this script, and then restart it with\n                           /bin/sh or the shell \\$CONFIG_SHELL\n  --no-bootstrap-sync      do not check whether bootstrap is out of sync\n  --force                  attempt to bootstrap even if the sources seem\n                           not to have been checked out\n  --no-git                 do not use git to update gnulib.  Requires that\n                           \\$GNULIB_SRCDIR or the --gnulib-srcdir option\n                           points to a gnulib repository with the correct\n                           revision\n  --skip-po                do not download po files\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources can be fetched in various ways:\n\n * If the environment variable GNULIB_SRCDIR is set (either as an\n   environment variable or via the --gnulib-srcdir option), then sources\n   are fetched from that local directory.  If it is a git repository and\n   the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, if this package is in a git repository with a 'gnulib'\n   submodule configured, then that submodule is initialized and updated\n   and sources are fetched from there.  If GNULIB_REFDIR is set (either\n   as an environment variable or via the --gnulib-refdir option) and is\n   a git repository, then it is used as a reference.\n\n * Otherwise, if the 'gnulib' directory does not exist, Gnulib sources\n   are cloned into that directory using git from \\$GNULIB_URL, defaulting\n   to $default_gnulib_url.\n   If the configuration variable GNULIB_REVISION is set in bootstrap.conf,\n   then that revision is checked out.\n\n * Otherwise, the existing Gnulib sources in the 'gnulib' directory are\n   used.  If it is a git repository and the configuration variable\n   GNULIB_REVISION is set in bootstrap.conf, then that revision is\n   checked out.\n\nIf you maintain a package and want to pin a particular revision of the\nGnulib sources that has been tested with your package, then there are\ntwo possible approaches: either configure a 'gnulib' submodule with the\nappropriate revision, or set GNULIB_REVISION (and if necessary\nGNULIB_URL) in bootstrap.conf.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n# Fetch auxiliary files that are omitted from the version control\n# repository of this package.\nautopull()\n{\n  # Ensure that CDPATH is not set.  Otherwise, the output from cd\n  # would cause trouble in at least one use below.\n  (unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n  # Parse options.\n\n  # Use git to update gnulib sources\n  use_git=true\n\n  for option\n  do\n    case $option in\n    --help)\n      autopull_usage\n      return;;\n    --version)\n      set -e\n      echo \"autopull.sh $scriptlibversion\"\n      echo \"$copyright\"\n      return 0\n      ;;\n    --skip-po)\n      SKIP_PO=t;;\n    --force)\n      checkout_only_file=;;\n    --bootstrap-sync)\n      bootstrap_sync=true;;\n    --no-bootstrap-sync)\n      bootstrap_sync=false;;\n    --no-git)\n      use_git=false;;\n    *)\n      bootstrap_option_hook $option || die \"$option: unknown option\";;\n    esac\n  done\n\n  $use_git || test -n \"$GNULIB_SRCDIR\" \\\n    || die \"Error: --no-git requires \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir option\"\n  test -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n    || die \"Error: \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory\"\n\n  if test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n    die \"Running this script from a non-checked-out distribution is risky.\"\n  fi\n\n  check_build_prerequisites $use_git\n\n  if $use_gnulib || $bootstrap_sync; then\n    prepare_GNULIB_SRCDIR\n    if $bootstrap_sync; then\n      upgrade_bootstrap\n    fi\n  fi\n\n  # Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.\n  # Also find the compatible sha1 utility on the BSDs\n  if test x\"$SKIP_PO\" = x; then\n    find_tool SHA1SUM sha1sum gsha1sum shasum sha1\n  fi\n\n  # See if we can use gnulib's git-merge-changelog merge driver.\n  if $use_git && test -d .git && check_exists git; then\n    if git config merge.merge-changelog.driver >/dev/null ; then\n      :\n    elif check_exists git-merge-changelog; then\n      echo \"$0: initializing git-merge-changelog driver\"\n      git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'\n      git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'\n    else\n      echo \"$0: consider installing git-merge-changelog from gnulib\"\n    fi\n  fi\n\n  case $SKIP_PO in\n  '')\n    if test -d po; then\n      update_po_files po $package || return\n    fi\n\n    if test -d runtime-po; then\n      update_po_files runtime-po $package-runtime || return\n    fi;;\n  esac\n\n  # ---------------------------------------------------------------------------\n\n  bootstrap_post_pull_hook \\\n    || die \"bootstrap_post_pull_hook failed\"\n\n  # Don't proceed if there are uninitialized submodules.  In particular,\n  # autogen.sh will remove dangling links, which might be links into\n  # uninitialized submodules.\n  # But it's OK if the 'gnulib' submodule is uninitialized, as long as\n  # GNULIB_SRCDIR is set.\n  if $use_git; then\n    # Uninitialized submodules are listed with an initial dash.\n    uninitialized=`git submodule | grep '^-' | awk '{ print $2 }'`\n    if test -n \"$GNULIB_SRCDIR\"; then\n      uninitialized=`echo \"$uninitialized\" | grep -v '^gnulib$'`\n    fi\n    if test -n \"$uninitialized\"; then\n      die \"Some git submodules are not initialized: \"`echo \"$uninitialized\" | tr '\\n' ',' | sed -e 's|,$|.|'`\" Either use option '--no-git', or run 'git submodule update --init' and bootstrap again.\"\n    fi\n  fi\n\n  echo \"$0: done.  Now you can run './autogen.sh'.\"\n}\n\n# ----------------------------- Get translations. -----------------------------\n\ndownload_po_files() {\n  subdir=$1\n  domain=$2\n  echo \"$me: getting translations into $subdir for $domain...\"\n  cmd=$(printf \"$po_download_command_format\" \"$subdir\" \"$domain\")\n  eval \"$cmd\"\n}\n\n# Mirror .po files to $po_dir/.reference and copy only the new\n# or modified ones into $po_dir.  Also update $po_dir/LINGUAS.\n# Note po files that exist locally only are left in $po_dir but will\n# not be included in LINGUAS and hence will not be distributed.\nupdate_po_files() {\n  # Directory containing primary .po files.\n  # Overwrite them only when we're sure a .po file is new.\n  po_dir=$1\n  domain=$2\n\n  # Mirror *.po files into this dir.\n  # Usually contains *.s1 checksum files.\n  ref_po_dir=\"$po_dir/.reference\"\n\n  test -d $ref_po_dir || mkdir $ref_po_dir || return\n  download_po_files $ref_po_dir $domain \\\n    && ls \"$ref_po_dir\"/*.po 2>/dev/null |\n      sed 's|.*/||; s|\\.po$||' > \"$po_dir/LINGUAS\" || return\n\n  langs=$(cd $ref_po_dir && echo *.po | sed 's/\\.po//g')\n  test \"$langs\" = '*' && langs=x\n  for po in $langs; do\n    case $po in x) continue;; esac\n    new_po=\"$ref_po_dir/$po.po\"\n    cksum_file=\"$ref_po_dir/$po.s1\"\n    if ! test -f \"$cksum_file\" ||\n        ! test -f \"$po_dir/$po.po\" ||\n        ! $SHA1SUM -c \"$cksum_file\" < \"$new_po\" > /dev/null 2>&1; then\n      echo \"$me: updated $po_dir/$po.po...\"\n      cp \"$new_po\" \"$po_dir/$po.po\" \\\n          && $SHA1SUM < \"$new_po\" > \"$cksum_file\" || return\n    fi\n  done\n}\n\n# -------- Generate files automatically from existing sources.  --------------\n\nautogen_usage() {\n  cat <<EOF\nUsage: $me [OPTION]...\nBootstrap this package from the checked-out sources.\n\nOptional environment variables:\n  GNULIB_SRCDIR            Specifies the local directory where gnulib\n                           sources reside.  Use this if you already\n                           have gnulib sources on your machine, and\n                           you want to use these sources.\n\nOptions:\n  --copy                   copy files instead of creating symbolic links\n  --force                  attempt to bootstrap even if the sources seem\n                           not to have been checked out\nEOF\n  bootstrap_print_option_usage_hook\n  cat <<EOF\nIf the file bootstrap.conf exists in the same directory as this script, its\ncontents are read as shell variables to configure the bootstrap.\n\nFor build prerequisites, environment variables like \\$AUTOCONF and \\$AMTAR\nare honored.\n\nGnulib sources are assumed to be present:\n  * in \\$GNULIB_SRCDIR, if that environment variable is set,\n  * otherwise, in the 'gnulib' submodule, if such a submodule is configured,\n  * otherwise, in the 'gnulib' subdirectory.\n\nRunning without arguments will suffice in most cases.\nEOF\n}\n\n\nversion_controlled_file() {\n  parent=$1\n  file=$2\n  if test -d .git; then\n    git rm -n \"$file\" > /dev/null 2>&1\n  elif test -d .svn; then\n    svn log -r HEAD \"$file\" > /dev/null 2>&1\n  elif test -d CVS; then\n    grep -F \"/${file##*/}/\" \"$parent/CVS/Entries\" 2>/dev/null |\n             grep '^/[^/]*/[0-9]' > /dev/null\n  else\n    warn_ \"no version control for $file?\"\n    false\n  fi\n}\n\n# Strip blank and comment lines to leave significant entries.\ngitignore_entries() {\n  sed '/^#/d; /^$/d' \"$@\"\n}\n\n# If $STR is not already on a line by itself in $FILE, insert it at the start.\n# Entries are inserted at the start of the ignore list to ensure existing\n# entries starting with ! are not overridden.  Such entries support\n# whitelisting exceptions after a more generic blacklist pattern.\ninsert_if_absent() {\n  file=$1\n  str=$2\n  test -f $file || touch $file\n  test -r $file || die \"Error: failed to read ignore file: $file\"\n  duplicate_entries=$(gitignore_entries $file | sort | uniq -d)\n  if [ \"$duplicate_entries\" ] ; then\n    die \"Error: Duplicate entries in $file: \" $duplicate_entries\n  fi\n  linesold=$(gitignore_entries $file | wc -l)\n  linesnew=$( { echo \"$str\"; cat $file; } | gitignore_entries | sort -u | wc -l)\n  if [ $linesold != $linesnew ] ; then\n    { echo \"$str\" | cat - $file > $file.bak && mv $file.bak $file; } \\\n      || die \"insert_if_absent $file $str: failed\"\n  fi\n}\n\n# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with\n# insert_if_absent.\ninsert_vc_ignore() {\n  vc_ignore_file=\"$1\"\n  pattern=\"$2\"\n  case $vc_ignore_file in\n  *.gitignore)\n    # A .gitignore entry that does not start with '/' applies\n    # recursively to subdirectories, so prepend '/' to every\n    # .gitignore entry.\n    pattern=$(echo \"$pattern\" | sed s,^,/,);;\n  esac\n  insert_if_absent \"$vc_ignore_file\" \"$pattern\"\n}\n\nsymlink_to_dir()\n{\n  src=$1/$2\n  dst=${3-$2}\n\n  test -f \"$src\" && {\n\n    # If the destination directory doesn't exist, create it.\n    # This is required at least for \"lib/uniwidth/cjk.h\".\n    dst_dir=$(dirname \"$dst\")\n    if ! test -d \"$dst_dir\"; then\n      mkdir -p \"$dst_dir\"\n\n      # If we've just created a directory like lib/uniwidth,\n      # tell version control system(s) it's ignorable.\n      # FIXME: for now, this does only one level\n      parent=$(dirname \"$dst_dir\")\n      for dot_ig in x $vc_ignore; do\n        test $dot_ig = x && continue\n        ig=$parent/$dot_ig\n        insert_vc_ignore $ig \"${dst_dir##*/}\"\n      done\n    fi\n\n    if $copy; then\n      {\n        test ! -h \"$dst\" || {\n          echo \"$me: rm -f $dst\" &&\n          rm -f \"$dst\"\n        }\n      } &&\n      test -f \"$dst\" &&\n      cmp -s \"$src\" \"$dst\" || {\n        echo \"$me: cp -fp $src $dst\" &&\n        cp -fp \"$src\" \"$dst\"\n      }\n    else\n      # Leave any existing symlink alone, if it already points to the source,\n      # so that broken build tools that care about symlink times\n      # aren't confused into doing unnecessary builds.  Conversely, if the\n      # existing symlink's timestamp is older than the source, make it afresh,\n      # so that broken tools aren't confused into skipping needed builds.  See\n      # <https://lists.gnu.org/r/bug-gnulib/2011-05/msg00326.html>.\n      test -h \"$dst\" &&\n      src_ls=$(ls -diL \"$src\" 2>/dev/null) && set $src_ls && src_i=$1 &&\n      dst_ls=$(ls -diL \"$dst\" 2>/dev/null) && set $dst_ls && dst_i=$1 &&\n      test \"$src_i\" = \"$dst_i\" &&\n      both_ls=$(ls -dt \"$src\" \"$dst\") &&\n      test \"X$both_ls\" = \"X$dst$nl$src\" || {\n        dot_dots=\n        case $src in\n        /*) ;;\n        *)\n          case /$dst/ in\n          *//* | */../* | */./* | /*/*/*/*/*/)\n             die \"invalid symlink calculation: $src -> $dst\";;\n          /*/*/*/*/)    dot_dots=../../../;;\n          /*/*/*/)      dot_dots=../../;;\n          /*/*/)        dot_dots=../;;\n          esac;;\n        esac\n\n        echo \"$me: ln -fs $dot_dots$src $dst\" &&\n        ln -fs \"$dot_dots$src\" \"$dst\"\n      }\n    fi\n  }\n}\n\n# Regenerate all autogeneratable files that are omitted from the\n# version control repository.  In particular, regenerate all\n# aclocal.m4, config.h.in, Makefile.in, configure files with new\n# versions of autoconf or automake.\nautogen()\n{\n  # Ensure that CDPATH is not set.  Otherwise, the output from cd\n  # would cause trouble in at least one use below.\n  (unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n  # Environment variables that may be set by the user.\n  : \"${AUTOPOINT=autopoint}\"\n  : \"${AUTORECONF=autoreconf}\"\n\n  if test \"$vc_ignore\" = auto; then\n    vc_ignore=\n    test -d .git && vc_ignore=.gitignore\n    test -d CVS && vc_ignore=\"$vc_ignore .cvsignore\"\n  fi\n\n\n  # Parse options.\n\n  # Whether to use copies instead of symlinks.\n  copy=false\n\n  for option\n  do\n    case $option in\n    --help)\n      autogen_usage\n      return;;\n    --version)\n      set -e\n      echo \"autogen.sh $scriptlibversion\"\n      echo \"$copyright\"\n      return 0\n      ;;\n    --force)\n      checkout_only_file=;;\n    --copy)\n      copy=true;;\n    *)\n      bootstrap_option_hook $option || die \"$option: unknown option\";;\n    esac\n  done\n\n  test -z \"$GNULIB_SRCDIR\" || test -d \"$GNULIB_SRCDIR\" \\\n    || die \"Error: \\$GNULIB_SRCDIR environment variable or --gnulib-srcdir option is specified, but does not denote a directory\"\n\n  if test -n \"$checkout_only_file\" && test ! -r \"$checkout_only_file\"; then\n    die \"Running this script from a non-checked-out distribution is risky.\"\n  fi\n\n  if $use_gnulib; then\n    if test -z \"$GNULIB_SRCDIR\"; then\n      gnulib_path=$(test -f .gitmodules && git config --file .gitmodules submodule.gnulib.path)\n      test -z \"$gnulib_path\" && gnulib_path=gnulib\n      GNULIB_SRCDIR=$gnulib_path\n    fi\n  fi\n\n  # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.\n  found_aux_dir=no\n  grep '^[\t ]*AC_CONFIG_AUX_DIR(\\['\"$build_aux\"'])' configure.ac \\\n      >/dev/null && found_aux_dir=yes\n  grep '^[\t ]*AC_CONFIG_AUX_DIR('\"$build_aux\"')' configure.ac \\\n      >/dev/null && found_aux_dir=yes\n  test $found_aux_dir = yes \\\n    || die \"configure.ac lacks 'AC_CONFIG_AUX_DIR([$build_aux])'; add it\"\n\n  # If $build_aux doesn't exist, create it now, otherwise some bits\n  # below will malfunction.  If creating it, also mark it as ignored.\n  if test ! -d $build_aux; then\n    mkdir $build_aux\n    for dot_ig in x $vc_ignore; do\n      test $dot_ig = x && continue\n      insert_vc_ignore $dot_ig $build_aux\n    done\n  fi\n\n  check_build_prerequisites false\n\n  use_libtool=0\n  # We'd like to use grep -E, to see if any of LT_INIT,\n  # AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,\n  # but that's not portable enough (e.g., for Solaris).\n  grep '^[\t ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \\\n    && use_libtool=1\n  grep '^[\t ]*LT_INIT' configure.ac >/dev/null \\\n    && use_libtool=1\n  if test $use_libtool = 1; then\n    find_tool LIBTOOLIZE glibtoolize libtoolize\n  fi\n\n  if $use_gnulib; then\n    gnulib_tool=$GNULIB_SRCDIR/gnulib-tool\n    <$gnulib_tool || return\n  fi\n\n  # NOTE: we have to be careful to run both autopoint and libtoolize\n  # before gnulib-tool, since gnulib-tool is likely to provide newer\n  # versions of files \"installed\" by these two programs.\n  # Then, *after* gnulib-tool (see below), we have to be careful to\n  # run autoreconf in such a way that it does not run either of these\n  # two just-pre-run programs.\n\n  # Import from gettext.\n  with_gettext=yes\n  grep '^[\t ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \\\n      with_gettext=no\n\n  if test $with_gettext = yes || test $use_libtool = 1; then\n\n    tempbase=.bootstrap$$\n    trap \"rm -f $tempbase.0 $tempbase.1\" HUP INT PIPE TERM\n\n    > $tempbase.0 > $tempbase.1 &&\n    find . ! -type d -print | sort > $tempbase.0 || return\n\n    if test $with_gettext = yes; then\n      # Released autopoint has the tendency to install macros that have been\n      # obsoleted in current gnulib, so run this before gnulib-tool.\n      echo \"$0: $AUTOPOINT --force\"\n      $AUTOPOINT --force || return\n    fi\n\n    # Autoreconf runs aclocal before libtoolize, which causes spurious\n    # warnings if the initial aclocal is confused by the libtoolized\n    # (or worse out-of-date) macro directory.\n    # libtoolize 1.9b added the --install option; but we support back\n    # to libtoolize 1.5.22, where the install action was default.\n    if test $use_libtool = 1; then\n      install=\n      case $($LIBTOOLIZE --help) in\n        *--install*) install=--install ;;\n      esac\n      echo \"running: $LIBTOOLIZE $install --copy\"\n      $LIBTOOLIZE $install --copy\n    fi\n\n    find . ! -type d -print | sort >$tempbase.1\n    old_IFS=$IFS\n    IFS=$nl\n    for file in $(comm -13 $tempbase.0 $tempbase.1); do\n      IFS=$old_IFS\n      parent=${file%/*}\n      version_controlled_file \"$parent\" \"$file\" || {\n        for dot_ig in x $vc_ignore; do\n          test $dot_ig = x && continue\n          ig=$parent/$dot_ig\n          insert_vc_ignore \"$ig\" \"${file##*/}\"\n        done\n      }\n    done\n    IFS=$old_IFS\n\n    rm -f $tempbase.0 $tempbase.1\n    trap - HUP INT PIPE TERM\n  fi\n\n  # Import from gnulib.\n\n  if $use_gnulib; then\n    gnulib_tool_options=\"\\\n     --no-changelog\\\n     --aux-dir=$build_aux\\\n     --doc-base=$doc_base\\\n     --lib=$gnulib_name\\\n     --m4-base=$m4_base/\\\n     --source-base=$source_base/\\\n     --tests-base=$tests_base\\\n     --local-dir=$local_gl_dir\\\n     $gnulib_tool_option_extras\\\n    \"\n    if test $use_libtool = 1; then\n      case \"$gnulib_tool_options \" in\n        *' --libtool '*) ;;\n        *) gnulib_tool_options=\"$gnulib_tool_options --libtool\" ;;\n      esac\n    fi\n    echo \"$0: $gnulib_tool $gnulib_tool_options --import ...\"\n    $gnulib_tool $gnulib_tool_options --import $gnulib_modules \\\n      || die \"gnulib-tool failed\"\n\n    for file in $gnulib_files; do\n      symlink_to_dir \"$GNULIB_SRCDIR\" $file \\\n        || die \"failed to symlink $file\"\n    done\n  fi\n\n  bootstrap_post_import_hook \\\n    || die \"bootstrap_post_import_hook failed\"\n\n  # Remove any dangling symlink matching \"*.m4\" or \"*.[ch]\" in some\n  # gnulib-populated directories.  Such .m4 files would cause aclocal to fail.\n  # The following requires GNU find 4.2.3 or newer.  Considering the usual\n  # portability constraints of this script, that may seem a very demanding\n  # requirement, but it should be ok.  Ignore any failure, which is fine,\n  # since this is only a convenience to help developers avoid the relatively\n  # unusual case in which a symlinked-to .m4 file is git-removed from gnulib\n  # between successive runs of this script.\n  find \"$m4_base\" \"$source_base\" \\\n    -depth \\( -name '*.m4' -o -name '*.[ch]' \\) \\\n    -type l -xtype l -delete > /dev/null 2>&1\n\n  # Invoke autoreconf with --force --install to ensure upgrades of tools\n  # such as ylwrap.\n  AUTORECONFFLAGS=\"--verbose --install --force -I $m4_base $ACLOCAL_FLAGS\"\n\n  # Some systems (RHEL 5) are using ancient autotools, for which the\n  # --no-recursive option had not been invented.  Detect that lack and\n  # omit the option when it's not supported.  FIXME in 2017: remove this\n  # hack when RHEL 5 autotools are updated, or when they become irrelevant.\n  case $($AUTORECONF --help) in\n    *--no-recursive*) AUTORECONFFLAGS=\"$AUTORECONFFLAGS --no-recursive\";;\n  esac\n\n  # Tell autoreconf not to invoke autopoint or libtoolize; they were run above.\n  echo \"running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS\"\n  AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \\\n    || die \"autoreconf failed\"\n\n  # Get some extra files from gnulib, overriding existing files.\n  for file in $gnulib_extra_files; do\n    case $file in\n      */INSTALL) dst=INSTALL;;\n      build-aux/*) dst=$build_aux/${file#build-aux/};;\n      *) dst=$file;;\n    esac\n    symlink_to_dir \"$GNULIB_SRCDIR\" $file $dst \\\n      || die \"failed to symlink $file\"\n  done\n\n  if test $with_gettext = yes; then\n    # Create gettext configuration.\n    echo \"$0: Creating po/Makevars from po/Makevars.template ...\"\n    rm -f po/Makevars\n    sed '\n      /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '\"$EXTRA_LOCALE_CATEGORIES\"'/\n      /^COPYRIGHT_HOLDER *=/s/=.*/= '\"$COPYRIGHT_HOLDER\"'/\n      /^MSGID_BUGS_ADDRESS *=/s|=.*|= '\"$MSGID_BUGS_ADDRESS\"'|\n      /^XGETTEXT_OPTIONS *=/{\n        s/$/ \\\\/\n        a\\\n            '\"$XGETTEXT_OPTIONS\"' $${end_of_xgettext_options+}\n      }\n    ' po/Makevars.template >po/Makevars \\\n      || die 'cannot generate po/Makevars'\n\n    # If the 'gettext' module is in use, grab the latest Makefile.in.in.\n    # If only the 'gettext-h' module is in use, assume autopoint already\n    # put the correct version of this file into place.\n    case $gnulib_modules in\n      *gettext-h*) ;;\n      *gettext*)\n        cp $GNULIB_SRCDIR/build-aux/po/Makefile.in.in po/Makefile.in.in \\\n          || die \"cannot create po/Makefile.in.in\"\n        ;;\n    esac\n\n    if test -d runtime-po; then\n      # Similarly for runtime-po/Makevars, but not quite the same.\n      rm -f runtime-po/Makevars\n      sed '\n        /^DOMAIN *=.*/s/=.*/= '\"$package\"'-runtime/\n        /^subdir *=.*/s/=.*/= runtime-po/\n        /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'\"$package\"'@gnu.org/\n        /^XGETTEXT_OPTIONS *=/{\n          s/$/ \\\\/\n          a\\\n              '\"$XGETTEXT_OPTIONS_RUNTIME\"' $${end_of_xgettext_options+}\n        }\n      ' po/Makevars.template >runtime-po/Makevars \\\n      || die 'cannot generate runtime-po/Makevars'\n\n      # Copy identical files from po to runtime-po.\n      (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po)\n    fi\n  fi\n\n  bootstrap_epilogue\n\n  echo \"$0: done.  Now you can run './configure'.\"\n}\n\n# ----------------------------------------------------------------------------\n\n# Local Variables:\n# eval: (add-hook 'before-save-hook 'time-stamp)\n# time-stamp-start: \"scriptlibversion=\"\n# time-stamp-format: \"%:y-%02m-%02d.%02H\"\n# time-stamp-time-zone: \"UTC0\"\n# time-stamp-end: \"; # UTC\"\n# End:\n"
  },
  {
    "path": "bootstrap.bat",
    "content": "@echo off\n:: Copyright (C) 2018-2024 Free Software Foundation, Inc.\n:: This file is part of GNU Make.\n::\n:: GNU Make is free software; you can redistribute it and/or modify it under\n:: the terms of the GNU General Public License as published by the Free\n:: Software Foundation; either version 3 of the License, or (at your option)\n:: any later version.\n::\n:: GNU Make is distributed in the hope that it will be useful, but WITHOUT\n:: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n:: FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.\n:: more details.\n::\n:: You should have received a copy of the GNU General Public License along\n:: with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nsetlocal\nset \"svurl=https://git.savannah.gnu.org/cgit\"\nset \"gnuliburl=%svurl%/gnulib.git/plain\"\n\nwhere curl >nul 2>&1\nif ERRORLEVEL 1 (\n    echo Cannot find curl: it must be installed for bootstrap\n    exit /b 1\n)\n\nwhere sed >nul 2>&1\nif ERRORLEVEL 1 (\n    echo Cannot find sed: it must be installed for bootstrap\n    echo Hint: you can use the sed provided in the Git for Windows install\n    exit /b 1\n)\n\nif exist lib goto Downloads\nmkdir lib\nif ERRORLEVEL 1 exit /b 1\n\n:Downloads\necho -- Downloading Gnulib modules\ncall :Download lib getloadavg.c\ncall :Download lib intprops.h\ncall :Download lib intprops-internal.h\n\necho -- Configuring the workspace\ncopy /Y gl\\lib\\*.* lib > nul\n\n:: In general it's tricky to use special characters as arguments to a program\n:: in Windows batch files; the quoting rules are obscure and have changed over\n:: time which means older systems may behave differently.  However, Windows\n:: echo is a dumb program that just writes out its command line without much\n:: interpreting: all we have to be careful of is ^ quoting.  So, use echo\n:: to create script files to use with sed -f rather than using sed -e.\n\n:: Create a sed script to convert templates\nif exist convert.sed del /Q convert.sed\necho s,@PACKAGE@,make,g > convert.sed\nif ERRORLEVEL 1 goto Failed\necho s,@PACKAGE_BUGREPORT@,bug-make@gnu.org,g >> convert.sed\nif ERRORLEVEL 1 goto Failed\necho s,@PACKAGE_NAME@,GNU Make,g >> convert.sed\nif ERRORLEVEL 1 goto Failed\necho s,@PACKAGE_TARNAME@,make,g >> convert.sed\nif ERRORLEVEL 1 goto Failed\necho s,@PACKAGE_URL@,https://www.gnu.org/software/make/,g >> convert.sed\necho s/^^AC_INIT^(\\[GNU.Make\\],\\[\\^([0-9.]*\\^)\\].*/s,@PACKAGE_VERSION@,\\1,g/p > cac.sed\nsed -n -f cac.sed configure.ac >> convert.sed\nif ERRORLEVEL 1 goto Failed\n:: Get the list of sources from Makefile.am\necho s,\\\\\\n,,g > mam.sed\necho s,[ \\t][ \\t]*, ,g >> mam.sed\necho s, [^^ ]*\\.h,,g >> mam.sed\necho s,src/,$^(src^),g >> mam.sed\necho s,lib/,$^(lib^),g >> mam.sed\necho s/^^\\^([A-Za-z0-9]*\\^)_SRCS *= *\\^(.*\\^)/s,%%\\1_SOURCES%%,\\2,/p > mam2.sed\nsed -z -f mam.sed Makefile.am | sed -n -f mam2.sed >> convert.sed\nif ERRORLEVEL 1 goto Failed\n\necho - Creating Basic.mk\nsed -f convert.sed Basic.mk.template > Basic.mk\nif ERRORLEVEL 1 goto Failed\necho - Creating src\\mkconfig.h\nsed -f convert.sed src\\mkconfig.h.in > src\\mkconfig.h\nif ERRORLEVEL 1 goto Failed\n\necho - Creating src\\gmk-default.h\necho static const char *const GUILE_module_defn = ^\" \\ > src\\gmk-default.h\necho s/;.*// > gmk.sed\necho /^^[ \\t]*$/d >> gmk.sed\necho s/\"/\\\\\"/g >> gmk.sed\necho s/$/ \\\\/ >> gmk.sed\nsed -f gmk.sed src\\gmk-default.scm >> src\\gmk-default.h\nif ERRORLEVEL 1 goto Failed\necho ^\";>> src\\gmk-default.h\n\n:: These files would be created by bootstrap; they are not needed on Windows\n:: but our makefile depends on them\necho >> lib\\alloca.in.h\n\ndel /Q convert.sed cac.sed mam.sed mam2.sed gmk.sed\n\necho.\necho Done.  Run build_w32.bat to build GNU Make.\ngoto :EOF\n\n:Download\nif exist \"%1\\%2\" goto :EOF\necho - Downloading %1\\%2\ncurl -sS -o \"%1\\%2\" \"%gnuliburl%/%1/%2\"\nif ERRORLEVEL 1 exit /b 1\ngoto :EOF\n\n:Failed\necho *** Bootstrap failed.\necho Resolve the issue, or use the configured source in the release tarball\nexit /b 1\n"
  },
  {
    "path": "bootstrap.conf",
    "content": "# Bootstrap configuration.                                   -*-shell-script-*-\n\n# Copyright (C) 2018-2024 Free Software Foundation, Inc.\n\n# GNU Make is free software: you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free\n# Software Foundation; either version 3 of the License, or (at your option)\n# any later version.\n\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Allow bootstrap to know that this is not a package\ncheckout_only_file=README.git\n\n# Choose a specific version of gnulib, when checking out\nGNULIB_REVISION=stable-202401\n\n# Always copy files rather than symlink\ncopy=true\n\n# Additional xgettext options to use.  Use \"\\\\\\newline\" to break lines.\n# Ensure that all our magical output macros are correctly marked as\n# C (printf) format strings.\nXGETTEXT_OPTIONS='\\\\\\\n --from-code=UTF-8\\\\\\\n --flag=_:1:pass-c-format\\\\\\\n --flag=N_:1:pass-c-format\\\\\\\n --flag=DB:2:c-format --flag=DBF:2:c-format --flag=DBS:2:c-format\\\\\\\n --flag=O:3:c-format  --flag=OSN:3:c-format --flag=ONS:3:c-format\\\\\\\n --flag=OS:3:c-format --flag=OSS:3:c-format --flag=OSSS:3:c-format\\\\\\\n --flag=ON:3:c-format --flag=ONN:3:c-format\\\\\\\n'\n\n# We manage our own .gitignore files\nvc_ignore=\n\n# Build prerequisites\nbuildreq=\"\\\nautoconf   2.69\nautomake   1.16.1\n\"\n\ngnulib_name=libgnu\ngnulib_files=\"doc/make-stds.texi m4/sig_atomic_t.m4\"\n\n# Using the full strtoll module pulls in a lot of stuff.  But, it's pretty\n# simple to use just the base source file, so pull that.  We'll use it in\n# src/misc.c if strtoll() is not found.\ngnulib_files=\"$gnulib_files lib/strtol.c\"\n\ngnulib_modules=\"\\\nalloca\nfdl\nfindprog-in\ngetloadavg\nhost-cpu-c-abi\nlargefile\nmake-glob\nmake-macros\"\n"
  },
  {
    "path": "build.cfg.in",
    "content": "# Configuration for building GNU Make in the absence of any 'make' program.\n# @configure_input@\n\n# Copyright (C) 1993-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# See Makefile.in for comments describing these variables.\n\ntop_srcdir='@top_srcdir@'\n\nprefix='@prefix@'\nexec_prefix=`eval echo @exec_prefix@`\n\nCC='@CC@'\nAR='@AR@'\nCFLAGS='@CFLAGS@ @GUILE_CFLAGS@'\nCPPFLAGS='@CPPFLAGS@'\nDEFS='@DEFS@'\nARFLAGS='@ARFLAGS@'\nLDFLAGS='@AM_LDFLAGS@ @LDFLAGS@'\nALLOCA='@ALLOCA@'\nLOADLIBES='@LIBS@ @GUILE_LIBS@ @LIBINTL@'\nREMOTE='@REMOTE@'\nOBJEXT='@OBJEXT@'\nEXEEXT='@EXEEXT@'\n"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/sh\n# Shell script to build GNU Make in the absence of any 'make' program.\n\n# Copyright (C) 1993-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Get configure-generated values\n. ./build.cfg\n\ndie () { echo \"$*\" 1>&2; exit 1; }\nusage () { echo \"$0 [-k]\"; exit $1; }\n\nkeep_going=false\n\n: ${OUTDIR:=.}\nOUTLIB=\"$OUTDIR/lib\"\n\n# Directory to find libraries in for '-lXXX'.\nlibdir=$exec_prefix/lib\n# Directory to search by default for included makefiles.\nincludedir=$prefix/include\n\nlocaledir=$prefix/share/locale\n\ndefines=\"-DLOCALEDIR=\\\"$localedir\\\" -DLIBDIR=\\\"$libdir\\\" -DINCLUDEDIR=\\\"$includedir\\\"\"\n\n# Look up a make variable value.\n# It can handle simple recursion where variables are separate words.\n# Print the value to stdout.\nget_mk_var ()\n{\n  v=$(sed -e :a -e '/\\\\$/N; s/\\\\\\n//; ta' \"$1\" | sed -n \"s=^ *$2 *\\= *==p\")\n  for w in $v; do\n    case $w in\n      (\\$[\\(\\{]*[\\)\\}]) w=${w#\\$[\\(\\{]}; (get_mk_var \"$1\" \"${w%[\\)\\}]}\") ;;\n      (*) echo \"$w\" ;;\n    esac\n  done\n}\n\n# Compile source files.  Object files are put into $objs.\ncompile ()\n{\n  success=true\n  objs=\n  for ofile in \"$@\"; do\n    # We should try to use a Makefile variable like libgnu_a_SOURCES or\n    # something but just hardcode it.\n    file=\"${ofile%.$OBJEXT}.c\"\n    case $file in\n        (lib/libgnu_a-*.c) file=\"lib/${file#lib/libgnu_a-}\" ;;\n    esac\n    echo \"compiling $file...\"\n    of=\"$OUTDIR/$ofile\"\n    mkdir -p \"${of%/*}\" || exit 1\n    if $CC $cflags $CPPFLAGS $CFLAGS -c -o \"$of\" \"$top_srcdir/$file\"; then\n        : worked\n    else\n        $keep_going || die \"Compilation failed.\"\n        success=false\n    fi\n\n    objs=\"${objs:+$objs }$of\"\n  done\n\n  $success\n}\n\n# Use config.status to convert a .in file.  Output file is put into $out.\n# $out will be empty if no conversion was needed.\nconvert ()\n{\n  out=\n  base=$1\n  var=\"GENERATE_$(echo $base | tr 'a-z./+' A-Z__X)\"\n\n  # Is this file disabled?\n  grep \"${var}_FALSE\\\"]=\\\"\\\"\" config.status >/dev/null && return 0\n\n  # If there's no .in file then no conversion needed\n  in=\"$top_srcdir/lib/$(echo ${base%.*}.in.${base##*.} | tr / _)\"\n  test -f \"$in\" || return 0\n\n  # Not disabled, so create it\n  out=\"$OUTLIB/$base\"\n  mkdir -p \"${out%/*}\"\n\n  # First perform the normal replacements, using config.status\n  sed -e 's|@GUARD_PREFIX@|GL|g' \\\n      -e 's/@GNULIB_UNISTD_H_GETOPT@/0/g' \\\n      \"$in\" > \"${out}_\"\n  ./config.status --file \"${out}__:${out}_\"\n  int=\"${out}__\"\n\n  # Then see if there any files we need to include.  Unfortunately there's no\n  # algorithmic conversion so we just have to hard-code it.\n  incls=$(sed -n 's/.*definitions* of \\(_[^ $]*\\).*/\\1/p' \"$in\")\n\n  for inc in $incls; do\n    case $inc in\n      (_GL_FUNCDECL_RPL) fn=$(get_mk_var lib/Makefile CXXDEFS_H) ;;\n      (_GL_ARG_NONNULL)  fn=$(get_mk_var lib/Makefile ARG_NONNULL_H) ;;\n      (_GL_WARN_ON_USE)  fn=$(get_mk_var lib/Makefile WARN_ON_USE_H) ;;\n      (_Noreturn)        fn=$(get_mk_var lib/Makefile _NORETURN_H) ;;\n      (*) echo \"Unknown file replacement: $inc\"; exit 1 ;;\n    esac\n\n    fn=\"$top_srcdir/lib/${fn##*/}\"\n    test -f \"$fn\" || { echo \"Missing file: $fn\"; exit 1; }\n\n    sed \"/definitions* of $inc/r $fn\" \"$int\" > \"${int}_\"\n    int=${int}_\n  done\n\n  # Done!\n  mv \"$int\" \"$out\"\n}\n\n# Get source files provided from gnulib and convert to object files\nLIBOBJS=\nfor lo in $( (get_mk_var lib/Makefile libgnu_a_OBJECTS; get_mk_var lib/Makefile libgnu_a_LIBADD) | sed \"s=\\$[\\(\\{]OBJEXT[\\)\\}]=$OBJEXT=g\"); do\n  LIBOBJS=\"${LIBOBJS:+$LIBOBJS }lib/$lo\"\ndone\n\n# Get object files from the Makefile\nOBJS=$(get_mk_var Makefile make_OBJECTS | sed \"s=\\$[\\(\\{]OBJEXT[\\)\\}]=$OBJEXT=g\")\n\nwhile test -n \"$1\"; do\n    case $1 in\n        (-k) keep_going=true; shift ;;\n        (--) shift; break ;;\n        (-[h?]) usage 0 ;;\n        (-*) echo \"Unknown option: $1\"; usage 1 ;;\n    esac\ndone\n\ntest -z \"$1\" || die \"Unknown argument: $*\"\n\n# Generate gnulib header files that would normally be created by make\nset -e\nfor b in $(get_mk_var lib/Makefile BUILT_SOURCES); do\n    convert $b\ndone\nset +e\n\n# Build the gnulib library\ncflags=\"$DEFS -I$OUTLIB -Ilib -I$top_srcdir/lib -I$OUTDIR/src -Isrc -I$top_srcdir/src\"\ncompile $LIBOBJS || die \"Compilation failed.\"\n\necho \"creating libgnu.a...\"\n$AR $ARFLAGS \"$OUTLIB\"/libgnu.a $objs || die \"Archive of libgnu failed.\"\n\n# Compile the source files into those objects.\ncflags=\"$DEFS $defines -I$OUTDIR/src -Isrc -I$top_srcdir/src -I$OUTLIB -Ilib -I$top_srcdir/lib\"\ncompile $OBJS || die \"Compilation failed.\"\n\n# Link all the objects together.\necho \"linking make...\"\n$CC $CFLAGS $LDFLAGS -L\"$OUTLIB\" -o \"$OUTDIR/makenew$EXEEXT\" $objs -lgnu $LOADLIBES || die \"Link failed.\"\n\nmv -f \"$OUTDIR/makenew$EXEEXT\" \"$OUTDIR/make$EXEEXT\" || exit 1\n\necho done.\n"
  },
  {
    "path": "build_w32.bat",
    "content": "@echo off\r\n:: Copyright (C) 1996-2024 Free Software Foundation, Inc.\r\n:: This file is part of GNU Make.\r\n::\r\n:: GNU Make is free software; you can redistribute it and/or modify it under\r\n:: the terms of the GNU General Public License as published by the Free\r\n:: Software Foundation; either version 3 of the License, or (at your option)\r\n:: any later version.\r\n::\r\n:: GNU Make is distributed in the hope that it will be useful, but WITHOUT\r\n:: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r\n:: FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.\r\n:: more details.\r\n::\r\n:: You should have received a copy of the GNU General Public License along\r\n:: with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n\r\nsetlocal\r\nif not \"%RECURSEME%\"==\"%~0\" (\r\n    set \"RECURSEME=%~0\"\r\n    %ComSpec% /s /c \"\"%~0\" %*\"\r\n    goto :EOF\r\n)\r\n\r\ncall :Reset\r\n\r\nif \"%1\" == \"-h\" goto Usage\r\nif \"%1\" == \"--help\" goto Usage\r\n\r\necho.\r\necho Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8/10/11\r\necho.\r\n\r\nset MAKE=gnumake\r\nset GUILE=Y\r\nset COMPILER=cl.exe\r\nset RC=rc.exe\r\nset O=obj\r\nset ARCH=x64\r\nset DEBUG=N\r\nset DIRENT=Y\r\nset VERBOSE=N\r\n\r\nif exist maintMakefile (\r\n    set MAINT=Y\r\n) else (\r\n    set MAINT=N\r\n)\r\n\r\n:ParseSW\r\nif \"%1\" == \"--verbose\" goto SetVerbose\r\nif \"%1\" == \"--debug\" goto SetDebug\r\nif \"%1\" == \"--without-guile\" goto NoGuile\r\nif \"%1\" == \"--x86\" goto Set32Bit\r\nif \"%1\" == \"gcc\" goto SetCC\r\nif \"%1\" == \"tcc\" goto SetTCC\r\nif \"%1\" == \"\" goto DoneSW\r\ngoto Usage\r\n\r\n:SetVerbose\r\nset VERBOSE=Y\r\nshift\r\ngoto ParseSW\r\n\r\n:SetDebug\r\nset DEBUG=Y\r\necho - Building without compiler optimizations\r\nshift\r\ngoto ParseSW\r\n\r\n:NoGuile\r\nset GUILE=N\r\necho - Building without Guile\r\nshift\r\ngoto ParseSW\r\n\r\n:Set32Bit\r\nset ARCH=x86\r\necho - Building 32bit GNU Make\r\nshift\r\ngoto ParseSW\r\n\r\n:SetCC\r\nset COMPILER=gcc\r\nset RC=windres\r\nset O=o\r\necho - Building with GCC\r\nshift\r\ngoto ParseSW\r\n\r\n:SetTCC\r\nset COMPILER=tcc\r\nset RC=windres\r\nset O=o\r\necho - Building with TinyC\r\nshift\r\ngoto ParseSW\r\n\r\n:DoneSW\r\nif \"%MAINT%\" == \"Y\" echo - Enabling maintainer mode\r\n\r\nif \"%COMPILER%\" == \"gcc\" goto FindGcc\r\nif \"%COMPILER%\" == \"tcc\" goto FindTcc\r\n\r\n:: Find a compiler.  Visual Studio requires a lot of effort to locate :-/.\r\ncall %COMPILER% >nul 2>&1\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\n:: Visual Studio 15 2017 and above provides the \"vswhere\" tool\r\ncall :FindVswhere\r\nif ERRORLEVEL 1 goto LegacyVS\r\n\r\nfor /f \"tokens=* usebackq\" %%i in (`\"%VSWHERE%\" -latest -property installationPath`) do (\r\n    set InstallPath=%%i\r\n)\r\nset \"VSVARS=%InstallPath%\\VC\\Auxiliary\\Build\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\n:: No \"vswhere\" or it can't find a compiler.  Go old-school.\r\n:LegacyVS\r\nset \"VSVARS=%VS150COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS140COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS120COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS110COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS100COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS90COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS80COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS71COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%VS70COMNTOOLS%\\..\\..\\VC\\vcvarsall.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%V6TOOLS%\\VC98\\Bin\\vcvars32.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%V6TOOLS%\\VC97\\Bin\\vcvars32.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\nset \"VSVARS=%V5TOOLS%\\VC\\Bin\\vcvars32.bat\"\r\ncall :CheckMSVC\r\nif not ERRORLEVEL 1 goto FoundMSVC\r\n\r\n:: We did not find anything--fail\r\necho No MSVC compiler available.\r\necho Please run vcvarsall.bat and/or configure your Path.\r\nexit 1\r\n\r\n:FoundMSVC\r\nset OUTDIR=.\\WinRel\r\nset LNKOUT=./WinRel\r\nset \"OPTS=/O2 /D NDEBUG\"\r\nset LINKOPTS=\r\nif \"%DEBUG%\" == \"Y\" set OUTDIR=.\\WinDebug\r\nif \"%DEBUG%\" == \"Y\" set LNKOUT=./WinDebug\r\nif \"%DEBUG%\" == \"Y\" set \"OPTS=/Zi /Od /D _DEBUG\"\r\nif \"%DEBUG%\" == \"Y\" set LINKOPTS=/DEBUG\r\nif \"%MAINT%\" == \"Y\" set \"OPTS=%OPTS% /D MAKE_MAINTAINER_MODE\"\r\n:: Show the compiler version that we found\r\n:: Unfortunately this also shows a \"usage\" note; I can't find anything better.\r\necho.\r\ncall %COMPILER%\r\ngoto FindRC\r\n\r\n:FindGcc\r\nset OUTDIR=.\\GccRel\r\nset LNKOUT=./GccRel\r\nset OPTS=-O2\r\nset DIRENT=N\r\nif \"%DEBUG%\" == \"Y\" set OPTS=-O0\r\nif \"%DEBUG%\" == \"Y\" set OUTDIR=.\\GccDebug\r\nif \"%DEBUG%\" == \"Y\" set LNKOUT=./GccDebug\r\nif \"%MAINT%\" == \"Y\" set \"OPTS=%OPTS% -DMAKE_MAINTAINER_MODE\"\r\n:: Show the compiler version that we found\r\necho.\r\ncall %COMPILER% --version\r\nif not ERRORLEVEL 1 goto FindRC\r\necho No %COMPILER% found.\r\nexit 1\r\n\r\n:FindTcc\r\nset OUTDIR=.\\TccRel\r\nset LNKOUT=./TccRel\r\nset OPTS=-O2\r\nif \"%DEBUG%\" == \"Y\" set OPTS=-O0\r\nif \"%DEBUG%\" == \"Y\" set OUTDIR=.\\TccDebug\r\nif \"%DEBUG%\" == \"Y\" set LNKOUT=./TccDebug\r\nif \"%MAINT%\" == \"Y\" set \"OPTS=%OPTS% -DMAKE_MAINTAINER_MODE\"\r\n:: Show the compiler version that we found\r\necho.\r\ncall %COMPILER% -v\r\nif not ERRORLEVEL 1 goto FindRC\r\necho No %COMPILER% found.\r\nexit 1\r\n\r\n:FindRC\r\nset HAVE_RC=Y\r\ncall where %RC% >nul 2>&1\r\nif not ERRORLEVEL 1 goto Build\r\necho.\r\necho %RC% was not found. Building without UTF-8 resource.\r\nset HAVE_RC=N\r\n\r\n:Build\r\necho.\r\n:: Clean the directory if it exists\r\nif exist %OUTDIR%\\nul rmdir /S /Q %OUTDIR%\r\n\r\n:: Recreate it\r\nmkdir %OUTDIR%\r\nmkdir %OUTDIR%\\src\r\nmkdir %OUTDIR%\\src\\w32\r\nmkdir %OUTDIR%\\src\\w32\\compat\r\nmkdir %OUTDIR%\\src\\w32\\subproc\r\nmkdir %OUTDIR%\\lib\r\n\r\nif \"%GUILE%\" == \"Y\" call :ChkGuile\r\n\r\nif not exist src\\config.h.W32 goto NotConfig\r\n\r\necho.\r\necho Compiling %OUTDIR% version\r\n\r\ncopy src\\config.h.W32 %OUTDIR%\\src\\config.h\r\n\r\ncopy lib\\glob.in.h %OUTDIR%\\lib\\glob.h\r\ncopy lib\\fnmatch.in.h %OUTDIR%\\lib\\fnmatch.h\r\n\r\nif exist %OUTDIR%\\link.sc del %OUTDIR%\\link.sc\r\n\r\ncall :Compile src/ar\r\ncall :Compile src/arscan\r\ncall :Compile src/commands\r\ncall :Compile src/default\r\ncall :Compile src/dir\r\ncall :Compile src/expand\r\ncall :Compile src/file\r\ncall :Compile src/function\r\ncall :Compile src/getopt\r\ncall :Compile src/getopt1\r\ncall :Compile src/guile GUILE\r\ncall :Compile src/hash\r\ncall :Compile src/implicit\r\ncall :Compile src/job\r\ncall :Compile src/load\r\ncall :Compile src/loadapi\r\ncall :Compile src/main GUILE\r\ncall :Compile src/misc\r\ncall :Compile src/output\r\ncall :Compile src/read\r\ncall :Compile src/remake\r\ncall :Compile src/remote-stub\r\ncall :Compile src/rule\r\ncall :Compile src/shuffle\r\ncall :Compile src/signame\r\ncall :Compile src/strcache\r\ncall :Compile src/variable\r\ncall :Compile src/version\r\ncall :Compile src/vpath\r\ncall :Compile src/warning\r\ncall :Compile src/w32/pathstuff\r\ncall :Compile src/w32/w32os\r\ncall :Compile src/w32/compat/posixfcn\r\ncall :Compile src/w32/subproc/misc\r\ncall :Compile src/w32/subproc/sub_proc\r\ncall :Compile src/w32/subproc/w32err\r\ncall :Compile lib/fnmatch\r\ncall :Compile lib/glob\r\ncall :Compile lib/getloadavg\r\n\r\n:: Compile dirent unless it is supported by compiler library (like with gcc).\r\nif \"%DIRENT%\" == \"Y\" call :Compile src\\w32\\compat\\dirent\r\n\r\n:: Compile UTF-8 resource if a resource compiler is available.\r\nif \"%HAVE_RC%\" == \"Y\" call :ResourceCompile src/w32/utf8\r\n\r\ncall :Link\r\n\r\necho.\r\nif exist %OUTDIR%\\%MAKE%.exe goto Success\r\necho %OUTDIR% build FAILED!\r\nexit 1\r\n\r\n:Success\r\necho %OUTDIR% build succeeded.\r\nif exist Basic.mk copy /Y Basic.mk Makefile\r\nif not exist tests\\config-flags.pm copy /Y tests\\config-flags.pm.W32 tests\\config-flags.pm\r\ncall :Reset\r\ngoto :EOF\r\n\r\n::\r\n:: Subroutines\r\n::\r\n\r\n:Compile\r\nif \"%VERBOSE%\" == \"N\" echo - Compiling %1.c\r\necho %LNKOUT%/%1.%O% >>%OUTDIR%\\link.sc\r\nset EXTRAS=\r\nif \"%2\" == \"GUILE\" set \"EXTRAS=%GUILECFLAGS%\"\r\nif exist \"%OUTDIR%\\%1.%O%\" del \"%OUTDIR%\\%1.%O%\"\r\nif \"%COMPILER%\" == \"gcc\" goto GccCompile\r\nif \"%COMPILER%\" == \"tcc\" goto TccCompile\r\n\r\n:: MSVC Compile\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall %COMPILER% /nologo /MT /W4 /EHsc %OPTS% /I %OUTDIR%/src /I src /I %OUTDIR%/lib /I lib /I src/w32/include /D _CONSOLE /D HAVE_CONFIG_H /FR%OUTDIR% /Fp%OUTDIR%\\%MAKE%.pch /Fo%OUTDIR%\\%1.%O% /Fd%OUTDIR%\\%MAKE%.pdb %EXTRAS% /c %1.c\r\n@echo off\r\ngoto CompileDone\r\n\r\n:GccCompile\r\n:: GCC Compile\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall %COMPILER% -mthreads -Wall -std=gnu99 -gdwarf-2 -g3 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR%/lib -I./lib -I./src/w32/include -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%/%1.%O% -c %1.c\r\n@echo off\r\ngoto CompileDone\r\n\r\n:TccCompile\r\n:: TCC Compile\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall %COMPILER% -mthreads -Wall -std=c11 %OPTS% -I%OUTDIR%/src -I./src -I%OUTDIR%/lib -I./lib -I./src/w32/include -D_cdecl= -D_MSC_VER -DHAVE_CONFIG_H %EXTRAS% -o %OUTDIR%/%1.%O% -c %1.c\r\n@echo off\r\ngoto CompileDone\r\n\r\n:ResourceCompile\r\nif \"%VERBOSE%\" == \"N\" echo - Compiling %1.rc\r\necho %LNKOUT%/%1.%O% >>%OUTDIR%\\link.sc\r\nif exist \"%OUTDIR%\\%1.%O%\" del \"%OUTDIR%\\%1.%O%\"\r\nif \"%COMPILER%\" == \"gcc\" goto GccResourceCompile\r\nif \"%COMPILER%\" == \"tcc\" goto TccResourceCompile\r\n\r\n:: MSVC Resource Compile\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall %RC% /fo %OUTDIR%\\%1.%O% %1.rc\r\n@echo off\r\ngoto CompileDone\r\n\r\n:GccResourceCompile\r\n:: GCC Resource Compile\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall %RC% -o %OUTDIR%/%1.%O% -i %1.rc\r\n@echo off\r\ngoto CompileDone\r\n\r\n:TccResourceCompile\r\n:: TCC Resource Compile\r\ngoto GccResourceCompile\r\n\r\n:CompileDone\r\nif not exist \"%OUTDIR%\\%1.%O%\" exit 1\r\ngoto :EOF\r\n\r\n:Link\r\necho.\r\necho - Linking %LNKOUT%/%MAKE%.exe\r\nif \"%COMPILER%\" == \"gcc\" goto GccLink\r\nif \"%COMPILER%\" == \"tcc\" goto TccLink\r\n\r\n:: MSVC Link\r\necho %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib >>%OUTDIR%\\link.sc\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\ncall link.exe /NOLOGO /SUBSYSTEM:console /PDB:%LNKOUT%\\%MAKE%.pdb %LINKOPTS% /OUT:%LNKOUT%\\%MAKE%.exe @%LNKOUT%\\link.sc\r\n@echo off\r\ngoto :EOF\r\n\r\n:GccLink\r\n:: GCC Link\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\necho %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 >>%OUTDIR%\\link.sc\r\ncall %COMPILER% -mthreads -gdwarf-2 -g3 %OPTS% -o %LNKOUT%/%MAKE%.exe @%LNKOUT%/link.sc -Wl,--out-implib=%LNKOUT%/libgnumake-1.dll.a\r\n@echo off\r\ngoto :EOF\r\n\r\n:TccLink\r\n:: TCC Link\r\nif \"%VERBOSE%\" == \"Y\" echo on\r\necho %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lodbc32 -lodbccp32 >>%OUTDIR%\\link.sc\r\ncall %COMPILER% -mthreads %OPTS% -o %LNKOUT%/%MAKE%.exe @%LNKOUT%/link.sc \r\n@echo off\r\ngoto :EOF\r\n\r\n:ChkGuile\r\n:: Build with Guile is supported only on NT and later versions\r\nif not \"%OS%\" == \"Windows_NT\" goto NoGuile\r\ncall pkg-config --help > %OUTDIR%\\guile.tmp 2> NUL\r\nif ERRORLEVEL 1 goto NoPkgCfg\r\n\r\nset PKGMSC=\r\nif not \"%COMPILER%\" == \"gcc\" set PKGMSC=--msvc-syntax\r\n\r\necho Checking for Guile 2.0\r\ncall pkg-config --cflags --short-errors \"guile-2.0\" > %OUTDIR%\\gl-c2.tmp 2> NUL\r\nif not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\\gl-c2.tmp\r\n\r\ncall pkg-config --libs --static --short-errors %PKGMSC% \"guile-2.0\" > %OUTDIR%\\gl-l2.tmp 2> NUL\r\nif not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\\gl-l2.tmp\r\n\r\nif not \"%GUILECFLAGS%\" == \"\" goto GuileDone\r\n\r\necho Checking for Guile 1.8\r\ncall pkg-config --cflags --short-errors \"guile-1.8\" > %OUTDIR%\\gl-c18.tmp 2> NUL\r\nif not ERRORLEVEL 1 set /P GUILECFLAGS= < %OUTDIR%\\gl-c18.tmp\r\n\r\ncall pkg-config --libs --static --short-errors %PKGMSC% \"guile-1.8\" > %OUTDIR%\\gl-l18.tmp 2> NUL\r\nif not ERRORLEVEL 1 set /P GUILELIBS= < %OUTDIR%\\gl-l18.tmp\r\n\r\nif not \"%GUILECFLAGS%\" == \"\" goto GuileDone\r\n\r\necho - No Guile found, building without Guile\r\ngoto GuileDone\r\n\r\n:NoPkgCfg\r\necho - pkg-config not found, building without Guile\r\n\r\n:GuileDone\r\nif \"%GUILECFLAGS%\" == \"\" goto :EOF\r\n\r\necho - Guile found: building with Guile\r\nset \"GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE\"\r\ngoto :EOF\r\n\r\n:FindVswhere\r\nset VSWHERE=vswhere\r\ncall \"%VSWHERE%\" -help >nul 2>&1\r\nif not ERRORLEVEL 1 exit /b 0\r\nset \"VSWHERE=C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere\"\r\ncall \"%VSWHERE%\" -help >nul 2>&1\r\nif ERRORLEVEL 1 exit /b 1\r\ngoto :EOF\r\n\r\n:CheckMSVC\r\nif not exist \"%VSVARS%\" exit /b 1\r\ncall \"%VSVARS%\" %ARCH%\r\nif ERRORLEVEL 1 exit /b 1\r\ncall %COMPILER% >nul 2>&1\r\nif ERRORLEVEL 1 exit /b 1\r\ngoto :EOF\r\n\r\n:NotConfig\r\necho.\r\necho *** This workspace is not configured.\r\necho Either retrieve the configured source in the release tarball\r\necho or, if building from Git, run the .\\bootstrap.bat script first.\r\nexit /b 1\r\n\r\n:Usage\r\necho Usage: %0 [options] [gcc] OR [tcc]\r\necho Options:\r\necho.  --without-guile   Do not compile Guile support even if found\r\necho.  --debug           Make a Debug build--default is Release\r\necho.  --x86             Make a 32bit binary--default is 64bit\r\necho.  --help            Display these instructions and exit\r\necho.\r\necho. \"gcc\" means compile with GCC, \"tcc\" means compile with Tiny C's TCC\r\ngoto :EOF\r\n\r\n:Reset\r\nset ARCH=\r\nset COMPILER=\r\nset DEBUG=\r\nset GUILE=\r\nset GUILECFLAGS=\r\nset GUILELIBS=\r\nset LINKOPTS=\r\nset MAKE=\r\nset NOGUILE=\r\nset O=\r\nset OPTS=\r\nset OUTDIR=\r\nset LNKOUT=\r\nset PKGMSC=\r\nset VSVARS=\r\ngoto :EOF\r\n"
  },
  {
    "path": "builddos.bat",
    "content": "@echo off\r\nrem Copyright (C) 1998-2024 Free Software Foundation, Inc.\r\nrem This file is part of GNU Make.\r\nrem\r\nrem GNU Make is free software; you can redistribute it and/or modify it under\r\nrem the terms of the GNU General Public License as published by the Free\r\nrem Software Foundation; either version 3 of the License, or (at your option)\r\nrem any later version.\r\nrem\r\nrem GNU Make is distributed in the hope that it will be useful, but WITHOUT\r\nrem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r\nrem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.\r\nrem more details.\r\nrem\r\nrem You should have received a copy of the GNU General Public License along\r\nrem with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n\r\necho Building Make for MSDOS with DJGPP\r\n\r\nrem The SmallEnv trick protects against too small environment block,\r\nrem in which case the values will be truncated and the whole thing\r\nrem goes awry.  COMMAND.COM will say \"Out of environment space\", but\r\nrem many people don't care, so we force them to care by refusing to go.\r\n\r\nrem Where is the srcdir?\r\nset XSRC=.\r\nif not \"%XSRC%\"==\".\" goto SmallEnv\r\nif \"%1%\"==\"\" goto SrcDone\r\nif \"%1%\"==\".\" goto SrcDone\r\nset XSRC=%1\r\n\r\nif not \"%XSRC%\"==\"%1\" goto SmallEnv\r\n\r\n:SrcDone\r\n\r\nif not exist src mkdir src\r\nif not exist lib mkdir lib\r\n\r\ncopy /Y %XSRC%\\src\\configh.dos .\\src\\config.h\r\n\r\ncopy /Y %XSRC%\\lib\\glob.in.h .\\lib\\glob.h\r\ncopy /Y %XSRC%\\lib\\fnmatch.in.h .\\lib\\fnmatch.h\r\n\r\nrem Echo ON so they will see what is going on.\r\n@echo on\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/commands.c -o commands.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/output.c -o output.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/job.c -o job.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/dir.c -o dir.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/file.c -o file.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/misc.c -o misc.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -DLOCALEDIR=\\\"/dev/env/DJDIR/share/locale\\\" -O2 -g %XSRC%/src/main.c -o main.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -DINCLUDEDIR=\\\"/dev/env/DJDIR/include\\\" -O2 -g %XSRC%/src/read.c -o read.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -DLIBDIR=\\\"/dev/env/DJDIR/lib\\\" -O2 -g %XSRC%/src/remake.c -o remake.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/rule.c -o rule.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/implicit.c -o implicit.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/default.c -o default.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/variable.c -o variable.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/warning.c -o warning.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/expand.c -o expand.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/function.c -o function.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/vpath.c -o vpath.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/hash.c -o hash.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/strcache.c -o strcache.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/version.c -o version.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/ar.c -o ar.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/arscan.c -o arscan.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/signame.c -o signame.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/remote-stub.c -o remote-stub.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/getopt.c -o getopt.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/getopt1.c -o getopt1.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/shuffle.c -o shuffle.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/load.c -o load.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/lib/glob.c -o lib/glob.o\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/lib/fnmatch.c -o lib/fnmatch.o\r\n@echo off\r\necho commands.o > respf.$$$\r\nfor %%f in (job output dir file misc main read remake rule implicit default variable warning load) do echo %%f.o >> respf.$$$\r\nfor %%f in (expand function vpath hash strcache version ar arscan signame remote-stub getopt getopt1 shuffle) do echo %%f.o >> respf.$$$\r\nfor %%f in (lib\\glob lib\\fnmatch) do echo %%f.o >> respf.$$$\r\ngcc -c -I./src -I%XSRC%/src -I./lib -I%XSRC%/lib -DHAVE_CONFIG_H -O2 -g %XSRC%/src/guile.c -o guile.o\r\necho guile.o >> respf.$$$\r\n@echo Linking...\r\n@echo on\r\ngcc -o make.exe @respf.$$$\r\n@echo off\r\nif not exist make.exe echo Make.exe build failed...\r\nif exist make.exe echo make.exe is now built!\r\nif exist make.exe del respf.$$$\r\nif exist make.exe copy /Y %XSRC%\\Basic.mk Makefile\r\ngoto End\r\n\r\n:SmallEnv\r\necho Your environment is too small.  Please enlarge it and run me again.\r\n\r\n:End\r\nset XRSC=\r\n@echo on\r\n"
  },
  {
    "path": "configure.ac",
    "content": "# Process this file with autoconf to produce a configure script.\n#\n# Copyright (C) 1993-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAC_INIT([GNU Make],[4.4.90],[bug-make@gnu.org])\n\nAC_PREREQ([2.69])\n\n# Autoconf setup\nAC_CONFIG_AUX_DIR([build-aux])\nAC_CONFIG_SRCDIR([src/vpath.c])\nAC_CONFIG_HEADERS([src/config.h])\n\nAC_CONFIG_LIBOBJ_DIR([lib])\n\n# Automake setup\n# We have to enable \"foreign\" because ChangeLog is auto-generated\n# Automake 1.15 and gnulib don't get along: gnulib has some strange error\n# in the way it handles getloadavg.c which causes make distcheck to fail.\n# https://lists.gnu.org/archive/html/bug-gnulib/2018-06/msg00024.html\nAM_INIT_AUTOMAKE([1.16.1 foreign -Werror -Wall])\n\n# Checks for programs.\nAC_USE_SYSTEM_EXTENSIONS\nAC_PROG_CC\nAC_PROG_CXX\nAC_DEFINE_UNQUOTED(MAKE_CXX, [\"$CXX\"], [Default C++ compiler.])\n\n# Configure gnulib\ngl_EARLY\ngl_INIT\n\nAC_PROG_INSTALL\nAC_PROG_RANLIB\nAC_PROG_CPP\nAC_CHECK_PROG([AR], [ar], [ar], [ar])\n# Perl is needed for the test suite (only)\nAC_CHECK_PROG([PERL], [perl], [perl], [perl])\n\n# Specialized system macros\nAC_CANONICAL_HOST\nAC_C_BIGENDIAN\n\n# Enable gettext, in \"external\" mode.\nAM_GNU_GETTEXT_VERSION([0.19.4])\nAM_GNU_GETTEXT([external])\n\n# Checks for libraries.\nAC_SEARCH_LIBS([strerror],[cposix])\nAC_SEARCH_LIBS([getpwnam], [sun])\n\nAC_HEADER_DIRENT\nAC_HEADER_STAT\n\nAC_CHECK_HEADERS([stdlib.h string.h strings.h locale.h unistd.h limits.h \\\n                  memory.h sys/param.h sys/resource.h sys/time.h sys/select.h \\\n                  sys/file.h fcntl.h spawn.h])\n\nAM_PROG_CC_C_O\nAC_C_CONST\nAC_TYPE_UID_T\nAC_TYPE_PID_T\nAC_TYPE_OFF_T\nAC_TYPE_SIZE_T\nAC_TYPE_SSIZE_T\nAC_TYPE_INTMAX_T\nAC_TYPE_UINTMAX_T\n\n# Check for sig_atomic_t\ngt_TYPE_SIG_ATOMIC_T\n\n# Find out whether our struct stat returns nanosecond resolution timestamps.\n\nAC_STRUCT_ST_MTIM_NSEC\nAC_CACHE_CHECK([whether to use high resolution file timestamps],\n               [make_cv_file_timestamp_hi_res],\n[ make_cv_file_timestamp_hi_res=no\n  AS_IF([test \"$ac_cv_struct_st_mtim_nsec\" != no],\n        [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n#if HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif]],\n                      [[char a[0x7fffffff < (uintmax_t)-1 >> 30 ? 1 : -1];]])],\n        [make_cv_file_timestamp_hi_res=yes])\n  ])])\nAS_IF([test \"$make_cv_file_timestamp_hi_res\" = yes], [val=1], [val=0])\nAC_DEFINE_UNQUOTED([FILE_TIMESTAMP_HI_RES], [$val],\n                   [Use high resolution file timestamps if nonzero.])\n\nAS_IF([test \"$make_cv_file_timestamp_hi_res\" = yes],\n[ # Solaris 2.5.1 needs -lposix4 to get the clock_gettime function.\n  # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.\n  AC_SEARCH_LIBS([clock_gettime], [rt posix4])\n  AS_IF([test \"$ac_cv_search_clock_gettime\" != no],\n  [ AC_DEFINE([HAVE_CLOCK_GETTIME], [1],\n              [Define to 1 if you have the clock_gettime function.])\n  ])\n])\n\n# See if we have a standard version of gettimeofday().  Since actual\n# implementations can differ, just make sure we have the most common\n# one.\nAC_CACHE_CHECK([for standard gettimeofday], [ac_cv_func_gettimeofday],\n  [ac_cv_func_gettimeofday=no\n   AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <sys/time.h>\n                  int main ()\n                  {\n                    struct timeval t; t.tv_sec = -1; t.tv_usec = -1;\n                    return gettimeofday (&t, 0) != 0\n                          || t.tv_sec < 0 || t.tv_usec < 0;\n                  }]])],\n                  [ac_cv_func_gettimeofday=yes],\n                  [ac_cv_func_gettimeofday=no],\n                  [ac_cv_func_gettimeofday=\"no (cross-compiling)\"])])\nAS_IF([test \"$ac_cv_func_gettimeofday\" = yes],\n[ AC_DEFINE([HAVE_GETTIMEOFDAY], [1],\n            [Define to 1 if you have a standard gettimeofday function])\n])\n\nAC_CHECK_FUNCS([strtoll strdup strndup stpcpy memrchr mempcpy umask mkstemp \\\n                mktemp fdopen dup dup2 getcwd realpath sigsetmask sigaction \\\n                getgroups seteuid setegid setlinebuf setreuid setregid \\\n                mkfifo getrlimit setrlimit setvbuf pipe strerror strsignal \\\n                lstat readlink atexit isatty ttyname pselect posix_spawn \\\n                posix_spawnattr_setsigmask])\n\n# We need to check declarations, not just existence, because on Tru64 this\n# function is not declared without special flags, which themselves cause\n# other problems.  We'll just use our own.\nAC_CHECK_DECLS([bsd_signal], [], [], [[#define _GNU_SOURCE 1\n#include <signal.h>]])\n\nAC_FUNC_FORK\n\n# Rumor has it that strcasecmp lives in -lresolv on some odd systems.\n# It doesn't hurt much to use our own if we can't find it so I don't\n# make the effort here.\nAC_CHECK_FUNCS([strcasecmp strncasecmp strcmpi strncmpi stricmp strnicmp])\n\n# strcoll() is used by the GNU glob library\nAC_FUNC_STRCOLL\nAC_FUNC_CLOSEDIR_VOID\n\n# dir.c and our glob.c use dirent.d_type if available\nAC_STRUCT_DIRENT_D_TYPE\n\n# See if the user wants to add (or not) GNU Guile support\nAC_ARG_WITH([guile], [AS_HELP_STRING([--with-guile],\n            [Support GNU Guile for embedded scripting])])\n\n# Annoyingly, each version of Guile comes with it's own PC file so we have to\n# specify them as individual packages.  Ugh.\nPKG_PROG_PKG_CONFIG\n\nAS_IF([test \"x$with_guile\" != xno],\n[ guile_versions=\"3.0 2.2 2.0 1.8\"\n  guile_version=no\n  have_guile=no\n  AC_MSG_CHECKING([for GNU Guile])\n  for v in $guile_versions; do\n    PKG_CHECK_EXISTS([guile-$v], [guile_version=$v; have_guile=yes; break], [])\n  done\n  AC_MSG_RESULT([$guile_version])\n  AS_IF([test \"$have_guile\" = yes],\n  [ PKG_CHECK_MODULES(GUILE, [guile-$guile_version])\n    # Unfortunately pkg doesn't help in multi-arch environments where the\n    # package is installed for some architectures but not others; we need\n    # to try to link.\n    keep_CPPFLAGS=\"$CPPFLAGS\"\n    keep_LIBS=\"$LIBS\"\n    CPPFLAGS=\"$CPPFLAGS $GUILE_CFLAGS\"\n    LIBS=\"$LIBS $GUILE_LIBS\"\n    AC_CHECK_HEADER([libguile.h],\n                    [have_guile=yes],\n                    [have_guile=no],\n                    [/* Avoid configuration error warnings. */])\n    AS_IF([test \"$have_guile\" = yes],\n    [ AC_MSG_CHECKING([whether we can link GNU Guile])\n      AC_LINK_IFELSE([AC_LANG_PROGRAM([[\n#include <libguile.h>\nstatic void *\nguile_init (void *arg)\n{\n   (void) arg;\n   return 0;\n}\n]], [[\n    scm_with_guile (guile_init, 0);\n]])],\n        [have_guile=yes],\n        [have_guile=no])\n      AC_MSG_RESULT([$have_guile])])\n    CPPFLAGS=\"$keep_CPPFLAGS\"\n    LIBS=\"$keep_LIBS\"\n  ])\n])\n\nAS_IF([test \"$have_guile\" = yes],\n      [AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])])\nAM_CONDITIONAL([HAVE_GUILE], [test \"$have_guile\" = \"yes\"])\n\nAC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , ,\n  [AC_INCLUDES_DEFAULT\n#include <signal.h>\n/* NetBSD declares sys_siglist in unistd.h.  */\n#if HAVE_UNISTD_H\n# include <unistd.h>\n#endif\n])\n\n\n# Check out the wait reality.\nAC_CHECK_HEADERS([sys/wait.h],[],[],[[#include <sys/types.h>]])\nAC_CHECK_FUNCS([waitpid wait3])\nAC_CACHE_CHECK([for union wait], [make_cv_union_wait],\n[ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>\n#include <sys/wait.h>]],\n     [[union wait status; int pid; pid = wait (&status);\n#ifdef WEXITSTATUS\n/* Some POSIXoid systems have both the new-style macros and the old\n   union wait type, and they do not work together.  If union wait\n   conflicts with WEXITSTATUS et al, we don't want to use it at all.  */\n        if (WEXITSTATUS (status) != 0) pid = -1;\n#ifdef WTERMSIG\n        /* If we have WEXITSTATUS and WTERMSIG, just use them on ints.  */\n        -- blow chunks here --\n#endif\n#endif\n#ifdef HAVE_WAITPID\n        /* Make sure union wait works with waitpid.  */\n        pid = waitpid (-1, &status, 0);\n#endif\n      ]])],\n    [make_cv_union_wait=yes],\n    [make_cv_union_wait=no])\n])\nAS_IF([test \"$make_cv_union_wait\" = yes],\n[ AC_DEFINE([HAVE_UNION_WAIT], [1],\n            [Define to 1 if you have the 'union wait' type in <sys/wait.h>.])\n])\n\n\n# If we're building on Windows/DOS/OS/2, add some support for DOS drive specs.\nAS_IF([test \"$PATH_SEPARATOR\" = ';'],\n[ AC_DEFINE([HAVE_DOS_PATHS], [1],\n            [Define to 1 if your system requires backslashes or drive specs in pathnames.])\n])\n\n# See if the user wants to use pmake's \"customs\" distributed build capability\nAC_SUBST([REMOTE]) REMOTE=stub\nuse_customs=false\nAC_ARG_WITH([customs],\n[AS_HELP_STRING([--with-customs=DIR],[enable remote jobs via Customs--see README.customs])],\n[ AS_CASE([$withval], [n|no], [:],\n    [make_cppflags=\"$CPPFLAGS\"\n     AS_CASE([$withval],\n             [y|ye|yes], [:],\n             [CPPFLAGS=\"$CPPFLAGS -I$with_customs/include/customs\"\n              make_ldflags=\"$LDFLAGS -L$with_customs/lib\"])\n     CF_NETLIBS\n     AC_CHECK_HEADER([customs.h],\n                     [use_customs=true\n                      REMOTE=cstms\n                      LIBS=\"$LIBS -lcustoms\" LDFLAGS=\"$make_ldflags\"],\n                     [with_customs=no\n                      CPPFLAGS=\"$make_cppflags\" make_badcust=yes])\n    ])\n])\n\n# Tell automake about this, so it can include the right .c files.\nAM_CONDITIONAL([USE_CUSTOMS], [test \"$use_customs\" = true])\n\n# See if the user asked to handle case insensitive file systems.\nAH_TEMPLATE([HAVE_CASE_INSENSITIVE_FS], [Use case insensitive file names])\nAC_ARG_ENABLE([case-insensitive-file-system],\n  AS_HELP_STRING([--enable-case-insensitive-file-system],[assume file systems are case insensitive]),\n  [AS_IF([test \"$enableval\" = yes], [AC_DEFINE([HAVE_CASE_INSENSITIVE_FS])])])\n\n# See if we can handle the job server feature, and if the user wants it.\nAC_ARG_ENABLE([job-server],\n  AS_HELP_STRING([--disable-job-server],[disallow recursive make communication during -jN]),\n  [make_cv_job_server=\"$enableval\" user_job_server=\"$enableval\"],\n  [make_cv_job_server=\"yes\"])\n\nAS_IF([test \"$ac_cv_func_waitpid\" = no && test \"$ac_cv_func_wait3\" = no],\n      [has_wait_nohang=no],\n      [has_wait_nohang=yes])\n\nAC_CACHE_CHECK([for SA_RESTART], [make_cv_sa_restart], [\n  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]],\n      [[return SA_RESTART;]])],\n    [make_cv_sa_restart=yes],\n    [make_cv_sa_restart=no])])\n\nAS_IF([test \"$make_cv_sa_restart\" != no],\n[ AC_DEFINE([HAVE_SA_RESTART], [1],\n     [Define to 1 if <signal.h> defines the SA_RESTART constant.])\n])\n\n# Only allow jobserver on systems that support it\nAS_CASE([/$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/],\n  [*/no/*], [make_cv_job_server=no])\n\n# Also supported on OS2 and MinGW\nAS_CASE([$host_os], [os2*|mingw*], [make_cv_job_server=yes])\n\n# If we support it and the user didn't disable it, build with jobserver\nAS_CASE([/$make_cv_job_server/$user_job_server/],\n  [*/no/*], [: no jobserver],\n  [AC_DEFINE(MAKE_JOBSERVER, 1,\n             [Define to 1 to enable job server support in GNU Make.])\n  ])\n\n# If dl*() functions are supported we can enable the load operation\nAC_CHECK_DECLS([dlopen, dlsym, dlerror], [], [],\n  [[#include <dlfcn.h>]])\n\nAC_ARG_ENABLE([load],\n  AS_HELP_STRING([--disable-load],[disable support for the 'load' operation]),\n  [make_cv_load=\"$enableval\" user_load=\"$enableval\"],\n  [make_cv_load=\"yes\"])\n\nAS_CASE([/$ac_cv_have_decl_dlopen/$ac_cv_have_decl_dlsym/$ac_cv_have_decl_dlerror/],\n  [*/no/*], [make_cv_load=no])\n\n# We might need -ldl\nAS_IF([test \"$make_cv_load\" = yes], [\n  AC_SEARCH_LIBS([dlopen], [dl], [], [make_cv_load=])\n  ])\n\nAS_CASE([/$make_cv_load/$user_load/],\n  [*/no/*], [make_cv_load=no],\n  [AC_DEFINE(MAKE_LOAD, 1,\n             [Define to 1 to enable 'load' support in GNU Make.])\n  ])\n\n# If we want load support, we might need to link with export-dynamic.\n# See if we can figure it out.  Unfortunately this is very difficult.\n# For example passing -rdynamic to the SunPRO linker gives a warning\n# but succeeds and creates a shared object, not an executable!\nAS_IF([test \"$make_cv_load\" = yes], [\n  AC_MSG_CHECKING([if the linker accepts -Wl,--export-dynamic])\n  old_LDFLAGS=\"$LDFLAGS\"\n  LDFLAGS=\"$LDFLAGS -Wl,--export-dynamic\"\n  AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],\n    [AC_MSG_RESULT([yes])\n     AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])],\n    [AC_MSG_RESULT([no])\n     AC_MSG_CHECKING([if the linker accepts -rdynamic])\n     LDFLAGS=\"$old_LDFLAGS -rdynamic\"\n     AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])],\n       [AC_MSG_RESULT([yes])\n        AC_SUBST([AM_LDFLAGS], [-rdynamic])],\n       [AC_MSG_RESULT([no])])\n   ])\n  LDFLAGS=\"$old_LDFLAGS\"\n])\n\n# if we have both lstat() and readlink() then we can support symlink\n# timechecks.\nAS_IF([test \"$ac_cv_func_lstat\" = yes && test \"$ac_cv_func_readlink\" = yes],\n  [ AC_DEFINE([MAKE_SYMLINKS], [1],\n              [Define to 1 to enable symbolic link timestamp checking.])\n])\n\n# Use posix_spawn if we have support and the user didn't disable it\n\nAC_ARG_ENABLE([posix-spawn],\n  AS_HELP_STRING([--disable-posix-spawn],[disable support for posix_spawn()]),\n  [make_cv_posix_spawn=\"$enableval\" user_posix_spawn=\"$enableval\"],\n  [make_cv_posix_spawn=\"yes\"])\n\nAS_CASE([/$ac_cv_header_spawn/$ac_cv_func_posix_spawn/],\n  [*/no/*], [make_cv_posix_spawn=no])\n\nAS_IF([test \"$make_cv_posix_spawn\" = yes],\n  AC_CACHE_CHECK([for posix_spawn that fails synchronously],\n    [make_cv_synchronous_posix_spawn],\n    [make_cv_synchronous_posix_spawn=no\n     AC_RUN_IFELSE([AC_LANG_SOURCE([[\n       #include <errno.h>\n       #include <spawn.h>\n       extern char **environ;\n       int main () {\n         char path[[]] = \"./xxx-non-existent\";\n         char *argv[[]] = {path, 0};\n         return posix_spawn (0, path, 0, 0, argv, environ) == ENOENT ? 0 : 1;\n       }]])],\n       [make_cv_synchronous_posix_spawn=yes],\n       [make_cv_synchronous_posix_spawn=no],\n       [make_cv_synchronous_posix_spawn=\"no (cross-compiling)\"])]))\n\nAS_CASE([/$user_posix_spawn/$make_cv_posix_spawn/$make_cv_synchronous_posix_spawn/],\n  [*/no/*], [make_cv_posix_spawn=no],\n  [AC_DEFINE(USE_POSIX_SPAWN, 1, [Define to 1 to use posix_spawn().])\n  ])\n\n# Find the SCCS commands, so we can include them in our default rules.\n\nAC_CACHE_CHECK([for location of SCCS get command], [make_cv_path_sccs_get], [\n  AS_IF([test -f /usr/sccs/get],\n        [make_cv_path_sccs_get=/usr/sccs/get],\n        [make_cv_path_sccs_get=get])\n])\nAC_DEFINE_UNQUOTED([SCCS_GET], [\"$make_cv_path_sccs_get\"],\n                   [Define to the name of the SCCS 'get' command.])\n\nac_clean_files=\"$ac_clean_files s.conftest conftoast\" # Remove these later.\nAS_IF([(/usr/sccs/admin -n s.conftest || admin -n s.conftest) >/dev/null 2>&1 &&\n   test -f s.conftest],\n[ # We successfully created an SCCS file.\n  AC_CACHE_CHECK([if SCCS get command understands -G], [make_cv_sys_get_minus_G],\n    [AS_IF([$make_cv_path_sccs_get -Gconftoast s.conftest >/dev/null 2>&1 &&\n            test -f conftoast],\n           [make_cv_sys_get_minus_G=yes],\n           [make_cv_sys_get_minus_G=no])\n    ])\n  AS_IF([test \"$make_cv_sys_get_minus_G\" = yes],\n    [AC_DEFINE([SCCS_GET_MINUS_G], [1],\n     [Define to 1 if the SCCS 'get' command understands the '-G<file>' option.])\n    ])\n])\nrm -f s.conftest conftoast\n\n# Let the makefile know what our build host is\n\nAC_DEFINE_UNQUOTED([MAKE_HOST],[\"$host\"],[Build host information.])\nMAKE_HOST=\"$host\"\nAC_SUBST([MAKE_HOST])\n\nw32_target_env=no\nAM_CONDITIONAL([WINDOWSENV], [false])\nAM_CONDITIONAL([HAVE_WINDRES], [false])\n\nAS_CASE([$host],\n  [*-*-mingw32],\n   [AM_CONDITIONAL([WINDOWSENV], [true])\n    w32_target_env=yes\n    AC_DEFINE([MK_OS_W32], [1], [Build for the Windows32 API.])\n    AC_DEFINE([HAVE_DOS_PATHS], [1], [Support DOS-style pathnames.])\n    # Windows host tools.\n    # If windres is available, make will use UTF-8.\n    AC_CHECK_TOOL([WINDRES], [windres], [:])\n    AM_CONDITIONAL([HAVE_WINDRES], [test \"$WINDRES\" != ':'])\n  ])\n\nAC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'],\n        [Define to the character that separates directories in PATH.])\n\nAC_DEFINE_UNQUOTED([HAVE_DECL_GETLOADAVG],[$HAVE_DECL_GETLOADAVG],\n        [Define to 1 if you have the declaration of 'getloadavg'.])\n\n# Remember that we ran configure to generate config.h\n\nAC_DEFINE([MK_CONFIGURE], [1],\n          [Define to 1 if config.h is generated by running the configure script.])\n\n# Include the Maintainer's Makefile section, if it's here.\n\nMAINT_MAKEFILE=/dev/null\nAS_IF([test -r \"$srcdir/maintMakefile\"],\n[ MAINT_MAKEFILE=\"$srcdir/maintMakefile\"\n])\nAC_SUBST_FILE([MAINT_MAKEFILE])\n\n# Allow building with dmalloc\nAM_WITH_DMALLOC\n\n# Add custom header to config.h\nAH_BOTTOM([/* Include customized declarations.  */\n#include \"../src/mkcustom.h\"])\n\n# Forcibly disable SET_MAKE.  If it's set it breaks things like the test\n# scripts, etc.\nSET_MAKE=\n\n# Sanity check and inform the user of what we found\n\nAS_IF([test \"x$make_badcust\" = xyes], [\necho\necho \"WARNING: --with-customs specified but no customs.h could be found;\"\necho \"         disabling Customs support.\"\necho\n])\n\nAS_CASE([$with_customs],\n[\"\"|n|no|y|ye|yes], [:],\n[AS_IF([test -f \"$with_customs/lib/libcustoms.a\"], [:],\n[ echo\n  echo \"WARNING: '$with_customs/lib' does not appear to contain the\"\n  echo \"         Customs library.  You must build and install Customs\"\n  echo \"         before compiling GNU Make.\"\n  echo\n])])\n\nAS_IF([test \"x$has_wait_nohang\" = xno],\n[ echo\n  echo \"WARNING: Your system has neither waitpid() nor wait3().\"\n  echo \"         Without one of these, signal handling is unreliable.\"\n  echo \"         You should be aware that running GNU Make with -j\"\n  echo \"         could result in erratic behavior.\"\n  echo\n])\n\nAS_IF([test \"x$make_cv_job_server\" = xno && test \"x$user_job_server\" = xyes],\n[ echo\n  echo \"WARNING: Make job server requires a POSIX-ish system that\"\n  echo \"         supports the pipe(), sigaction(), and either\"\n  echo \"         waitpid() or wait3() functions.  Your system doesn't\"\n  echo \"         appear to provide one or more of those.\"\n  echo \"         Disabling job server support.\"\n  echo\n])\n\nAS_IF([test \"x$make_cv_load\" = xno && test \"x$user_load\" = xyes],\n[ echo\n  echo \"WARNING: 'load' support requires a POSIX-ish system that\"\n  echo \"         supports the dlopen(), dlsym(), and dlerror() functions.\"\n  echo \"         Your system doesn't appear to provide one or more of these.\"\n  echo \"         Disabling 'load' support.\"\n  echo\n])\n\nAS_IF([test \"x$make_cv_posix_spawn\" = xno && test \"x$user_posix_spawn\" = xyes],\n[ echo\n  echo \"WARNING: posix_spawn() is not supported on this system.\"\n  echo\n])\n\n# autoconf initializes $prefix to NONE.\nAM_CONDITIONAL([KNOWN_PREFIX],\n               [test \"x$prefix\" = xNONE -o \"x$prefix\" = x/usr/local \\\n                     -o \"x$prefix\" = x/usr/gnu -o \"x$prefix\" = x/usr])\n\n# Specify what files are to be created.\nAC_CONFIG_FILES([build.cfg tests/config-flags.pm \\\n                 Makefile lib/Makefile doc/Makefile po/Makefile.in])\n# We don't need this: the standard automake output suffices for POSIX systems.\n#mk/Posix.mk\n\n# Put build.sh in the build directory so it's easy to find\nAC_CONFIG_LINKS([build.sh:build.sh])\n\n# OK, do it!\n\nAC_OUTPUT\n\ndnl Local Variables:\ndnl comment-start: \"dnl \"\ndnl comment-end: \"\"\ndnl comment-start-skip: \"\\\\bdnl\\\\b\\\\s *\"\ndnl compile-command: \"make configure config.h.in\"\ndnl End:\n"
  },
  {
    "path": "doc/.gitignore",
    "content": "manual/\nmake.t2d/\nmake.t2p/\ngendocs_template\nfdl.texi\nmake-stds.texi\nstamp-vti\nversion.texi\nmake.info*\nmake*.html\nmake.aux\nmake.cp\nmake.cps\nmake.dvi\nmake.fn\nmake.fns\nmake.ky\nmake.log\nmake.pdf\nmake.pg\nmake.ps\nmake.toc\nmake.tp\nmake.vr\n"
  },
  {
    "path": "doc/Makefile.am",
    "content": "# -*-Makefile-*-, or close enough\n# Copyright (C) 2000-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nTEXI2HTML = texi2html\nTEXI2HTML_FLAGS = -split_chapter\n\ninfo_TEXINFOS =\tmake.texi\nmake_TEXINFOS = fdl.texi make-stds.texi\n\nCLEANFILES = make*.html\n"
  },
  {
    "path": "doc/make.1",
    "content": ".TH MAKE 1 \"26 May 2023\" \"GNU\" \"User Commands\"\n.SH NAME\nmake \\- GNU Make utility to maintain groups of programs\n.SH SYNOPSIS\n.B make\n[\\fIOPTION\\fR]... [\\fITARGET\\fR]...\n.SH DESCRIPTION\n.LP\nThe\n.I make\nutility will determine automatically which pieces of a large program need to\nbe recompiled, and issue the commands to recompile them.  The manual describes\nthe GNU implementation of\n.BR make ,\nwhich was written by Richard Stallman and Roland McGrath, and is currently\nmaintained by Paul Smith.  Our examples show C programs, since they are very\ncommon, but you can use\n.B make\nwith any programming language whose compiler can be run with a shell command.\nIn fact,\n.B make\nis not limited to programs.  You can use it to describe any task where some\nfiles must be updated automatically from others whenever the others change.\n.LP\nTo prepare to use\n.BR make ,\nyou must write a file called the\n.I makefile\nthat describes the relationships among files in your program, and provides\ncommands for updating each file.  In a program, typically the executable file\nis updated from object files, which are in turn made by compiling source\nfiles.\n.LP\nOnce a suitable makefile exists, each time you change some source files,\nthis simple shell command:\n.sp 1\n.RS\n.B make\n.RE\n.sp 1\nsuffices to perform all necessary recompilations.\nThe\n.B make\nprogram uses the makefile description and the last-modification times of the\nfiles to decide which of the files need to be updated.  For each of those\nfiles, it issues the commands recorded in the makefile.\n.LP\n.B make\nexecutes commands in the\n.I makefile\nto update one or more\n.IR targets ,\nwhere\n.I target\nis typically a program.\nIf no\n.B \\-f\noption is present,\n.B make\nwill look for the makefiles\n.IR GNUmakefile ,\n.IR makefile ,\nand\n.IR Makefile ,\nin that order.\n.LP\nNormally you should call your makefile either\n.I makefile\nor\n.IR Makefile .\n(We recommend\n.I Makefile\nbecause it appears prominently near the beginning of a directory\nlisting, right near other important files such as\n.IR  README .)\nThe first name checked,\n.IR GNUmakefile ,\nis not recommended for most makefiles.  You should use this name if you have a\nmakefile that is specific to GNU Make, and will not be understood by other\nversions of\n.BR make .\nIf\n.I makefile\nis '\\-', the standard input is read.\n.LP\n.B make\nupdates a target if it depends on prerequisite files\nthat have been modified since the target was last modified,\nor if the target does not exist.\n.SH OPTIONS\n.sp 1\n.TP 0.5i\n\\fB\\-b\\fR, \\fB\\-m\\fR\nThese options are ignored for compatibility with other versions of\n.BR make .\n.TP 0.5i\n\\fB\\-B\\fR, \\fB\\-\\-always\\-make\\fR\nUnconditionally make all targets.\n.TP 0.5i\n\\fB\\-C\\fR \\fIdir\\fR, \\fB\\-\\-directory\\fR=\\fIdir\\fR\nChange to directory\n.I dir\nbefore reading the makefiles or doing anything else.\nIf multiple\n.B \\-C\noptions are specified, each is interpreted relative to the\nprevious one:\n.BR \"\\-C \" /\n.BR \"\\-C \" etc\nis equivalent to\n.BR \"\\-C \" /etc.\nThis is typically used with recursive invocations of\n.BR make .\n.TP 0.5i\n.B \\-d\nPrint debugging information in addition to normal processing.\nThe debugging information says which files are being considered for\nremaking, which file-times are being compared and with what results,\nwhich files actually need to be remade, which implicit rules are\nconsidered and which are applied---everything interesting about how\n.B make\ndecides what to do.\n.TP 0.5i\n.BI \\-\\-debug \"[=FLAGS]\"\nPrint debugging information in addition to normal processing.\nIf the\n.I FLAGS\nare omitted, then the behavior is the same as if\n.B \\-d\nwas specified.\n.I FLAGS\nmay be any or all of the following names, comma- or space-separated.  Only the\nfirst character is significant: the rest may be omitted:\n.I all\nfor all debugging output (same as using\n.BR \\-d ),\n.I basic\nfor basic debugging,\n.I verbose\nfor more verbose basic debugging,\n.I implicit\nfor showing implicit rule search operations,\n.I jobs\nfor details on invocation of commands,\n.I makefile\nfor debugging while remaking makefiles,\n.I print\nshows all recipes that are run even if they are silent, and\n.I why\nshows the reason\n.BR make\ndecided to rebuild each target.  Use\n.I none\nto disable all previous debugging flags.\n.TP 0.5i\n\\fB\\-e\\fR, \\fB\\-\\-environment\\-overrides\\fR\nGive variables taken from the environment precedence over variables\nfrom makefiles.\n.TP 0.5i\n\\fB\\-E\\fR \\fIstring\\fR, \\fB\\-\\-eval\\fR \\fIstring\\fR\nInterpret \\fIstring\\fR using the \\fBeval\\fR function, before parsing any\nmakefiles.\n.TP 0.5i\n\\fB\\-f\\fR \\fIfile\\fR, \\fB\\-\\-file\\fR=\\fIfile\\fR, \\fB\\-\\-makefile\\fR=\\fIFILE\\fR\nUse\n.I file\nas a makefile.\n.TP 0.5i\n\\fB\\-i\\fR, \\fB\\-\\-ignore\\-errors\\fR\nIgnore all errors in commands executed to remake files.\n.TP 0.5i\n\\fB\\-I\\fR \\fIdir\\fR, \\fB\\-\\-include\\-dir\\fR=\\fIdir\\fR\nSpecifies a directory\n.I dir\nto search for included makefiles.\nIf several\n.B \\-I\noptions are used to specify several directories, the directories are\nsearched in the order specified.\nUnlike the arguments to other flags of\n.BR make ,\ndirectories given with\n.B \\-I\nflags may come directly after the flag:\n.BI \\-I dir\nis allowed, as well as\n.B \\-I\n.IR dir .\nThis syntax is allowed for compatibility with the C\npreprocessor's\n.B \\-I\nflag.\n.TP 0.5i\n\\fB\\-j\\fR [\\fIjobs\\fR], \\fB\\-\\-jobs\\fR[=\\fIjobs\\fR]\nSpecifies the number of\n.I jobs\n(commands) to run simultaneously.\nIf there is more than one\n.B \\-j\noption, the last one is effective.\nIf the\n.B \\-j\noption is given without an argument,\n.BR make\nwill not limit the number of jobs that can run simultaneously.\n.TP 0.5i\n\\fB\\--jobserver-style=\\fR\\fIstyle\\fR\nThe style of jobserver to use.  The\n.I style\nmay be one of\n.BR fifo ,\n.BR pipe ,\nor\n.B sem\n(Windows only).\n.TP 0.5i\n\\fB\\-k\\fR, \\fB\\-\\-keep\\-going\\fR\nContinue as much as possible after an error.\nWhile the target that failed, and those that depend on it, cannot\nbe remade, the other dependencies of these targets can be processed\nall the same.\n.TP 0.5i\n\\fB\\-l\\fR [\\fIload\\fR], \\fB\\-\\-load\\-average\\fR[=\\fIload\\fR]\nSpecifies that no new jobs (commands) should be started if there are\nothers jobs running and the load average is at least\n.I load\n(a floating-point number).\nWith no argument, removes a previous load limit.\n.TP 0.5i\n\\fB\\-L\\fR, \\fB\\-\\-check\\-symlink\\-times\\fR\nUse the latest mtime between symlinks and target.\n.TP 0.5i\n\\fB\\-n\\fR, \\fB\\-\\-just\\-print\\fR, \\fB\\-\\-dry\\-run\\fR, \\fB\\-\\-recon\\fR\nPrint the commands that would be executed, but do not execute them (except in\ncertain circumstances).\n.TP 0.5i\n\\fB\\-o\\fR \\fIfile\\fR, \\fB\\-\\-old\\-file\\fR=\\fIfile\\fR, \\fB\\-\\-assume\\-old\\fR=\\fIfile\\fR\nDo not remake the file\n.I file\neven if it is older than its dependencies, and do not remake anything\non account of changes in\n.IR file .\nEssentially the file is treated as very old and its rules are ignored.\n.TP 0.5i\n\\fB\\-O\\fR[\\fItype\\fR], \\fB\\-\\-output\\-sync\\fR[=\\fItype\\fR]\nWhen running multiple jobs in parallel with \\fB-j\\fR, ensure the output of\neach job is collected together rather than interspersed with output from\nother jobs.  If\n.I type\nis not specified or is\n.B target\nthe output from the entire recipe for each target is grouped together.  If\n.I type\nis\n.B line\nthe output from each command line within a recipe is grouped together.\nIf\n.I type\nis\n.B recurse\noutput from an entire recursive make is grouped together.  If\n.I type\nis\n.B none\noutput synchronization is disabled.\n.TP 0.5i\n\\fB\\-p\\fR, \\fB\\-\\-print\\-data\\-base\\fR\nPrint the data base (rules and variable values) that results from\nreading the makefiles; then execute as usual or as otherwise\nspecified.\nThis also prints the version information given by the\n.B \\-v\nswitch (see below).  To print the built-in data base only, use\n.IR \"make \\-p \\-f/dev/null\" .\n.TP 0.5i\n\\fB\\-\\-print\\-targets\\fR\nPrint each target defined as a result of reading the makefiles, one target per\nline, then exit with success.  Implicit rule targets are not printed, nor are\nspecial targets (target names that consist of \".\" followed by all upper-case\nletters).  No recipe commands are invoked and no makefiles are rebuilt.\n.TP 0.5i\n\\fB\\-q\\fR, \\fB\\-\\-question\\fR\n``Question mode''.\nDo not run any commands, or print anything; just return an exit status\nthat is zero if the specified targets are already up to date, nonzero\notherwise.\n.TP 0.5i\n\\fB\\-r\\fR, \\fB\\-\\-no\\-builtin\\-rules\\fR\nEliminate use of the built\\-in implicit rules.\nAlso clear out the default list of suffixes for suffix rules.\n.TP 0.5i\n\\fB\\-R\\fR, \\fB\\-\\-no\\-builtin\\-variables\\fR\nDon't define any built\\-in variables.\n.TP 0.5i\n\\fB\\-s\\fR, \\fB\\-\\-silent\\fR, \\fB\\-\\-quiet\\fR\nSilent operation; do not print the commands as they are executed.\n.TP 0.5i\n.B \\-\\-no\\-silent\nCancel the effect of the \\fB\\-s\\fR option.\n.TP 0.5i\n\\fB\\-S\\fR, \\fB\\-\\-no\\-keep\\-going\\fR, \\fB\\-\\-stop\\fR\nCancel the effect of the\n.B \\-k\noption.\n.TP 0.5i\n\\fB\\-t\\fR, \\fB\\-\\-touch\\fR\nTouch files (mark them up to date without really changing them)\ninstead of running their commands.\nThis is used to pretend that the commands were done, in order to fool\nfuture invocations of\n.BR make .\n.TP 0.5i\n.B \\-\\-trace\nInformation about the disposition of each target is printed (why the target is\nbeing rebuilt and what commands are run to rebuild it).\n.TP 0.5i\n\\fB\\-v\\fR, \\fB\\-\\-version\\fR\nPrint the version of the\n.B make\nprogram plus a copyright, a list of authors and a notice that there\nis no warranty.\n.TP 0.5i\n\\fB\\-w\\fR, \\fB\\-\\-print\\-directory\\fR\nPrint a message containing the working directory\nbefore and after other processing.\nThis may be useful for tracking down errors from complicated nests of\nrecursive\n.B make\ncommands.\n.TP 0.5i\n.B \\-\\-no\\-print\\-directory\nTurn off\n.BR \\-w ,\neven if it was turned on implicitly.\n.TP 0.5i\n.BI \\-\\-shuffle \"[=MODE]\"\nEnable shuffling of goal and prerequisite ordering.\n.I MODE\nis one of\n.I none\nto disable shuffle mode,\n.I random\nto shuffle prerequisites in random order,\n.I reverse\nto consider prerequisites in reverse order, or an integer\n.I <seed>\nwhich enables\n.I random\nmode with a specific\n.I seed\nvalue.  If\n.I MODE\nis omitted the default is\n.IR random .\n.TP 0.5i\n\\fB\\-W\\fR \\fIfile\\fR, \\fB\\-\\-what\\-if\\fR=\\fIfile\\fR, \\fB\\-\\-new\\-file\\fR=\\fIfile\\fR, \\fB\\-\\-assume\\-new\\fR=\\fIfile\\fR\nPretend that the target\n.I file\nhas just been modified.\nWhen used with the\n.B \\-n\nflag, this shows you what would happen if you were to modify that file.\nWithout\n.BR \\-n ,\nit is almost the same as running a\n.I touch\ncommand on the given file before running\n.BR make ,\nexcept that the modification time is changed only in the imagination of\n.BR make .\n.TP 0.5i\n\\fB\\-\\-warn\\fR[=\\fIARG[\\fR,\\fIARG\\fR]]\nControl warning reporting for makefiles.  This option can appear multiple times.\nIn case of conflicts, later settings override earlier settings.\n.I ARG\ncan be an action; one of\n.IR ignore ,\n.IR warn ,\nor\n.I error\nto set the default action for all warnings, or it can be a specific warning:\n.I circular-dep\n(finding a circular dependency),\n.I invalid-ref\n(referencing an invalid variable name),\n.I invalid-var\n(assigning to an invalid variable name),\nor\n.I undefined-var\n(referencing an undefined variable).  The behavior of each warning can be set\nby adding\n.BI : action\nafter the warning name.  If an action is not specified the default is\n.IR warn .\nIf no\n.I ARG\nis provided the action for all warnings is\n.IR warn .\nIf no\n.B \\-\\-warn\noption is provided the default action for\n.I invalid-var\nand\n.I invalid-ref\nis\n.I warn\nand the default action for\n.I undefined-var\nis\n.IR ignore .\n.TP 0.5i\n.B \\-\\-warn\\-undefined\\-variables\nA deprecated alternative for\n.BR \\-\\-warn=undefined-var .\n.SH \"EXIT STATUS\"\nGNU Make exits with a status of zero if all makefiles were successfully parsed\nand no targets that were built failed.  A status of one will be returned\nif the\n.B \\-q\nflag was used and\n.B make\ndetermines that a target needs to be rebuilt.  A status of two will be\nreturned if any errors were encountered.\n.SH \"SEE ALSO\"\nThe full documentation for\n.B make\nis maintained as a Texinfo manual.  If the\n.B info\nand\n.B make\nprograms are properly installed at your site, the command\n.IP\n.B info make\n.PP\nshould give you access to the complete manual.\n.SH BUGS\nSee the chapter ``Problems and Bugs'' in\n.IR \"The GNU Make Manual\" .\n.SH AUTHOR\nThis manual page contributed by Dennis Morse of Stanford University.\nFurther updates contributed by Mike Frysinger.  It has been reworked by Roland\nMcGrath.  Maintained by Paul Smith.\n.SH \"COPYRIGHT\"\nCopyright \\(co 1992\\(en1993, 1996\\(en2024 Free Software Foundation, Inc.\nThis file is part of\n.IR \"GNU Make\" .\n.LP\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n.LP\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n.LP\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see\n.IR https://www.gnu.org/licenses/ .\n"
  },
  {
    "path": "doc/make.texi",
    "content": "\\input texinfo                @c -*- Texinfo -*-\n@c %**start of header\n@setfilename make.info\n\n@include version.texi\n@set EDITION 0.77\n\n@settitle GNU Make\n@setchapternewpage odd\n@c Combine the variable and function indices:\n@syncodeindex vr fn\n@c Combine the program and concept indices:\n@syncodeindex pg cp\n@c FSF publishers: format makebook.texi instead of using this file directly.\n@c ISBN confirmed by Jasimin Huang <jasimin@fsf.org> on 25 Mar 2009\n@set ISBN 1-882114-83-3\n@c %**end of header\n\n@copying\nThis file documents the GNU implementation of the @code{make} utility.\n@code{make} determines automatically which pieces of a large program need to\nbe recompiled, and issues the commands to recompile them.\n\nThis is Edition @value{EDITION}, last updated @value{UPDATED},\nof @cite{The GNU Make Manual}, for GNU @code{make} version @value{VERSION}.\n\nCopyright @copyright{} 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,\n1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007,\n2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,\n2020, 2021, 2022, 2023, 2024 Free Software Foundation, Inc.\n\n@quotation\nPermission is granted to copy, distribute and/or modify this document\nunder the terms of the GNU Free Documentation License, Version 1.3 or\nany later version published by the Free Software Foundation; with no\nInvariant Sections, with the Front-Cover Texts being ``A GNU Manual,''\nand with the Back-Cover Texts as in (a) below.  A copy of the\nlicense is included in the section entitled ``GNU Free Documentation\nLicense.''\n\n(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and\nmodify this GNU manual.  Buying copies from the FSF supports it in\ndeveloping GNU and promoting software freedom.''\n@end quotation\n@end copying\n\n@c finalout\n\n@c ISPELL CHECK: done, 10 June 1993 --roland\n@c ISPELL CHECK: done, 2000-06-25 --Martin Buchholz\n@c ISPELL CHECK: done, 2023-08-30 --pds\n\n@dircategory Software development\n@direntry\n* Make: (make).            Remake files automatically.\n@end direntry\n\n@iftex\n@shorttitlepage GNU Make\n@end iftex\n@titlepage\n@title GNU Make\n@subtitle A Program for Directing Recompilation\n@subtitle GNU @code{make} Version @value{VERSION}\n@subtitle @value{UPDATED-MONTH}\n@author Richard M. Stallman, Roland McGrath, Paul D. Smith\n@page\n@vskip 0pt plus 1filll\n@insertcopying\n@sp 2\nPublished by the Free Software Foundation @*\n51 Franklin St. -- Fifth Floor @*\nBoston, MA 02110-1301 USA @*\nISBN @value{ISBN} @*\n@sp 2\nCover art by Etienne Suvasa.\n@end titlepage\n\n@summarycontents\n@contents\n\n@ifnottex\n@node Top, Overview, (dir), (dir)\n@top GNU Make\n\n@insertcopying\n@end ifnottex\n\n@menu\n* Overview::                    Overview of @code{make}.\n* Introduction::                An introduction to @code{make}.\n* Makefiles::                   Makefiles tell @code{make} what to do.\n* Rules::                       Rules describe when a file must be remade.\n* Recipes::                     Recipes say how to remake a file.\n* Using Variables::             You can use variables to avoid repetition.\n* Conditionals::                Use or ignore parts of the makefile based\n                                  on the values of variables.\n* Functions::                   Many powerful ways to manipulate text.\n* Invoking make: Running.       How to invoke @code{make} on the command line.\n* Implicit Rules::              Use implicit rules to treat many files alike,\n                                  based on their file names.\n* Archives::                    How @code{make} can update library archives.\n* Extending make::              Using extensions to @code{make}.\n* Integrating make::            Integrating @code{make} with other tools.\n* Features::                    Features GNU Make has over other @code{make}s.\n* Missing::                     What GNU Make lacks from other @code{make}s.\n* Makefile Conventions::        Conventions for writing makefiles for\n                                  GNU programs.\n* Quick Reference::             A quick reference for experienced users.\n* Error Messages::              A list of common errors generated by @code{make}.\n* Troubleshooting::             Advice on finding problems.\n* Complex Makefile::            A real example of a straightforward,\n                                  but nontrivial, makefile.\n\n* GNU Free Documentation License::  License for copying this manual.\n* Concept Index::               Index of Concepts.\n* Name Index::                  Index of Functions, Variables, & Directives.\n\n@detailmenu\n --- The Detailed Node Listing ---\n\nOverview of @code{make}\n\n* Preparing::                   Preparing and running @code{make}.\n* Reading::                     On reading this text.\n* Bugs::                        Problems and bugs.\n\nAn Introduction to Makefiles\n\n* Rule Introduction::           What a rule looks like.\n* Simple Makefile::             A simple makefile.\n* How Make Works::              How @code{make} processes this makefile.\n* Variables Simplify::          Variables make makefiles simpler.\n* make Deduces::                Letting @code{make} deduce the recipes.\n* Combine By Prerequisite::     Another style of makefile.\n* Cleanup::                     Rules for cleaning the directory.\n\nWriting Makefiles\n\n* Makefile Contents::           What makefiles contain.\n* Makefile Names::              How to name your makefile.\n* Include::                     How one makefile can use another makefile.\n* MAKEFILES Variable::          The environment can specify extra makefiles.\n* Remaking Makefiles::          How makefiles get remade.\n* Overriding Makefiles::        How to override part of one makefile\n                                  with another makefile.\n* Reading Makefiles::           How makefiles are read in.\n* Parsing Makefiles::           How makefiles are parsed.\n* Secondary Expansion::         How and when secondary expansion is performed.\n\nWhat Makefiles Contain\n\n* Splitting Lines::             Splitting long lines in makefiles\n\nWriting Rules\n\n* Rule Example::                An example explained.\n* Rule Syntax::                 General syntax explained.\n* Prerequisite Types::          There are two types of prerequisites.\n* Wildcards::                   Using wildcard characters such as `*'.\n* Directory Search::            Searching other directories for source files.\n* Phony Targets::               Using a target that is not a real file's name.\n* Force Targets::               You can use a target without a recipe\n                                  or prerequisites to mark other targets\n                                  as phony.\n* Empty Targets::               When only the date matters and the\n                                  files are empty.\n* Special Targets::             Targets with special built-in meanings.\n* Multiple Targets::            When to make use of several targets in a rule.\n* Multiple Rules::              How to use several rules with the same target.\n* Static Pattern::              Static pattern rules apply to multiple targets\n                                  and can vary the prerequisites according to\n                                  the target name.\n* Double-Colon::                How to use a special kind of rule to allow\n                                  several independent rules for one target.\n* Automatic Prerequisites::     How to automatically generate rules giving\n                                  prerequisites from source files themselves.\n\nUsing Wildcard Characters in File Names\n\n* Wildcard Examples::           Several examples.\n* Wildcard Pitfall::            Problems to avoid.\n* Wildcard Function::           How to cause wildcard expansion where\n                                  it does not normally take place.\n\nSearching Directories for Prerequisites\n\n* General Search::              Specifying a search path that applies\n                                  to every prerequisite.\n* Selective Search::            Specifying a search path\n                                  for a specified class of names.\n* Search Algorithm::            When and how search paths are applied.\n* Recipes/Search::              How to write recipes that work together\n                                  with search paths.\n* Implicit/Search::             How search paths affect implicit rules.\n* Libraries/Search::            Directory search for link libraries.\n\nStatic Pattern Rules\n\n* Static Usage::                The syntax of static pattern rules.\n* Static versus Implicit::      When are they better than implicit rules?\n\nWriting Recipes in Rules\n\n* Recipe Syntax::               Recipe syntax features and pitfalls.\n* Echoing::                     How to control when recipes are echoed.\n* Execution::                   How recipes are executed.\n* Parallel::                    How recipes can be executed in parallel.\n* Errors::                      What happens after a recipe execution error.\n* Interrupts::                  What happens when a recipe is interrupted.\n* Recursion::                   Invoking @code{make} from makefiles.\n* Canned Recipes::              Defining canned recipes.\n* Empty Recipes::               Defining useful, do-nothing recipes.\n\nRecipe Syntax\n\n* Splitting Recipe Lines::      Breaking long recipe lines for readability.\n* Variables in Recipes::        Using @code{make} variables in recipes.\n\nRecipe Execution\n\n* One Shell::                   One shell for all lines in a recipe.\n* Choosing the Shell::          How @code{make} chooses the shell used\n                                  to run recipes.\n\nParallel Execution\n\n* Parallel Disable::            Disabling parallel execution\n* Parallel Output::             Handling output during parallel execution\n* Parallel Input::              Handling input during parallel execution\n\nRecursive Use of @code{make}\n\n* MAKE Variable::               The special effects of using @samp{$(MAKE)}.\n* Variables/Recursion::         How to communicate variables to a sub-@code{make}.\n* Options/Recursion::           How to communicate options to a sub-@code{make}.\n* -w Option::                   How the @samp{-w} or @samp{--print-directory} option\n                                  helps debug use of recursive @code{make} commands.\n\nHow to Use Variables\n\n* Variable Naming::             Choosing names for variables.\n* Reference::                   How to use the value of a variable.\n* Flavors::                     Variables come in two flavors.\n* Expanding::                   How text is expanded by @code{make}.\n* Values::                      All the ways variables get their values.\n* Setting::                     How to set a variable in the makefile.\n* Substitution Refs::           Substituting values in variable expansion.\n* Override Directive::          How to set a variable in the makefile even if\n                                  the user has set it with a command argument.\n* Multi-Line::                  An alternate way to set a variable\n                                  to a multi-line string.\n* Undefine Directive::          How to undefine a variable so that it appears\n                                  as if it was never set.\n* Environment::                 Variable values can come from the environment.\n* Target-specific::             Variable values can be defined on a per-target\n                                  basis.\n* Pattern-specific::            Target-specific variable values can be applied\n                                  to a group of targets that match a pattern.\n* Suppressing Inheritance::     Suppress inheritance of variables.\n* Special Variables::           Variables with special meaning or behavior.\n\nBasics of Variable References\n\n* Computed Names::              Computing the name of a variable reference.\n\nThe Two Flavors of Variables\n\n* Recursive Variables::         Recursive variables delay expansion.\n* Simple Variables::            Simple variables expand immediately.\n\nSetting Variables\n\n* Immediate Assignment::        Recursive variables with immediate expansion.\n* Shell Assignment::            Assigning variables to shell output.\n* Conditional Assignment::      Assigning variables only if not yet defined.\n* Appending Assignment::        How to append to the value of a variable.\n* Whitespace in Values::        Leading and trailing whitespace in values.\n\nConditional Parts of Makefiles\n\n* Conditional Example::         Example of a conditional\n* Conditional Syntax::          The syntax of conditionals.\n* Testing Flags::               Conditionals that test flags.\n\nFunctions for Transforming Text\n\n* Syntax of Functions::         How to write a function call.\n* Text Functions::              General-purpose text manipulation functions.\n* File Name Functions::         Functions for manipulating file names.\n* Conditional Functions::       Functions that implement conditions.\n* Let Function::                Local variables.\n* Foreach Function::            Repeat some text with controlled variation.\n* File Function::               Write text to a file.\n* Call Function::               Expand a user-defined function.\n* Value Function::              Return the un-expanded value of a variable.\n* Eval Function::               Evaluate the arguments as makefile syntax.\n* Origin Function::             Find where a variable got its value.\n* Flavor Function::             Find out the flavor of a variable.\n* Make Control Functions::      Functions that control how make runs.\n* Shell Function::              Substitute the output of a shell command.\n* Guile Function::              Use GNU Guile embedded scripting language.\n\nHow to Run @code{make}\n\n* Makefile Arguments::          How to specify which makefile to use.\n* Goals::                       How to use goal arguments to specify which\n                                  parts of the makefile to use.\n* Instead of Execution::        How to use mode flags to specify what\n                                  kind of thing to do with the recipes\n                                  in the makefile other than simply\n                                  execute them.\n* Avoiding Compilation::        How to avoid recompiling certain files.\n* Overriding::                  How to override a variable to specify\n                                  an alternate compiler and other things.\n* Testing::                     How to proceed past some errors, to\n                                  test compilation.\n* Warnings::                    How to control reporting of makefile issues.\n* Temporary Files::             Where @code{make} keeps its temporary files.\n* Options Summary::             Summary of Options\n\nUsing Implicit Rules\n\n* Using Implicit::              How to use an existing implicit rule\n                                  to get the recipes for updating a file.\n* Catalogue of Rules::          A list of built-in rules.\n* Implicit Variables::          How to change what predefined rules do.\n* Chained Rules::               How to use a chain of implicit rules.\n* Pattern Rules::               How to define new implicit rules.\n* Last Resort::                 How to define a recipe for rules which\n                                  cannot find any.\n* Suffix Rules::                The old-fashioned style of implicit rule.\n* Implicit Rule Search::        The precise algorithm for applying\n                                  implicit rules.\n\nDefining and Redefining Pattern Rules\n\n* Pattern Intro::               An introduction to pattern rules.\n* Pattern Examples::            Examples of pattern rules.\n* Automatic Variables::         How to use automatic variables in the\n                                  recipe of implicit rules.\n* Pattern Match::               How patterns match.\n* Match-Anything Rules::        Precautions you should take prior to\n                                  defining rules that can match any\n                                  target file whatever.\n* Canceling Rules::             How to override or cancel built-in rules.\n\nUsing @code{make} to Update Archive Files\n\n* Archive Members::             Archive members as targets.\n* Archive Update::              The implicit rule for archive member targets.\n* Archive Pitfalls::            Dangers to watch out for when using archives.\n* Archive Suffix Rules::        You can write a special kind of suffix rule\n                                  for updating archives.\n\nImplicit Rule for Archive Member Targets\n\n* Archive Symbols::             How to update archive symbol directories.\n\nExtending GNU @code{make}\n\n* Guile Integration::           Using Guile as an embedded scripting language.\n* Loading Objects::             Loading dynamic objects as extensions.\n\nGNU Guile Integration\n\n* Guile Types::                 Converting Guile types to @code{make} strings.\n* Guile Interface::             Invoking @code{make} functions from Guile.\n* Guile Example::               Example using Guile in @code{make}.\n\nLoading Dynamic Objects\n\n* load Directive::              Loading dynamic objects as extensions.\n* Initializing Functions::      How initializing functions are called.\n* Remaking Loaded Objects::     How loaded objects get remade.\n* Loaded Object API::           Programmatic interface for loaded objects.\n* Loaded Object Example::       Example of a loaded object\n\nIntegrating GNU @code{make}\n\n* Job Slots::                   Share job slots with GNU Make.\n* Terminal Output::             Control output to terminals.\n\nSharing Job Slots with GNU @code{make}\n\n* POSIX Jobserver::             Using the jobserver on POSIX systems.\n* Windows Jobserver::           Using the jobserver on Windows systems.\n\nQuick Reference\n\n* Makefile Directives::         All makefile directives.\n* Makefile Functions::          All makefile built-in functions.\n* Automatic Variable Reference::  All automatic variables for recipes.\n* Special Variable Reference::  All special variables for makefiles.\n\nTroubleshooting Make and Makefiles\n\n* Parse Error::                 Syntax errors when parsing makefiles.\n* Command Failure::             Recipe commands exit with error codes.\n* Wrong Rule::                  @code{make} chooses the wrong rule.\n* No Rule Found::               No rule was found to build a target.\n* Extra Rebuilds::              Targets are rebuilt unnecessarily.\n* Missing Rebuilds::            Out-of-date targets are not rebuilt.\n* Troubleshooting Strategies::  Strategies used for troubleshooting issues.\n\n@end detailmenu\n@end menu\n\n@node Overview\n@comment  node-name,  next,  previous,  up\n@chapter Overview of @code{make}\n\nThe @code{make} utility determines which files in a project are out of date,\nand runs commands to bring them up to date.  This manual describes the GNU\nproject's implementation of @code{make}, GNU Make, which was created by\nRichard Stallman and Roland McGrath.  Paul D. Smith has handled development\nand maintenance since Version 3.76 (1997).\n\nGNU @code{make} conforms to @cite{IEEE Standard 1003.1-2024} (POSIX.1-2024).\n@cindex POSIX\n@cindex IEEE Standard 1003.1\n@cindex standards conformance\n\nOur examples show C programs, since they are common, but you can use\n@code{make} with any programming language whose compiler can be run with a\nshell command.  Indeed, @code{make} is not limited to compiling programs: it\ncan be used to automate any task where some files need to be updated\nautomatically whenever other files have been changed.\n\n@menu\n* Preparing::                   Preparing and running @code{make}.\n* Reading::                     On reading this text.\n* Bugs::                        Problems and bugs.\n@end menu\n\n@node Preparing\n@section Preparing and Running Make\n\nTo use @code{make}, you must write a file, called a @dfn{makefile}, that\ndescribes the relationships among files in your project and provides commands\nfor updating each file.  For example, in a typical C program the executable\nfile is updated from object files, which are in turn made by compiling source\nfiles.\n\nOnce a suitable makefile exists, each time you change some source files,\nthis simple shell command:\n\n@example\nmake\n@end example\n\n@noindent\nsuffices to perform all necessary recompilations.  The @code{make} program\nuses the information in the makefile and the last-modification times of the\nfiles to decide which of the files need to be updated.  For each of those\nfiles, it issues the recipes provided in the makefile.\n\nYou can provide command line arguments to @code{make} to control which\nfiles should be recompiled, or how.  @xref{Running, ,How to Run\n@code{make}}.\n\n@node Reading\n@section How to Read This Manual\n\nIf you are new to @code{make}, or are looking for a general\nintroduction, read the first few sections of each chapter, skipping the\nlater sections.  In each chapter, the first few sections contain\nintroductory or general information and the later sections contain\nspecialized or technical information.\n@ifnottex\nThe exception is the second chapter, @ref{Introduction, ,An\nIntroduction to Makefiles}, all of which is introductory.\n@end ifnottex\n@iftex\nThe exception is @ref{Introduction, ,An Introduction to Makefiles},\nall of which is introductory.\n@end iftex\n\nIf you are familiar with other @code{make} programs, see @ref{Features,\n,Features of GNU @code{make}}, which lists the enhancements GNU Make has, and\n@ref{Missing, ,Incompatibilities and Missing Features}, which explains the few\nthings GNU Make lacks that others have.\n\nFor a quick summary, see @ref{Options Summary}, @ref{Quick Reference},\nand @ref{Special Targets}.\n\nIf you have a makefile already and it is not working as you expect,\n@pxref{Troubleshooting, ,Troubleshooting Make and Makefiles}.\n\n@node Bugs\n@section Problems and Bugs\n@cindex reporting bugs\n@cindex bugs, reporting\n@cindex problems and bugs, reporting\n\nIf you have problems with GNU @code{make} or think you've found a bug,\nplease report it to the developers; we cannot promise to do anything but\nwe might well want to fix it.\n\nBefore reporting a bug, make sure you've actually found a real bug.\nCarefully reread the documentation and see if it really says you can do\nwhat you're trying to do.  If it's not clear whether you should be able\nto do something or not, report that too; it's a bug in the\ndocumentation!\n\nBefore reporting a bug or trying to fix it yourself, try to isolate it\nto the smallest possible makefile that reproduces the problem.  Then\nsend us the makefile and the exact results @code{make} gave you,\nincluding any error or warning messages.  Please don't paraphrase\nthese messages: it's best to cut and paste them into your report.\nWhen generating this small makefile, be sure to not use any non-free\nor unusual tools in your recipes: you can almost always emulate what\nsuch a tool would do with simple shell commands.  Finally, be sure to\nexplain what you expected to occur; this will help us decide whether\nthe problem was really in the documentation.\n\nOnce you have a precise problem you can report it in one of two ways.\nEither send electronic mail to:\n\n@example\n    bug-make@@gnu.org\n@end example\n\n@noindent\nor use our Web-based project management tool, at:\n\n@example\n    https://savannah.gnu.org/projects/make/\n@end example\n\n@noindent\nIn addition to the information above, please be careful to include the\nversion number of @code{make} you are using.  You can get this\ninformation with the command @samp{make --version}.  Be sure also to\ninclude the type of machine and operating system you are using.\n\nIf you have a code change you'd like to submit, see the @file{README} file\nsection ``Submitting Patches'' for information.\n\n@node Introduction\n@comment  node-name,  next,  previous,  up\n@chapter An Introduction to Makefiles\n\nYou need a file called a @dfn{makefile} to tell @code{make} what to do.  For\nexample, the makefile might tell @code{make} how to compile and link a\nprogram.\n@cindex makefile\n\nA makefile is a combination of two different ``languages'' in a single file.\nMost of the makefile is written to be parsed by @code{make}, but also included\nin the makefile are @emph{recipes} which contain the commands used to update\ntargets.  These commands are passed to a shell to be parsed and run so they\nuse shell syntax, not @code{make} syntax.  It's important to keep in mind the\ndifference between these two syntaxes when writing makefiles.\n\nFor a detailed description of the content of makefiles, @pxref{Makefile\nContents, ,What Makefiles Contain}.\n\nA makefile is not a procedural list of steps to be taken.  Instead, it\ndescribes a @dfn{directed acyclic graph}, where each node in the graph is a\npotential target to be created and each edge in the graph is a prerequisite\nrelationship.  Every rule in a makefile defines (or updates) a node and\n(optionally) some of the edges starting from that node.\n\nIn this chapter, we will discuss a simple makefile that describes how to\ncompile and link a text editor which consists of eight C source files\nand three header files.  The makefile can also tell @code{make} how to\nrun miscellaneous commands when explicitly asked (for example, to remove\ncertain files as a clean-up operation).  To see a more complex example\nof a makefile, see @ref{Complex Makefile}.\n\nWhen @code{make} recompiles the editor, each changed C source file\nmust be recompiled.  If a header file has changed, each C source file\nthat includes the header file must be recompiled to be safe.  Each\ncompilation produces an object file corresponding to the source file.\nFinally, if any source file has been recompiled, all the object files,\nwhether newly made or saved from previous compilations, must be linked\ntogether to produce the new executable editor.\n@cindex recompilation\n@cindex editor\n\n@menu\n* Rule Introduction::           What a rule looks like.\n* Simple Makefile::             A simple makefile.\n* How Make Works::              How @code{make} processes this makefile.\n* Variables Simplify::          Variables make makefiles simpler.\n* make Deduces::                Letting @code{make} deduce the recipes.\n* Combine By Prerequisite::     Another style of makefile.\n* Cleanup::                     Rules for cleaning the directory.\n@end menu\n\n@node Rule Introduction\n@comment  node-name,  next,  previous,  up\n@section What a Rule Looks Like\n@cindex rule, introduction to\n@cindex makefile rule parts\n@cindex parts of makefile rule\n\nA simple makefile consists of ``rules'' with the following shape:\n\n@cindex targets, introduction to\n@cindex prerequisites, introduction to\n@cindex recipes, introduction to\n@example\n@group\n@var{target} @dots{} : @var{prerequisites} @dots{}\n        @var{recipe}\n        @dots{}\n        @dots{}\n@end group\n@end example\n\nA @dfn{target} is usually the name of a file that is generated by a\nprogram; examples of targets are executable or object files.  A target\ncan also be the name of an action to carry out, such as @samp{clean}\n(@pxref{Phony Targets}).\n\nA @dfn{prerequisite} is a file that is used as input to create the\ntarget.  A target often depends on several files.\n\n@cindex tabs in rules\nA @dfn{recipe} is an action that @code{make} carries out.  A recipe\nmay have more than one command, either on the same line or each on its\nown line.  @strong{Please note:} you need to put a tab character at\nthe beginning of every recipe line!  This is an obscurity that catches\nthe unwary.  If you prefer to prefix your recipes with a character\nother than tab, you can set the @code{.RECIPEPREFIX} variable to an\nalternate character (@pxref{Special Variables}).\n\nUsually a recipe is in a rule with prerequisites and serves to create a\ntarget file if any of the prerequisites change.  However, the rule that\nspecifies a recipe for the target need not have prerequisites.  For\nexample, the rule containing the delete command associated with the\ntarget @samp{clean} does not have prerequisites.\n\nA @dfn{rule}, then, explains how and when to remake certain files\nwhich are the targets of the particular rule.  @code{make} carries out\nthe recipe on the prerequisites to create or update the target.  A\nrule can also explain how and when to carry out an action.\n@xref{Rules, , Writing Rules}.\n\nA makefile may contain other text besides rules, but a simple makefile\nneed only contain rules.  Rules may look somewhat more complicated\nthan shown in this template, but all fit the pattern more or less.\n\n@node Simple Makefile\n@section A Simple Makefile\n@cindex simple makefile\n@cindex makefile, simple\n\nHere is a straightforward makefile that describes the way an\nexecutable file called @code{edit} depends on eight object files\nwhich, in turn, depend on eight C source and three header files.\n\nIn this example, all the C files include @file{defs.h}, but only those\ndefining editing commands include @file{command.h}, and only low\nlevel files that change the editor buffer include @file{buffer.h}.\n\n@example\n@group\nedit : main.o kbd.o command.o display.o \\\n       insert.o search.o files.o utils.o\n        cc -o edit main.o kbd.o command.o display.o \\\n                   insert.o search.o files.o utils.o\n\nmain.o : main.c defs.h\n        cc -c main.c\nkbd.o : kbd.c defs.h command.h\n        cc -c kbd.c\ncommand.o : command.c defs.h command.h\n        cc -c command.c\ndisplay.o : display.c defs.h buffer.h\n        cc -c display.c\ninsert.o : insert.c defs.h buffer.h\n        cc -c insert.c\nsearch.o : search.c defs.h buffer.h\n        cc -c search.c\nfiles.o : files.c defs.h buffer.h command.h\n        cc -c files.c\nutils.o : utils.c defs.h\n        cc -c utils.c\nclean :\n        rm edit main.o kbd.o command.o display.o \\\n           insert.o search.o files.o utils.o\n@end group\n@end example\n\n@noindent\nWe split each long line into two lines using backslash/newline; this is\nlike using one long line, but is easier to read.  @xref{Splitting Lines,\n, Splitting Long Lines}.\n@cindex continuation lines\n@cindex @code{\\} (backslash), for continuation lines\n@cindex backslash (@code{\\}), for continuation lines\n@cindex quoting newline, in makefile\n@cindex newline, quoting, in makefile\n\nTo use this makefile to create the executable file called @file{edit},\ntype:\n\n@example\nmake\n@end example\n\nTo use this makefile to delete the executable file and all the object\nfiles from the directory, type:\n\n@example\nmake clean\n@end example\n\nIn the example makefile, the targets include the executable file @samp{edit},\nand the object files @samp{main.o}, @samp{kbd.o}, etc.  The prerequisites are\nfiles such as @samp{main.c} and @samp{defs.h}.  You can see that each\n@samp{.o} file is both a target and a prerequisite: this is common in\nmakefiles.  Recipes include @w{@samp{cc -c main.c}} and @w{@samp{cc -c\nkbd.c}}.\n\nWhen a target is a program, it needs to be recompiled or relinked if any of\nits prerequisites change.  In addition, any prerequisites that are themselves\nautomatically generated should be updated first.  In this example, @file{edit}\ndepends on the eight object files; the object file @file{main.o} depends on\nthe source file @file{main.c} and on the header file @file{defs.h}.\n\nA recipe may follow each line that contains a target and\nprerequisites.  These recipes say how to update the target file.  A\ntab character (or whatever character is specified by the\n@code{.RECIPEPREFIX} variable; @pxref{Special Variables}) must come at\nthe beginning of every line in the recipe to distinguish recipes from\nother lines in the makefile.  (Bear in mind that @code{make} does not\nknow anything about how the recipes work.  It is up to you to supply\nrecipes that will update the target file properly.  All @code{make}\ndoes is execute the recipe you have specified when the target file\nneeds to be updated.)\n@cindex recipe\n\nThe target @samp{clean} is not a file, but merely the name of an\naction.  Since you normally do not want to carry out the actions in\nthis rule, @samp{clean} is not a prerequisite of any other rule.\nConsequently, @code{make} never does anything with it unless you tell\nit specifically.  Note that this rule not only is not a prerequisite,\nit also does not have any prerequisites, so the only purpose of the\nrule is to run the specified recipe.  Targets that do not refer to\nfiles but are just actions are called @dfn{phony targets}.\n@xref{Phony Targets}, for information about this kind of target.\n@xref{Errors, , Errors in Recipes}, to see how to cause @code{make}\nto ignore errors from @code{rm} or any other command.\n@cindex @code{clean} target\n@cindex @code{rm} (shell command)\n\n@node How Make Works\n@comment  node-name,  next,  previous,  up\n@section How @code{make} Processes a Makefile\n@cindex processing a makefile\n@cindex makefile, how @code{make} processes\n\nBy default, @code{make} starts with the first target (not targets whose names\nstart with @samp{.} unless they also contain one or more @samp{/}).  This is\ncalled the @dfn{default goal}.  (@dfn{Goals} are the targets that @code{make}\nstrives ultimately to update.  You can override this behavior using the\ncommand line (@pxref{Goals, , Arguments to Specify the Goals}) or with the\n@code{.DEFAULT_GOAL} special variable (@pxref{Special Variables, , Other\nSpecial Variables}).\n@cindex default goal\n@cindex goal, default\n@cindex goal\n\nIn the simple example of the previous section, the default goal is to\nupdate the executable program @file{edit}; therefore, we put that rule\nfirst.\n\nThus, when you give the command:\n\n@example\nmake\n@end example\n\n@noindent\n@code{make} reads the makefile in the current directory and begins by\nprocessing the first rule.  In the example, this rule is for relinking\n@file{edit}; but before @code{make} can fully process this rule, it\nmust process the rules for the files that @file{edit} depends on,\nwhich in this case are the object files.  Each of these files is\nprocessed according to its own rule.  These rules say to update each\n@samp{.o} file by compiling its source file.  The recompilation must\nbe done if the source file, or any of the header files named as\nprerequisites, is more recent than the object file, or if the object\nfile does not exist.\n\nThe other rules are processed because their targets appear as\nprerequisites of the goal.  If some other rule is not depended on by the\ngoal (or anything it depends on, etc.), that rule is not processed,\nunless you tell @code{make} to do so (with a command such as\n@w{@code{make clean}}).\n\nBefore recompiling an object file, @code{make} considers updating its\nprerequisites, the source file and header files.  This makefile does not\nspecify anything to be done for them---the @samp{.c} and @samp{.h} files\nare not the targets of any rules---so @code{make} does nothing for these\nfiles.  But @code{make} would update automatically generated C programs,\nsuch as those made by Bison or Yacc, by their own rules at this time.\n\nAfter recompiling whichever object files need it, @code{make} decides\nwhether to relink @file{edit}.  This must be done if the file\n@file{edit} does not exist, or if any of the object files are newer than\nit.  If an object file was just recompiled, it is now newer than\n@file{edit}, so @file{edit} is relinked.\n@cindex relinking\n\nThus, if we change the file @file{insert.c} and run @code{make},\n@code{make} will compile that file to update @file{insert.o}, and then\nlink @file{edit}.  If we change the file @file{command.h} and run\n@code{make}, @code{make} will recompile the object files @file{kbd.o},\n@file{command.o} and @file{files.o} and then link the file @file{edit}.\n\n@node Variables Simplify\n@section Variables Make Makefiles Simpler\n@cindex variables\n@cindex simplifying with variables\n\nIn our example, we had to list all the object files twice in the rule for\n@file{edit} (repeated here):\n\n@example\n@group\nedit : main.o kbd.o command.o display.o \\\n              insert.o search.o files.o utils.o\n        cc -o edit main.o kbd.o command.o display.o \\\n                   insert.o search.o files.o utils.o\n@end group\n@end example\n\n@cindex @code{objects}\nSuch duplication is error-prone; if a new object file is added to the\nsystem, we might add it to one list and forget the other.  We can eliminate\nthe risk and simplify the makefile by using a variable.  @dfn{Variables}\nallow a text string to be defined once and substituted in multiple places\nlater (@pxref{Using Variables, ,How to Use Variables}).\n\n@cindex @code{OBJECTS}\n@cindex @code{objs}\n@cindex @code{OBJS}\n@cindex @code{obj}\n@cindex @code{OBJ}\nIt is standard practice for every makefile to have a variable named\n@code{objects}, @code{OBJECTS}, @code{objs}, @code{OBJS}, @code{obj},\nor @code{OBJ} which is a list of all object file names.  We would\ndefine such a variable @code{objects} with a line like this in the\nmakefile:\n\n@example\n@group\nobjects = main.o kbd.o command.o display.o \\\n          insert.o search.o files.o utils.o\n@end group\n@end example\n\n@noindent\nThen, each place we want to put a list of the object file names, we can\nsubstitute the variable's value by writing @samp{$(objects)}\n(@pxref{Using Variables, ,How to Use Variables}).\n\nHere is how the complete simple makefile looks when you use a variable\nfor the object files:\n\n@example\n@group\nobjects = main.o kbd.o command.o display.o \\\n          insert.o search.o files.o utils.o\n\nedit : $(objects)\n        cc -o edit $(objects)\nmain.o : main.c defs.h\n        cc -c main.c\nkbd.o : kbd.c defs.h command.h\n        cc -c kbd.c\ncommand.o : command.c defs.h command.h\n        cc -c command.c\ndisplay.o : display.c defs.h buffer.h\n        cc -c display.c\ninsert.o : insert.c defs.h buffer.h\n        cc -c insert.c\nsearch.o : search.c defs.h buffer.h\n        cc -c search.c\nfiles.o : files.c defs.h buffer.h command.h\n        cc -c files.c\nutils.o : utils.c defs.h\n        cc -c utils.c\nclean :\n        rm edit $(objects)\n@end group\n@end example\n\n@node make Deduces\n@section Letting @code{make} Deduce the Recipes\n@cindex deducing recipes (implicit rules)\n@cindex implicit rule, introduction to\n@cindex rule, implicit, introduction to\n\nIt is not necessary to spell out the recipes for compiling the individual\nC source files, because @code{make} can figure them out: it has an\n@dfn{implicit rule} for updating a @samp{.o} file from a correspondingly\nnamed @samp{.c} file using a @samp{cc -c} command.  For example, it will\nuse the recipe @samp{cc -c main.c -o main.o} to compile @file{main.c} into\n@file{main.o}.  We can therefore omit the recipes from the rules for the\nobject files.  @xref{Implicit Rules, ,Using Implicit Rules}.\n\nWhen a @samp{.c} file is used automatically in this way, it is also\nautomatically added to the list of prerequisites.  We can therefore omit\nthe @samp{.c} files from the prerequisites, provided we omit the recipe.\n\nHere is the entire example, with both of these changes, and a variable\n@code{objects} as suggested above:\n\n@example\n@group\nobjects = main.o kbd.o command.o display.o \\\n          insert.o search.o files.o utils.o\n\nedit : $(objects)\n        cc -o edit $(objects)\n\nmain.o : defs.h\nkbd.o : defs.h command.h\ncommand.o : defs.h command.h\ndisplay.o : defs.h buffer.h\ninsert.o : defs.h buffer.h\nsearch.o : defs.h buffer.h\nfiles.o : defs.h buffer.h command.h\nutils.o : defs.h\n\n.PHONY : clean\nclean :\n        rm edit $(objects)\n@end group\n@end example\n\n@noindent\nThis is how we would write the makefile in actual practice.  (The\ncomplications associated with @samp{clean} are described elsewhere.\nSee @ref{Phony Targets}, and @ref{Errors, ,Errors in Recipes}.)\n\nBecause implicit rules are so convenient, they are important.  You\nwill see them used frequently.\n\n@node Combine By Prerequisite\n@section Another Style of Makefile\n@cindex combining rules by prerequisite\n\nWhen the objects of a makefile are created only by implicit rules, an\nalternative style of makefile is possible.  In this style of makefile,\nyou group entries by their prerequisites instead of by their targets.\nHere is what one looks like:\n\n@example\n@group\nobjects = main.o kbd.o command.o display.o \\\n          insert.o search.o files.o utils.o\n\nedit : $(objects)\n        cc -o edit $(objects)\n\n$(objects) : defs.h\nkbd.o command.o files.o : command.h\ndisplay.o insert.o search.o files.o : buffer.h\n@end group\n@end example\n\n@noindent\nHere @file{defs.h} is given as a prerequisite of all the object files;\n@file{command.h} and @file{buffer.h} are prerequisites of the specific\nobject files listed for them.\n\nWhether this is better is a matter of taste: it is more compact, but some\npeople dislike it because they find it clearer to put all the information\nabout each target in one place.\n\n@node Cleanup\n@section Rules for Cleaning the Directory\n@cindex cleaning up\n@cindex removing, to clean up\n\nCompiling a program is not the only thing you might want to write rules\nfor.  Makefiles commonly tell how to do a few other things besides\ncompiling a program: for example, how to delete all the object files\nand executables so that the directory is @samp{clean}.\n\n@cindex @code{clean} target\nHere is how we\ncould write a @code{make} rule for cleaning our example editor:\n\n@example\n@group\nclean:\n        rm edit $(objects)\n@end group\n@end example\n\nIn practice, we might want to write the rule in a somewhat more\ncomplicated manner to handle unanticipated situations.  We would do this:\n\n@example\n@group\n.PHONY : clean\nclean :\n        -rm edit $(objects)\n@end group\n@end example\n\n@noindent\nThis prevents @code{make} from getting confused by an actual file\ncalled @file{clean} and causes it to continue in spite of errors from\n@code{rm}.  (See @ref{Phony Targets}, and @ref{Errors, ,Errors in\nRecipes}.)\n\n@noindent\nA rule such as this should not be placed at the beginning of the\nmakefile, because we do not want it to run by default!  Thus, in the\nexample makefile, we want the rule for @code{edit}, which recompiles\nthe editor, to remain the default goal.\n\nSince @code{clean} is not a prerequisite of @code{edit}, this rule will not\nrun at all if we give the command @samp{make} with no arguments.  In\norder to make the rule run, we have to type @samp{make clean}.\n@xref{Running, ,How to Run @code{make}}.\n\n@node Makefiles\n@chapter Writing Makefiles\n\n@cindex makefile, how to write\nThe information that tells @code{make} how to recompile a system comes from\nreading a data base called the @dfn{makefile}.\n\n@menu\n* Makefile Contents::           What makefiles contain.\n* Makefile Names::              How to name your makefile.\n* Include::                     How one makefile can use another makefile.\n* MAKEFILES Variable::          The environment can specify extra makefiles.\n* Remaking Makefiles::          How makefiles get remade.\n* Overriding Makefiles::        How to override part of one makefile\n                                  with another makefile.\n* Reading Makefiles::           How makefiles are read in.\n* Parsing Makefiles::           How makefiles are parsed.\n* Secondary Expansion::         How and when secondary expansion is performed.\n@end menu\n\n@node Makefile Contents\n@section What Makefiles Contain\n\nMakefiles contain five kinds of things: @dfn{explicit rules},\n@dfn{implicit rules}, @dfn{variable definitions}, @dfn{directives},\nand @dfn{comments}.  Rules, variables, and directives are described at\nlength in later chapters.\n\n@itemize @bullet\n@cindex rule, explicit, definition of\n@cindex explicit rule, definition of\n@item\nAn @dfn{explicit rule} says when and how to remake one or more files,\ncalled the rule's @dfn{targets}.  It lists the other files that the\ntargets depend on, called the @dfn{prerequisites} of the target, and\nmay also give a recipe to use to create or update the targets.\n@xref{Rules, ,Writing Rules}.\n\n@cindex rule, implicit, definition of\n@cindex implicit rule, definition of\n@item\nAn @dfn{implicit rule} says when and how to remake a class of files\nbased on their names.  It describes how a target may depend on a file\nwith a name similar to the target and gives a recipe to create or\nupdate such a target.  @xref{Implicit Rules, ,Using Implicit Rules}.\n\n@cindex variable definition\n@item\nA @dfn{variable definition} is a line that specifies a text string\nvalue for a variable that can be substituted into the text later.  The\nsimple makefile example shows a variable definition for @code{objects}\nas a list of all object files (@pxref{Variables Simplify, , Variables\nMake Makefiles Simpler}).\n\n@cindex directive\n@item\nA @dfn{directive} is an instruction for @code{make} to do something\nspecial while reading the makefile.  These include:\n\n@itemize @bullet\n@item\nReading another makefile (@pxref{Include, ,Including Other Makefiles}).\n\n@item\nDeciding (based on the values of variables) whether to use or\nignore a part of the makefile (@pxref{Conditionals, ,Conditional Parts of Makefiles}).\n\n@item\nDefining a variable from a verbatim string containing multiple lines\n(@pxref{Multi-Line, ,Defining Multi-Line Variables}).\n@end itemize\n\n@cindex comments, in makefile\n@cindex @code{#} (comments), in makefile\n@item\n@samp{#} in a line of a makefile starts a @dfn{comment}.  It and the\nrest of the line are ignored, except that a trailing backslash not\nescaped by another backslash will continue the comment across multiple\nlines.  A line containing just a comment (with perhaps spaces before\nit) is effectively blank, and is ignored.  If you want a literal\n@code{#}, escape it with a backslash (e.g., @code{\\#}).  Comments may\nappear on any line in the makefile, although they are treated\nspecially in certain situations.\n\nYou cannot use comments within variable references or function calls:\nany instance of @code{#} will be treated literally (rather than as the\nstart of a comment) inside a variable reference or function call.\n\nComments within a recipe are passed to the shell, just as with any\nother recipe text.  The shell decides how to interpret it: whether or\nnot this is a comment is up to the shell.\n\nWithin a @code{define} directive, comments are not ignored during the\ndefinition of the variable, but rather kept intact in the value of the\nvariable.  When the variable is expanded they will either be treated\nas @code{make} comments or as recipe text, depending on the context in\nwhich the variable is evaluated.\n@end itemize\n\n@menu\n* Splitting Lines::             Splitting long lines in makefiles\n@end menu\n\n@node Splitting Lines\n@subsection Splitting Long Lines\n@cindex splitting long lines\n@cindex long lines, splitting\n@cindex backslash (@code{\\}), to quote newlines\n\nMakefiles use a ``line-based'' syntax in which the newline character\nis special and marks the end of a statement.  GNU @code{make} has no\nlimit on the length of a statement line, up to the amount of memory in\nyour computer.\n\nHowever, it is difficult to read lines which are too long to display\nwithout wrapping or scrolling.  So, you can format your makefiles for\nreadability by adding newlines into the middle of a statement: you do\nthis by escaping the internal newlines with a backslash (@code{\\})\ncharacter.  Where we need to make a distinction we will refer to\n``physical lines'' as a single line ending with a newline (regardless\nof whether it is escaped) and a ``logical line'' being a complete\nstatement including all escaped newlines up to the first non-escaped\nnewline.\n\nThe way in which backslash/newline combinations are handled depends on\nwhether the statement is a recipe line or a non-recipe line.  Handling\nof backslash/newline in a recipe line is discussed later\n(@pxref{Splitting Recipe Lines}).\n\nOutside of recipe lines, backslash/newlines are converted into a\nsingle space character.  Once that is done, all whitespace around the\nbackslash/newline is condensed into a single space: this includes all\nwhitespace preceding the backslash, all whitespace at the beginning of\nthe line after the backslash/newline, and any consecutive\nbackslash/newline combinations.\n\nIf the @code{.POSIX} special target is defined then backslash/newline handling\nis modified slightly to conform to POSIX: first, whitespace preceding a\nbackslash is not removed and second, consecutive backslash/newlines are not\ncondensed.\n\n@subsubheading Splitting Without Adding Whitespace\n@cindex whitespace, avoiding on line split\n@cindex removing whitespace from split lines\n\nIf you need to split a line but do @emph{not} want any whitespace\nadded, you can utilize a subtle trick: replace your backslash/newline\npairs with the three characters dollar sign, backslash, and newline:\n\n@example\nvar := one$\\\n       word\n@end example\n\nAfter @code{make} removes the backslash/newline and condenses the\nfollowing line into a single space, this is equivalent to:\n\n@example\nvar := one$ word\n@end example\n\nThen @code{make} will perform variable expansion.  The variable\nreference @samp{$ } refers to a variable with the one-character name\n`` '' (space) which does not exist, and so expands to the empty\nstring, giving a final assignment which is the equivalent of:\n\n@example\nvar := oneword\n@end example\n\n\n@node Makefile Names\n@section What Name to Give Your Makefile\n@cindex makefile name\n@cindex name of makefile\n@cindex default makefile name\n@cindex file name of makefile\n\n@c following paragraph rewritten to avoid overfull hbox\nBy default, when @code{make} looks for the makefile, it tries the\nfollowing names, in order: @file{GNUmakefile}, @file{makefile}\nand @file{Makefile}.\n@findex Makefile\n@findex GNUmakefile\n@findex makefile\n\n@cindex @code{README}\nNormally you should call your makefile either @file{makefile} or\n@file{Makefile}.  (We recommend @file{Makefile} because it appears\nprominently near the beginning of a directory listing, right near other\nimportant files such as @file{README}.)  The first name checked,\n@file{GNUmakefile}, is not recommended for most makefiles.  You should\nuse this name if you have a makefile that is specific to GNU\n@code{make}, and will not be understood by other versions of\n@code{make}.  Other @code{make} programs look for @file{makefile} and\n@file{Makefile}, but not @file{GNUmakefile}.\n\nIf @code{make} finds none of these names, it does not use any makefile.\nThen you must specify a goal with a command argument, and @code{make}\nwill attempt to figure out how to remake it using only its built-in\nimplicit rules.  @xref{Implicit Rules, ,Using Implicit Rules}.\n\n@cindex @code{-f}\n@cindex @code{--file}\n@cindex @code{--makefile}\nIf you want to use a nonstandard name for your makefile, you can specify\nthe makefile name with the @samp{-f} or @samp{--file} option.  The\narguments @w{@samp{-f @var{name}}} or @w{@samp{--file=@var{name}}} tell\n@code{make} to read the file @var{name} as the makefile.  If you use\nmore than one @samp{-f} or @samp{--file} option, you can specify several\nmakefiles.  All the makefiles are effectively concatenated in the order\nspecified.  The default makefile names @file{GNUmakefile},\n@file{makefile} and @file{Makefile} are not checked automatically if you\nspecify @samp{-f} or @samp{--file}.\n@cindex specifying makefile name\n@cindex makefile name, how to specify\n@cindex name of makefile, how to specify\n@cindex file name of makefile, how to specify\n\n@node Include\n@section Including Other Makefiles\n@cindex including other makefiles\n@cindex makefile, including\n\n@findex include\nThe @code{include} directive tells @code{make} to suspend reading the\ncurrent makefile and read one or more other makefiles before continuing.\nThe directive is a line in the makefile that looks like this:\n\n@example\ninclude @var{filenames}@dots{}\n@end example\n\n@noindent\n@var{filenames} can contain shell file name patterns.  If\n@var{filenames} is empty, nothing is included and no error is printed.\n@cindex shell file name pattern (in @code{include})\n@cindex shell wildcards (in @code{include})\n@cindex wildcard, in @code{include}\n\nExtra spaces are allowed and ignored at the beginning of the line, but\nthe first character must not be a tab (or the value of\n@code{.RECIPEPREFIX})---if the line begins with a tab, it will be\nconsidered a recipe line.  Whitespace is required between\n@code{include} and the file names, and between file names; extra\nwhitespace is ignored there and at the end of the directive.  A\ncomment starting with @samp{#} is allowed at the end of the line.  If\nthe file names contain any variable or function references, they are\nexpanded.  @xref{Using Variables, ,How to Use Variables}.\n\nFor example, if you have three @file{.mk} files, @file{a.mk},\n@file{b.mk}, and @file{c.mk}, and @code{$(bar)} expands to\n@code{bish bash}, then the following expression\n\n@example\ninclude foo *.mk $(bar)\n@end example\n\nis equivalent to\n\n@example\ninclude foo a.mk b.mk c.mk bish bash\n@end example\n\nWhen @code{make} processes an @code{include} directive, it suspends\nreading of the containing makefile and reads from each listed file in\nturn.  When that is finished, @code{make} resumes reading the\nmakefile in which the directive appears.\n\nOne occasion for using @code{include} directives is when several programs,\nhandled by individual makefiles in various directories, need to use a\ncommon set of variable definitions\n(@pxref{Setting, ,Setting Variables}) or pattern rules\n(@pxref{Pattern Rules, ,Defining and Redefining Pattern Rules}).\n\nAnother such occasion is when you want to generate prerequisites from\nsource files automatically; the prerequisites can be put in a file that\nis included by the main makefile.  This practice is generally cleaner\nthan that of somehow appending the prerequisites to the end of the main\nmakefile as has been traditionally done with other versions of\n@code{make}.  @xref{Automatic Prerequisites}.\n@cindex prerequisites, automatic generation\n@cindex automatic generation of prerequisites\n@cindex generating prerequisites automatically\n\n@cindex @code{-I}\n@cindex @code{--include-dir}\n@cindex included makefiles, default directories\n@cindex default directories for included makefiles\n@findex /usr/gnu/include\n@findex /usr/local/include\n@findex /usr/include\nIf the specified name does not start with a slash (or a drive letter and colon\nwhen GNU Make is compiled with MS-DOS / MS-Windows path support), and the file\nis not found in the current directory, several other directories are searched.\nFirst, any directories you have specified with the @samp{-I} or\n@samp{--include-dir} options are searched (@pxref{Options Summary, ,Summary of\nOptions}).  Then the following directories (if they exist) are searched, in\nthis order: @file{@var{prefix}/include} (normally @file{/usr/local/include}\n@footnote{GNU Make compiled for MS-DOS and MS-Windows behaves as if\n@var{prefix} has been defined to be the root of the DJGPP tree hierarchy.})\n@file{/usr/gnu/include}, @file{/usr/local/include}, @file{/usr/include}.\n\nThe @code{.INCLUDE_DIRS} variable will contain the current list of\ndirectories that make will search for included files.  @xref{Special\nVariables, ,Other Special Variables}.\n\nYou can avoid searching in these default directories by adding the\ncommand line option @code{-I} with the special value @code{-} (e.g.,\n@code{-I-}) to the command line.  This will cause @code{make} to\nforget any already-set include directories, including the default\ndirectories.\n\nIf an included makefile cannot be found in any of these directories it is not\nan immediately fatal error; processing of the makefile containing the\n@code{include} continues.  Once it has finished reading makefiles, @code{make}\nwill try to remake any that are out of date or don't exist.  @xref{Remaking\nMakefiles, ,How Makefiles Are Remade}.  Only after it has failed to find a\nrule to remake the makefile, or it found a rule but the recipe failed, will\n@code{make} diagnose the missing makefile as a fatal error.\n\nIf you want @code{make} to simply ignore a makefile which does not exist\nor cannot be remade, with no error message, use the @w{@code{-include}}\ndirective instead of @code{include}, like this:\n\n@example\n-include @var{filenames}@dots{}\n@end example\n\nThis acts like @code{include} in every way except that there is no\nerror (not even a warning) if any of the @var{filenames} (or any\nprerequisites of any of the @var{filenames}) do not exist or cannot be\nremade.\n\nFor compatibility with some other @code{make} implementations,\n@code{sinclude} is another name for @w{@code{-include}}.\n\n@node MAKEFILES Variable\n@section The Variable @code{MAKEFILES}\n@cindex makefile, and @code{MAKEFILES} variable\n@cindex including (@code{MAKEFILES} variable)\n\n@vindex MAKEFILES\nIf the environment variable @code{MAKEFILES} is defined, @code{make}\nconsiders its value as a list of names (separated by whitespace) of\nadditional makefiles to be read before the others.  This works much\nlike the @code{include} directive: various directories are searched\nfor those files (@pxref{Include, ,Including Other Makefiles}).  In\naddition, the default goal is never taken from one of these makefiles\n(or any makefile included by them) and it is not an error if the files\nlisted in @code{MAKEFILES} are not found.\n\n@cindex recursion, and @code{MAKEFILES} variable\nThe main use of @code{MAKEFILES} is in communication between recursive\ninvocations of @code{make} (@pxref{Recursion, ,Recursive Use of\n@code{make}}).  It usually is not desirable to set the environment\nvariable before a top-level invocation of @code{make}, because it is\nusually better not to mess with a makefile from outside.  However, if\nyou are running @code{make} without a specific makefile, a makefile in\n@code{MAKEFILES} can do useful things to help the built-in implicit\nrules work better, such as defining search paths (@pxref{Directory Search}).\n\nSome users are tempted to set @code{MAKEFILES} in the environment\nautomatically on login, and program makefiles to expect this to be done.\nThis is a very bad idea, because such makefiles will fail to work if run by\nanyone else.  It is much better to write explicit @code{include} directives\nin the makefiles.  @xref{Include, , Including Other Makefiles}.\n\n@node Remaking Makefiles\n@section How Makefiles Are Remade\n@cindex updating makefiles\n@cindex remaking makefiles\n@cindex makefile, remaking of\nSometimes makefiles can be remade from other files, such as RCS or SCCS\nfiles.  If a makefile can be remade from other files, you probably want\n@code{make} to get an up-to-date version of the makefile to read in.\n\nTo this end, after reading in all makefiles @code{make} will consider\neach as a goal target, in the order in which they were processed, and\nattempt to update it.  If parallel builds (@pxref{Parallel, ,Parallel\nExecution}) are enabled then makefiles will be rebuilt in parallel as\nwell.\n\nIf a makefile has a rule which says how to update it (found either in\nthat very makefile or in another one) or if an implicit rule applies\nto it (@pxref{Implicit Rules, ,Using Implicit Rules}), it will be\nupdated if necessary.  After all makefiles have been checked, if any\nhave actually been changed, @code{make} starts with a clean slate and\nreads all the makefiles over again.  (It will also attempt to update\neach of them over again, but normally this will not change them again,\nsince they are already up to date.)  Each restart will cause the\nspecial variable @code{MAKE_RESTARTS} to be updated (@pxref{Special\nVariables}).\n\nIf you know that one or more of your makefiles cannot be remade and\nyou want to keep @code{make} from performing an implicit rule search\non them, perhaps for efficiency reasons, you can use any normal method\nof preventing implicit rule look-up to do so.  For example, you can\nwrite an explicit rule with the makefile as the target, and an empty\nrecipe (@pxref{Empty Recipes, ,Using Empty Recipes}).\n\nIf the makefiles specify a double-colon rule to remake a file with a recipe\nbut no prerequisites, that file will always be remade (@pxref{Double-Colon}).\nIn the case of makefiles, a makefile that has a double-colon rule with a\nrecipe but no prerequisites will be remade every time @code{make} is run, and\nthen again after @code{make} starts over and reads the makefiles in again.\nThis would cause an infinite loop: @code{make} would constantly remake the\nmakefile and restart, and never do anything else.  So, to avoid this,\n@code{make} will @strong{not} attempt to remake makefiles which are specified\nas targets of a double-colon rule with a recipe but no prerequisites.\n\nPhony targets (@pxref{Phony Targets}) have the same effect: they are never\nconsidered up-to-date and so an included file marked as phony would cause\n@code{make} to restart continuously.  To avoid this @code{make} will not\nattempt to remake makefiles which are marked phony.\n\nYou can take advantage of this to optimize startup time: if you know you don't\nneed your @file{Makefile} to be remade you can prevent make from trying to\nremake it by adding either:\n\n@example\n.PHONY: Makefile\n@end example\n\nor:\n\n@example\nMakefile:: ;\n@end example\n\nIf you do not specify any makefiles to be read with @samp{-f} or\n@samp{--file} options, @code{make} will try the default makefile names;\n@pxref{Makefile Names, ,What Name to Give Your Makefile}.  Unlike\nmakefiles explicitly requested with @samp{-f} or @samp{--file} options,\n@code{make} is not certain that these makefiles should exist.  However,\nif a default makefile does not exist but can be created by running\n@code{make} rules, you probably want the rules to be run so that the\nmakefile can be used.\n\nTherefore, if none of the default makefiles exists, @code{make} will\ntry to make each of them until it succeeds in making one, or it runs\nout of names to try.  Note that it is not an error if @code{make}\ncannot find or make any makefile; a makefile is not always\nnecessary.\n\nWhen you use the @samp{-t} or @samp{--touch} option\n(@pxref{Instead of Execution, ,Instead of Executing Recipes}),\nyou would not want to use an out-of-date makefile to decide which\ntargets to touch.  So the @samp{-t} option has no effect on updating\nmakefiles; they are really updated even if @samp{-t} is specified.\nLikewise, @samp{-q} (or @samp{--question}) and @samp{-n} (or\n@samp{--just-print}) do not prevent updating of makefiles, because an\nout-of-date makefile would result in the wrong output for other targets.\nThus, @samp{make -f mfile -n foo} will update @file{mfile}, read it in,\nand then print the recipe to update @file{foo} and its prerequisites\nwithout running it.  The recipe printed for @file{foo} will be the one\nspecified in the updated contents of @file{mfile}.\n\nHowever, on occasion you might actually wish to prevent updating of even\nthe makefiles.  You can do this by specifying the makefiles as goals in\nthe command line as well as specifying them as makefiles.  When the\nmakefile name is specified explicitly as a goal, the options @samp{-t}\nand so on do apply to them.\n\nThus, @samp{make -f mfile -n mfile foo} would read the makefile\n@file{mfile}, print the recipe needed to update it without actually\nrunning it, and then print the recipe needed to update @file{foo}\nwithout running that.  The recipe for @file{foo} will be the one\nspecified by the existing contents of @file{mfile}.\n\n@node Overriding Makefiles\n@section Overriding Part of Another Makefile\n\n@cindex overriding makefiles\n@cindex makefile, overriding\nSometimes it is useful to have a makefile that is mostly just like\nanother makefile.  You can often use the @samp{include} directive to\ninclude one in the other, and add more targets or variable definitions.\nHowever, it is invalid for two makefiles to give different recipes for\nthe same target.  But there is another way.\n\n@cindex match-anything rule, used to override\nIn the containing makefile (the one that wants to include the other),\nyou can use a match-anything pattern rule to say that to remake any\ntarget that cannot be made from the information in the containing\nmakefile, @code{make} should look in another makefile.\n@xref{Pattern Rules}, for more information on pattern rules.\n\nFor example, if you have a makefile called @file{Makefile} that says how\nto make the target @samp{foo} (and other targets), you can write a\nmakefile called @file{GNUmakefile} that contains:\n\n@example\nfoo:\n        frobnicate > foo\n\n%: force\n        @@$(MAKE) -f Makefile $@@\nforce: ;\n@end example\n\nIf you say @samp{make foo}, @code{make} will find @file{GNUmakefile},\nread it, and see that to make @file{foo}, it needs to run the recipe\n@samp{frobnicate > foo}.  If you say @samp{make bar}, @code{make} will\nfind no way to make @file{bar} in @file{GNUmakefile}, so it will use the\nrecipe from the pattern rule: @samp{make -f Makefile bar}.  If\n@file{Makefile} provides a rule for updating @file{bar}, @code{make}\nwill apply the rule.  And likewise for any other target that\n@file{GNUmakefile} does not say how to make.\n\nThe way this works is that the pattern rule has a pattern of just\n@samp{%}, so it matches any target whatever.  The rule specifies a\nprerequisite @file{force}, to guarantee that the recipe will be run even\nif the target file already exists.  We give the @file{force} target an\nempty recipe to prevent @code{make} from searching for an implicit rule to\nbuild it---otherwise it would apply the same match-anything rule to\n@file{force} itself and create a prerequisite loop!\n\n@node Reading Makefiles\n@section How @code{make} Reads a Makefile\n@cindex reading makefiles\n@cindex makefile, reading\n\nGNU @code{make} does its work in two distinct phases.  During the\nfirst phase it reads all the makefiles, included makefiles, etc. and\ninternalizes all the variables and their values and implicit and\nexplicit rules, and builds a dependency graph of all the targets and\ntheir prerequisites.  During the second phase, @code{make} uses this\ninternalized data to determine which targets need to be updated and\nrun the recipes necessary to update them.\n\nIt's important to understand this two-phase approach because it has a\ndirect impact on how variable and function expansion happens; this is\noften a source of some confusion when writing makefiles.  Below is a\nsummary of the different constructs that can be found in a makefile,\nand the phase in which expansion happens for each part of the\nconstruct.\n\nWe say that expansion is @dfn{immediate} if it happens during the\nfirst phase: @code{make} will expand that part of the construct as the\nmakefile is parsed.  We say that expansion is @dfn{deferred} if it is\nnot immediate.  Expansion of a deferred construct part is delayed\nuntil the construct is used: either when it is referenced in an\nimmediate context, or when it is needed during the second phase.\n\nYou may not be familiar with some of these constructs yet.  You can\nreference this section as you become familiar with them, in later\nchapters.\n\n@subheading Variable Assignment\n@cindex =, expansion\n@cindex :=, expansion\n@cindex ::=, expansion\n@cindex :::=, expansion\n@cindex !=, expansion\n@cindex +=, expansion\n@cindex define, expansion\n\nVariable definitions are parsed as follows:\n\n@example\n@var{immediate} = @var{deferred}\n@var{immediate} := @var{immediate}\n@var{immediate} ::= @var{immediate}\n@var{immediate} :::= @var{immediate-with-escape}\n@var{immediate} += @var{deferred} or @var{immediate}\n@var{immediate} != @var{immediate}\n\ndefine @var{immediate}\n  @var{deferred}\nendef\n\ndefine @var{immediate} =\n  @var{deferred}\nendef\n\ndefine @var{immediate} :=\n  @var{immediate}\nendef\n\ndefine @var{immediate} ::=\n  @var{immediate}\nendef\n\ndefine @var{immediate} :::=\n  @var{immediate-with-escape}\nendef\n\ndefine @var{immediate} +=\n  @var{deferred} or @var{immediate}\nendef\n\ndefine @var{immediate} !=\n  @var{immediate}\nendef\n@end example\n\nFor the append operator @samp{+=}, the right-hand side is considered\nimmediate if the variable was previously set as a simple variable\n(@samp{:=} or @samp{::=}), and deferred otherwise.\n\nFor the @var{immediate-with-escape} operator @samp{:::=}, the value on\nthe right-hand side is immediately expanded but then escaped (that is,\nall instances of @code{$} in the result of the expansion are replaced\nwith @code{$$}).\n\nFor the shell assignment operator @samp{!=}, the right-hand side is\nevaluated immediately and handed to the shell.  The result is stored\nin the variable named on the left, and that variable is considered a\nrecursively expanded variable (and will thus be re-evaluated on each\nreference).\n\n@subsubheading Conditional Assignment Modifier\n@cindex ?=, expansion\n@cindex ?:=, expansion\n@cindex ?::=, expansion\n@cindex ?:::=, expansion\n@cindex ?!=, expansion\n\nAdding a conditional modifier (@pxref{Conditional Assignment, ,Conditional\nVariable Assignment}) to an assignment operator does not change the expansion\nstyle for that operator: if the variable is not defined then the assignment\nwill be made using expansion as defined above.\n\nIf the variable is already defined, then the right-hand side of the assignment\nis ignored and not expanded.\n\n@subheading Conditional Directives\n@cindex ifdef, expansion\n@cindex ifeq, expansion\n@cindex ifndef, expansion\n@cindex ifneq, expansion\n\nConditional directives are parsed immediately.  This means, for\nexample, that automatic variables cannot be used in conditional\ndirectives, as automatic variables are not set until the recipe for\nthat rule is invoked.  If you need to use automatic variables in a\nconditional directive you @emph{must} move the condition into the\nrecipe and use shell conditional syntax instead.\n\n@subheading Rule Definition\n@cindex target, expansion\n@cindex prerequisite, expansion\n@cindex implicit rule, expansion\n@cindex pattern rule, expansion\n@cindex explicit rule, expansion\n\nA rule is always expanded the same way, regardless of the form:\n\n@example\n@var{immediate} : @var{immediate} ; @var{deferred}\n        @var{deferred}\n@end example\n\nThat is, the target and prerequisite sections are expanded\nimmediately, and the recipe used to build the target is always\ndeferred.  This is true for explicit rules, pattern rules, suffix\nrules, static pattern rules, and simple prerequisite definitions.\n\n@node Parsing Makefiles\n@section How Makefiles Are Parsed\n@cindex parsing makefiles\n@cindex makefiles, parsing\n\nGNU @code{make} parses makefiles line-by-line.  Parsing proceeds using\nthe following steps:\n\n@enumerate\n@item\nRead in a full logical line, including backslash-escaped lines\n(@pxref{Splitting Lines, , Splitting Long Lines}).\n\n@item\nRemove comments (@pxref{Makefile Contents, , What Makefiles Contain}).\n\n@item\nIf the line begins with the recipe prefix character and we are in a\nrule context, add the line to the current recipe and read the next\nline (@pxref{Recipe Syntax}).\n\n@item\nExpand elements of the line which appear in an @emph{immediate}\nexpansion context (@pxref{Reading Makefiles, , How @code{make} Reads a\nMakefile}).\n\n@item\nScan the line for a separator character, such as @samp{:} or @samp{=},\nto determine whether the line is a macro assignment or a rule\n(@pxref{Recipe Syntax}).\n\n@item\nInternalize the resulting operation and read the next line.\n@end enumerate\n\nAn important consequence of this is that a macro can expand to an\nentire rule, @emph{if it is one line long}.  This will work:\n\n@example\nmyrule = target : ; echo built\n\n$(myrule)\n@end example\n\nHowever, this will not work because @code{make} does not re-split lines\nafter it has expanded them:\n\n@example\ndefine myrule\ntarget:\n        echo built\nendef\n\n$(myrule)\n@end example\n\nThe above makefile results in the definition of a target @samp{target}\nwith prerequisites @samp{echo} and @samp{built}, as if the makefile\ncontained @code{target: echo built}, rather than a rule with a recipe.\nNewlines still present in a line after expansion is complete are\nignored as normal whitespace.\n\nIn order to properly expand a multi-line macro you must use the\n@code{eval} function: this causes the @code{make} parser to be run on\nthe results of the expanded macro (@pxref{Eval Function}).\n\n@node Secondary Expansion\n@section Secondary Expansion\n@cindex secondary expansion\n@cindex expansion, secondary\n\n@findex .SECONDEXPANSION\nPreviously we learned that GNU @code{make} works in two distinct\nphases: a read-in phase and a target-update phase (@pxref{Reading\nMakefiles, , How @code{make} Reads a Makefile}).  GNU Make also has\nthe ability to enable a @emph{second expansion} of the prerequisites\n(only) for some or all targets defined in the makefile.  In order for\nthis second expansion to occur, the special target\n@code{.SECONDEXPANSION} must be defined before the first prerequisite\nlist that makes use of this feature.\n\nIf @code{.SECONDEXPANSION} is defined then when GNU @code{make} needs to check\nthe prerequisites of a target, the prerequisites are expanded a @emph{second\ntime}.  In most circumstances this secondary expansion will have no effect,\nsince all variable and function references will have been expanded during the\ninitial parsing of the makefiles.  In order to take advantage of the secondary\nexpansion phase of the parser, then, it's necessary to @emph{escape} the\nvariable or function reference in the makefile.  In this case the first\nexpansion merely un-escapes the reference but doesn't expand it, and expansion\nis left to the secondary expansion phase.  For example, consider this\nmakefile:\n\n@example\n.SECONDEXPANSION:\nONEVAR = onefile\nTWOVAR = twofile\nmyfile: $(ONEVAR) $$(TWOVAR)\n@end example\n\nAfter the first expansion phase the prerequisites list of the\n@file{myfile} target will be @code{onefile} and @code{$(TWOVAR)}; the\nfirst (un-escaped) variable reference to @var{ONEVAR} is expanded,\nwhile the second (escaped) variable reference is simply un-escaped,\nwithout being recognized as a variable reference.  Now during the\nsecondary expansion the first word is expanded again but since it\ncontains no variable or function references it remains the value\n@file{onefile}, while the second word is now a normal reference to the\nvariable @var{TWOVAR}, which is expanded to the value @file{twofile}.\nThe final result is that there are two prerequisites, @file{onefile}\nand @file{twofile}.\n\nObviously, this is not a very interesting case since the same result\ncould more easily have been achieved simply by having both variables\nappear, un-escaped, in the prerequisites list.  One difference becomes\napparent if the variables are reset; consider this example:\n\n@example\n.SECONDEXPANSION:\nAVAR = top\nonefile: $(AVAR)\ntwofile: $$(AVAR)\nAVAR = bottom\n@end example\n\nHere the prerequisite of @file{onefile} will be expanded immediately,\nand resolve to the value @file{top}, while the prerequisite of\n@file{twofile} will not be full expanded until the secondary expansion\nand yield a value of @file{bottom}.\n\nThis is marginally more exciting, but the true power of this feature\nonly becomes apparent when you discover that secondary expansions\nalways take place within the scope of the automatic variables for that\ntarget.  This means that you can use variables such as @code{$@@},\n@code{$*}, etc. during the second expansion and they will have their\nexpected values, just as in the recipe.  All you have to do is defer\nthe expansion by escaping the @code{$}.  Also, secondary expansion\noccurs for both explicit and implicit (pattern) rules.  Knowing this,\nthe possible uses for this feature increase dramatically.  For\nexample:\n\n@example\n.SECONDEXPANSION:\nmain_OBJS := main.o try.o test.o\nlib_OBJS := lib.o api.o\n\nmain lib: $$($$@@_OBJS)\n@end example\n\nHere, after the initial expansion the prerequisites of both the\n@file{main} and @file{lib} targets will be @code{$($@@_OBJS)}.  During\nthe secondary expansion, the @code{$@@} variable is set to the name of\nthe target and so the expansion for the @file{main} target will yield\n@code{$(main_OBJS)}, or @code{main.o try.o test.o}, while the\nsecondary expansion for the @file{lib} target will yield\n@code{$(lib_OBJS)}, or @code{lib.o api.o}.\n\nYou can also mix in functions here, as long as they are properly escaped:\n\n@example\nmain_SRCS := main.c try.c test.c\nlib_SRCS := lib.c api.c\n\n.SECONDEXPANSION:\nmain lib: $$(patsubst %.c,%.o,$$($$@@_SRCS))\n@end example\n\nThis version allows users to specify source files rather than object\nfiles, but gives the same resulting prerequisites list as the previous\nexample.\n\nEvaluation of automatic variables during the secondary expansion\nphase, especially of the target name variable @code{$$@@}, behaves\nsimilarly to evaluation within recipes.  However, there are some\nsubtle differences and ``corner cases'' which come into play for the\ndifferent types of rule definitions that @code{make} understands.  The\nsubtleties of using the different automatic variables are described\nbelow.\n\n@subheading Secondary Expansion of Explicit Rules\n@cindex secondary expansion and explicit rules\n@cindex explicit rules, secondary expansion of\n\nDuring the secondary expansion of explicit rules, @code{$$@@} and\n@code{$$%} evaluate, respectively, to the file name of the target and,\nwhen the target is an archive member, the target member name.  The\n@code{$$<} variable evaluates to the first prerequisite in the first\nrule for this target.  @code{$$^} and @code{$$+} evaluate to the list\nof all prerequisites of rules @emph{that have already appeared} for\nthe same target (@code{$$+} with repetitions and @code{$$^}\nwithout).  The following example will help illustrate these behaviors:\n\n@example\n.SECONDEXPANSION:\n\nfoo: foo.1 bar.1 $$< $$^ $$+    # line #1\n\nfoo: foo.2 bar.2 $$< $$^ $$+    # line #2\n\nfoo: foo.3 bar.3 $$< $$^ $$+    # line #3\n@end example\n\nIn the first prerequisite list, all three variables (@code{$$<},\n@code{$$^}, and @code{$$+}) expand to the empty string.  In the\nsecond, they will have values @code{foo.1}, @code{foo.1 bar.1}, and\n@code{foo.1 bar.1} respectively.  In the third they will have values\n@code{foo.1}, @code{foo.1 bar.1 foo.2 bar.2}, and @code{foo.1 bar.1\nfoo.2 bar.2 foo.1 foo.1 bar.1 foo.1 bar.1} respectively.\n\nRules undergo secondary expansion in makefile order, except that\nthe rule with the recipe is always evaluated last.\n\nThe variables @code{$$?} and @code{$$*} are not available and expand\nto the empty string.\n\n@subheading Secondary Expansion of Static Pattern Rules\n@cindex secondary expansion and static pattern rules\n@cindex static pattern rules, secondary expansion of\n\nRules for secondary expansion of static pattern rules are identical to\nthose for explicit rules, above, with one exception: for static\npattern rules the @code{$$*} variable is set to the pattern stem.  As\nwith explicit rules, @code{$$?} is not available and expands to the\nempty string.\n\n@subheading Secondary Expansion of Implicit Rules\n@cindex secondary expansion and implicit rules\n@cindex implicit rules, secondary expansion of\n\nAs @code{make} searches for an implicit rule, it substitutes the stem\nand then performs secondary expansion for every rule with a matching\ntarget pattern.  The value of the automatic variables is derived in\nthe same fashion as for static pattern rules.  As an example:\n\n@example\n.SECONDEXPANSION:\n\nfoo: bar\n\nfoo foz: fo%: bo%\n\n%oo: $$< $$^ $$+ $$*\n@end example\n\nWhen the implicit rule is tried for target @file{foo}, @code{$$<}\nexpands to @file{bar}, @code{$$^} expands to @file{bar boo},\n@code{$$+} also expands to @file{bar boo}, and @code{$$*} expands to\n@file{f}.\n\nNote that the directory prefix (D), as described in @ref{Implicit Rule\nSearch, ,Implicit Rule Search Algorithm}, is appended (after\nexpansion) to all the patterns in the prerequisites list.  As an\nexample:\n\n@example\n.SECONDEXPANSION:\n\n/tmp/foo.o:\n\n%.o: $$(addsuffix /%.c,foo bar) foo.h\n        @@echo $^\n@end example\n\nThe prerequisite list printed, after the secondary expansion and\ndirectory prefix reconstruction, will be @file{/tmp/foo/foo.c\n/tmp/bar/foo.c foo.h}.  If you are not interested in this\nreconstruction, you can use @code{$$*} instead of @code{%} in the\nprerequisites list.\n\n@node Rules\n@chapter Writing Rules\n@cindex writing rules\n@cindex rule, how to write\n@cindex target\n@cindex prerequisite\n\nA @dfn{rule} appears in the makefile and says when and how to remake\ncertain files, called the rule's @dfn{targets} (most often only one per rule).\nIt lists the other files that are the @dfn{prerequisites} of the target, and\nthe @dfn{recipe} to use to create or update the target.\n\n@cindex default goal\n@cindex goal, default\nThe order of rules is not significant, except for determining the @dfn{default\ngoal}: the target for @code{make} to consider, if you do not otherwise specify\none.  The default goal is the first target of the first rule in the first\nmakefile.  There are two exceptions: a target starting with a period is not a\ndefault unless it also contains one or more slashes, @samp{/}; and, a target\nthat defines a pattern rule has no effect on the default goal.  (@xref{Pattern\nRules, ,Defining and Redefining Pattern Rules}.)\n\nTherefore, we usually write the makefile so that the first rule is the\none for compiling the entire program or all the programs described by\nthe makefile (often with a target called @samp{all}).\n@xref{Goals, ,Arguments to Specify the Goals}.\n\n@menu\n* Rule Example::                An example explained.\n* Rule Syntax::                 General syntax explained.\n* Prerequisite Types::          There are two types of prerequisites.\n* Wildcards::                   Using wildcard characters such as `*'.\n* Directory Search::            Searching other directories for source files.\n* Phony Targets::               Using a target that is not a real file's name.\n* Force Targets::               You can use a target without a recipe\n                                  or prerequisites to mark other targets\n                                  as phony.\n* Empty Targets::               When only the date matters and the\n                                  files are empty.\n* Special Targets::             Targets with special built-in meanings.\n* Multiple Targets::            When to make use of several targets in a rule.\n* Multiple Rules::              How to use several rules with the same target.\n* Static Pattern::              Static pattern rules apply to multiple targets\n                                  and can vary the prerequisites according to\n                                  the target name.\n* Double-Colon::                How to use a special kind of rule to allow\n                                  several independent rules for one target.\n* Automatic Prerequisites::     How to automatically generate rules giving\n                                  prerequisites from source files themselves.\n@end menu\n\n@ifnottex\n@node Rule Example\n@section Rule Example\n\nHere is an example of a rule:\n\n@example\nfoo.o : foo.c defs.h       # module for twiddling the frobs\n        cc -c -g foo.c\n@end example\n\nIts target is @file{foo.o} and its prerequisites are @file{foo.c} and\n@file{defs.h}.  It has one command in the recipe: @samp{cc -c -g foo.c}.\nThe recipe starts with a tab to identify it as a recipe.\n\nThis rule says two things:\n\n@itemize @bullet\n@item\nHow to decide whether @file{foo.o} is out of date: it is out of date\nif it does not exist, or if either @file{foo.c} or @file{defs.h} is\nmore recent than it.\n\n@item\nHow to update the file @file{foo.o}: by running @code{cc} as stated.\nThe recipe does not explicitly mention @file{defs.h}, but we presume\nthat @file{foo.c} includes it, and that is why @file{defs.h} was added\nto the prerequisites.\n@end itemize\n@end ifnottex\n\n@node Rule Syntax\n@section Rule Syntax\n\n@cindex rule syntax\n@cindex syntax of rules\nIn general, a rule looks like this:\n\n@example\n@var{targets} : @var{prerequisites}\n        @var{recipe}\n        @dots{}\n@end example\n\n@noindent\nor like this:\n\n@example\n@var{targets} : @var{prerequisites} ; @var{recipe}\n        @var{recipe}\n        @dots{}\n@end example\n\n@cindex targets\n@cindex rule targets\nThe @var{targets} are file names, separated by spaces.  Wildcard\ncharacters may be used (@pxref{Wildcards, ,Using Wildcard Characters\nin File Names}) and a name of the form @file{@var{a}(@var{m})}\nrepresents member @var{m} in archive file @var{a}\n(@pxref{Archive Members, ,Archive Members as Targets}).\nUsually there is only one\ntarget per rule, but occasionally there is a reason to have more\n(@pxref{Multiple Targets, , Multiple Targets in a Rule}).\n\n@cindex recipes\n@cindex tab character (in commands)\nThe @var{recipe} lines start with a tab character (or the first\ncharacter in the value of the @code{.RECIPEPREFIX} variable;\n@pxref{Special Variables}).  The first recipe line may appear on the line\nafter the prerequisites, with a tab character, or may appear on the\nsame line, with a semicolon.  Either way, the effect is the same.\nThere are other differences in the syntax of recipes.\n@xref{Recipes, ,Writing Recipes in Rules}.\n\n@cindex dollar sign (@code{$}), in rules\n@cindex @code{$}, in rules\n@cindex rules, and @code{$}\nBecause dollar signs are used to start @code{make} variable\nreferences, if you really want a dollar sign in a target or\nprerequisite you must write two of them, @samp{$$} (@pxref{Using\nVariables, ,How to Use Variables}).  If you have enabled secondary\nexpansion (@pxref{Secondary Expansion}) and you want a literal dollar\nsign in the prerequisites list, you must actually write @emph{four}\ndollar signs (@samp{$$$$}).\n\nYou may split a long line by inserting a backslash followed by a\nnewline, but this is not required, as @code{make} places no limit on\nthe length of a line in a makefile.\n\nA rule tells @code{make} two things: when the targets are out of date,\nand how to update them when necessary.\n\n@cindex prerequisites\n@cindex rule prerequisites\nThe criterion for being out of date is specified in terms of the\n@var{prerequisites}, which consist of file names separated by spaces.\n(Wildcards and archive members (@pxref{Archives}) are allowed here too.)\nA target is out of date if it does not exist or if it is older than any\nof the prerequisites (by comparison of last-modification times).  The\nidea is that the contents of the target file are computed based on\ninformation in the prerequisites, so if any of the prerequisites changes,\nthe contents of the existing target file are no longer necessarily\nvalid.\n\nHow to update is specified by a @var{recipe}.  This is one or more\nlines to be executed by the shell (normally @samp{sh}), but with some\nextra features (@pxref{Recipes, ,Writing Recipes in Rules}).\n\n@node Prerequisite Types\n@comment  node-name,  next,  previous,  up\n@section Types of Prerequisites\n@cindex prerequisite types\n@cindex types of prerequisites\n\n@cindex prerequisites, normal\n@cindex normal prerequisites\n@cindex prerequisites, order-only\n@cindex order-only prerequisites\nThere are two different types of prerequisites understood by GNU @code{make}:\nnormal prerequisites, described in the previous section, and @dfn{order-only}\nprerequisites.  A normal prerequisite makes two statements: first, it imposes\nan order in which recipes will be invoked: the recipes for all prerequisites\nof a target will be completed before the recipe for the target is started.\nSecond, it imposes a dependency relationship: if any prerequisite is newer\nthan the target, then the target is considered out-of-date and must be\nrebuilt.\n\nNormally, this is exactly what you want: if a target's prerequisite is\nupdated, then the target should also be updated.\n\nOccasionally you may want to ensure that a prerequisite is built before a\ntarget, but @emph{without} forcing the target to be updated if the\nprerequisite is updated.  @dfn{Order-only} prerequisites are used to create\nthis type of relationship.  Order-only prerequisites can be specified by\nplacing a pipe symbol (@code{|}) in the prerequisites list: any prerequisites\nto the left of the pipe symbol are normal; any prerequisites to the right are\norder-only:\n\n@example\n@var{targets} : @var{normal-prerequisites} | @var{order-only-prerequisites}\n@end example\n\nThe normal prerequisites section may of course be empty.  Also, you\nmay still declare multiple lines of prerequisites for the same target:\nthey are appended appropriately (normal prerequisites are appended to\nthe list of normal prerequisites; order-only prerequisites are\nappended to the list of order-only prerequisites).  Note that if you\ndeclare the same file to be both a normal and an order-only\nprerequisite, the normal prerequisite takes precedence (since they\nhave a strict superset of the behavior of an order-only prerequisite).\n\nOrder-only prerequisites are never checked when determining if the\ntarget is out of date; even order-only prerequisites marked as phony\n(@pxref{Phony Targets}) will not cause the target to be rebuilt.\n\nConsider an example where your targets are to be placed in a separate\ndirectory, and that directory might not exist before @code{make} is\nrun.  In this situation, you want the directory to be created before\nany targets are placed into it but, because the timestamps on\ndirectories change whenever a file is added, removed, or renamed, we\ncertainly don't want to rebuild all the targets whenever the\ndirectory's timestamp changes.  One way to manage this is with\norder-only prerequisites: make the directory an order-only\nprerequisite on all the targets:\n\n@example\nOBJDIR := objdir\nOBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)\n\n$(OBJDIR)/%.o : %.c\n        $(COMPILE.c) $(OUTPUT_OPTION) $<\n\nall: $(OBJS)\n\n$(OBJS): | $(OBJDIR)\n\n$(OBJDIR):\n        mkdir $(OBJDIR)\n@end example\n\nNow the rule to create the @file{objdir} directory will be run, if\nneeded, before any @samp{.o} is built, but no @samp{.o} will be built\nbecause the @file{objdir} directory timestamp changed.\n\n@node Wildcards\n@section Using Wildcard Characters in File Names\n@cindex wildcard\n@cindex file name with wildcards\n@cindex globbing (wildcards)\n\n@cindex @code{*} (wildcard character)\n@cindex @code{?} (wildcard character)\n@cindex @code{[@dots{}]} (wildcard characters)\nA single file name can specify many files using @dfn{wildcard characters}.\nThe wildcard characters in @code{make} are @samp{*}, @samp{?} and\n@samp{[@dots{}]}, the same as in the Bourne shell.  For example, @file{*.c}\nspecifies a list of all the files (in the working directory) whose names\nend in @samp{.c}.\n\nIf an expression matches multiple files then the results will be\nsorted.@footnote{Some older versions of GNU @code{make} did not sort the\nresults of wildcard expansion.}  However multiple expressions will not be\nglobally sorted.  For example, @file{*.c *.h} will list all the files whose\nnames end in @samp{.c}, sorted, followed by all the files whose names end in\n@samp{.h}, sorted.\n\n@cindex @code{~} (tilde)\n@cindex tilde (@code{~})\n@cindex home directory\nThe character @samp{~} at the beginning of a file name also has special\nsignificance.  If alone, or followed by a slash, it represents your home\ndirectory.  For example @file{~/bin} expands to @file{/home/you/bin}.\nIf the @samp{~} is followed by a word, the string represents the home\ndirectory of the user named by that word.  For example @file{~john/bin}\nexpands to @file{/home/john/bin}.  On systems which don't have a home\ndirectory for each user (such as MS-DOS or MS-Windows), this\nfunctionality can be simulated by setting the environment variable\n@var{HOME}.\n\nWildcard expansion is performed by @code{make} automatically in\ntargets and in prerequisites.  In recipes, the shell is responsible\nfor wildcard expansion.  In other contexts, wildcard expansion happens\nonly if you request it explicitly with the @code{wildcard} function.\n\nThe special significance of a wildcard character can be turned off by\npreceding it with a backslash.  Thus, @file{foo\\*bar} would refer to a\nspecific file whose name consists of @samp{foo}, an asterisk, and\n@samp{bar}.\n\n@menu\n* Wildcard Examples::           Several examples.\n* Wildcard Pitfall::            Problems to avoid.\n* Wildcard Function::           How to cause wildcard expansion where\n                                  it does not normally take place.\n@end menu\n\n@node Wildcard Examples\n@subsection Wildcard Examples\n\nWildcards can be used in the recipe of a rule, where they are expanded\nby the shell.  For example, here is a rule to delete all the object files:\n\n@example\n@group\nclean:\n        rm -f *.o\n@end group\n@end example\n@cindex @code{rm} (shell command)\n\nWildcards are also useful in the prerequisites of a rule.  With the\nfollowing rule in the makefile, @samp{make print} will print all the\n@samp{.c} files that have changed since the last time you printed them:\n\n@example\nprint: *.c\n        lpr -p $?\n        touch print\n@end example\n\n@cindex @code{print} target\n@cindex @code{lpr} (shell command)\n@cindex @code{touch} (shell command)\n@noindent\nThis rule uses @file{print} as an empty target file; see @ref{Empty\nTargets, ,Empty Target Files to Record Events}.  (The automatic variable\n@samp{$?} is used to print only those files that have changed; see\n@ref{Automatic Variables}.)\n\nWildcard expansion does not happen when you define a variable.  Thus, if\nyou write this:\n\n@example\nobjects = *.o\n@end example\n\n@noindent\nthen the value of the variable @code{objects} is the actual string\n@samp{*.o}.  However, if you use the value of @code{objects} in a\ntarget or prerequisite, wildcard expansion will take place there.  If\nyou use the value of @code{objects} in a recipe, the shell may perform\nwildcard expansion when the recipe runs.  To set @code{objects} to the\nexpansion, instead use:\n\n@example\nobjects := $(wildcard *.o)\n@end example\n\n@noindent\n@xref{Wildcard Function}.\n\n@node Wildcard Pitfall\n@subsection Pitfalls of Using Wildcards\n@cindex wildcard pitfalls\n@cindex pitfalls of wildcards\n@cindex mistakes with wildcards\n@cindex errors with wildcards\n@cindex problems with wildcards\n\nNow here is an example of a naive way of using wildcard expansion, that\ndoes not do what you would intend.  Suppose you would like to say that the\nexecutable file @file{foo} is made from all the object files in the\ndirectory, and you write this:\n\n@example\nobjects = *.o\n\nfoo : $(objects)\n        cc -o foo $(CFLAGS) $(objects)\n@end example\n\n@noindent\nThe value of @code{objects} is the actual string @samp{*.o}.  Wildcard\nexpansion happens in the rule for @file{foo}, so that each @emph{existing}\n@samp{.o} file becomes a prerequisite of @file{foo} and will be recompiled if\nnecessary.\n\nBut what if you delete all the @samp{.o} files?  When a wildcard matches\nno files, it is left as it is, so then @file{foo} will depend on the\noddly-named file @file{*.o}.  Since no such file is likely to exist,\n@code{make} will give you an error saying it cannot figure out how to\nmake @file{*.o}.  This is not what you want!\n\nActually it is possible to obtain the desired result with wildcard\nexpansion, but you need more sophisticated techniques, including the\n@code{wildcard} function and string substitution.\n@ifnottex\n@xref{Wildcard Function, ,The Function @code{wildcard}}.\n@end ifnottex\n@iftex\nThese are described in the following section.\n@end iftex\n\n@cindex wildcards and MS-DOS/MS-Windows backslashes\n@cindex backslashes in pathnames and wildcard expansion\n\nMicrosoft operating systems (MS-DOS and MS-Windows) use backslashes to\nseparate directories in pathnames, like so:\n\n@example\n  c:\\foo\\bar\\baz.c\n@end example\n\nThis is equivalent to the Unix-style @file{c:/foo/bar/baz.c} (the\n@file{c:} part is the so-called drive letter).  When @code{make} runs on\nthese systems, it supports backslashes as well as the Unix-style forward\nslashes in pathnames.  However, this support does @emph{not} include the\nwildcard expansion, where backslash is a quote character.  Therefore,\nyou @emph{must} use Unix-style slashes in these cases.\n\n\n@node Wildcard Function\n@subsection The Function @code{wildcard}\n@findex wildcard\n\nWildcard expansion happens automatically in rules.  But wildcard expansion\ndoes not normally take place when a variable is set, or inside the\narguments of a function.  If you want to do wildcard expansion in such\nplaces, you need to use the @code{wildcard} function, like this:\n\n@example\n$(wildcard @var{pattern}@dots{})\n@end example\n\n@noindent\nThis string, used anywhere in a makefile, is replaced by a\nspace-separated list of names of existing files that match one of the\ngiven file name patterns.  If no existing file name matches a pattern,\nthen that pattern is omitted from the output of the @code{wildcard}\nfunction.  Note that this is different from how unmatched wildcards\nbehave in rules, where they are used verbatim rather than ignored\n(@pxref{Wildcard Pitfall}).\n\nAs with wildcard expansion in rules, the results of the @code{wildcard}\nfunction are sorted.  But again, each individual expression is sorted\nseparately, so @samp{$(wildcard *.c *.h)} will expand to all files matching\n@samp{.c}, sorted, followed by all files matching @samp{.h}, sorted.\n\nOne use of the @code{wildcard} function is to get a list of all the C source\nfiles in a directory, like this:\n\n@example\n$(wildcard *.c)\n@end example\n\nWe can change the list of C source files into a list of object files by\nreplacing the @samp{.c} suffix with @samp{.o} in the result, like this:\n\n@example\n$(patsubst %.c,%.o,$(wildcard *.c))\n@end example\n\n@noindent\n(Here we have used another function, @code{patsubst}.\n@xref{Text Functions, ,Functions for String Substitution and Analysis}.)\n\nThus, a makefile to compile all C source files in the directory and then\nlink them together could be written as follows:\n\n@example\nobjects := $(patsubst %.c,%.o,$(wildcard *.c))\n\nfoo : $(objects)\n        cc -o foo $(objects)\n@end example\n\n@noindent\n(This takes advantage of the implicit rule for compiling C programs, so\nthere is no need to write explicit rules for compiling the files.\n@xref{Flavors, ,The Two Flavors of Variables}, for an explanation of\n@samp{:=}, which is a variant of @samp{=}.)\n\n@node Directory Search\n@section Searching Directories for Prerequisites\n@cindex vpath\n@cindex search path for prerequisites (@code{VPATH})\n@cindex directory search (@code{VPATH})\n\nFor large systems, it is often desirable to put sources in a separate\ndirectory from the binaries.  The @dfn{directory search} features of\n@code{make} facilitate this by searching several directories\nautomatically to find a prerequisite.  When you redistribute the files\namong directories, you do not need to change the individual rules,\njust the search paths.\n\n@menu\n* General Search::              Specifying a search path that applies\n                                  to every prerequisite.\n* Selective Search::            Specifying a search path\n                                  for a specified class of names.\n* Search Algorithm::            When and how search paths are applied.\n* Recipes/Search::              How to write recipes that work together\n                                  with search paths.\n* Implicit/Search::             How search paths affect implicit rules.\n* Libraries/Search::            Directory search for link libraries.\n@end menu\n\n@node General Search\n@subsection @code{VPATH}: Search Path for All Prerequisites\n@vindex VPATH\n\nThe value of the @code{make} variable @code{VPATH} specifies a list of\ndirectories that @code{make} should search.  Most often, the\ndirectories are expected to contain prerequisite files that are not in the\ncurrent directory; however, @code{make} uses @code{VPATH} as a search\nlist for both prerequisites and targets of rules.\n\nThus, if a file that is listed as a target or prerequisite does not exist\nin the current directory, @code{make} searches the directories listed in\n@code{VPATH} for a file with that name.  If a file is found in one of\nthem, that file may become the prerequisite (see below).  Rules may then\nspecify the names of files in the prerequisite list as if they all\nexisted in the current directory.  @xref{Recipes/Search, ,Writing Recipes with Directory Search}.\n\nIn the @code{VPATH} variable, directory names are separated by colons or\nblanks.  The order in which directories are listed is the order followed\nby @code{make} in its search.  (On MS-DOS and MS-Windows, semi-colons\nare used as separators of directory names in @code{VPATH}, since the\ncolon can be used in the pathname itself, after the drive letter.)\n\nFor example,\n\n@example\nVPATH = src:../headers\n@end example\n\n@noindent\nspecifies a path containing two directories, @file{src} and\n@file{../headers}, which @code{make} searches in that order.\n\nWith this value of @code{VPATH}, the following rule,\n\n@example\nfoo.o : foo.c\n@end example\n\n@noindent\nis interpreted as if it were written like this:\n\n@example\nfoo.o : src/foo.c\n@end example\n\n@noindent\nassuming the file @file{foo.c} does not exist in the current directory but\nis found in the directory @file{src}.\n\n@node Selective Search\n@subsection The @code{vpath} Directive\n@findex vpath\n\nSimilar to the @code{VPATH} variable, but more selective, is the\n@code{vpath} directive (note lower case), which allows you to specify a\nsearch path for a particular class of file names: those that match a\nparticular pattern.  Thus you can supply certain search directories for\none class of file names and other directories (or none) for other file\nnames.\n\nThere are three forms of the @code{vpath} directive:\n\n@table @code\n@item vpath @var{pattern} @var{directories}\nSpecify the search path @var{directories} for file names that match\n@var{pattern}.\n\nThe search path, @var{directories}, is a list of directories to be\nsearched, separated by colons (semi-colons on MS-DOS and MS-Windows) or\nblanks, just like the search path used in the @code{VPATH} variable.\n\n@item vpath @var{pattern}\nClear out the search path associated with @var{pattern}.\n\n@c Extra blank line makes sure this gets two lines.\n@item vpath\n\nClear all search paths previously specified with @code{vpath} directives.\n@end table\n\nA @code{vpath} pattern is a string containing a @samp{%} character.  The\nstring must match the file name of a prerequisite that is being searched\nfor, the @samp{%} character matching any sequence of zero or more\ncharacters (as in pattern rules; @pxref{Pattern Rules, ,Defining and\nRedefining Pattern Rules}).  For example, @code{%.h} matches files that\nend in @code{.h}.  (If there is no @samp{%}, the pattern must match the\nprerequisite exactly, which is not useful very often.)\n\n@cindex @code{%}, quoting in @code{vpath}\n@cindex @code{\\} (backslash), to quote @code{%}\n@cindex backslash (@code{\\}), to quote @code{%}\n@cindex quoting @code{%}, in @code{vpath}\n@samp{%} characters in a @code{vpath} directive's pattern can be quoted\nwith preceding backslashes (@samp{\\}).  Backslashes that would otherwise\nquote @samp{%} characters can be quoted with more backslashes.\nBackslashes that quote @samp{%} characters or other backslashes are\nremoved from the pattern before it is compared to file names.  Backslashes\nthat are not in danger of quoting @samp{%} characters go unmolested.\n\nWhen a prerequisite fails to exist in the current directory, if the\n@var{pattern} in a @code{vpath} directive matches the name of the\nprerequisite file, then the @var{directories} in that directive are searched\njust like (and before) the directories in the @code{VPATH} variable.\n\nFor example,\n\n@example\nvpath %.h ../headers\n@end example\n\n@noindent\ntells @code{make} to look for any prerequisite whose name ends in @file{.h}\nin the directory @file{../headers} if the file is not found in the current\ndirectory.\n\nIf several @code{vpath} patterns match the prerequisite file's name, then\n@code{make} processes each matching @code{vpath} directive one by one,\nsearching all the directories mentioned in each directive.  @code{make}\nhandles multiple @code{vpath} directives in the order in which they\nappear in the makefile; multiple directives with the same pattern are\nindependent of each other.\n\n@need 750\nThus,\n\n@example\n@group\nvpath %.c foo\nvpath %   blish\nvpath %.c bar\n@end group\n@end example\n\n@noindent\nwill look for a file ending in @samp{.c} in @file{foo}, then\n@file{blish}, then @file{bar}, while\n\n@example\n@group\nvpath %.c foo:bar\nvpath %   blish\n@end group\n@end example\n\n@noindent\nwill look for a file ending in @samp{.c} in @file{foo}, then\n@file{bar}, then @file{blish}.\n\n@node Search Algorithm\n@subsection How Directory Searches are Performed\n@cindex algorithm for directory search\n@cindex directory search algorithm\n\nWhen a prerequisite is found through directory search, regardless of type\n(general or selective), the pathname located may not be the one that\n@code{make} actually provides you in the prerequisite list.  Sometimes\nthe path discovered through directory search is thrown away.\n\nThe algorithm @code{make} uses to decide whether to keep or abandon a\npath found via directory search is as follows:\n\n@enumerate\n@item\nIf a target file does not exist at the path specified in the makefile,\ndirectory search is performed.\n\n@item\nIf the directory search is successful, that path is kept and this file\nis tentatively stored as the target.\n\n@item\nAll prerequisites of this target are examined using this same method.\n\n@item\nAfter processing the prerequisites, the target may or may not need to be\nrebuilt:\n\n@enumerate a\n@item\nIf the target does @emph{not} need to be rebuilt, the path to the file\nfound during directory search is used for any prerequisite lists which\ncontain this target.  In short, if @code{make} doesn't need to rebuild\nthe target then you use the path found via directory search.\n\n@item\nIf the target @emph{does} need to be rebuilt (is out-of-date), the\npathname found during directory search is @emph{thrown away}, and the\ntarget is rebuilt using the file name specified in the makefile.  In\nshort, if @code{make} must rebuild, then the target is rebuilt locally,\nnot in the directory found via directory search.\n@end enumerate\n@end enumerate\n\nThis algorithm may seem complex, but in practice it is quite often\nexactly what you want.\n\n@cindex traditional directory search (GPATH)\n@cindex directory search, traditional (GPATH)\nOther versions of @code{make} use a simpler algorithm: if the file does\nnot exist, and it is found via directory search, then that pathname is\nalways used whether or not the target needs to be built.  Thus, if the\ntarget is rebuilt it is created at the pathname discovered during\ndirectory search.\n\n@vindex GPATH\nIf, in fact, this is the behavior you want for some or all of your\ndirectories, you can use the @code{GPATH} variable to indicate this to\n@code{make}.\n\n@code{GPATH} has the same syntax and format as @code{VPATH} (that is, a\nspace- or colon-delimited list of pathnames).  If an out-of-date target\nis found by directory search in a directory that also appears in\n@code{GPATH}, then that pathname is not thrown away.  The target is\nrebuilt using the expanded path.\n\n@node Recipes/Search\n@subsection Writing Recipes with Directory Search\n@cindex recipes, and directory search\n@cindex directory search (@code{VPATH}), and recipes\n\nWhen a prerequisite is found in another directory through directory search,\nthis cannot change the recipe of the rule; they will execute as written.\nTherefore, you must write the recipe with care so that it will look for\nthe prerequisite in the directory where @code{make} finds it.\n\nThis is done with the @dfn{automatic variables} such as @samp{$^}\n(@pxref{Automatic Variables}).\nFor instance, the value of @samp{$^} is a\nlist of all the prerequisites of the rule, including the names of\nthe directories in which they were found, and the value of\n@samp{$@@} is the target.  Thus:\n\n@example\nfoo.o : foo.c\n        cc -c $(CFLAGS) $^ -o $@@\n@end example\n\n@noindent\n(The variable @code{CFLAGS} exists so you can specify flags for C\ncompilation by implicit rules; we use it here for consistency so it will\naffect all C compilations uniformly;\n@pxref{Implicit Variables, ,Variables Used by Implicit Rules}.)\n\nOften the prerequisites include header files as well, which you do not\nwant to mention in the recipe.  The automatic variable @samp{$<} is\njust the first prerequisite:\n\n@example\nVPATH = src:../headers\nfoo.o : foo.c defs.h hack.h\n        cc -c $(CFLAGS) $< -o $@@\n@end example\n\n@node Implicit/Search\n@subsection Directory Search and Implicit Rules\n@cindex @code{VPATH}, and implicit rules\n@cindex directory search (@code{VPATH}), and implicit rules\n@cindex search path for prerequisites (@code{VPATH}), and implicit rules\n@cindex implicit rule, and directory search\n@cindex implicit rule, and @code{VPATH}\n@cindex rule, implicit, and directory search\n@cindex rule, implicit, and @code{VPATH}\n\nThe search through the directories specified in @code{VPATH} or with\n@code{vpath} also happens during consideration of implicit rules\n(@pxref{Implicit Rules, ,Using Implicit Rules}).\n\nFor example, when a file @file{foo.o} has no explicit rule, @code{make}\nconsiders implicit rules, such as the built-in rule to compile\n@file{foo.c} if that file exists.  If such a file is lacking in the\ncurrent directory, the appropriate directories are searched for it.  If\n@file{foo.c} exists (or is mentioned in the makefile) in any of the\ndirectories, the implicit rule for C compilation is applied.\n\nThe recipes of implicit rules normally use automatic variables as a\nmatter of necessity; consequently they will use the file names found by\ndirectory search with no extra effort.\n\n@node Libraries/Search\n@subsection Directory Search for Link Libraries\n@cindex link libraries, and directory search\n@cindex libraries for linking, directory search\n@cindex directory search (@code{VPATH}), and link libraries\n@cindex @code{VPATH}, and link libraries\n@cindex search path for prerequisites (@code{VPATH}), and link libraries\n@cindex @code{-l} (library search)\n@cindex link libraries, patterns matching\n@cindex @code{.LIBPATTERNS}, and link libraries\n@vindex .LIBPATTERNS\n\nDirectory search applies in a special way to libraries used with the\nlinker.  This special feature comes into play when you write a prerequisite\nwhose name is of the form @samp{-l@var{name}}.  (You can tell something\nstrange is going on here because the prerequisite is normally the name of a\nfile, and the @emph{file name} of a library generally looks like\n@file{lib@var{name}.a}, not like @samp{-l@var{name}}.)\n\nWhen a prerequisite's name has the form @samp{-l@var{name}}, @code{make}\nhandles it specially by searching for the file @file{lib@var{name}.so},\nand, if it is not found, for the file @file{lib@var{name}.a} in the current\ndirectory, in directories specified by matching @code{vpath}\nsearch paths and the @code{VPATH} search path, and then in the\ndirectories @file{/lib}, @file{/usr/lib}, and @file{@var{prefix}/lib}\n(normally @file{/usr/local/lib}, but MS-DOS/MS-Windows versions of\n@code{make} behave as if @var{prefix} is defined to be the root of the\nDJGPP installation tree).\n\nFor example, if there is a @file{/usr/lib/libcurses.a} library on your\nsystem (and no @file{/usr/lib/libcurses.so} file), then\n\n@example\n@group\nfoo : foo.c -lcurses\n        cc $^ -o $@@\n@end group\n@end example\n\n@noindent\nwould cause the command @samp{cc foo.c /usr/lib/libcurses.a -o foo} to\nbe executed when @file{foo} is older than @file{foo.c} or than\n@file{/usr/lib/libcurses.a}.\n\nAlthough the default set of files to be searched for is\n@file{lib@var{name}.so} and @file{lib@var{name}.a}, this is customizable\nvia the @code{.LIBPATTERNS} variable.  Each word in the value of this\nvariable is a pattern string.  When a prerequisite like\n@samp{-l@var{name}} is seen, @code{make} will replace the percent in\neach pattern in the list with @var{name} and perform the above directory\nsearches using each library file name.\n\nThe default value for @code{.LIBPATTERNS} is @samp{lib%.so lib%.a},\nwhich provides the default behavior described above.\n\nYou can turn off link library expansion completely by setting this\nvariable to an empty value.\n\n@node Phony Targets\n@section Phony Targets\n@cindex phony targets\n@cindex targets, phony\n@cindex targets without a file\n\nA phony target is one that is not really the name of a file; rather it\nis just a name for a recipe to be executed when you make an explicit\nrequest.  There are two reasons to use a phony target: to avoid a\nconflict with a file of the same name, and to improve performance.\n\nIf you write a rule whose recipe will not create the target file, the\nrecipe will be executed every time the target comes up for remaking.\nHere is an example:\n\n@example\n@group\nclean:\n        rm *.o temp\n@end group\n@end example\n\n@noindent\nBecause the @code{rm} command does not create a file named @file{clean},\nprobably no such file will ever exist.  Therefore, the @code{rm} command\nwill be executed every time you say @samp{make clean}.\n@cindex @code{rm} (shell command)\n\n@cindex using .PHONY\nIn this example, the @file{clean} target will not work properly if a\nfile named @file{clean} is ever created in this directory.  Since it\nhas no prerequisites, @file{clean} would always be considered up to\ndate and its recipe would not be executed.  To avoid this problem you\ncan explicitly declare the target to be phony by making it a\nprerequisite of the special target @code{.PHONY}\n(@pxref{Special Targets, ,Special Built-in Target Names}) as follows:\n\n@example\n@group\n.PHONY: clean\nclean:\n        rm *.o temp\n@end group\n@end example\n\n@noindent\nOnce this is done, @samp{make clean} will run the recipe regardless of\nwhether there is a file named @file{clean}.\n\nPrerequisites of @code{.PHONY} are always interpreted as literal\ntarget names, never as patterns (even if they contain @samp{%}\ncharacters).  To always rebuild a pattern rule consider using a\n``force target'' (@pxref{Force Targets, ,Rules without Recipes or\nPrerequisites}).\n\nPhony targets are also useful in conjunction with recursive\ninvocations of @code{make} (@pxref{Recursion, ,Recursive Use of @code{make}}).\nIn this situation the makefile will often contain a variable which\nlists a number of sub-directories to be built.  A simplistic way to\nhandle this is to define one rule with a recipe that loops over the\nsub-directories, like this:\n\n@example\n@group\nSUBDIRS = foo bar baz\n\nsubdirs:\n        for dir in $(SUBDIRS); do \\\n          $(MAKE) -C $$dir; \\\n        done\n@end group\n@end example\n\nThere are problems with this method, however.  First, any error detected in a\nsub-make is ignored by this rule, so it will continue to build the rest of the\ndirectories even when one fails.  This can be overcome by adding shell\ncommands to note the error and exit, but then it will do so even if\n@code{make} is invoked with the @code{-k} option, which is unfortunate.\nSecond, and perhaps more importantly, you cannot take full advantage of\n@code{make}'s ability to build targets in parallel (@pxref{Parallel, ,Parallel\nExecution}), since there is only one rule.  Each individual makefile's targets\nwill be built in parallel, but only one sub-directory will be built at a time.\n\nBy declaring the sub-directories as @code{.PHONY} targets (you must do\nthis as the sub-directory obviously always exists; otherwise it won't\nbe built) you can remove these problems:\n\n@example\n@group\nSUBDIRS = foo bar baz\n\n.PHONY: subdirs $(SUBDIRS)\n\nsubdirs: $(SUBDIRS)\n\n$(SUBDIRS):\n        $(MAKE) -C $@@\n\nfoo: baz\n@end group\n@end example\n\nHere we've also declared that the @file{foo} sub-directory cannot be\nbuilt until after the @file{baz} sub-directory is complete; this kind of\nrelationship declaration is particularly important when attempting\nparallel builds.\n\nThe implicit rule search (@pxref{Implicit Rules}) is skipped for\n@code{.PHONY} targets.  This is why declaring a target as\n@code{.PHONY} is good for performance, even if you are not worried\nabout the actual file existing.\n\nA phony target should not be a prerequisite of a real target file; if it is,\nits recipe will be run every time @code{make} considers that file.  As long as\na phony target is never a prerequisite of a real target, the phony target\nrecipe will be executed only when the phony target is a specified goal\n(@pxref{Goals, ,Arguments to Specify the Goals}).\n\nYou should not declare an included makefile as phony.  Phony targets are not\nintended to represent real files, and because the target is always considered\nout of date make will always rebuild it then re-execute itself\n(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}).  To avoid this,\n@code{make} will not re-execute itself if an included file marked as phony is\nre-built.\n\nPhony targets can have prerequisites.  When one directory contains multiple\nprograms, it is most convenient to describe all of the programs in one\nmakefile @file{./Makefile}.  Since the target remade by default will be the\nfirst one in the makefile, it is common to make this a phony target named\n@samp{all} and give it, as prerequisites, all the individual programs.  For\nexample:\n\n@example\nall : prog1 prog2 prog3\n.PHONY : all\n\nprog1 : prog1.o utils.o\n        cc -o prog1 prog1.o utils.o\n\nprog2 : prog2.o\n        cc -o prog2 prog2.o\n\nprog3 : prog3.o sort.o utils.o\n        cc -o prog3 prog3.o sort.o utils.o\n@end example\n\n@noindent\nNow you can say just @samp{make} to remake all three programs, or\nspecify as arguments the ones to remake (as in @samp{make prog1\nprog3}).  Phoniness is not inherited: the prerequisites of a phony\ntarget are not themselves phony, unless explicitly declared to be so.\n\nWhen one phony target is a prerequisite of another, it serves as a subroutine\nof the other.  For example, here @samp{make cleanall} will delete the\nobject files, the difference files, and the file @file{program}:\n\n@example\n.PHONY: cleanall cleanobj cleandiff\n\ncleanall : cleanobj cleandiff\n        rm program\n\ncleanobj :\n        rm *.o\n\ncleandiff :\n        rm *.diff\n@end example\n\n@node Force Targets\n@section Rules without Recipes or Prerequisites\n@cindex force targets\n@cindex targets, force\n@cindex @code{FORCE}\n@cindex rule, no recipe or prerequisites\n\nIf a rule has no prerequisites or recipe, and the target of the rule\nis a nonexistent file, then @code{make} imagines this target to have\nbeen updated whenever its rule is run.  This implies that all targets\ndepending on this one will always have their recipe run.\n\nAn example will illustrate this:\n\n@example\n@group\nclean: FORCE\n        rm $(objects)\nFORCE:\n@end group\n@end example\n\nHere the target @samp{FORCE} satisfies the special conditions, so the\ntarget @file{clean} that depends on it is forced to run its recipe.\nThere is nothing special about the name @samp{FORCE}, but that is one\nname commonly used this way.\n\nAs you can see, using @samp{FORCE} this way has the same results as using\n@samp{.PHONY: clean}.\n\nUsing @samp{.PHONY} is more explicit and more efficient.  However,\nother versions of @code{make} do not support @samp{.PHONY}; thus\n@samp{FORCE} appears in many makefiles.  @xref{Phony Targets}.\n\n@node Empty Targets\n@section Empty Target Files to Record Events\n@cindex empty targets\n@cindex targets, empty\n@cindex recording events with empty targets\n\nThe @dfn{empty target} is a variant of the phony target; it is used to hold\nrecipes for an action that you request explicitly from time to time.\nUnlike a phony target, this target file can really exist; but the file's\ncontents do not matter, and usually are empty.\n\nThe purpose of the empty target file is to record, with its\nlast-modification time, when the rule's recipe was last executed.  It\ndoes so because one of the commands in the recipe is a @code{touch}\ncommand to update the target file.\n\nThe empty target file should have some prerequisites (otherwise it\ndoesn't make sense).  When you ask to remake the empty target, the\nrecipe is executed if any prerequisite is more recent than the target;\nin other words, if a prerequisite has changed since the last time you\nremade the target.  Here is an example:\n\n@example\nprint: foo.c bar.c\n        lpr -p $?\n        touch print\n@end example\n@cindex @code{print} target\n@cindex @code{lpr} (shell command)\n@cindex @code{touch} (shell command)\n\n@noindent\nWith this rule, @samp{make print} will execute the @code{lpr} command if\neither source file has changed since the last @samp{make print}.  The\nautomatic variable @samp{$?} is used to print only those files that have\nchanged (@pxref{Automatic Variables}).\n\n@node Special Targets\n@section Special Built-in Target Names\n@cindex special targets\n@cindex built-in special targets\n@cindex targets, built-in special\n\nCertain names have special meanings if they appear as targets.\n\n@table @code\n@findex .PHONY\n@item .PHONY\n\nThe prerequisites of the special target @code{.PHONY} are considered to\nbe phony targets.  When it is time to consider such a target,\n@code{make} will run its recipe unconditionally, regardless of\nwhether a file with that name exists or what its last-modification\ntime is.  @xref{Phony Targets, ,Phony Targets}.\n\n@findex .SUFFIXES\n@item .SUFFIXES\n\nThe prerequisites of the special target @code{.SUFFIXES} are the list\nof suffixes to be used in checking for suffix rules.\n@xref{Suffix Rules, , Old-Fashioned Suffix Rules}.\n\n@findex .DEFAULT@r{, special target}\n@item .DEFAULT\n\nThe recipe specified for @code{.DEFAULT} is used for any target for\nwhich no rules are found (either explicit rules or implicit rules).\n@xref{Last Resort}.  If a @code{.DEFAULT} recipe is specified, every\nfile mentioned as a prerequisite, but not as a target in a rule, will have\nthat recipe executed on its behalf.  @xref{Implicit Rule Search,\n,Implicit Rule Search Algorithm}.\n\n@findex .PRECIOUS\n@item .PRECIOUS\n@cindex precious targets\n@cindex preserving with @code{.PRECIOUS}\n\nThe targets which @code{.PRECIOUS} depends on are given the following\nspecial treatment: if @code{make} is killed or interrupted during the\nexecution of their recipes, the target is not deleted.\n@xref{Interrupts, ,Interrupting or Killing @code{make}}.  Also, if the\ntarget is an intermediate file, it will not be deleted after it is no\nlonger needed, as is normally done.  @xref{Chained Rules, ,Chains of\nImplicit Rules}.  In this latter respect it overlaps with the\n@code{.SECONDARY} special target.\n\nYou can also list the target pattern of an implicit rule (such as\n@samp{%.o}) as a prerequisite file of the special target @code{.PRECIOUS}\nto preserve intermediate files created by rules whose target patterns\nmatch that file's name.\n\n@findex .INTERMEDIATE\n@item .INTERMEDIATE\n@cindex intermediate targets, explicit\n\nThe targets which @code{.INTERMEDIATE} depends on are treated as\nintermediate files.  @xref{Chained Rules, ,Chains of Implicit Rules}.\n@code{.INTERMEDIATE} with no prerequisites has no effect.\n\n@findex .NOTINTERMEDIATE\n@item .NOTINTERMEDIATE\n@cindex not intermediate targets, explicit\n\nPrerequisites of the special target @code{.NOTINTERMEDIATE} are never\nconsidered intermediate files.  @xref{Chained Rules, ,Chains of Implicit Rules}.\n@code{.NOTINTERMEDIATE} with no prerequisites causes all targets to be treated\nas not intermediate.\n\nIf the prerequisite is a target pattern then targets that are built using that\npattern rule are not considered intermediate.\n\n@findex .SECONDARY\n@item .SECONDARY\n@cindex secondary targets\n@cindex preserving with @code{.SECONDARY}\n\nThe targets which @code{.SECONDARY} depends on are treated as\nintermediate files, except that they are never automatically deleted.\n@xref{Chained Rules, ,Chains of Implicit Rules}.\n\n@code{.SECONDARY} can be used to avoid redundant rebuilds in some unusual\nsituations.  For example:\n\n@example\n@group\nhello.bin: hello.o bye.o\n        $(CC) -o $@@ $^\n\n%.o: %.c\n        $(CC) -c -o $@@ $<\n\n.SECONDARY: hello.o bye.o\n@end group\n@end example\n\nSuppose @file{hello.bin} is up to date in regards to the source files,\n@emph{but} the object file @file{hello.o} is missing.  Without\n@code{.SECONDARY} make would rebuild @file{hello.o} then rebuild\n@file{hello.bin} even though the source files had not changed.  By declaring\n@file{hello.o} as @code{.SECONDARY} @code{make} will not need to rebuild it\nand won't need to rebuild @file{hello.bin} either.  Of course, if one of the\nsource files @emph{were} updated then all object files would be rebuilt so\nthat the creation of @file{hello.bin} could succeed.\n\n@code{.SECONDARY} with no prerequisites causes all targets to be treated\nas secondary (i.e., no target is removed because it is considered\nintermediate).\n\n@item .SECONDEXPANSION\n\nIf @code{.SECONDEXPANSION} is mentioned as a target anywhere in the\nmakefile, then all prerequisite lists defined @emph{after} it appears\nwill be expanded a second time after all makefiles have been read in.\n@xref{Secondary Expansion, ,Secondary Expansion}.\n\n@findex .DELETE_ON_ERROR\n@item .DELETE_ON_ERROR\n@cindex removing targets on failure\n\nIf @code{.DELETE_ON_ERROR} is mentioned as a target anywhere in the\nmakefile, then @code{make} will delete the target of a rule if it has\nchanged and its recipe exits with a nonzero exit status, just as it\ndoes when it receives a signal.  @xref{Errors, ,Errors in Recipes}.\n\n@findex .IGNORE\n@item .IGNORE\n\nIf you specify prerequisites for @code{.IGNORE}, then @code{make} will\nignore errors in execution of the recipe for those particular files.\nThe recipe for @code{.IGNORE} (if any) is ignored.\n\nIf mentioned as a target with no prerequisites, @code{.IGNORE} says to\nignore errors in execution of recipes for all files.  This usage of\n@samp{.IGNORE} is supported only for historical compatibility.  Since\nthis affects every recipe in the makefile, it is not very useful; we\nrecommend you use the more selective ways to ignore errors in specific\nrecipes.  @xref{Errors, ,Errors in Recipes}.\n\n@findex .LOW_RESOLUTION_TIME\n@item .LOW_RESOLUTION_TIME\n\nIf you specify prerequisites for @code{.LOW_RESOLUTION_TIME},\n@command{make} assumes that these files are created by commands that\ngenerate low resolution time stamps.  The recipe for the\n@code{.LOW_RESOLUTION_TIME} target are ignored.\n\nThe high resolution file time stamps of many modern file systems\nlessen the chance of @command{make} incorrectly concluding that a file\nis up to date.  Unfortunately, some hosts do not provide a way to set a\nhigh resolution file time stamp, so commands like @samp{cp -p} that\nexplicitly set a file's time stamp must discard its sub-second part.\nIf a file is created by such a command, you should list it as a\nprerequisite of @code{.LOW_RESOLUTION_TIME} so that @command{make}\ndoes not mistakenly conclude that the file is out of date.  For\nexample:\n\n@example\n@group\n.LOW_RESOLUTION_TIME: dst\ndst: src\n        cp -p src dst\n@end group\n@end example\n\nSince @samp{cp -p} discards the sub-second part of @file{src}'s time\nstamp, @file{dst} is typically slightly older than @file{src} even when\nit is up to date.  The @code{.LOW_RESOLUTION_TIME} line causes\n@command{make} to consider @file{dst} to be up to date if its time stamp\nis at the start of the same second that @file{src}'s time stamp is in.\n\nDue to a limitation of the archive format, archive member time stamps\nare always low resolution.  You need not list archive members as\nprerequisites of @code{.LOW_RESOLUTION_TIME}, as @command{make} does this\nautomatically.\n\n@findex .SILENT\n@item .SILENT\n\nIf you specify prerequisites for @code{.SILENT}, then @code{make} will\nnot print the recipe used to remake those particular files before\nexecuting them.  The recipe for @code{.SILENT} is ignored.\n\nIf mentioned as a target with no prerequisites, @code{.SILENT} says\nnot to print any recipes before executing them.  You may also use more\nselective ways to silence specific recipe command lines.\n@xref{Echoing, ,Recipe Echoing}.  If you want to silence all recipes\nfor a particular run of @code{make}, use the @samp{-s} or\n@w{@samp{--silent}} option (@pxref{Options Summary}).\n\n@findex .EXPORT_ALL_VARIABLES\n@item .EXPORT_ALL_VARIABLES\n\nSimply by being mentioned as a target, this tells @code{make} to export all\nvariables to child processes by default.  This is an alternative to using\n@code{export} with no arguments.  @xref{Variables/Recursion, ,Communicating\nVariables to a Sub-@code{make}}.\n\n@findex .NOTPARALLEL\n@item .NOTPARALLEL\n@cindex parallel execution, overriding\n\nIf @code{.NOTPARALLEL} is mentioned as a target with no prerequisites, all\ntargets in this invocation of @code{make} will be run serially, even if the\n@samp{-j} option is given.  Any recursively invoked @code{make} command will\nstill run recipes in parallel (unless its makefile also contains this target).\n\nIf @code{.NOTPARALLEL} has targets as prerequisites, then all the\nprerequisites of those targets will be run serially.  This implicitly adds a\n@code{.WAIT} between each prerequisite of the listed targets.  @xref{Parallel\nDisable, , Disabling Parallel Execution}.\n\n@item .ONESHELL\n@cindex recipe execution, single invocation\n\nIf @code{.ONESHELL} is mentioned as a target, then when a target is\nbuilt all lines of the recipe will be given to a single invocation of\nthe shell rather than each line being invoked separately.\n@xref{Execution, ,Recipe Execution}.\n\n@findex .POSIX\n@item .POSIX\n@cindex POSIX-conforming mode, setting\n\nIf @code{.POSIX} is mentioned as a target, then the makefile will be\nparsed and run in POSIX-conforming mode.  This does @emph{not} mean\nthat only POSIX-conforming makefiles will be accepted: all advanced\nGNU @code{make} features are still available.  Rather, this target\ncauses @code{make} to behave as required by POSIX in those areas\nwhere @code{make}'s default behavior differs.\n\nIn particular, if this target is mentioned then recipes will be\ninvoked as if the shell had been passed the @code{-e} flag: the first\nfailing command in a recipe will cause the recipe to fail immediately.\n@end table\n\nAny defined implicit rule suffix also counts as a special target if it\nappears as a target, and so does the concatenation of two suffixes, such\nas @samp{.c.o}.  These targets are suffix rules, an obsolete way of\ndefining implicit rules (but a way still widely used).  In principle, any\ntarget name could be special in this way if you break it in two and add\nboth pieces to the suffix list.  In practice, suffixes normally begin with\n@samp{.}, so these special target names also begin with @samp{.}.\n@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.\n\n@node Multiple Targets\n@section Multiple Targets in a Rule\n@cindex multiple targets\n@cindex several targets in a rule\n@cindex targets, multiple\n@cindex rule, with multiple targets\n\nWhen an explicit rule has multiple targets they can be treated in one\nof two possible ways: as independent targets or as grouped targets.\nThe manner in which they are treated is determined by the separator that\nappears after the list of targets.\n\n@subsubheading Rules with Independent Targets\n@cindex independent targets\n@cindex targets, independent\n\nRules that use the standard target separator, @code{:}, define\nindependent targets.  This is equivalent to writing the same rule once\nfor each target, with duplicated prerequisites and recipes.  Typically,\nthe recipe would use automatic variables such as @samp{$@@} to specify\nwhich target is being built.\n\nRules with independent targets are useful in two cases:\n\n@itemize @bullet\n@item\nYou want just prerequisites, no recipe.  For example:\n\n@example\nkbd.o command.o files.o: command.h\n@end example\n\n@noindent\ngives an additional prerequisite to each of the three object files\nmentioned.  It is equivalent to writing:\n\n@example\nkbd.o: command.h\ncommand.o: command.h\nfiles.o: command.h\n@end example\n\n@item\nSimilar recipes work for all the targets.  The automatic variable\n@samp{$@@} can be used to substitute the particular target to be\nremade into the commands (@pxref{Automatic Variables}).  For example:\n\n@example\n@group\nbigoutput littleoutput : text.g\n        generate text.g -$(subst output,,$@@) > $@@\n@end group\n@end example\n\n@noindent\nis equivalent to\n\n@example\nbigoutput : text.g\n        generate text.g -big > bigoutput\nlittleoutput : text.g\n        generate text.g -little > littleoutput\n@end example\n\n@noindent\nHere we assume the hypothetical program @code{generate} makes two\ntypes of output, one if given @samp{-big} and one if given\n@samp{-little}.\n@xref{Text Functions, ,Functions for String Substitution and Analysis},\nfor an explanation of the @code{subst} function.\n@end itemize\n\nSuppose you would like to vary the prerequisites according to the\ntarget, much as the variable @samp{$@@} allows you to vary the recipe.\nYou cannot do this with multiple targets in an ordinary rule, but you\ncan do it with a @dfn{static pattern rule}.  @xref{Static Pattern,\n,Static Pattern Rules}.\n\n@subsubheading Rules with Grouped Targets\n@cindex grouped targets\n@cindex targets, grouped\n\nIf instead of independent targets you have a recipe that generates multiple\nfiles from a single invocation, you can express that relationship by declaring\nyour rule to use @emph{grouped targets}.  A grouped target rule uses the\nseparator @code{&:} (the @samp{&} here is used to imply ``all'').\n\nWhen @code{make} builds any one of the grouped targets, it understands that\nall the other targets in the group are also updated as a result of the\ninvocation of the recipe.  Furthermore, if only some of the grouped targets\nare out of date or missing @code{make} will realize that running the recipe\nwill update all of the targets.  Finally, if any of the grouped targets are\nout of date, all the grouped targets are considered out of date.\n\nAs an example, this rule defines a grouped target:\n\n@example\n@group\nfoo bar biz &: baz boz\n        echo $^ > foo\n        echo $^ > bar\n        echo $^ > biz\n@end group\n@end example\n\nDuring the execution of a grouped target's recipe, the automatic\nvariable @samp{$@@} is set to the name of the particular target in the\ngroup which triggered the rule.  Caution must be used if relying on\nthis variable in the recipe of a grouped target rule.\n\nUnlike independent targets, a grouped target rule @emph{must} include\na recipe.  However, targets that are members of a grouped target may\nalso appear in independent target rule definitions that do not have\nrecipes.\n\nEach target may have only one recipe associated with it.  If a grouped\ntarget appears in either an independent target rule or in another\ngrouped target rule with a recipe, you will get a warning and the\nlatter recipe will replace the former recipe.  Additionally the target\nwill be removed from the previous group and appear only in the new\ngroup.\n\nIf you would like a target to appear in multiple groups, then you must\nuse the double-colon grouped target separator, @code{&::} when\ndeclaring all of the groups containing that target.  Grouped\ndouble-colon targets are each considered independently, and each\ngrouped double-colon rule's recipe is executed at most once, if at\nleast one of its multiple targets requires updating.\n\n@node Multiple Rules\n@section Multiple Rules for One Target\n@cindex multiple rules for one target\n@cindex several rules for one target\n@cindex rule, multiple for one target\n@cindex target, multiple rules for one\n\nOne file can be the target of several rules.  All the prerequisites\nmentioned in all the rules are merged into one list of prerequisites for\nthe target.  If the target is older than any prerequisite from any rule,\nthe recipe is executed.\n\nThere can only be one recipe to be executed for a file.  If more than\none rule gives a recipe for the same file, @code{make} uses the last\none given and prints an error message.  (As a special case, if the\nfile's name begins with a dot, no error message is printed.  This odd\nbehavior is only for compatibility with other implementations of\n@code{make}@dots{} you should avoid using it).  Occasionally it is\nuseful to have the same target invoke multiple recipes which are\ndefined in different parts of your makefile; you can use\n@dfn{double-colon rules} (@pxref{Double-Colon}) for this.\n\nAn extra rule with just prerequisites can be used to give a few extra\nprerequisites to many files at once.  For example, makefiles often\nhave a variable, such as @code{objects}, containing a list of all the\ncompiler output files in the system being made.  An easy way to say\nthat all of them must be recompiled if @file{config.h} changes is to\nwrite the following:\n\n@example\nobjects = foo.o bar.o\nfoo.o : defs.h\nbar.o : defs.h test.h\n$(objects) : config.h\n@end example\n\nThis could be inserted or taken out without changing the rules that really\nspecify how to make the object files, making it a convenient form to use if\nyou wish to add the additional prerequisite intermittently.\n\nAnother wrinkle is that the additional prerequisites could be\nspecified with a variable that you set with a command line argument to\n@code{make} (@pxref{Overriding, ,Overriding Variables}).  For example,\n\n@example\n@group\nextradeps=\n$(objects) : $(extradeps)\n@end group\n@end example\n\n@noindent\nmeans that the command @samp{make extradeps=foo.h} will consider\n@file{foo.h} as a prerequisite of each object file, but plain @samp{make}\nwill not.\n\nIf none of the explicit rules for a target has a recipe, then @code{make}\nsearches for an applicable implicit rule to find one\n@pxref{Implicit Rules, ,Using Implicit Rules}).\n\n@node Static Pattern\n@section Static Pattern Rules\n@cindex static pattern rule\n@cindex rule, static pattern\n@cindex pattern rules, static (not implicit)\n@cindex varying prerequisites\n@cindex prerequisites, varying (static pattern)\n\n@dfn{Static pattern rules} are rules which specify multiple targets and\nconstruct the prerequisite names for each target based on the target name.\nThey are more general than ordinary rules with multiple targets because the\ntargets do not have to have identical prerequisites.  Their prerequisites must\nbe @emph{analogous}, but not necessarily @emph{identical}.\n\n@menu\n* Static Usage::                The syntax of static pattern rules.\n* Static versus Implicit::      When are they better than implicit rules?\n@end menu\n\n@node Static Usage\n@subsection Syntax of Static Pattern Rules\n@cindex static pattern rule, syntax of\n@cindex pattern rules, static, syntax of\n\nHere is the syntax of a static pattern rule:\n\n@example\n@var{targets} @dots{}: @var{target-pattern}: @var{prereq-patterns} @dots{}\n        @var{recipe}\n        @dots{}\n@end example\n\n@noindent\nThe @var{targets} list specifies the targets that the rule applies to.\nThe targets can contain wildcard characters, just like the targets of\nordinary rules (@pxref{Wildcards, ,Using Wildcard Characters in File\nNames}).\n\n@cindex target pattern, static (not implicit)\n@cindex stem\nThe @var{target-pattern} and @var{prereq-patterns} say how to compute the\nprerequisites of each target.  Each target is matched against the\n@var{target-pattern} to extract a part of the target name, called the\n@dfn{stem}.  This stem is substituted into each of the @var{prereq-patterns}\nto make the prerequisite names (one from each @var{prereq-pattern}).\n\nEach pattern normally contains the character @samp{%} just once.  When the\n@var{target-pattern} matches a target, the @samp{%} can match any part of\nthe target name; this part is called the @dfn{stem}.  The rest of the\npattern must match exactly.  For example, the target @file{foo.o} matches\nthe pattern @samp{%.o}, with @samp{foo} as the stem.  The targets\n@file{foo.c} and @file{foo.out} do not match that pattern.\n\n@cindex prerequisite pattern, static (not implicit)\nThe prerequisite names for each target are made by substituting the stem\nfor the @samp{%} in each prerequisite pattern.  For example, if one\nprerequisite pattern is @file{%.c}, then substitution of the stem\n@samp{foo} gives the prerequisite name @file{foo.c}.  It is legitimate\nto write a prerequisite pattern that does not contain @samp{%}; then this\nprerequisite is the same for all targets.\n\n@cindex @code{%}, quoting in static pattern\n@cindex @code{\\} (backslash), to quote @code{%}\n@cindex backslash (@code{\\}), to quote @code{%}\n@cindex quoting @code{%}, in static pattern\n@samp{%} characters in pattern rules can be quoted with preceding\nbackslashes (@samp{\\}).  Backslashes that would otherwise quote @samp{%}\ncharacters can be quoted with more backslashes.  Backslashes that quote\n@samp{%} characters or other backslashes are removed from the pattern\nbefore it is compared to file names or has a stem substituted into it.\nBackslashes that are not in danger of quoting @samp{%} characters go\nunmolested.  For example, the pattern @file{the\\%weird\\\\%pattern\\\\} has\n@samp{the%weird\\} preceding the operative @samp{%} character, and\n@samp{pattern\\\\} following it.  The final two backslashes are left alone\nbecause they cannot affect any @samp{%} character.\n\nHere is an example, which compiles each of @file{foo.o} and @file{bar.o}\nfrom the corresponding @file{.c} file:\n\n@example\n@group\nobjects = foo.o bar.o\n\nall: $(objects)\n\n$(objects): %.o: %.c\n        $(CC) -c $(CFLAGS) $< -o $@@\n@end group\n@end example\n\n@noindent\nHere @samp{$<} is the automatic variable that holds the name of the\nprerequisite and @samp{$@@} is the automatic variable that holds the name\nof the target; see @ref{Automatic Variables}.\n\nEach target specified must match the target pattern; a warning is issued\nfor each target that does not.  If you have a list of files, only some of\nwhich will match the pattern, you can use the @code{filter} function to\nremove non-matching file names (@pxref{Text Functions, ,Functions for String Substitution and Analysis}):\n\n@example\nfiles = foo.elc bar.o lose.o\n\n$(filter %.o,$(files)): %.o: %.c\n        $(CC) -c $(CFLAGS) $< -o $@@\n$(filter %.elc,$(files)): %.elc: %.el\n        emacs -f batch-byte-compile $<\n@end example\n\n@noindent\nIn this example the result of @samp{$(filter %.o,$(files))} is\n@file{bar.o lose.o}, and the first static pattern rule causes each of\nthese object files to be updated by compiling the corresponding C source\nfile.  The result of @w{@samp{$(filter %.elc,$(files))}} is\n@file{foo.elc}, so that file is made from @file{foo.el}.\n\nAnother example shows how to use @code{$*} in static pattern rules:\n@vindex $*@r{, and static pattern}\n\n@example\n@group\nbigoutput littleoutput : %output : text.g\n        generate text.g -$* > $@@\n@end group\n@end example\n\n@noindent\nWhen the @code{generate} command is run, @code{$*} will expand to the\nstem, either @samp{big} or @samp{little}.\n\n@node Static versus Implicit\n@subsection Static Pattern Rules versus Implicit Rules\n@cindex rule, static pattern versus implicit\n@cindex static pattern rule, versus implicit\n\nA static pattern rule has much in common with an implicit rule defined as a\npattern rule (@pxref{Pattern Rules, ,Defining and Redefining Pattern Rules}).\nBoth have a pattern for the target and patterns for constructing the\nnames of prerequisites.  The difference is in how @code{make} decides\n@emph{when} the rule applies.\n\nAn implicit rule @emph{can} apply to any target that matches its pattern,\nbut it @emph{does} apply only when the target has no recipe otherwise\nspecified, and only when the prerequisites can be found.  If more than one\nimplicit rule appears applicable, only one applies; the choice depends on\nthe order of rules.\n\nBy contrast, a static pattern rule applies to the precise list of targets\nthat you specify in the rule.  It cannot apply to any other target and it\ninvariably does apply to each of the targets specified.  If two conflicting\nrules apply, and both have recipes, that's an error.\n\nThe static pattern rule can be better than an implicit rule for these\nreasons:\n\n@itemize @bullet\n@item\nYou may wish to override the usual implicit rule for a few\nfiles whose names cannot be categorized syntactically but\ncan be given in an explicit list.\n\n@item\nIf you cannot be sure of the precise contents of the directories\nyou are using, you may not be sure which other irrelevant files\nmight lead @code{make} to use the wrong implicit rule.  The choice\nmight depend on the order in which the implicit rule search is done.\nWith static pattern rules, there is no uncertainty: each rule applies\nto precisely the targets specified.\n@end itemize\n\n@node Double-Colon\n@section Double-Colon Rules\n@cindex double-colon rules\n@cindex rule, double-colon (@code{::})\n@cindex multiple rules for one target (@code{::})\n@cindex @code{::} rules (double-colon)\n\n@dfn{Double-colon} rules are explicit rules written with @samp{::}\ninstead of @samp{:} after the target names.  They are handled\ndifferently from ordinary rules when the same target appears in more\nthan one rule.  Pattern rules with double-colons have an entirely\ndifferent meaning (@pxref{Match-Anything Rules}).\n\nWhen a target appears in multiple rules, all the rules must be the same\ntype: all ordinary, or all double-colon.  If they are double-colon, each\nof them is independent of the others.  Each double-colon rule's recipe\nis executed if the target is older than any prerequisites of that rule.\nIf there are no prerequisites for that rule, its recipe is always\nexecuted (even if the target already exists).  This can result in\nexecuting none, any, or all of the double-colon rules.\n\nDouble-colon rules with the same target are in fact completely separate\nfrom one another.  Each double-colon rule is processed individually, just\nas rules with different targets are processed.\n\nThe double-colon rules for a target are executed in the order they appear\nin the makefile.  However, the cases where double-colon rules really make\nsense are those where the order of executing the recipes would not matter.\n\nDouble-colon rules are somewhat obscure and not often very useful; they\nprovide a mechanism for cases in which the method used to update a target\ndiffers depending on which prerequisite files caused the update, and such\ncases are rare.\n\nEach double-colon rule should specify a recipe; if it does not, an\nimplicit rule will be used if one applies.\n@xref{Implicit Rules, ,Using Implicit Rules}.\n\n@node Automatic Prerequisites\n@section Generating Prerequisites Automatically\n@cindex prerequisites, automatic generation\n@cindex automatic generation of prerequisites\n@cindex generating prerequisites automatically\n\nIn the makefile for a program, many of the rules you need to write often\nsay only that some object file depends on some header\nfile.  For example, if @file{main.c} uses @file{defs.h} via an\n@code{#include}, you would write:\n\n@example\nmain.o: defs.h\n@end example\n\n@noindent\nYou need this rule so that @code{make} knows that it must remake\n@file{main.o} whenever @file{defs.h} changes.  You can see that for a\nlarge program you would have to write dozens of such rules in your\nmakefile.  And, you must always be very careful to update the makefile\nevery time you add or remove an @code{#include}.\n@cindex @code{#include}\n\n@cindex @code{-M} (to compiler)\nTo avoid this hassle, most modern C compilers can write these rules for\nyou, by looking at the @code{#include} lines in the source files.\nUsually this is done with the @samp{-M} option to the compiler.\nFor example, the command:\n\n@example\ncc -M main.c\n@end example\n\n@noindent\ngenerates the output:\n\n@example\nmain.o : main.c defs.h\n@end example\n\n@noindent\nThus you no longer have to write all those rules yourself.\nThe compiler will do it for you.\n\nNote that such a rule constitutes mentioning @file{main.o} in a\nmakefile, so it can never be considered an intermediate file by\nimplicit rule search.  This means that @code{make} won't ever remove\nthe file after using it; @pxref{Chained Rules, ,Chains of Implicit\nRules}.\n\n@cindex @code{make depend}\nWith old @code{make} programs, it was traditional practice to use this\ncompiler feature to generate prerequisites on demand with a command like\n@samp{make depend}.  That command would create a file @file{depend}\ncontaining all the automatically-generated prerequisites; then the\nmakefile could use @code{include} to read them in (@pxref{Include}).\n\nIn GNU @code{make}, the feature of remaking makefiles makes this\npractice obsolete---you need never tell @code{make} explicitly to\nregenerate the prerequisites, because it always regenerates any makefile\nthat is out of date.  @xref{Remaking Makefiles}.\n\nThe practice we recommend for automatic prerequisite generation is to have\none makefile corresponding to each source file.  For each source file\n@file{@var{name}.c} there is a makefile @file{@var{name}.d} which lists\nwhat files the object file @file{@var{name}.o} depends on.  That way\nonly the source files that have changed need to be rescanned to produce\nthe new prerequisites.\n\nHere is the pattern rule to generate a file of prerequisites (i.e., a makefile)\ncalled @file{@var{name}.d} from a C source file called @file{@var{name}.c}:\n\n@smallexample\n@group\n%.d: %.c\n        @@set -e; rm -f $@@; \\\n         $(CC) -M $(CPPFLAGS) $< > $@@.$$$$; \\\n         sed 's,\\($*\\)\\.o[ :]*,\\1.o $@@ : ,g' < $@@.$$$$ > $@@; \\\n         rm -f $@@.$$$$\n@end group\n@end smallexample\n\n@noindent\n@xref{Pattern Rules}, for information on defining pattern rules.  The\n@samp{-e} flag to the shell causes it to exit immediately if the\n@code{$(CC)} command (or any other command) fails (exits with a\nnonzero status).\n@cindex @code{-e} (shell flag)\n\n@cindex @code{-MM} (to GNU compiler)\nWith the GNU C compiler, you may wish to use the @samp{-MM} flag instead\nof @samp{-M}.  This omits prerequisites on system header files.\n@xref{Preprocessor Options, , Options Controlling the Preprocessor,\ngcc, Using GNU CC}, for details.\n\n@cindex @code{sed} (shell command)\nThe purpose of the @code{sed} command is to translate (for example):\n\n@example\nmain.o : main.c defs.h\n@end example\n\n@noindent\ninto:\n\n@example\nmain.o main.d : main.c defs.h\n@end example\n\n@noindent\n@cindex @code{.d}\nThis makes each @samp{.d} file depend on all the source and header files\nthat the corresponding @samp{.o} file depends on.  @code{make} then\nknows it must regenerate the prerequisites whenever any of the source or\nheader files changes.\n\nOnce you've defined the rule to remake the @samp{.d} files,\nyou then use the @code{include} directive to read them all in.\n@xref{Include}.  For example:\n\n@example\n@group\nsources = foo.c bar.c\n\ninclude $(sources:.c=.d)\n@end group\n@end example\n\n@noindent\n(This example uses a substitution variable reference to translate the\nlist of source files @samp{foo.c bar.c} into a list of prerequisite\nmakefiles, @samp{foo.d bar.d}.  @xref{Substitution Refs}, for full\ninformation on substitution references.)  Since the @samp{.d} files are\nmakefiles like any others, @code{make} will remake them as necessary\nwith no further work from you.  @xref{Remaking Makefiles}.\n\nNote that the @samp{.d} files contain target definitions; you should\nbe sure to place the @code{include} directive @emph{after} the first,\ndefault goal in your makefiles or run the risk of having a random\nobject file become the default goal.\n@xref{How Make Works}.\n\n@node Recipes\n@chapter Writing Recipes in Rules\n@cindex recipes\n@cindex recipes, how to write\n@cindex writing recipes\n\nThe recipe of a rule consists of one or more shell command lines to\nbe executed, one at a time, in the order they appear.  Typically, the\nresult of executing these commands is that the target of the rule is\nbrought up to date.\n\nUsers use many different shell programs, but recipes in makefiles are\nalways interpreted by @file{/bin/sh} unless the makefile specifies\notherwise.  @xref{Execution, ,Recipe Execution}.\n\n@menu\n* Recipe Syntax::               Recipe syntax features and pitfalls.\n* Echoing::                     How to control when recipes are echoed.\n* Execution::                   How recipes are executed.\n* Parallel::                    How recipes can be executed in parallel.\n* Errors::                      What happens after a recipe execution error.\n* Interrupts::                  What happens when a recipe is interrupted.\n* Recursion::                   Invoking @code{make} from makefiles.\n* Canned Recipes::              Defining canned recipes.\n* Empty Recipes::               Defining useful, do-nothing recipes.\n@end menu\n\n@node Recipe Syntax\n@section Recipe Syntax\n@cindex recipe syntax\n@cindex syntax of recipe\n\nMakefiles have the unusual property that there are really two distinct\nsyntaxes in one file.  Most of the makefile uses @code{make} syntax\n(@pxref{Makefiles, ,Writing Makefiles}).  However, recipes are meant\nto be interpreted by the shell and so they are written using shell\nsyntax.  The @code{make} program does not try to understand shell\nsyntax: it performs only a very few specific translations on the\ncontent of the recipe before handing it to the shell.\n\nEach line in the recipe must start with a tab (or the first character\nin the value of the @code{.RECIPEPREFIX} variable; @pxref{Special\nVariables}), except that the first recipe line may be attached to the\ntarget-and-prerequisites line with a semicolon in between.  @emph{Any}\nline in the makefile that begins with a tab and appears in a ``rule\ncontext'' (that is, after a rule has been started until another rule\nor variable definition) will be considered part of a recipe for that\nrule.  Blank lines and lines of just comments may appear among the\nrecipe lines; they are ignored.\n\nSome consequences of these rules include:\n\n@itemize @bullet\n@item\nA blank line that begins with a tab is not blank: it's an empty\nrecipe (@pxref{Empty Recipes}).\n\n@cindex comments, in recipes\n@cindex recipes, comments in\n@cindex @code{#} (comments), in recipes\n@item\nA comment in a recipe is not a @code{make} comment; it will be\npassed to the shell as-is.  Whether the shell treats it as a comment\nor not depends on your shell.\n\n@item\nA variable definition in a ``rule context'' which is indented by a tab\nas the first character on the line, will be considered part of a\nrecipe, not a @code{make} variable definition, and passed to the\nshell.\n\n@item\nA conditional expression (@code{ifdef}, @code{ifeq},\netc. @pxref{Conditional Syntax, ,Syntax of Conditionals}) in a ``rule\ncontext'' which is indented by a tab as the first character on the\nline, will be considered part of a recipe and be passed to the shell.\n\n@end itemize\n\n@menu\n* Splitting Recipe Lines::      Breaking long recipe lines for readability.\n* Variables in Recipes::        Using @code{make} variables in recipes.\n@end menu\n\n@node Splitting Recipe Lines\n@subsection Splitting Recipe Lines\n@cindex recipes, splitting\n@cindex splitting recipes\n@cindex recipes, backslash (@code{\\}) in\n@cindex recipes, quoting newlines in\n@cindex backslash (@code{\\}), in recipes\n@cindex @code{\\} (backslash), in recipes\n@cindex quoting newline, in recipes\n@cindex newline, quoting, in recipes\n\nOne of the few ways in which @code{make} does interpret recipes is\nchecking for a backslash just before the newline.  As in normal\nmakefile syntax, a single logical recipe line can be split into\nmultiple physical lines in the makefile by placing a backslash before\neach newline.  A sequence of lines like this is considered a single\nrecipe line, and one instance of the shell will be invoked to run it.\n\nHowever, in contrast to how they are treated in other places in a\nmakefile (@pxref{Splitting Lines, , Splitting Long Lines}),\nbackslash/newline pairs are @emph{not} removed from the recipe.  Both\nthe backslash and the newline characters are preserved and passed to\nthe shell.  How the backslash/newline is interpreted depends on your\nshell.  If the first character of the next line after the\nbackslash/newline is the recipe prefix character (a tab by default;\n@pxref{Special Variables}), then that character (and only that\ncharacter) is removed.  Whitespace is never added to the recipe.\n\nFor example, the recipe for the all target in this makefile:\n\n@example\n@group\nall :\n        @@echo no\\\nspace\n        @@echo no\\\n        space\n        @@echo one \\\n        space\n        @@echo one\\\n         space\n@end group\n@end example\n\n@noindent\nconsists of four separate shell commands where the output is:\n\n@example\n@group\nnospace\nnospace\none space\none space\n@end group\n@end example\n\nAs a more complex example, this makefile:\n\n@example\n@group\nall : ; @@echo 'hello \\\n        world' ; echo \"hello \\\n    world\"\n@end group\n@end example\n\n@noindent\nwill invoke one shell with a command of:\n\n@example\n@group\necho 'hello \\\nworld' ; echo \"hello \\\n    world\"\n@end group\n@end example\n\n@noindent\nwhich, according to shell quoting rules, will yield the following output:\n\n@example\n@group\nhello \\\nworld\nhello     world\n@end group\n@end example\n\n@noindent\nNotice how the backslash/newline pair was removed inside the string\nquoted with double quotes (@code{\"@dots{}\"}), but not from the string\nquoted with single quotes (@code{'@dots{}'}).  This is the way the\ndefault shell (@file{/bin/sh}) handles backslash/newline pairs.  If\nyou specify a different shell in your makefiles it may treat them\ndifferently.\n\nSometimes you want to split a long line inside of single quotes, but\nyou don't want the backslash/newline to appear in the quoted content.\nThis is often the case when passing scripts to languages such as Perl,\nwhere extraneous backslashes inside the script can change its meaning\nor even be a syntax error.  One simple way of handling this is to\nplace the quoted string, or even the entire command, into a\n@code{make} variable then use the variable in the recipe.  In this\nsituation the newline quoting rules for makefiles will be used, and\nthe backslash/newline will be removed.  If we rewrite our example\nabove using this method:\n\n@example\n@group\nHELLO = 'hello \\\nworld'\n\nall : ; @@echo $(HELLO)\n@end group\n@end example\n\n@noindent\nwe will get output like this:\n\n@example\n@group\nhello world\n@end group\n@end example\n\nIf you like, you can also use target-specific variables\n(@pxref{Target-specific, ,Target-specific Variable Values}) to obtain\na tighter correspondence between the variable and the recipe that\nuses it.\n\n@node Variables in Recipes\n@subsection Using Variables in Recipes\n@cindex variable references in recipes\n@cindex recipes, using variables in\n\nThe other way in which @code{make} processes recipes is by expanding\nany variable references in them (@pxref{Reference,Basics of Variable\nReferences}).  This occurs after make has finished reading all the\nmakefiles and the target is determined to be out of date; so, the\nrecipes for targets which are not rebuilt are never expanded.\n\nVariable and function references in recipes have identical syntax and\nsemantics to references elsewhere in the makefile.  They also have the\nsame quoting rules: if you want a dollar sign to appear in your\nrecipe, you must double it (@samp{$$}).  For shells like the default\nshell, that use dollar signs to introduce variables, it's important to\nkeep clear in your mind whether the variable you want to reference is\na @code{make} variable (use a single dollar sign) or a shell variable\n(use two dollar signs).  For example:\n\n@example\n@group\nLIST = one two three\nall:\n        for i in $(LIST); do \\\n            echo $$i; \\\n        done\n@end group\n@end example\n\n@noindent\nresults in the following command being passed to the shell:\n\n@example\n@group\nfor i in one two three; do \\\n    echo $i; \\\ndone\n@end group\n@end example\n\n@noindent\nwhich generates the expected result:\n\n@example\n@group\none\ntwo\nthree\n@end group\n@end example\n\n@node Echoing\n@section Recipe Echoing\n@cindex echoing of recipes\n@cindex silent operation\n@cindex @code{@@} (in recipes)\n@cindex recipes, echoing\n@cindex printing of recipes\n\nNormally @code{make} prints each line of the recipe before it is\nexecuted.  We call this @dfn{echoing} because it gives the appearance\nthat you are typing the lines yourself.\n\nWhen a line starts with @samp{@@}, the echoing of that line is suppressed.\nThe @samp{@@} is discarded before the line is passed to the shell.\nTypically you would use this for a command whose only effect is to print\nsomething, such as an @code{echo} command to indicate progress through\nthe makefile:\n\n@example\n@@echo About to make distribution files\n@end example\n\nNote that the start of a recipe line is interpreted differently when\nusing @code{.ONESHELL} (@pxref{One Shell, ,Using One Shell}).\n\n@cindex @code{-n}\n@cindex @code{--just-print}\n@cindex @code{--dry-run}\n@cindex @code{--recon}\nWhen @code{make} is given the flag @samp{-n} or @samp{--just-print} it\nonly echoes most recipes, without executing them.  @xref{Options\nSummary, ,Summary of Options}.  In this case even the recipe lines\nstarting with @samp{@@} are printed.  This flag is useful for finding\nout which recipes @code{make} thinks are necessary without actually\ndoing them.\n\n@cindex @code{-s}\n@cindex @code{--silent}\n@cindex @code{--quiet}\nThe @samp{-s} or @samp{--silent}\nflag to @code{make} prevents all echoing, as if all recipes\nstarted with @samp{@@}.  A rule in the makefile for the special target\n@code{.SILENT} without prerequisites has the same effect\n(@pxref{Special Targets, ,Special Built-in Target Names}).\n\n@node Execution\n@section Recipe Execution\n@cindex recipe, execution\n@cindex execution, of recipes\n@vindex @code{SHELL} @r{(recipe execution)}\n\nWhen it is time to execute recipes to update a target, they are\nexecuted by invoking a new sub-shell for each line of the recipe,\nunless the @code{.ONESHELL} special target is in effect\n(@pxref{One Shell, ,Using One Shell})  (In practice, @code{make} may\ntake shortcuts that do not affect the results.)\n\n@cindex @code{cd} (shell command)\n@cindex shell variables, setting in recipes\n@cindex recipes setting shell variables\n@strong{Please note:} this implies that setting shell variables and\ninvoking shell commands such as @code{cd} that set a context local to\neach process will not affect the following lines in the recipe.@footnote{On\nMS-DOS, the value of current working directory is @strong{global}, so\nchanging it @emph{will} affect the following recipe lines on those\nsystems.}  If you want to use @code{cd} to affect the next statement,\nput both statements in a single recipe line.  Then @code{make} will\ninvoke one shell to run the entire line, and the shell will execute\nthe statements in sequence.  For example:\n\n@example\nfoo : bar/lose\n        cd $(<D) && gobble $(<F) > ../$@@\n@end example\n\n@noindent\nHere we use the shell AND operator (@code{&&}) so that if the\n@code{cd} command fails, the script will fail without trying to invoke\nthe @code{gobble} command in the wrong directory, which could cause\nproblems (in this case it would certainly cause @file{../foo} to be\ntruncated, at least).\n\n@menu\n* One Shell::                   One shell for all lines in a recipe.\n* Choosing the Shell::          How @code{make} chooses the shell used\n                                  to run recipes.\n@end menu\n\n@node One Shell\n@subsection Using One Shell\n@cindex recipe lines, single shell\n@cindex @code{.ONESHELL}, use of\n@findex .ONESHELL\n\nSometimes you would prefer that all the lines in the recipe be passed\nto a single invocation of the shell.  There are generally two\nsituations where this is useful: first, it can improve performance in\nmakefiles where recipes consist of many command lines, by avoiding\nextra processes.  Second, you might want newlines to be included in\nyour recipe command (for example perhaps you are using a very\ndifferent interpreter as your @code{SHELL}).  If the @code{.ONESHELL}\nspecial target appears anywhere in the makefile then @emph{all}\nrecipe lines for each target will be provided to a single invocation\nof the shell.  Newlines between recipe lines will be preserved.  For\nexample:\n\n@example\n.ONESHELL:\nfoo : bar/lose\n        cd $(<D)\n        gobble $(<F) > ../$@@\n@end example\n\n@noindent\nwould now work as expected even though the commands are on different\nrecipe lines.\n\nIf @code{.ONESHELL} is provided, then only the first line of the\nrecipe will be checked for the special prefix characters (@samp{@@},\n@samp{-}, and @samp{+}).  Subsequent lines will include the special\ncharacters in the recipe line when the @code{SHELL} is invoked.  If\nyou want your recipe to start with one of these special characters\nyou'll need to arrange for them to not be the first characters on the\nfirst line, perhaps by adding a comment or similar.  For example, this\nwould be a syntax error in Perl because the first @samp{@@} is removed\nby make:\n\n@example\n.ONESHELL:\nSHELL = /usr/bin/perl\n.SHELLFLAGS = -e\nshow :\n        @@f = qw(a b c);\n        print \"@@f\\n\";\n@end example\n\n@noindent\nHowever, either of these alternatives would work properly:\n\n@example\n.ONESHELL:\nSHELL = /usr/bin/perl\n.SHELLFLAGS = -e\nshow :\n        # Make sure \"@@\" is not the first character on the first line\n        @@f = qw(a b c);\n        print \"@@f\\n\";\n@end example\n\n@noindent\nor\n\n@example\n.ONESHELL:\nSHELL = /usr/bin/perl\n.SHELLFLAGS = -e\nshow :\n        my @@f = qw(a b c);\n        print \"@@f\\n\";\n@end example\n\nAs a special feature, if @code{SHELL} is determined to be a\nPOSIX-style shell, the special prefix characters in ``internal''\nrecipe lines will be @emph{removed} before the recipe is processed.\nThis feature is intended to allow existing makefiles to add the\n@code{.ONESHELL} special target and still run properly without\nextensive modifications.  Since the special prefix characters are not\nlegal at the beginning of a line in a POSIX shell script this is not a\nloss in functionality.  For example, this works as expected:\n\n@example\n.ONESHELL:\nfoo : bar/lose\n        @@cd $(@@D)\n        @@gobble $(@@F) > ../$@@\n@end example\n\nEven with this special feature, however, makefiles with\n@code{.ONESHELL} will behave differently in ways that could be\nnoticeable.  For example, normally if any line in the recipe fails,\nthat causes the rule to fail and no more recipe lines are processed.\nUnder @code{.ONESHELL} a failure of any but the final recipe line will\nnot be noticed by @code{make}.  You can modify @code{.SHELLFLAGS} to\nadd the @code{-e} option to the shell which will cause any failure\nanywhere in the command line to cause the shell to fail, but this\ncould itself cause your recipe to behave differently.  Ultimately you\nmay need to harden your recipe lines to allow them to work with\n@code{.ONESHELL}.\n\n@node Choosing the Shell\n@subsection Choosing the Shell\n@cindex shell, choosing the\n@cindex @code{SHELL}, value of\n@cindex @code{.SHELLFLAGS}, value of\n\n@vindex SHELL\n@vindex .SHELLFLAGS\nThe program used as the shell is taken from the variable @code{SHELL}.\nIf this variable is not set in your makefile, the program\n@file{/bin/sh} is used as the shell.  The argument(s) passed to the\nshell are taken from the variable @code{.SHELLFLAGS}.  The default\nvalue of @code{.SHELLFLAGS} is @code{-c} normally, or @code{-ec} in\nPOSIX-conforming mode.\n\n@cindex environment, @code{SHELL} in\nUnlike most variables, the variable @code{SHELL} is never set from the\nenvironment.  This is because the @code{SHELL} environment variable is\nused to specify your personal choice of shell program for interactive\nuse.  It would be very bad for personal choices like this to affect the\nfunctioning of makefiles.  @xref{Environment, ,Variables from the\nEnvironment}.\n\nFurthermore, when you do set @code{SHELL} in your makefile that value\nis @emph{not} exported in the environment to recipe lines that\n@code{make} invokes.  Instead, the value inherited from the user's\nenvironment, if any, is exported.  You can override this behavior by\nexplicitly exporting @code{SHELL} (@pxref{Variables/Recursion,\n,Communicating Variables to a Sub-@code{make}}), forcing it to be\npassed in the environment to recipe lines.\n\nHowever, on MS-DOS and MS-Windows the value of @code{SHELL} in the\nenvironment @strong{is} used, since on those systems most users do not\nset this variable, and therefore it is most likely set specifically to\nbe used by @code{make}.  On MS-DOS, if the setting of @code{SHELL} is\nnot suitable for @code{make}, you can set the variable\n@code{MAKESHELL} to the shell that @code{make} should use; if set it\nwill be used as the shell instead of the value of @code{SHELL}.\n\n@subsubheading Choosing a Shell in DOS and Windows\n@cindex shell, in DOS and Windows\n@cindex DOS, choosing a shell in\n@cindex Windows, choosing a shell in\n\nChoosing a shell in MS-DOS and MS-Windows is much more complex than on\nother systems.\n\n@vindex COMSPEC\nOn MS-DOS, if @code{SHELL} is not set, the value of the variable\n@code{COMSPEC} (which is always set) is used instead.\n\n@cindex @code{SHELL}, MS-DOS specifics\nThe processing of lines that set the variable @code{SHELL} in Makefiles\nis different on MS-DOS.  The stock shell, @file{command.com}, is\nridiculously limited in its functionality and many users of @code{make}\ntend to install a replacement shell.  Therefore, on MS-DOS, @code{make}\nexamines the value of @code{SHELL}, and changes its behavior based on\nwhether it points to a Unix-style or DOS-style shell.  This allows\nreasonable functionality even if @code{SHELL} points to\n@file{command.com}.\n\nIf @code{SHELL} points to a Unix-style shell, @code{make} on MS-DOS\nadditionally checks whether that shell can indeed be found; if not, it\nignores the line that sets @code{SHELL}.  In MS-DOS, GNU @code{make}\nsearches for the shell in the following places:\n\n@enumerate\n@item\nIn the precise place pointed to by the value of @code{SHELL}.  For\nexample, if the makefile specifies @samp{SHELL = /bin/sh}, @code{make}\nwill look in the directory @file{/bin} on the current drive.\n\n@item\nIn the current directory.\n\n@item\nIn each of the directories in the @code{PATH} variable, in order.\n\n@end enumerate\n\nIn every directory it examines, @code{make} will first look for the\nspecific file (@file{sh} in the example above).  If this is not found,\nit will also look in that directory for that file with one of the known\nextensions which identify executable files.  For example @file{.exe},\n@file{.com}, @file{.bat}, @file{.btm}, @file{.sh}, and some others.\n\nIf any of these attempts is successful, the value of @code{SHELL} will\nbe set to the full pathname of the shell as found.  However, if none of\nthese is found, the value of @code{SHELL} will not be changed, and thus\nthe line that sets it will be effectively ignored.  This is so\n@code{make} will only support features specific to a Unix-style shell if\nsuch a shell is actually installed on the system where @code{make} runs.\n\nNote that this extended search for the shell is limited to the cases\nwhere @code{SHELL} is set from the Makefile; if it is set in the\nenvironment or command line, you are expected to set it to the full\npathname of the shell, exactly as things are on Unix.\n\nThe effect of the above DOS-specific processing is that a Makefile that\ncontains @samp{SHELL = /bin/sh} (as many Unix makefiles do), will work\non MS-DOS unaltered if you have e.g.@: @file{sh.exe} installed in some\ndirectory along your @code{PATH}.\n\n@node Parallel\n@section Parallel Execution\n@cindex recipes, execution in parallel\n@cindex parallel execution\n@cindex execution, in parallel\n@cindex job slots\n@cindex @code{-j}\n@cindex @code{--jobs}\n\nGNU @code{make} knows how to execute several recipes at once.  Normally,\n@code{make} will execute only one recipe at a time, waiting for it to finish\nbefore executing the next.  However, the @samp{-j} or @samp{--jobs} option\ntells @code{make} to execute many recipes simultaneously.  You can inhibit\nparallelism for some or all targets from within the makefile (@pxref{Parallel\nDisable, ,Disabling Parallel Execution}).\n\nOn MS-DOS, the @samp{-j} option has no effect, since that system doesn't\nsupport multi-processing.\n\nIf the @samp{-j} option is followed by an integer, this is the number of\nrecipes to execute at once; this is called the number of @dfn{job slots}.\nIf there is nothing looking like an integer after the @samp{-j} option,\nthere is no limit on the number of job slots.  The default number of job\nslots is one, which means serial execution (one thing at a time).\n\nHandling recursive @code{make} invocations raises issues for parallel\nexecution.  For more information on this, see @ref{Options/Recursion,\n,Communicating Options to a Sub-@code{make}}.\n\nIf a recipe fails (is killed by a signal or exits with a nonzero\nstatus), and errors are not ignored for that recipe (@pxref{Errors,\n,Errors in Recipes}), the remaining recipe lines to remake the same\ntarget will not be run.  If a recipe fails and the @samp{-k} or\n@samp{--keep-going} option was not given (@pxref{Options Summary,\n,Summary of Options}), @code{make} aborts execution.  If make\nterminates for any reason (including a signal) with child processes\nrunning, it waits for them to finish before actually exiting.\n\n@cindex load average\n@cindex limiting jobs based on load\n@cindex jobs, limiting based on load\n@cindex @code{-l} (load average)\n@cindex @code{--max-load}\n@cindex @code{--load-average}\nWhen the system is heavily loaded, you will probably want to run fewer jobs\nthan when it is lightly loaded.  You can use the @samp{-l} option to tell\n@code{make} to limit the number of jobs to run at once, based on the load\naverage.  The @samp{-l} or @samp{--max-load}\noption is followed by a floating-point number.  For\nexample,\n\n@example\n-l 2.5\n@end example\n\n@noindent\nwill not let @code{make} start more than one job if the load average is\nabove 2.5.  The @samp{-l} option with no following number removes the\nload limit, if one was given with a previous @samp{-l} option.\n\nMore precisely, when @code{make} goes to start up a job, and it already has\nat least one job running, it checks the current load average; if it is not\nlower than the limit given with @samp{-l}, @code{make} waits until the load\naverage goes below that limit, or until all the other jobs finish.\n\nBy default, there is no load limit.\n\n@menu\n* Parallel Disable::            Disabling parallel execution\n* Parallel Output::             Handling output during parallel execution\n* Parallel Input::              Handling input during parallel execution\n@end menu\n\n@node Parallel Disable\n@subsection Disabling Parallel Execution\n@cindex disabling parallel execution\n@cindex parallel execution, disabling\n\nIf a makefile completely and accurately defines the dependency relationships\nbetween all of its targets, then @code{make} will correctly build the goals\nregardless of whether parallel execution is enabled or not.  This is the ideal\nway to write makefiles.\n\nHowever, sometimes some or all of the targets in a makefile cannot be executed\nin parallel and it's not feasible to add the prerequisites needed to inform\n@code{make}.  In that case the makefile can use various methods to disable\nparallel execution.\n\n@cindex .NOTPARALLEL special target\nIf the @code{.NOTPARALLEL} special target with no prerequisites is specified\nanywhere then the entire instance of @code{make} will be run serially,\nregardless of the parallel setting.  For example:\n\n@example\n@group\nall: one two three\none two three: ; @@sleep 1; echo $@@\n\n.NOTPARALLEL:\n@end group\n@end example\n\nRegardless of how @code{make} is invoked, the targets @file{one}, @file{two},\nand @file{three} will be run serially.\n\nIf the @code{.NOTPARALLEL} special target has prerequisites, then each of\nthose prerequisites will be considered a target and all prerequisites of these\ntargets will be run serially.  Note that only when building this target will\nthe prerequisites be run serially: if some other target lists the same\nprerequisites and is not in @code{.NOTPARALLEL} then these prerequisites may\nbe run in parallel.  For example:\n\n@example\n@group\nall: base notparallel\n\nbase: one two three\nnotparallel: one two three\n\none two three: ; @@sleep 1; echo $@@\n\n.NOTPARALLEL: notparallel\n@end group\n@end example\n\nHere @samp{make -j base} will run the targets @file{one}, @file{two}, and\n@file{three} in parallel, while @samp{make -j notparallel} will run them\nserially.  If you run @samp{make -j all} then they @emph{will} be run in\nparallel since @file{base} lists them as prerequisites and is not serialized.\n\nThe @code{.NOTPARALLEL} target should not have commands.\n\n@cindex .WAIT special target\n@findex .WAIT\nFinally you can control the serialization of specific prerequisites in a\nfine-grained way using the @code{.WAIT} special target.  When this target\nappears in a prerequisite list and parallel execution is enabled, @code{make}\nwill not build any of the prerequisites to the @emph{right} of @code{.WAIT}\nuntil all prerequisites to the @emph{left} of @code{.WAIT} have completed.\nFor example:\n\n@example\n@group\nall: one two .WAIT three\none two three: ; @@sleep 1; echo $@@\n@end group\n@end example\n\nIf parallel execution is enabled, @code{make} will try to build @file{one} and\n@file{two} in parallel but will not try to build @file{three} until both are\ncomplete.\n\nAs with targets provided to @code{.NOTPARALLEL}, @code{.WAIT} takes effect\nonly when building the target in whose prerequisite list it appears.  If the\nsame prerequisites are present in other targets, without @code{.WAIT}, then\nthey may still be run in parallel.  Because of this, neither\n@code{.NOTPARALLEL} with targets nor @code{.WAIT} are as reliable for\ncontrolling parallel execution as defining a prerequisite relationship.\nHowever they are easy to use and may be sufficient in less complex situations.\n\nThe @code{.WAIT} prerequisite will not be present in any of the automatic\nvariables for the rule.\n\nYou can create an actual target @code{.WAIT} in your makefile for portability\nbut this is not required to use this feature.  If a @code{.WAIT} target is\ncreated it should not have prerequisites or commands.\n\nThe @code{.WAIT} feature is also implemented in other versions of @code{make}\nand it's specified in the POSIX standard for @code{make}.\n\n@node Parallel Output\n@subsection Output During Parallel Execution\n@cindex output during parallel execution\n@cindex parallel execution, output during\n\nWhen running several recipes in parallel the output from each\nrecipe appears as soon as it is generated, with the result that\nmessages from different recipes may be interspersed, sometimes even\nappearing on the same line.  This can make reading the output very\ndifficult.\n\n@cindex @code{--output-sync}\n@cindex @code{-O}\nTo avoid this you can use the @samp{--output-sync} (@samp{-O}) option.\nThis option instructs @code{make} to save the output from the commands\nit invokes and print it all once the commands are completed.\nAdditionally, if there are multiple recursive @code{make} invocations\nrunning in parallel, they will communicate so that only one of them is\ngenerating output at a time.\n\nIf working directory printing is enabled (@pxref{-w Option, ,The\n@samp{--print-directory} Option}), the enter/leave messages are\nprinted around each output grouping.  If you prefer not to see these\nmessages add the @samp{--no-print-directory} option to @code{MAKEFLAGS}.\n\nThere are four levels of granularity when synchronizing output,\nspecified by giving an argument to the option (e.g.,  @samp{-Oline} or\n@samp{--output-sync=recurse}).\n\n@table @code\n@item none\nThis is the default: all output is sent directly as it is generated and\nno synchronization is performed.\n\n@item line\nOutput from each individual line of the recipe is grouped and printed\nas soon as that line is complete.  If a recipe consists of multiple\nlines, they may be interspersed with lines from other recipes.\n\n@item target\nOutput from the entire recipe for each target is grouped and printed\nonce the target is complete.  This is the default if the\n@code{--output-sync} or @code{-O} option is given with no argument.\n\n@item recurse\nOutput from each recursive invocation of @code{make} is grouped and\nprinted once the recursive invocation is complete.\n\n@end table\n\nRegardless of the mode chosen, the total build time will be the same.\nThe only difference is in how the output appears.\n\nThe @samp{target} and @samp{recurse} modes both collect the output of\nthe entire recipe of a target and display it uninterrupted when the\nrecipe completes.  The difference between them is in how recipes that\ncontain recursive invocations of @code{make} are treated\n(@pxref{Recursion, ,Recursive Use of @code{make}}).  For all recipes\nwhich have no recursive lines, the @samp{target} and @samp{recurse}\nmodes behave identically.\n\nIf the @samp{recurse} mode is chosen, recipes that contain recursive\n@code{make} invocations are treated the same as other targets: the\noutput from the recipe, including the output from the recursive\n@code{make}, is saved and printed after the entire recipe is complete.\nThis ensures output from all the targets built by a given recursive\n@code{make} instance are grouped together, which may make the output\neasier to understand.  However it also leads to long periods of time\nduring the build where no output is seen, followed by large bursts of\noutput.  If you are not watching the build as it proceeds, but instead\nviewing a log of the build after the fact, this may be the best option\nfor you.\n\nIf you are watching the output, the long gaps of quiet during the\nbuild can be frustrating.  The @samp{target} output synchronization\nmode detects when @code{make} is going to be invoked recursively,\nusing the standard methods, and it will not synchronize the output of\nthose lines.  The recursive @code{make} will perform the\nsynchronization for its targets and the output from each will be\ndisplayed immediately when it completes.  Be aware that output from\nrecursive lines of the recipe are not synchronized (for example if\nthe recursive line prints a message before running @code{make}, that\nmessage will not be synchronized).\n\nThe @samp{line} mode can be useful for front-ends that are watching\nthe output of @code{make} to track when recipes are started and\ncompleted.\n\nSome programs invoked by @code{make} may behave differently if they\ndetermine they're writing output to a terminal versus a file (often\ndescribed as ``interactive'' vs. ``non-interactive'' modes).  For\nexample, many programs that can display colorized output will not do\nso if they determine they are not writing to a terminal.  If your\nmakefile invokes a program like this then using the output\nsynchronization options will cause the program to believe it's running\nin ``non-interactive'' mode even though the output will ultimately go\nto the terminal.\n\n@node Parallel Input\n@subsection Input During Parallel Execution\n@cindex input during parallel execution\n@cindex parallel execution, input during\n@cindex standard input\n\nTwo processes cannot both take input from the same device at the same\ntime.  To make sure that only one recipe tries to take input from the\nterminal at once, @code{make} will invalidate the standard input\nstreams of all but one running recipe.  If another recipe attempts to\nread from standard input it will usually incur a fatal error (a\n@samp{Broken pipe} signal).\n@cindex broken pipe\n\nIt is unpredictable which recipe will have a valid standard input stream\n(which will come from the terminal, or wherever you redirect the standard\ninput of @code{make}).  The first recipe run will always get it first, and\nthe first recipe started after that one finishes will get it next, and so\non.\n\nWe will change how this aspect of @code{make} works if we find a better\nalternative.  In the mean time, you should not rely on any recipe using\nstandard input at all if you are using the parallel execution feature; but\nif you are not using this feature, then standard input works normally in\nall recipes.\n\n@node Errors\n@section Errors in Recipes\n@cindex errors (in recipes)\n@cindex recipes, errors in\n@cindex exit status (errors)\n\nAfter each shell invocation returns, @code{make} looks at its exit\nstatus.  If the shell completed successfully (the exit status is\nzero), the next line in the recipe is executed in a new shell; after\nthe last line is finished, the rule is finished.\n\nIf there is an error (the exit status is nonzero), @code{make} gives up on\nthe current rule, and perhaps on all rules.\n\nSometimes the failure of a certain recipe line does not indicate a problem.\nFor example, you may use the @code{mkdir} command to ensure that a\ndirectory exists.  If the directory already exists, @code{mkdir} will\nreport an error, but you probably want @code{make} to continue regardless.\n\n@cindex @code{-} (in recipes)\nTo ignore errors in a recipe line, write a @samp{-} at the beginning\nof the line's text (after the initial tab).  The @samp{-} is discarded\nbefore the line is passed to the shell for execution.\n\nNote that the beginning of a recipe line is interpreted differently when\nusing @code{.ONESHELL} (@pxref{One Shell, ,Using One Shell}).\n\nFor example,\n\n@example\n@group\nclean:\n        -rm -f *.o\n@end group\n@end example\n@cindex @code{rm} (shell command)\n\n@noindent\nThis causes @code{make} to continue even if @code{rm} is unable to\nremove a file.\n\n@cindex @code{-i}\n@cindex @code{--ignore-errors}\nWhen you run @code{make} with the @samp{-i} or @samp{--ignore-errors}\nflag, errors are ignored in all recipes of all rules.  A rule in the\nmakefile for the special target @code{.IGNORE} has the same effect, if\nthere are no prerequisites.  This is less flexible but sometimes useful.\n\nWhen errors are to be ignored, because of either a @samp{-} or the\n@samp{-i} flag, @code{make} treats an error return just like success,\nexcept that it prints out a message that tells you the status code\nthe shell exited with, and says that the error has been ignored.\n\nWhen an error happens that @code{make} has not been told to ignore,\nit implies that the current target cannot be correctly remade, and neither\ncan any other that depends on it either directly or indirectly.  No further\nrecipes will be executed for these targets, since their preconditions\nhave not been achieved.\n\n\n@cindex @code{-k}\n@cindex @code{--keep-going}\nNormally @code{make} gives up immediately in this circumstance, returning a\nnonzero status.  However, if the @samp{-k} or @samp{--keep-going}\nflag is specified, @code{make}\ncontinues to consider the other prerequisites of the pending targets,\nremaking them if necessary, before it gives up and returns nonzero status.\nFor example, after an error in compiling one object file, @samp{make -k}\nwill continue compiling other object files even though it already knows\nthat linking them will be impossible.  @xref{Options Summary, ,Summary of Options}.\n\nThe usual behavior assumes that your purpose is to get the specified\ntargets up to date; once @code{make} learns that this is impossible, it\nmight as well report the failure immediately.  The @samp{-k} option says\nthat the real purpose is to test as many of the changes made in the\nprogram as possible, perhaps to find several independent problems so\nthat you can correct them all before the next attempt to compile.  This\nis why Emacs' @code{compile} command passes the @samp{-k} flag by\ndefault.\n@cindex Emacs (@code{M-x compile})\n\n@findex .DELETE_ON_ERROR@r{, errors in recipes}\n@cindex deletion of target files\n@cindex removal of target files\n@cindex target, deleting on error\nUsually when a recipe line fails, if it has changed the target file at all,\nthe file is corrupted and cannot be used---or at least it is not\ncompletely updated.  Yet the file's time stamp says that it is now up to\ndate, so the next time @code{make} runs, it will not try to update that\nfile.  The situation is just the same as when the shell is killed by a\nsignal; @pxref{Interrupts}.  So generally the right thing to do is to\ndelete the target file if the recipe fails after beginning to change\nthe file.  @code{make} will do this if @code{.DELETE_ON_ERROR} appears\nas a target.  This is almost always what you want @code{make} to do, but\nit is not historical practice; so for compatibility, you must explicitly\nrequest it.\n\n@node Interrupts\n@section Interrupting or Killing @code{make}\n@cindex interrupt\n@cindex signal\n@cindex deletion of target files\n@cindex removal of target files\n@cindex target, deleting on interrupt\n@cindex killing (interruption)\n\nIf @code{make} gets a fatal signal while a shell is executing, it may\ndelete the target file that the recipe was supposed to update.  This is\ndone if the target file's last-modification time has changed since\n@code{make} first checked it.\n\nThe purpose of deleting the target is to make sure that it is remade from\nscratch when @code{make} is next run.  Why is this?  Suppose you type\n@kbd{Ctrl-c} while a compiler is running, and it has begun to write an\nobject file @file{foo.o}.  The @kbd{Ctrl-c} kills the compiler, resulting\nin an incomplete file whose last-modification time is newer than the source\nfile @file{foo.c}.  But @code{make} also receives the @kbd{Ctrl-c} signal\nand deletes this incomplete file.  If @code{make} did not do this, the next\ninvocation of @code{make} would think that @file{foo.o} did not require\nupdating---resulting in a strange error message from the linker when it\ntries to link an object file half of which is missing.\n\n@cindex .PRECIOUS, preserving targets\nYou can prevent the deletion of a target file in this way by making the\nspecial target @code{.PRECIOUS} depend on it.  Before remaking a target,\n@code{make} checks to see whether it appears on the prerequisites of\n@code{.PRECIOUS}, and thereby decides whether the target should be deleted\nif a signal happens.  Some reasons why you might do this are that the\ntarget is updated in some atomic fashion, or exists only to record a\nmodification-time (its contents do not matter), or must exist at all\ntimes to prevent other sorts of trouble.\n\nAlthough @code{make} does its best to clean up there are certain situations\nin which cleanup is impossible.  For example, @code{make} may be killed by\nan uncatchable signal.  Or, one of the programs make invokes may be killed\nor crash, leaving behind an up-to-date but corrupt target file: @code{make}\nwill not realize that this failure requires the target to be cleaned.  Or\n@code{make} itself may encounter a bug and crash.\n\nFor these reasons it's best to write @emph{defensive recipes}, which won't\nleave behind corrupted targets even if they fail.  Most commonly these\nrecipes create temporary files rather than updating the target directly,\nthen rename the temporary file to the final target name.  Some compilers\nalready behave this way, so that you don't need to write a defensive recipe.\n\n@node Recursion\n@section Recursive Use of @code{make}\n@cindex recursion\n@cindex subdirectories, recursion for\n\nRecursive use of @code{make} means using @code{make} as a command in a\nmakefile.  This technique is useful when you want separate makefiles for\nvarious subsystems that compose a larger system.  For example, suppose you\nhave a sub-directory @file{subdir} which has its own makefile, and you would\nlike the containing directory's makefile to run @code{make} on the\nsub-directory.  You can do it by writing this:\n\n@example\nsubsystem:\n        cd subdir && $(MAKE)\n@end example\n\n@noindent\nor, equivalently, this (@pxref{Options Summary, ,Summary of Options}):\n\n@example\nsubsystem:\n        $(MAKE) -C subdir\n@end example\n@cindex @code{-C}\n@cindex @code{--directory}\n\nYou can write recursive @code{make} commands just by copying this example,\nbut there are many things to know about how they work and why, and about\nhow the sub-@code{make} relates to the top-level @code{make}.  You may\nalso find it useful to declare targets that invoke recursive\n@code{make} commands as @samp{.PHONY} (for more discussion on when\nthis is useful, see @ref{Phony Targets}).\n\n@vindex @code{CURDIR}\nFor your convenience, when GNU @code{make} starts (after it has\nprocessed any @code{-C} options) it sets the variable @code{CURDIR} to\nthe pathname of the current working directory.  This value is never\ntouched by @code{make} again: in particular note that if you include\nfiles from other directories the value of @code{CURDIR} does not\nchange.  The value has the same precedence it would have if it were\nset in the makefile (by default, an environment variable @code{CURDIR}\nwill not override this value).  Note that setting this variable has no\nimpact on the operation of @code{make} (it does not cause @code{make}\nto change its working directory, for example).\n\n@menu\n* MAKE Variable::               The special effects of using @samp{$(MAKE)}.\n* Variables/Recursion::         How to communicate variables to a sub-@code{make}.\n* Options/Recursion::           How to communicate options to a sub-@code{make}.\n* -w Option::                   How the @samp{-w} or @samp{--print-directory} option\n                                  helps debug use of recursive @code{make} commands.\n@end menu\n\n@node MAKE Variable\n@subsection How the @code{MAKE} Variable Works\n@vindex MAKE\n@cindex recursion, and @code{MAKE} variable\n\nRecursive @code{make} commands should always use the variable @code{MAKE},\nnot the explicit command name @samp{make}, as shown here:\n\n@example\n@group\nsubsystem:\n        cd subdir && $(MAKE)\n@end group\n@end example\n\nThe value of this variable is the file name with which @code{make} was\ninvoked.  If this file name was @file{/bin/make}, then the recipe executed\nis @samp{cd subdir && /bin/make}.  If you use a special version of\n@code{make} to run the top-level makefile, the same special version will be\nexecuted for recursive invocations.\n@cindex @code{cd} (shell command)\n\n@cindex +, and recipes\nAs a special feature, using the variable @code{MAKE} in the recipe of\na rule alters the effects of the @samp{-t} (@samp{--touch}), @samp{-n}\n(@samp{--just-print}), or @samp{-q} (@w{@samp{--question}}) option.\nUsing the @code{MAKE} variable has the same effect as using a @samp{+}\ncharacter at the beginning of the recipe line.  @xref{Instead of\nExecution, ,Instead of Executing the Recipes}.  This special feature\nis only enabled if the @code{MAKE} variable appears directly in the\nrecipe: it does not apply if the @code{MAKE} variable is referenced\nthrough expansion of another variable.  In the latter case you must\nuse the @samp{+} token to get these special effects.\n\nNote that the beginning of a recipe line is interpreted differently when\nusing @code{.ONESHELL} (@pxref{One Shell, ,Using One Shell}).\n\nConsider the command @samp{make -t} in the above example.  (The\n@samp{-t} option marks targets as up to date without actually running\nany recipes; see @ref{Instead of Execution}.)  Following the usual\ndefinition of @samp{-t}, a @samp{make -t} command in the example would\ncreate a file named @file{subsystem} and do nothing else.  What you\nreally want it to do is run @samp{@w{cd subdir &&} @w{make -t}}; but\nthat would require executing the recipe, and @samp{-t} says not to\nexecute recipes.\n@cindex @code{-t}, and recursion\n@cindex recursion, and @code{-t}\n@cindex @code{--touch}, and recursion\n\nThe special feature makes this do what you want: whenever a recipe\nline of a rule contains the variable @code{MAKE}, the flags @samp{-t},\n@samp{-n} and @samp{-q} do not apply to that line.  Recipe lines\ncontaining @code{MAKE} are executed normally despite the presence of a\nflag that causes most recipes not to be run.  The usual\n@code{MAKEFLAGS} mechanism passes the flags to the sub-@code{make}\n(@pxref{Options/Recursion, ,Communicating Options to a\nSub-@code{make}}), so your request to touch the files, or print the\nrecipes, is propagated to the subsystem.\n\n@node Variables/Recursion\n@subsection Communicating Variables to a Sub-@code{make}\n@cindex sub-@code{make}\n@cindex environment, and recursion\n@cindex exporting variables\n@cindex variables, environment\n@cindex variables, exporting\n@cindex recursion, and environment\n@cindex recursion, and variables\n\nVariable values of the top-level @code{make} can be passed to the\nsub-@code{make} through the environment by explicit request.  These\nvariables are defined in the sub-@code{make} as defaults, but they do\nnot override variables defined in the makefile used by\nthe sub-@code{make} unless you use the @samp{-e} switch (@pxref{Options\nSummary, ,Summary of Options}).\n\nTo pass down, or @dfn{export}, a variable, @code{make} adds the\nvariable and its value to the environment for running each line of the\nrecipe.  The sub-@code{make}, in turn, uses the environment to\ninitialize its table of variable values.  @xref{Environment,\n,Variables from the Environment}.\n\nExcept by explicit request, @code{make} exports a variable only if it\nis either defined in the environment initially, or if set on the command\nline and its name consists only of letters, numbers, and underscores.\n\n@cindex SHELL, exported value\nThe value of the @code{make} variable @code{SHELL} is not exported.\nInstead, the value of the @code{SHELL} variable from the invoking\nenvironment is passed to the sub-@code{make}.  You can force\n@code{make} to export its value for @code{SHELL} by using the\n@code{export} directive, described below.  @xref{Choosing the Shell}.\n\nThe special variable @code{MAKEFLAGS} is always exported (unless you\nunexport it).  @code{MAKEFILES} is exported if you set it to anything.\n\n@code{make} automatically passes down variable values that were defined\non the command line, by putting them in the @code{MAKEFLAGS} variable.\n@iftex\nSee the next section.\n@end iftex\n@ifnottex\n@xref{Options/Recursion}.\n@end ifnottex\n\nVariables are @emph{not} normally passed down if they were created by\ndefault by @code{make} (@pxref{Implicit Variables, ,Variables Used by\nImplicit Rules}).  The sub-@code{make} will define these for\nitself.\n\n@findex export\nIf you want to export specific variables to a sub-@code{make}, use the\n@code{export} directive, like this:\n\n@example\nexport @var{variable} @dots{}\n@end example\n\n@noindent\n@findex unexport\nIf you want to @emph{prevent} a variable from being exported, use the\n@code{unexport} directive, like this:\n\n@example\nunexport @var{variable} @dots{}\n@end example\n\n@noindent\nIn both of these forms, the arguments to @code{export} and\n@code{unexport} are expanded, and so could be variables or functions\nwhich expand to a (list of) variable names to be (un)exported.\n\nGNU Make will add any variable you export to the environment of all child\nprocesses.  However, be aware that some child processes themselves will not\naccept all types of variables.  For example, many modern shells will clean the\nincoming environment by removing or hiding any environment variable whose name\nis invalid for the shell (e.g., alphanumeric plus underscore).  There is\nnothing GNU Make can do about the behavior of these child processes: if you\nwant your makefile to be maximally portable you should choose simple variable\nnames for all exported variables.\n\nAs a convenience, you can define a variable and export it at the same\ntime by doing:\n\n@example\nexport @var{variable} = value\n@end example\n\n@noindent\nhas the same result as:\n\n@example\n@var{variable} = value\nexport @var{variable}\n@end example\n\n@noindent\nand\n\n@example\nexport @var{variable} := value\n@end example\n\n@noindent\nhas the same result as:\n\n@example\n@var{variable} := value\nexport @var{variable}\n@end example\n\nLikewise,\n\n@example\nexport @var{variable} += value\n@end example\n\n@noindent\nis just like:\n\n@example\n@var{variable} += value\nexport @var{variable}\n@end example\n\n@noindent\n@xref{Appending Assignment, ,Appending More Text to Variables}.\n\nYou may notice that the @code{export} and @code{unexport} directives\nwork in @code{make} in the same way they work in the shell, @code{sh}.\n\nIf you want all variables to be exported by default, you can use\n@code{export} by itself:\n\n@example\nexport\n@end example\n\n@noindent\nThis tells @code{make} that variables which are not explicitly mentioned in an\n@code{export} or @code{unexport} directive should be exported.  Any variable\ngiven in an @code{unexport} directive will still @emph{not} be exported.\n\n@findex .EXPORT_ALL_VARIABLES\nAnother way to export variables by default is to add the special target\n@code{.EXPORT_ALL_VARIABLES} to your makefile.  This will be ignored by other\nvariants of @code{make}.\n\nWhen using @code{export} by itself or @code{.EXPORT_ALL_VARIABLES} to export\nvariables by default, only variables whose names consist solely of\nalphanumerics and underscores will be exported.  To export other variables you\nmust specifically mention them in an @code{export} directive.\n\nAdding a variable's value to the environment requires it to be expanded.  If\nexpanding a variable has side-effects (such as the @code{info} or @code{eval}\nor similar functions) then these side-effects will be seen every time a\ncommand is invoked.  You can avoid this by ensuring that such variables have\nnames which are not exportable by default.  However, a better solution is to\n@emph{not} use this ``export by default'' facility at all, and instead\nexplicitly @code{export} the relevant variables by name.\n\nBe aware that exporting all variables can have serious performance impacts,\nespecially for recursive variables used in conjunction with the @code{shell}\nfunction.  We recommend you avoid this and instead export only the specific\nvariables needed to run your commands.  If you do need to export all\nvariables, use simple variable assignment wherever possible, especially when\ninvoking the @code{shell} function.\n\nYou can use @code{unexport} by itself to tell @code{make} @emph{not} to export\nvariables by default.  Since this is the default behavior, you would only need\nto do this if @code{export} had been used by itself earlier (in an included\nmakefile, perhaps).  You @strong{cannot} use @code{export} and @code{unexport}\nby themselves to have variables exported for some recipes and not for others.\nThe last @code{export} or @code{unexport} directive that appears by itself\ndetermines the behavior for the entire run of @code{make}.\n\n@vindex MAKELEVEL\n@cindex recursion, level of\nAs a special feature, the variable @code{MAKELEVEL} is changed when it\nis passed down from level to level.  This variable's value is a string\nwhich is the depth of the level as a decimal number.  The value is\n@samp{0} for the top-level @code{make}; @samp{1} for a sub-@code{make},\n@samp{2} for a sub-sub-@code{make}, and so on.  The incrementation\nhappens when @code{make} sets up the environment for a recipe.\n\nThe main use of @code{MAKELEVEL} is to test it in a conditional\ndirective (@pxref{Conditionals, ,Conditional Parts of Makefiles}); this\nway you can write a makefile that behaves one way if run recursively and\nanother way if run directly by you.\n\n@vindex MAKEFILES\nYou can use the variable @code{MAKEFILES} to cause all sub-@code{make}\ncommands to use additional makefiles.  The value of @code{MAKEFILES} is\na whitespace-separated list of file names.  This variable, if defined in\nthe outer-level makefile, is passed down through the environment; then\nit serves as a list of extra makefiles for the sub-@code{make} to read\nbefore the usual or specified ones.  @xref{MAKEFILES Variable, ,The\nVariable @code{MAKEFILES}}.\n\n@node Options/Recursion\n@subsection Communicating Options to a Sub-@code{make}\n@cindex options, and recursion\n@cindex recursion, and options\n\n@vindex MAKEFLAGS\nFlags such as @samp{-s} and @samp{-k} are passed automatically to the\nsub-@code{make} through the variable @code{MAKEFLAGS}.  This variable is\nset up automatically by @code{make} to contain the flag letters that\n@code{make} received.  Thus, if you do @w{@samp{make -ks}} then\n@code{MAKEFLAGS} gets the value @samp{ks}.\n\nAs a consequence, every sub-@code{make} gets a value for @code{MAKEFLAGS} in\nits environment.  In response, it takes the flags from that value and\nprocesses them as if they had been given as arguments.  @xref{Options Summary,\n,Summary of Options}.  This means that, unlike other environment variables,\n@code{MAKEFLAGS} specified in the environment take precedence over\n@code{MAKEFLAGS} specified in the makefile.\n\nThe value of @code{MAKEFLAGS} is a possibly empty group of characters\nrepresenting single-letter options that take no argument, followed by a space\nand any options that take arguments or which have long option names.  If an\noption has both single-letter and long options, the single-letter option is\nalways preferred.  If there are no single-letter options on the command line,\nthen the value of @code{MAKEFLAGS} starts with a space.\n\n@cindex command line variable definitions, and recursion\n@cindex variables, command line, and recursion\n@cindex recursion, and command line variable definitions\nLikewise variables defined on the command line are passed to the\nsub-@code{make} through @code{MAKEFLAGS}.  Words in the value of\n@code{MAKEFLAGS} that contain @samp{=}, @code{make} treats as variable\ndefinitions just as if they appeared on the command line.\n@xref{Overriding, ,Overriding Variables}.\n\n@cindex @code{-C}, and recursion\n@cindex @code{-f}, and recursion\n@cindex @code{-o}, and recursion\n@cindex @code{-W}, and recursion\n@cindex @code{--directory}, and recursion\n@cindex @code{--file}, and recursion\n@cindex @code{--old-file}, and recursion\n@cindex @code{--assume-old}, and recursion\n@cindex @code{--assume-new}, and recursion\n@cindex @code{--new-file}, and recursion\n@cindex recursion, and @code{-C}\n@cindex recursion, and @code{-f}\n@cindex recursion, and @code{-o}\n@cindex recursion, and @code{-W}\nThe options @samp{-C}, @samp{-f}, @samp{-o}, and @samp{-W} are not put\ninto @code{MAKEFLAGS}; these options are not passed down.\n\n@cindex @code{-j}, and recursion\n@cindex @code{--jobs}, and recursion\n@cindex recursion, and @code{-j}\n@cindex job slots, and recursion\nThe @samp{-j} option is a special case (@pxref{Parallel, ,Parallel Execution}).\nIf you set it to some numeric value @samp{N} and your operating system\nsupports it (most any UNIX system will; others typically won't), the\nparent @code{make} and all the sub-@code{make}s will communicate to\nensure that there are only @samp{N} jobs running at the same time\nbetween them all.  Note that any job that is marked recursive\n(@pxref{Instead of Execution, ,Instead of Executing Recipes})\ndoesn't count against the total jobs (otherwise we could get @samp{N}\nsub-@code{make}s running and have no slots left over for any real work!)\n\nIf your operating system doesn't support the above communication, then\nno @samp{-j} is added to @code{MAKEFLAGS}, so that sub-@code{make}s\nrun in non-parallel mode.  If the @w{@samp{-j}} option were passed down\nto sub-@code{make}s you would get many more jobs running in parallel\nthan you asked for.  If you give @samp{-j} with no numeric argument,\nmeaning to run as many jobs as possible in parallel, this is passed\ndown, since multiple infinities are no more than one.\n\nIf you do not want to pass the other flags down, you must change the\nvalue of @code{MAKEFLAGS}, for example like this:\n\n@example\nsubsystem:\n        cd subdir && $(MAKE) MAKEFLAGS=\n@end example\n\n@vindex MAKEOVERRIDES\nThe command line variable definitions really appear in the variable\n@code{MAKEOVERRIDES}, and @code{MAKEFLAGS} contains a reference to this\nvariable.  If you do want to pass flags down normally, but don't want to\npass down the command line variable definitions, you can reset\n@code{MAKEOVERRIDES} to empty, like this:\n\n@example\nMAKEOVERRIDES =\n@end example\n\n@noindent\n@cindex Arg list too long\n@cindex E2BIG\nThis is not usually useful to do.  However, some systems have a small\nfixed limit on the size of the environment, and putting so much\ninformation into the value of @code{MAKEFLAGS} can exceed it.  If you\nsee the error message @samp{Arg list too long}, this may be the problem.\n(For strict compliance with POSIX, changing @code{MAKEOVERRIDES} does\nnot affect @code{MAKEFLAGS} if the special target @samp{.POSIX} appears\nin the makefile.  You probably do not care about this.)\n\n@vindex MFLAGS\nA similar variable @code{MFLAGS} exists also, for historical\ncompatibility.  It has the same value as @code{MAKEFLAGS} except that it\ndoes not contain the command line variable definitions, and it always\nbegins with a hyphen unless it is empty (@code{MAKEFLAGS} begins with a\nhyphen only when it begins with an option that has no single-letter\nversion, such as @samp{--no-print-directory}).  @code{MFLAGS} was\ntraditionally used explicitly in the recursive @code{make} command, like\nthis:\n\n@example\nsubsystem:\n        cd subdir && $(MAKE) $(MFLAGS)\n@end example\n\n@noindent\nbut now @code{MAKEFLAGS} makes this usage redundant.  If you want your\nmakefiles to be compatible with old @code{make} programs, use this\ntechnique; it will work fine with more modern @code{make} versions too.\n\n@cindex setting options from environment\n@cindex options, setting from environment\n@cindex setting options in makefiles\n@cindex options, setting in makefiles\nThe @code{MAKEFLAGS} variable can also be useful if you want to have\ncertain options, such as @samp{-k} (@pxref{Options Summary, ,Summary of\nOptions}), set each time you run @code{make}.  You simply put a value for\n@code{MAKEFLAGS} in your environment.  You can also set @code{MAKEFLAGS} in\na makefile, to specify additional flags that should also be in effect for\nthat makefile.  (Note that you cannot use @code{MFLAGS} this way.  That\nvariable is set only for compatibility; @code{make} does not interpret a\nvalue you set for it in any way.)\n\nWhen @code{make} interprets the value of @code{MAKEFLAGS} (either from the\nenvironment or from a makefile), it first prepends a hyphen if the value\ndoes not already begin with one.  Then it chops the value into words\nseparated by blanks, and parses these words as if they were options given\non the command line (except that @samp{-C}, @samp{-f}, @samp{-h},\n@samp{-o}, @samp{-W}, and their long-named versions are ignored; and there\nis no error for an invalid option).\n\nIf you do put @code{MAKEFLAGS} in your environment, you should be sure not\nto include any options that will drastically affect the actions of\n@code{make} and undermine the purpose of makefiles and of @code{make}\nitself.  For instance, the @samp{-t}, @samp{-n}, and @samp{-q} options, if\nput in one of these variables, could have disastrous consequences and would\ncertainly have at least surprising and probably annoying effects.\n\nIf you'd like to run other implementations of @code{make} in addition\nto GNU @code{make}, and hence do not want to add GNU\n@code{make}-specific flags to the @code{MAKEFLAGS} variable, you can\nadd them to the @code{GNUMAKEFLAGS} variable instead.  This variable\nis parsed just before @code{MAKEFLAGS}, in the same way as\n@code{MAKEFLAGS}.  When @code{make} constructs @code{MAKEFLAGS} to\npass to a recursive @code{make} it will include all flags, even those\ntaken from @code{GNUMAKEFLAGS}.  As a result, after parsing\n@code{GNUMAKEFLAGS} GNU @code{make} sets this variable to the empty\nstring to avoid duplicating flags during recursion.\n\nIt's best to use @code{GNUMAKEFLAGS} only with flags which won't\nmaterially change the behavior of your makefiles.  If your makefiles\nrequire GNU Make anyway then simply use @code{MAKEFLAGS}.  Flags such\nas @samp{--no-print-directory} or @samp{--output-sync} may be\nappropriate for @code{GNUMAKEFLAGS}.\n\n@node -w Option\n@subsection The @samp{--print-directory} Option\n@cindex directories, printing them\n@cindex printing directories\n@cindex recursion, and printing directories\n\nIf you use several levels of recursive @code{make} invocations, the\n@samp{-w} or @w{@samp{--print-directory}} option can make the output a\nlot easier to understand by showing each directory as @code{make}\nstarts processing it and as @code{make} finishes processing it.  For\nexample, if @samp{make -w} is run in the directory @file{/u/gnu/make},\n@code{make} will print a line of the form:\n\n@example\nmake: Entering directory `/u/gnu/make'.\n@end example\n\n@noindent\nbefore doing anything else, and a line of the form:\n\n@example\nmake: Leaving directory `/u/gnu/make'.\n@end example\n\n@noindent\nwhen processing is completed.\n\n@cindex @code{-C}, and @code{-w}\n@cindex @code{--directory}, and @code{--print-directory}\n@cindex recursion, and @code{-w}\n@cindex @code{-w}, and @code{-C}\n@cindex @code{-w}, and recursion\n@cindex @code{--print-directory}, and @code{--directory}\n@cindex @code{--print-directory}, and recursion\n@cindex @code{--no-print-directory}\n@cindex @code{--print-directory}, disabling\n@cindex @code{-w}, disabling\nNormally, you do not need to specify this option because @samp{make}\ndoes it for you: @samp{-w} is turned on automatically when you use the\n@samp{-C} option, and in sub-@code{make}s.  @code{make} will not\nautomatically turn on @samp{-w} if you also use @samp{-s}, which says to\nbe silent, or if you use @samp{--no-print-directory} to explicitly\ndisable it.\n\n@node Canned Recipes\n@section Defining Canned Recipes\n@cindex canned recipes\n@cindex recipes, canned\n@cindex sequences of commands\n@cindex commands, sequences of\n\nWhen the same sequence of commands is useful in making various\ntargets, you can define it as a canned sequence with the @code{define}\ndirective, and refer to the canned sequence from the recipes for those\ntargets.  The canned sequence is actually a variable, so the name must\nnot conflict with other variable names.\n\nHere is an example of defining a canned recipe:\n\n@example\ndefine run-yacc =\nyacc $(firstword $^)\nmv y.tab.c $@@\nendef\n@end example\n@cindex @code{yacc}\n\n@noindent\nHere @code{run-yacc} is the name of the variable being defined;\n@code{endef} marks the end of the definition; the lines in between are the\ncommands.  The @code{define} directive does not expand variable references\nand function calls in the canned sequence; the @samp{$} characters,\nparentheses, variable names, and so on, all become part of the value of the\nvariable you are defining.\n@xref{Multi-Line, ,Defining Multi-Line Variables},\nfor a complete explanation of @code{define}.\n\nThe first command in this example runs Yacc on the first prerequisite of\nwhichever rule uses the canned sequence.  The output file from Yacc is\nalways named @file{y.tab.c}.  The second command moves the output to the\nrule's target file name.\n\nTo use the canned sequence, substitute the variable into the recipe of a\nrule.  You can substitute it like any other variable\n(@pxref{Reference, ,Basics of Variable References}).\nBecause variables defined by @code{define} are recursively expanded\nvariables, all the variable references you wrote inside the @code{define}\nare expanded now.  For example:\n\n@example\nfoo.c : foo.y\n        $(run-yacc)\n@end example\n\n@noindent\n@samp{foo.y} will be substituted for the variable @samp{$^} when it occurs in\n@code{run-yacc}'s value, and @samp{foo.c} for @samp{$@@}.\n\nThis is a realistic example, but this particular one is not needed in\npractice because @code{make} has an implicit rule to figure out these\ncommands based on the file names involved\n(@pxref{Implicit Rules, ,Using Implicit Rules}).\n\n@cindex @@, and @code{define}\n@cindex -, and @code{define}\n@cindex +, and @code{define}\nIn recipe execution, each line of a canned sequence is treated just as\nif the line appeared on its own in the rule, preceded by a tab.  In\nparticular, @code{make} invokes a separate sub-shell for each line.  You\ncan use the special prefix characters that affect command lines\n(@samp{@@}, @samp{-}, and @samp{+}) on each line of a canned sequence.\n@xref{Recipes, ,Writing Recipes in Rules}.\nFor example, using this canned sequence:\n\n@example\ndefine frobnicate =\n@@echo \"frobnicating target $@@\"\nfrob-step-1 $< -o $@@-step-1\nfrob-step-2 $@@-step-1 -o $@@\nendef\n@end example\n\n@noindent\n@code{make} will not echo the first line, the @code{echo} command.\nBut it @emph{will} echo the following two recipe lines.\n\nOn the other hand, prefix characters on the recipe line that refers to\na canned sequence apply to every line in the sequence.  So the rule:\n\n@example\nfrob.out: frob.in\n        @@$(frobnicate)\n@end example\n\n@noindent\ndoes not echo @emph{any} recipe lines.\n(@xref{Echoing, ,Recipe Echoing}, for a full explanation of @samp{@@}.)\n\n@node Empty Recipes\n@section Using Empty Recipes\n@cindex empty recipes\n@cindex recipes, empty\n\nIt is sometimes useful to define recipes which do nothing.  This is done\nsimply by giving a recipe that consists of nothing but whitespace.  For\nexample:\n\n@example\ntarget: ;\n@end example\n\n@noindent\ndefines an empty recipe for @file{target}.  You could also use a line\nbeginning with a recipe prefix character to define an empty recipe,\nbut this would be confusing because such a line looks empty.\n\n@findex .DEFAULT@r{, and empty recipes}\nYou may be wondering why you would want to define a recipe that does\nnothing.  One reason this is useful is to prevent a target from\ngetting implicit recipes (from implicit rules or the @code{.DEFAULT}\nspecial target; @pxref{Implicit Rules} and @pxref{Last Resort,\n,Defining Last-Resort Default Rules}).\n\nEmpty recipes can also be used to avoid errors for targets that will\nbe created as a side-effect of another recipe: if the target does not\nexist the empty recipe ensures that @code{make} won't complain that it\ndoesn't know how to build the target, and @code{make} will assume the\ntarget is out of date.\n\nYou may be inclined to define empty recipes for targets that are not\nactual files, but only exist so that their prerequisites can be\nremade.  However, this is not the best way to do that, because the\nprerequisites may not be remade properly if the target file actually\ndoes exist.  @xref{Phony Targets, ,Phony Targets}, for a better way to\ndo this.\n\n@node Using Variables\n@chapter How to Use Variables\n@cindex variable\n@cindex value\n\nA makefile @dfn{variable} is a name defined to represent a string of text,\ncalled the variable's @dfn{value}.  (In some other versions of @code{make},\nvariables are called @dfn{macros}.)\n@cindex macro\n\nVariable values can contain lists of file names, options to pass to compilers,\nprograms to run, directories to look in for source files, directories to write\noutput in, or anything else you can imagine.\n\nThere are two different ways, called @dfn{flavors}, that a variable can hold\nits value internally (@pxref{Flavors, The Two Flavors of Variables}).  The\nflavor of the variable is specified by the assignment operator used when it is\ndefined (@pxref{Setting, ,Setting Variables}).\n\nWhen a variable is @dfn{referenced} in targets, prerequisites, recipes, and\nother parts of the makefile (@pxref{Reference, ,Basics of Variable\nReferences}), the reference is replaced with the value of the variable.  This\nis called @dfn{expanding} the variable (@pxref{Expanding, ,How Expansion\nWorks}).  A variable reference is not always expanded immediately as the\nmakefile is parsed; expansion can be deferred until later depending on the\ncontext.  @xref{Reading Makefiles, ,How @code{make} Reads a Makefile}.\n\nWhen a variable reference is expanded, the value it expands to is that of its\nmost recent definition at the time of expansion.  In other words, variables\nin @code{make} are @dfn{dynamically scoped}.\n\n@menu\n* Variable Naming::             Choosing names for variables.\n* Reference::                   How to use the value of a variable.\n* Flavors::                     Variables come in two flavors.\n* Expanding::                   How text is expanded by @code{make}.\n* Values::                      All the ways variables get their values.\n* Setting::                     How to set a variable in the makefile.\n* Substitution Refs::           Substituting values in variable expansion.\n* Override Directive::          How to set a variable in the makefile even if\n                                  the user has set it with a command argument.\n* Multi-Line::                  An alternate way to set a variable\n                                  to a multi-line string.\n* Undefine Directive::          How to undefine a variable so that it appears\n                                  as if it was never set.\n* Environment::                 Variable values can come from the environment.\n* Target-specific::             Variable values can be defined on a per-target\n                                  basis.\n* Pattern-specific::            Target-specific variable values can be applied\n                                  to a group of targets that match a pattern.\n* Suppressing Inheritance::     Suppress inheritance of variables.\n* Special Variables::           Variables with special meaning or behavior.\n@end menu\n\n@node Variable Naming\n@section Names of Variables\n@cindex names of variables\n@cindex variables, names of\n\nA variable name may be any sequence of characters not containing @samp{:},\n@samp{#}, @samp{=}, or whitespace.\n\nVariable names are case-sensitive.  For instance the names @samp{foo},\n@samp{FOO}, and @samp{Foo} all refer to different variables.\n\nIt is traditional to use upper case letters in variable names, but we\nrecommend using lower case letters for variable names that serve internal\npurposes in the makefile, and reserving upper case for parameters that\ncontrol implicit rules or for parameters that the user should override with\ncommand options. @xref{Overriding, ,Overriding Variables}.\n\nAlthough GNU Make allows most characters to be part of a variable name, shells\ngenerally only support variable names containing letters, numbers, and\nunderscores.  Consider this when defining variables that need to be exported\nto the shell.  @xref{Variables/Recursion, ,Communicating Variables to a\nSub-@code{make}}.\n\nVariable names beginning with @samp{.} followed by uppercase letters are\nreserved by the POSIX standard.  GNU Make reserves variable names beginning\nwith @samp{.} and containing uppercase letters and non-alphabetic characters.\nThese variables may be given special meaning in future versions of GNU Make.\n\nA few variables have names that are a single punctuation character or\njust a few characters.  These are the @dfn{automatic variables}, and\nthey have particular specialized uses.  @xref{Automatic Variables}.\n\n@node Reference\n@section Basics of Variable References\n@cindex variables, how to reference\n@cindex reference to variables\n@cindex @code{$}, in variable reference\n@cindex dollar sign (@code{$}), in variable reference\n\nTo reference a variable's value, write a dollar sign (@samp{$}) followed by\nthe name of the variable in parentheses or braces: both @code{$(foo)} and\n@code{$@{foo@}} are references to the variable @samp{foo}.\n\nIf the variable name consists of a single character then the parenthesis or\nbraces can be omitted.  Thus @code{$A} is a reference to the variable\n@samp{A}.  We recommend using parenthesis or braces even for single-letter\nvariable names to avoid confusion (e.g., @code{$foo} refers to the variable\n@samp{f} followed by the string @samp{oo} which may not be clear) unless\nomitting them gives significant readability improvements.  One place where\nreadability is often improved by omitting parentheses and braces is with\nautomatic variables (@pxref{Automatic Variables}).\n\nThis special behavior of @samp{$} is why you must write @samp{$$} to have the\neffect of a single dollar sign in a makefile.\n\nVariable references can be used in any context: targets, prerequisites,\nrecipes, most directives, and new variable values.  Here is an\nexample of a common case, where a variable holds the names of all the\nobject files in a program:\n\n@example\n@group\nobjects = program.o foo.o utils.o\nprogram : $(objects)\n        cc -o program $(objects)\n\n$(objects) : defs.h\n@end group\n@end example\n\n@menu\n* Computed Names::              Computing the name of a variable reference.\n@end menu\n\n@node Computed Names\n@subsection Computed Variable Names\n@cindex nested variable reference\n@cindex computed variable name\n@cindex variables, computed names\n@cindex variables, nested references\n@cindex variables, @samp{$} in name\n@cindex @code{$}, in variable name\n@cindex dollar sign (@code{$}), in variable name\n\nMost of the time static variable names are sufficient, but in more complex\nsituations it can be extremely useful to dynamically construct variable names.\nThis can be achieved by using a variable reference inside a reference to a\nvariable.  This is referred to as a @dfn{computed variable name} or a\n@dfn{nested variable reference}.  For example,\n\n@example\nx = y\ny = z\na := $($(x))\n@end example\n\n@noindent\ndefines the variable @samp{a} to have the value @code{z}, in this way:\n@code{make} first expands @code{$(x)} to the value @code{y}, which means\n@code{$($(x))} expands to @code{$(y)}, and @code{$(y)} expands to the string\n@code{z}.  Thus the name of the variable to reference is not stated\nexplicitly; it is computed by expansion of @samp{$(x)}.\n\nThe previous example shows two levels of nesting, but any number of levels\nare possible.  For example, here are three levels:\n\n@example\nx = y\ny = z\nz = u\na := $($($(x)))\n@end example\n\n@noindent\nHere the innermost @code{$(x)} expands to @samp{y}, so @code{$($(x))}\nexpands to @code{$(y)} which in turn expands to @samp{z}; now we have\n@code{$(z)}, which expands to @samp{u}.\n\nReferences to recursively-expanded variables within a variable name are\nre-expanded in the usual fashion.  For example:\n\n@example\nx = $(y)\ny = z\nz = Hello\na := $($(x))\n@end example\n\n@noindent\ndefines @samp{a} as @code{Hello}: @code{$($(x))} becomes @code{$($(y))}\nwhich becomes @code{$(z)} which becomes @samp{Hello}.\n\nNested variable references can also contain modified references and function\ninvocations (@pxref{Functions, ,Functions for Transforming Text}), just like\nany other reference.  For example, using the @code{subst} function\n(@pxref{Text Functions, ,Functions for String Substitution and Analysis}):\n\n@example\n@group\nx = variable1\nvariable2 := Hello\ny = $(subst 1,2,$(x))\nz = y\na := $($($(z)))\n@end group\n@end example\n\n@noindent\neventually defines @code{a} as @samp{Hello}.  It is doubtful that anyone\nwould ever want to write a nested reference as convoluted as this one, but\nit works: @code{$($($(z)))} expands to @code{$($(y))} which becomes\n@code{$($(subst 1,2,$(x)))}.  This gets the value @samp{variable1} from\n@samp{x} and changes it by substitution to @samp{variable2}, so that the\nentire string becomes @code{$(variable2)}, a simple variable reference\nwhose value is @samp{Hello}.\n\nA computed variable name need not consist entirely of a single variable\nreference.  It can contain several variable references, as well as some\ninvariant text.  For example,\n\n@example\n@group\na_dirs := dira dirb\n1_dirs := dir1 dir2\n@end group\n\n@group\na_files := filea fileb\n1_files := file1 file2\n@end group\n\n@group\nifeq \"$(use_a)\" \"yes\"\na1 := a\nelse\na1 := 1\nendif\n@end group\n\n@group\nifeq \"$(use_dirs)\" \"yes\"\ndf := dirs\nelse\ndf := files\nendif\n\ndirs := $($(a1)_$(df))\n@end group\n@end example\n\n@noindent\nwill give @samp{dirs} the same value as @samp{a_dirs}, @samp{1_dirs},\n@samp{a_files} or @samp{1_files} depending on the settings of @samp{use_a}\nand @samp{use_dirs}.\n\nComputed variable names can also be used in substitution references:\n\n@example\n@group\na_objects := a.o b.o c.o\n1_objects := 1.o 2.o 3.o\n\nsources := $($(a1)_objects:.o=.c)\n@end group\n@end example\n\n@noindent\ndefines @samp{sources} as either @samp{a.c b.c c.c} or @samp{1.c 2.c 3.c},\ndepending on the value of @samp{a1}.\n\nThe only restriction on this sort of use of nested variable references is that\nthey cannot specify part of the name of a function to be called.  This is\nbecause the test for a recognized function name is done before the expansion\nof nested references.  For example,\n\n@example\n@group\nifdef do_sort\nfunc := sort\nelse\nfunc := strip\nendif\n@end group\n\n@group\nbar := a d b g q c\n@end group\n\n@group\nfoo := $($(func) $(bar))\n@end group\n@end example\n\n@noindent\nattempts to give @samp{foo} the value of the variable @samp{sort a d b g q c}\nor @samp{strip a d b g q c}, rather than giving @samp{a d b g q c} as the\nargument to either the @samp{sort} or the @samp{strip} function.  This\nrestriction could be removed in the future if that change is shown to be a\ngood idea.\n\nYou can also use computed variable names in the left-hand side of a variable\nassignment, or in a @samp{define} directive, as in:\n\n@example\ndir = foo\n$(dir)_sources := $(wildcard $(dir)/*.c)\ndefine $(dir)_print =\nlpr $($(dir)_sources)\nendef\n@end example\n\n@noindent\nThis example defines the variables @samp{dir}, @samp{foo_sources}, and\n@samp{foo_print}.\n\nNote that @dfn{nested variable references} are quite different from\n@dfn{recursively expanded variables}\n(@pxref{Flavors, ,The Two Flavors of Variables}), though both are\nused together in complex ways when doing makefile programming.\n\n@node Flavors\n@section The Two Flavors of Variables\n@cindex flavors of variables\n@cindex variables, flavors\n\nThere are two different ways that a variable in GNU Make can behave when a\nreference is expanded; we call them the @dfn{flavors} of variables.\n\nThe assignment operator used to set the variable's value (@pxref{Setting, ,\nSetting Variables}) determines both the way in which the value is handled\nduring assignment, and also the flavor of the variable's value after\nassignment.  Although there are a number of different assignment operators,\nall variables will end up as one of the two flavors.\n\n@menu\n* Recursive Variables::         Recursive variables delay expansion.\n* Simple Variables::            Simple variables expand immediately.\n@end menu\n\n@node Recursive Variables\n@subsection Recursively Expanded Variable Assignment\n@cindex recursive variable expansion\n@cindex recursively expanded variables\n@cindex variables, recursively expanded\n\nThe first flavor of variable is a @dfn{recursively expanded} variable.  This\nis the standard type of variable supported by all versions of @code{make} and\ndefined by POSIX.\n\nWhen a recursively expanded variable is expanded due to a variable reference,\nthe value of the variable is also expanded.  This is called @dfn{recursive\nexpansion}.\n\nConsider this makefile:\n\n@example\nfoo = $(bar)\nbar = $(ugh)\nugh = Huh?\n\nall: ; @@echo $(foo)\n@end example\n\nAfter @code{make} parses this makefile the value of the variable @code{foo}\nwill be the string @samp{$(bar)}, the value of the variable @code{bar} will be\nthe string @samp{$(ugh)}, and the value of the variable @code{ugh} will be the\nstring @samp{Huh?}.\n\nIf you run @code{make} with this makefile, it will print @samp{Huh?}: the\nvariable reference @samp{$(foo)} expands to @samp{$(bar)} which expands to\n@samp{$(ugh)} which finally expands to @samp{Huh?}.\n\nThe big advantage of this flavor of variable is that it can refer to variables\nwhich have not been defined yet.  This means:\n\n@example\nCFLAGS = $(include_dirs) -O\ninclude_dirs = -Ifoo -Ibar\n@end example\n\n@noindent\nwill do what was intended, even though when @code{CFLAGS} was set the variable\n@samp{include_dirs} was not set yet: when @code{CFLAGS} is expanded in a\nrecipe it will expand to the value of @code{include_dirs} at that time,\nyielding @samp{-Ifoo -Ibar -O}.\n\nThis flavor also allows variables to contain references to automatic variables\n(@pxref{Automatic Variables}); since automatic variables are not set until a\nrecipe is going to be run it would not work if the variable's value was\nexpanded when the variable was assigned.\n\nThere are also a number of disadvantages.  The first one is that programmers\nare not used to this type of assignment and may be confused.  In a makefile\nlike this:\n\n@example\n@group\nCFLAGS = -g\nDEBUG_FLAGS = $(CFLAGS)\n\nCFLAGS = -O2\nOPT_FLAGS = $(CFLAGS)\n@end group\n@end example\n\n@noindent\nwhen @code{DEBUG_FLAGS} and @code{OPT_FLAGS} are expanded later they will\n@emph{both} contain the value @samp{-O2}; each assignment to @code{CFLAGS}\noverwrites the previous assignment and whatever the last value was, will be\nseen when references to @samp{$(CFLAGS)} are expanded.\n\nAnother disadvantage is that you cannot reference a variable in its own value;\nfor instance this:\n@cindex loops in variable expansion\n@cindex variables, loops in expansion\n\n@example\nCFLAGS = $(CFLAGS) -O\n@end example\n\n@noindent\nwill generate an error due to an infinite loop in the variable expansion.  If\nyou want to append to the end of the variable you can use the @samp{+=}\nassignment operator (@pxref{Appending Assignment, , Appending More Text to\nVariables}) to deal with this.  The fact that a ``recursively expanded''\nvariable cannot contain a recursive reference to itself is one of those\nidiosyncratic proofs that naming is hard in computer science.\n\nA third disadvantage is that the value will be re-expanded every time the\nvariable is referenced.  If the expansion of that variable is expensive--for\nexample if it contains functions (@pxref{Functions, ,Functions for\nTransforming Text}) which are expensive to execute--this can impact the\nperformance of @code{make}.  It may also cause functions like @code{wildcard}\nand @code{shell} to give unpredictable results since you cannot easily control\nwhen they are called, or how many times.\n\n@node Simple Variables\n@subsection Simply Expanded Variable Assignment\nTo avoid the problems and inconveniences of recursively expanded variables,\nGNU Make provides another flavor of variable value: @dfn{simply expanded\nvariables}.\n\nThe value of a simply expanded variable is expanded only once, immediately\nwhen the variable is assigned in the makefile.  All references to variables\nand functions in its value are resolved at the time the variable is assigned.\nWhen the variable is later expanded it is not re-expanded (thus it is not\n``recursive''): the stored value is used verbatim as the result of the\nexpansion.\n\nIf we write the example from the previous section using simply expanded\nvariables (note the use of @samp{:=} for assignment), we will get more\ntraditional behavior:\n\n@example\n@group\nCFLAGS = -g\nDEBUG_FLAGS := $(CFLAGS)\n\nCFLAGS = -O2\nOPT_FLAGS := $(CFLAGS)\n@end group\n@end example\n\nNow the value of @code{DEBUG_FLAGS} will be @samp{-g} while the value of\n@code{OPT_FLAGS} is @samp{-O2} as expected.\n\nSimply expanded variables simplify makefile programming because they work like\nvariables in most other programming languages.  They allow you to redefine a\nvariable using its own value.  And they make the use of functions more\nefficient since they are expanded only one time, not each time the variable is\nreferenced.\n\n@node Expanding\n@section How Expansion Works\n@cindex expanding variables\n@cindex variables, expanding\n\nThe process of @dfn{expanding} a string in @code{make} means, to replace each\nvariable reference (@pxref{Reference, ,Basics of Variable References}) with\nthe value of that variable.  All text which is not part of a variable\nreference is preserved in the result.\n\nExpansion proceeds from @emph{right to left} and from @emph{inside out}.  For\nexample, given the following text:\n\n@example\nsave the $(shell $(date)) for $(event)\n@end example\n\n@noindent\nthe expansion would keep the static string @samp{save the } (starting from\nright to left), then expand the variable named @code{date} (going from inside\nout) and use the result as the argument to the GNU Make function @code{shell}\n(@pxref{Shell Function, ,The @code{shell} Function}).  The output of that\nshell command is appended into the result of the expansion.  Then the static\nstring @samp{ for } is added, and finally the expansion of the variable\n@code{event}.\n\nThe expansion of a variable that has not been defined is not an error: instead\nit silently expands to an empty string.  This behavior is required by POSIX;\nhowever it can be controlled in GNU Make (@pxref{Warnings, ,Makefile\nWarnings}).\n\nAlthough expansion always proceeds in the same way, deciding @emph{when} text\nis expanded depends on the context in which it's used: often text is expanded\nas the makefile is parsed.  In other situations the expansion is delayed (for\nexample the text of a recipe is not expanded until the recipe is invoked).\n@xref{Reading Makefiles, ,How @code{make} Reads a Makefile}.\n\nAlso, deciding how to interpret the value of a variable during expansion\ndepends on the type of variable.  @xref{Flavors, ,The Two Flavors of Variables}.\n\n@node Values\n@section How Variables Get Their Values\n@cindex variables, how they get their values\n@cindex value, how a variable gets it\n\nVariables can get values in several different ways:\n\n@itemize @bullet\n@item\nYou can specify an overriding value on the command line when you run\n@code{make}.  @xref{Overriding, ,Overriding Variables}.\n\n@item\nYou can specify a value in the makefile, either with an assignment\n(@pxref{Setting, ,Setting Variables}) or with a verbatim definition\n(@pxref{Multi-Line, ,Defining Multi-Line Variables}).\n\n@item\nYou can specify a short-lived value with the @code{let} function\n(@pxref{Let Function}) or with the @code{foreach} function\n(@pxref{Foreach Function}).\n\n@item\nVariables and their values in the environment when @code{make} is invoked are\nimported as @code{make} variables.  @xref{Environment, ,Variables from the\nEnvironment}.\n\n@item\nSeveral variables are given new values for each rule that @code{make} invokes,\nbefore the recipe for that rule is expanded.  @xref{Automatic Variables}.\n\n@item\nSeveral variables have default initial values.\n@xref{Implicit Variables, ,Variables Used by Implicit Rules}.\n@end itemize\n\n@node Setting\n@section Setting Variables\n@cindex setting variables\n@cindex variables, setting\n@cindex =\n@cindex :=\n@cindex ::=\n\nA makefile variable is set by writing a line starting with the variable name\nfollowed by one of the assignment operators @code{=}, @code{:=}, @code{::=},\n@code{:::=}, or @code{!=}.  Whitespace can optionally come before the variable\nname, between the variable name and the operator, and after the operator but\nbefore the value, and is discarded.  Whatever text follows becomes the value\nof the variable.  For example:\n\n@example\nobjects = main.o foo.o bar.o utils.o\n@end example\n\n@noindent\ndefines a variable named @code{objects} to contain the value @samp{main.o\nfoo.o bar.o utils.o}.  The whitespace before and after the assignment operator\nis ignored.\n\nIf there is ambiguity between the end of the variable name and the start of\nthe assignment operator (@pxref{Setting, ,Setting Variables}), GNU Make always\nprefers the operator.  For example:\n\n@example\nFOO?=bar\n@end example\n\n@noindent\nwill always be parsed into the tokens @samp{FOO}, @samp{?=}, and @samp{bar}.\nOn the other hand, this:\n\n@example\nFOO? = bar\n@end example\n\n@noindent\nwill be parsed as @samp{FOO?}, @samp{=}, and @samp{bar}.  For this reason,\namong others, it's a best practice to always add whitespace around operators\nwhen setting @code{make} variables.\n\nThere is no limit on the length of the value of a variable, except the amount\nof memory on the computer.  You can split the value of a variable into\nmultiple physical lines, for readability, by adding backslashes\n(@pxref{Splitting Lines, ,Splitting Long Lines}).\n\nThe assignment operator controls two things: first, how the value (the\nstring after the operator) is handled when the variable is set, and second how\nthe value is handled when the variable is expanded (i.e., its flavor:\n@pxref{Flavors, The Two Flavors of Variables}).\n\nThe @samp{=} operator creates a @emph{recursively expanded} variable.  The\nvalue of the variable @emph{is not} expanded when the variable is defined: the\nright hand side of the assignment operator is used verbatim as the value of\nthe variable.\n\nThe @samp{:=} and @samp{::=} operators create a @emph{simply expanded}\nvariable.  The value of the variable @emph{is} expanded when the variable is\ndefined.  These operators are interchangeable: @samp{:=} is specific to GNU\nMake while @samp{::=} has the same behavior and is specified by POSIX.\n\nThe @samp{:::=} operator creates a @emph{recursively expanded} variable, like\n@samp{=}.  The value of the variable @emph{is} expanded when the variable is\ndefined, like @samp{:=} / @samp{::=}.  After the expansion, the resulting\nvalue is @emph{escaped} by substituting each dollar sign in the value with two\ndollar signs (@samp{$$}).  @xref{Immediate Assignment, ,Immediately Expanded\nVariable Assignment}.\n\nThe shell assignment operator @samp{!=} creates a @emph{recursively expanded}\nvariable.  The value of the variable is obtained by passing the expanded\nright-hand side to the shell as a command, and collecting its output.\n@xref{Shell Assignment, Shell Variable Assignment}.\n\nEach of these assignment operators can also be prefixed with a question mark\n(@samp{?}) to make them @dfn{conditional}.  The right-hand side is only\nconsidered if the variable is not yet set.  If it is set, the value of the\nassignment is ignored.  @xref{Conditional Assignment, ,Conditional Variable\nAssignment}.\n\nFinally, more text can be added to an already-set variable value using the\nappending assignment operator @samp{+=}.  @xref{Appending Assignment,\n,Appending More Text to Variables}.\n\n@menu\n* Immediate Assignment::        Recursive variables with immediate expansion.\n* Shell Assignment::            Assigning variables to shell output.\n* Conditional Assignment::      Assigning variables only if not yet defined.\n* Appending Assignment::        How to append to the value of a variable.\n* Whitespace in Values::        Leading and trailing whitespace in values.\n@end menu\n\n@node Immediate Assignment\n@subsection Immediately Expanded Variable Assignment\n@cindex immediate variable assignment\n@cindex variables, immediate assignment\n@cindex :::=\n\nThe @samp{:::=} assignment operator allows for immediate expansion, but unlike\nsimple assignment the resulting variable is recursive and will be re-expanded\nagain on every use.  In order to avoid unexpected results, after the value is\nimmediately expanded it will automatically be quoted: all instances of\n@samp{$} in the value after expansion will be converted into @samp{$$}.  This\ntype of assignment uses the @samp{:::=} operator.  For example,\n\n@example\n@group\nvar = first\nOUT :::= $(var)\nvar = second\n@end group\n@end example\n\n@noindent\nresults in the @code{OUT} variable containing the text @samp{first}, while here:\n\n@example\n@group\nvar = one$$two\nOUT :::= $(var)\nvar = three\n@end group\n@end example\n\n@noindent\nresults in the @code{OUT} variable containing the text @samp{one$$two}.  The\nvalue is expanded when the variable is assigned, so the result is the\nexpansion of the first value of @code{var}, @samp{one$two}; then the value is\nre-escaped before the assignment is complete giving the final result of\n@samp{one$$two}.\n\nThis is generally equivalent to the GNU Make @samp{:=} / @samp{::=} assignment\noperators, but there are a few differences:\n\nFirst, since the variable is a recursive variable when appending to it with\nthe @samp{+=} operator the value on the right-hand side is not expanded\nimmediately as it would be using @samp{:=} / @samp{::=}.\n\nSecond, expansion of these variables is slightly less efficient since they\nwill be re-expanded when they are referenced.  However since all dollar signs\nare escaped the expansion simply un-escapes the value, it won't expand any\nvariables or run any functions.\n\nHere is another example:\n\n@example\n@group\nvar = one$$two\nOUT :::= $(var)\nOUT += $(var)\nvar = three$$four\n@end group\n@end example\n\nAfter this, the value of @code{OUT} is the text @samp{one$$two $(var)}.  When\nthis variable is used it will be expanded and the result will be\n@samp{one$two three$four}.\n\nThis style of assignment is equivalent to the traditional BSD @code{make}\n@samp{:=} assignment operator, and different from GNU Make's @samp{:=}\nassignment operator.  The @samp{:::=} assignment operator was added to POSIX\nto provide portability.\n\n@node Shell Assignment\n@subsection Shell Variable Assignment\n@cindex shell variable assignment\n@cindex variables, shell assignment\n@cindex !=\n\nThe shell assignment operator @samp{!=} creates a @emph{recursively expanded}\nvariable.  The value of the variable is computed by first expanding the\nright-hand side of the assignment then invoking a shell and passing the\nexpanded value to the shell as a script to run.  The output generated by the\nshell (to standard out) is used as the value of the variable.\n\nIf the last character of output is a newline, that character is removed; all\nother newlines are replaced by spaces.  For example:\n\n@example\nhash != printf '\\043'\nfile_list != find . -name '*.c'\n@end example\n\nBecause the variable is recursively expanded you must take care to ensure\nthat, if the shell script outputs dollar signs which you don't want to be\nexpanded by @code{make} when the variable is expanded, you escape them with\ntwo dollar signs.\n\nThe @samp{!=} operator is portable to some other versions of @code{make} and\nis defined in the latest POSIX specifications.\n\nAlternatively, you can set a simply expanded variable to the result of running\na program using the @code{shell} function call.  @xref{Shell Function, , The\n@code{shell} Function}.  For example:\n\n@example\nhash := $(shell printf '\\043')\nvar := $(shell find . -name \"*.c\")\n@end example\n\nAs with the @code{shell} function, the exit status of the just-invoked\nshell script is stored in the @code{.SHELLSTATUS} variable when assigning with\n@samp{!=}.\n\n@node Conditional Assignment\n@subsection Conditional Variable Assignment\n@cindex conditional variable assignment\n@cindex variables, conditional assignment\n@cindex ?=\n@cindex ?:=\n@cindex ?::=\n@cindex ?:::=\n@cindex ?!=\n\nAny non-appending assignment operator (@samp{=}, @samp{:=}, @samp{::=},\n@samp{:::=}, @samp{!=}) can be prefixed with a conditional modifier, @samp{?}.\nWhen this modifier is used, the assignment will proceed normally according to\nthe base assignment operator, @emph{only if} the variable is not already\ndefined.\n\nIf the variable is already defined, the assignment is ignored and the\nright-hand side (value) of the assignment is not processed.\n\nFor example this statement:\n\n@example\nFOO ?= bar\n@end example\n\n@noindent\nis equivalent to this (@pxref{Origin Function, ,The @code{origin} Function}):\n\n@example\nifeq ($(origin FOO), undefined)\n  FOO = bar\nendif\n@end example\n\nMore generally a statement of the form:\n\n@example\nNAME ?<op> VALUE\n@end example\n\nwill do nothing if the variable @code{NAME} is defined, and will perform the\noperation @samp{NAME <op> VALUE} for any assignment operation @samp{<op>} if\n@code{NAME} is not defined.\n\nNote that a variable set to an empty value is still considered to be defined,\nso assignments modified with @samp{?} will not set that variable.\n\n@node Appending Assignment\n@subsection Appending More Text to Variables\n@cindex +=\n@cindex appending to variables\n@cindex variables, appending to\n\nOften it is useful to add more text to the value of a variable already defined.\nYou do this with a line containing @samp{+=}, like this:\n\n@example\nobjects += another.o\n@end example\n\n@noindent\nThis takes the value of the variable @code{objects}, and adds the text\n@samp{another.o} to it (preceded by a single space, if it has a value\nalready).  Thus:\n\n@example\nobjects = main.o foo.o bar.o utils.o\nobjects += another.o\n@end example\n\n@noindent\nsets @code{objects} to @samp{main.o foo.o bar.o utils.o another.o}.\n\nUsing @samp{+=} is similar to:\n\n@example\nobjects = main.o foo.o bar.o utils.o\nobjects := $(objects) another.o\n@end example\n\n@noindent\nbut differs in ways that become important when you use more complex values.\n\nWhen the variable in question has not been defined before, @samp{+=}\nacts just like normal @samp{=}: it defines a recursively-expanded\nvariable.  However, when there @emph{is} a previous definition, exactly\nwhat @samp{+=} does depends on what flavor of variable you defined\noriginally.  @xref{Flavors, ,The Two Flavors of Variables}, for an\nexplanation of the two flavors of variables.\n\nWhen you add to a variable's value with @samp{+=}, @code{make} acts\nessentially as if you had included the extra text in the initial definition of\nthe variable.  If you defined it first with @samp{:=} or @samp{::=}, making it\na simply-expanded variable, @samp{+=} adds to that simply-expanded definition,\nand expands the new text before appending it to the old value just as\n@samp{:=} does (see @ref{Setting, ,Setting Variables}, for a full explanation\nof @samp{:=} or @samp{::=}).  In fact,\n\n@example\nvariable := value\nvariable += more\n@end example\n\n@noindent\nis exactly equivalent to:\n\n@noindent\n@example\nvariable := value\nvariable := $(variable) more\n@end example\n\nOn the other hand, when you use @samp{+=} with a variable that you defined\nfirst to be recursively-expanded using plain @samp{=} or @samp{:::=},\n@code{make} appends the un-expanded text to the existing value, whatever it\nis.  This means that\n\n@example\n@group\nvariable = value\nvariable += more\n@end group\n@end example\n\n@noindent\nis roughly equivalent to:\n\n@example\n@group\ntemp = value\nvariable = $(temp) more\n@end group\n@end example\n\n@noindent\nexcept that of course it never defines a variable called @code{temp}.\nThe importance of this comes when the variable's old value contains\nvariable references.  Take this common example:\n\n@example\nCFLAGS = $(includes) -O\n@dots{}\nCFLAGS += -pg # enable profiling\n@end example\n\n@noindent\nThe first line defines the @code{CFLAGS} variable with a reference to another\nvariable, @code{includes}.  (@code{CFLAGS} is used by the rules for C\ncompilation; @pxref{Catalogue of Rules, ,Catalogue of Built-In Rules}.)\nUsing @samp{=} for the definition makes @code{CFLAGS} a recursively-expanded\nvariable, meaning @w{@samp{$(includes) -O}} is @emph{not} expanded when\n@code{make} processes the definition of @code{CFLAGS}.  Thus, @code{includes}\nneed not be defined yet for its value to take effect.  It only has to be\ndefined before any reference to @code{CFLAGS}.  If we tried to append to the\nvalue of @code{CFLAGS} without using @samp{+=}, we might do it like this:\n\n@example\nCFLAGS := $(CFLAGS) -pg # enable profiling\n@end example\n\n@noindent\nThis is pretty close, but not quite what we want.  Using @samp{:=}\nredefines @code{CFLAGS} as a simply-expanded variable; this means\n@code{make} expands the text @w{@samp{$(CFLAGS) -pg}} before setting the\nvariable.  If @code{includes} is not yet defined, we get @w{@samp{ -O\n-pg}}, and a later definition of @code{includes} will have no effect.\nConversely, by using @samp{+=} we set @code{CFLAGS} to the\n@emph{unexpanded} value @w{@samp{$(includes) -O -pg}}.  Thus we preserve\nthe reference to @code{includes}, so if that variable gets defined at\nany later point, a reference like @samp{$(CFLAGS)} still uses its\nvalue.\n\n@node Whitespace in Values\n@subsection Whitespace in Variable Values\n@cindex spaces, in variable values\n@cindex whitespace, in variable values\n@cindex variables, spaces in values\n\nAs described above, leading whitespace (whitespace between the assignment\noperator and the first non-whitespace character of the value) is discarded.\nAll whitespace after this is preserved, @emph{including} trailing spaces.\n\nUnwanted trailing whitespace can cause your makefile to behave in unexpected\nways: consider a variable reference such as @samp{$(dir)/file.c} if the\nvariable @samp{dir} had an unexpected trailing space in its value.  If your\ntext editor has settings to automatically strip all trailing spaces from files\nwhen they are saved, or to make trailing whitespace visible somehow, it's a\ngood idea to enable these facilities for makefiles.\n\nYou may occasionally need to define a variable value that begins with\nwhitespace.  To force whitespace at the beginning of a value you can use a\nvariable reference that expands to the empty string.  For example:\n\n@example\n@group\nemptystring :=\nspace := $(emptystring) $(emptystring)\n@end group\n@end example\n\nThe space between the assignment operator and the variable reference\n@samp{$(emptystring)} will be discarded, then the rest of the string is\nexpanded.  The @samp{emptystring} variables expand to no text, leaving just\nthe space as the value.\n\nThe second reference to @samp{$(emptystring)} is used to avoid having the\ntrailing space stripped by editors and to make the intent simpler to\nunderstand.  You don't have to use a second variable reference; you could also\nuse a comment such as:\n\n@example\n@group\nemptystring :=\nspace := $(emptystring) #<-one space\n@end group\n@end example\n\n@noindent\nto achieve the same effect.\n\nConversely, if you do @emph{not} want any whitespace at the end of the\nvariable value you must not put whitespace plus a comment on the end of the\nvariable value, such as this:\n\n@example\ndir := /foo/bar    # directory to put the frobs in\n@end example\n\n@noindent\nHere the value of the variable @code{dir} is @w{@samp{/foo/bar    }} (with\nfour trailing spaces), which was probably not the intention.  For this reason\nadding comments to the end of variable assignment lines is discouraged in\nmakefiles, and using preceding comment lines is preferred; for example:\n\n@example\n@group\n# directory to put the frobs in\ndir := /foo/bar\n@end group\n@end example\n\nAnother option is to make extensive use of the @code{strip} function\n(@pxref{Text Functions}) to ensure variable expansions have no leading or\ntrailing whitespace.\n\n@node Substitution Refs\n@section Substitution References\n@cindex modified variable reference\n@cindex substitution variable reference\n@cindex variables, modified reference\n@cindex variables, substitution reference\n\n@cindex variables, substituting suffix in\n@cindex suffix, substituting in variables\nA @dfn{substitution reference} substitutes the value of a variable with\nalterations that you specify.  It has the form\n@samp{$(@var{var}:@var{a}=@var{b})} (or\n@samp{$@{@var{var}:@var{a}=@var{b}@}}) and its meaning is to take the value\nof the variable @var{var}, replace every @var{a} at the end of a word with\n@var{b} in that value, and substitute the resulting string.\n\nWhen we say ``at the end of a word'', we mean that @var{a} must appear\neither followed by whitespace or at the end of the value in order to be\nreplaced; other occurrences of @var{a} in the value are unaltered.  For\nexample:\n\n@example\nfoo := a.o b.o l.a c.o\nbar := $(foo:.o=.c)\n@end example\n\n@noindent\nsets @samp{bar} to @samp{a.c b.c l.a c.c}.  @xref{Setting, ,Setting Variables}.\n\nA substitution reference is shorthand for the @code{patsubst}\nexpansion function (@pxref{Text Functions, ,Functions for String Substitution and Analysis}):\n@samp{$(@var{var}:@var{a}=@var{b})} is equivalent to\n@samp{$(patsubst %@var{a},%@var{b},@var{var})}.  We provide\nsubstitution references as well as @code{patsubst} for compatibility\nwith other implementations of @code{make}.\n\nAnother type of substitution reference lets you use the full power of\nthe @code{patsubst} function.  It has the same form\n@samp{$(@var{var}:@var{a}=@var{b})} described above, except that now\n@var{a} must contain a single @samp{%} character.  This case is\nequivalent to @samp{$(patsubst @var{a},@var{b},$(@var{var}))}.\n@xref{Text Functions, ,Functions for String Substitution and Analysis},\nfor a description of the @code{patsubst} function.  For example:\n\n@example\n@group\nfoo := a.o b.o l.a c.o\nbar := $(foo:%.o=%.c)\n@end group\n@end example\n\n@noindent\nsets @samp{bar} to @samp{a.c b.c l.a c.c}.\n\n@node Override Directive\n@section The @code{override} Directive\n@findex override\n@cindex overriding with @code{override}\n@cindex variables, overriding\n\nIf a variable has been set with a command argument\n(@pxref{Overriding, ,Overriding Variables}),\nthen ordinary assignments in the makefile are ignored.  If you want to set\nthe variable in the makefile even though it was set with a command\nargument, you can use an @code{override} directive, which is a line that\nlooks like this:\n\n@example\noverride @var{variable} = @var{value}\n@end example\n\n@noindent\nor\n\n@example\noverride @var{variable} := @var{value}\n@end example\n\nTo append more text to a variable defined on the command line, use:\n\n@example\noverride @var{variable} += @var{more text}\n@end example\n\n@noindent\n@xref{Appending Assignment, ,Appending More Text to Variables}.\n\nVariable assignments marked with the @code{override} flag have a\nhigher priority than all other assignments, except another\n@code{override}.  Subsequent assignments or appends to this variable\nwhich are not marked @code{override} will be ignored.\n\nThe @code{override} directive was not invented for escalation in the war\nbetween makefiles and command arguments.  It was invented so you can alter\nand add to values that the user specifies with command arguments.\n\nFor example, suppose you always want the @samp{-g} switch when you run the\nC compiler, but you would like to allow the user to specify the other\nswitches with a command argument just as usual.  You could use this\n@code{override} directive:\n\n@example\noverride CFLAGS += -g\n@end example\n\nYou can also use @code{override} directives with @code{define} directives\n(@pxref{Multi-Line, , Defining Multi-Line Variables}).  This is done as you\nmight expect:\n\n@example\noverride define foo =\nbar\nendef\n@end example\n\n@node Multi-Line\n@section Defining Multi-Line Variables\n@findex define\n@findex endef\n@cindex multi-line variable definition\n@cindex variables, multi-line\n@cindex verbatim variable definition\n@cindex defining variables verbatim\n@cindex variables, defining verbatim\n\nAnother way to set the value of a variable is to use the @code{define}\ndirective.  This directive has an unusual syntax which allows newline\ncharacters to be included in the value, which is convenient for\ndefining both canned sequences of commands (@pxref{Canned Recipes,\n,Defining Canned Recipes}), and also sections of makefile syntax to\nuse with @code{eval} (@pxref{Eval Function}).\n\nThe @code{define} directive is followed on the same line by the name\nof the variable being defined and an (optional) assignment operator,\nand nothing more.  The value to give the variable appears on the\nfollowing lines.  The end of the value is marked by a line containing\njust the word @code{endef}.\n\nAside from this difference in syntax, @code{define} works just like\nany other variable definition.  The variable name may contain function\nand variable references, which are expanded when the directive is read\nto find the actual variable name to use.\n\nThe final newline before the @code{endef} is not included in the\nvalue; if you want your value to contain a trailing newline you must\ninclude a blank line.  For example in order to define a variable that\ncontains a newline character you must use @emph{two} empty lines, not one:\n\n@example\ndefine newline\n\n\nendef\n@end example\n\nYou may omit the variable assignment operator if you prefer.  If\nomitted, @code{make} assumes it to be @samp{=} and creates a\nrecursively-expanded variable (@pxref{Flavors, ,The Two Flavors of Variables}).\nWhen using a @samp{+=} operator, the value is appended to the previous\nvalue as with any other append operation: with a single space\nseparating the old and new values.\n\nYou may nest @code{define} directives: @code{make} will keep track of\nnested directives and report an error if they are not all properly\nclosed with @code{endef}.  Note that lines beginning with the recipe\nprefix character are considered part of a recipe, so any @code{define}\nor @code{endef} strings appearing on such a line will not be\nconsidered @code{make} directives.\n\n@example\ndefine two-lines\necho foo\necho $(bar)\nendef\n@end example\n\n@need 800\nWhen used in a recipe, the previous example is functionally equivalent\nto this:\n\n@example\ntwo-lines = echo foo; echo $(bar)\n@end example\n\n@noindent\nsince two commands separated by semicolon behave much like two separate\nshell commands.  However, note that using two separate lines means\n@code{make} will invoke the shell twice, running an independent sub-shell\nfor each line.  @xref{Execution, ,Recipe Execution}.\n\nIf you want variable definitions made with @code{define} to take\nprecedence over command-line variable definitions, you can use the\n@code{override} directive together with @code{define}:\n\n@example\noverride define two-lines =\nfoo\n$(bar)\nendef\n@end example\n\n@noindent\n@xref{Override Directive, ,The @code{override} Directive}.\n\n@node Undefine Directive\n@section Undefining Variables\n@findex undefine\n@cindex undefining variable\n\nIf you want to clear a variable, setting its value to empty is usually\nsufficient. Expanding such a variable will yield the same result (empty\nstring) regardless of whether it was set or not. However, if you are\nusing the @code{flavor} (@pxref{Flavor Function}) and\n@code{origin} (@pxref{Origin Function}) functions, there is a difference\nbetween a variable that was never set and a variable with an empty value.\nIn such situations you may want to use the @code{undefine} directive to\nmake a variable appear as if it was never set. For example:\n\n@example\n@group\nfoo := foo\nbar = bar\n\nundefine foo\nundefine bar\n\n$(info $(origin foo))\n$(info $(flavor bar))\n@end group\n@end example\n\nThis example will print ``undefined'' for both variables.\n\nIf you want to undefine a command-line variable definition, you can use\nthe @code{override} directive together with @code{undefine}, similar to\nhow this is done for variable definitions:\n\n@example\noverride undefine CFLAGS\n@end example\n\n@node Environment\n@section Variables from the Environment\n\n@cindex variables, environment\n@cindex environment\nVariables in @code{make} can come from the environment in which\n@code{make} is run.  Every environment variable that @code{make} sees\nwhen it starts up is transformed into a @code{make} variable with the\nsame name and value.  However, an explicit assignment in the makefile,\nor with a command argument, overrides the environment.  (If the\n@samp{-e} flag is specified, then values from the environment override\nassignments in the makefile.  @xref{Options Summary, ,Summary of\nOptions}.  But this is not recommended practice.)\n\nThus, by setting the variable @code{CFLAGS} in your environment, you can\ncause all C compilations in most makefiles to use the compiler switches you\nprefer.  This is safe for variables with standard or conventional meanings\nbecause you know that no makefile will use them for other things.  (Note\nthis is not totally reliable; some makefiles set @code{CFLAGS} explicitly\nand therefore are not affected by the value in the environment.)\n\nWhen @code{make} runs a recipe, some variables defined in the makefile\nare placed into the environment of each command @code{make} invokes.\nBy default, only variables that came from the @code{make}'s\nenvironment or set on its command line are placed into the environment\nof the commands.  You can use the @code{export} directive to pass\nother variables.  @xref{Variables/Recursion, , Communicating Variables\nto a Sub-@code{make}}, for full details.\n\nOther use of variables from the environment is not recommended.  It is not\nwise for makefiles to depend for their functioning on environment variables\nset up outside their control, since this would cause different users to get\ndifferent results from the same makefile.  This is against the whole\npurpose of most makefiles.\n\n@cindex SHELL, import from environment\nSuch problems would be especially likely with the variable\n@code{SHELL}, which is normally present in the environment to specify\nthe user's choice of interactive shell.  It would be very undesirable\nfor this choice to affect @code{make}; so, @code{make} handles the\n@code{SHELL} environment variable in a special way; see @ref{Choosing\nthe Shell}.\n\n@node Target-specific\n@section Target-specific Variable Values\n@cindex target-specific variables\n@cindex variables, target-specific\n\nVariable values in @code{make} are usually global; that is, they are the\nsame regardless of where they are evaluated (unless they're reset, of\ncourse).  Exceptions to that are variables defined with the @code{let}\nfunction (@pxref{Let Function}) or the @code{foreach} function\n(@pxref{Foreach Function}, and automatic variables\n(@pxref{Automatic Variables}).\n\nAnother exception are @dfn{target-specific variable values}.  This\nfeature allows you to define different values for the same variable,\nbased on the target that @code{make} is currently building.  As with\nautomatic variables, these values are only available within the context\nof a target's recipe (and in other target-specific assignments).\n\nSet a target-specific variable value like this:\n\n@example\n@var{target} @dots{} : @var{variable-assignment}\n@end example\n\nTarget-specific variable assignments can be prefixed with any or all of the\nspecial keywords @code{export}, @code{unexport}, @code{override}, or\n@code{private}; these apply their normal behavior to this instance of the\nvariable only.\n\nMultiple @var{target} values create a target-specific variable value for\neach member of the target list individually.\n\nThe @var{variable-assignment} can be any valid form of assignment; recursive\n(@samp{=}), simple (@samp{:=} or @samp{::=}), immediate (@samp{::=}), shell\n(@samp{!=}), or appending (@samp{+=}), and may be preceded by a conditional\nmodifier (@samp{?}).  The variable that appears within the\n@var{variable-assignment} is evaluated within the context of the target: thus,\nany previously-defined target-specific variable values will be in effect.\nNote that this variable is actually distinct from any ``global'' value: the\ntwo variables do not have to have the same flavor (recursive vs.@: simple).\n\nTarget-specific variables have the same priority as any other makefile\nvariable.  Variables provided on the command line (and in the\nenvironment if the @samp{-e} option is in force) will take precedence.\nSpecifying the @code{override} directive will allow the target-specific\nvariable value to be preferred.\n\nThere is one more special feature of target-specific variables: when\nyou define a target-specific variable that variable value is also in\neffect for all prerequisites of this target, and all their\nprerequisites, etc.@: (unless those prerequisites override that variable\nwith their own target-specific variable value).  So, for example, a\nstatement like this:\n\n@example\nprog : CFLAGS = -g\nprog : prog.o foo.o bar.o\n@end example\n\n@noindent\nwill set @code{CFLAGS} to @samp{-g} in the recipe for @file{prog}, but\nit will also set @code{CFLAGS} to @samp{-g} in the recipes that create\n@file{prog.o}, @file{foo.o}, and @file{bar.o}, and any recipes which\ncreate their prerequisites.\n\nBe aware that a given prerequisite will only be built once per\ninvocation of make, at most.  If the same file is a prerequisite of\nmultiple targets, and each of those targets has a different value for\nthe same target-specific variable, then the first target to be built\nwill cause that prerequisite to be built and the prerequisite will\ninherit the target-specific value from the first target.  It will\nignore the target-specific values from any other targets.\n\n@node Pattern-specific\n@section Pattern-specific Variable Values\n@cindex pattern-specific variables\n@cindex variables, pattern-specific\n\nIn addition to target-specific variable values\n(@pxref{Target-specific, ,Target-specific Variable Values}), GNU\n@code{make} supports pattern-specific variable values.  In this form,\nthe variable is defined for any target that matches the pattern\nspecified.\n\nSet a pattern-specific variable value like this:\n\n@example\n@var{pattern} @dots{} : @var{variable-assignment}\n@end example\nwhere @var{pattern} is a %-pattern.  As with target-specific variable\nvalues, multiple @var{pattern} values create a pattern-specific variable\nvalue for each pattern individually.  The @var{variable-assignment} can\nbe any valid form of assignment.  Any command line variable setting will\ntake precedence, unless @code{override} is specified.\n\nFor example:\n\n@example\n%.o : CFLAGS = -O\n@end example\n\n@noindent\nwill assign @code{CFLAGS} the value of @samp{-O} for all targets\nmatching the pattern @samp{%.o}.\n\nIf a target matches more than one pattern, the matching pattern-specific\nvariables with longer stems are interpreted first. This results in more\nspecific variables taking precedence over the more generic ones, for\nexample:\n\n@example\n%.o: %.c\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@\n\nlib/%.o: CFLAGS := -fPIC -g\n%.o: CFLAGS := -g\n\nall: foo.o lib/bar.o\n@end example\n\nIn this example the first definition of the @code{CFLAGS} variable\nwill be used to update @file{lib/bar.o} even though the second one\nalso applies to this target. Pattern-specific variables which result\nin the same stem length are considered in the order in which they\nwere defined in the makefile.\n\nPattern-specific variables are searched after any target-specific\nvariables defined explicitly for that target, and before target-specific\nvariables defined for the parent target.\n\n@node Suppressing Inheritance\n@section Suppressing Inheritance\n@findex private\n@cindex suppressing inheritance\n@cindex inheritance, suppressing\n\nAs described in previous sections, @code{make} variables are inherited\nby prerequisites.  This capability allows you to modify the behavior\nof a prerequisite based on which targets caused it to be rebuilt.  For\nexample, you might set a target-specific variable on a @code{debug}\ntarget, then running @samp{make debug} will cause that variable to be\ninherited by all prerequisites of @code{debug}, while just running\n@samp{make all} (for example) would not have that assignment.\n\nSometimes, however, you may not want a variable to be inherited.  For\nthese situations, @code{make} provides the @code{private} modifier.\nAlthough this modifier can be used with any variable assignment, it\nmakes the most sense with target- and pattern-specific variables.  Any\nvariable marked @code{private} will be visible to its local target but\nwill not be inherited by prerequisites of that target.  A global\nvariable marked @code{private} will be visible in the global scope but\nwill not be inherited by any target, and hence will not be visible\nin any recipe.\n\nAs an example, consider this makefile:\n@example\nEXTRA_CFLAGS =\n\nprog: private EXTRA_CFLAGS = -L/usr/local/lib\nprog: a.o b.o\n@end example\n\nDue to the @code{private} modifier, @samp{a.o} and @samp{b.o} will not\ninherit the @code{EXTRA_CFLAGS} variable assignment from the\n@code{prog} target.\n\n@node Special Variables\n@comment  node-name,  next,  previous,  up\n@section Other Special Variables\n@cindex makefiles, and special variables\n@cindex special variables\n\nGNU @code{make} supports some variables that have special properties.\n\n@table @code\n\n@vindex MAKEFILE_LIST\n@cindex makefiles, and @code{MAKEFILE_LIST} variable\n@cindex including (@code{MAKEFILE_LIST} variable)\n@item MAKEFILE_LIST\nContains the name of each makefile that is parsed by @code{make}, in\nthe order in which it was parsed.  The name is appended just\nbefore @code{make} begins to parse the makefile.  Thus, if the first\nthing a makefile does is examine the last word in this variable, it\nwill be the name of the current makefile.  Once the current makefile\nhas used @code{include}, however, the last word will be the\njust-included makefile.\n\nIf a makefile named @code{Makefile} has this content:\n\n@example\n@group\nname1 := $(lastword $(MAKEFILE_LIST))\n\ninclude inc.mk\n\nname2 := $(lastword $(MAKEFILE_LIST))\n\nall:\n        @@echo name1 = $(name1)\n        @@echo name2 = $(name2)\n@end group\n@end example\n\n@noindent\nthen you would expect to see this output:\n\n@example\n@group\nname1 = Makefile\nname2 = inc.mk\n@end group\n@end example\n\n@vindex .DEFAULT_GOAL\n@item .DEFAULT_GOAL\nSets the default goal to be used if no targets were specified on the\ncommand line (@pxref{Goals, , Arguments to Specify the Goals}).  The\n@code{.DEFAULT_GOAL} variable allows you to discover the current\ndefault goal, restart the default goal selection algorithm by clearing\nits value, or to explicitly set the default goal.  The following\nexample illustrates these cases:\n\n@example\n@group\n# Query the default goal.\nifeq ($(.DEFAULT_GOAL),)\n  $(warning no default goal is set)\nendif\n\n.PHONY: foo\nfoo: ; @@echo $@@\n\n$(warning default goal is $(.DEFAULT_GOAL))\n\n# Reset the default goal.\n.DEFAULT_GOAL :=\n\n.PHONY: bar\nbar: ; @@echo $@@\n\n$(warning default goal is $(.DEFAULT_GOAL))\n\n# Set our own.\n.DEFAULT_GOAL := foo\n@end group\n@end example\n\nThis makefile prints:\n\n@example\n@group\nno default goal is set\ndefault goal is foo\ndefault goal is bar\nfoo\n@end group\n@end example\n\nNote that assigning more than one target name to @code{.DEFAULT_GOAL} is\ninvalid and will result in an error.\n\n@vindex MAKE_RESTARTS\n@item MAKE_RESTARTS\nThis variable is set only if this instance of @code{make} has\nrestarted (@pxref{Remaking Makefiles, , How Makefiles Are Remade}): it\nwill contain the number of times this instance has restarted.  Note\nthis is not the same as recursion (counted by the @code{MAKELEVEL}\nvariable).  You should not set, modify, or export this variable.\n\n@vindex MAKE_TERMOUT\n@vindex MAKE_TERMERR\n@item MAKE_TERMOUT\n@itemx MAKE_TERMERR\nWhen @code{make} starts it will check whether stdout and stderr will\nshow their output on a terminal.  If so, it will set\n@code{MAKE_TERMOUT} and @code{MAKE_TERMERR}, respectively, to the name\nof the terminal device (or @code{true} if this cannot be determined).\nIf set these variables will be marked for export.  These variables\nwill not be changed by @code{make} and they will not be modified if\nalready set.\n\nThese values can be used (particularly in combination with output\nsynchronization (@pxref{Parallel Output, ,Output During Parallel\nExecution}) to determine whether @code{make} itself is writing to a\nterminal; they can be tested to decide whether to force recipe\ncommands to generate colorized output for example.\n\nIf you invoke a sub-@code{make} and redirect its stdout or stderr it\nis your responsibility to reset or unexport these variables as well,\nif your makefiles rely on them.\n\n@vindex .RECIPEPREFIX\n@item .RECIPEPREFIX\nThe first character of the value of this variable is used as the\ncharacter make assumes is introducing a recipe line.  If the variable\nis empty (as it is by default) that character is the standard tab\ncharacter.  For example, this is a valid makefile:\n\n@example\n@group\n.RECIPEPREFIX = >\nall:\n> @@echo Hello, world\n@end group\n@end example\n\nThe value of @code{.RECIPEPREFIX} can be changed multiple times; once set\nit stays in effect for all rules parsed until it is modified.\n\n@vindex .VARIABLES\n@item .VARIABLES\nExpands to a list of the @emph{names} of all global variables defined\nso far.  This includes variables which have empty values, as well as\nbuilt-in variables (@pxref{Implicit Variables, , Variables Used by\nImplicit Rules}), but does not include any variables which are only\ndefined in a target-specific context.  Note that any value you assign\nto this variable will be ignored; it will always return its special\nvalue.\n\n@c @vindex .TARGETS\n@c @item .TARGETS\n@c The second special variable is @code{.TARGETS}.  When expanded, the\n@c value consists of a list of all targets defined in all makefiles read\n@c up until that point.  Note it's not enough for a file to be simply\n@c mentioned in the makefile to be listed in this variable, even if it\n@c would match an implicit rule and become an ``implicit target''.  The\n@c file must appear as a target, on the left-hand side of a ``:'', to be\n@c considered a target for the purposes of this variable.\n\n@vindex .FEATURES\n@item .FEATURES\nExpands to a list of special features supported by this version of\n@code{make}.  Possible values include, but are not limited to:\n\n@table @samp\n\n@item archives\nSupports @code{ar} (archive) files using special file name syntax.\n@xref{Archives, ,Using @code{make} to Update Archive Files}.\n\n@item check-symlink\nSupports the @code{-L} (@code{--check-symlink-times}) flag.\n@xref{Options Summary, ,Summary of Options}.\n\n@item else-if\nSupports ``else if'' non-nested conditionals.  @xref{Conditional\nSyntax, ,Syntax of Conditionals}.\n\n@item extra-prereqs\nSupports the @code{.EXTRA_PREREQS} special target.\n\n@item grouped-target\nSupports grouped target syntax for explicit rules.  @xref{Multiple Targets,\n,Multiple Targets in a Rule}.\n\n@item guile\nHas GNU Guile available as an embedded extension language.\n@xref{Guile Integration, ,GNU Guile Integration}.\n\n@item jobserver\nSupports ``job server'' enhanced parallel builds.  @xref{Parallel,\n,Parallel Execution}.\n\n@item jobserver-fifo\nSupports ``job server'' enhanced parallel builds using named pipes.\n@xref{Integrating make, ,Integrating GNU @code{make}}.\n\n@item load\nSupports dynamically loadable objects for creating custom extensions.\n@xref{Loading Objects, ,Loading Dynamic Objects}.\n\n@item notintermediate\nSupports the @code{.NOTINTERMEDIATE} special target.\n@xref{Integrating make, ,Integrating GNU @code{make}}.\n\n@item oneshell\nSupports the @code{.ONESHELL} special target.  @xref{One Shell, ,Using\nOne Shell}.\n\n@item order-only\nSupports order-only prerequisites.  @xref{Prerequisite Types, ,Types\nof Prerequisites}.\n\n@item output-sync\nSupports the @code{--output-sync} command line option.  @xref{Options Summary,\n,Summary of Options}.\n\n@item second-expansion\nSupports secondary expansion of prerequisite lists.\n\n@item shell-export\nSupports exporting @code{make} variables to @code{shell} functions.\n\n@item shortest-stem\nUses the ``shortest stem'' method of choosing which pattern, of\nmultiple applicable options, will be used.  @xref{Pattern Match, ,How\nPatterns Match}.\n\n@item target-specific\nSupports target-specific and pattern-specific variable assignments.\n@xref{Target-specific, ,Target-specific Variable Values}.\n\n@item undefine\nSupports the @code{undefine} directive.  @xref{Undefine Directive}.\n@end table\n\n@vindex .INCLUDE_DIRS\n@item .INCLUDE_DIRS\nExpands to a list of directories that @code{make} searches for\nincluded makefiles (@pxref{Include, , Including Other Makefiles}).\nNote that modifying this variable's value does not change the list of\ndirectories which are searched.\n\n@vindex .EXTRA_PREREQS\n@item .EXTRA_PREREQS\nEach word in this variable is a new prerequisite which is added to\ntargets for which it is set.  These prerequisites differ from normal\nprerequisites in that they do not appear in any of the automatic\nvariables (@pxref{Automatic Variables}).  This allows prerequisites to\nbe defined which do not impact the recipe.\n\nConsider a rule to link a program:\n\n@example\nmyprog: myprog.o file1.o file2.o\n       $(CC) $(CFLAGS) $(LDFLAGS) -o $@@ $^ $(LDLIBS)\n@end example\n\nNow suppose you want to enhance this makefile to ensure that updates\nto the compiler cause the program to be re-linked.  You can add the\ncompiler as a prerequisite, but you must ensure that it's not passed\nas an argument to link command.  You'll need something like this:\n\n@example\nmyprog: myprog.o file1.o file2.o $(CC)\n       $(CC) $(CFLAGS) $(LDFLAGS) -o $@@ \\\n           $(filter-out $(CC),$^) $(LDLIBS)\n@end example\n\nThen consider having multiple extra prerequisites: they would all have\nto be filtered out.  Using @code{.EXTRA_PREREQS} and target-specific\nvariables provides a simpler solution:\n\n@example\nmyprog: myprog.o file1.o file2.o\n       $(CC) $(CFLAGS) $(LDFLAGS) -o $@@ $^ $(LDLIBS)\nmyprog: .EXTRA_PREREQS = $(CC)\n@end example\n\nThis feature can also be useful if you want to add prerequisites to a\nmakefile you cannot easily modify: you can create a new file such as\n@file{extra.mk}:\n\n@example\nmyprog: .EXTRA_PREREQS = $(CC)\n@end example\n\nthen invoke @code{make -f extra.mk -f Makefile}.\n\nSetting @code{.EXTRA_PREREQS} globally will cause those prerequisites\nto be added to all targets (which did not themselves override it with\na target-specific value).  Note @code{make} is smart enough not to add\na prerequisite listed in @code{.EXTRA_PREREQS} as a prerequisite to\nitself.\n\n@item .WARNINGS\nChanges the actions taken when @code{make} detects warning conditions in the\nmakefile.  @xref{Warnings, ,Makefile Warnings}.\n\n@end table\n\n@node Conditionals\n@chapter Conditional Parts of Makefiles\n\n@cindex conditionals\nA @dfn{conditional} directive causes part of a makefile to be obeyed\nor ignored depending on the values of variables.  Conditionals can\ncompare the value of one variable to another, or the value of a\nvariable to a constant string.  Conditionals control what @code{make}\nactually ``sees'' in the makefile, so they @emph{cannot} be used to\ncontrol recipes at the time of execution.\n\n@menu\n* Conditional Example::         Example of a conditional\n* Conditional Syntax::          The syntax of conditionals.\n* Testing Flags::               Conditionals that test flags.\n@end menu\n\n@node Conditional Example\n@section Example of a Conditional\n\nThe following example of a conditional tells @code{make} to use one\nset of libraries if the @code{CC} variable is @samp{gcc}, and a\ndifferent set of libraries otherwise.  It works by controlling which\nof two recipe lines will be used for the rule.  The result is that\n@samp{CC=gcc} as an argument to @code{make} changes not only which\ncompiler is used but also which libraries are linked.\n\n@example\nlibs_for_gcc = -lgnu\nnormal_libs =\n\nfoo: $(objects)\nifeq ($(CC),gcc)\n        $(CC) -o foo $(objects) $(libs_for_gcc)\nelse\n        $(CC) -o foo $(objects) $(normal_libs)\nendif\n@end example\n\nThis conditional uses three directives: one @code{ifeq}, one @code{else}\nand one @code{endif}.\n\nThe @code{ifeq} directive begins the conditional, and specifies the\ncondition.  It contains two arguments, separated by a comma and surrounded\nby parentheses.  Variable substitution is performed on both arguments and\nthen they are compared.  The lines of the makefile following the\n@code{ifeq} are obeyed if the two arguments match; otherwise they are\nignored.\n\nThe @code{else} directive causes the following lines to be obeyed if the\nprevious conditional failed.  In the example above, this means that the\nsecond alternative linking command is used whenever the first alternative\nis not used.  It is optional to have an @code{else} in a conditional.\n\nThe @code{endif} directive ends the conditional.  Every conditional must\nend with an @code{endif}.  Unconditional makefile text follows.\n\nAs this example illustrates, conditionals work at the textual level:\nthe lines of the conditional are treated as part of the makefile, or\nignored, according to the condition.  This is why the larger syntactic\nunits of the makefile, such as rules, may cross the beginning or the\nend of the conditional.\n\nWhen the variable @code{CC} has the value @samp{gcc}, the above example has\nthis effect:\n\n@example\nfoo: $(objects)\n        $(CC) -o foo $(objects) $(libs_for_gcc)\n@end example\n\n@noindent\nWhen the variable @code{CC} has any other value, the effect is this:\n\n@example\nfoo: $(objects)\n        $(CC) -o foo $(objects) $(normal_libs)\n@end example\n\nEquivalent results can be obtained in another way by conditionally assigning a\nvariable and then using the variable unconditionally:\n\n@example\nlibs_for_gcc = -lgnu\nnormal_libs =\n\nifeq ($(CC),gcc)\n  libs = $(libs_for_gcc)\nelse\n  libs = $(normal_libs)\nendif\n\nfoo: $(objects)\n        $(CC) -o foo $(objects) $(libs)\n@end example\n\n@node Conditional Syntax\n@section Syntax of Conditionals\n@findex ifdef\n@findex ifeq\n@findex ifndef\n@findex ifneq\n@findex else\n@findex endif\n\nThe syntax of a simple conditional with no @code{else} is as follows:\n\n@example\n@var{conditional-directive}\n@var{text-if-true}\nendif\n@end example\n\n@noindent\nThe @var{text-if-true} may be any lines of text, to be considered as part\nof the makefile if the condition is true.  If the condition is false, no\ntext is used instead.\n\nThe syntax of a complex conditional is as follows:\n\n@example\n@var{conditional-directive}\n@var{text-if-true}\nelse\n@var{text-if-false}\nendif\n@end example\n\nor:\n\n@example\n@var{conditional-directive-one}\n@var{text-if-one-is-true}\nelse @var{conditional-directive-two}\n@var{text-if-two-is-true}\nelse\n@var{text-if-one-and-two-are-false}\nendif\n@end example\n\n@noindent\nThere can be as many ``@code{else} @var{conditional-directive}''\nclauses as necessary.  Once a given condition is true,\n@var{text-if-true} is used and no other clause is used; if no\ncondition is true then @var{text-if-false} is used.  The\n@var{text-if-true} and @var{text-if-false} can be any number of lines\nof text.\n\nThe syntax of the @var{conditional-directive} is the same whether the\nconditional is simple or complex; after an @code{else} or not.  There\nare four different directives that test different conditions.  Here is\na table of them:\n\n@table @code\n@item ifeq (@var{arg1}, @var{arg2})\n@itemx ifeq '@var{arg1}' '@var{arg2}'\n@itemx ifeq \"@var{arg1}\" \"@var{arg2}\"\n@itemx ifeq \"@var{arg1}\" '@var{arg2}'\n@itemx ifeq '@var{arg1}' \"@var{arg2}\"\nExpand all variable references in @var{arg1} and @var{arg2} and\ncompare them.  If they are identical, the @var{text-if-true} is\neffective; otherwise, the @var{text-if-false}, if any, is effective.\n\nOften you want to test if a variable has a non-empty value.  When the\nvalue results from complex expansions of variables and functions,\nexpansions you would consider empty may actually contain whitespace\ncharacters and thus are not seen as empty.  However, you can use the\n@code{strip} function (@pxref{Text Functions}) to avoid interpreting\nwhitespace as a non-empty value.  For example:\n\n@example\n@group\nifeq ($(strip $(foo)),)\n@var{text-if-empty}\nendif\n@end group\n@end example\n\n@noindent\nwill evaluate @var{text-if-empty} even if the expansion of\n@code{$(foo)} contains whitespace characters.\n\n@item ifneq (@var{arg1}, @var{arg2})\n@itemx ifneq '@var{arg1}' '@var{arg2}'\n@itemx ifneq \"@var{arg1}\" \"@var{arg2}\"\n@itemx ifneq \"@var{arg1}\" '@var{arg2}'\n@itemx ifneq '@var{arg1}' \"@var{arg2}\"\nExpand all variable references in @var{arg1} and @var{arg2} and\ncompare them.  If they are different, the @var{text-if-true} is\neffective; otherwise, the @var{text-if-false}, if any, is effective.\n\n@item ifdef @var{variable-name}\nThe @code{ifdef} form takes the @emph{name} of a variable as its\nargument, not a reference to a variable.  If the value of that\nvariable has a non-empty value, the @var{text-if-true} is effective;\notherwise, the @var{text-if-false}, if any, is effective.  Variables\nthat have never been defined have an empty value.  The text\n@var{variable-name} is expanded, so it could be a variable or function\nthat expands to the name of a variable.  For example:\n\n@example\nbar = true\nfoo = bar\nifdef $(foo)\nfrobozz = yes\nendif\n@end example\n\nThe variable reference @code{$(foo)} is expanded, yielding @code{bar},\nwhich is considered to be the name of a variable.  The variable\n@code{bar} is not expanded, but its value is examined to determine if\nit is non-empty.\n\nNote that @code{ifdef} only tests whether a variable has a value.  It\ndoes not expand the variable to see if that value is nonempty.\nConsequently, tests using @code{ifdef} return true for all definitions\nexcept those like @code{foo =}.  To test for an empty value, use\n@w{@code{ifeq ($(foo),)}}.  For example,\n\n@example\nbar =\nfoo = $(bar)\nifdef foo\nfrobozz = yes\nelse\nfrobozz = no\nendif\n@end example\n\n@noindent\nsets @samp{frobozz} to @samp{yes}, while:\n\n@example\nfoo =\nifdef foo\nfrobozz = yes\nelse\nfrobozz = no\nendif\n@end example\n\n@noindent\nsets @samp{frobozz} to @samp{no}.\n\n@item ifndef @var{variable-name}\nIf the variable @var{variable-name} has an empty value, the\n@var{text-if-true} is effective; otherwise, the @var{text-if-false},\nif any, is effective.  The rules for expansion and testing of\n@var{variable-name} are identical to the @code{ifdef} directive.\n@end table\n\nExtra spaces are allowed and ignored at the beginning of the\nconditional directive line, but a tab is not allowed.  (If the line\nbegins with a tab, it will be considered part of a recipe for a rule.)\nAside from this, extra spaces or tabs may be inserted with no effect\nanywhere except within the directive name or within an argument.  A\ncomment starting with @samp{#} may appear at the end of the line.\n\nThe other two directives that play a part in a conditional are @code{else}\nand @code{endif}.  Each of these directives is written as one word, with no\narguments.  Extra spaces are allowed and ignored at the beginning of the\nline, and spaces or tabs at the end.  A comment starting with @samp{#} may\nappear at the end of the line.\n\nConditionals affect which lines of the makefile @code{make} uses.  If\nthe condition is true, @code{make} reads the lines of the\n@var{text-if-true} as part of the makefile; if the condition is false,\n@code{make} ignores those lines completely.  It follows that syntactic\nunits of the makefile, such as rules, may safely be split across the\nbeginning or the end of the conditional.\n\n@code{make} evaluates conditionals when it reads a makefile.\nConsequently, you cannot use automatic variables in the tests of\nconditionals because they are not defined until recipes are run\n(@pxref{Automatic Variables}).\n\nTo prevent intolerable confusion, it is not permitted to start a\nconditional in one makefile and end it in another.  However, you may\nwrite an @code{include} directive within a conditional, provided you do\nnot attempt to terminate the conditional inside the included file.\n\n@node Testing Flags\n@section Conditionals that Test Flags\n\nYou can write a conditional that tests @code{make} command flags such as\n@samp{-t} by using the variable @code{MAKEFLAGS} together with the\n@code{findstring} function\n(@pxref{Text Functions, , Functions for String Substitution and Analysis}).\nThis is useful when @code{touch} is not enough to make a file appear up\nto date.\n\nRecall that @code{MAKEFLAGS} will put all single-letter options (such as\n@samp{-t}) into the first word, and that word will be empty if no\nsingle-letter options were given.  To work with this, it's helpful to add a\nvalue at the start to ensure there's a word: for example\n@samp{-$(MAKEFLAGS)}.\n\nThe @code{findstring} function determines whether one string appears as a\nsubstring of another.  If you want to test for the @samp{-t} flag, use\n@samp{t} as the first string and the first word of @code{MAKEFLAGS} as the\nother.\n\nFor example, here is how to arrange to use @samp{ranlib -t} to finish\nmarking an archive file up to date:\n\n@example\narchive.a: @dots{}\nifneq (,$(findstring t,$(firstword -$(MAKEFLAGS))))\n        +touch archive.a\n        +ranlib -t archive.a\nelse\n        ranlib archive.a\nendif\n@end example\n\n@noindent\nThe @samp{+} prefix marks those recipe lines as ``recursive'' so that\nthey will be executed despite use of the @samp{-t} flag.\n@xref{Recursion, ,Recursive Use of @code{make}}.\n\n@node Functions\n@chapter Functions for Transforming Text\n@cindex functions\n\n@dfn{Functions} allow you to do text processing in the makefile to\ncompute the files to operate on or the commands to use in recipes.\nYou use a function in a @dfn{function call}, where you give the name\nof the function and some text (the @dfn{arguments}) for the function\nto operate on.  The result of the function's processing is substituted\ninto the makefile at the point of the call, just as a variable might\nbe substituted.\n\n@menu\n* Syntax of Functions::         How to write a function call.\n* Text Functions::              General-purpose text manipulation functions.\n* File Name Functions::         Functions for manipulating file names.\n* Conditional Functions::       Functions that implement conditions.\n* Let Function::                Local variables.\n* Foreach Function::            Repeat some text with controlled variation.\n* File Function::               Write text to a file.\n* Call Function::               Expand a user-defined function.\n* Value Function::              Return the un-expanded value of a variable.\n* Eval Function::               Evaluate the arguments as makefile syntax.\n* Origin Function::             Find where a variable got its value.\n* Flavor Function::             Find out the flavor of a variable.\n* Make Control Functions::      Functions that control how make runs.\n* Shell Function::              Substitute the output of a shell command.\n* Guile Function::              Use GNU Guile embedded scripting language.\n@end menu\n\n@node Syntax of Functions\n@section Function Call Syntax\n@cindex @code{$}, in function call\n@cindex dollar sign (@code{$}), in function call\n@cindex arguments of functions\n@cindex functions, syntax of\n\nA function call resembles a variable reference.  It can appear\nanywhere a variable reference can appear, and it is expanded using the\nsame rules as variable references.  A function call looks like this:\n\n@example\n$(@var{function} @var{arguments})\n@end example\n\n@noindent\nor like this:\n\n@example\n$@{@var{function} @var{arguments}@}\n@end example\n\nHere @var{function} is a function name; one of a short list of names\nthat are part of @code{make}.  You can also essentially create your own\nfunctions by using the @code{call} built-in function.\n\nThe @var{arguments} are the arguments of the function.  They are separated\nfrom the function name by one or more spaces or tabs, and if there is more\nthan one argument, then they are separated by commas.  Such whitespace and\ncommas are not part of an argument's value.  The delimiters which you use to\nsurround the function call, whether parentheses or braces, can appear in an\nargument only in matching pairs; the other kind of delimiters may appear\nsingly.  If the arguments themselves contain other function calls or variable\nreferences, it is wisest to use the same kind of delimiters for all the\nreferences; write @w{@samp{$(subst a,b,$(x))}}, not @w{@samp{$(subst\na,b,$@{x@})}}.  This is because it is clearer, and because only one type of\ndelimiter is matched to find the end of the reference.\n\nEach argument is expanded before the function is invoked, unless otherwise\nnoted below.  The substitution is done in the order in which the arguments\nappear.\n\n@subsubheading Special Characters\n@cindex special characters in function arguments\n@cindex function arguments, special characters in\n\nWhen using characters that are special to @code{make} as function arguments,\nyou may need to hide them.  GNU @code{make} doesn't support escaping\ncharacters with backslashes or other escape sequences; however, because\narguments are split before they are expanded you can hide them by putting them\ninto variables.\n\nCharacters you may need to hide include:\n\n@itemize @bullet\n@item\nCommas\n@item\nInitial whitespace in the first argument\n@item\nUnmatched open parenthesis or brace\n@item\nAn open parenthesis or brace if you don't want it to start a matched pair\n@end itemize\n\nFor example, you can define variables @code{comma} and @code{space} whose\nvalues are isolated comma and space characters, then substitute these\nvariables where such characters are wanted, like this:\n\n@example\n@group\ncomma:= ,\nempty:=\nspace:= $(empty) $(empty)\nfoo:= a b c\nbar:= $(subst $(space),$(comma),$(foo))\n# @r{bar is now `a,b,c'.}\n@end group\n@end example\n\n@noindent\nHere the @code{subst} function replaces each space with a comma, through\nthe value of @code{foo}, and substitutes the result.\n\n@node Text Functions\n@section Functions for String Substitution and Analysis\n@cindex functions, for text\n\nHere are some functions that operate on strings:\n\n@table @code\n@item $(subst @var{from},@var{to},@var{text})\n@findex subst\nPerforms a textual replacement on the text @var{text}: each occurrence\nof @var{from} is replaced by @var{to}.  The result is substituted for\nthe function call.  For example,\n\n@example\n$(subst ee,EE,feet on the street)\n@end example\n\nproduces the value @samp{fEEt on the strEEt}.\n\n@item $(patsubst @var{pattern},@var{replacement},@var{text})\n@findex patsubst\nFinds whitespace-separated words in @var{text} that match @var{pattern} and\nreplaces them with @var{replacement}.  Here @var{pattern} may contain a\n@samp{%} which acts as a wildcard, matching any number of any characters\nwithin a word.  If @var{replacement} also contains a @samp{%}, the @samp{%} is\nreplaced by the text that matched the @samp{%} in @var{pattern}.  Words that\ndo not match the pattern are kept without change in the output.  Only the\nfirst @samp{%} in the @var{pattern} and @var{replacement} is treated this way;\nany subsequent @samp{%} is unchanged.\n\nIf @var{pattern} does not contain a @samp{%} then the entire word must compare\nequal to be a match.\n\n@cindex @code{%}, quoting in @code{patsubst}\n@cindex @code{\\} (backslash), to quote @code{%}\n@cindex backslash (@code{\\}), to quote @code{%}\n@cindex quoting @code{%}, in @code{patsubst}\n@samp{%} characters in @code{patsubst} function invocations can be\nquoted with preceding backslashes (@samp{\\}).  Backslashes that would\notherwise quote @samp{%} characters can be quoted with more backslashes.\nBackslashes that quote @samp{%} characters or other backslashes are\nremoved from the pattern before it is compared to file names or has a stem\nsubstituted into it.  Backslashes that are not in danger of quoting\n@samp{%} characters go unmolested.  For example, the pattern\n@file{the\\%weird\\\\%pattern\\\\} has @samp{the%weird\\} preceding the\noperative @samp{%} character, and @samp{pattern\\\\} following it.  The\nfinal two backslashes are left alone because they cannot affect any\n@samp{%} character.\n\nWhitespace between words is folded into single space characters;\nleading and trailing whitespace is discarded.\n\nFor example,\n\n@example\n$(patsubst %.c,%.o,x.c.c bar.c)\n@end example\n\n@noindent\nproduces the value @samp{x.c.o bar.o}, while\n\n@example\n$(patsubst foo.c,foo.o,foo.c foobar.c)\n@end example\n\n@noindent\nproduces the value @samp{foo.o foobar.c}.\n\nSubstitution references (@pxref{Substitution Refs, ,Substitution\nReferences}) are a simpler way to get the effect of the @code{patsubst}\nfunction.\n\n@item $(strip @var{string})\n@cindex stripping whitespace\n@cindex whitespace, stripping\n@cindex spaces, stripping\n@findex strip\nRemoves leading and trailing whitespace from @var{string} and replaces\neach internal sequence of one or more whitespace characters with a\nsingle space.  Thus, @samp{$(strip a b  c )} results in @w{@samp{a b c}}.\n\nThe function @code{strip} can be very useful when used in conjunction\nwith conditionals.  When comparing something with the empty string\n@samp{} using @code{ifeq} or @code{ifneq}, you usually want a string of\njust whitespace to match the empty string (@pxref{Conditionals}).\n\nThus, the following may fail to have the desired results:\n\n@example\n.PHONY: all\nifneq   \"$(needs_made)\" \"\"\nall: $(needs_made)\nelse\nall:;@@echo 'Nothing to make!'\nendif\n@end example\n\n@noindent\nReplacing the variable reference @w{@samp{$(needs_made)}} with the\nfunction call @w{@samp{$(strip $(needs_made))}} in the @code{ifneq}\ndirective would make it more robust.\n\n@item $(findstring @var{find},@var{in})\n@findex findstring\n@cindex searching for strings\n@cindex finding strings\n@cindex strings, searching for\nSearches @var{in} for an occurrence of @var{find}.  If it occurs, the\nvalue is @var{find}; otherwise, the value is empty.  You can use this\nfunction in a conditional to test for the presence of a specific\nsubstring in a given string.  Thus, the two examples,\n\n@example\n$(findstring a,a b c)\n$(findstring a,b c)\n@end example\n\n@noindent\nproduce the values @samp{a} and @samp{} (the empty string),\nrespectively.  @xref{Testing Flags}, for a practical application of\n@code{findstring}.\n\n@need 750\n@findex filter\n@cindex filtering words\n@cindex words, filtering\n@item $(filter @var{pattern}@dots{},@var{text})\nReturns all whitespace-separated words in @var{text} that @emph{do} match\nany of the @var{pattern} words, removing any words that @emph{do not}\nmatch.  Each word in @var{pattern} is compared to every word in @var{text}\nusing the same algorithm as the @code{patsubst} function above.\n\n@example\nsources := foo.c bar.c baz.s ugh.h\nfoo: $(sources)\n        cc $(filter %.c %.s,$(sources)) -o foo\n@end example\n\n@noindent\nsays that @file{foo} depends on @file{foo.c}, @file{bar.c},\n@file{baz.s} and @file{ugh.h} but only @file{foo.c}, @file{bar.c} and\n@file{baz.s} should be specified in the command to the\ncompiler.\n\n@item $(filter-out @var{pattern}@dots{},@var{text})\n@findex filter-out\n@cindex filtering out words\n@cindex words, filtering out\nReturns all whitespace-separated words in @var{text} that @emph{do not} match\nany of the @var{pattern} words, removing the words that @emph{do} match one or\nmore.  Each word in @var{pattern} is compared to every word in @var{text}\nusing the same algorithm as the @code{patsubst} function above.  This is the\nexact opposite of the @code{filter} function.\n\nFor example, given:\n\n@example\n@group\nobjects = main1.o foo.o main2.o bar.o remain1.o\nmains = main1.o main2.o\n@end group\n@end example\n\n@noindent\nthe following generates a list which contains all the object files not\nin @samp{mains}:\n\n@example\n$(filter-out $(mains),$(objects))\n@end example\n\n@noindent\nThis would expand to @samp{foo.o bar.o remain1.o}.\n\n@need 1500\n@findex sort\n@cindex sorting words\n@item $(sort @var{list})\nSorts the words of @var{list} in lexical order, removing duplicate\nwords.  The output is a list of words separated by single spaces.\nThus,\n\n@example\n$(sort foo bar lose)\n@end example\n\n@noindent\nreturns the value @samp{bar foo lose}.\n\n@cindex removing duplicate words\n@cindex duplicate words, removing\n@cindex words, removing duplicates\nIncidentally, since @code{sort} removes duplicate words, you can use\nit for this purpose even if you don't care about the sort order.\n\n@item $(word @var{n},@var{text})\n@findex word\n@cindex word, selecting a\n@cindex selecting a word\nReturns the @var{n}th word of @var{text}.  The legitimate values of\n@var{n} start from 1.  If @var{n} is bigger than the number of words\nin @var{text}, the value is empty.  For example,\n\n@example\n$(word 2, foo bar baz)\n@end example\n\n@noindent\nreturns @samp{bar}.\n\n@item $(wordlist @var{s},@var{e},@var{text})\n@findex wordlist\n@cindex words, selecting lists of\n@cindex selecting word lists\nReturns the list of words in @var{text} starting with word @var{s} and\nending with word @var{e} (inclusive).  The legitimate values of @var{s}\nstart from 1; @var{e} may start from 0.  If @var{s} is bigger than the\nnumber of words in @var{text}, the value is empty.  If @var{e} is\nbigger than the number of words in @var{text}, words up to the end of\n@var{text} are returned.  If @var{s} is greater than @var{e}, nothing\nis returned.  For example,\n\n@example\n$(wordlist 2, 3, foo bar baz)\n@end example\n\n@noindent\nreturns @samp{bar baz}.\n\n@item $(words @var{text})\n@findex words\n@cindex words, finding number\nReturns the number of words in @var{text}.  Thus, the last word of @var{text}\nis @w{@code{$(word $(words @var{text}),@var{text})}}.\n\n@item $(firstword @var{names}@dots{})\n@findex firstword\n@cindex words, extracting first\nThe argument @var{names} is regarded as a series of names, separated\nby whitespace.  The value is the first name in the series.  The rest\nof the names are ignored.\n\nFor example,\n\n@example\n$(firstword foo bar)\n@end example\n\n@noindent\nproduces the result @samp{foo}.  Although @code{$(firstword\n@var{text})} is the same as @code{$(word 1,@var{text})}, the\n@code{firstword} function is retained for its simplicity.\n\n\n@item $(lastword @var{names}@dots{})\n@findex lastword\n@cindex words, extracting last\nThe argument @var{names} is regarded as a series of names, separated\nby whitespace.  The value is the last name in the series.\n\nFor example,\n\n@example\n$(lastword foo bar)\n@end example\n\n@noindent\nproduces the result @samp{bar}.  Although @code{$(lastword\n@var{text})} is the same as @code{$(word $(words @var{text}),@var{text})},\nthe @code{lastword} function was added for its simplicity and better\nperformance.\n@end table\n\n\nHere is a realistic example of the use of @code{subst} and\n@code{patsubst}.  Suppose that a makefile uses the @code{VPATH} variable\nto specify a list of directories that @code{make} should search for\nprerequisite files\n(@pxref{General Search, , @code{VPATH} Search Path for All Prerequisites}).\nThis example shows how to\ntell the C compiler to search for header files in the same list of\ndirectories.\n\nThe value of @code{VPATH} is a list of directories separated by colons,\nsuch as @samp{src:../headers}.  First, the @code{subst} function is used to\nchange the colons to spaces:\n\n@example\n$(subst :, ,$(VPATH))\n@end example\n\n@noindent\nThis produces @samp{src ../headers}.  Then @code{patsubst} is used to turn\neach directory name into a @samp{-I} flag.  These can be added to the\nvalue of the variable @code{CFLAGS}, which is passed automatically to the C\ncompiler, like this:\n\n@example\noverride CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))\n@end example\n\n@noindent\nThe effect is to append the text @samp{-Isrc -I../headers} to the\npreviously given value of @code{CFLAGS}.  The @code{override} directive is\nused so that the new value is assigned even if the previous value of\n@code{CFLAGS} was specified with a command argument (@pxref{Override\nDirective, , The @code{override} Directive}).\n\n@node File Name Functions\n@section Functions for File Names\n@cindex functions, for file names\n@cindex file name functions\n\nSeveral of the built-in expansion functions relate specifically to\ntaking apart file names or lists of file names.\n\nEach of the following functions performs a specific transformation on a\nfile name.  The argument of the function is regarded as a series of file\nnames, separated by whitespace.  (Leading and trailing whitespace is\nignored.)  Each file name in the series is transformed in the same way and\nthe results are concatenated with single spaces between them.\n\n@table @code\n@item $(dir @var{names}@dots{})\n@findex dir\n@cindex directory part\n@cindex file name, directory part\nExtracts the directory-part of each file name in @var{names}.  The\ndirectory-part of the file name is everything up through (and\nincluding) the last slash in it.  If the file name contains no slash,\nthe directory part is the string @samp{./}.  For example,\n\n@example\n$(dir src/foo.c hacks)\n@end example\n\n@noindent\nproduces the result @samp{src/ ./}.\n\n@item $(notdir @var{names}@dots{})\n@findex notdir\n@cindex file name, nondirectory part\n@cindex nondirectory part\nExtracts all but the directory-part of each file name in @var{names}.\nIf the file name contains no slash, it is left unchanged.  Otherwise,\neverything through the last slash is removed from it.\n\nA file name that ends with a slash becomes an empty string.  This is\nunfortunate, because it means that the result does not always have the\nsame number of whitespace-separated file names as the argument had;\nbut we do not see any other valid alternative.\n\nFor example,\n\n@example\n$(notdir src/foo.c hacks)\n@end example\n\n@noindent\nproduces the result @samp{foo.c hacks}.\n\n@item $(suffix @var{names}@dots{})\n@findex suffix\n@cindex suffix, function to find\n@cindex file name suffix\nExtracts the suffix of each file name in @var{names}.  If the file name\ncontains a period, the suffix is everything starting with the last\nperiod.  Otherwise, the suffix is the empty string.  This frequently\nmeans that the result will be empty when @var{names} is not, and if\n@var{names} contains multiple file names, the result may contain fewer\nfile names.\n\nFor example,\n\n@example\n$(suffix src/foo.c src-1.0/bar.c hacks)\n@end example\n\n@noindent\nproduces the result @samp{.c .c}.\n\n@item $(basename @var{names}@dots{})\n@findex basename\n@cindex basename\n@cindex file name, basename of\nExtracts all but the suffix of each file name in @var{names}.  If the file\nname contains a period, the basename is everything up to (and not including)\nthe last period.  Periods in the directory part are ignored.  If there is no\nperiod, the basename is the entire file name.  For example,\n\n@example\n$(basename src/foo.c src-1.0/bar hacks)\n@end example\n\n@noindent\nproduces the result @samp{src/foo src-1.0/bar hacks}.\n\n@c plural convention with dots (be consistent)\n@item $(addsuffix @var{suffix},@var{names}@dots{})\n@findex addsuffix\n@cindex suffix, adding\n@cindex file name suffix, adding\nThe argument @var{names} is regarded as a series of names, separated\nby whitespace; @var{suffix} is used as a unit.  The value of\n@var{suffix} is appended to the end of each individual name and the\nresulting larger names are concatenated with single spaces between\nthem.  For example,\n\n@example\n$(addsuffix .c,foo bar)\n@end example\n\n@noindent\nproduces the result @samp{foo.c bar.c}.\n\n@item $(addprefix @var{prefix},@var{names}@dots{})\n@findex addprefix\n@cindex prefix, adding\n@cindex file name prefix, adding\nThe argument @var{names} is regarded as a series of names, separated\nby whitespace; @var{prefix} is used as a unit.  The value of\n@var{prefix} is prepended to the front of each individual name and the\nresulting larger names are concatenated with single spaces between\nthem.  For example,\n\n@example\n$(addprefix src/,foo bar)\n@end example\n\n@noindent\nproduces the result @samp{src/foo src/bar}.\n\n@item $(join @var{list1},@var{list2})\n@findex join\n@cindex joining lists of words\n@cindex words, joining lists\nConcatenates the two arguments word by word: the two first words (one\nfrom each argument) concatenated form the first word of the result, the\ntwo second words form the second word of the result, and so on.  So the\n@var{n}th word of the result comes from the @var{n}th word of each\nargument.  If one argument has more words than the other, the extra\nwords are copied unchanged into the result.\n\nFor example, @samp{$(join a b,.c .o)} produces @samp{a.c b.o}.\n\nWhitespace between the words in the lists is not preserved; it is\nreplaced with a single space.\n\nThis function can merge the results of the @code{dir} and\n@code{notdir} functions, to produce the original list of files which\nwas given to those two functions.\n\n@item $(wildcard @var{pattern})\n@cindex wildcard, function\nThe argument @var{pattern} is a file name pattern, typically containing\nwildcard characters (as in shell file name patterns).  The result of\n@code{wildcard} is a space-separated list of the names of existing files\nthat match the pattern.\n@xref{Wildcards, ,Using Wildcard Characters in File Names}.\n\n@item $(realpath @var{names}@dots{})\n@findex realpath\n@cindex realpath\n@cindex file name, realpath of\nFor each file name in @var{names} return the canonical absolute name.\nA canonical name does not contain any @code{.} or @code{..} components,\nnor any repeated path separators (@code{/}) or symlinks.  In case of a\nfailure the empty string is returned.  Consult the @code{realpath(3)}\ndocumentation for a list of possible failure causes.\n\n@item $(abspath @var{names}@dots{})\n@findex abspath\n@cindex abspath\n@cindex file name, abspath of\nFor each file name in @var{names} return an absolute name that does\nnot contain any @code{.} or @code{..} components, nor any repeated path\nseparators (@code{/}).  Note that, in contrast to the @code{realpath}\nfunction, @code{abspath} does not resolve symlinks and does not require\nthe file names to refer to existing files or directories.  Use the\n@code{wildcard} function to test for existence.\n@end table\n\n@node Conditional Functions\n@section Functions for Conditionals\n@cindex conditional expansion\nThere are four functions that provide conditional expansion.  A key\naspect of these functions is that not all of the arguments are\nexpanded initially.  Only those arguments which need to be expanded,\nwill be expanded.\n\n@table @code\n@item $(if @var{condition},@var{then-part}[,@var{else-part}])\n@findex if\nThe @code{if} function provides support for conditional expansion in a\nfunctional context (as opposed to the GNU @code{make} makefile\nconditionals such as @code{ifeq} (@pxref{Conditional Syntax, ,Syntax of\nConditionals})).\n\nThe first argument, @var{condition}, first has all preceding and\ntrailing whitespace stripped, then is expanded.  If it expands to any\nnon-empty string, then the condition is considered to be true.  If it\nexpands to an empty string, the condition is considered to be false.\n\nIf the condition is true then the second argument, @var{then-part}, is\nevaluated and this is used as the result of the evaluation of the entire\n@code{if} function.\n\nIf the condition is false then the third argument, @var{else-part}, is\nevaluated and this is the result of the @code{if} function.  If there is\nno third argument, the @code{if} function evaluates to nothing (the\nempty string).\n\nNote that only one of the @var{then-part} or the @var{else-part} will be\nevaluated, never both.  Thus, either can contain side-effects (such as\n@code{shell} function calls, etc.)\n\n@item $(or @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])\n@findex or\nThe @code{or} function provides a ``short-circuiting'' OR operation.\nEach argument is expanded, in order.  If an argument expands to a\nnon-empty string the processing stops and the result of the expansion\nis that string.  If, after all arguments are expanded, all of them are\nfalse (empty), then the result of the expansion is the empty string.\n\n@item $(and @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])\n@findex and\nThe @code{and} function provides a ``short-circuiting'' AND operation.\nEach argument is expanded, in order.  If an argument expands to an\nempty string the processing stops and the result of the expansion is\nthe empty string.  If all arguments expand to a non-empty string then\nthe result of the expansion is the expansion of the last argument.\n\n@item $(intcmp @var{lhs},@var{rhs}[,@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]])\n@findex intcmp\nThe @code{intcmp} function provides support for numerical comparison of\nintegers.  This function has no counterpart among the GNU @code{make} makefile\nconditionals.\n\nThe left-hand side, @var{lhs}, and right-hand side, @var{rhs}, are expanded\nand parsed as integral numbers in base 10.  Expansion of the remaining\narguments is controlled by how the numerical left-hand side compares to the\nnumerical right-hand side.\n\nIf there are no further arguments, then the function expands to empty if the\nleft-hand side and right-hand side do not compare equal, or to their numerical\nvalue if they do compare equal.\n\nElse if the left-hand side is strictly less than the right-hand side, the\n@code{intcmp} function evaluates to the expansion of the third argument,\n@var{lt-part}.  If both sides compare equal, then the @code{intcmp} function\nevaluates to the expansion of the fourth argument, @var{eq-part}.  If the\nleft-hand side is strictly greater than the right-hand side, then the\n@code{intcmp} function evaluates to the expansion of the fifth argument,\n@var{gt-part}.\n\nIf @var{gt-part} is missing, it defaults to @var{eq-part}.  If @var{eq-part}\nis missing, it defaults to the empty string.  Thus both @samp{$(intcmp\n9,7,hello)} and @samp{$(intcmp 9,7,hello,world,)} evaluate to the empty\nstring, while @samp{$(intcmp 9,7,hello,world)} (notice the absence of a comma\nafter @code{world}) evaluates to @samp{world}.\n\n@end table\n\n@node Let Function\n@section The @code{let} Function\n@findex let\n@cindex variables, local\n\nThe @code{let} function provides a means to limit the scope of a\nvariable.  The assignment of the named variables in a @code{let}\nexpression is in effect only within the text provided by the\n@code{let} expression, and this assignment doesn't impact that named\nvariable in any outer scope.\n\nAdditionally, the @code{let} function enables list unpacking by\nassigning all unassigned values to the last named variable.\n\nThe syntax of the @code{let} function is:\n\n@example\n$(let @var{var} [@var{var} ...],[@var{list}],@var{text})\n@end example\n\n@noindent\nThe first two arguments, @var{var} and @var{list}, are expanded before\nanything else is done; note that the last argument, @var{text}, is\n@strong{not} expanded at the same time.  Next, each word of the\nexpanded value of @var{list} is bound to each of the variable names,\n@var{var}, in turn, with the final variable name being bound to the\nremainder of the expanded @var{list}.  In other words, the first word\nof @var{list} is bound to the first variable @var{var}, the second\nword to the second variable @var{var}, and so on.\n\nIf there are more variable names in @var{var} than there are words in\n@var{list}, the remaining @var{var} variable names are set to the\nempty string.  If there are fewer @var{var}s than words in @var{list}\nthen the last @var{var} is set to all remaining words in @var{list}.\n\nThe variables in @var{var} are assigned as simply-expanded variables\nduring the execution of @code{let}.  @xref{Flavors, ,The Two Flavors\nof Variables}.\n\nAfter all variables are thus bound, @var{text} is expanded to provide\nthe result of the @code{let} function.\n\nFor example, this macro reverses the order of the words in the list\nthat it is given as its first argument:\n\n@example\nreverse = $(let first rest,$1,\\\n            $(if $(rest),$(call reverse,$(rest)) )$(first))\n\nall: ; @@echo $(call reverse,d c b a)\n@end example\n\n@noindent\nwill print @code{a b c d}.  When first called, @code{let} will expand\n@var{$1} to @code{d c b a}.  It will then assign @var{first} to\n@code{d} and assign @var{rest} to @code{c b a}.  It will then expand\nthe if-statement, where @code{$(rest)} is not empty so we recursively\ninvoke the @var{reverse} function with the value of @var{rest} which\nis now @code{c b a}.  The recursive invocation of @code{let} assigns\n@var{first} to @code{c} and @var{rest} to @code{b a}.  The recursion\ncontinues until @code{let} is called with just a single value,\n@code{a}.  Here @var{first} is @code{a} and @var{rest} is empty, so we\ndo not recurse but simply expand @code{$(first)} to @code{a} and\nreturn, which adds @code{ b}, etc.\n\nAfter the @var{reverse} call is complete, the @var{first} and\n@var{rest} variables are no longer set.  If variables by those names\nexisted beforehand, they are not affected by the expansion of the\n@code{reverse} macro.\n\n@node Foreach Function\n@section The @code{foreach} Function\n@findex foreach\n@cindex words, iterating over\n\nThe @code{foreach} function is similar to the @code{let} function, but very\ndifferent from other functions.  It causes one piece of text to be used\nrepeatedly, each time with a different substitution performed on it.  The\n@code{foreach} function resembles the @code{for} command in the\nshell @code{sh} and the @code{foreach} command in the C-shell @code{csh}.\n\nThe syntax of the @code{foreach} function is:\n\n@example\n$(foreach @var{var},@var{list},@var{text})\n@end example\n\n@noindent\nThe first two arguments, @var{var} and @var{list}, are expanded before\nanything else is done; note that the last argument, @var{text}, is\n@strong{not} expanded at the same time.  Then for each word of the expanded\nvalue of @var{list}, the variable named by the expanded value of @var{var}\nis set to that word, and @var{text} is expanded.  Presumably @var{text}\ncontains references to that variable, so its expansion will be different\neach time.\n\nThe result is that @var{text} is expanded as many times as there are\nwhitespace-separated words in @var{list}.  The multiple expansions of\n@var{text} are concatenated, with spaces between them, to make the result\nof @code{foreach}.\n\nThis simple example sets the variable @samp{files} to the list of all files\nin the directories in the list @samp{dirs}:\n\n@example\ndirs := a b c d\nfiles := $(foreach dir,$(dirs),$(wildcard $(dir)/*))\n@end example\n\nHere @var{text} is @samp{$(wildcard $(dir)/*)}.  The first repetition\nfinds the value @samp{a} for @code{dir}, so it produces the same result\nas @samp{$(wildcard a/*)}; the second repetition produces the result\nof @samp{$(wildcard b/*)}; and the third, that of @samp{$(wildcard c/*)}.\n\nThis example has the same result (except for setting @samp{dirs}) as\nthe following example:\n\n@example\nfiles := $(wildcard a/* b/* c/* d/*)\n@end example\n\nWhen @var{text} is complicated, you can improve readability by giving it\na name, with an additional variable:\n\n@example\nfind_files = $(wildcard $(dir)/*)\ndirs := a b c d\nfiles := $(foreach dir,$(dirs),$(find_files))\n@end example\n\n@noindent\nHere we use the variable @code{find_files} this way.  We use plain @samp{=}\nto define a recursively-expanding variable, so that its value contains an\nactual function call to be re-expanded under the control of @code{foreach};\na simply-expanded variable would not do, since @code{wildcard} would be\ncalled only once at the time of defining @code{find_files}.\n\nLike the @code{let} function, the @code{foreach} function has no permanent\neffect on the variable @var{var}; its value and flavor after the\n@code{foreach} function call are the same as they were beforehand.  The\nother values which are taken from @var{list} are in effect only\ntemporarily, during the execution of @code{foreach}.  The variable\n@var{var} is a simply-expanded variable during the execution of\n@code{foreach}.  If @var{var} was undefined before the @code{foreach}\nfunction call, it is undefined after the call.\n@xref{Flavors, ,The Two Flavors of Variables}.\n\nYou must take care when using complex variable expressions that result in\nvariable names because many strange things are valid variable names, but\nare probably not what you intended.  For example,\n\n@smallexample\nfiles := $(foreach Esta-escrito-en-espanol!,b c ch,$(find_files))\n@end smallexample\n\n@noindent\nmight be useful if the value of @code{find_files} references the variable\nwhose name is @samp{Esta-escrito-en-espanol!} (es un nombre bastante largo,\nno?), but it is more likely to be a mistake.\n\n@node File Function\n@section The @code{file} Function\n@findex file\n@cindex writing to a file\n@cindex file, writing to\n@cindex reading from a file\n@cindex file, reading from\n\nThe @code{file} function allows the makefile to write to or read from\na file.  Two modes of writing are supported: overwrite, where the text\nis written to the beginning of the file and any existing content is\nlost, and append, where the text is written to the end of the file,\npreserving the existing content.  In both cases the file is created if\nit does not exist.  It is a fatal error if the file cannot be opened\nfor writing, or if the write operation fails.  The @code{file}\nfunction expands to the empty string when writing to a file.\n\nWhen reading from a file, the @code{file} function expands to the\nverbatim contents of the file, except that the final newline (if there\nis one) will be stripped.  Attempting to read from a non-existent file\nexpands to the empty string.\n\nThe syntax of the @code{file} function is:\n\n@example\n$(file @var{op} @var{filename}[,@var{text}])\n@end example\n\nWhen the @code{file} function is evaluated all its arguments are\nexpanded first, then the file indicated by @var{filename} will be\nopened in the mode described by @var{op}.\n\nThe operator @var{op} can be @code{>} to indicate the file will be\noverwritten with new content, @code{>>} to indicate the current\ncontents of the file will be appended to, or @code{<} to indicate the\ncontents of the file will be read in.  The @var{filename} specifies\nthe file to be written to or read from.  There may optionally be\nwhitespace between the operator and the file name.\n\nWhen reading files, it is an error to provide a @var{text} value.\n\nWhen writing files, @var{text} will be written to the file.  If\n@var{text} does not already end in a newline a final newline will be\nwritten (even if @var{text} is the empty string).  If the @var{text}\nargument is not given at all, nothing will be written.\n\nFor example, the @code{file} function can be useful if your build\nsystem has a limited command line size and your recipe runs a command\nthat can accept arguments from a file as well.  Many commands use the\nconvention that an argument prefixed with an @code{@@} specifies a\nfile containing more arguments.  Then you might write your recipe in\nthis way:\n\n@example\n@group\nprogram: $(OBJECTS)\n        $(file >$@@.in,$^)\n        $(CMD) $(CMDFLAGS) @@$@@.in\n        @@rm $@@.in\n@end group\n@end example\n\nIf the command required each argument to be on a separate line of the\ninput file, you might write your recipe like this:\n\n@example\n@group\nprogram: $(OBJECTS)\n        $(file >$@@.in) $(foreach O,$^,$(file >>$@@.in,$O))\n        $(CMD) $(CMDFLAGS) @@$@@.in\n        @@rm $@@.in\n@end group\n@end example\n\n@node Call Function\n@section The @code{call} Function\n@findex call\n@cindex functions, user defined\n@cindex user defined functions\n\nThe @code{call} function is unique in that it can be used to create new\nparameterized functions.  You can write a complex expression as the\nvalue of a variable, then use @code{call} to expand it with different\nvalues.\n\nThe syntax of the @code{call} function is:\n\n@example\n$(call @var{variable},@var{param},@var{param},@dots{})\n@end example\n\nWhen @code{make} expands this function, it assigns each @var{param} to\ntemporary variables @code{$(1)}, @code{$(2)}, etc.  The variable\n@code{$(0)} will contain @var{variable}.  There is no maximum number of\nparameter arguments.  There is no minimum, either, but it doesn't make\nsense to use @code{call} with no parameters.\n\nThen @var{variable} is expanded as a @code{make} variable in the context\nof these temporary assignments.  Thus, any reference to @code{$(1)} in\nthe value of @var{variable} will resolve to the first @var{param} in the\ninvocation of @code{call}.\n\nNote that @var{variable} is the @emph{name} of a variable, not a\n@emph{reference} to that variable.  Therefore you would not normally use\na @samp{$} or parentheses when writing it.  (You can, however, use a\nvariable reference in the name if you want the name not to be a\nconstant.)\n\nIf @var{variable} is the name of a built-in function, the built-in function\nis always invoked (even if a @code{make} variable by that name also\nexists).\n\nThe @code{call} function expands the @var{param} arguments before\nassigning them to temporary variables.  This means that @var{variable}\nvalues containing references to built-in functions that have special\nexpansion rules, like @code{foreach} or @code{if}, may not work as you\nexpect.\n\nSome examples may make this clearer.\n\nThis macro simply reverses its arguments:\n\n@smallexample\nreverse = $(2) $(1)\n\nfoo = $(call reverse,a,b)\n@end smallexample\n\n@noindent\nHere @code{foo} will contain @samp{b a}.\n\nThis one is slightly more interesting: it defines a macro to search for\nthe first instance of a program in @code{PATH}:\n\n@smallexample\npathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))\n\nLS := $(call pathsearch,ls)\n@end smallexample\n\n@noindent\nNow the variable @code{LS} contains @code{/bin/ls} or similar.\n\nThe @code{call} function can be nested.  Each recursive invocation gets its\nown local values for @code{$(1)}, etc.@: that mask the values of higher-level\n@code{call} functions.  For example, here is an implementation of a @dfn{map}\nfunction:\n\n@smallexample\nmap = $(foreach a,$(2),$(call $(1),$(a)))\n@end smallexample\n\nNow you can @code{map} a function that normally takes only one argument,\nsuch as @code{origin}, to multiple values in one step:\n\n@smallexample\no = $(call map,origin,o map MAKE)\n@end smallexample\n\nand end up with @code{o} containing something like @samp{file file default}.\n\nA final caution: be careful when adding whitespace to the arguments to\n@code{call}.  As with other functions, any whitespace contained in the\nsecond and subsequent arguments is kept; this can cause strange\neffects.  It's generally safest to remove all extraneous whitespace when\nproviding parameters to @code{call}.\n\n@node Value Function\n@comment  node-name,  next,  previous,  up\n@section The @code{value} Function\n@findex value\n@cindex variables, unexpanded value\n\nThe @code{value} function provides a way for you to use the value of a\nvariable @emph{without} having it expanded.  Please note that this\ndoes not undo expansions which have already occurred; for example if\nyou create a simply expanded variable its value is expanded during the\ndefinition; in that case the @code{value} function will return the\nsame result as using the variable directly.\n\nThe syntax of the @code{value} function is:\n\n@example\n$(value @var{variable})\n@end example\n\nNote that @var{variable} is the @emph{name} of a variable, not a\n@emph{reference} to that variable.  Therefore you would not normally\nuse a @samp{$} or parentheses when writing it.  (You can, however, use\na variable reference in the name if you want the name not to be a\nconstant.)\n\nThe result of this function is a string containing the value of\n@var{variable}, without any expansion occurring.  For example, in this\nmakefile:\n\n@example\n@group\nFOO = $PATH\n\nall:\n        @@echo $(FOO)\n        @@echo $(value FOO)\n@end group\n@end example\n\n@noindent\nThe first output line would be @code{ATH}, since the ``$P'' would be\nexpanded as a @code{make} variable, while the second output line would\nbe the current value of your @code{$PATH} environment variable, since\nthe @code{value} function avoided the expansion.\n\nThe @code{value} function is most often used in conjunction with the\n@code{eval} function (@pxref{Eval Function}).\n\n@node Eval Function\n@comment  node-name,  next,  previous,  up\n@section The @code{eval} Function\n@findex eval\n@cindex evaluating makefile syntax\n@cindex makefile syntax, evaluating\n\nThe @code{eval} function is very special: it allows you to define new\nmakefile constructs that are not constant; which are the result of\nevaluating other variables and functions.  The argument to the\n@code{eval} function is expanded, then the results of that expansion\nare parsed as makefile syntax.  The expanded results can define new\n@code{make} variables, targets, implicit or explicit rules, etc.\n\nThe result of the @code{eval} function is always the empty string;\nthus, it can be placed virtually anywhere in a makefile without\ncausing syntax errors.\n\nIt's important to realize that the @code{eval} argument is expanded\n@emph{twice}; first by the @code{eval} function, then the results of\nthat expansion are expanded again when they are parsed as makefile\nsyntax.  This means you may need to provide extra levels of escaping\nfor ``$'' characters when using @code{eval}.  The @code{value}\nfunction (@pxref{Value Function}) can sometimes be useful in these\nsituations, to circumvent unwanted expansions.\n\nHere is an example of how @code{eval} can be used; this example\ncombines a number of concepts and other functions.  Although it might\nseem overly complex to use @code{eval} in this example, rather than\njust writing out the rules, consider two things: first, the template\ndefinition (in @code{PROGRAM_template}) could need to be much more\ncomplex than it is here; and second, you might put the complex,\n``generic'' part of this example into another makefile, then include\nit in all the individual makefiles.  Now your individual makefiles are\nquite straightforward.\n\n@example\n@group\nPROGRAMS    = server client\n\nserver_OBJS = server.o server_priv.o server_access.o\nserver_LIBS = priv protocol\n\nclient_OBJS = client.o client_api.o client_mem.o\nclient_LIBS = protocol\n\n# Everything after this is generic\n\n.PHONY: all\nall: $(PROGRAMS)\n\ndefine PROGRAM_template =\n $(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)\n ALL_OBJS   += $$($(1)_OBJS)\nendef\n\n$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))\n\n$(PROGRAMS):\n        $(LINK.o) $^ $(LDLIBS) -o $@@\n\nclean:\n        rm -f $(ALL_OBJS) $(PROGRAMS)\n@end group\n@end example\n\n@node Origin Function\n@section The @code{origin} Function\n@findex origin\n@cindex variables, origin of\n@cindex origin of variable\n\nThe @code{origin} function is unlike most other functions in that it does\nnot operate on the values of variables; it tells you something @emph{about}\na variable.  Specifically, it tells you where it came from.\n\nThe syntax of the @code{origin} function is:\n\n@example\n$(origin @var{variable})\n@end example\n\nNote that @var{variable} is the @emph{name} of a variable to inquire about,\nnot a @emph{reference} to that variable.  Therefore you would not normally\nuse a @samp{$} or parentheses when writing it.  (You can, however, use a\nvariable reference in the name if you want the name not to be a constant.)\n\nThe result of this function is a string telling you how the variable\n@var{variable} was defined:\n\n@table @samp\n@item undefined\n\nif @var{variable} was never defined.\n\n@item default\n\nif @var{variable} has a default definition, as is usual with @code{CC}\nand so on.  @xref{Implicit Variables, ,Variables Used by Implicit Rules}.\nNote that if you have redefined a default variable, the @code{origin}\nfunction will return the origin of the later definition.\n\n@item environment\n\nif @var{variable} was inherited from the environment provided to\n@code{make}.\n\n@item environment override\n\nif @var{variable} was inherited from the environment provided to\n@code{make}, and is overriding a setting for @var{variable} in the\nmakefile as a result of the @w{@samp{-e}} option (@pxref{Options\nSummary, ,Summary of Options}).\n\n@item file\n\nif @var{variable} was defined in a makefile.\n\n@item command line\n\nif @var{variable} was defined on the command line.\n\n@item override\n\nif @var{variable} was defined with an @code{override} directive in a\nmakefile (@pxref{Override Directive, ,The @code{override} Directive}).\n\n@item automatic\n\nif @var{variable} is an automatic variable defined for the execution\nof the recipe for each rule (@pxref{Automatic Variables}).\n@end table\n\nThis information is primarily useful (other than for your curiosity) to\ndetermine if you want to believe the value of a variable.  For example,\nsuppose you have a makefile @file{foo} that includes another makefile\n@file{bar}.  You want a variable @code{bletch} to be defined in @file{bar}\nif you run the command @w{@samp{make -f bar}}, even if the environment contains\na definition of @code{bletch}.  However, if @file{foo} defined\n@code{bletch} before including @file{bar}, you do not want to override that\ndefinition.  This could be done by using an @code{override} directive in\n@file{foo}, giving that definition precedence over the later definition in\n@file{bar}; unfortunately, the @code{override} directive would also\noverride any command line definitions.  So, @file{bar} could\ninclude:\n\n@example\n@group\nifdef bletch\nifeq \"$(origin bletch)\" \"environment\"\nbletch = barf, gag, etc.\nendif\nendif\n@end group\n@end example\n\n@noindent\nIf @code{bletch} has been defined from the environment, this will redefine\nit.\n\nIf you want to override a previous definition of @code{bletch} if it came\nfrom the environment, even under @samp{-e}, you could instead write:\n\n@example\n@group\nifneq \"$(findstring environment,$(origin bletch))\" \"\"\nbletch = barf, gag, etc.\nendif\n@end group\n@end example\n\nHere the redefinition takes place if @samp{$(origin bletch)} returns either\n@samp{environment} or @samp{environment override}.\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@node Flavor Function\n@section The @code{flavor} Function\n@findex flavor\n@cindex variables, flavor of\n@cindex flavor of variable\n\nThe @code{flavor} function, like the @code{origin} function, does not\noperate on the values of variables but rather it tells you something\n@emph{about} a variable.  Specifically, it tells you the flavor of a\nvariable (@pxref{Flavors, ,The Two Flavors of Variables}).\n\nThe syntax of the @code{flavor} function is:\n\n@example\n$(flavor @var{variable})\n@end example\n\nNote that @var{variable} is the @emph{name} of a variable to inquire about,\nnot a @emph{reference} to that variable.  Therefore you would not normally\nuse a @samp{$} or parentheses when writing it.  (You can, however, use a\nvariable reference in the name if you want the name not to be a constant.)\n\nThe result of this function is a string that identifies the flavor of the\nvariable @var{variable}:\n\n@table @samp\n@item undefined\n\nif @var{variable} was never defined.\n\n@item recursive\n\nif @var{variable} is a recursively expanded variable.\n\n@item simple\n\nif @var{variable} is a simply expanded variable.\n\n@end table\n\n@node Make Control Functions\n@section Functions That Control Make\n@cindex functions, for controlling make\n@cindex controlling make\n\nThese functions control the way make runs.  Generally, they are used to\nprovide information to the user of the makefile or to cause make to stop\nif some sort of environmental error is detected.\n\n@table @code\n@item $(error @var{text}@dots{})\n@findex error\n@cindex error, stopping on\n@cindex stopping make\nGenerates a fatal error where the message is @var{text}.  Note that\nthe error is generated whenever this function is evaluated.  So, if\nyou put it inside a recipe or on the right side of a recursive\nvariable assignment, it won't be evaluated until later.  The\n@var{text} will be expanded before the error is generated.\n\nFor example,\n\n@example\nifdef ERROR1\n$(error error is $(ERROR1))\nendif\n@end example\n\n@noindent\nwill generate a fatal error during the read of the makefile if the\n@code{make} variable @code{ERROR1} is defined.  Or,\n\n@example\nERR = $(error found an error!)\n\n.PHONY: err\nerr: ; $(ERR)\n@end example\n\n@noindent\nwill generate a fatal error while @code{make} is running, if the\n@code{err} target is invoked.\n\n@item $(warning @var{text}@dots{})\n@findex warning\n@cindex warnings, printing\n@cindex printing user warnings\nThis function works similarly to the @code{error} function, above,\nexcept that @code{make} doesn't exit.  Instead, @var{text} is expanded\nand the resulting message is displayed, but processing of the makefile\ncontinues.\n\nThe result of the expansion of this function is the empty string.\n\n@item $(info @var{text}@dots{})\n@findex info\n@cindex printing messages\nThis function does nothing more than print its (expanded) argument(s)\nto standard output.  No makefile name or line number is added.  The\nresult of the expansion of this function is the empty string.\n@end table\n\n@node Shell Function\n@section The @code{shell} Function\n@findex shell\n@cindex command expansion\n@cindex backquotes\n@cindex shell command, function for\n\nThe @code{shell} function is unlike any other function other than the\n@code{wildcard} function\n(@pxref{Wildcard Function, ,The Function @code{wildcard}}) in that it\ncommunicates with the world outside of @code{make}.\n\nThe @code{shell} function provides for @code{make} the same facility that\nbackquotes (@samp{`}) provide in most shells: it does @dfn{command expansion}.\nThis means that it takes as an argument a shell command and expands to the\noutput of the command.  The only processing @code{make} does on the result is\nto convert each newline (or carriage-return / newline pair) to a single space.\nIf there is a trailing (carriage-return and) newline it will simply be\nremoved.\n\nThe commands run by calls to the @code{shell} function are run when the\nfunction calls are expanded (@pxref{Reading Makefiles, , How @code{make} Reads\na Makefile}).  Because this function involves spawning a new shell, you should\ncarefully consider the performance implications of using the @code{shell}\nfunction within recursively expanded variables vs.@: simply expanded variables\n(@pxref{Flavors, ,The Two Flavors of Variables}).\n\nAn alternative to the @code{shell} function is the @samp{!=} assignment\noperator; it provides a similar behavior but has subtle differences\n(@pxref{Setting, , Setting Variables}).  The @samp{!=} assignment operator is\nincluded in newer POSIX standards.\n\n@vindex .SHELLSTATUS\nAfter the @code{shell} function or @samp{!=} assignment operator is\nused, its exit status is placed in the @code{.SHELLSTATUS} variable.\n\nHere are some examples of the use of the @code{shell} function:\n\n@example\ncontents := $(shell cat foo)\n@end example\n\n@noindent\nsets @code{contents} to the contents of the file @file{foo}, with a space\n(rather than a newline) separating each line.\n\n@example\nfiles := $(shell echo *.c)\n@end example\n\n@noindent\nsets @code{files} to the expansion of @samp{*.c}.  Unless @code{make} is\nusing a very strange shell, this has the same result as\n@w{@samp{$(wildcard *.c)}} (as long as at least one @samp{.c} file\nexists).\n\nAll variables that are marked as @code{export} will also be passed to the\nshell started by the @code{shell} function.  It is possible to create a\nvariable expansion loop: consider this @file{makefile}:\n\n@example\nexport HI = $(shell echo hi)\nall: ; @@echo $$HI\n@end example\n\nWhen @code{make} wants to run the recipe it must add the variable @var{HI} to\nthe environment; to do so it must be expanded.  The value of this variable\nrequires an invocation of the @code{shell} function, and to invoke it we must\ncreate its environment.  Since @var{HI} is exported, we need to expand it to\ncreate its environment.  And so on.  In this obscure case @code{make} will use\nthe value of the variable from the environment provided to @code{make}, or\nelse the empty string if there was none, rather than looping or issuing an\nerror.  This is often what you want; for example:\n\n@example\nexport PATH = $(shell echo /usr/local/bin:$$PATH)\n@end example\n\nHowever, it would be simpler and more efficient to use a simply-expanded\nvariable here (@samp{:=}) in the first place.\n\n@node Guile Function\n@section The @code{guile} Function\n@findex guile\n@cindex Guile\n\nIf GNU @code{make} is built with support for GNU Guile as an embedded\nextension language then the @code{guile} function will be available.\nThe @code{guile} function takes one argument which is first expanded\nby @code{make} in the normal fashion, then passed to the GNU Guile\nevaluator.  The result of the evaluator is converted into a string and\nused as the expansion of the @code{guile} function in the makefile.\nSee @ref{Guile Integration, ,GNU Guile Integration} for details on\nwriting extensions to @code{make} in Guile.\n\nYou can determine whether GNU Guile support is available by checking\nthe @code{.FEATURES} variable for the word @var{guile}.\n\n@node Running\n@chapter How to Run @code{make}\n\nA makefile that says how to recompile a program can be used in more\nthan one way.  The simplest use is to recompile every file that is out\nof date.  Usually, makefiles are written so that if you run\n@code{make} with no arguments, it does just that.\n\nBut you might want to update only some of the files; you might want to use\na different compiler or different compiler options; you might want just to\nfind out which files are out of date without changing them.\n\nBy giving arguments when you run @code{make}, you can do any of these\nthings and many others.\n\n@cindex exit status of make\nThe exit status of @code{make} is always one of three values:\n@table @code\n@item 0\nThe exit status is zero if @code{make} is successful.\n@item 2\nThe exit status is two if @code{make} encounters any errors.\nIt will print messages describing the particular errors.\n@item 1\nThe exit status is one if you use the @samp{-q} flag and @code{make}\ndetermines that some target is not already up to date.\n@xref{Instead of Execution, ,Instead of Executing Recipes}.\n@end table\n\n@menu\n* Makefile Arguments::          How to specify which makefile to use.\n* Goals::                       How to use goal arguments to specify which\n                                  parts of the makefile to use.\n* Instead of Execution::        How to use mode flags to specify what\n                                  kind of thing to do with the recipes\n                                  in the makefile other than simply\n                                  execute them.\n* Avoiding Compilation::        How to avoid recompiling certain files.\n* Overriding::                  How to override a variable to specify\n                                  an alternate compiler and other things.\n* Testing::                     How to proceed past some errors, to\n                                  test compilation.\n* Warnings::                    How to control reporting of makefile issues.\n* Temporary Files::             Where @code{make} keeps its temporary files.\n* Options Summary::             Summary of Options\n@end menu\n\n@node Makefile Arguments\n@section Arguments to Specify the Makefile\n@cindex @code{--file}\n@cindex @code{--makefile}\n@cindex @code{-f}\n\nThe way to specify the name of the makefile is with the @samp{-f} or\n@samp{--file} option (@samp{--makefile} also works).  For example,\n@samp{-f altmake} says to use the file @file{altmake} as the makefile.\n\nIf you use the @samp{-f} flag several times and follow each @samp{-f}\nwith an argument, all the specified files are used jointly as\nmakefiles.\n\nIf you do not use the @samp{-f} or @samp{--file} flag, the default is\nto try @file{GNUmakefile}, @file{makefile}, and @file{Makefile}, in\nthat order, and use the first of these three which exists or can be made\n(@pxref{Makefiles, ,Writing Makefiles}).\n\n@node Goals\n@section Arguments to Specify the Goals\n@cindex goal, how to specify\n\nThe @dfn{goals} are the targets that @code{make} should strive ultimately\nto update.  Other targets are updated as well if they appear as\nprerequisites of goals, or prerequisites of prerequisites of goals, etc.\n\nBy default, the goal is the first target in the makefile (not counting\ntargets that start with a period).  Therefore, makefiles are usually\nwritten so that the first target is for compiling the entire program or\nprograms they describe.  If the first rule in the makefile has several\ntargets, only the first target in the rule becomes the default goal, not\nthe whole list.  You can manage the selection of the default goal from\nwithin your makefile using the @code{.DEFAULT_GOAL} variable\n(@pxref{Special Variables, , Other Special Variables}).\n\nYou can also specify a different goal or goals with command line\narguments to @code{make}.  Use the name of the goal as an argument.\nIf you specify several goals, @code{make} processes each of them in\nturn, in the order you name them.\n\nAny target in the makefile may be specified as a goal (unless it\nstarts with @samp{-} or contains an @samp{=}, in which case it will be\nparsed as a switch or variable definition, respectively).  Even\ntargets not in the makefile may be specified, if @code{make} can find\nimplicit rules that say how to make them.\n\n@vindex MAKECMDGOALS\n@code{Make} will set the special variable @code{MAKECMDGOALS} to the\nlist of goals you specified on the command line.  If no goals were given\non the command line, this variable is empty.  Note that this variable\nshould be used only in special circumstances.\n\nAn example of appropriate use is to avoid including @file{.d} files\nduring @code{clean} rules (@pxref{Automatic Prerequisites}), so\n@code{make} won't create them only to immediately remove them\nagain:\n\n@example\n@group\nsources = foo.c bar.c\n\nifeq (,$(filter clean,$(MAKECMDGOALS)))\ninclude $(sources:.c=.d)\nendif\n@end group\n@end example\n\nOne use of specifying a goal is if you want to compile only a part of\nthe program, or only one of several programs.  Specify as a goal each\nfile that you wish to remake.  For example, consider a directory containing\nseveral programs, with a makefile that starts like this:\n\n@example\n.PHONY: all\nall: size nm ld ar as\n@end example\n\nIf you are working on the program @code{size}, you might want to say\n@w{@samp{make size}} so that only the files of that program are recompiled.\n\nAnother use of specifying a goal is to make files that are not normally\nmade.  For example, there may be a file of debugging output, or a\nversion of the program that is compiled specially for testing, which has\na rule in the makefile but is not a prerequisite of the default goal.\n\nAnother use of specifying a goal is to run the recipe associated with\na phony target (@pxref{Phony Targets}) or empty target (@pxref{Empty\nTargets, ,Empty Target Files to Record Events}).  Many makefiles contain\na phony target named @file{clean} which deletes everything except source\nfiles.  Naturally, this is done only if you request it explicitly with\n@w{@samp{make clean}}.  Following is a list of typical phony and empty\ntarget names.  @xref{Standard Targets}, for a detailed list of all the\nstandard target names which GNU software packages use.\n\n@table @file\n@item all\n@cindex @code{all} @r{(standard target)}\nMake all the top-level targets the makefile knows about.\n\n@item clean\n@cindex @code{clean} @r{(standard target)}\nDelete all files that are normally created by running @code{make}.\n\n@item mostlyclean\n@cindex @code{mostlyclean} @r{(standard target)}\nLike @samp{clean}, but may refrain from deleting a few files that people\nnormally don't want to recompile.  For example, the @samp{mostlyclean}\ntarget for GCC does not delete @file{libgcc.a}, because recompiling it\nis rarely necessary and takes a lot of time.\n\n@item distclean\n@cindex @code{distclean} @r{(standard target)}\n@itemx realclean\n@cindex @code{realclean} @r{(standard target)}\n@itemx clobber\n@cindex @code{clobber} @r{(standard target)}\nAny of these targets might be defined to delete @emph{more} files than\n@samp{clean} does.  For example, this would delete configuration files\nor links that you would normally create as preparation for compilation,\neven if the makefile itself cannot create these files.\n\n@item install\n@cindex @code{install} @r{(standard target)}\nCopy the executable file into a directory that users typically search\nfor commands; copy any auxiliary files that the executable uses into\nthe directories where it will look for them.\n\n@item print\n@cindex @code{print} @r{(standard target)}\nPrint listings of the source files that have changed.\n\n@item tar\n@cindex @code{tar} @r{(standard target)}\nCreate a tar file of the source files.\n\n@item shar\n@cindex @code{shar} @r{(standard target)}\nCreate a shell archive (shar file) of the source files.\n\n@item dist\n@cindex @code{dist} @r{(standard target)}\nCreate a distribution file of the source files.  This might\nbe a tar file, or a shar file, or a compressed version of one of the\nabove, or even more than one of the above.\n\n@item TAGS\n@cindex @code{TAGS} @r{(standard target)}\nUpdate a tags table for this program.\n\n@item check\n@cindex @code{check} @r{(standard target)}\n@itemx test\n@cindex @code{test} @r{(standard target)}\nPerform self tests on the program this makefile builds.\n@end table\n\n@node Instead of Execution\n@section Instead of Executing Recipes\n@cindex execution, instead of\n@cindex recipes, instead of executing\n\nThe makefile tells @code{make} how to tell whether a target is up to date,\nand how to update each target.  But updating the targets is not always\nwhat you want.  Certain options specify other activities for @code{make}.\n\n@comment Extra blank lines make it print better.\n@table @samp\n@item -n\n@itemx --just-print\n@itemx --dry-run\n@itemx --recon\n@cindex @code{--just-print}\n@cindex @code{--dry-run}\n@cindex @code{--recon}\n@cindex @code{-n}\n\n``No-op''.  Causes @code{make} to print the recipes that are needed to\nmake the targets up to date, but not actually execute them.  Note that\nsome recipes are still executed, even with this flag (@pxref{MAKE\nVariable, ,How the @code{MAKE} Variable Works}).  Also any recipes\nneeded to update included makefiles are still executed\n(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}).\n\n@item -t\n@itemx --touch\n@cindex @code{--touch}\n@cindex touching files\n@cindex target, touching\n@cindex @code{-t}\n\n``Touch''.  Marks targets as up to date without actually changing\nthem.  In other words, @code{make} pretends to update the targets but\ndoes not really change their contents; instead only their modification\ntimes are updated.\n\n@item -q\n@itemx --question\n@cindex @code{--question}\n@cindex @code{-q}\n@cindex question mode\n\n``Question''.  Silently check whether the targets are up to date, but\ndo not execute recipes; the exit code shows whether any updates are\nneeded.\n\n@item -W @var{file}\n@itemx --what-if=@var{file}\n@itemx --assume-new=@var{file}\n@itemx --new-file=@var{file}\n@cindex @code{--what-if}\n@cindex @code{-W}\n@cindex @code{--assume-new}\n@cindex @code{--new-file}\n@cindex what if\n@cindex files, assuming new\n\n``What if''.  Each @samp{-W} flag is followed by a file name.  The given\nfiles' modification times are recorded by @code{make} as being the present\ntime, although the actual modification times remain the same.\nYou can use the @samp{-W} flag in conjunction with the @samp{-n} flag\nto see what would happen if you were to modify specific files.\n@end table\n\nWith the @samp{-n} flag, @code{make} prints the recipe that it would\nnormally execute but usually does not execute it.\n\nWith the @samp{-t} flag, @code{make} ignores the recipes in the rules\nand uses (in effect) the command @code{touch} for each target that needs to\nbe remade.  The @code{touch} command is also printed, unless @samp{-s} or\n@code{.SILENT} is used.  For speed, @code{make} does not actually invoke\nthe program @code{touch}.  It does the work directly.\n\nWith the @samp{-q} flag, @code{make} prints nothing and executes no\nrecipes, but the exit status code it returns is zero if and only if the\ntargets to be considered are already up to date.  If the exit status is\none, then some updating needs to be done.  If @code{make} encounters an\nerror, the exit status is two, so you can distinguish an error from a\ntarget that is not up to date.\n\nIt is an error to use more than one of these three flags in the same\ninvocation of @code{make}.\n\n@cindex +, and recipe execution\nThe @samp{-n}, @samp{-t}, and @samp{-q} options do not affect recipe\nlines that begin with @samp{+} characters or contain the strings\n@samp{$(MAKE)} or @samp{$@{MAKE@}}.  Note that only the line containing\nthe @samp{+} character or the strings @samp{$(MAKE)} or @samp{$@{MAKE@}}\nis run regardless of these options.  Other lines in the same rule are\nnot run unless they too begin with @samp{+} or contain @samp{$(MAKE)} or\n@samp{$@{MAKE@}} (@xref{MAKE Variable, ,How the @code{MAKE} Variable Works}.)\n\n@cindex phony targets and recipe execution\nThe @samp{-t} flag prevents phony targets (@pxref{Phony Targets}) from\nbeing updated, unless there are recipe lines beginning with @samp{+}\nor containing @samp{$(MAKE)} or @samp{$@{MAKE@}}.\n\nThe @samp{-W} flag provides two features:\n\n@itemize @bullet\n@item\nIf you also use the @samp{-n} or @samp{-q} flag, you can see what\n@code{make} would do if you were to modify some files.\n\n@item\nWithout the @samp{-n} or @samp{-q} flag, when @code{make} is actually\nexecuting recipes, the @samp{-W} flag can direct @code{make} to act as\nif some files had been modified, without actually running the recipes\nfor those files.\n@end itemize\n\nNote that the options @samp{-p} and @samp{-v} allow you to obtain other\ninformation about @code{make} or about the makefiles in use\n(@pxref{Options Summary, ,Summary of Options}).\n\n@node Avoiding Compilation\n@section Avoiding Recompilation of Some Files\n@cindex @code{-o}\n@cindex @code{--old-file}\n@cindex @code{--assume-old}\n@cindex files, assuming old\n@cindex files, avoiding recompilation of\n@cindex recompilation, avoiding\n\nSometimes you may have changed a source file but you do not want to\nrecompile all the files that depend on it.  For example, suppose you add\na macro or a declaration to a header file that many other files depend\non.  Being conservative, @code{make} assumes that any change in the\nheader file requires recompilation of all dependent files, but you know\nthat they do not need to be recompiled and you would rather not waste\nthe time waiting for them to compile.\n\nIf you anticipate the problem before changing the header file, you can\nuse the @samp{-t} flag.  This flag tells @code{make} not to run the\nrecipes in the rules, but rather to mark the target up to date by\nchanging its last-modification date.  You would follow this procedure:\n\n@enumerate\n@item\nUse the command @samp{make} to recompile the source files that really\nneed recompilation, ensuring that the object files are up-to-date\nbefore you begin.\n\n@item\nMake the changes in the header files.\n\n@item\nUse the command @samp{make -t} to mark all the object files as\nup to date.  The next time you run @code{make}, the changes in the\nheader files will not cause any recompilation.\n@end enumerate\n\nIf you have already changed the header file at a time when some files\ndo need recompilation, it is too late to do this.  Instead, you can\nuse the @w{@samp{-o @var{file}}} flag, which marks a specified file as\n``old'' (@pxref{Options Summary, ,Summary of Options}).  This means\nthat the file itself will not be remade, and nothing else will be\nremade on its account.  Follow this procedure:\n\n@enumerate\n@item\nRecompile the source files that need compilation for reasons independent\nof the particular header file, with @samp{make -o @var{headerfile}}.\nIf several header files are involved, use a separate @samp{-o} option\nfor each header file.\n\n@item\nTouch all the object files with @samp{make -t}.\n@end enumerate\n\n@node Overriding\n@section Overriding Variables\n@cindex overriding variables with arguments\n@cindex variables, overriding with arguments\n@cindex command line variables\n@cindex variables, command line\n\nAn argument that contains @samp{=} specifies the value of a variable:\n@samp{@var{v}=@var{x}} sets the value of the variable @var{v} to @var{x}.\nIf you specify a value in this way, all ordinary assignments of the same\nvariable in the makefile are ignored; we say they have been\n@dfn{overridden} by the command line argument.\n\nThe most common way to use this facility is to pass extra flags to\ncompilers.  For example, in a properly written makefile, the variable\n@code{CFLAGS} is included in each recipe that runs the C compiler, so a\nfile @file{foo.c} would be compiled something like this:\n\n@example\ncc -c $(CFLAGS) foo.c\n@end example\n\nThus, whatever value you set for @code{CFLAGS} affects each compilation\nthat occurs.  The makefile probably specifies the usual value for\n@code{CFLAGS}, like this:\n\n@example\nCFLAGS=-g\n@end example\n\nEach time you run @code{make}, you can override this value if you\nwish.  For example, if you say @samp{make CFLAGS='-g -O'}, each C\ncompilation will be done with @samp{cc -c -g -O}.  (This also\nillustrates how you can use quoting in the shell to enclose spaces and\nother special characters in the value of a variable when you override\nit.)\n\nThe variable @code{CFLAGS} is only one of many standard variables that\nexist just so that you can change them this way.  @xref{Implicit\nVariables, , Variables Used by Implicit Rules}, for a complete list.\n\nYou can also program the makefile to look at additional variables of your\nown, giving the user the ability to control other aspects of how the\nmakefile works by changing the variables.\n\nWhen you override a variable with a command line argument, you can\ndefine either a recursively-expanded variable or a simply-expanded\nvariable.  The examples shown above make a recursively-expanded\nvariable; to make a simply-expanded variable, write @samp{:=} or\n@samp{::=} instead of @samp{=}.  But, unless you want to include a\nvariable reference or function call in the @emph{value} that you\nspecify, it makes no difference which kind of variable you create.\n\nThere is one way that the makefile can change a variable that you have\noverridden.  This is to use the @code{override} directive, which is a line\nthat looks like this: @samp{override @var{variable} = @var{value}}\n(@pxref{Override Directive, ,The @code{override} Directive}).\n\n@node Testing\n@section Testing the Compilation of a Program\n@cindex testing compilation\n@cindex compilation, testing\n\nNormally, when an error happens in executing a shell command, @code{make}\ngives up immediately, returning a nonzero status.  No further recipes are\nexecuted for any target.  The error implies that the goal cannot be\ncorrectly remade, and @code{make} reports this as soon as it knows.\n\nWhen you are compiling a program that you have just changed, this is not\nwhat you want.  Instead, you would rather that @code{make} try compiling\nevery file that can be tried, to show you as many compilation errors\nas possible.\n\n@cindex @code{-k}\n@cindex @code{--keep-going}\nOn these occasions, you should use the @samp{-k} or\n@samp{--keep-going} flag.  This tells @code{make} to continue to\nconsider the other prerequisites of the pending targets, remaking them\nif necessary, before it gives up and returns nonzero status.  For\nexample, after an error in compiling one object file, @samp{make -k}\nwill continue compiling other object files even though it already\nknows that linking them will be impossible.  In addition to continuing\nafter failed shell commands, @samp{make -k} will continue as much as\npossible after discovering that it does not know how to make a target\nor prerequisite file.  This will always cause an error message, but\nwithout @samp{-k}, it is a fatal error (@pxref{Options Summary,\n,Summary of Options}).\n\nThe usual behavior of @code{make} assumes that your purpose is to get the\ngoals up to date; once @code{make} learns that this is impossible, it might as\nwell report the failure immediately.  The @samp{-k} flag allows testing as\nmany of the changes made in the program as possible, perhaps to find several\nindependent problems so that you can correct them all before the next attempt\nto compile.  This is why Emacs' @kbd{M-x compile} command passes the @samp{-k}\nflag by default.\n\n@node Warnings\n@section Makefile Warnings\n@cindex warnings\n@cindex enabling warnings\n\nGNU Make can detect some types of incorrect usage in makefiles.  When one of\nthese incorrect usages is detected, GNU Make can perform one of these actions:\n\n@table @samp\n@item ignore\n@cindex warning action ignore\n@cindex ignore, warning action\nIgnore the usage.\n\n@item warn\n@cindex warning action warn\n@cindex warn, warning action\nShow a warning about the usage and continue processing the makefile.\n\n@item error\n@cindex warning action error\n@cindex error, warning action\nShow an error for the usage and immediately stop processing the makefile.\n@end table\n\n@noindent\nThe types of warnings GNU Make can detect are:\n\n@table @samp\n@item circular-dep\n@findex circular-dep\n@cindex warning circular dependency\nFinding a loop in the dependency graph (the prerequisites of a target contain\nor depend on the target itself).  If the action is not @samp{error}, the\ncircular reference is dropped from the graph before continuing.  The default\naction is @samp{warn}.\n\n@item invalid-ref\n@findex invalid-ref\n@cindex warning invalid reference\nUsing an invalid variable name in a variable reference.  The default action is\n@samp{warn}.\n\n@item invalid-var\n@findex invalid-var\n@cindex warning invalid variable\nAssigning to an invalid variable name (e.g., a name containing whitespace).\nThe default action is @samp{warn}.\n\n@item undefined-var\n@findex undefined-var\n@cindex warning undefined variable\nReferencing a variable that has not been defined.  The default action is\n@samp{ignore}.  Note the deprecated @code{--warn-undefined-variables} option\nsets the action for this warning to @samp{warn}.\n@end table\n\nThe actions for these warnings can be changed by specifying warning control\noptions.  Each warning control option consists of either a warning type, or a\nwarning action, or a warning type and warning action separated by a colon\n(@code{:}).  Multiple control options are separated by either whitespace or\ncommas.\n\nIf the control option is just a warning type, then the action associated with\nthat type is set to @code{warn}.  If the option is just an action, then that\naction is applied to all warning types (a ``global action'').\n\n``Global actions'' take precedence over default actions.  Actions associated\nwith a specific warning type take precedence over ``global actions'' and\ndefault actions.\n\nIf multiple control options provide actions for the same warning type, the\nlast action specified will be used.\n\nThere are two ways to specify control options: using the @code{--warn} command\nline option, or using the @code{.WARNINGS} variable.\n\n@subsubheading The @code{.WARNINGS} variable\n@vindex .WARNINGS\nWarning control options provided in the @code{.WARNINGS} variable take effect\nas soon as the variable assignment is parsed and will last until this instance\nof @code{make} finishes parsing all makefiles.  These settings will not be\npassed to recursive invocations of @code{make}.\n\nNote that the value of this variable is expanded immediately, even if the\nrecursive expansion assignment operator (@code{=}) is used.\n\nEach assignment of @code{.WARNINGS} completely replaces any previous settings.\nIf you want to preserve the previous settings, use the @code{+=} assignment\noperator.\n\nCurrently, assigning @code{.WARNINGS} as a target-specific or pattern-specific\nvariable has no effect.  This may change in the future.\n\n@subsubheading The @code{--warn} option\n@cindex @code{--warn}\nThe @code{--warn} option can be specified on the command line, or by adding it\nto the @code{MAKEFLAGS} variable (@pxref{Recursion, ,Recursive Use of\n@code{make}}).  Settings added to @code{MAKEFLAGS} take affect after the\nassignment is parsed.  This option is passed to sub-makes through the\n@code{MAKEFLAGS} variable.\n\nThe @code{--warn} option can be provided multiple times: the effects are\ncumulative with later options overriding over earlier options.  When GNU Make\nprovides warning settings to sub-makes, they are all combined into a single\n@code{--warn} option in @code{MAKEFLAGS} with a standard order.\n\nSpecifying @code{--warn} with no arguments is equivalent to using\n@code{--warn=warn}, which sets the action for all warning types to\n@samp{warn}.\n\nAny action specified with an @code{--warn} option will take precedence over\nactions provided in the makefile with @code{.WARNINGS}.  This means if you use\n@code{--warn=error}, for example, all warnings will be treated as errors\nregardless of any @code{.WARNINGS} assignments.\n\n@node Temporary Files\n@section Temporary Files\n@cindex temporary files\n\nIn some situations, @code{make} will need to create its own temporary files.\nThese files must not be disturbed while @code{make} is running, including all\nrecursively-invoked instances of @code{make}.  All temporary filenames created\nby GNU Make will start with the letters @samp{Gm}.\n\n@cindex @code{MAKE_TMPDIR}\nIf the environment variable @code{MAKE_TMPDIR} is set then all temporary files\ncreated by @code{make} will be placed there.\n\n@cindex @code{TMPDIR}\n@cindex @code{TMP}\n@cindex @code{TEMP}\nIf @code{MAKE_TMPDIR} is not set, then the standard location for temporary\nfiles for the current operating system will be used.  For POSIX systems this\nwill be the location set in the @code{TMPDIR} environment variable, or else\nthe system's default location (e.g., @file{/tmp}) is used.  On Windows,\nfirst @code{TMP} then @code{TEMP} will be checked, then @code{TMPDIR}, and\nfinally the system default temporary file location will be used.\n\nNote that this directory must already exist or @code{make} will fail:\n@code{make} will not attempt to create it.\n\nThese variables @emph{cannot} be set from within a makefile: GNU @code{make}\nmust have access to this location before it begins reading the makefiles.\n\n@node Options Summary\n@section Summary of Options\n@cindex options\n@cindex flags\n@cindex switches\n\nHere is a table of all the options @code{make} understands:\n\n@table @samp\n@item -b\n@cindex @code{-b}\n@itemx -m\n@cindex @code{-m}\nThese options are ignored for compatibility with other versions of @code{make}.\n\n@item -B\n@cindex @code{-B}\n@itemx --always-make\n@cindex @code{--always-make}\nConsider all targets out-of-date.  GNU @code{make} proceeds to\nconsider targets and their prerequisites using the normal algorithms;\nhowever, all targets so considered are always remade regardless of the\nstatus of their prerequisites.  To avoid infinite recursion, if\n@code{MAKE_RESTARTS} (@pxref{Special Variables, , Other Special\nVariables}) is set to a number greater than 0 this option is disabled\nwhen considering whether to remake makefiles (@pxref{Remaking\nMakefiles, , How Makefiles Are Remade}).\n\n@item -C @var{dir}\n@cindex @code{-C}\n@itemx --directory=@var{dir}\n@cindex @code{--directory}\nChange to directory @var{dir} before reading the makefiles.  If multiple\n@samp{-C} options are specified, each is interpreted relative to the\nprevious one: @samp{-C / -C etc} is equivalent to @samp{-C /etc}.\nThis is typically used with recursive invocations of @code{make}\n(@pxref{Recursion, ,Recursive Use of @code{make}}).\n\n@item -d\n@cindex @code{-d}\n@c Extra blank line here makes the table look better.\n\nPrint debugging information in addition to normal processing.  The\ndebugging information says which files are being considered for\nremaking, which file-times are being compared and with what results,\nwhich files actually need to be remade, which implicit rules are\nconsidered and which are applied---everything interesting about how\n@code{make} decides what to do.  The @code{-d} option is equivalent to\n@samp{--debug=a} (see below).\n\n@item --debug[=@var{options}]\n@cindex @code{--debug}\n@c Extra blank line here makes the table look better.\n\nPrint debugging information in addition to normal processing.  Various\nlevels and types of output can be chosen.  With no arguments, print the\n``basic'' level of debugging.  Possible arguments are below; only the\nfirst character is considered, and values must be comma- or\nspace-separated.\n\n@table @code\n@item a (@i{all})\nAll types of debugging output are enabled.  This is equivalent to using\n@samp{-d}.\n\n@item b (@i{basic})\nBasic debugging prints each target that was found to be out-of-date, and\nwhether the build was successful or not.\n\n@item v (@i{verbose})\nA level above @samp{basic}; includes messages about which makefiles were\nparsed, prerequisites that did not need to be rebuilt, etc.  This option\nalso enables @samp{basic} messages.\n\n@item i (@i{implicit})\nPrints messages describing the implicit rule searches for each target.\nThis option also enables @samp{basic} messages.\n\n@item j (@i{jobs})\nPrints messages giving details on the invocation of specific sub-commands.\n\n@item m (@i{makefile})\nBy default, debug messages are not enabled while trying to remake the\nmakefiles.  This option enables messages while rebuilding makefiles, too.  The\n@samp{all} option enables this option as well.  This option also enables\n@samp{basic} messages.\n\n@item p (@i{print})\nPrints the recipe to be executed, even when the recipe is normally\nsilent (due to @code{.SILENT} or @samp{@@}).\n\n@item w (@i{why})\nExplains why each target must be remade by showing which prerequisites\nare more up to date than the target.\n\n@item n (@i{none})\nDisable all debugging currently enabled.  If additional debugging\nflags are encountered after this they will still take effect.\n@end table\n\n@item -e\n@cindex @code{-e}\n@itemx --environment-overrides\n@cindex @code{--environment-overrides}\nGive variables taken from the environment precedence\nover variables from makefiles.\n@xref{Environment, ,Variables from the Environment}.\n\n@item -E @var{string}\n@cindex @code{-E}\n@item --eval=@var{string}\n@cindex @code{--eval}\n@c Extra blank line here makes the table look better.\n\nEvaluate @var{string} as makefile syntax.  This is a command-line\nversion of the @code{eval} function (@pxref{Eval Function}).  The\nevaluation is performed after the default rules and variables have\nbeen defined, but before any makefiles are read.\n\n@item -f @var{file}\n@cindex @code{-f}\n@itemx --file=@var{file}\n@cindex @code{--file}\n@itemx --makefile=@var{file}\n@cindex @code{--makefile}\nRead the file named @var{file} as a makefile.\n@xref{Makefiles, ,Writing Makefiles}.\n\n@item -h\n@cindex @code{-h}\n@itemx --help\n@cindex @code{--help}\n@c Extra blank line here makes the table look better.\n\nRemind you of the options that @code{make} understands and then exit.\n\n@item -i\n@cindex @code{-i}\n@itemx --ignore-errors\n@cindex @code{--ignore-errors}\nIgnore all errors in recipes executed to remake files.\n@xref{Errors, ,Errors in Recipes}.\n\n@item -I @var{dir}\n@cindex @code{-I}\n@itemx --include-dir=@var{dir}\n@cindex @code{--include-dir}\nSpecifies a directory @var{dir} to search for included makefiles.\n@xref{Include, ,Including Other Makefiles}.  If several @samp{-I}\noptions are used to specify several directories, the directories are\nsearched in the order specified.  If the directory @var{dir} is a\nsingle dash (@code{-}) then any already-specified directories up to\nthat point (including the default directory paths) will be discarded.\nYou can examine the current list of directories to be searched via the\n@code{.INCLUDE_DIRS} variable.\n\n@item -j [@var{jobs}]\n@cindex @code{-j}\n@itemx --jobs[=@var{jobs}]\n@cindex @code{--jobs}\nSpecifies the number of recipes (jobs) to run simultaneously.  With no\nargument, @code{make} runs as many recipes simultaneously as possible.\nIf there is more than one @samp{-j} option, the last one is effective.\n@xref{Parallel, ,Parallel Execution}, for more information on how\nrecipes are run.  Note that this option is ignored on MS-DOS.\n\n@item --jobserver-style=[@var{style}]\n@cindex @code{--jobserver-style}\nChooses the style of jobserver to use.  This option only has effect if\nparallel builds are enabled (@pxref{Parallel, ,Parallel Execution}).  On POSIX\nsystems @var{style} can be one of @code{fifo} (the default) or @code{pipe}.\nOn Windows the only acceptable @var{style} is @code{sem} (the default).  This\noption is useful if you need to use an older version of GNU @code{make}, or a\ndifferent tool that requires a specific jobserver style.\n\n@item -k\n@cindex @code{-k}\n@itemx --keep-going\n@cindex @code{--keep-going}\nContinue as much as possible after an error.  While the target that\nfailed, and those that depend on it, cannot be remade, the other\nprerequisites of these targets can be processed all the same.\n@xref{Testing, ,Testing the Compilation of a Program}.\n\n@item -l [@var{load}]\n@cindex @code{-l}\n@itemx --load-average[=@var{load}]\n@cindex @code{--load-average}\n@itemx --max-load[=@var{load}]\n@cindex @code{--max-load}\nSpecifies that no new recipes should be started if there are other\nrecipes running and the load average is at least @var{load} (a\nfloating-point number).  With no argument, removes a previous load\nlimit.  @xref{Parallel, ,Parallel Execution}.\n\n@item -L\n@cindex @code{-L}\n@itemx --check-symlink-times\n@cindex @code{--check-symlink-times}\nOn systems that support symbolic links, this option causes @code{make}\nto consider the timestamps on any symbolic links in addition to the\ntimestamp on the file referenced by those links.  When this option is\nprovided, the most recent timestamp among the file and the symbolic\nlinks is taken as the modification time for this target file.\n\n@item -n\n@cindex @code{-n}\n@itemx --just-print\n@cindex @code{--just-print}\n@itemx --dry-run\n@cindex @code{--dry-run}\n@itemx --recon\n@cindex @code{--recon}\n@c Extra blank line here makes the table look better.\n\nPrint the recipe that would be executed, but do not execute it (except\nin certain circumstances).\n@xref{Instead of Execution, ,Instead of Executing Recipes}.\n\n@item -o @var{file}\n@cindex @code{-o}\n@itemx --old-file=@var{file}\n@cindex @code{--old-file}\n@itemx --assume-old=@var{file}\n@cindex @code{--assume-old}\nDo not remake the file @var{file} even if it is older than its\nprerequisites, and do not remake anything on account of changes in\n@var{file}.  Essentially the file is treated as very old and its rules\nare ignored.  @xref{Avoiding Compilation, ,Avoiding Recompilation of\nSome Files}.\n\n@item -O[@var{type}]\n@cindex @code{-O}\n@itemx --output-sync[=@var{type}]\n@cindex @code{--output-sync}\n@cindex output during parallel execution\n@cindex parallel execution, output during\nEnsure that the complete output from each recipe is printed in one\nuninterrupted sequence.  This option is only useful when using the\n@code{--jobs} option to run multiple recipes simultaneously\n(@pxref{Parallel, ,Parallel Execution})  Without this option output\nwill be displayed as it is generated by the recipes.\n\nWith no type or the type @samp{target}, output from the entire recipe\nof each target is grouped together.  With the type @samp{line}, output\nfrom each line in the recipe is grouped together.  With the type\n@samp{recurse}, the output from an entire recursive make is grouped\ntogether.  With the type @samp{none}, no output synchronization is\nperformed.  @xref{Parallel Output, ,Output During Parallel Execution}.\n\n@item -p\n@cindex @code{-p}\n@itemx --print-data-base\n@cindex @code{--print-data-base}\n@cindex data base of @code{make} rules\n@cindex predefined rules and variables, printing\nPrint the data base (rules and variable values) that results from reading the\nmakefiles; then execute as usual or as otherwise specified.  This also prints\nthe version information given by the @samp{-v} switch (see below).  To print\nthe data base without trying to remake any files, use @w{@samp{make -qp}}.  To\nprint the data base of predefined rules and variables, use @w{@samp{make -p -f\n/dev/null}}.  The data base output contains file name and line number\ninformation for recipe and variable definitions, so it can be a useful\ndebugging tool in complex environments.\n\n@item --print-targets\n@cindex @code{--print-targets}\n@cindex print @file{makefile} targets\n@cindex targets, printing\nPrint all the targets defined by reading the makefiles, one target per line,\nthen exit immediately with success.  No implicit targets are printed.  No\nspecial targets (target names consisting of ``.'' followed by all upper-case\nletters) are printed.\n\nNo commands are run, including commands that would rebuild makefiles\n(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}); if makefiles need to\nbe rebuilt then the targets listed might be outdated.  Also, @code{make} will\nnot generate any errors or warnings for missing @code{include} files.\n\n@item -q\n@cindex @code{-q}\n@itemx --question\n@cindex @code{--question}\n``Question mode''.  Do not run any recipes, or print anything; just\nreturn an exit status that is zero if the specified targets are already\nup to date, one if any remaking is required, or two if an error is\nencountered.  @xref{Instead of Execution, ,Instead of Executing\nRecipes}.\n\n@item -r\n@cindex @code{-r}\n@itemx --no-builtin-rules\n@cindex @code{--no-builtin-rules}\nEliminate use of the built-in implicit rules (@pxref{Implicit Rules,\n,Using Implicit Rules}).  You can still define your own by writing\npattern rules (@pxref{Pattern Rules, ,Defining and Redefining Pattern\nRules}).  The @samp{-r} option also clears out the default list of\nsuffixes for suffix rules (@pxref{Suffix Rules, ,Old-Fashioned Suffix\nRules}).  But you can still define your own suffixes with a rule for\n@code{.SUFFIXES}, and then define your own suffix rules.  Note that only\n@emph{rules} are affected by the @code{-r} option; default variables\nremain in effect (@pxref{Implicit Variables, ,Variables Used by Implicit\nRules}); see the @samp{-R} option below.\n\n@item -R\n@cindex @code{-R}\n@itemx --no-builtin-variables\n@cindex @code{--no-builtin-variables}\nEliminate use of the built-in rule-specific variables (@pxref{Implicit\nVariables, ,Variables Used by Implicit Rules}).  You can still define\nyour own, of course.  The @samp{-R} option also automatically enables\nthe @samp{-r} option (see above), since it doesn't make sense to have\nimplicit rules without any definitions for the variables that they use.\n\n@item -s\n@cindex @code{-s}\n@itemx --silent\n@cindex @code{--silent}\n@itemx --quiet\n@cindex @code{--quiet}\n@c Extra blank line here makes the table look better.\n\nSilent operation; do not print the recipes as they are executed.\n@xref{Echoing, ,Recipe Echoing}.\n\n@item -S\n@cindex @code{-S}\n@itemx --no-keep-going\n@cindex @code{--no-keep-going}\n@itemx --stop\n@cindex @code{--stop}\n@c Extra blank line here makes the table look better.\n\nCancel the effect of the @samp{-k} option.  This is never necessary\nexcept in a recursive @code{make} where @samp{-k} might be inherited\nfrom the top-level @code{make} via @code{MAKEFLAGS}\n(@pxref{Recursion, ,Recursive Use of @code{make}})\nor if you set @samp{-k} in @code{MAKEFLAGS} in your environment.\n\n@item --shuffle[=@var{mode}]\n@cindex @code{--shuffle}\n@c Extra blank line here makes the table look better.\n\nThis option enables a form of fuzz-testing of prerequisite relationships.\nWhen parallelism is enabled (@samp{-j}) the order in which targets are\nbuilt becomes less deterministic.  If prerequisites are not fully declared\nin the makefile this can lead to intermittent and hard-to-track-down build\nfailures.\n\nThe @samp{--shuffle} option forces @code{make} to purposefully reorder goals\nand prerequisites so target/prerequisite relationships still hold, but\nordering of prerequisites of a given target are reordered as described below.\n\nThe order in which prerequisites are listed in automatic variables is not\nchanged by this option.\n\nThe @code{.NOTPARALLEL} pseudo-target disables shuffling for that makefile.\nAlso any prerequisite list which contains @code{.WAIT} will not be shuffled.\n@xref{Parallel Disable, ,Disabling Parallel Execution}.\n\nThe @samp{--shuffle=} option accepts these values:\n\n@table @code\n@item random\nChoose a random seed for the shuffle.  This is the default if no mode is\nspecified.  The chosen seed is also provided to sub-@code{make} commands.  The\nseed is included in error messages so that it can be re-used in future runs to\nreproduce the problem or verify that it has been resolved.\n\n@item reverse\nReverse the order of goals and prerequisites, rather than a random shuffle.\n\n@item @var{seed}\nUse @samp{random} shuffle initialized with the specified seed value.  The\n@var{seed} is an integer.\n\n@item none\nDisable shuffling.  This negates any previous @samp{--shuffle} options.\n@end table\n\n@item -t\n@cindex @code{-t}\n@itemx --touch\n@cindex @code{--touch}\n@c Extra blank line here makes the table look better.\n\nTouch files (mark them up to date without really changing them)\ninstead of running their recipes.  This is used to pretend that the\nrecipes were done, in order to fool future invocations of\n@code{make}.  @xref{Instead of Execution, ,Instead of Executing Recipes}.\n\n@item --trace\n@cindex @code{--trace}\nShow tracing information for @code{make} execution.  Using @code{--trace} is\nshorthand for @code{--debug=print,why}.\n\n@item -v\n@cindex @code{-v}\n@itemx --version\n@cindex @code{--version}\nPrint the version of the @code{make} program plus a copyright, a list\nof authors, and a notice that there is no warranty; then exit.\n\n@item -w\n@cindex @code{-w}\n@itemx --print-directory\n@cindex @code{--print-directory}\nPrint a message containing the working directory both before and after\nexecuting the makefile.  This may be useful for tracking down errors\nfrom complicated nests of recursive @code{make} commands.\n@xref{Recursion, ,Recursive Use of @code{make}}.  (In practice, you\nrarely need to specify this option since @samp{make} does it for you;\nsee @ref{-w Option, ,The @samp{--print-directory} Option}.)\n\n@item --no-print-directory\n@cindex @code{--no-print-directory}\nDisable printing of the working directory under @code{-w}.\nThis option is useful when @code{-w} is turned on automatically,\nbut you do not want to see the extra messages.\n@xref{-w Option, ,The @samp{--print-directory} Option}.\n\n@item -W @var{file}\n@cindex @code{-W}\n@itemx --what-if=@var{file}\n@cindex @code{--what-if}\n@itemx --new-file=@var{file}\n@cindex @code{--new-file}\n@itemx --assume-new=@var{file}\n@cindex @code{--assume-new}\nPretend that the target @var{file} has just been modified.  When used\nwith the @samp{-n} flag, this shows you what would happen if you were\nto modify that file.  Without @samp{-n}, it is almost the same as\nrunning a @code{touch} command on the given file before running\n@code{make}, except that the modification time is changed only in the\nimagination of @code{make}.\n@xref{Instead of Execution, ,Instead of Executing Recipes}.\n\n\n@item --warn[=@var{arg}[,@var{arg}]]\n@cindex @code{--warn}\n@cindex warnings\nSpecify the handling of @ref{Warnings, ,Makefile Warnings} detected in\nmakefiles.\n\n@item --warn-undefined-variables\n@cindex @code{--warn-undefined-variables}\n@cindex variables, warning for undefined\n@cindex undefined variables, warning message\nA deprecated name for @code{--warn=undefined-var}.  @xref{Warnings,\n,Makefile Warnings}.\n@end table\n\n@node Implicit Rules\n@chapter Using Implicit Rules\n@cindex implicit rule\n@cindex rule, implicit\n\nCertain standard ways of remaking target files are used very often.  For\nexample, one customary way to make an object file is from a C source file\nusing the C compiler, @code{cc}.\n\n@dfn{Implicit rules} tell @code{make} how to use customary techniques so\nthat you do not have to specify them in detail when you want to use\nthem.  For example, there is an implicit rule for C compilation.  File\nnames determine which implicit rules are run.  For example, C\ncompilation typically takes a @file{.c} file and makes a @file{.o} file.\nSo @code{make} applies the implicit rule for C compilation when it sees\nthis combination of file name endings.\n\nA chain of implicit rules can apply in sequence; for example, @code{make}\nwill remake a @file{.o} file from a @file{.y} file by way of a @file{.c} file.\n@iftex\n@xref{Chained Rules, ,Chains of Implicit Rules}.\n@end iftex\n\nThe built-in implicit rules use several variables in their recipes so\nthat, by changing the values of the variables, you can change the way the\nimplicit rule works.  For example, the variable @code{CFLAGS} controls the\nflags given to the C compiler by the implicit rule for C compilation.\n@iftex\n@xref{Implicit Variables, ,Variables Used by Implicit Rules}.\n@end iftex\n\nYou can define your own implicit rules by writing @dfn{pattern rules}.\n@iftex\n@xref{Pattern Rules, ,Defining and Redefining Pattern Rules}.\n@end iftex\n\n@dfn{Suffix rules} are a more limited way to define implicit rules.\nPattern rules are more general and clearer, but suffix rules are\nretained for compatibility.\n@iftex\n@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.\n@end iftex\n\n@menu\n* Using Implicit::              How to use an existing implicit rule\n                                  to get the recipes for updating a file.\n* Catalogue of Rules::          A list of built-in rules.\n* Implicit Variables::          How to change what predefined rules do.\n* Chained Rules::               How to use a chain of implicit rules.\n* Pattern Rules::               How to define new implicit rules.\n* Last Resort::                 How to define a recipe for rules which\n                                  cannot find any.\n* Suffix Rules::                The old-fashioned style of implicit rule.\n* Implicit Rule Search::        The precise algorithm for applying\n                                  implicit rules.\n@end menu\n\n@node Using Implicit\n@section Using Implicit Rules\n@cindex implicit rule, how to use\n@cindex rule, implicit, how to use\n\nTo allow @code{make} to find a customary method for updating a target\nfile, all you have to do is refrain from specifying recipes yourself.\nEither write a rule with no recipe, or don't write a rule at all.\nThen @code{make} will figure out which implicit rule to use based on\nwhich kind of source file exists or can be made.\n\nFor example, suppose the makefile looks like this:\n\n@example\nfoo : foo.o bar.o\n        cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)\n@end example\n\n@noindent\nBecause you mention @file{foo.o} but do not give a rule for it, @code{make}\nwill automatically look for an implicit rule that tells how to update it.\nThis happens whether or not the file @file{foo.o} currently exists.\n\nIf an implicit rule is found, it can supply both a recipe and one or\nmore prerequisites (the source files).  You would want to write a rule\nfor @file{foo.o} with no recipe if you need to specify additional\nprerequisites, such as header files, that the implicit rule cannot\nsupply.\n\nEach implicit rule has a target pattern and prerequisite patterns.  There may\nbe many implicit rules with the same target pattern.  For example, numerous\nrules make @samp{.o} files: one, from a @samp{.c} file with the C compiler;\nanother, from a @samp{.p} file with the Pascal compiler; and so on.  The rule\nthat actually applies is the one whose prerequisites exist or can be made.\nSo, if you have a file @file{foo.c}, @code{make} will run the C compiler;\notherwise, if you have a file @file{foo.p}, @code{make} will run the Pascal\ncompiler; and so on.\n\nOf course, when you write the makefile, you know which implicit rule you\nwant @code{make} to use, and you know it will choose that one because you\nknow which possible prerequisite files are supposed to exist.\n@xref{Catalogue of Rules, ,Catalogue of Built-In Rules},\nfor a catalogue of all the predefined implicit rules.\n\nAbove, we said an implicit rule applies if the required prerequisites ``exist\nor can be made''.  A file ``can be made'' if it is mentioned explicitly in\nthe makefile as a target or a prerequisite, or if an implicit rule can be\nrecursively found for how to make it.  When an implicit prerequisite is the\nresult of another implicit rule, we say that @dfn{chaining} is occurring.\n@xref{Chained Rules, ,Chains of Implicit Rules}.\n\nIn general, @code{make} searches for an implicit rule for each target, and\nfor each double-colon rule, that has no recipe.  A file that is mentioned\nonly as a prerequisite is considered a target whose rule specifies nothing,\nso implicit rule search happens for it.  @xref{Implicit Rule Search, ,Implicit Rule Search Algorithm}, for the\ndetails of how the search is done.\n\nNote that explicit prerequisites do not influence implicit rule search.\nFor example, consider this explicit rule:\n\n@example\nfoo.o: foo.p\n@end example\n\n@noindent\nThe prerequisite on @file{foo.p} does not necessarily mean that\n@code{make} will remake @file{foo.o} according to the implicit rule to\nmake an object file, a @file{.o} file, from a Pascal source file, a\n@file{.p} file.  For example, if @file{foo.c} also exists, the implicit\nrule to make an object file from a C source file is used instead,\nbecause it appears before the Pascal rule in the list of predefined\nimplicit rules (@pxref{Catalogue of Rules, , Catalogue of Built-In\nRules}).\n\nIf you do not want an implicit rule to be used for a target that has no\nrecipe, you can give that target an empty recipe by writing a semicolon\n(@pxref{Empty Recipes, ,Defining Empty Recipes}).\n\n@node Catalogue of Rules\n@section Catalogue of Built-In Rules\n@cindex implicit rule, predefined\n@cindex rule, implicit, predefined\n\nHere is a catalogue of predefined implicit rules which are always\navailable unless the makefile explicitly overrides or cancels them.\n@xref{Canceling Rules, ,Canceling Implicit Rules}, for information on\ncanceling or overriding an implicit rule.  The @samp{-r} or\n@samp{--no-builtin-rules} option cancels all predefined rules.\n\nThis manual only documents the default rules available on POSIX-based\noperating systems.  Other operating systems, such as VMS, Windows,\nOS/2, etc. may have different sets of default rules.  To see the full\nlist of default rules and variables available in your version of GNU\n@code{make}, run @samp{make -p} in a directory with no makefile.\n\nNot all of these rules will always be defined, even when the @samp{-r}\noption is not given.  Many of the predefined implicit rules are\nimplemented in @code{make} as suffix rules, so which ones will be\ndefined depends on the @dfn{suffix list} (the list of prerequisites of\nthe special target @code{.SUFFIXES}).  The default suffix list is:\n@code{.out}, @code{.a}, @code{.ln}, @code{.o}, @code{.c}, @code{.cc},\n@code{.C}, @code{.cpp}, @code{.p}, @code{.f}, @code{.F}, @code{.m},\n@code{.r}, @code{.y}, @code{.l}, @code{.ym}, @code{.lm}, @code{.s},\n@code{.S}, @code{.mod}, @code{.sym}, @code{.def}, @code{.h},\n@code{.info}, @code{.dvi}, @code{.tex}, @code{.texinfo}, @code{.texi},\n@code{.txinfo}, @code{.w}, @code{.ch} @code{.web}, @code{.sh},\n@code{.elc}, @code{.el}.  All of the implicit rules described below\nwhose prerequisites have one of these suffixes are actually suffix\nrules.  If you modify the suffix list, the only predefined suffix\nrules in effect will be those named by one or two of the suffixes that\nare on the list you specify; rules whose suffixes fail to be on the\nlist are disabled.  @xref{Suffix Rules, ,Old-Fashioned Suffix Rules},\nfor full details on suffix rules.\n\n@table @asis\n@item Compiling C programs\n@cindex C, rule to compile\n@pindex cc\n@pindex gcc\n@pindex .o\n@pindex .c\n@file{@var{n}.o} is made automatically from @file{@var{n}.c} with\na recipe of the form @w{@samp{$(CC) $(CPPFLAGS) $(CFLAGS) -c}}.\n\n@item Compiling C++ programs\n@cindex C++, rule to compile\n@pindex g++\n@pindex .cc\n@pindex .cpp\n@pindex .C\n@file{@var{n}.o} is made automatically from @file{@var{n}.cc},\n@file{@var{n}.cpp}, or @file{@var{n}.C} with a recipe of the form\n@w{@samp{$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c}}.  We encourage you to use the\nsuffix @samp{.cc} or @samp{.cpp} for C++ source files instead of @samp{.C} to\nbetter support case-insensitive file systems.\n\n@item Compiling Pascal programs\n@cindex Pascal, rule to compile\n@pindex pc\n@pindex .p\n@file{@var{n}.o} is made automatically from @file{@var{n}.p}\nwith the recipe @samp{$(PC) $(PFLAGS) -c}.\n\n@item Compiling Fortran and Ratfor programs\n@cindex Fortran, rule to compile\n@cindex Ratfor, rule to compile\n@pindex f77\n@pindex .f\n@pindex .r\n@pindex .F\n@file{@var{n}.o} is made automatically from @file{@var{n}.r},\n@file{@var{n}.F} or @file{@var{n}.f} by running the\nFortran compiler.  The precise recipe used is as follows:\n\n@table @samp\n@item .f\n@samp{$(FC) $(FFLAGS) -c}.\n@item .F\n@samp{$(FC) $(FFLAGS) $(CPPFLAGS) -c}.\n@item .r\n@samp{$(FC) $(FFLAGS) $(RFLAGS) -c}.\n@end table\n\n@item Preprocessing Fortran and Ratfor programs\n@file{@var{n}.f} is made automatically from @file{@var{n}.r} or\n@file{@var{n}.F}.  This rule runs just the preprocessor to convert a\nRatfor or preprocessable Fortran program into a strict Fortran\nprogram.  The precise recipe used is as follows:\n\n@table @samp\n@item .F\n@samp{$(FC) $(CPPFLAGS) $(FFLAGS) -F}.\n@item .r\n@samp{$(FC) $(FFLAGS) $(RFLAGS) -F}.\n@end table\n\n@item Compiling Modula-2 programs\n@cindex Modula-2, rule to compile\n@pindex m2c\n@pindex .sym\n@pindex .def\n@pindex .mod\n@file{@var{n}.sym} is made from @file{@var{n}.def} with a recipe of the form\n@w{@samp{$(M2C) $(M2FLAGS) $(DEFFLAGS)}}.  @file{@var{n}.o} is made from\n@file{@var{n}.mod}; the form is: @w{@samp{$(M2C) $(M2FLAGS) $(MODFLAGS)}}.\n\n@need 1200\n@item Assembling and preprocessing assembler programs\n@cindex assembly, rule to compile\n@pindex as\n@pindex .s\n@file{@var{n}.o} is made automatically from @file{@var{n}.s} by\nrunning the assembler, @code{as}.  The precise recipe is\n@samp{$(AS) $(ASFLAGS)}.\n\n@pindex .S\n@file{@var{n}.s} is made automatically from @file{@var{n}.S} by\nrunning the C preprocessor, @code{cpp}.  The precise recipe is\n@w{@samp{$(CPP) $(CPPFLAGS)}}.\n\n@item Linking a single object file\n@cindex linking, predefined rule for\n@pindex ld\n@pindex .o\n@file{@var{n}} is made automatically from @file{@var{n}.o} by running the C\ncompiler to link the program.  The precise recipe used is @w{@samp{$(CC)\n$(LDFLAGS) @var{n}.o $(LOADLIBES) $(LDLIBS)}}.\n\nThis rule does the right thing for a simple program with only one\nsource file.  It will also do the right thing if there are multiple\nobject files (presumably coming from various other source files), one\nof which has a name matching that of the executable file.  Thus,\n\n@example\nx: y.o z.o\n@end example\n\n@noindent\nwhen @file{x.c}, @file{y.c} and @file{z.c} all exist will execute:\n\n@example\n@group\ncc -c x.c -o x.o\ncc -c y.c -o y.o\ncc -c z.c -o z.o\ncc x.o y.o z.o -o x\nrm -f x.o\nrm -f y.o\nrm -f z.o\n@end group\n@end example\n\n@noindent\nIn more complicated cases, such as when there is no object file whose\nname derives from the executable file name, you must write an explicit\nrecipe for linking.\n\nEach kind of file automatically made into @samp{.o} object files will\nbe automatically linked by using the compiler (@samp{$(CC)},\n@samp{$(FC)} or @samp{$(PC)}; the C compiler @samp{$(CC)} is used to\nassemble @samp{.s} files) without the @samp{-c} option.  This could be\ndone by using the @samp{.o} object files as intermediates, but it is\nfaster to do the compiling and linking in one step, so that's how it's\ndone.\n\n@item Yacc for C programs\n@pindex yacc\n@cindex Yacc, rule to run\n@pindex .y\n@file{@var{n}.c} is made automatically from @file{@var{n}.y} by\nrunning Yacc with the recipe @samp{$(YACC) $(YFLAGS)}.\n\n@item Lex for C programs\n@pindex lex\n@cindex Lex, rule to run\n@pindex .l\n@file{@var{n}.c} is made automatically from @file{@var{n}.l} by\nrunning Lex.  The actual recipe is @samp{$(LEX) $(LFLAGS)}.\n\n@item Lex for Ratfor programs\n@file{@var{n}.r} is made automatically from @file{@var{n}.l} by\nrunning Lex.  The actual recipe is @samp{$(LEX) $(LFLAGS)}.\n\nThe convention of using the same suffix @samp{.l} for all Lex files\nregardless of whether they produce C code or Ratfor code makes it\nimpossible for @code{make} to determine automatically which of the two\nlanguages you are using in any particular case.  If @code{make} is\ncalled upon to remake an object file from a @samp{.l} file, it must\nguess which compiler to use.  It will guess the C compiler, because\nthat is more common.  If you are using Ratfor, make sure @code{make}\nknows this by mentioning @file{@var{n}.r} in the makefile.  Or, if you\nare using Ratfor exclusively, with no C files, remove @samp{.c} from\nthe list of implicit rule suffixes with:\n\n@example\n@group\n.SUFFIXES:\n.SUFFIXES: .o .r .f .l @dots{}\n@end group\n@end example\n\n@item Making Lint Libraries from C, Yacc, or Lex programs\n@pindex lint\n@cindex @code{lint}, rule to run\n@pindex .ln\n@file{@var{n}.ln} is made from @file{@var{n}.c} by running @code{lint}.\nThe precise recipe is @w{@samp{$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i}}.\nThe same recipe is used on the C code produced from\n@file{@var{n}.y} or @file{@var{n}.l}.\n\n@item @TeX{} and Web\n@cindex @TeX{}, rule to run\n@cindex Web, rule to run\n@pindex tex\n@pindex cweave\n@pindex weave\n@pindex tangle\n@pindex ctangle\n@pindex .dvi\n@pindex .tex\n@pindex .web\n@pindex .w\n@pindex .ch\n@file{@var{n}.dvi} is made from @file{@var{n}.tex} with the recipe\n@samp{$(TEX)}.  @file{@var{n}.tex} is made from @file{@var{n}.web} with\n@samp{$(WEAVE)}, or from @file{@var{n}.w} (and from @file{@var{n}.ch} if\nit exists or can be made) with @samp{$(CWEAVE)}.  @file{@var{n}.p} is\nmade from @file{@var{n}.web} with @samp{$(TANGLE)} and @file{@var{n}.c}\nis made from @file{@var{n}.w} (and from @file{@var{n}.ch} if it exists\nor can be made) with @samp{$(CTANGLE)}.\n\n@item Texinfo and Info\n@cindex Texinfo, rule to format\n@cindex Info, rule to format\n@pindex texi2dvi\n@pindex makeinfo\n@pindex .texinfo\n@pindex .info\n@pindex .texi\n@pindex .txinfo\n@file{@var{n}.dvi} is made from @file{@var{n}.texinfo},\n@file{@var{n}.texi}, or @file{@var{n}.txinfo}, with the recipe\n@w{@samp{$(TEXI2DVI) $(TEXI2DVI_FLAGS)}}.  @file{@var{n}.info} is made from\n@file{@var{n}.texinfo}, @file{@var{n}.texi}, or @file{@var{n}.txinfo}, with\nthe recipe @w{@samp{$(MAKEINFO) $(MAKEINFO_FLAGS)}}.\n\n@item RCS\n@cindex RCS, rule to extract from\n@pindex co\n@pindex ,v @r{(RCS file extension)}\nAny file @file{@var{n}} is extracted if necessary from an RCS file\nnamed either @file{@var{n},v} or @file{RCS/@var{n},v}.  The precise\nrecipe used is @w{@samp{$(CO) $(COFLAGS)}}.  @file{@var{n}} will not be\nextracted from RCS if it already exists, even if the RCS file is\nnewer.  The rules for RCS are terminal\n(@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}),\nso RCS files cannot be generated from another source; they must\nactually exist.\n\n@item SCCS\n@cindex SCCS, rule to extract from\n@pindex get\n@pindex s. @r{(SCCS file prefix)}\nAny file @file{@var{n}} is extracted if necessary from an SCCS file\nnamed either @file{s.@var{n}} or @file{SCCS/s.@var{n}}.  The precise\nrecipe used is @w{@samp{$(GET) $(GFLAGS)}}.  The rules for SCCS are\nterminal (@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}),\nso SCCS files cannot be generated from another source; they must\nactually exist.\n\n@pindex .sh\nFor the benefit of SCCS, a file @file{@var{n}} is copied from\n@file{@var{n}.sh} and made executable (by everyone).  This is for\nshell scripts that are checked into SCCS.  Since RCS preserves the\nexecution permission of a file, you do not need to use this feature\nwith RCS.\n\nWe recommend that you avoid using SCCS.  RCS is widely held to be\nsuperior, and is also free.  By choosing free software in place of\ncomparable (or inferior) proprietary software, you support the free\nsoftware movement.\n@end table\n\nUsually, you want to change only the variables listed in the table\nabove, which are documented in the following section.\n\nHowever, the recipes in built-in implicit rules actually use\nvariables such as @code{COMPILE.c}, @code{LINK.p}, and\n@code{PREPROCESS.S}, whose values contain the recipes listed above.\n\n@code{make} follows the convention that the rule to compile a\n@file{.@var{x}} source file uses the variable @code{COMPILE.@var{x}}.\nSimilarly, the rule to produce an executable from a @file{.@var{x}}\nfile uses @code{LINK.@var{x}}; and the rule to preprocess a\n@file{.@var{x}} file uses @code{PREPROCESS.@var{x}}.\n\n@vindex OUTPUT_OPTION\nEvery rule that produces an object file uses the variable\n@code{OUTPUT_OPTION}.  @code{make} defines this variable either to\ncontain @samp{-o $@@}, or to be empty, depending on a compile-time\noption.  You need the @samp{-o} option to ensure that the output goes\ninto the right file when the source file is in a different directory,\nas when using @code{VPATH} (@pxref{Directory Search}).  However,\ncompilers on some systems do not accept a @samp{-o} switch for object\nfiles.  If you use such a system, and use @code{VPATH}, some\ncompilations will put their output in the wrong place.\nA possible workaround for this problem is to give @code{OUTPUT_OPTION}\nthe value @w{@samp{; mv $*.o $@@}}.\n\n@node Implicit Variables\n@section Variables Used by Implicit Rules\n@cindex flags for compilers\n\nThe recipes in built-in implicit rules make liberal use of certain\npredefined variables.  You can alter the values of these variables in\nthe makefile, with arguments to @code{make}, or in the environment to\nalter how the implicit rules work without redefining the rules\nthemselves.  You can cancel all variables used by implicit rules with\nthe @samp{-R} or @samp{--no-builtin-variables} option.\n\nFor example, the recipe used to compile a C source file actually says\n@samp{$(CC) -c $(CFLAGS) $(CPPFLAGS)}.  The default values of the variables\nused are @samp{cc} and nothing, resulting in the command @samp{cc -c}.  By\nredefining @samp{CC} to @samp{ncc}, you could cause @samp{ncc} to be\nused for all C compilations performed by the implicit rule.  By redefining\n@samp{CFLAGS} to be @samp{-g}, you could pass the @samp{-g} option to\neach compilation.  @emph{All} implicit rules that do C compilation use\n@samp{$(CC)} to get the program name for the compiler and @emph{all}\ninclude @samp{$(CFLAGS)} among the arguments given to the compiler.\n\nThe variables used in implicit rules fall into two classes: those that are\nnames of programs (like @code{CC}) and those that contain arguments for the\nprograms (like @code{CFLAGS}).  (The ``name of a program'' may also contain\nsome command arguments, but it must start with an actual executable program\nname.)  If a variable value contains more than one argument, separate them\nwith spaces.\n\nThe following tables describe some of the more commonly used built-in\nvariables.  This list is not exhaustive, and the default values shown here may\nnot be what @code{make} selects for your environment.  To see the\ncomplete list of predefined variables for your instance of GNU @code{make} you\ncan run @samp{make -p} in a directory with no makefiles.\n\nHere is a table of some of the more common variables used as names of\nprograms in built-in rules:\n\n@table @code\n@item AR\n@vindex AR\nArchive-maintaining program; default @samp{ar}.\n@pindex ar\n\n@item AS\n@vindex AS\nProgram for compiling assembly files; default @samp{as}.\n@pindex as\n\n@item CC\n@vindex CC\nProgram for compiling C programs; default @samp{cc}.\n@pindex cc\n\n@item CXX\n@vindex CXX\nProgram for compiling C++ programs; default @samp{g++}.\n@pindex g++\n\n@item CPP\n@vindex CPP\nProgram for running the C preprocessor, with results to standard output;\ndefault @samp{$(CC) -E}.\n\n@item FC\n@vindex FC\nProgram for compiling or preprocessing Fortran and Ratfor programs;\ndefault @samp{f77}.\n@pindex f77\n\n@item M2C\n@vindex M2C\nProgram to use to compile Modula-2 source code; default @samp{m2c}.\n@pindex m2c\n\n@item PC\n@vindex PC\nProgram for compiling Pascal programs; default @samp{pc}.\n@pindex pc\n\n@item CO\n@vindex CO\nProgram for extracting a file from RCS; default @samp{co}.\n@pindex co\n\n@item GET\n@vindex GET\nProgram for extracting a file from SCCS; default @samp{get}.\n@pindex get\n\n@item LEX\n@vindex LEX\nProgram to use to turn Lex grammars into source code; default @samp{lex}.\n@pindex lex\n\n@item YACC\n@vindex YACC\nProgram to use to turn Yacc grammars into source code; default @samp{yacc}.\n@pindex yacc\n\n@item LINT\n@vindex LINT\nProgram to use to run lint on source code; default @samp{lint}.\n@pindex lint\n\n@item MAKEINFO\n@vindex MAKEINFO\nProgram to convert a Texinfo source file into an Info file; default\n@samp{makeinfo}.\n@pindex makeinfo\n\n@item TEX\n@vindex TEX\nProgram to make @TeX{} @sc{dvi} files from @TeX{} source;\ndefault @samp{tex}.\n@pindex tex\n\n@item TEXI2DVI\n@vindex TEXI2DVI\nProgram to make @TeX{} @sc{dvi} files from Texinfo source;\ndefault @samp{texi2dvi}.\n@pindex texi2dvi\n\n@item WEAVE\n@vindex WEAVE\nProgram to translate Web into @TeX{}; default @samp{weave}.\n@pindex weave\n\n@item CWEAVE\n@vindex CWEAVE\nProgram to translate C Web into @TeX{}; default @samp{cweave}.\n@pindex cweave\n\n@item TANGLE\n@vindex TANGLE\nProgram to translate Web into Pascal; default @samp{tangle}.\n@pindex tangle\n\n@item CTANGLE\n@vindex CTANGLE\nProgram to translate C Web into C; default @samp{ctangle}.\n@pindex ctangle\n\n@item RM\n@vindex RM\nCommand to remove a file; default @samp{rm -f}.\n@pindex rm\n@end table\n\nHere is a table of variables whose values are additional arguments for the\nprograms above.  The default values for all of these is the empty\nstring, unless otherwise noted.\n\n@table @code\n@item ARFLAGS\n@vindex ARFLAGS\nFlags to give the archive-maintaining program; default @samp{rv}.\n\n@item ASFLAGS\n@vindex ASFLAGS\nExtra flags to give to the assembler (when explicitly\ninvoked on a @samp{.s} or @samp{.S} file).\n\n@item CFLAGS\n@vindex CFLAGS\nExtra flags to give to the C compiler.\n\n@item CXXFLAGS\n@vindex CXXFLAGS\nExtra flags to give to the C++ compiler.\n\n@item COFLAGS\n@vindex COFLAGS\nExtra flags to give to the RCS @code{co} program.\n\n@item CPPFLAGS\n@vindex CPPFLAGS\nExtra flags to give to the C preprocessor and programs\nthat use it (the C and Fortran compilers).\n\n@item FFLAGS\n@vindex FFLAGS\nExtra flags to give to the Fortran compiler.\n\n@item GFLAGS\n@vindex GFLAGS\nExtra flags to give to the SCCS @code{get} program.\n\n@item LDFLAGS\n@vindex LDFLAGS\nExtra flags to give to compilers when they are supposed to invoke the linker,\n@samp{ld}, such as @code{-L}.  Libraries (@code{-lfoo}) should be\nadded to the @code{LDLIBS} variable instead.\n\n@item LDLIBS\n@vindex LDLIBS\n@vindex LOADLIBES\nLibrary flags or names given to compilers when they are supposed to\ninvoke the linker, @samp{ld}.  @code{LOADLIBES} is a deprecated (but\nstill supported) alternative to @code{LDLIBS}.  Non-library linker\nflags, such as @code{-L}, should go in the @code{LDFLAGS} variable.\n\n@item LFLAGS\n@vindex LFLAGS\nExtra flags to give to Lex.\n\n@item YFLAGS\n@vindex YFLAGS\nExtra flags to give to Yacc.\n\n@item PFLAGS\n@vindex PFLAGS\nExtra flags to give to the Pascal compiler.\n\n@item RFLAGS\n@vindex RFLAGS\nExtra flags to give to the Fortran compiler for Ratfor programs.\n\n@item LINTFLAGS\n@vindex LINTFLAGS\nExtra flags to give to lint.\n@end table\n\n@node Chained Rules\n@section Chains of Implicit Rules\n\n@cindex chains of rules\n@cindex rule, implicit, chains of\nSometimes a file can be made by a sequence of implicit rules.  For example,\na file @file{@var{n}.o} could be made from @file{@var{n}.y} by running\nfirst Yacc and then @code{cc}.  Such a sequence is called a @dfn{chain}.\n\nIf the file @file{@var{n}.c} exists, or is mentioned in the makefile, no\nspecial searching is required: @code{make} finds that the object file can\nbe made by C compilation from @file{@var{n}.c}; later on, when considering\nhow to make @file{@var{n}.c}, the rule for running Yacc is\nused.  Ultimately both @file{@var{n}.c} and @file{@var{n}.o} are\nupdated.\n\n@cindex intermediate files\n@cindex files, intermediate\nHowever, even if @file{@var{n}.c} does not exist and is not mentioned,\n@code{make} knows how to envision it as the missing link between\n@file{@var{n}.o} and @file{@var{n}.y}!  In this case, @file{@var{n}.c} is\ncalled an @dfn{intermediate file}.  Once @code{make} has decided to use the\nintermediate file, it is entered in the data base as if it had been\nmentioned in the makefile, along with the implicit rule that says how to\ncreate it.\n\nIntermediate files are remade using their rules just like all other\nfiles.  But intermediate files are treated differently in two ways.\n\nThe first difference is what happens if the intermediate file does not\nexist.  If an ordinary file @var{b} does not exist, and @code{make}\nconsiders a target that depends on @var{b}, it invariably creates\n@var{b} and then updates the target from @var{b}.  But if @var{b} is\nan intermediate file, then @code{make} can leave well enough alone:\nit won't create @var{b} unless one of its prerequisites is out of\ndate.  This means the target depending on @var{b} won't be rebuilt\neither, unless there is some other reason to update that target: for\nexample the target doesn't exist or a different prerequisite is newer\nthan the target.\n\nThe second difference is that if @code{make} @emph{does} create @var{b} in\norder to update something else, it deletes @var{b} later on after it is no\nlonger needed.  Therefore, an intermediate file which did not exist before\n@code{make} also does not exist after @code{make}.  @code{make} reports the\ndeletion to you by printing a @samp{rm} command showing which file it is\ndeleting.\n\nYou can explicitly mark a file as intermediate by listing it as a prerequisite\nof the special target @code{.INTERMEDIATE}.  This takes effect even if the\nfile is mentioned explicitly in some other way.\n\nA file cannot be intermediate if it is mentioned in the makefile as a target\nor prerequisite, so one way to avoid the deletion of intermediate files is by\nadding it as a prerequisite to some target.  However, doing so can cause make\nto do extra work when searching pattern rules (@pxref{Implicit Rule Search,\n,Implicit Rule Search Algorithm}).\n\nAs an alternative, listing a file as a prerequisite of the special target\n@code{.NOTINTERMEDIATE} forces it to not be considered intermediate (just as\nany other mention of the file will do).  Also, listing the target pattern of a\npattern rule as a prerequisite of @code{.NOTINTERMEDIATE} ensures that no\ntargets generated using that pattern rule are considered intermediate.\n\nYou can disable intermediate files completely in your makefile by\nproviding @code{.NOTINTERMEDIATE} as a target with no prerequisites:\nin that case it applies to every file in the makefile.\n\n@cindex intermediate files, preserving\n@cindex preserving intermediate files\n@cindex secondary files\nIf you do not want @code{make} to create a file merely because it does\nnot already exist, but you also do not want @code{make} to\nautomatically delete the file, you can mark it as a @dfn{secondary}\nfile.  To do this, list it as a prerequisite of the special target\n@code{.SECONDARY}.  Marking a file as secondary also marks it as\nintermediate.\n\nA chain can involve more than two implicit rules.  For example, it is\npossible to make a file @file{foo} from @file{RCS/foo.y,v} by running RCS,\nYacc and @code{cc}.  Then both @file{foo.y} and @file{foo.c} are\nintermediate files that are deleted at the end.\n\nNo single implicit rule can appear more than once in a chain.  This means\nthat @code{make} will not even consider such a ridiculous thing as making\n@file{foo} from @file{foo.o.o} by running the linker twice.  This\nconstraint has the added benefit of preventing any infinite loop in the\nsearch for an implicit rule chain.\n\nThere are some special implicit rules to optimize certain cases that would\notherwise be handled by rule chains.  For example, making @file{foo} from\n@file{foo.c} could be handled by compiling and linking with separate\nchained rules, using @file{foo.o} as an intermediate file.  But what\nactually happens is that a special rule for this case does the compilation\nand linking with a single @code{cc} command.  The optimized rule is used in\npreference to the step-by-step chain because it comes earlier in the\nordering of rules.\n\nFinally, for performance reasons @code{make} will not consider non-terminal\nmatch-anything rules (i.e., @samp{%:}) when searching for a rule to\nbuild a prerequisite of an implicit rule (@pxref{Match-Anything Rules}).\n\n@node Pattern Rules\n@section Defining and Redefining Pattern Rules\n\nYou define an implicit rule by writing a @dfn{pattern rule}.  A pattern\nrule looks like an ordinary rule, except that its target contains the\ncharacter @samp{%} (exactly one of them).  The target is considered a\npattern for matching file names; the @samp{%} can match any nonempty\nsubstring, while other characters match only themselves.  The prerequisites\nlikewise use @samp{%} to show how their names relate to the target name.\n\nThus, a pattern rule @samp{%.o : %.c ; @var{recipe}} describes a process for\nbuilding any file @file{@var{stem}.o} from another file @file{@var{stem}.c}\nusing the recipe @var{recipe}.\n\nIt is not possible to create a pattern rule that does not have a recipe;\nomitting the recipe removes that pattern rule instead (@pxref{Canceling Rules,\n,Canceling Implicit Rules}).\n\nNote that expansion using @samp{%} in pattern rules occurs\n@strong{after} any variable or function expansions, which take place\nwhen the makefile is read.  @xref{Using Variables, , How to Use\nVariables}, and @ref{Functions, ,Functions for Transforming Text}.\n\n@menu\n* Pattern Intro::               An introduction to pattern rules.\n* Pattern Examples::            Examples of pattern rules.\n* Automatic Variables::         How to use automatic variables in the\n                                  recipe of implicit rules.\n* Pattern Match::               How patterns match.\n* Match-Anything Rules::        Precautions you should take prior to\n                                  defining rules that can match any\n                                  target file whatever.\n* Canceling Rules::             How to override or cancel built-in rules.\n@end menu\n\n@node Pattern Intro\n@subsection Introduction to Pattern Rules\n@cindex pattern rule\n@cindex rule, pattern\n\nA pattern rule contains the character @samp{%} (exactly one of them)\nin the target; otherwise, it looks exactly like an ordinary rule.  The\ntarget is a pattern for matching file names; the @samp{%} matches any\nnonempty substring, while other characters match only themselves.\n@cindex target pattern, implicit\n@cindex @code{%}, in pattern rules\n\nFor example, @samp{%.c} as a pattern matches any file name that ends in\n@samp{.c}.  @samp{s.%.c} as a pattern matches any file name that starts\nwith @samp{s.}, ends in @samp{.c} and is at least five characters long.\n(There must be at least one character to match the @samp{%}.)  The substring\nthat the @samp{%} matches is called the @dfn{stem}.\n\n@samp{%} in a prerequisite of a pattern rule stands for the same stem\nthat was matched by the @samp{%} in the target.  In order for the\npattern rule to apply, its target pattern must match the file name\nunder consideration and all of its prerequisites (after pattern\nsubstitution) must name files that exist or can be made.  These files\nbecome prerequisites of the target.\n@cindex prerequisite pattern, implicit\n\nThus, a rule of the form\n\n@example\n%.o : %.c ; @var{recipe}@dots{}\n@end example\n\n@noindent\nspecifies how to make a file @file{@var{n}.o}, with another file\n@file{@var{n}.c} as its prerequisite, provided that @file{@var{n}.c}\nexists or can be made.\n\nThere may also be prerequisites that do not use @samp{%}; such a prerequisite\nattaches to every file made by this pattern rule.  These unvarying\nprerequisites are useful occasionally.\n\nA pattern rule need not have any prerequisites that contain @samp{%}, or\nin fact any prerequisites at all.  Such a rule is effectively a general\nwildcard.  It provides a way to make any file that matches the target\npattern.  @xref{Last Resort}.\n\nMore than one pattern rule may match a target.  In this case\n@code{make} will choose the ``best fit'' rule.  @xref{Pattern Match,\n,How Patterns Match}.\n\n@cindex multiple targets, in pattern rule\n@cindex target, multiple in pattern rule\nPattern rules may have more than one target; however, every target must\ncontain a @code{%} character.  Multiple target patterns in pattern rules are\nalways treated as grouped targets (@pxref{Multiple Targets, , Multiple Targets\nin a Rule}) regardless of whether they use the @code{:} or @code{&:}\nseparator.\n\nThere is one exception: if a pattern target is out of date or does\nnot exist and the makefile does not need to build it, then it will not cause\nthe other targets to be considered out of date.  Note that this historical\nexception will be removed in future versions of GNU @code{make} and should not\nbe relied on.  If this situation is detected @code{make} will generate a\nwarning @emph{pattern recipe did not update peer target}; however, @code{make}\ncannot detect all such situations.  Please be sure that your recipe updates\n@emph{all} the target patterns when it runs.\n\n@node Pattern Examples\n@subsection Pattern Rule Examples\n\nHere are some examples of pattern rules actually predefined in\n@code{make}.  First, the rule that compiles @samp{.c} files into @samp{.o}\nfiles:\n\n@example\n%.o : %.c\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@\n@end example\n\n@noindent\ndefines a rule that can make any file @file{@var{x}.o} from\n@file{@var{x}.c}.  The recipe uses the automatic variables @samp{$@@} and\n@samp{$<} to substitute the names of the target file and the source file\nin each case where the rule applies (@pxref{Automatic Variables}).\n\nHere is a second built-in rule:\n\n@example\n% :: RCS/%,v\n        $(CO) $(COFLAGS) $<\n@end example\n\n@noindent\ndefines a rule that can make any file @file{@var{x}} whatsoever from a\ncorresponding file @file{@var{x},v} in the sub-directory @file{RCS}.  Since\nthe target is @samp{%}, this rule will apply to any file whatever, provided\nthe appropriate prerequisite file exists.  The double colon makes the rule\n@dfn{terminal}, which means that its prerequisite may not be an intermediate\nfile (@pxref{Match-Anything Rules, ,Match-Anything Pattern Rules}).\n\n@need 500\nThis pattern rule has two targets:\n\n@example\n@group\n%.tab.c %.tab.h: %.y\n        bison -d $<\n@end group\n@end example\n\n@noindent\n@c The following paragraph is rewritten to avoid overfull hboxes\nThis tells @code{make} that the recipe @samp{bison -d @var{x}.y} will\nmake both @file{@var{x}.tab.c} and @file{@var{x}.tab.h}.  If the file\n@file{foo} depends on the files @file{parse.tab.o} and @file{scan.o}\nand the file @file{scan.o} depends on the file @file{parse.tab.h},\nwhen @file{parse.y} is changed, the recipe @samp{bison -d parse.y}\nwill be executed only once, and the prerequisites of both\n@file{parse.tab.o} and @file{scan.o} will be satisfied.  (Presumably\nthe file @file{parse.tab.o} will be recompiled from @file{parse.tab.c}\nand the file @file{scan.o} from @file{scan.c}, while @file{foo} is\nlinked from @file{parse.tab.o}, @file{scan.o}, and its other\nprerequisites, and it will execute happily ever after.)\n\n@node Automatic Variables\n@subsection Automatic Variables\n@cindex automatic variables\n@cindex variables, automatic\n@cindex variables, and implicit rule\n\nSuppose you are writing a pattern rule to compile a @samp{.c} file into a\n@samp{.o} file: how do you write the @samp{cc} command so that it operates\non the right source file name?  You cannot write the name in the recipe,\nbecause the name is different each time the implicit rule is applied.\n\nWhat you do is use a special feature of @code{make}, the @dfn{automatic\nvariables}.  These variables have values computed afresh for each rule that\nis executed, based on the target and prerequisites of the rule.  In this\nexample, you would use @samp{$@@} for the object file name and @samp{$<}\nfor the source file name.\n\n@cindex automatic variables in prerequisites\n@cindex prerequisites, and automatic variables\nIt's very important that you recognize the limited scope in which\nautomatic variable values are available: they only have values within\nthe recipe.  In particular, you cannot use them anywhere\nwithin the target list of a rule; they have no value there and will\nexpand to the empty string.  Also, they cannot be accessed directly\nwithin the prerequisite list of a rule.  A common mistake is\nattempting to use @code{$@@} within the prerequisites list; this will\nnot work.  However, there is a special feature of GNU @code{make},\nsecondary expansion (@pxref{Secondary Expansion}), which will allow\nautomatic variable values to be used in prerequisite lists.\n\nHere is a table of automatic variables:\n\n@table @code\n@vindex $@@\n@vindex @@ @r{(automatic variable)}\n@item $@@\nThe file name of the target of the rule.  If the target is an archive\nmember, then @samp{$@@} is the name of the archive file.  In a pattern\nrule that has multiple targets (@pxref{Pattern Intro, ,Introduction to\nPattern Rules}), @samp{$@@} is the name of whichever target caused the\nrule's recipe to be run.\n\n@vindex $%\n@vindex % @r{(automatic variable)}\n@item $%\nThe target member name, when the target is an archive member.\n@xref{Archives}.  For example, if the target is @file{foo.a(bar.o)} then\n@samp{$%} is @file{bar.o} and @samp{$@@} is @file{foo.a}.  @samp{$%} is\nempty when the target is not an archive member.\n\n@vindex $<\n@vindex < @r{(automatic variable)}\n@item $<\nThe name of the first prerequisite.  If the target got its recipe from\nan implicit rule, this will be the first prerequisite added by the\nimplicit rule (@pxref{Implicit Rules}).\n\n@vindex $?\n@vindex ? @r{(automatic variable)}\n@item $?\nThe names of all the prerequisites that are newer than the target, with\nspaces between them.  If the target does not exist, all prerequisites\nwill be included.  For prerequisites which are archive members, only the\nnamed member is used (@pxref{Archives}).\n\n@samp{$?} is useful even in explicit rules when you wish to operate on only\nthe prerequisites that have changed.  For example, suppose that an archive\nnamed @file{lib} is supposed to contain copies of several object files.\nThis rule copies just the changed object files into the archive:\n\n@example\n@group\nlib: foo.o bar.o lose.o win.o\n        ar r lib $?\n@end group\n@end example\n@cindex prerequisites, list of changed\n@cindex list of changed prerequisites\n\n@vindex $^\n@vindex ^ @r{(automatic variable)}\n@item $^\nThe names of all the prerequisites, with spaces between them.  For\nprerequisites which are archive members, only the named member is used\n(@pxref{Archives}).  A target has only one prerequisite on each other file\nit depends on, no matter how many times each file is listed as a\nprerequisite.  So if you list a prerequisite more than once for a target,\nthe value of @code{$^} contains just one copy of the name.  This list\ndoes @strong{not} contain any of the order-only prerequisites; for those\nsee the @samp{$|} variable, below.\n@cindex prerequisites, list of all\n@cindex list of all prerequisites\n\n@vindex $+\n@vindex + @r{(automatic variable)}\n@item $+\nThis is like @samp{$^}, but prerequisites listed more than once are\nduplicated in the order they were listed in the makefile.  This is\nprimarily useful for use in linking commands where it is meaningful to\nrepeat library file names in a particular order.\n\n@vindex $|\n@vindex | @r{(automatic variable)}\n@item $|\nThe names of all the order-only prerequisites, with spaces between\nthem.\n\n@vindex $*\n@vindex * @r{(automatic variable)}\n@item $*\nThe stem with which an implicit rule matches (@pxref{Pattern Match, ,How\nPatterns Match}).  If the target is @file{dir/a.foo.b} and the target\npattern is @file{a.%.b} then the stem is @file{dir/foo}.  The stem is\nuseful for constructing names of related files.\n@cindex stem, variable for\n\nIn a static pattern rule, the stem is part of the file name that matched\nthe @samp{%} in the target pattern.\n\nIn an explicit rule, there is no stem; so @samp{$*} cannot be determined\nin that way.  Instead, if the target name ends with a recognized suffix\n(@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}), @samp{$*} is set to\nthe target name minus the suffix.  For example, if the target name is\n@samp{foo.c}, then @samp{$*} is set to @samp{foo}, since @samp{.c} is a\nsuffix.  GNU @code{make} does this bizarre thing only for compatibility\nwith other implementations of @code{make}.  You should generally avoid\nusing @samp{$*} except in implicit rules or static pattern rules.\n\nIf the target name in an explicit rule does not end with a recognized\nsuffix, @samp{$*} is set to the empty string for that rule.\n@end table\n\nOf the variables listed above, four have values that are single file\nnames, and three have values that are lists of file names.  These\nseven have variants that get just the file's directory name or just\nthe file name within the directory.  The variant variables' names are\nformed by appending @samp{D} or @samp{F}, respectively.  The functions\n@code{dir} and @code{notdir} can be used to obtain a similar effect\n(@pxref{File Name Functions, , Functions for File Names}).  Note,\nhowever, that the @samp{D} variants all omit the trailing slash which\nalways appears in the output of the @code{dir} function.  Here is a\ntable of the variants:\n\n@table @samp\n@vindex $(@@D)\n@vindex @@D @r{(automatic variable)}\n@item $(@@D)\nThe directory part of the file name of the target, with the trailing\nslash removed.  If the value of @samp{$@@} is @file{dir/foo.o} then\n@samp{$(@@D)} is @file{dir}.  This value is @file{.} if @samp{$@@} does\nnot contain a slash.\n\n@vindex $(@@F)\n@vindex @@F @r{(automatic variable)}\n@item $(@@F)\nThe file-within-directory part of the file name of the target.  If the\nvalue of @samp{$@@} is @file{dir/foo.o} then @samp{$(@@F)} is\n@file{foo.o}.  @samp{$(@@F)} is equivalent to @samp{$(notdir $@@)}.\n\n@vindex $(*D)\n@vindex *D @r{(automatic variable)}\n@item $(*D)\n@vindex $(*F)\n@vindex *F @r{(automatic variable)}\n@itemx $(*F)\nThe directory part and the file-within-directory\npart of the stem; @file{dir} and @file{foo} in this example.\n\n@vindex $(%D)\n@vindex %D @r{(automatic variable)}\n@item $(%D)\n@vindex $(%F)\n@vindex %F @r{(automatic variable)}\n@itemx $(%F)\nThe directory part and the file-within-directory part of the target\narchive member name.  This makes sense only for archive member targets\nof the form @file{@var{archive}(@var{member})} and is useful only when\n@var{member} may contain a directory name.  (@xref{Archive Members,\n,Archive Members as Targets}.)\n\n@vindex $(<D)\n@vindex <D @r{(automatic variable)}\n@item $(<D)\n@vindex $(<F)\n@vindex <F @r{(automatic variable)}\n@itemx $(<F)\nThe directory part and the file-within-directory\npart of the first prerequisite.\n\n@vindex $(^D)\n@vindex ^D @r{(automatic variable)}\n@item $(^D)\n@vindex $(^F)\n@vindex ^F @r{(automatic variable)}\n@itemx $(^F)\nLists of the directory parts and the file-within-directory\nparts of all prerequisites.\n\n@vindex $(+D)\n@vindex +D @r{(automatic variable)}\n@item $(+D)\n@vindex $(+F)\n@vindex +F @r{(automatic variable)}\n@itemx $(+F)\nLists of the directory parts and the file-within-directory\nparts of all prerequisites, including multiple instances of duplicated\nprerequisites.\n\n@vindex $(?D)\n@vindex ?D @r{(automatic variable)}\n@item $(?D)\n@vindex $(?F)\n@vindex ?F @r{(automatic variable)}\n@itemx $(?F)\nLists of the directory parts and the file-within-directory parts of\nall prerequisites that are newer than the target.\n@end table\n\nNote that we use a special stylistic convention when we talk about these\nautomatic variables; we write ``the value of @samp{$<}'', rather than\n@w{``the variable @code{<}''} as we would write for ordinary variables\nsuch as @code{objects} and @code{CFLAGS}.  We think this convention\nlooks more natural in this special case.  Please do not assume it has a\ndeep significance; @samp{$<} refers to the variable named @code{<} just\nas @samp{$(CFLAGS)} refers to the variable named @code{CFLAGS}.\nYou could just as well use @samp{$(<)} in place of @samp{$<}.\n\n@node Pattern Match\n@subsection How Patterns Match\n\n@cindex stem\nA target pattern is composed of a @samp{%} between a prefix and a suffix,\neither or both of which may be empty.  The pattern matches a file name only\nif the file name starts with the prefix and ends with the suffix, without\noverlap.  The text between the prefix and the suffix is called the\n@dfn{stem}.  Thus, when the pattern @samp{%.o} matches the file name\n@file{test.o}, the stem is @samp{test}.  The pattern rule prerequisites are\nturned into actual file names by substituting the stem for the character\n@samp{%}.  Thus, if in the same example one of the prerequisites is written\nas @samp{%.c}, it expands to @samp{test.c}.\n\nWhen the target pattern does not contain a slash (and it usually does\nnot), directory names in the file names are removed from the file name\nbefore it is compared with the target prefix and suffix.  After the\ncomparison of the file name to the target pattern, the directory\nnames, along with the slash that ends them, are added on to the\nprerequisite file names generated from the pattern rule's prerequisite\npatterns and the file name.  The directories are ignored only for the\npurpose of finding an implicit rule to use, not in the application of\nthat rule.  Thus, @samp{e%t} matches the file name @file{src/eat},\nwith @samp{src/a} as the stem.  When prerequisites are turned into file\nnames, the directories from the stem are added at the front, while the\nrest of the stem is substituted for the @samp{%}.  The stem\n@samp{src/a} with a prerequisite pattern @samp{c%r} gives the file name\n@file{src/car}.\n\n@cindex pattern rules, order of\n@cindex order of pattern rules\nA pattern rule can be used to build a given file only if there is a\ntarget pattern that matches the file name, @emph{and} all\nprerequisites in that rule either exist or can be built.  The rules\nyou write take precedence over those that are built in. Note however,\nthat a rule which can be satisfied without chaining other implicit\nrules (for example, one which has no prerequisites or its\nprerequisites already exist or are mentioned) always takes priority\nover a rule with prerequisites that must be made by chaining other\nimplicit rules.\n\n@cindex stem, shortest\nIt is possible that more than one pattern rule will meet these\ncriteria.  In that case, @code{make} will choose the rule with the\nshortest stem (that is, the pattern that matches most specifically).\nIf more than one pattern rule has the shortest stem, @code{make} will\nchoose the first one found in the makefile.\n\nThis algorithm results in more specific rules being preferred over\nmore generic ones; for example:\n\n@example\n%.o: %.c\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@@\n\n%.o : %.f\n        $(COMPILE.F) $(OUTPUT_OPTION) $<\n\nlib/%.o: lib/%.c\n        $(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@@\n@end example\n\nGiven these rules and asked to build @file{bar.o} where both\n@file{bar.c} and @file{bar.f} exist, @code{make} will choose the first\nrule and compile @file{bar.c} into @file{bar.o}.  In the same\nsituation where @file{bar.c} does not exist, then @code{make} will\nchoose the second rule and compile @file{bar.f} into @file{bar.o}.\n\nIf @code{make} is asked to build @file{lib/bar.o} and both\n@file{lib/bar.c} and @file{lib/bar.f} exist, then the third rule will\nbe chosen since the stem for this rule (@samp{bar}) is shorter than\nthe stem for the first rule (@samp{lib/bar}).  If @file{lib/bar.c}\ndoes not exist then the third rule is not eligible and the second rule\nwill be used, even though the stem is longer.\n\n@node Match-Anything Rules\n@subsection Match-Anything Pattern Rules\n\n@cindex match-anything rule\n@cindex terminal rule\nWhen a pattern rule's target is just @samp{%}, it matches any file name\nwhatever.  We call these rules @dfn{match-anything} rules.  They are very\nuseful, but it can take a lot of time for @code{make} to think about them,\nbecause it must consider every such rule for each file name listed either\nas a target or as a prerequisite.\n\nSuppose the makefile mentions @file{foo.c}.  For this target, @code{make}\nwould have to consider making it by linking an object file @file{foo.c.o},\nor by C compilation-and-linking in one step from @file{foo.c.c}, or by\nPascal compilation-and-linking from @file{foo.c.p}, and many other\npossibilities.\n\nWe know these possibilities are ridiculous since @file{foo.c} is a C source\nfile, not an executable.  If @code{make} did consider these possibilities,\nit would ultimately reject them, because files such as @file{foo.c.o} and\n@file{foo.c.p} would not exist.  But these possibilities are so\nnumerous that @code{make} would run very slowly if it had to consider\nthem.\n\nTo gain speed, we have put various constraints on the way @code{make}\nconsiders match-anything rules.  There are two different constraints that\ncan be applied, and each time you define a match-anything rule you must\nchoose one or the other for that rule.\n\nOne choice is to mark the match-anything rule as @dfn{terminal} by defining\nit with a double colon.  When a rule is terminal, it does not apply unless\nits prerequisites actually exist.  Prerequisites that could be made with\nother implicit rules are not good enough.  In other words, no further\nchaining is allowed beyond a terminal rule.\n\nFor example, the built-in implicit rules for extracting sources from RCS\nand SCCS files are terminal; as a result, if the file @file{foo.c,v} does\nnot exist, @code{make} will not even consider trying to make it as an\nintermediate file from @file{foo.c,v.o} or from @file{RCS/SCCS/s.foo.c,v}.\nRCS and SCCS files are generally ultimate source files, which should not be\nremade from any other files; therefore, @code{make} can save time by not\nlooking for ways to remake them.\n\nIf you do not mark the match-anything rule as terminal, then it is\nnon-terminal.  A non-terminal match-anything rule cannot apply to a\nprerequisite of an implicit rule, or to a file name that indicates a\nspecific type of data.  A file name indicates a specific type of data\nif some non-match-anything implicit rule target matches it.\n\nFor example, the file name @file{foo.c} matches the target for the pattern\nrule @samp{%.c : %.y} (the rule to run Yacc).  Regardless of whether this\nrule is actually applicable (which happens only if there is a file\n@file{foo.y}), the fact that its target matches is enough to prevent\nconsideration of any non-terminal match-anything rules for the file\n@file{foo.c}.  Thus, @code{make} will not even consider trying to make\n@file{foo.c} as an executable file from @file{foo.c.o}, @file{foo.c.c},\n@file{foo.c.p}, etc.\n\nThe motivation for this constraint is that non-terminal match-anything\nrules are used for making files containing specific types of data (such as\nexecutable files) and a file name with a recognized suffix indicates some\nother specific type of data (such as a C source file).\n\nSpecial built-in dummy pattern rules are provided solely to recognize\ncertain file names so that non-terminal match-anything rules will not be\nconsidered.  These dummy rules have no prerequisites and no recipes, and\nthey are ignored for all other purposes.  For example, the built-in\nimplicit rule\n\n@example\n%.p :\n@end example\n\n@noindent\nexists to make sure that Pascal source files such as @file{foo.p} match a\nspecific target pattern and thereby prevent time from being wasted looking\nfor @file{foo.p.o} or @file{foo.p.c}.\n\nDummy pattern rules such as the one for @samp{%.p} are made for every\nsuffix listed as valid for use in suffix rules (@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}).\n\n@node Canceling Rules\n@subsection Canceling Implicit Rules\n\nYou can override a built-in implicit rule (or one you have defined\nyourself) by defining a new pattern rule with the same target and\nprerequisites, but a different recipe.  When the new rule is defined, the\nbuilt-in one is replaced.  The new rule's position in the sequence of\nimplicit rules is determined by where you write the new rule.\n\nYou can cancel a built-in implicit rule by defining a pattern rule with the\nsame target and prerequisites, but no recipe.  For example, the following\nwould cancel the rule that runs the assembler:\n\n@example\n%.o : %.s\n@end example\n\n@node Last Resort\n@section Defining Last-Resort Default Rules\n@cindex last-resort default rules\n@cindex default rules, last-resort\n\nYou can define a last-resort implicit rule by writing a terminal\nmatch-anything pattern rule with no prerequisites (@pxref{Match-Anything\nRules}).  This is just like any other pattern rule; the only thing\nspecial about it is that it will match any target.  So such a rule's\nrecipe is used for all targets and prerequisites that have no recipe\nof their own and for which no other implicit rule applies.\n\nFor example, when testing a makefile, you might not care if the source\nfiles contain real data, only that they exist.  Then you might do this:\n\n@example\n%::\n        touch $@@\n@end example\n\n@noindent\nto cause all the source files needed (as prerequisites) to be created\nautomatically.\n\n@findex .DEFAULT\nYou can instead define a recipe to be used for targets for which there\nare no rules at all, even ones which don't specify recipes.  You do\nthis by writing a rule for the target @code{.DEFAULT}.  Such a rule's\nrecipe is used for all prerequisites which do not appear as targets in\nany explicit rule, and for which no implicit rule applies.  Naturally,\nthere is no @code{.DEFAULT} rule unless you write one.\n\nIf you use @code{.DEFAULT} with no recipe or prerequisites:\n\n@example\n.DEFAULT:\n@end example\n\n@noindent\nthe recipe previously stored for @code{.DEFAULT} is cleared.  Then\n@code{make} acts as if you had never defined @code{.DEFAULT} at all.\n\nIf you do not want a target to get the recipe from a match-anything\npattern rule or @code{.DEFAULT}, but you also do not want any recipe\nto be run for the target, you can give it an empty recipe\n(@pxref{Empty Recipes, ,Defining Empty Recipes}).\n\nYou can use a last-resort rule to override part of another makefile.\n@xref{Overriding Makefiles, , Overriding Part of Another Makefile}.\n\n@node Suffix Rules\n@section Old-Fashioned Suffix Rules\n@cindex old-fashioned suffix rules\n@cindex suffix rule\n@cindex inference rule\n\n@dfn{Suffix rules} (called @dfn{inference rules} in POSIX) are an\nold-fashioned way of defining implicit rules for @code{make}.  Suffix rules\nare less powerful and harder to use than pattern rules (@pxref{Pattern Rules,\n,Defining and Redefining Pattern Rules}); they are supported by GNU Make\nprimarily for POSIX compatibility.  They come in two flavors:\n@dfn{single-suffix} and @dfn{double-suffix}.\n\nA single-suffix rule is defined by a single suffix, which is the source\nsuffix.  It matches any file name, and the corresponding implicit prerequisite\nname is made by appending the source suffix.  A single-suffix rule whose\nsource suffix is @samp{.c} is equivalent to the pattern rule @samp{% : %.c}.\n\nA double-suffix rule is defined by a pair of suffixes: the source suffix and\nthe target suffix.  It matches any file whose name ends with the target\nsuffix.  The corresponding implicit prerequisite is made by replacing the\ntarget suffix with the source suffix in the file name.  A two-suffix rule\n@samp{.c.o} has a source suffix @samp{.c} and a target suffix @samp{.o}, and\nis equivalent to the pattern rule @samp{%.o : %.c}.\n\nSuffix rule definitions are recognized by comparing each rule's target\nagainst a defined list of known suffixes.  When @code{make} sees a rule\nwhose target is a known suffix, this rule is considered a single-suffix\nrule.  When @code{make} sees a rule whose target is two known suffixes\nconcatenated, this rule is taken as a double-suffix rule.\n\nFor example, @samp{.c} and @samp{.o} are both on the default list of\nknown suffixes.  Therefore, if you define a rule whose target is\n@samp{.c.o}, @code{make} takes it to be a double-suffix rule with source\nsuffix @samp{.c} and target suffix @samp{.o}.  Here is the old-fashioned\nway to define the rule for compiling a C source file:\n\n@example\n.c.o:\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<\n@end example\n\nSuffix rules cannot have any prerequisites of their own.  If they have any,\nthey are treated as normal files with funny names, not as suffix rules.\nThus, the rule:\n\n@example\n.c.o: foo.h\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<\n@end example\n\n@noindent\ntells how to make the file @file{.c.o} from the prerequisite file\n@file{foo.h}, and is not at all like the pattern rule:\n\n@example\n%.o: %.c foo.h\n        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@@ $<\n@end example\n\n@noindent\nwhich tells how to make @samp{.o} files from @samp{.c} files, and makes all\n@samp{.o} files using this pattern rule also depend on @file{foo.h}.\n\nSuffix rules with no recipe are also meaningless.  They do not remove\nprevious rules as do pattern rules with no recipe (@pxref{Canceling\nRules, , Canceling Implicit Rules}).  They simply enter the suffix or\npair of suffixes concatenated as a target in the data base.\n\nThe known suffixes are simply the names of the prerequisites of the special\ntarget @code{.SUFFIXES}.  You can add your own suffixes by writing a rule\nfor @code{.SUFFIXES} that adds more prerequisites, as in:\n\n@example\n.SUFFIXES: .hack .win\n@end example\n\n@noindent\nwhich adds @samp{.hack} and @samp{.win} to the end of the list of suffixes.\n\nIf you wish to eliminate the default known suffixes instead of just adding\nto them, write a rule for @code{.SUFFIXES} with no prerequisites.  By\nspecial dispensation, this eliminates all existing prerequisites of\n@code{.SUFFIXES}.  You can then write another rule to add the suffixes you\nwant.  For example,\n\n@example\n@group\n.SUFFIXES:            # @r{Delete the default suffixes}\n.SUFFIXES: .c .o .h   # @r{Define our suffix list}\n@end group\n@end example\n\nThe @samp{-r} or @samp{--no-builtin-rules} flag causes the default\nlist of suffixes to be empty.\n\n@vindex SUFFIXES\nThe variable @code{SUFFIXES} is defined to the default list of suffixes\nbefore @code{make} reads any makefiles.  You can change the list of suffixes\nwith a rule for the special target @code{.SUFFIXES}, but that does not alter\nthis variable.\n\n@node Implicit Rule Search\n@section Implicit Rule Search Algorithm\n@cindex implicit rule, search algorithm\n@cindex search algorithm, implicit rule\n\nHere is the procedure @code{make} uses for searching for an implicit rule\nfor a target @var{t}.  This procedure is followed for each double-colon\nrule with no recipe, for each target of ordinary rules none of which have\na recipe, and for each prerequisite that is not the target of any rule.  It\nis also followed recursively for prerequisites that come from implicit\nrules, in the search for a chain of rules.\n\nSuffix rules are not mentioned in this algorithm because suffix rules are\nconverted to equivalent pattern rules once the makefiles have been read in.\n\nFor an archive member target of the form\n@samp{@var{archive}(@var{member})}, the following algorithm is run\ntwice, first using the entire target name @var{t}, and second using\n@samp{(@var{member})} as the target @var{t} if the first run found no\nrule.\n\n@enumerate\n@item\nSplit @var{t} into a directory part, called @var{d}, and the rest,\ncalled @var{n}.  For example, if @var{t} is @samp{src/foo.o}, then\n@var{d} is @samp{src/} and @var{n} is @samp{foo.o}.\n\n@item\nMake a list of all the pattern rules one of whose targets matches\n@var{t} or @var{n}.  If the target pattern contains a slash, it is\nmatched against @var{t}; otherwise, against @var{n}.\n\n@item\nIf any rule in that list is @emph{not} a match-anything rule, or if\n@var{t} is a prerequisite of an implicit rule, then remove all\nnon-terminal match-anything rules from the list.\n\n@item\nRemove from the list all rules with no recipe.\n\n@item\nFor each pattern rule in the list:\n\n@enumerate a\n@item\nFind the stem @var{s}, which is the nonempty part of @var{t} or @var{n}\nmatched by the @samp{%} in the target pattern.\n\n@item\nCompute the prerequisite names by substituting @var{s} for @samp{%}; if\nthe target pattern does not contain a slash, append @var{d} to\nthe front of each prerequisite name.\n\n@item\nTest whether all the prerequisites exist or ought to exist.  (If a\nfile name is mentioned in the makefile as a target or as an explicit\nprerequisite of target T, then we say it ought to exist.)\n\nIf all prerequisites exist or ought to exist, or there are no prerequisites,\nthen this rule applies.\n@end enumerate\n\n@item\nIf no pattern rule has been found so far, try harder.\nFor each pattern rule in the list:\n\n@enumerate a\n@item\nIf the rule is terminal, ignore it and go on to the next rule.\n\n@item\nCompute the prerequisite names as before.\n\n@item\nTest whether all the prerequisites exist or ought to exist.\n\n@item\nFor each prerequisite that does not exist, follow this algorithm\nrecursively to see if the prerequisite can be made by an implicit\nrule.\n\n@item\nIf all prerequisites exist, ought to exist, or can be\nmade by implicit rules, then this rule applies.\n@end enumerate\n\n@item\nIf no pattern rule has been found then try step 5 and step 6 again with a\nmodified definition of ``ought to exist'': if a filename is mentioned as a\ntarget or as an explicit prerequisite of @emph{any} target, then it ought to\nexist.  This check is only present for backward-compatibility with older\nversions of GNU Make: we don't recommend relying on it.\n\n@item\nIf no implicit rule applies, the rule for @code{.DEFAULT}, if any,\napplies.  In that case, give @var{t} the same recipe that\n@code{.DEFAULT} has.  Otherwise, there is no recipe for @var{t}.\n@end enumerate\n\nOnce a rule that applies has been found, for each target pattern of the rule\nother than the one that matched @var{t} or @var{n}, the @samp{%} in the\npattern is replaced with @var{s} and the resultant file name is stored until\nthe recipe to remake the target file @var{t} is executed.  After the recipe is\nexecuted each of these stored file names is entered into the data base, marked\nas having been updated, and given the same update status as the file @var{t}.\n\nWhen the recipe of a pattern rule is executed for @var{t}, the\nautomatic variables are set corresponding to the target and\nprerequisites.  @xref{Automatic Variables}.\n\n@node Archives\n@chapter Using @code{make} to Update Archive Files\n@cindex archive\n\n@dfn{Archive files} are files containing named sub-files called\n@dfn{members}; they are maintained with the program @code{ar} and their\nmain use is as subroutine libraries for linking.\n\n@menu\n* Archive Members::             Archive members as targets.\n* Archive Update::              The implicit rule for archive member targets.\n* Archive Pitfalls::            Dangers to watch out for when using archives.\n* Archive Suffix Rules::        You can write a special kind of suffix rule\n                                  for updating archives.\n@end menu\n\n@node Archive Members\n@section Archive Members as Targets\n@cindex archive member targets\n\nAn individual member of an archive file can be used as a target or\nprerequisite in @code{make}.  You specify the member named @var{member} in\narchive file @var{archive} as follows:\n\n@example\n@var{archive}(@var{member})\n@end example\n\n@noindent\nThis construct is available only in targets and prerequisites, not in\nrecipes!  Most programs that you might use in recipes do not support\nthis syntax and cannot act directly on archive members.  Only\n@code{ar} and other programs specifically designed to operate on\narchives can do so.  Therefore, valid recipes to update an archive\nmember target probably must use @code{ar}.  For example, this rule\nsays to create a member @file{hack.o} in archive @file{foolib} by\ncopying the file @file{hack.o}:\n\n@example\nfoolib(hack.o) : hack.o\n        ar cr foolib hack.o\n@end example\n\nIn fact, nearly all archive member targets are updated in just this way\nand there is an implicit rule to do it for you.  @strong{Please note:} The\n@samp{c} flag to @code{ar} is required if the archive file does not\nalready exist.\n\nTo specify several members in the same archive, you can write all the\nmember names together between the parentheses.  For example:\n\n@example\nfoolib(hack.o kludge.o)\n@end example\n\n@noindent\nis equivalent to:\n\n@example\nfoolib(hack.o) foolib(kludge.o)\n@end example\n\n@cindex wildcard, in archive member\nYou can also use shell-style wildcards in an archive member reference.\n@xref{Wildcards, ,Using Wildcard Characters in File Names}.  For\nexample, @w{@samp{foolib(*.o)}} expands to all existing members of the\n@file{foolib} archive whose names end in @samp{.o}; perhaps\n@samp{@w{foolib(hack.o)} @w{foolib(kludge.o)}}.\n\n@node Archive Update\n@section Implicit Rule for Archive Member Targets\n\nRecall that a target that looks like @file{@var{a}(@var{m})} stands for the\nmember named @var{m} in the archive file @var{a}.\n\nWhen @code{make} looks for an implicit rule for such a target, as a special\nfeature it considers implicit rules that match @file{(@var{m})}, as well as\nthose that match the actual target @file{@var{a}(@var{m})}.\n\nThis causes one special rule whose target is @file{(%)} to match.  This\nrule updates the target @file{@var{a}(@var{m})} by copying the file @var{m}\ninto the archive.  For example, it will update the archive member target\n@file{foo.a(bar.o)} by copying the @emph{file} @file{bar.o} into the\narchive @file{foo.a} as a @emph{member} named @file{bar.o}.\n\nWhen this rule is chained with others, the result is very powerful.\nThus, @samp{make \"foo.a(bar.o)\"} (the quotes are needed to protect the\n@samp{(} and @samp{)} from being interpreted specially by the shell) in\nthe presence of a file @file{bar.c} is enough to cause the following\nrecipe to be run, even without a makefile:\n\n@example\ncc -c bar.c -o bar.o\nar r foo.a bar.o\nrm -f bar.o\n@end example\n\n@noindent\nHere @code{make} has envisioned the file @file{bar.o} as an intermediate\nfile.  @xref{Chained Rules, ,Chains of Implicit Rules}.\n\nImplicit rules such as this one are written using the automatic variable\n@samp{$%}.  @xref{Automatic Variables}.\n\nAn archive member name in an archive cannot contain a directory name, but\nit may be useful in a makefile to pretend that it does.  If you write an\narchive member target @file{foo.a(dir/file.o)}, @code{make} will perform\nautomatic updating with this recipe:\n\n@example\nar r foo.a dir/file.o\n@end example\n\n@noindent\nwhich has the effect of copying the file @file{dir/file.o} into a member\nnamed @file{file.o}.  In connection with such usage, the automatic variables\n@code{%D} and @code{%F} may be useful.\n\n@menu\n* Archive Symbols::             How to update archive symbol directories.\n@end menu\n\n@node Archive Symbols\n@subsection Updating Archive Symbol Directories\n@cindex @code{__.SYMDEF}\n@cindex updating archive symbol directories\n@cindex archive symbol directory updating\n@cindex symbol directories, updating archive\n@cindex directories, updating archive symbol\n\nAn archive file that is used as a library usually contains a special member\nnamed @file{__.SYMDEF} that contains a directory of the external symbol\nnames defined by all the other members.  After you update any other\nmembers, you need to update @file{__.SYMDEF} so that it will summarize the\nother members properly.  This is done by running the @code{ranlib} program:\n\n@example\nranlib @var{archivefile}\n@end example\n\nNormally you would put this command in the rule for the archive file,\nand make all the members of the archive file prerequisites of that rule.\nFor example,\n\n@example\nlibfoo.a: libfoo.a(x.o y.o @dots{})\n        ranlib libfoo.a\n@end example\n\n@noindent\nThe effect of this is to update archive members @file{x.o}, @file{y.o},\netc., and then update the symbol directory member @file{__.SYMDEF} by\nrunning @code{ranlib}.  The rules for updating the members are not shown\nhere; most likely you can omit them and use the implicit rule which copies\nfiles into the archive, as described in the preceding section.\n\nThis is not necessary when using the GNU @code{ar} program, which\nupdates the @file{__.SYMDEF} member automatically.\n\n@node Archive Pitfalls\n@section Dangers When Using Archives\n@cindex archive, and parallel execution\n@cindex parallel execution, and archive update\n@cindex archive, and @code{-j}\n@cindex @code{-j}, and archive update\n\nThe built-in rules for updating archives are incompatible with parallel\nbuilds.  These rules (required by the POSIX standard) add each object file\ninto the archive as it's compiled.  When parallel builds are enabled this\nallows multiple @code{ar} commands to be updating the same archive\nsimultaneously, which is not supported.\n\nIf you want to use parallel builds with archives you can override the default\nrules by adding these lines to your makefile:\n\n@example\n(%) : % ;\n%.a : ; $(AR) $(ARFLAGS) $@@ $?\n@end example\n\nThe first line changes the rule that updates an individual object in the\narchive to do nothing, and the second line changes the default rule for\nbuilding an archive to update all the outdated objects (@code{$?}) in one\ncommand.\n\nOf course you will still need to declare the prerequisites of your library\nusing the archive syntax:\n\n@example\nlibfoo.a: libfoo.a(x.o y.o @dots{})\n@end example\n\nIf you prefer to write an explicit rule you can use:\n\n@example\nlibfoo.a: libfoo.a(x.o y.o @dots{})\n        $(AR) $(ARFLAGS) $@@ $?\n@end example\n\n@node Archive Suffix Rules\n@section Suffix Rules for Archive Files\n@cindex suffix rule, for archive\n@cindex archive, suffix rule for\n@cindex library archive, suffix rule for\n@cindex @code{.a} (archives)\n\nYou can write a special kind of suffix rule for dealing with archive\nfiles.  @xref{Suffix Rules}, for a full explanation of suffix rules.\nArchive suffix rules are obsolete in GNU @code{make}, because pattern\nrules for archives are a more general mechanism (@pxref{Archive\nUpdate}).  But they are retained for compatibility with other\n@code{make}s.\n\nTo write a suffix rule for archives, you simply write a suffix rule\nusing the target suffix @samp{.a} (the usual suffix for archive files).\nFor example, here is the old-fashioned suffix rule to update a library\narchive from C source files:\n\n@example\n@group\n.c.a:\n        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o\n        $(AR) r $@@ $*.o\n        $(RM) $*.o\n@end group\n@end example\n\n@noindent\nThis works just as if you had written the pattern rule:\n\n@example\n@group\n(%.o): %.c\n        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o\n        $(AR) r $@@ $*.o\n        $(RM) $*.o\n@end group\n@end example\n\nIn fact, this is just what @code{make} does when it sees a suffix rule\nwith @samp{.a} as the target suffix.  Any double-suffix rule\n@w{@samp{.@var{x}.a}} is converted to a pattern rule with the target\npattern @samp{(%.o)} and a prerequisite pattern of @samp{%.@var{x}}.\n\nSince you might want to use @samp{.a} as the suffix for some other kind\nof file, @code{make} also converts archive suffix rules to pattern rules\nin the normal way (@pxref{Suffix Rules}).  Thus a double-suffix rule\n@w{@samp{.@var{x}.a}} produces two pattern rules: @samp{@w{(%.o):}\n@w{%.@var{x}}} and @samp{@w{%.a}: @w{%.@var{x}}}.\n\n@node Extending make\n@chapter Extending GNU @code{make}\n@cindex make extensions\n\nGNU @code{make} provides many advanced capabilities, including many\nuseful functions.  However, it does not contain a complete programming\nlanguage and so it has limitations.  Sometimes these limitations can be\novercome through use of the @code{shell} function to invoke a separate\nprogram, although this can be inefficient.\n\nIn cases where the built-in capabilities of GNU @code{make} are\ninsufficient to your requirements there are two options for extending\n@code{make}.  On systems where it's provided, you can utilize GNU\nGuile as an embedded scripting language (@pxref{Guile Integration,,GNU\nGuile Integration}).  On systems which support dynamically loadable\nobjects, you can write your own extension in any language (which can\nbe compiled into such an object) and load it to provide extended\ncapabilities (@pxref{load Directive, ,The @code{load} Directive}).\n\n@menu\n* Guile Integration::           Using Guile as an embedded scripting language.\n* Loading Objects::             Loading dynamic objects as extensions.\n@end menu\n\n@node Guile Integration\n@section GNU Guile Integration\n@cindex Guile\n@cindex extensions, Guile\n\nGNU @code{make} may be built with support for GNU Guile as an embedded\nextension language.  Guile implements the Scheme language.  A review\nof GNU Guile and the Scheme language and its features is beyond the\nscope of this manual: see the documentation for GNU Guile and Scheme.\n\nYou can determine if @code{make} contains support for Guile by\nexamining the @code{.FEATURES} variable; it will contain the word\n@var{guile} if Guile support is available.\n\nThe Guile integration provides one new @code{make} function: @code{guile}.\nThe @code{guile} function takes one argument which is first expanded\nby @code{make} in the normal fashion, then passed to the GNU Guile\nevaluator.  The result of the evaluator is converted into a string and\nused as the expansion of the @code{guile} function in the makefile.\n\nIn addition, GNU @code{make} exposes Guile procedures for use in Guile\nscripts.\n\n@menu\n* Guile Types::                 Converting Guile types to @code{make} strings.\n* Guile Interface::             Invoking @code{make} functions from Guile.\n* Guile Example::               Example using Guile in @code{make}.\n@end menu\n\n@node Guile Types\n@subsection Conversion of Guile Types\n@cindex convert guile types\n@cindex guile, conversion of types\n@cindex types, conversion of\n\nThere is only one ``data type'' in @code{make}: a string.  GNU Guile,\non the other hand, provides a rich variety of different data types.\nAn important aspect of the interface between @code{make} and GNU Guile\nis the conversion of Guile data types into @code{make} strings.\n\nThis conversion is relevant in two places: when a makefile invokes the\n@code{guile} function to evaluate a Guile expression, the result of\nthat evaluation must be converted into a make string so it can be\nfurther evaluated by @code{make}.  And secondly, when a Guile script\ninvokes one of the procedures exported by @code{make} the argument\nprovided to the procedure must be converted into a string.\n\nThe conversion of Guile types into @code{make} strings is as below:\n\n@table @code\n@item #f\nFalse is converted into the empty string: in @code{make} conditionals\nthe empty string is considered false.\n\n@item #t\nTrue is converted to the string @samp{#t}: in @code{make} conditionals\nany non-empty string is considered true.\n\n@item symbol\n@item number\nA symbol or number is converted into the string representation of that\nsymbol or number.\n\n@item character\nA printable character is converted to the same character.\n\n@item string\nA string containing only printable characters is converted to the same\nstring.\n\n@item list\nA list is converted recursively according to the above rules.  This\nimplies that any structured list will be flattened (that is, a result\nof @samp{'(a b (c d) e)} will be converted to the @code{make} string\n@samp{a b c d e}).\n\n@item other\nAny other Guile type results in an error.  In future versions of\n@code{make}, other Guile types may be converted.\n\n@end table\n\nThe translation of @samp{#f} (to the empty string) and @samp{#t} (to\nthe non-empty string @samp{#t}) is designed to allow you to use Guile\nboolean results directly as @code{make} boolean conditions.  For\nexample:\n\n@example\n$(if $(guile (access? \"myfile\" R_OK)),$(info myfile exists))\n@end example\n\nAs a consequence of these conversion rules you must consider the\nresult of your Guile script, as that result will be converted into a\nstring and parsed by @code{make}.  If there is no natural result for\nthe script (that is, the script exists solely for its side-effects),\nyou should add @samp{#f} as the final expression in order to avoid\nsyntax errors in your makefile.\n\n@node Guile Interface\n@subsection Interfaces from Guile to @code{make}\n@cindex make interface to guile\n@cindex make procedures in guile\n\nIn addition to the @code{guile} function available in makefiles,\n@code{make} exposes some procedures for use in your Guile scripts.  At\nstartup @code{make} creates a new Guile module, @code{gnu make}, and\nexports these procedures as public interfaces from that module:\n\n@table @code\n@item gmk-expand\n@findex gmk-expand\nThis procedure takes a single argument which is converted into a\nstring.  The string is expanded by @code{make} using normal\n@code{make} expansion rules.  The result of the expansion is converted\ninto a Guile string and provided as the result of the procedure.\n\n@item gmk-eval\n@findex gmk-eval\nThis procedure takes a single argument which is converted into a\nstring.  The string is evaluated by @code{make} as if it were a\nmakefile.  This is the same capability available via the @code{eval}\nfunction (@pxref{Eval Function}).  The result of the @code{gmk-eval}\nprocedure is always the empty string.\n\nNote that @code{gmk-eval} is not quite the same as using\n@code{gmk-expand} with the @code{eval} function: in the latter case\nthe evaluated string will be expanded @emph{twice}; first by\n@code{gmk-expand}, then again by the @code{eval} function.\n\n@end table\n\n@node Guile Example\n@subsection Example Using Guile in @code{make}\n@cindex Guile example\n@cindex example using Guile\n\nHere is a very simple example using GNU Guile to manage writing to a\nfile.  These Guile procedures simply open a file, allow writing to the\nfile (one string per line), and close the file.  Note that because we\ncannot store complex values such as Guile ports in @code{make}\nvariables, we'll keep the port as a global variable in the Guile\ninterpreter.\n\nYou can create Guile functions easily using @code{define}/@code{endef}\nto create a Guile script, then use the @code{guile} function to\ninternalize it:\n\n@example\n@group\ndefine GUILEIO\n;; A simple Guile IO library for GNU Make\n\n(define MKPORT #f)\n\n(define (mkopen name mode)\n  (set! MKPORT (open-file name mode))\n  #f)\n\n(define (mkwrite s)\n  (display s MKPORT)\n  (newline MKPORT)\n  #f)\n\n(define (mkclose)\n  (close-port MKPORT)\n  #f)\n\n#f\nendef\n\n# Internalize the Guile IO functions\n$(guile $(GUILEIO))\n@end group\n@end example\n\nIf you have a significant amount of Guile support code, you might\nconsider keeping it in a different file (e.g., @file{guileio.scm}) and\nthen loading it in your makefile using the @code{guile} function:\n\n@example\n$(guile (load \"guileio.scm\"))\n@end example\n\nAn advantage to this method is that when editing @file{guileio.scm},\nyour editor will understand that this file contains Scheme syntax\nrather than makefile syntax.\n\nNow you can use these Guile functions to create files.  Suppose you\nneed to operate on a very large list, which cannot fit on the command\nline, but the utility you're using accepts the list as input as well:\n\n@example\n@group\nprog: $(PREREQS)\n        @@$(guile (mkopen \"tmp.out\" \"w\")) \\\n         $(foreach X,$^,$(guile (mkwrite \"$(X)\"))) \\\n         $(guile (mkclose))\n        $(LINK) < tmp.out\n@end group\n@end example\n\nA more comprehensive suite of file manipulation procedures is possible\nof course.  You could, for example, maintain multiple output files at\nthe same time by choosing a symbol for each one and using it as the\nkey to a hash table, where the value is a port, then returning the\nsymbol to be stored in a @code{make} variable.\n\n@node Loading Objects\n@section Loading Dynamic Objects\n@cindex loaded objects\n@cindex objects, loaded\n@cindex extensions, loading\n\nMany operating systems provide a facility for dynamically loading compiled\nobjects.  If your system provides this facility, GNU @code{make} can make use\nof it to load dynamic objects at runtime, providing new capabilities which may\nthen be invoked by your makefile.\n\nThe @code{load} makefile directive is used to load a dynamic object.  Once the\nobject is loaded, an initializing function will be invoked to allow the object\nto initialize itself and register new facilities with GNU @code{make}.  A\ndynamic object might include new @code{make} functions, for example, and the\ninitializing function would register them with GNU @code{make}'s function\nhandling system.\n\n@menu\n* load Directive::              Loading dynamic objects as extensions.\n* Initializing Functions::      How initializing functions are called.\n* Remaking Loaded Objects::     How loaded objects get remade.\n* Loaded Object API::           Programmatic interface for loaded objects.\n* Loaded Object Example::       Example of a loaded object\n@end menu\n\n@node load Directive\n@subsection The @code{load} Directive\n@cindex load directive\n@cindex extensions, load directive\n\nObjects are loaded into GNU @code{make} by placing the @code{load}\ndirective into your makefile.  The syntax of the @code{load} directive\nis as follows:\n\n@findex load\n@example\nload @var{object-file} @dots{}\n@end example\n\nor:\n\n@example\nload @var{object-file}(@var{symbol-name}) @dots{}\n@end example\n\nMore than one object file may be loaded with a single @code{load} directive,\nand both forms of @code{load} arguments may be used in the same directive.\n\nThe file @var{object-file} is dynamically loaded by GNU @code{make}.  If\n@var{object-file} does not include a directory path then it is first looked\nfor in the current directory.  If it is not found there, or a directory path\nis included, then system-specific paths will be searched.  If the load fails\nfor any reason, @code{make} will print a message and exit.\n\nIf the load succeeds @code{make} will invoke an initializing function.  If\n@var{symbol-name} is provided, it will be used as the name of the initializing\nfunction.\n\nIf @var{symbol-name} is not provided, the initializing function name is created\nby taking the base file name of @var{object-file}, up to the first character\nwhich is not a valid symbol name character (alphanumerics and underscores are\nvalid symbol name characters).  To this prefix will be appended the suffix\n@code{_gmk_setup}.\n\nFor example:\n\n@example\nload ../mk_funcs.so\n@end example\n\nwill load the dynamic object @file{../mk_funcs.so}.  After the object is\nloaded, @code{make} will invoke the initializing function (assumed to be\ndefined by the shared object) @code{mk_funcs_gmk_setup}.\n\nOn the other hand:\n\n@example\nload ../mk_funcs.so(init_mk_func)\n@end example\n\nwill load the dynamic object @file{../mk_funcs.so}.  After the object is\nloaded, @code{make} will invoke the initializing function @code{init_mk_func}.\n\nRegardless of how many times an object file appears in a @code{load}\ndirective, it will only be loaded (and its setup function will only be\ninvoked) once.\n\n@vindex .LOADED\nAfter an object has been successfully loaded, its file name is appended to the\n@code{.LOADED} variable.\n\n@findex -load\nIf you would prefer that failure to load a dynamic object not be reported as\nan error, you can use the @code{-load} directive instead of @code{load}.  GNU\n@code{make} will not fail and no message will be generated if an object fails\nto load.  The failed object is not added to the @code{.LOADED} variable, which\ncan then be consulted to determine if the load was successful.\n\n@subsubheading Unloading Objects\n@cindex unloading objects\n@cindex unload function for loaded objects\n\nWhen GNU Make needs to unload a loaded object, either because it is exiting or\nbecause the loaded object has been rebuilt, it will invoke an unload function.\nThe unload function name is created by taking the base file name of the object\nfile, up to the first character which is not a valid symbol name character\n(alphanumerics and underscores are valid symbol name characters), then\nappending the suffix @code{_gmk_unload}.\n\nIf that function exists it will be called using the signature:\n\n@example\nvoid <name>_gmk_unload (void);\n@end example\n\nIf the function does not exist, it will not be called.\n\nNote that only one unload function may be defined per loaded object,\nregardless of how many different setup methods are provided in that loaded\nobject.  If your loaded object provides multiple setup methods that require\nunload support it's up to you to coordinate which setups have been invoked in\nthe unload function.\n\n@node Initializing Functions\n@subsection Initializing Functions\n@cindex loaded object initializing function\n@cindex initializing function, for loaded objects\n\nThe initializing function defined by the loaded object must have this\nsignature:\n\n@example\nint <name> (unsigned int abi_version, const gmk_floc *floc);\n@end example\n\nWhere @emph{<name>} is described in the previous section.\n\nThe @code{abi_version} value will be the value of the @code{GMK_ABI_VERSION}\nconstant (see the @file{gnumake.h} file) for this GNU Make release.  The\n@code{floc} pointer provides the file name and line number of the invocation\nof the @code{load} operation.\n\nThe initializing function should return an @code{int}, which must be @code{0}\non failure and non-@code{0} on success.  If the return value is @code{-1},\nthen GNU Make will @emph{not} attempt to rebuild the object file\n(@pxref{Remaking Loaded Objects, ,How Loaded Objects Are Remade}).\n\n@node Remaking Loaded Objects\n@subsection How Loaded Objects Are Remade\n@cindex updating loaded objects\n@cindex remaking loaded objects\n@cindex loaded objects, remaking of\n\nLoaded objects undergo the same re-make procedure as makefiles\n(@pxref{Remaking Makefiles, ,How Makefiles Are Remade}).  If any loaded object\nis recreated, then @code{make} will start from scratch and re-read all the\nmakefiles, and reload the object files again.  It is not necessary for the\nloaded object to do anything special to support this.\n\nIt's up to the makefile author to provide the rules needed for rebuilding the\nloaded object.\n\n@node Loaded Object API\n@subsection Loaded Object Interface\n@cindex loaded object API\n@cindex interface for loaded objects\n\nTo be useful, loaded objects must be able to interact with GNU @code{make}.\nThis interaction includes both interfaces the loaded object provides to\nmakefiles and also interfaces @code{make} provides to the loaded object to\nmanipulate @code{make}'s operation.\n\nThe interface between loaded objects and @code{make} is defined by the\n@file{gnumake.h} C header file.  All loaded objects written in C should\ninclude this header file.  Any loaded object not written in C will need to\nimplement the interface defined in this header file.\n\nTypically, a loaded object will register one or more new GNU @code{make}\nfunctions using the @code{gmk_add_function} routine from within its setup\nfunction.  The implementations of these @code{make} functions may make use of\nthe @code{gmk_expand} and @code{gmk_eval} routines to perform their tasks,\nthen optionally return a string as the result of the function expansion.\n\n@subsubheading Loaded Object Licensing\n@cindex loaded object licensing\n@cindex plugin_is_GPL_compatible\n\nEvery dynamic extension should define the global symbol\n@code{plugin_is_GPL_compatible} to assert that it has been licensed under a\nGPL-compatible license.  If this symbol does not exist, @code{make} emits a\nfatal error and exits when it tries to load your extension.\n\nThe declared type of the symbol should be @code{int}. It does not need to be\nin any allocated section, though.  The code merely asserts that the symbol\nexists in the global scope. Something like this is enough:\n\n@example\nint plugin_is_GPL_compatible;\n@end example\n\n@subsubheading Data Structures\n\n@table @code\n@item gmk_floc\nThis structure represents a filename/location pair.  It is provided when\ndefining items, so GNU @code{make} can inform the user where the definition\noccurred if necessary.\n@end table\n\n@subsubheading Checking Versions\n@findex gmk_get_version\n\nThe @code{gmk_get_version} allows loaded objects to check which loaded object\nAPI version is supported by GNU Make.  The API version is specified as two\nvalues: the @emph{major} version and the @emph{minor} version.  Note, these\ntwo values are not the same as the version of GNU Make!\n\nThe @emph{major} version is incremented when there is a change to the loaded\nobject ABI, which might cause .\n\nIt is called as:\n\n@example\nvoid gmk_get_version (unsigned int *major, unsigned int *minor);\n@end example\n\n@table @code\n@item major\nIf not NULL, the major version number is placed here.\n\n@item minor\nIf not NULL, the minor version number is placed here.\n@end table\n\n\n@subsubheading Registering Functions\n@findex gmk_add_function\n\nThere is currently one way for makefiles to invoke operations provided by the\nloaded object: through the @code{make} function call interface.  A loaded\nobject can register one or more new functions which may then be invoked from\nwithin the makefile in the same way as any other function.\n\nUse @code{gmk_add_function} to create a new @code{make} function.  Its\narguments are as follows:\n\n@table @code\n@item name\nThe function name.  This is what the makefile should use to invoke the\nfunction.  The name must be between 1 and 255 characters long and it may only\ncontain alphanumeric, period (@samp{.}), dash (@samp{-}), and underscore\n(@samp{_}) characters.  It may not begin with a period.\n\n@item func_ptr\nA pointer to a function that @code{make} will invoke when it expands the\nfunction in a makefile.  This function must be defined by the loaded object.\n\n@item min_args\nThe minimum number of arguments the function will accept.  Must be between 0\nand 255.  GNU @code{make} will check this and fail before invoking\n@code{func_ptr} if the function was invoked with too few arguments.\n\n@item max_args\nThe maximum number of arguments the function will accept.  Must be between 0\nand 255.  GNU @code{make} will check this and fail before invoking\n@code{func_ptr} if the function was invoked with too many arguments.  If the\nvalue is 0, then any number of arguments is accepted.  If the value is greater\nthan 0, then it must be greater than or equal to @code{min_args}.\n\n@item flags\nFlags that specify how this function will operate; the desired flags should be\nOR'd together.  If the @code{GMK_FUNC_NOEXPAND} flag is given then the\nfunction arguments will not be expanded before the function is called;\notherwise they will be expanded first.\n@end table\n\n@subsubheading Registered Function Interface\n@findex gmk_func_ptr\n\nA function registered with @code{make} must match the @code{gmk_func_ptr}\ntype.  It will be invoked with three parameters: @code{name} (the name of the\nfunction), @code{argc} (the number of arguments to the function), and\n@code{argv} (an array of pointers to arguments to the function).  The last\npointer (that is, @code{argv[argc]}) will be null (@code{0}).\n\nThe return value of the function is the result of expanding the function.  If\nthe function expands to nothing the return value may be null.  Otherwise, it\nmust be a pointer to a string created with @code{gmk_alloc}.  Once the\nfunction returns, @code{make} owns this string and will free it when\nappropriate; it cannot be accessed by the loaded object.\n\n@subsubheading GNU @code{make} Facilities\n\nThere are some facilities exported by GNU @code{make} for use by loaded\nobjects.  Typically these would be run from within the setup function and/or\nthe functions registered via @code{gmk_add_function}, to retrieve or modify\nthe data @code{make} works with.\n\n@table @code\n@item gmk_expand\n@findex gmk_expand\nThis function takes a string and expands it using @code{make} expansion rules.\nThe result of the expansion is returned in a nil-terminated string buffer.\nThe caller is responsible for calling @code{gmk_free} with a pointer to the\nreturned buffer when done.\n\n@item gmk_eval\n@findex gmk_eval\nThis function takes a buffer and evaluates it as a segment of makefile syntax.\nThis function can be used to define new variables, new rules, etc.  It is\nequivalent to using the @code{eval} @code{make} function.\n@end table\n\nNote that there is a difference between @code{gmk_eval} and calling\n@code{gmk_expand} with a string using the @code{eval} function: in the latter\ncase the string will be expanded @emph{twice}; once by @code{gmk_expand} and\nthen again by the @code{eval} function.  Using @code{gmk_eval} the buffer is\nonly expanded once, at most (as it's read by the @code{make} parser).\n\n@subsubheading Memory Management\n\nSome systems allow for different memory management schemes.  Thus you should\nnever pass memory that you've allocated directly to any @code{make} function,\nnor should you attempt to directly free any memory returned to you by any\n@code{make} function.  Instead, use the @code{gmk_alloc} and @code{gmk_free}\nfunctions.\n\nIn particular, the string returned to @code{make} by a function registered\nusing @code{gmk_add_function} @emph{must} be allocated using @code{gmk_alloc},\nand the string returned from the @code{make} @code{gmk_expand} function\n@emph{must} be freed (when no longer needed) using @code{gmk_free}.\n\n@table @code\n@item gmk_alloc\n@findex gmk_alloc\nReturn a pointer to a newly-allocated buffer.  This function will always\nreturn a valid pointer; if not enough memory is available @code{make} will\nexit.  @code{gmk_alloc} does not initialize allocated memory.\n\n@item gmk_free\n@findex gmk_free\nFree a buffer returned to you by @code{make}.  Once the @code{gmk_free}\nfunction returns the string will no longer be valid.  If NULL is passed to\n@code{gmk_free}, no operation is performed.\n@end table\n\n@node Loaded Object Example\n@subsection Example Loaded Object\n@cindex loaded object example\n@cindex example of loaded objects\n\nLet's suppose we wanted to write a new GNU @code{make} function that would\ncreate a temporary file and return its name.  We would like our function to\ntake a prefix as an argument.  First we can write the function in a file\n@file{mk_temp.c}:\n\n@example\n@group\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <errno.h>\n\n#include <gnumake.h>\n\nint plugin_is_GPL_compatible;\n\nstruct tmpfile @{\n  struct tmpfile *next;\n  char *name;\n@};\nstatic struct tmpfile *files = NULL;\n@end group\n\n@group\nstatic char *\ngen_tmpfile(const char *nm, unsigned int argc, char **argv)\n@{\n  int fd;\n\n  /* Compute the size of the filename and allocate space for it.  */\n  int len = strlen (argv[0]) + 6 + 1;\n  char *buf = gmk_alloc (len);\n\n  strcpy (buf, argv[0]);\n  strcat (buf, \"XXXXXX\");\n\n  fd = mkstemp(buf);\n  if (fd >= 0)\n    @{\n      struct tmpfile *new = malloc (sizeof (struct tmpfile));\n      new->name = strdup (buf);\n      new->next = files;\n      files = new;\n\n      /* Don't leak the file descriptor.  */\n      close (fd);\n      return buf;\n    @}\n\n  /* Failure.  */\n  fprintf (stderr, \"mkstemp(%s) failed: %s\\n\", buf, strerror (errno));\n  gmk_free (buf);\n  return NULL;\n@}\n@end group\n\n@group\nint\nmk_temp_gmk_setup (unsigned int abi, const gmk_floc *floc)\n@{\n  printf (\"mk_temp abi %u plugin loaded from %s:%lu\\n\",\n          abi, floc->filenm, floc->lineno);\n  /* Register the function with make name \"mk-temp\".  */\n  gmk_add_function (\"mk-temp\", gen_tmpfile, 1, 1, 1);\n  return 1;\n@}\n@end group\n\n@group\nvoid\nmk_temp_gmk_close ()\n@{\n  while (files)\n    @{\n      struct tmpfile *f = files;\n      files = f->next;\n      printf (\"mk_temp removing %s\\n\", f->name);\n      remove (f->name);\n      free (f->name);\n      free (f);\n    @}\n  printf (\"mk_temp plugin closed\\n\");\n@}\n@end group\n@end example\n\nNext, we will write a @file{Makefile} that can build this shared object, load\nit, and use it:\n\n@example\n@group\nall:\n        @@echo Temporary file: $(mk-temp tmpfile.)\n        @@echo Temporary file: $(mk-temp tmpfile.)\n\n-load mk_temp.so\n\nmk_temp.so: mk_temp.c\n        $(CC) -shared -fPIC -o $@@ $<\n@end group\n@end example\n\nOn MS-Windows, due to peculiarities of how shared objects are produced, the\ncompiler needs to scan the @dfn{import library} produced when building\n@code{make}, typically called @file{libgnumake-@var{version}.dll.a}, where\n@var{version} is the version of the load object API.  So the recipe to produce\na shared object will look like this on Windows (assuming the API version is\n1):\n\n@example\n@group\nmk_temp.dll: mk_temp.c\n        $(CC) -shared -o $@@ $< -lgnumake-1\n@end group\n@end example\n\nNow when you run @code{make} you'll see something like:\n\n@example\n@group\n$ make\ncc -shared -fPIC -o mk_temp.so mk_temp.c\nmk_temp abi 1 plugin loaded from Makefile:5\nTemporary file: tmpfile.OYkGMT\nTemporary file: tmpfile.sYsJO0\nmk_temp removing tmpfile.sYsJO0\nmk_temp removing tmpfile.OYkGMT\nmk_temp plugin closed\n@end group\n@end example\n\n@node Integrating make\n@chapter Integrating GNU @code{make}\n@cindex make integration\n\nGNU @code{make} is often one component in a larger system of tools,\nincluding integrated development environments, compiler toolchains,\nand others.  The role of @code{make} is to start commands and\ndetermine whether they succeeded or not: no special integration is\nneeded to accomplish that.  However, sometimes it is convenient to\nbind @code{make} more tightly with other parts of the system, both\nhigher-level (tools that invoke @code{make}) and lower-level (tools\nthat @code{make} invokes).\n\n@menu\n* Job Slots::                   Share job slots with GNU Make.\n* Terminal Output::             Control output to terminals.\n@end menu\n\n@node Job Slots\n@section Sharing Job Slots with GNU @code{make}\n@cindex job slots, sharing\n@cindex tools, sharing job slots\n\nGNU @code{make} has the ability to run multiple recipes in parallel\n(@pxref{Parallel, ,Parallel Execution}) and to cap the total number of\nparallel jobs even across recursive invocations of @code{make}\n(@pxref{Options/Recursion, ,Communicating Options to a\nSub-@code{make}}).  Tools that @code{make} invokes which are also able\nto run multiple operations in parallel, either using multiple threads\nor multiple processes, can be enhanced to participate in GNU\n@code{make}'s job management facility to ensure that the total number\nof active threads/processes running on the system does not exceed the\nmaximum number of slots provided to GNU @code{make}. \n\n@cindex jobserver\nGNU @code{make} uses a method called the ``jobserver'' to control the\nnumber of active jobs across recursive invocations.  The actual\nimplementation of the jobserver varies across different operating\nsystems, but some fundamental aspects are always true.\n\n@cindex @code{--jobserver-auth}\nFirst, @code{make} will provide information necessary for accessing the\njobserver through the environment to its children, in the @code{MAKEFLAGS}\nenvironment variable.  Tools which want to participate in the jobserver\nprotocol will need to parse this environment variable and find the word\nstarting with @code{--jobserver-auth=}.  The value of this option will\ndescribe how to communicate with the jobserver.  The interpretation of this\nvalue is described in the sections below.\n\nBe aware that the @code{MAKEFLAGS} variable may contain multiple instances of\nthe @code{--jobserver-auth=} option.  Only the @emph{last} instance is\nrelevant.\n\nSecond, every command @code{make} starts has one implicit job slot\nreserved for it before it starts.  Any tool which wants to participate\nin the jobserver protocol should assume it can always run one job\nwithout having to contact the jobserver at all.\n\nFinally, it's critical that tools that participate in the jobserver\nprotocol return the exact number of slots they obtained from the\njobserver back to the jobserver before they exit, even under error\nconditions.  Remember that the implicit job slot should @strong{not}\nbe returned to the jobserver!  Returning too few slots means that\nthose slots will be lost for the rest of the build process; returning\ntoo many slots means that extra slots will be available.  The\ntop-level @code{make} command will print an error message at the end\nof the build if it detects an incorrect number of slots available in\nthe jobserver.\n\nAs an example, suppose you are implementing a linker which provides\nfor multi-threaded operation.  You would like to enhance the linker so\nthat if it is invoked by GNU @code{make} it can participate in the\njobserver protocol to control how many threads are used during link.\nFirst you will need to modify the linker to determine if the\n@code{MAKEFLAGS} environment variable is set.  Next you will need to\nparse the value of that variable to determine if the jobserver is\navailable, and how to access it.  If it is available then you can\naccess it to obtain job slots controlling how much parallelism your\ntool can use.  Once done your tool must return those job slots back to\nthe jobserver.\n\n@menu\n* POSIX Jobserver::             Using the jobserver on POSIX systems.\n* Windows Jobserver::           Using the jobserver on Windows systems.\n@end menu\n\n@node POSIX Jobserver\n@subsection POSIX Jobserver Interaction\n@cindex jobserver on POSIX\n\nOn POSIX systems the jobserver is implemented in one of two ways: on systems\nthat support it, GNU @code{make} will create a named pipe and use that for the\njobserver.  In this case the auth option will have the form\n@code{--jobserver-auth=fifo:PATH} where @samp{PATH} is the pathname of the\nnamed pipe.  To access the jobserver you should open the named pipe path and\nread/write to it as described below.\n\n@cindex @code{--jobserver-style}\nIf the system doesn't support named pipes, or if the user provided the\n@code{--jobserver-style} option and specified @samp{pipe}, then the jobserver\nwill be implemented as a simple UNIX pipe.  In this case the auth option will\nhave the form @code{--jobserver-auth=R,W} where @samp{R} and @samp{W} are\nnon-negative integers representing file descriptors: @samp{R} is the read file\ndescriptor and @samp{W} is the write file descriptor.  If either or both of\nthese file descriptors are negative, it means the jobserver is disabled for\nthis process.\n\nWhen using a simple pipe, only command lines that @code{make} understands to\nbe recursive invocations of @code{make} (@pxref{MAKE Variable, ,How the\n@code{MAKE} Variable Works}) will have access to the jobserver.  When writing\nmakefiles you must be sure to mark the command as recursive (most commonly by\nprefixing the command line with the @code{+} indicator (@pxref{Recursion,\n,Recursive Use of @code{make}}).  Note that the read side of the jobserver\npipe is set to ``blocking'' mode.  This should not be changed.\n\nIn both implementations of the jobserver, the pipe will be pre-loaded with one\nsingle-character token for each available job.  To obtain an extra slot you\nmust read a single character from the jobserver; to release a slot you must\nwrite a single character back into the jobserver.\n\nIt's important that when you release the job slot, you write back the same\ncharacter you read.  Don't assume that all tokens are the same character;\ndifferent characters may have different meanings to GNU @code{make}.  The\norder is not important, since @code{make} has no idea in what order jobs will\ncomplete anyway.\n\nThere are various error conditions you must consider to ensure your\nimplementation is robust:\n\n@itemize @bullet\n@item\nIf you have a command-line argument controlling the parallel operation of your\ntool, consider whether your tool should detect situations where both the\njobserver and the command-line argument are specified, and how it should\nreact.\n\n@item\nIf your tool does not recognize the format of the @code{--jobserver-auth}\nstring, it should assume the jobserver is using a different style and it\ncannot connect.\n\n@item\nIf your tool determines that the @code{--jobserver-auth} option references a\nsimple pipe but that the file descriptors specified are closed, this means\nthat the calling @code{make} process did not think that your tool was a\nrecursive @code{make} invocation (e.g., the command line was not prefixed with\na @code{+} character).  You should notify your users of this situation.\n\n@item\nYour tool should be sure to write back the tokens it read, even under error\nconditions.  This includes not only errors in your tool but also outside\ninfluences such as interrupts (@code{SIGINT}), etc.  You may want to install\nsignal handlers to manage this write-back.\n\n@item\nYour tool may also examine the first word of the @code{MAKEFLAGS} variable and\nlook for the character @code{n}.  If this character is present then\n@code{make} was invoked with the @samp{-n} option and your tool may want to\nstop without performing any operations.\n@end itemize\n\n@node Windows Jobserver\n@subsection Windows Jobserver Interaction\n@cindex jobserver on Windows\n\nOn Windows systems the jobserver is implemented as a named semaphore.\nThe semaphore will be set with an initial count equal to the number of\navailable slots; to obtain a slot you must wait on the semaphore (with\nor without a timeout).  To release a slot, release the semaphore.\n\nTo access the semaphore you must parse the @code{MAKEFLAGS} variable and\nlook for the argument string @code{--jobserver-auth=NAME} where\n@samp{NAME} is the name of the named semaphore.  Use this name with\n@code{OpenSemaphore} to create a handle to the semaphore.\n\n@cindex @code{--jobserver-style} for Windows\nThe only valid style for @code{--jobserver-style} is @samp{sem}.\n\nThere are various error conditions you must consider to ensure your\nimplementation is robust:\n\n@itemize @bullet\n@item\nUsually you will have a command-line argument controlling the parallel\noperation of your tool.  Consider whether your tool should detect\nsituations where both the jobserver and the command-line argument are\nspecified, and how it should react.\n\n@item\nYour tool should be sure to release the semaphore for the tokens it\nread, even under error conditions.  This includes not only errors in\nyour tool but also outside influences such as interrupts\n(@code{SIGINT}), etc.  You may want to install signal handlers to\nmanage this write-back.\n@end itemize\n\n@node Terminal Output\n@section Synchronized Terminal Output\n@cindex parallel output to terminal\n@cindex terminal, output to\n\nNormally GNU @code{make} will invoke all commands with access to the\nsame standard and error outputs that @code{make} itself was started\nwith.  A number of tools will detect whether the output is a terminal\nor not-a-terminal, and use this information to change the output\nstyle.  For example if the output goes to a terminal the tool may add\ncontrol characters that set color, or even change the location of the\ncursor.  If the output is not going to a terminal then these special\ncontrol characters are not emitted so that they don't corrupt log\nfiles, etc.\n\nThe @code{--output-sync} (@pxref{Parallel Output, ,Output During\nParallel Execution}) option will defeat the terminal detection.  When\noutput synchronization is enabled GNU @code{make} arranges for all\ncommand output to be written to a file, so that its output can be\nwritten as a block without interference from other commands.  This\nmeans that all tools invoked by @code{make} will believe that their\noutput is not going to be displayed on a terminal, even when it will\nbe (because @code{make} will display it there after the command is\ncompleted).\n\nIn order to facilitate tools which would like to determine whether or\nnot their output will be displayed on a terminal, GNU @code{make} will\nset the @code{MAKE_TERMOUT} and @code{MAKE_TERMERR} environment\nvariables before invoking any commands.  Tools which would like to\ndetermine whether standard or error output (respectively) will be\ndisplayed on a terminal can check these environment variables to\ndetermine if they exist and contain a non-empty value.  If so the tool\ncan assume that the output will (eventually) be displayed on a\nterminal.  If the variables are not set or have an empty value, then\nthe tool should fall back to its normal methods of detecting whether\noutput is going to a terminal or not.\n\nThe content of the variables can be parsed to determine the type of\nterminal which will be used to display the output.\n\nSimilarly, environments which invoke @code{make} and would like to\ncapture the output and eventually display it on a terminal (or some\ndisplay which can interpret terminal control characters) can set these\nvariables before invoking @code{make}.  GNU @code{make} will not\nmodify these environment variables if they already exist when it\nstarts.\n\n@node Features\n@chapter Features of GNU @code{make}\n@cindex features of GNU @code{make}\n@cindex portability\n@cindex compatibility\n\nHere is a summary of the features of GNU @code{make}, for comparison\nwith and credit to other versions of @code{make}.  We consider the\nfeatures of @code{make} in 4.2 BSD systems as a baseline.  If you are\nconcerned with writing portable makefiles, you should not use the\nfeatures of @code{make} listed here, nor the ones in @ref{Missing}.\n\nMany features come from the version of @code{make} in System V.\n\n@itemize @bullet\n@item\nThe @code{VPATH} variable and its special meaning.\n@xref{Directory Search, , Searching Directories for Prerequisites}.\nThis feature exists in System V @code{make}, but is undocumented.\nIt is documented in 4.3 BSD @code{make} (which says it mimics System V's\n@code{VPATH} feature).\n\n@item\nIncluded makefiles.  @xref{Include, ,Including Other Makefiles}.\nAllowing multiple files to be included with a single directive is a GNU\nextension.\n\n@item\nVariables are read from and communicated via the environment.\n@xref{Environment, ,Variables from the Environment}.\n\n@item\nOptions passed through the variable @code{MAKEFLAGS} to recursive\ninvocations of @code{make}.\n@xref{Options/Recursion, ,Communicating Options to a Sub-@code{make}}.\n\n@item\nThe automatic variable @code{$%} is set to the member name\nin an archive reference.  @xref{Automatic Variables}.\n\n@item\nThe automatic variables @code{$@@}, @code{$*}, @code{$<}, @code{$%},\nand @code{$?} have corresponding forms like @code{$(@@F)} and\n@code{$(@@D)}.  We have generalized this to @code{$^} as an obvious\nextension.  @xref{Automatic Variables}.\n\n@item\nSubstitution variable references.\n@xref{Reference, ,Basics of Variable References}.\n\n@item\nThe command line options @samp{-b} and @samp{-m}, accepted and\nignored.  In System V @code{make}, these options actually do something.\n\n@item\nExecution of recursive commands to run @code{make} via the variable\n@code{MAKE} even if @samp{-n}, @samp{-q} or @samp{-t} is specified.\n@xref{Recursion, ,Recursive Use of @code{make}}.\n\n@item\nSupport for suffix @samp{.a} in suffix rules.  @xref{Archive Suffix\nRules}.  This feature is obsolete in GNU @code{make}, because the\ngeneral feature of rule chaining (@pxref{Chained Rules, ,Chains of\nImplicit Rules}) allows one pattern rule for installing members in an\narchive (@pxref{Archive Update}) to be sufficient.\n\n@item\nThe arrangement of lines and backslash/newline combinations in\nrecipes is retained when the recipes are printed, so they appear as\nthey do in the makefile, except for the stripping of initial\nwhitespace.\n@end itemize\n\nThe following features were inspired by various other versions of\n@code{make}.  In some cases it is unclear exactly which versions inspired\nwhich others.\n\n@itemize @bullet\n@item\nPattern rules using @samp{%}.\nThis has been implemented in several versions of @code{make}.\nWe're not sure who invented it first, but it's been spread around a bit.\n@xref{Pattern Rules, ,Defining and Redefining Pattern Rules}.\n\n@item\nRule chaining and implicit intermediate files.\nThis was implemented by Stu Feldman in his version of @code{make}\nfor AT&T Eighth Edition Research Unix, and later by Andrew Hume of\nAT&T Bell Labs in his @code{mk} program (where he terms it\n``transitive closure'').  We do not really know if\nwe got this from either of them or thought it up ourselves at the\nsame time.  @xref{Chained Rules, ,Chains of Implicit Rules}.\n\n@item\nThe automatic variable @code{$^} containing a list of all prerequisites\nof the current target.  We did not invent this, but we have no idea who\ndid.  @xref{Automatic Variables}.  The automatic variable\n@code{$+} is a simple extension of @code{$^}.\n\n@item\nThe ``what if'' flag (@samp{-W} in GNU @code{make}) was (as far as we know)\ninvented by Andrew Hume in @code{mk}.\n@xref{Instead of Execution, ,Instead of Executing Recipes}.\n\n@item\nThe concept of doing several things at once (parallelism) exists in\nmany incarnations of @code{make} and similar programs, though not in the\nSystem V or BSD implementations.  @xref{Execution, ,Recipe Execution}.\n\n@item\nA number of different build tools that support parallelism also\nsupport collecting output and displaying as a single block.\n@xref{Parallel Output, ,Output During Parallel Execution}.\n\n@item\nModified variable references using pattern substitution come from\nSunOS 4.  @xref{Reference, ,Basics of Variable References}.\nThis functionality was provided in GNU @code{make} by the\n@code{patsubst} function before the alternate syntax was implemented\nfor compatibility with SunOS 4.  It is not altogether clear who\ninspired whom, since GNU @code{make} had @code{patsubst} before SunOS\n4 was released.\n\n@item\nThe special significance of @samp{+} characters preceding recipe lines\n(@pxref{Instead of Execution, ,Instead of Executing Recipes}) is\nmandated by @cite{IEEE Standard 1003.1-2024} (POSIX).\n\n@item\nThe @samp{+=} syntax to append to the value of a variable comes from SunOS\n4 @code{make}.  @xref{Appending Assignment, , Appending More Text to Variables}.\n\n@item\nThe syntax @w{@samp{@var{archive}(@var{mem1} @var{mem2}@dots{})}} to list\nmultiple members in a single archive file comes from SunOS 4 @code{make}.\n@xref{Archive Members}.\n\n@item\nThe @code{-include} directive to include makefiles with no error for a\nnonexistent file comes from SunOS 4 @code{make}.  (But note that SunOS 4\n@code{make} does not allow multiple makefiles to be specified in one\n@code{-include} directive.)  The same feature appears with the name\n@code{sinclude} in SGI @code{make} and perhaps others.\n\n@item\nThe @code{!=} shell assignment operator exists in many BSD of\n@code{make} and is purposefully implemented here to behave identically\nto those implementations.\n\n@item\nVarious build management tools are implemented using scripting\nlanguages such as Perl or Python and thus provide a natural embedded\nscripting language, similar to GNU @code{make}'s integration of GNU\nGuile.\n@end itemize\n\nThe remaining features are inventions new in GNU @code{make}:\n\n@itemize @bullet\n@item\nUse the @samp{-v} or @samp{--version} option to print version and\ncopyright information.\n\n@item\nUse the @samp{-h} or @samp{--help} option to summarize the options to\n@code{make}.\n\n@item\nSimply-expanded variables.  @xref{Flavors, ,The Two Flavors of Variables}.\n\n@item\nPass command line variable assignments automatically through the\nvariable @code{MAKE} to recursive @code{make} invocations.\n@xref{Recursion, ,Recursive Use of @code{make}}.\n\n@item\nUse the @samp{-C} or @samp{--directory} command option to change\ndirectory.  @xref{Options Summary, ,Summary of Options}.\n\n@item\nMake verbatim variable definitions with @code{define}.\n@xref{Multi-Line, ,Defining Multi-Line Variables}.\n\n@item\nDeclare phony targets with the special target @code{.PHONY}.\n\nAndrew Hume of AT&T Bell Labs implemented a similar feature with a\ndifferent syntax in his @code{mk} program.  This seems to be a case of\nparallel discovery.  @xref{Phony Targets, ,Phony Targets}.\n\n@item\nManipulate text by calling functions.\n@xref{Functions, ,Functions for Transforming Text}.\n\n@item\nUse the @samp{-o} or @samp{--old-file}\noption to pretend a file's modification-time is old.\n@xref{Avoiding Compilation, ,Avoiding Recompilation of Some Files}.\n\n@item\nConditional execution.\n\nThis feature has been implemented numerous times in various versions\nof @code{make}; it seems a natural extension derived from the features\nof the C preprocessor and similar macro languages and is not a\nrevolutionary concept.  @xref{Conditionals, ,Conditional Parts of Makefiles}.\n\n@item\nSpecify a search path for included makefiles.\n@xref{Include, ,Including Other Makefiles}.\n\n@item\nSpecify extra makefiles to read with an environment variable.\n@xref{MAKEFILES Variable, ,The Variable @code{MAKEFILES}}.\n\n@item\nStrip leading sequences of @samp{./} from file names, so that\n@file{./@var{file}} and @file{@var{file}} are considered to be the\nsame file.\n\n@item\nUse a special search method for library prerequisites written in the\nform @samp{-l@var{name}}.\n@xref{Libraries/Search, ,Directory Search for Link Libraries}.\n\n@item\nAllow suffixes for suffix rules\n(@pxref{Suffix Rules, ,Old-Fashioned Suffix Rules}) to contain any\ncharacters.  In other versions of @code{make}, they must begin with\n@samp{.} and not contain any @samp{/} characters.\n\n@item\nKeep track of the current level of @code{make} recursion using the\nvariable @code{MAKELEVEL}.  @xref{Recursion, ,Recursive Use of @code{make}}.\n\n@item\nProvide any goals given on the command line in the variable\n@code{MAKECMDGOALS}.  @xref{Goals, ,Arguments to Specify the Goals}.\n\n@item\nSpecify static pattern rules.  @xref{Static Pattern, ,Static Pattern Rules}.\n\n@item\nProvide selective @code{vpath} search.\n@xref{Directory Search, ,Searching Directories for Prerequisites}.\n\n@item\nProvide computed variable references.\n@xref{Reference, ,Basics of Variable References}.\n\n@item\nUpdate makefiles.  @xref{Remaking Makefiles, ,How Makefiles Are Remade}.\nSystem V @code{make} has a very, very limited form of this\nfunctionality in that it will check out SCCS files for makefiles.\n\n@item\nVarious new built-in implicit rules.\n@xref{Catalogue of Rules, ,Catalogue of Built-In Rules}.\n\n@item\nLoad dynamic objects which can modify the behavior of @code{make}.\n@xref{Loading Objects, ,Loading Dynamic Objects}.\n@end itemize\n\n@node Missing\n@chapter Incompatibilities and Missing Features\n@cindex incompatibilities\n@cindex missing features\n@cindex features, missing\n\nThe @code{make} programs in various other systems support a few features\nthat are not implemented in GNU @code{make}.  The POSIX standard\n(@cite{IEEE Standard 1003.1-2024}) which specifies @code{make} does not\nrequire any of these features.\n\n@itemize @bullet\n@item\nA target of the form @samp{@var{file}((@var{entry}))} stands for a member\nof archive file @var{file}.  The member is chosen, not by name, but by\nbeing an object file which defines the linker symbol @var{entry}.\n\nThis feature was not put into GNU @code{make} because of the\nnon-modularity of putting knowledge into @code{make} of the internal\nformat of archive file symbol tables.\n@xref{Archive Symbols, ,Updating Archive Symbol Directories}.\n\n@item\nSuffixes (used in suffix rules) that end with the character @samp{~}\nhave a special meaning to System V @code{make};\nthey refer to the SCCS file that corresponds\nto the file one would get without the @samp{~}.  For example, the\nsuffix rule @samp{.c~.o} would make the file @file{@var{n}.o} from\nthe SCCS file @file{s.@var{n}.c}.  For complete coverage, a whole\nseries of such suffix rules is required.\n@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.\n\nIn GNU @code{make}, this entire series of cases is handled by two\npattern rules for extraction from SCCS, in combination with the\ngeneral feature of rule chaining.\n@xref{Chained Rules, ,Chains of Implicit Rules}.\n\n@item\nIn System V and 4.3 BSD @code{make}, files found by @code{VPATH}\nsearch (@pxref{Directory Search, ,Searching Directories for\nPrerequisites}) have their names changed inside recipes.  We feel it\nis much cleaner to always use automatic variables and thus make this\nfeature unnecessary.\n\n@item\nIn some Unix @code{make}s, the automatic variable @code{$*} appearing in\nthe prerequisites of a rule has the amazingly strange ``feature'' of\nexpanding to the full name of the @emph{target of that rule}.  We cannot\nimagine what went on in the minds of Unix @code{make} developers to do\nthis; it is utterly inconsistent with the normal definition of @code{$*}.\n@vindex * @r{(automatic variable), unsupported bizarre usage}\n\n@item\nIn some Unix @code{make}s, implicit rule search (@pxref{Implicit\nRules, ,Using Implicit Rules}) is apparently done for @emph{all}\ntargets, not just those without recipes.  This means you can\ndo:\n\n@example\n@group\nfoo.o:\n        cc -c foo.c\n@end group\n@end example\n\n@noindent\nand Unix @code{make} will intuit that @file{foo.o} depends on\n@file{foo.c}.\n\nWe feel that such usage is broken.  The prerequisite properties of\n@code{make} are well-defined (for GNU @code{make}, at least),\nand doing such a thing simply does not fit the model.\n\n@item\nGNU @code{make} does not include any built-in implicit rules for\ncompiling or preprocessing EFL programs.  If we hear of anyone who is\nusing EFL, we will gladly add them.\n\n@item\nIt appears that in SVR4 @code{make}, a suffix rule can be specified\nwith no recipe, and it is treated as if it had an empty recipe\n(@pxref{Empty Recipes}).  For example:\n\n@example\n.c.a:\n@end example\n\n@noindent\nwill override the built-in @file{.c.a} suffix rule.\n\nWe feel that it is cleaner for a rule without a recipe to always simply\nadd to the prerequisite list for the target.  The above example can be\neasily rewritten to get the desired behavior in GNU @code{make}:\n\n@example\n.c.a: ;\n@end example\n\n@item\nSome versions of @code{make} invoke the shell with the @samp{-e} flag,\nexcept under @samp{-k} (@pxref{Testing, ,Testing the Compilation of a\nProgram}).  The @samp{-e} flag tells the shell to exit as soon as any\nprogram it runs returns a nonzero status.  We feel it is cleaner to\nwrite each line of the recipe to stand on its own and not require this\nspecial treatment.\n@end itemize\n\n@comment The makefile standards are in a separate file that is also\n@comment included by standards.texi.\n@include make-stds.texi\n\n@node Quick Reference\n@appendix Quick Reference\n\nThis appendix summarizes the directives, text manipulation functions,\nand special variables which GNU @code{make} understands.\n@xref{Special Targets}, @ref{Catalogue of Rules, ,Catalogue of Built-In Rules},\nand @ref{Options Summary, ,Summary of Options},\nfor other summaries.\n\n@menu\n* Makefile Directives::         All makefile directives.\n* Makefile Functions::          All makefile built-in functions.\n* Automatic Variable Reference::  All automatic variables for recipes.\n* Special Variable Reference::  All special variables for makefiles.\n@end menu\n\n@node Makefile Directives\n@appendixsec Makefile Directives Reference\n\nHere is a summary of the directives GNU @code{make} recognizes:\n\n@table @code\n@item define @var{variable}\n@itemx define @var{variable} =\n@itemx define @var{variable} :=\n@itemx define @var{variable} ::=\n@itemx define @var{variable} :::=\n@itemx define @var{variable} !=\n@itemx define @var{variable} ?=\n@itemx define @var{variable} ?:=\n@itemx define @var{variable} ?::=\n@itemx define @var{variable} ?:::=\n@itemx define @var{variable} ?!=\n@itemx define @var{variable} +=\n@itemx endef\nDefine multi-line variables.@*\n@xref{Multi-Line}.\n\n@item undefine @var{variable}\nUndefining variables.@*\n@xref{Undefine Directive}.\n\n@item ifdef @var{variable}\n@itemx ifndef @var{variable}\n@itemx ifeq (@var{a},@var{b})\n@itemx ifeq \"@var{a}\" \"@var{b}\"\n@itemx ifeq '@var{a}' '@var{b}'\n@itemx ifneq (@var{a},@var{b})\n@itemx ifneq \"@var{a}\" \"@var{b}\"\n@itemx ifneq '@var{a}' '@var{b}'\n@itemx else\n@itemx endif\nConditionally evaluate part of the makefile.@*\n@xref{Conditionals}.\n\n@item include @var{file}\n@itemx -include @var{file}\n@itemx sinclude @var{file}\nInclude another makefile.@*\n@xref{Include, ,Including Other Makefiles}.\n\n@item override @var{variable-assignment}\nDefine a variable, overriding any previous definition, even one from\nthe command line.@*\n@xref{Override Directive, ,The @code{override} Directive}.\n\n@item export\nTell @code{make} to export all variables to child processes by default.@*\n@xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.\n\n@item export @var{variable}\n@itemx export @var{variable-assignment}\n@itemx unexport @var{variable}\nTell @code{make} whether or not to export a particular variable to child\nprocesses.@*\n@xref{Variables/Recursion, , Communicating Variables to a Sub-@code{make}}.\n\n@item private @var{variable-assignment}\nDo not allow this variable assignment to be inherited by prerequisites.@*\n@xref{Suppressing Inheritance}.\n\n@item vpath @var{pattern} @var{path}\nSpecify a search path for files matching a @samp{%} pattern.@*\n@xref{Selective Search, , The @code{vpath} Directive}.\n\n@item vpath @var{pattern}\nRemove all search paths previously specified for @var{pattern}.@*\n@xref{Selective Search, , The @code{vpath} Directive}.\n\n@item vpath\nRemove all search paths previously specified in any @code{vpath} directive.@*\n@xref{Selective Search, , The @code{vpath} Directive}.\n@end table\n\n@node Makefile Functions\n@appendixsec Makefile Functions Reference\n\nHere is a summary of the built-in functions (@pxref{Functions}):\n\n@table @code\n@item $(abspath @var{names}@dots{})\nFor each file name in @var{names}, expand to an absolute name that does not\ncontain any @code{.} or @code{..} components, but preserves symlinks.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(addprefix @var{prefix},@var{names}@dots{})\nPrepend @var{prefix} to each word in @var{names}.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(addsuffix @var{suffix},@var{names}@dots{})\nAppend @var{suffix} to each word in @var{names}.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(and @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])\nEvaluate each condition @var{conditionN} one at a time; if any\nexpansion results in the empty string substitute the empty string.  If\nall expansions result in a non-empty string, substitute the expansion\nof the last @var{condition}.@*\n@xref{Conditional Functions, ,Functions for Conditionals}.\n\n@item $(basename @var{names}@dots{})\nExtract the base name (name without suffix) of each file name.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(call @var{var},@var{param},@dots{})\nEvaluate the variable @var{var} replacing any references to @code{$(1)},\n@code{$(2)} with the first, second, etc.@: @var{param} values.@*\n@xref{Call Function, ,The @code{call} Function}.\n\n@item $(dir @var{names}@dots{})\nExtract the directory part of each file name.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(error @var{text}@dots{})\nWhen this function is expanded, @code{make} prints @var{text} to standard\nerror, then @code{make} exits with a failure code.@*\n@xref{Make Control Functions, ,Functions That Control Make}.\n\n@item $(eval @var{text})\nEvaluate @var{text} then read the results as makefile commands.\nExpands to the empty string.@*\n@xref{Eval Function, ,The @code{eval} Function}.\n\n@item $(file @var{op} @var{filename},@var{text})\nExpand the arguments, then open the file @var{filename} using mode\n@var{op} and write @var{text} to that file.@*\n@xref{File Function, ,The @code{file} Function}.\n\n@item $(filter @var{pattern}@dots{},@var{text})\nSelect words in @var{text} that match one of the @var{pattern} words.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(filter-out @var{pattern}@dots{},@var{text})\nSelect words in @var{text} that @emph{do not} match any of the @var{pattern}\nwords.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(findstring @var{find},@var{text})\nLocate @var{find} in @var{text}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(firstword @var{names}@dots{})\nExtract the first word of @var{names}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(flavor @var{variable})\nReturn a string describing the flavor of the @code{make} variable\n@var{variable}.@*\n@xref{Flavor Function, , The @code{flavor} Function}.\n\n@item $(foreach @var{var},@var{words},@var{text})\nEvaluate @var{text} with @var{var} bound to each word in @var{words},\nand concatenate the results.@*\n@xref{Foreach Function, ,The @code{foreach} Function}.\n\n@item $(if @var{condition},@var{then-part}[,@var{else-part}])\nEvaluate the condition @var{condition}; if it's non-empty substitute\nthe expansion of the @var{then-part} otherwise substitute the\nexpansion of the @var{else-part}.@*\n@xref{Conditional Functions, ,Functions for Conditionals}.\n\n@item $(info @var{text}@dots{})\nWhen this function is expanded, @code{make} prints @var{text} to standard\noutput and the function expands to the empty string.@*\n@xref{Make Control Functions, ,Functions That Control Make}.\n\n@item $(intcmp @var{lhs},@var{rhs}[,@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]])\nCompare @var{lhs} and @var{rhs} numerically; substitute the expansion of\n@var{lt-part}, @var{eq-part}, or @var{gt-part} depending on whether the\nleft-hand side is less-than, equal-to, or greater-than the right-hand side,\nrespectively.@*\n@xref{Conditional Functions, ,Functions for Conditionals}.\n\n@item $(join @var{list1},@var{list2})\nJoin two parallel lists of words.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(lastword @var{names}@dots{})\nExtract the last word of @var{names}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(let @var{var} [@var{var} ...],@var{words},@var{text})\nEvaluate @var{text} with the @var{var}s bound to the words in\n@var{words}.@*\n@xref{Let Function, ,The @code{let} Function}.\n\n@item $(notdir @var{names}@dots{})\nExtract the non-directory part of each file name.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(or @var{condition1}[,@var{condition2}[,@var{condition3}@dots{}]])\nEvaluate each condition @var{conditionN} one at a time; substitute the\nfirst non-empty expansion.  If all expansions are empty, substitute\nthe empty string.@*\n@xref{Conditional Functions, ,Functions for Conditionals}.\n\n@item $(origin @var{variable})\nReturn a string describing how the @code{make} variable @var{variable} was\ndefined.@*\n@xref{Origin Function, , The @code{origin} Function}.\n\n@item $(patsubst @var{pattern},@var{replacement},@var{text})\nReplace words matching @var{pattern} with @var{replacement} in @var{text}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(realpath @var{names}@dots{})\nFor each file name in @var{names}, expand to an absolute name that does not\ncontain any @code{.}, @code{..}, nor symlinks.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(shell @var{command})\nExecute a shell command and expand to its standard output.@*\n@xref{Shell Function, , The @code{shell} Function}.\n\n@item $(sort @var{list})\nSort the words in @var{list} lexicographically, removing duplicates.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(strip @var{string})\nRemove excess whitespace characters from @var{string}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(subst @var{from},@var{to},@var{text})\nReplace @var{from} with @var{to} in @var{text}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(suffix @var{names}@dots{})\nExtract the suffix (the last @samp{.} and following characters) of each file\nname.@*\n@xref{File Name Functions, ,Functions for File Names}.\n\n@item $(value @var{var})\nEvaluates to the contents of the variable @var{var}, with no expansion\nperformed on it.@*\n@xref{Value Function, ,The @code{value} Function}.\n\n@item $(warning @var{text}@dots{})\nWhen this function is expanded, @code{make} prints @var{text} to standard\nerror, prefixed with the current filename and line number.@*\n@xref{Make Control Functions, ,Functions That Control Make}.\n\n@item $(wildcard @var{pattern}@dots{})\nFind file names matching a shell file name pattern (@emph{not} a @samp{%}\npattern).@*\n@xref{Wildcard Function, ,The Function @code{wildcard}}.\n\n@item $(word @var{n},@var{text})\nExtract the @var{n}th word (one-origin) of @var{text}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(wordlist @var{s},@var{e},@var{text})\nReturns the list of words in @var{text} from @var{s} to @var{e}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n\n@item $(words @var{text})\nCount the number of words in @var{text}.@*\n@xref{Text Functions, , Functions for String Substitution and Analysis}.\n@end table\n\n@node Automatic Variable Reference\n@appendixsec Automatic Variable Reference\n\nHere is a summary of the automatic variables.  Remember automatic variables\n@emph{only} have values @emph{inside} a recipe.  @xref{Automatic Variables},\nfor full information.\n\n@table @code\n@item $@@\nThe file name of the target.\n\n@item $%\nThe target member name, when the target is an archive member.\n\n@item $<\nThe name of the first prerequisite.\n\n@item $?\nThe names of all the prerequisites that are\nnewer than the target, with spaces between them.\nFor prerequisites which are archive members, only\nthe named member is used (@pxref{Archives}).\n\n@item $^\n@itemx $+\nThe names of all the prerequisites, with spaces between them.  For\nprerequisites which are archive members, only the named member is used\n(@pxref{Archives}).  The value of @code{$^} omits duplicate\nprerequisites, while @code{$+} retains them and preserves their order.\n\n@item $*\nThe stem with which an implicit rule matches\n(@pxref{Pattern Match, ,How Patterns Match}).\n\n@item $(@@D)\n@itemx $(@@F)\nThe directory part and the file-within-directory part of @code{$@@}.\n\n@item $(*D)\n@itemx $(*F)\nThe directory part and the file-within-directory part of @code{$*}.\n\n@item $(%D)\n@itemx $(%F)\nThe directory part and the file-within-directory part of @code{$%}.\n\n@item $(<D)\n@itemx $(<F)\nThe directory part and the file-within-directory part of @code{$<}.\n\n@item $(^D)\n@itemx $(^F)\nThe directory part and the file-within-directory part of @code{$^}.\n\n@item $(+D)\n@itemx $(+F)\nThe directory part and the file-within-directory part of @code{$+}.\n\n@item $(?D)\n@itemx $(?F)\nThe directory part and the file-within-directory part of @code{$?}.\n@end table\n\n@node Special Variable Reference\n@appendixsec Special Variable Reference\n\nThese variables are used specially by GNU @code{make}:\n\n@table @code\n@item CURDIR\nSet to the absolute pathname of the current working directory (after\nall @code{-C} options are processed, if any).  Setting this variable\nhas no effect on the operation of @code{make}.@*\n@xref{Recursion, ,Recursive Use of @code{make}}.\n\n@item GNUMAKEFLAGS\nOther flags parsed by @code{make}.  You can set this in the environment or a\nmakefile to set @code{make} command-line flags.  This variable is only needed\nif you'd like to set GNU @code{make}-specific flags in a POSIX-compliant\nmakefile.  This variable will be seen by GNU @code{make} and ignored by other\n@code{make} implementations.  It's not needed if you only use GNU @code{make};\njust use @code{MAKEFLAGS} directly.@* @xref{Options/Recursion, ,Communicating\nOptions to a Sub-@code{make}}.\n\n@item .LIBPATTERNS\nDefines the naming of the libraries @code{make} searches for, and their\norder.@*\n@xref{Libraries/Search, ,Directory Search for Link Libraries}.\n\n@item MAKE\nThe name with which @code{make} was invoked.  Using this variable in\nrecipes has special meaning.@*\n@xref{MAKE Variable, ,How the @code{MAKE} Variable Works}.\n\n@item MAKECMDGOALS\nThe targets given to @code{make} on the command line.  Setting this\nvariable has no effect on the operation of @code{make}.@*\n@xref{Goals, ,Arguments to Specify the Goals}.\n\n@item MAKEFILES\nMakefiles to be read on every invocation of @code{make}.@*\n@xref{MAKEFILES Variable, ,The Variable @code{MAKEFILES}}.\n\n@item MAKEFLAGS\nThe flags given to @code{make}.  You can set this in the environment or\na makefile to set flags.@*\n@xref{Options/Recursion, ,Communicating Options to a Sub-@code{make}}.\n\nDon't use @code{MAKEFLAGS} explicitly in a recipe line: its contents may not\nbe quoted correctly for use in the shell.  Always allow recursive @code{make}\ninvocations to obtain these values through the environment from its parent.\n\n@item MAKELEVEL\nThe number of levels of recursion (sub-@code{make}s).@*\n@xref{Variables/Recursion}.\n\n@item MAKESHELL\nOn MS-DOS only, the name of the command interpreter that is to be used\nby @code{make}.  This value takes precedence over the value of\n@code{SHELL}.@*\n@xref{Choosing the Shell}.\n\n@item MAKE_VERSION\nThe built-in variable @samp{MAKE_VERSION} expands to the version\nnumber of the GNU @code{make} program.\n@vindex MAKE_VERSION\n\n@item MAKE_HOST\nThe built-in variable @samp{MAKE_HOST} expands to a string\nrepresenting the host that GNU @code{make} was built to run on.\n@vindex MAKE_HOST\n\n@item SHELL\nThe name of the system default command interpreter, usually @file{/bin/sh}.\nYou can set @code{SHELL} in the makefile to change the shell used to run\nrecipes.  @xref{Execution, ,Recipe Execution}.  The @code{SHELL}\nvariable is handled specially when importing from and exporting to the\nenvironment.@*\n@xref{Choosing the Shell}.\n\n@item SUFFIXES\nThe default list of suffixes before @code{make} reads any makefiles.@*\n@xref{Suffix Rules, ,Old-Fashioned Suffix Rules}.\n\n@item VPATH\nDirectory search path for files not found in the current directory.@*\n@xref{General Search, , @code{VPATH} Search Path for All Prerequisites}.\n@end table\n\n@node Error Messages\n@comment  node-name,  next,  previous,  up\n@appendix Errors Generated by Make\n\nHere is a list of the more common errors you might see generated by\n@code{make}, and some information about what they mean and how to fix\nthem.\n\nSometimes @code{make} errors are not fatal, especially in the presence\nof a @code{-} prefix on a recipe line, or the @code{-k} command line\noption.  Errors that are fatal are prefixed with the string\n@code{***}.\n\nError messages are all either prefixed with the name of the program\n(usually @samp{make}), or, if the error is found in a makefile, the name\nof the file and line number containing the problem.\n\nIn the table below, these common prefixes are left off.\n\n@table @samp\n\n@item [@var{foo}] Error @var{NN}\n@itemx [@var{foo}] @var{signal description}\nThese errors are not really @code{make} errors at all.  They mean that a\nprogram that @code{make} invoked as part of a recipe returned a\nnon-0 error code (@samp{Error @var{NN}}), which @code{make} interprets\nas failure, or it exited in some other abnormal fashion (with a\nsignal of some type).  @xref{Errors, ,Errors in Recipes}.\n\nIf no @code{***} is attached to the message, then the sub-process failed\nbut the rule in the makefile was prefixed with the @code{-} special\ncharacter, so @code{make} ignored the error.\n\n@item missing separator.  Stop.\n@itemx missing separator (did you mean TAB instead of 8 spaces?).  Stop.\nThis means that @code{make} could not understand much of anything\nabout the makefile line it just read.  GNU @code{make} looks for\nvarious separators (@code{:}, @code{=}, recipe prefix characters,\netc.) to indicate what kind of line it's parsing.  This message means\nit couldn't find a valid one.\n\nOne of the most common reasons for this message is that you (or\nperhaps your oh-so-helpful editor, as is the case with many MS-Windows\neditors) have attempted to indent your recipe lines with spaces\ninstead of a tab character.  In this case, @code{make} will use the\nsecond form of the error above.  Remember that every line in the\nrecipe must begin with a tab character (unless you set\n@code{.RECIPEPREFIX}; @pxref{Special Variables}).  Eight spaces do not\ncount.  @xref{Rule Syntax}.\n\n@item recipe commences before first target.  Stop.\n@itemx missing rule before recipe.  Stop.\nThis means the first thing in the makefile seems to be part of a\nrecipe: it begins with a recipe prefix character and doesn't appear to\nbe a legal @code{make} directive (such as a variable assignment).\nRecipes must always be associated with a target.\n\nThe second form is generated if the line has a semicolon as the first\nnon-whitespace character; @code{make} interprets this to mean you left\nout the \"target: prerequisite\" section of a rule.  @xref{Rule Syntax}.\n\n@item No rule to make target `@var{xxx}'.\n@itemx No rule to make target `@var{xxx}', needed by `@var{yyy}'.\nThis means that @code{make} decided it needed to build a target, but\nthen couldn't find any instructions in the makefile on how to do that,\neither explicit or implicit (including in the default rules database).\n\nIf you want that file to be built, you will need to add a rule to your\nmakefile describing how that target can be built.  Other possible\nsources of this problem are typos in the makefile (if that file name is\nwrong) or a corrupted source tree (if that file is not supposed to be\nbuilt, but rather only a prerequisite).\n\n@item No targets specified and no makefile found.  Stop.\n@itemx No targets.  Stop.\nThe former means that you didn't provide any targets to be built on the\ncommand line, and @code{make} couldn't find any makefiles to read in.\nThe latter means that some makefile was found, but it didn't contain any\ndefault goal and none was given on the command line.  GNU @code{make}\nhas nothing to do in these situations.\n@xref{Makefile Arguments, ,Arguments to Specify the Makefile}.\n\n@item Makefile `@var{xxx}' was not found.\n@itemx Included makefile `@var{xxx}' was not found.\nA makefile specified on the command line (first form) or included\n(second form) was not found.\n\n@item warning: overriding recipe for target `@var{xxx}'\n@itemx warning: ignoring old recipe for target `@var{xxx}'\nGNU @code{make} allows only one recipe to be specified per target\n(except for double-colon rules).  If you give a recipe for a target\nwhich already has been defined to have one, this warning is issued and\nthe second recipe will overwrite the first.  @xref{Multiple Rules,\n,Multiple Rules for One Target}.\n\n@item Circular @var{xxx} <- @var{yyy} dependency dropped.\nThis means that @code{make} detected a loop in the dependency graph:\nafter tracing the prerequisite @var{yyy} of target @var{xxx}, and its\nprerequisites, etc., one of them depended on @var{xxx} again.\n\n@item Recursive variable `@var{xxx}' references itself (eventually).  Stop.\nThis means you've defined a normal (recursive) @code{make} variable\n@var{xxx} that, when it's expanded, will refer to itself (@var{xxx}).\nThis is not allowed; either use simply-expanded variables (@samp{:=}\nor @samp{::=}) or use the append operator (@samp{+=}).  @xref{Using\nVariables, ,How to Use Variables}.\n\n@item Unterminated variable reference.  Stop.\nThis means you forgot to provide the proper closing parenthesis\nor brace in your variable or function reference.\n\n@item insufficient arguments to function `@var{xxx}'.  Stop.\nThis means you haven't provided the requisite number of arguments for\nthis function.  See the documentation of the function for a description\nof its arguments.  @xref{Functions, ,Functions for Transforming Text}.\n\n@item missing target pattern.  Stop.\n@itemx multiple target patterns.  Stop.\n@itemx target pattern contains no `%'.  Stop.\n@itemx mixed implicit and static pattern rules.  Stop.\nThese errors are generated for malformed static pattern rules\n(@pxref{Static Usage, ,Syntax of Static Pattern Rules}).  The first\nmeans the target-pattern part of the rule is empty; the second means\nthere are multiple pattern characters (@code{%}) in the target-pattern\npart; the third means there are no pattern characters in the\ntarget-pattern part; and the fourth means that all three parts of the\nstatic pattern rule contain pattern characters (@code{%})--the first\npart should not contain pattern characters.\n\nIf you see these errors and you aren't trying to create a static\npattern rule, check the value of any variables in your target and\nprerequisite lists to be sure they do not contain colons.\n\n@item warning: -jN forced in submake: disabling jobserver mode.\nThis warning and the next are generated if @code{make} detects error\nconditions related to parallel processing on systems where\nsub-@code{make}s can communicate (@pxref{Options/Recursion,\n,Communicating Options to a Sub-@code{make}}).  This warning is\ngenerated if a recursive invocation of a @code{make} process is forced\nto have @samp{-j@var{N}} in its argument list (where @var{N} is greater\nthan one).  This could happen, for example, if you set the @code{MAKE}\nenvironment variable to @samp{make -j2}.  In this case, the\nsub-@code{make} doesn't communicate with other @code{make} processes and\nwill simply pretend it has two jobs of its own.\n\n@item warning: jobserver unavailable: using -j1.  Add `+' to parent make rule.\nIn order for @code{make} processes to communicate, the parent will pass\ninformation to the child.  Since this could result in problems if the\nchild process isn't actually a @code{make}, the parent will only do this\nif it thinks the child is a @code{make}.  The parent uses the normal\nalgorithms to determine this (@pxref{MAKE Variable, ,How the @code{MAKE}\nVariable Works}).  If the makefile is constructed such that the parent\ndoesn't know the child is a @code{make} process, then the child will\nreceive only part of the information necessary.  In this case, the child\nwill generate this warning message and proceed with its build in a\nsequential manner.\n\n@item warning: ignoring prerequisites on suffix rule definition\nAccording to POSIX, a suffix rule cannot contain prerequisites.  If a rule\nthat could be a suffix rule has prerequisites it is interpreted as a simple\nexplicit rule, with an odd target name.  This requirement is obeyed when\nPOSIX-conforming mode is enabled (the @code{.POSIX} target is defined).  In\nversions of GNU @code{make} prior to 4.3, no warning was emitted and a\nsuffix rule was created, however all prerequisites were ignored and were not\npart of the suffix rule.  Starting with GNU @code{make} 4.3 the behavior is\nthe same, and in addition this warning is generated.  In a future version\nthe POSIX-conforming behavior will be the only behavior: no rule with a\nprerequisite can be a suffix rule and this warning will be removed.\n\n@end table\n\n@node Troubleshooting\n@appendix Troubleshooting Make and Makefiles\n\nTroubleshooting @code{make} and makefiles can be tricky.  There are two\nreasons: first, makefiles are not procedural programs and many users are used\nto procedural languages and scripts.  Second, makefiles consist of two\ndifferent syntaxes in one file: makefile syntax, that @code{make} reads, and\nshell syntax, which is sent to a shell program for parsing and execution.\n\nIf you have problems with GNU Make, first consider the type of problem you are\nhaving.  Problems will generally be in one of these categories:\n\n@itemize @bullet\n@item\nA syntax or other error was reported when @code{make} attempted to parse your\nmakefiles.\n\n@item\nA command that @code{make} invoked failed (exited with a non-0 exit code).\n\n@item\nThe command that @code{make} invoked was not the one you expected.\n\n@item\n@code{make} was not able to find a rule to build a target.\n\n@item\n@code{make} rebuilds a target that you didn't think was out of date.\n\n@item\nOr, @code{make} did not rebuild a target that you expected it to build.\n@end itemize\n\nThe strategies for troubleshooting differ for different types of problems.\nFor issues related to how makefiles are parsed, strategies include:\n\n@itemize @bullet\n@item\nUsing the @samp{-p} option to show the makefile database, after evaluation\n(@pxref{Options Summary, ,Summary of Options}).\n\n@item\nUsing the @code{info} or @code{warning} functions to understand how elements\nof the makefile are expanded (@pxref{Make Control Functions, ,Functions That\nControl Make}).\n@end itemize\n\nFor issues related to how rules are applied, strategies include:\n\n@itemize @bullet\n@item\nUsing the @samp{-n} or @samp{--trace} options to show the commands that\n@code{make} ran, and to explain which rules @code{make} invokes and why\n(@pxref{Options Summary, ,Summary of Options}).\n\n@item\nUsing the @samp{--debug=v,i} or full @samp{-d} options to show how @code{make}\nis determining which recipes should be used, or why targets do not need to be\nrebuilt (@pxref{Options Summary, ,Summary of Options}).\n@end itemize\n\n@menu\n* Parse Error::                 Syntax errors when parsing makefiles.\n* Command Failure::             Recipe commands exit with error codes.\n* Wrong Rule::                  @code{make} chooses the wrong rule.\n* No Rule Found::               No rule was found to build a target.\n* Extra Rebuilds::              Targets are rebuilt unnecessarily.\n* Missing Rebuilds::            Out-of-date targets are not rebuilt.\n* Troubleshooting Strategies::  Strategies used for troubleshooting issues.\n@end menu\n\n@node Parse Error\n@appendixsec Errors When Parsing Makefiles\n\nThis type of error is the simplest to resolve.  The error output you will see\nwill have a format like this:\n\n@example\nMakefile:10: *** missing separator.  Stop.\n@end example\n\nThis message gives you all the information you need to address the error: it\ngives the name of the makefile (here @samp{Makefile}) and the line number\n(here @samp{10}) in that makefile where GNU Make's parser failed.  Following\nthat is a description of the error.  Further explanations of these error\nmessages can be found in @ref{Error Messages, ,Errors Generated by Make}.\n\n@node Command Failure\n@appendixsec Errors Reported by Commands\n\nIf GNU Make parses the makefiles correctly and runs a command to rebuild a\ntarget, it expects that command to exit with an error code of @samp{0} (for\nsuccess).  Any other exit code will be reported by @code{make} as a failure\nand will generate an error message with this form:\n\n@example\nmake: *** [Makefile:10: target] Error 2\n@end example\n\nAll the information you need to find that command are given: the name of the\nmakefile (here @samp{Makefile}) and line number (here @samp{10}) of the\ncommand make invoked, the target (here @samp{target}) that make was trying to\nbuild, and finally the exit code of the command (here @samp{2}).\n\nThe precise meaning of the error code is different for different commands: you\nmust consult the documentation of the command that failed to interpret it.\nHowever there are some reasons for error codes:\n\n@table @samp\n@item 2\nIf the shell fails to parse your command (invalid shell syntax) it will exit\nwith a code of @samp{2}.  On Windows this can also mean that the command was\nnot found.\n\n@item 127\nIf the command you wanted to run was not found, the shell will exit with a\ncode of @samp{127}.\n@end table\n\nTo troubleshoot these errors (@pxref{Troubleshooting Strategies, ,Strategies\nfor Troubleshooting}), use the @samp{-n} or @samp{--trace} options so you can\nsee the complete command line being invoked.\n\nThan, examine the output of the command that @code{make} invoked to determine\nwhat went wrong and why: this output will appear @emph{before} the above error\nmessage.  The error may be due to an incorrect command line in which case the\nerror is in the way your command was written in the makefile, but it's far\nmore likely to be a problem with something outside of the makefile (for\nexample, a syntax error in the code you are trying to compile).\n\n@node Wrong Rule\n@appendixsec Choosing the Wrong Rule\n\nIf @code{make} seems to be invoking a different command than the one you\nintended, it could be that the wrong rule is being chosen.\n\nTo troubleshoot these errors (@pxref{Troubleshooting Strategies, ,Strategies\nfor Troubleshooting}), add the @samp{--trace} option to the @code{make}\ncommand line.  This shows the rule that was chosen.\n\nYou can also use the @samp{--debug=v,i} or the full @samp{-d} option to\ndetermine how @code{make} decided to use that rule.\n\n@node No Rule Found\n@appendixsec No Rule to Build A Target\n\nIf @code{make} cannot locate a rule to build a target that you requested,\neither via the command line or as a prerequisite of another target, it shows\nan error such as:\n\n@example\nmake: *** No rule to make target 'aprogram'.  Stop.\n@end example\n\nIf the makefile doesn't provide a rule for this target, you can add one.  If\nthere is a rule which you intended @code{make} to use to build this target and\nit wasn't used, the most common reasons for this are:\n\n@itemize @bullet\n@item\nThe target was misspelled.  You should consider following the @dfn{DRY}\nprinciple (Don't Repeat Yourself) by assigning file names (targets and\nprerequisites) to makefile variables and using those variables rather than\nretyping the file names.\n\n@item\nThe target is in a different directory.  @code{make} considers @samp{target}\nand @samp{dir/target} (for example) to be different targets.  If you are using\nrules that create files outside of the current working directory, be sure you\ncorrectly prefix them with their directories everywhere that they appear in\nthe makefile.\n\n@item\nA pattern rule didn't match because one of its prerequisites cannot be built.\nPattern rules will only be used when @strong{all} prerequisites can be\nsatisfied: either they exist already or @code{make} can find a way to build\nthem.  If any prerequisite cannot be created, then the pattern does not match\nand @code{make} will continue looking for another matching pattern.  If no\nmatching pattern can be found, then @code{make} will fail.\n@end itemize\n\nTo troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies\nfor Troubleshooting}), run @code{make} with the @samp{--debug=v,i} option, or\nthe full @samp{-d} option, and examine the detailed output.\n\nIf the definition of the rule in your makefile is complicated, you can use the\n@samp{-p} option to ask make to print its internal database of rules to ensure\nthey are correct, or as a last resort add invocations of the @code{info} or\n@code{warning} functions to show what steps @code{make} is taking during\nevaluation.\n\n@node Extra Rebuilds\n@appendixsec Unwanted Rebuilding of Targets\n\nIf @code{make} is rebuilding a target which you feel is already up to date and\ndoesn't need to be rebuilt, there can be a number of reasons:\n\n@itemize @bullet\n@item\nThe recipe does not update the target.  A makefile rule is a promise to\n@code{make} that if it invokes the recipe, the target will be updated.  The\nfile which @code{make} expects to be updated is placed in the @samp{$@@}\nvariable.  If the recipe doesn't update this file, and @emph{exactly} this\nfile, then the next time @code{make} is invoked it will try to re-build that\ntarget again.\n\n@item\nA prerequisite is marked as phony (@pxref{Special Targets, ,Special Built-in\nTarget Names}).  All phony targets are always considered out of date, and so\nany targets depending on them are also out of date.\n\n@item\nA directory is used as a prerequisite.  Directories are not treated specially\nby @code{make}: if their modification time is newer than the target then the\ntarget is considered out of date and rebuilt.  Since directory modification\ntimes are changed whenever a file is created, deleted, or renamed in that\ndirectory, it means targets depending on the directory will be considered out\nof date whenever a file is created, deleted, or renamed in that directory.\n\n@item\nSomething is deleting the target file.  Of course if a file does not exist it\nis always considered out of date (see the first item above).  If something in\nyour environment, either inside the @samp{makefile} or outside if it, is\ndeleting the target file then @code{make} will always rebuild it.\n\n@item\nThe target is created with a ``too-old'' modification time.  If the recipe\ncreates the target with a modification time in the past, then it may still be\nout of date with respect to its prerequisites.  This could happen if, for\nexample, you are extracting files from an archive or copying them from another\nlocation and the tool used to do the extraction or copying preserves the\noriginal file's modification time.\n@end itemize\n\nTo troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies\nfor Troubleshooting}), use the @samp{--trace} option to understand why\n@code{make} decides to build a target and see the full command used.\n\n@node Missing Rebuilds\n@appendixsec Out-of-Date Targets Not Rebuilt\n\nThe opposite of the previous problem is @code{make} not rebuilding targets\nthat you think should be rebuilt.  Some reasons for this might be:\n\n@itemize @bullet\n@item\nThe target is not being considered.  Unless the command line specifies\notherwise, @code{make} will only consider the first target in the makefile and\nits prerequisites.  If the target you expected to be built is not one of\nthese, then @code{make} won't build it.\n\n@item\nA different file is being built instead.  Be sure that your target is the file\nyou want to be built (including any directory prefix!) and that the recipe\nwill create the file listed as @samp{$@@}.  Also consider the directory that\n@code{make} is running in and whether relative pathnames are the ones you\nexpect.\n@end itemize\n\nTo troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies\nfor Troubleshooting}), use the @samp{-n} or @samp{--trace} option to see what\ncommand is being invoked.\n\nYou can also use the @samp{--debug=v,i} option or the full @samp{-d} option to\nobtain a complete description of everything @code{make} considered and why it\ndecided to build or not build every target.\n\n@node Troubleshooting Strategies\n@appendixsec Strategies for Troubleshooting\n\nThe strategies for troubleshooting differ for different types of problems.\n\n@subheading Show the makefile database\n\nUse the @samp{-p} option to show the makefile database, after evaluation\n(@pxref{Options Summary, ,Summary of Options}).  This allows you to see how\n@code{make} has evaluated the variables and recipes in your makefile.\n\nThe @samp{-p} option asks GNU Make to print its internal database of rules,\nafter all makefiles have been parsed.  You might see output such as:\n\n@example\nprogram: prereq.o\n#  Implicit rule search has not been done.\n#  Modification time never checked.\n#  File has not been updated.\n#  recipe to execute (from 'Makefile', line 10):\n        $(CC) -o $@@ $^ $(LDFLAGS) $(LDLIBS)\n@end example\n\nHere we can see the target (here @samp{program}) and prerequisites (here\n@samp{prereq.o}) after variable expansion, as well as the location of the\ndefinition of the recipe for this rule (here, in @samp{Makefile} at line\n@samp{10}).\n\n@subheading Add @code{info} or @code{warning} calls\n\nThe @code{info} or @code{warning} function can help to understand how elements\nof the makefile are expanded (@pxref{Make Control Functions, ,Functions That\nControl Make}).\n\nAlthough their use requires modifying the makefile, these functions are a\npowerful tool for troubleshooting complex makefiles such as those using\n@code{eval} and @code{call} functions to dynamically generate rules.  For\nexample if your makefile contains:\n\n@example\n$(foreach T,$(TARGET),$(eval $(call makerule,$T,$($T_PREREQ))))\n@end example\n\n@noindent\nthen duplicating this line and replacing @code{eval} with @code{info} will\nshow exactly what content @code{make} will be evaluating:\n\n@example\n$(foreach T,$(TARGET),$(info $(call makerule,$T,$($T_PREREQ))))\n@end example\n\nThe @code{warning} function provides the same output as @code{info}, except\nthat each output line is prefixed with the filename and line number where the\n@code{warning} function is expanded, and that the output goes to the standard\nerror file descriptor and not to standard output.\n\n@subheading Use the @samp{--trace} or @samp{-n} option\n\nThe @samp{-n} option will show you which commands would be invoked to bring\ntargets up to date, without actually invoking them.  Commands are displayed\neven if the @samp{@@} prefix or the @code{.SILENT} target was specified\n(@pxref{Options Summary, ,Summary of Options}).\n\nUse the @samp{--trace} option on the @code{make} command line to explain which\nrules @code{make} invokes and why (@pxref{Options Summary, ,Summary of\nOptions}).  This option also overrides @samp{@@} recipe prefixes and the\n@code{.SILENT} special target and shows the expanded command line.\n\nAdding this will result in output like this for each target which is rebuilt:\n\n@example\nMakefile:10: update target 'program' due to: target does not exist\n@end example\n\n@noindent\nor:\n\n@example\nMakefile:10: update target 'program' due to: prereq.o\n@end example\n\nThis shows the filename of the makefile (here @samp{Makefile}) and line number\n(here @samp{10}), along with the name of the target (here @samp{program}) and\nthe reason why it was rebuilt: in the first example because the target does\nnot exist, and in the second example because there were prerequisites (here,\n@samp{prereq.o}) that were newer than the target.  All newer prerequisites\nwould be listed here.\n\nAfter this information, the expanded command line make invoked will be shown,\njust as it is passed to the shell.  You should examine it carefully to\ndetermine whether it's correct, and compare it to the pre-expansion recipe in\nthe makefile to see what aspect of the recipe might be incorrect.\n\n@subheading Use the @samp{--debug=v,i} or @samp{-d} option\n\nUse the @samp{--debug=v,i}, or the full @samp{-d}, options to show how\n@code{make} is determining which recipes should be used, or why targets do not\nneed to be rebuilt (@pxref{Options Summary, ,Summary of Options}).\n\nThe amount of output generated by these options can be daunting, but\nredirecting the output to a file then searching it for the target you are\nconcerned with will show you exactly what steps GNU Make took when considering\nthis target, and why it decided to build, or not build, that target.\n\nIf the issue is that @code{make} decides @emph{not} to rebuild the target when\nyou think it should, this may be your only recourse since @samp{--trace} only\nshows why targets are considered out of date.\n\n@node Complex Makefile\n@appendix Complex Makefile Example\n\nHere is the makefile for the GNU @code{tar} program.  This is a\nmoderately complex makefile.  The first line uses a @code{#!} setting\nto allow the makefile to be executed directly.\n\nBecause it is the first target, the default goal is @samp{all}.  An\ninteresting feature of this makefile is that @file{testpad.h} is a\nsource file automatically created by the @code{testpad} program,\nitself compiled from @file{testpad.c}.\n\nIf you type @samp{make} or @samp{make all}, then @code{make} creates\nthe @file{tar} executable, the @file{rmt} daemon that provides\nremote tape access, and the @file{tar.info} Info file.\n\nIf you type @samp{make install}, then @code{make} not only creates\n@file{tar}, @file{rmt}, and @file{tar.info}, but also installs\nthem.\n\nIf you type @samp{make clean}, then @code{make} removes the @samp{.o}\nfiles, and the @file{tar}, @file{rmt}, @file{testpad},\n@file{testpad.h}, and @file{core} files.\n\nIf you type @samp{make distclean}, then @code{make} not only removes\nthe same files as does @samp{make clean} but also the\n@file{TAGS}, @file{Makefile}, and @file{config.status} files.\n(Although it is not evident, this makefile (and\n@file{config.status}) is generated by the user with the\n@code{configure} program, which is provided in the @code{tar}\ndistribution, but is not shown here.)\n\nIf you type @samp{make realclean}, then @code{make} removes the same\nfiles as does @samp{make distclean} and also removes the Info files\ngenerated from @file{tar.texinfo}.\n\nIn addition, there are targets @code{shar} and @code{dist} that create\ndistribution kits.\n\n@example\n@group\n#!/usr/bin/make -f\n# Generated automatically from Makefile.in by configure.\n# Un*x Makefile for GNU tar program.\n# Copyright (C) 1991 Free Software Foundation, Inc.\n@end group\n\n@group\n# This program is free software; you can redistribute\n# it and/or modify it under the terms of the GNU\n# General Public License @dots{}\n@dots{}\n@dots{}\n@end group\n\nSHELL = /bin/sh\n\n#### Start of system configuration section. ####\n\nsrcdir = .\n\n@group\n# If you use gcc, you should either run the\n# fixincludes script that comes with it or else use\n# gcc with the -traditional option.  Otherwise ioctl\n# calls will be compiled incorrectly on some systems.\nCC = gcc -O\nYACC = bison -y\nINSTALL = /usr/local/bin/install -c\nINSTALLDATA = /usr/local/bin/install -c -m 644\n@end group\n\n# Things you might add to DEFS:\n# -DSTDC_HEADERS        If you have ANSI C headers and\n#                       libraries.\n# -DPOSIX               If you have POSIX.1 headers and\n#                       libraries.\n# -DBSD42               If you have sys/dir.h (unless\n#                       you use -DPOSIX), sys/file.h,\n#                       and st_blocks in `struct stat'.\n# -DUSG                 If you have System V/ANSI C\n#                       string and memory functions\n#                       and headers, sys/sysmacros.h,\n#                       fcntl.h, getcwd, no valloc,\n#                       and ndir.h (unless\n#                       you use -DDIRENT).\n# -DNO_MEMORY_H         If USG or STDC_HEADERS but do not\n#                       include memory.h.\n# -DDIRENT              If USG and you have dirent.h\n#                       instead of ndir.h.\n# -DSIGTYPE=int         If your signal handlers\n#                       return int, not void.\n# -DNO_MTIO             If you lack sys/mtio.h\n#                       (magtape ioctls).\n# -DNO_REMOTE           If you do not have a remote shell\n#                       or rexec.\n# -DUSE_REXEC           To use rexec for remote tape\n#                       operations instead of\n#                       forking rsh or remsh.\n# -DVPRINTF_MISSING     If you lack vprintf function\n#                       (but have _doprnt).\n# -DDOPRNT_MISSING      If you lack _doprnt function.\n#                       Also need to define\n#                       -DVPRINTF_MISSING.\n# -DFTIME_MISSING       If you lack ftime system call.\n# -DSTRSTR_MISSING      If you lack strstr function.\n# -DVALLOC_MISSING      If you lack valloc function.\n# -DMKDIR_MISSING       If you lack mkdir and\n#                       rmdir system calls.\n# -DRENAME_MISSING      If you lack rename system call.\n# -DFTRUNCATE_MISSING   If you lack ftruncate\n#                       system call.\n# -DV7                  On Version 7 Unix (not\n#                       tested in a long time).\n# -DEMUL_OPEN3          If you lack a 3-argument version\n#                       of open, and want to emulate it\n#                       with system calls you do have.\n# -DNO_OPEN3            If you lack the 3-argument open\n#                       and want to disable the tar -k\n#                       option instead of emulating open.\n# -DXENIX               If you have sys/inode.h\n#                       and need it 94 to be included.\n\nDEFS =  -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \\\n        -DVPRINTF_MISSING -DBSD42\n# Set this to rtapelib.o unless you defined NO_REMOTE,\n# in which case make it empty.\nRTAPELIB = rtapelib.o\nLIBS =\nDEF_AR_FILE = /dev/rmt8\nDEFBLOCKING = 20\n\n@group\nCDEBUG = -g\nCFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \\\n        -DDEF_AR_FILE=\\\"$(DEF_AR_FILE)\\\" \\\n        -DDEFBLOCKING=$(DEFBLOCKING)\nLDFLAGS = -g\n@end group\n\n@group\nprefix = /usr/local\n# Prefix for each installed program,\n# normally empty or `g'.\nbinprefix =\n\n# The directory to install tar in.\nbindir = $(prefix)/bin\n\n# The directory to install the info files in.\ninfodir = $(prefix)/info\n@end group\n\n#### End of system configuration section. ####\n\n@group\nSRCS_C  = tar.c create.c extract.c buffer.c   \\\n          getoldopt.c update.c gnu.c mangle.c \\\n          version.c list.c names.c diffarch.c \\\n          port.c wildmat.c getopt.c getopt1.c \\\n          regex.c\nSRCS_Y  = getdate.y\nSRCS    = $(SRCS_C) $(SRCS_Y)\nOBJS    = $(SRCS_C:.c=.o) $(SRCS_Y:.y=.o) $(RTAPELIB)\n@end group\n@group\nAUX =   README COPYING ChangeLog Makefile.in  \\\n        makefile.pc configure configure.in \\\n        tar.texinfo tar.info* texinfo.tex \\\n        tar.h port.h open3.h getopt.h regex.h \\\n        rmt.h rmt.c rtapelib.c alloca.c \\\n        msd_dir.h msd_dir.c tcexparg.c \\\n        level-0 level-1 backup-specs testpad.c\n@end group\n\n.PHONY: all\nall:    tar rmt tar.info\n\n@group\ntar:    $(OBJS)\n        $(CC) $(LDFLAGS) -o $@@ $(OBJS) $(LIBS)\n@end group\n\n@group\nrmt:    rmt.c\n        $(CC) $(CFLAGS) $(LDFLAGS) -o $@@ rmt.c\n@end group\n\n@group\ntar.info: tar.texinfo\n        makeinfo tar.texinfo\n@end group\n\n@group\n.PHONY: install\ninstall: all\n        $(INSTALL) tar $(bindir)/$(binprefix)tar\n        -test ! -f rmt || $(INSTALL) rmt /etc/rmt\n        $(INSTALLDATA) $(srcdir)/tar.info* $(infodir)\n@end group\n\n@group\n$(OBJS): tar.h port.h testpad.h\nregex.o buffer.o tar.o: regex.h\n# getdate.y has 8 shift/reduce conflicts.\n@end group\n\n@group\ntestpad.h: testpad\n        ./testpad\n@end group\n\n@group\ntestpad: testpad.o\n        $(CC) -o $@@ testpad.o\n@end group\n\n@group\nTAGS:   $(SRCS)\n        etags $(SRCS)\n@end group\n\n@group\n.PHONY: clean\nclean:\n        rm -f *.o tar rmt testpad testpad.h core\n@end group\n\n@group\n.PHONY: distclean\ndistclean: clean\n        rm -f TAGS Makefile config.status\n@end group\n\n@group\n.PHONY: realclean\nrealclean: distclean\n        rm -f tar.info*\n@end group\n\n@group\n.PHONY: shar\nshar: $(SRCS) $(AUX)\n        shar $(SRCS) $(AUX) | compress \\\n          > tar-`sed -e '/version_string/!d' \\\n                     -e 's/[^0-9.]*\\([0-9.]*\\).*/\\1/' \\\n                     -e q\n                     version.c`.shar.Z\n@end group\n\n@group\n.PHONY: dist\ndist: $(SRCS) $(AUX)\n        echo tar-`sed \\\n             -e '/version_string/!d' \\\n             -e 's/[^0-9.]*\\([0-9.]*\\).*/\\1/' \\\n             -e q\n             version.c` > .fname\n        -rm -rf `cat .fname`\n        mkdir `cat .fname`\n        ln $(SRCS) $(AUX) `cat .fname`\n        tar chZf `cat .fname`.tar.Z `cat .fname`\n        -rm -rf `cat .fname` .fname\n@end group\n\n@group\ntar.zoo: $(SRCS) $(AUX)\n        -rm -rf tmp.dir\n        -mkdir tmp.dir\n        -rm tar.zoo\n        for X in $(SRCS) $(AUX) ; do \\\n            echo $$X ; \\\n            sed 's/$$/^M/' $$X \\\n            > tmp.dir/$$X ; done\n        cd tmp.dir ; zoo aM ../tar.zoo *\n        -rm -rf tmp.dir\n@end group\n@end example\n\n@node GNU Free Documentation License\n@appendix GNU Free Documentation License\n@cindex FDL, GNU Free Documentation License\n@include fdl.texi\n\n@node Concept Index\n@unnumbered Index of Concepts\n\n@printindex cp\n\n@node Name Index\n@unnumbered Index of Functions, Variables, & Directives\n\n@printindex fn\n\n@bye\n\n@c Local Variables:\n@c eval: (setq fill-column 78)\n@c End:\n"
  },
  {
    "path": "gl/.gitignore",
    "content": "*~\n#*\n.#*\n.*cache\n*.diff\n*.patch\n*.orig\n*.rej\n*.out\n*.log\n"
  },
  {
    "path": "gl/lib/fnmatch.c",
    "content": "/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2023 Free Software\nFoundation, Inc.\nThis file is part of the GNU C Library.\n\nThis library is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Library General Public License as\npublished by the Free Software Foundation; either version 2 of the\nLicense, or (at your option) any later version.\n\nThis library is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLibrary General Public License for more details.\n\nYou should have received a copy of the GNU Library General Public License\nalong with this library; see the file COPYING.LIB.  If not, write to the Free\nSoftware Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301\nUSA.  */\n\n#if HAVE_CONFIG_H\n# include <config.h>\n#endif\n\n/* Enable GNU extensions in fnmatch.h.  */\n#ifndef _GNU_SOURCE\n# define _GNU_SOURCE\t1\n#endif\n\n#include <errno.h>\n#include <fnmatch.h>\n#include <ctype.h>\n\n#if HAVE_STRING_H || defined _LIBC\n# include <string.h>\n#else\n# include <strings.h>\n#endif\n\n#if defined STDC_HEADERS || defined _LIBC\n# include <stdlib.h>\n#endif\n\n/* For platform which support the ISO C amendement 1 functionality we\n   support user defined character classes.  */\n#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)\n/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */\n# include <wchar.h>\n# include <wctype.h>\n#endif\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#if defined _LIBC || !defined __GNU_LIBRARY__\n\n\n# if defined STDC_HEADERS || !defined isascii\n#  define ISASCII(c) 1\n# else\n#  define ISASCII(c) isascii(c)\n# endif\n\n# ifdef isblank\n#  define ISBLANK(c) (ISASCII (c) && isblank (c))\n# else\n#  define ISBLANK(c) ((c) == ' ' || (c) == '\\t')\n# endif\n# ifdef isgraph\n#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))\n# else\n#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))\n# endif\n\n# define ISPRINT(c) (ISASCII (c) && isprint (c))\n# define ISDIGIT(c) (ISASCII (c) && isdigit (c))\n# define ISALNUM(c) (ISASCII (c) && isalnum (c))\n# define ISALPHA(c) (ISASCII (c) && isalpha (c))\n# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))\n# define ISLOWER(c) (ISASCII (c) && islower (c))\n# define ISPUNCT(c) (ISASCII (c) && ispunct (c))\n# define ISSPACE(c) (ISASCII (c) && isspace (c))\n# define ISUPPER(c) (ISASCII (c) && isupper (c))\n# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))\n\n# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))\n\n# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)\n/* The GNU C library provides support for user-defined character classes\n   and the functions from ISO C amendement 1.  */\n#  ifdef CHARCLASS_NAME_MAX\n#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX\n#  else\n/* This shouldn't happen but some implementation might still have this\n   problem.  Use a reasonable default value.  */\n#   define CHAR_CLASS_MAX_LENGTH 256\n#  endif\n\n#  ifdef _LIBC\n#   define IS_CHAR_CLASS(string) __wctype (string)\n#  else\n#   define IS_CHAR_CLASS(string) wctype (string)\n#  endif\n# else\n#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */\n\n#  define IS_CHAR_CLASS(string)\t\t\t\t\t\t      \\\n   (STREQ (string, \"alpha\") || STREQ (string, \"upper\")\t\t\t      \\\n    || STREQ (string, \"lower\") || STREQ (string, \"digit\")\t\t      \\\n    || STREQ (string, \"alnum\") || STREQ (string, \"xdigit\")\t\t      \\\n    || STREQ (string, \"space\") || STREQ (string, \"print\")\t\t      \\\n    || STREQ (string, \"punct\") || STREQ (string, \"graph\")\t\t      \\\n    || STREQ (string, \"cntrl\") || STREQ (string, \"blank\"))\n# endif\n\n/* Avoid depending on library functions or files\n   whose names are inconsistent.  */\n\n# if !defined _LIBC && !defined getenv\nextern char *getenv ();\n# endif\n\n# ifndef errno\nextern int errno;\n# endif\n\n/* Match STRING against the filename pattern PATTERN, returning zero if\n   it matches, nonzero if not.  */\nstatic int\ninternal_fnmatch (const char *pattern, const char *string,\n\t\t  int no_leading_period, int flags)\n{\n  const char *p = pattern, *n = string;\n  unsigned char c;\n\n/* Note that this evaluates C many times.  */\n# ifdef _LIBC\n#  define FOLD(c) (unsigned char)((flags & FNM_CASEFOLD) ? tolower (c) : (c))\n# else\n#  define FOLD(c) (unsigned char)((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))\n# endif\n\n  while ((c = *p++) != '\\0')\n    {\n      c = FOLD (c);\n\n      switch (c)\n\t{\n\tcase '?':\n\t  if (*n == '\\0')\n\t    return FNM_NOMATCH;\n\t  else if (*n == '/' && (flags & FNM_FILE_NAME))\n\t    return FNM_NOMATCH;\n\t  else if (*n == '.' && no_leading_period\n\t\t   && (n == string\n\t\t       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))\n\t    return FNM_NOMATCH;\n\t  break;\n\n\tcase '\\\\':\n\t  if (!(flags & FNM_NOESCAPE))\n\t    {\n\t      c = *p++;\n\t      if (c == '\\0')\n\t\t/* Trailing \\ loses.  */\n\t\treturn FNM_NOMATCH;\n\t      c = FOLD (c);\n\t    }\n\t  if (FOLD ((unsigned char) *n) != c)\n\t    return FNM_NOMATCH;\n\t  break;\n\n\tcase '*':\n\t  if (*n == '.' && no_leading_period\n\t      && (n == string\n\t\t  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))\n\t    return FNM_NOMATCH;\n\n\t  for (c = *p++; c == '?' || c == '*'; c = *p++)\n\t    {\n\t      if (*n == '/' && (flags & FNM_FILE_NAME))\n\t\t/* A slash does not match a wildcard under FNM_FILE_NAME.  */\n\t\treturn FNM_NOMATCH;\n\t      else if (c == '?')\n\t\t{\n\t\t  /* A ? needs to match one character.  */\n\t\t  if (*n == '\\0')\n\t\t    /* There isn't another character; no match.  */\n\t\t    return FNM_NOMATCH;\n\t\t  else\n\t\t    /* One character of the string is consumed in matching\n\t\t       this ? wildcard, so *??? won't match if there are\n\t\t       less than three characters.  */\n\t\t    ++n;\n\t\t}\n\t    }\n\n\t  if (c == '\\0')\n\t    /* The wildcard(s) is/are the last element of the pattern.\n\t       If the name is a file name and contains another slash\n\t       this does mean it cannot match.  */\n\t    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL\n\t\t    ? FNM_NOMATCH : 0);\n\t  else\n\t    {\n\t      const char *endp;\n\n\t      endp = strchr (n, (flags & FNM_FILE_NAME) ? '/' : '\\0');\n\t      if (endp == NULL)\n\t\tendp = n + strlen (n);\n\n\t      if (c == '[')\n\t\t{\n\t\t  int flags2 = ((flags & FNM_FILE_NAME)\n\t\t\t\t? flags : (flags & ~FNM_PERIOD));\n\n\t\t  for (--p; n < endp; ++n)\n\t\t    if (internal_fnmatch (p, n,\n\t\t\t\t\t  (no_leading_period\n\t\t\t\t\t   && (n == string\n\t\t\t\t\t       || (n[-1] == '/'\n\t\t\t\t\t\t   && (flags\n\t\t\t\t\t\t       & FNM_FILE_NAME)))),\n\t\t\t\t\t  flags2)\n\t\t\t== 0)\n\t\t      return 0;\n\t\t}\n\t      else if (c == '/' && (flags & FNM_FILE_NAME))\n\t\t{\n\t\t  while (*n != '\\0' && *n != '/')\n\t\t    ++n;\n\t\t  if (*n == '/'\n\t\t      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,\n\t\t\t\t\t    flags) == 0))\n\t\t    return 0;\n\t\t}\n\t      else\n\t\t{\n\t\t  int flags2 = ((flags & FNM_FILE_NAME)\n\t\t\t\t? flags : (flags & ~FNM_PERIOD));\n\n\t\t  if (c == '\\\\' && !(flags & FNM_NOESCAPE))\n\t\t    c = *p;\n\t\t  c = FOLD (c);\n\t\t  for (--p; n < endp; ++n)\n\t\t    if (FOLD ((unsigned char) *n) == c\n\t\t\t&& (internal_fnmatch (p, n,\n\t\t\t\t\t      (no_leading_period\n\t\t\t\t\t       && (n == string\n\t\t\t\t\t\t   || (n[-1] == '/'\n\t\t\t\t\t\t       && (flags\n\t\t\t\t\t\t\t   & FNM_FILE_NAME)))),\n\t\t\t\t\t      flags2) == 0))\n\t\t      return 0;\n\t\t}\n\t    }\n\n\t  /* If we come here no match is possible with the wildcard.  */\n\t  return FNM_NOMATCH;\n\n\tcase '[':\n\t  {\n\t    /* Nonzero if the sense of the character class is inverted.  */\n\t    static int posixly_correct;\n\t    int not;\n\t    char cold;\n\n\t    if (posixly_correct == 0)\n\t      posixly_correct = getenv (\"POSIXLY_CORRECT\") != NULL ? 1 : -1;\n\n\t    if (*n == '\\0')\n\t      return FNM_NOMATCH;\n\n\t    if (*n == '.' && no_leading_period && (n == string\n\t\t\t\t\t\t   || (n[-1] == '/'\n\t\t\t\t\t\t       && (flags\n\t\t\t\t\t\t\t   & FNM_FILE_NAME))))\n\t      return FNM_NOMATCH;\n\n\t    if (*n == '/' && (flags & FNM_FILE_NAME))\n\t      /* `/' cannot be matched.  */\n\t      return FNM_NOMATCH;\n\n\t    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));\n\t    if (not)\n\t      ++p;\n\n\t    c = *p++;\n\t    for (;;)\n\t      {\n\t\tunsigned char fn = FOLD ((unsigned char) *n);\n\n\t\tif (!(flags & FNM_NOESCAPE) && c == '\\\\')\n\t\t  {\n\t\t    if (*p == '\\0')\n\t\t      return FNM_NOMATCH;\n\t\t    c = FOLD ((unsigned char) *p);\n\t\t    ++p;\n\n\t\t    if (c == fn)\n\t\t      goto matched;\n\t\t  }\n\t\telse if (c == '[' && *p == ':')\n\t\t  {\n\t\t    /* Leave room for the null.  */\n\t\t    char str[CHAR_CLASS_MAX_LENGTH + 1];\n\t\t    size_t c1 = 0;\n# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)\n\t\t    wctype_t wt;\n# endif\n\t\t    const char *startp = p;\n\n\t\t    for (;;)\n\t\t      {\n\t\t\tif (c1 == CHAR_CLASS_MAX_LENGTH)\n\t\t\t  /* The name is too long and therefore the pattern\n\t\t\t     is ill-formed.  */\n\t\t\t  return FNM_NOMATCH;\n\n\t\t\tc = *++p;\n\t\t\tif (c == ':' && p[1] == ']')\n\t\t\t  {\n\t\t\t    p += 2;\n\t\t\t    break;\n\t\t\t  }\n\t\t\tif (c < 'a' || c >= 'z')\n\t\t\t  {\n\t\t\t    /* This cannot possibly be a character class name.\n\t\t\t       Match it as a normal range.  */\n\t\t\t    p = startp;\n\t\t\t    c = '[';\n\t\t\t    goto normal_bracket;\n\t\t\t  }\n\t\t\tstr[c1++] = c;\n\t\t      }\n\t\t    str[c1] = '\\0';\n\n# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)\n\t\t    wt = IS_CHAR_CLASS (str);\n\t\t    if (wt == 0)\n\t\t      /* Invalid character class name.  */\n\t\t      return FNM_NOMATCH;\n\n\t\t    if (__iswctype (__btowc ((unsigned char) *n), wt))\n\t\t      goto matched;\n# else\n\t\t    if ((STREQ (str, \"alnum\") && ISALNUM ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"alpha\") && ISALPHA ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"blank\") && ISBLANK ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"cntrl\") && ISCNTRL ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"digit\") && ISDIGIT ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"graph\") && ISGRAPH ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"lower\") && ISLOWER ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"print\") && ISPRINT ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"punct\") && ISPUNCT ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"space\") && ISSPACE ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"upper\") && ISUPPER ((unsigned char) *n))\n\t\t\t|| (STREQ (str, \"xdigit\") && ISXDIGIT ((unsigned char) *n)))\n\t\t      goto matched;\n# endif\n\t\t  }\n\t\telse if (c == '\\0')\n\t\t  /* [ (unterminated) loses.  */\n\t\t  return FNM_NOMATCH;\n\t\telse\n\t\t  {\n\t\t  normal_bracket:\n\t\t    if (FOLD (c) == fn)\n\t\t      goto matched;\n\n\t\t    cold = c;\n\t\t    c = *p++;\n\n\t\t    if (c == '-' && *p != ']')\n\t\t      {\n\t\t\t/* It is a range.  */\n\t\t\tunsigned char cend = *p++;\n\t\t\tif (!(flags & FNM_NOESCAPE) && cend == '\\\\')\n\t\t\t  cend = *p++;\n\t\t\tif (cend == '\\0')\n\t\t\t  return FNM_NOMATCH;\n\n\t\t\tif (cold <= fn && fn <= FOLD (cend))\n\t\t\t  goto matched;\n\n\t\t\tc = *p++;\n\t\t      }\n\t\t  }\n\n\t\tif (c == ']')\n\t\t  break;\n\t      }\n\n\t    if (!not)\n\t      return FNM_NOMATCH;\n\t    break;\n\n\t  matched:\n\t    /* Skip the rest of the [...] that already matched.  */\n\t    while (c != ']')\n\t      {\n\t\tif (c == '\\0')\n\t\t  /* [... (unterminated) loses.  */\n\t\t  return FNM_NOMATCH;\n\n\t\tc = *p++;\n\t\tif (!(flags & FNM_NOESCAPE) && c == '\\\\')\n\t\t  {\n\t\t    if (*p == '\\0')\n\t\t      return FNM_NOMATCH;\n\t\t    /* XXX 1003.2d11 is unclear if this is right.  */\n\t\t    ++p;\n\t\t  }\n\t\telse if (c == '[' && *p == ':')\n\t\t  {\n\t\t    do\n\t\t      if (*++p == '\\0')\n\t\t\treturn FNM_NOMATCH;\n\t\t    while (*p != ':' || p[1] == ']');\n\t\t    p += 2;\n\t\t    c = *p;\n\t\t  }\n\t      }\n\t    if (not)\n\t      return FNM_NOMATCH;\n\t  }\n\t  break;\n\n\tdefault:\n\t  if (c != FOLD ((unsigned char) *n))\n\t    return FNM_NOMATCH;\n\t}\n\n      ++n;\n    }\n\n  if (*n == '\\0')\n    return 0;\n\n  if ((flags & FNM_LEADING_DIR) && *n == '/')\n    /* The FNM_LEADING_DIR flag says that \"foo*\" matches \"foobar/frobozz\".  */\n    return 0;\n\n  return FNM_NOMATCH;\n\n# undef FOLD\n}\n\n\nint\nfnmatch (const char *pattern, const char *string, int flags)\n{\n  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);\n}\n\n#endif\t/* _LIBC or not __GNU_LIBRARY__.  */\n"
  },
  {
    "path": "gl/lib/fnmatch.in.h",
    "content": "/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2023 Free Software\nFoundation, Inc.\nThis file is part of the GNU C Library.\n\nThe GNU C Library is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Library General Public License as\npublished by the Free Software Foundation; either version 2 of the\nLicense, or (at your option) any later version.\n\nThe GNU C Library is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLibrary General Public License for more details.\n\nYou should have received a copy of the GNU Library General Public License\nalong with this library; see the file COPYING.LIB.  If not, write to the Free\nSoftware Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301\nUSA.  */\n\n#ifndef\t_FNMATCH_H\n#define\t_FNMATCH_H\t1\n\n#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n/* We #undef these before defining them because some losing systems\n   (HP-UX A.08.07 for example) define these in <unistd.h>.  */\n#undef\tFNM_PATHNAME\n#undef\tFNM_NOESCAPE\n#undef\tFNM_PERIOD\n\n/* Bits set in the FLAGS argument to `fnmatch'.  */\n#define\tFNM_PATHNAME\t(1 << 0) /* No wildcard can ever match `/'.  */\n#define\tFNM_NOESCAPE\t(1 << 1) /* Backslashes don't quote special chars.  */\n#define\tFNM_PERIOD\t(1 << 2) /* Leading `.' is matched only explicitly.  */\n\n#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE\n# define FNM_FILE_NAME\t FNM_PATHNAME\t/* Preferred GNU name.  */\n# define FNM_LEADING_DIR (1 << 3)\t/* Ignore `/...' after a match.  */\n# define FNM_CASEFOLD\t (1 << 4)\t/* Compare without regard to case.  */\n#endif\n\n/* Value returned by `fnmatch' if STRING does not match PATTERN.  */\n#define\tFNM_NOMATCH\t1\n\n/* This value is returned if the implementation does not support\n   `fnmatch'.  Since this is not the case here it will never be\n   returned but the conformance test suites still require the symbol\n   to be defined.  */\n#ifdef _XOPEN_SOURCE\n# define FNM_NOSYS\t(-1)\n#endif\n\n/* Match NAME against the filename pattern PATTERN,\n   returning zero if it matches, FNM_NOMATCH if not.  */\nextern int fnmatch (const char *pattern, const char *name, int flags);\n\n#ifdef\t__cplusplus\n}\n#endif\n\n#endif /* fnmatch.h */\n"
  },
  {
    "path": "gl/lib/glob.c",
    "content": "/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,\n2023 Free Software Foundation, Inc.\n\nThis library is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Library General Public License as\npublished by the Free Software Foundation; either version 2 of the\nLicense, or (at your option) any later version.\n\nThis library is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLibrary General Public License for more details.\n\nYou should have received a copy of the GNU Library General Public License\nalong with this library; see the file COPYING.LIB.  If not, write to the Free\nSoftware Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301\nUSA.  */\n\n/* AIX requires this to be the first thing in the file.  */\n#if defined _AIX && !defined __GNUC__\n #pragma alloca\n#endif\n\n#ifdef\tHAVE_CONFIG_H\n# include <config.h>\n#endif\n\n/* Enable GNU extensions in glob.h.  */\n#ifndef _GNU_SOURCE\n# define _GNU_SOURCE\t1\n#endif\n\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n\n/* Outcomment the following line for production quality code.  */\n/* #define NDEBUG 1 */\n#include <assert.h>\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#define GLOB_INTERFACE_VERSION 1\n#if defined _LIBC\n# define ELIDE_CODE\n#elif defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1\n# include <gnu-versions.h>\n# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION\n#  define ELIDE_CODE\n# endif\n#endif\n\n#ifndef ELIDE_CODE\n\n#if defined STDC_HEADERS || defined __GNU_LIBRARY__\n# include <stddef.h>\n#endif\n\n#if defined HAVE_UNISTD_H\n# include <unistd.h>\n# ifndef POSIX\n#  ifdef _POSIX_VERSION\n#   define POSIX\n#  endif\n# endif\n#endif\n\n#if !defined _AMIGA && !MK_OS_VMS && !MK_OS_W32\n# include <pwd.h>\n#endif\n\n#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS\nextern int errno;\n#endif\n#ifndef __set_errno\n# define __set_errno(val) errno = (val)\n#endif\n\n#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__\n# include <dirent.h>\n# define NAMLEN(dirent) strlen((dirent)->d_name)\n#else\n# define dirent direct\n# define NAMLEN(dirent) (dirent)->d_namlen\n# ifdef HAVE_SYS_NDIR_H\n#  include <sys/ndir.h>\n# endif\n# ifdef HAVE_SYS_DIR_H\n#  include <sys/dir.h>\n# endif\n# ifdef HAVE_NDIR_H\n#  include <ndir.h>\n# endif\n# ifdef HAVE_VMSDIR_H\n#  include \"vmsdir.h\"\n# endif /* HAVE_VMSDIR_H */\n#endif\n\n/* In GNU systems, <dirent.h> defines this macro for us.  */\n#ifdef _D_NAMLEN\n# undef NAMLEN\n# define NAMLEN(d) _D_NAMLEN(d)\n#endif\n\n/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available\n   if the `d_type' member for `struct dirent' is available.  */\n#if defined(_DIRENT_HAVE_D_TYPE) || defined(HAVE_STRUCT_DIRENT_D_TYPE)\n# define HAVE_D_TYPE\t1\n#endif\n\n\n#if (defined POSIX || MK_OS_W32) && !defined __GNU_LIBRARY__\n/* Posix does not require that the d_ino field be present, and some\n   systems do not provide it. */\n# define REAL_DIR_ENTRY(dp) 1\n#else\n# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)\n#endif /* POSIX */\n\n#include <stdlib.h>\n#include <string.h>\n\n#if !defined HAVE_STRCOLL\n# define strcoll\tstrcmp\n#endif\n\n#if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1\n# define HAVE_MEMPCPY\t1\n# undef  mempcpy\n# define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len)\n#endif\n\n#if !defined __alloca && !defined __GNU_LIBRARY__\n\n# ifdef\t__GNUC__\n#  undef alloca\n#  define alloca(n)\t__builtin_alloca (n)\n# else\t/* Not GCC.  */\n#  ifdef HAVE_ALLOCA_H\n#   include <alloca.h>\n#  else\t/* Not HAVE_ALLOCA_H.  */\n#   ifndef _AIX\n#    if MK_OS_W32\n#     include <malloc.h>\n#    else\nextern char *alloca ();\n#    endif /* MK_OS_W32 */\n#   endif /* Not _AIX.  */\n#  endif /* sparc or HAVE_ALLOCA_H.  */\n# endif\t/* GCC.  */\n#endif\n\n#ifndef __GNU_LIBRARY__\n# ifdef STAT_MACROS_BROKEN\n#  undef S_ISDIR\n# endif\n# ifndef S_ISDIR\n#  define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)\n# endif\n#endif\n\n/* Some system header files erroneously define these.\n   We want our own definitions from <fnmatch.h> to take precedence.  */\n#ifndef __GNU_LIBRARY__\n# undef\tFNM_PATHNAME\n# undef\tFNM_NOESCAPE\n# undef\tFNM_PERIOD\n#endif\n#include <fnmatch.h>\n\n/* Some system header files erroneously define these.\n   We want our own definitions from <glob.h> to take precedence.  */\n#ifndef __GNU_LIBRARY__\n# undef\tGLOB_ERR\n# undef\tGLOB_MARK\n# undef\tGLOB_NOSORT\n# undef\tGLOB_DOOFFS\n# undef\tGLOB_NOCHECK\n# undef\tGLOB_APPEND\n# undef\tGLOB_NOESCAPE\n# undef\tGLOB_PERIOD\n#endif\n#include <glob.h>\n\n#if !defined __alloca\n# define __alloca alloca\n#endif\n\n#ifdef HAVE_GETLOGIN_R\nextern int getlogin_r (char *, size_t);\n#else\nextern char *getlogin (void);\n#endif\n\f\nstatic\n#if __GNUC__ - 0 >= 2\ninline\n#endif\nconst char *next_brace_sub (const char *begin);\nstatic int glob_in_dir (const char *pattern, const char *directory,\n\t\t\tint flags,\n\t\t\tint (*errfunc) (const char *, int),\n\t\t\tglob_t *pglob);\nstatic int prefix_array (const char *prefix, char **array, size_t n);\nstatic int collated_compare (const void *, const void *);\n\n#if !defined NO_GLOB_PATTERN_P\nint __glob_pattern_p (const char *pattern, int quote);\n#endif\n\n/* Find the end of the sub-pattern in a brace expression.  We define\n   this as an inline function if the compiler permits.  */\nstatic\n#if __GNUC__ - 0 >= 2\ninline\n#endif\nconst char *\nnext_brace_sub (const char *begin)\n{\n  unsigned int depth = 0;\n  const char *cp = begin;\n\n  while (1)\n    {\n      if (depth == 0)\n\t{\n\t  if (*cp != ',' && *cp != '}' && *cp != '\\0')\n\t    {\n\t      if (*cp == '{')\n\t\t++depth;\n\t      ++cp;\n\t      continue;\n\t    }\n\t}\n      else\n\t{\n\t  while (*cp != '\\0' && (*cp != '}' || depth > 0))\n\t    {\n\t      if (*cp == '}')\n\t\t--depth;\n\t      ++cp;\n\t    }\n\t  if (*cp == '\\0')\n\t    /* An incorrectly terminated brace expression.  */\n\t    return NULL;\n\n\t  continue;\n\t}\n      break;\n    }\n\n  return cp;\n}\n\n/* Do glob searching for PATTERN, placing results in PGLOB.\n   The bits defined above may be set in FLAGS.\n   If a directory cannot be opened or read and ERRFUNC is not nil,\n   it is called with the pathname that caused the error, and the\n   `errno' value from the failing call; if it returns non-zero\n   `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.\n   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.\n   Otherwise, `glob' returns zero.  */\nint\nglob (const char *pattern, int flags,\n      int (*errfunc) (const char *, int), glob_t *pglob)\n{\n  const char *filename;\n  const char *dirname;\n  size_t dirlen;\n  int status;\n  size_t oldcount;\n\n  if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)\n    {\n      __set_errno (EINVAL);\n      return -1;\n    }\n\n  /* POSIX requires all slashes to be matched.  This means that with\n     a trailing slash we must match only directories.  */\n  if (pattern[0] && pattern[strlen (pattern) - 1] == '/')\n    flags |= GLOB_ONLYDIR;\n\n  if (flags & GLOB_BRACE)\n    {\n      const char *begin = strchr (pattern, '{');\n      if (begin != NULL)\n\t{\n\t  /* Allocate working buffer large enough for our work.  Note that\n\t    we have at least an opening and closing brace.  */\n\t  size_t firstc;\n\t  char *alt_start;\n\t  const char *p;\n\t  const char *next;\n\t  const char *rest;\n\t  size_t rest_len;\n#ifdef __GNUC__\n\t  char onealt[strlen (pattern) - 1];\n#else\n\t  char *onealt = (char *) malloc (strlen (pattern) - 1);\n\t  if (onealt == NULL)\n\t    {\n\t      if (!(flags & GLOB_APPEND))\n\t\tglobfree (pglob);\n\t      return GLOB_NOSPACE;\n\t    }\n#endif\n\n\t  /* We know the prefix for all sub-patterns.  */\n#ifdef HAVE_MEMPCPY\n\t  alt_start = mempcpy (onealt, pattern, begin - pattern);\n#else\n\t  memcpy (onealt, pattern, begin - pattern);\n\t  alt_start = &onealt[begin - pattern];\n#endif\n\n\t  /* Find the first sub-pattern and at the same time find the\n\t     rest after the closing brace.  */\n\t  next = next_brace_sub (begin + 1);\n\t  if (next == NULL)\n\t    {\n\t      /* It is an illegal expression.  */\n#ifndef __GNUC__\n\t      free (onealt);\n#endif\n\t      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);\n\t    }\n\n\t  /* Now find the end of the whole brace expression.  */\n\t  rest = next;\n\t  while (*rest != '}')\n\t    {\n\t      rest = next_brace_sub (rest + 1);\n\t      if (rest == NULL)\n\t\t{\n\t\t  /* It is an illegal expression.  */\n#ifndef __GNUC__\n\t\t  free (onealt);\n#endif\n\t\t  return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);\n\t\t}\n\t    }\n\t  /* Please note that we now can be sure the brace expression\n\t     is well-formed.  */\n\t  rest_len = strlen (++rest) + 1;\n\n\t  /* We have a brace expression.  BEGIN points to the opening {,\n\t     NEXT points past the terminator of the first element, and END\n\t     points past the final }.  We will accumulate result names from\n\t     recursive runs for each brace alternative in the buffer using\n\t     GLOB_APPEND.  */\n\n\t  if (!(flags & GLOB_APPEND))\n\t    {\n\t      /* This call is to set a new vector, so clear out the\n\t\t vector so we can append to it.  */\n\t      pglob->gl_pathc = 0;\n\t      pglob->gl_pathv = NULL;\n\t    }\n\t  firstc = pglob->gl_pathc;\n\n\t  p = begin + 1;\n\t  while (1)\n\t    {\n\t      int result;\n\n\t      /* Construct the new glob expression.  */\n#ifdef HAVE_MEMPCPY\n\t      mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);\n#else\n\t      memcpy (alt_start, p, next - p);\n\t      memcpy (&alt_start[next - p], rest, rest_len);\n#endif\n\n\t      result = glob (onealt,\n\t\t\t     ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))\n\t\t\t      | GLOB_APPEND), errfunc, pglob);\n\n\t      /* If we got an error, return it.  */\n\t      if (result && result != GLOB_NOMATCH)\n\t\t{\n#ifndef __GNUC__\n\t\t  free (onealt);\n#endif\n\t\t  if (!(flags & GLOB_APPEND))\n\t\t    globfree (pglob);\n\t\t  return result;\n\t\t}\n\n\t      if (*next == '}')\n\t\t/* We saw the last entry.  */\n\t\tbreak;\n\n\t      p = next + 1;\n\t      next = next_brace_sub (p);\n\t      assert (next != NULL);\n\t    }\n\n#ifndef __GNUC__\n\t  free (onealt);\n#endif\n\n\t  if (pglob->gl_pathc != firstc)\n\t    /* We found some entries.  */\n\t    return 0;\n\t  else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))\n\t    return GLOB_NOMATCH;\n\t}\n    }\n\n  /* Find the filename.  */\n  filename = strrchr (pattern, '/');\n#if MK_OS_DOS || MK_OS_W32\n  /* The case of \"d:pattern\".  Since `:' is not allowed in\n     file names, we can safely assume that wherever it\n     happens in pattern, it signals the filename part.  This\n     is so we could some day support patterns like \"[a-z]:foo\".  */\n  if (filename == NULL)\n    filename = strchr (pattern, ':');\n#endif /* MK_OS_DOS || MK_OS_W32 */\n  if (filename == NULL)\n    {\n      /* This can mean two things: a simple name or \"~name\".  The later\n\t case is nothing but a notation for a directory.  */\n      if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')\n\t{\n\t  dirname = pattern;\n\t  dirlen = strlen (pattern);\n\n\t  /* Set FILENAME to NULL as a special flag.  This is ugly but\n\t     other solutions would require much more code.  We test for\n\t     this special case below.  */\n\t  filename = NULL;\n\t}\n      else\n\t{\n\t  filename = pattern;\n#ifdef _AMIGA\n\t  dirname = \"\";\n#else\n\t  dirname = \".\";\n#endif\n\t  dirlen = 0;\n\t}\n    }\n  else if (filename == pattern)\n    {\n      /* \"/pattern\".  */\n      dirname = \"/\";\n      dirlen = 1;\n      ++filename;\n    }\n  else\n    {\n      char *newp;\n      dirlen = filename - pattern;\n#if MK_OS_DOS || MK_OS_W32\n      if (*filename == ':'\n\t  || (filename > pattern + 1 && filename[-1] == ':'))\n\t{\n\t  char *drive_spec;\n\n\t  ++dirlen;\n\t  drive_spec = (char *) __alloca (dirlen + 1);\n#ifdef HAVE_MEMPCPY\n\t  *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\\0';\n#else\n\t  memcpy (drive_spec, pattern, dirlen);\n\t  drive_spec[dirlen] = '\\0';\n#endif\n\t  /* For now, disallow wildcards in the drive spec, to\n\t     prevent infinite recursion in glob.  */\n\t  if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))\n\t    return GLOB_NOMATCH;\n\t  /* If this is \"d:pattern\", we need to copy `:' to DIRNAME\n\t     as well.  If it's \"d:/pattern\", don't remove the slash\n\t     from \"d:/\", since \"d:\" and \"d:/\" are not the same.*/\n\t}\n#endif\n      newp = (char *) __alloca (dirlen + 1);\n#ifdef HAVE_MEMPCPY\n      *((char *) mempcpy (newp, pattern, dirlen)) = '\\0';\n#else\n      memcpy (newp, pattern, dirlen);\n      newp[dirlen] = '\\0';\n#endif\n      dirname = newp;\n      ++filename;\n\n      if (filename[0] == '\\0'\n#if MK_OS_DOS || MK_OS_W32\n          && dirname[dirlen - 1] != ':'\n\t  && (dirlen < 3 || dirname[dirlen - 2] != ':'\n\t      || dirname[dirlen - 1] != '/')\n#endif\n\t  && dirlen > 1)\n\t/* \"pattern/\".  Expand \"pattern\", appending slashes.  */\n\t{\n\t  int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);\n\t  if (val == 0)\n\t    pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)\n\t\t\t       | (flags & GLOB_MARK));\n\t  return val;\n\t}\n    }\n\n  if (!(flags & GLOB_APPEND))\n    {\n      pglob->gl_pathc = 0;\n      pglob->gl_pathv = NULL;\n    }\n\n  oldcount = pglob->gl_pathc;\n\n#if !MK_OS_VMS\n  if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')\n    {\n      if (dirname[1] == '\\0' || dirname[1] == '/')\n\t{\n\t  /* Look up home directory.  */\n#if MK_OS_VMS\n/* This isn't obvious, RTLs of DECC and VAXC know about \"HOME\" */\n          const char *home_dir = getenv (\"SYS$LOGIN\");\n#else\n          const char *home_dir = getenv (\"HOME\");\n#endif\n# ifdef _AMIGA\n\t  if (home_dir == NULL || home_dir[0] == '\\0')\n\t    home_dir = \"SYS:\";\n# else\n#  if MK_OS_W32\n\t  if (home_dir == NULL || home_dir[0] == '\\0')\n            home_dir = \"c:/users/default\"; /* poor default */\n#  else\n#   if MK_OS_VMS\n/* Again, this isn't obvious, if \"HOME\" isn't known \"SYS$LOGIN\" should be set */\n\t  if (home_dir == NULL || home_dir[0] == '\\0')\n\t    home_dir = \"SYS$DISK:[]\";\n#   else\n\t  if (home_dir == NULL || home_dir[0] == '\\0')\n\t    {\n\t      int success;\n\t      char *name;\n#   if defined HAVE_GETLOGIN_R\n\t      size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;\n\n\t      if (buflen == 0)\n\t\t/* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try\n\t\t   a moderate value.  */\n\t\tbuflen = 20;\n\t      name = (char *) __alloca (buflen);\n\n\t      success = getlogin_r (name, buflen) >= 0;\n#   else\n\t      success = (name = getlogin ()) != NULL;\n#   endif\n\t      if (success)\n\t\t{\n\t\t  struct passwd *p;\n#   if defined HAVE_GETPWNAM_R\n\t\t  size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);\n\t\t  char *pwtmpbuf;\n\t\t  struct passwd pwbuf;\n\t\t  int save = errno;\n\n\t\t  if (pwbuflen == -1)\n\t\t    /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.\n\t\t       Try a moderate value.  */\n\t\t    pwbuflen = 1024;\n\t\t  pwtmpbuf = (char *) __alloca (pwbuflen);\n\n\t\t  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)\n\t\t\t != 0)\n\t\t    {\n\t\t      if (errno != ERANGE)\n\t\t\t{\n\t\t\t  p = NULL;\n\t\t\t  break;\n\t\t\t}\n\t\t      pwbuflen *= 2;\n\t\t      pwtmpbuf = (char *) __alloca (pwbuflen);\n\t\t      __set_errno (save);\n\t\t    }\n#   else\n\t\t  p = getpwnam (name);\n#   endif\n\t\t  if (p != NULL)\n\t\t    home_dir = p->pw_dir;\n\t\t}\n\t    }\n\t  if (home_dir == NULL || home_dir[0] == '\\0')\n\t    {\n\t      if (flags & GLOB_TILDE_CHECK)\n\t\treturn GLOB_NOMATCH;\n\t      else\n\t\thome_dir = \"~\"; /* No luck.  */\n\t    }\n#   endif /* MK_OS_VMS */\n#  endif /* MK_OS_W32 */\n# endif\n\t  /* Now construct the full directory.  */\n\t  if (dirname[1] == '\\0')\n\t    dirname = home_dir;\n\t  else\n\t    {\n\t      char *newp;\n\t      size_t home_len = strlen (home_dir);\n\t      newp = (char *) __alloca (home_len + dirlen);\n# ifdef HAVE_MEMPCPY\n\t      mempcpy (mempcpy (newp, home_dir, home_len),\n\t\t       &dirname[1], dirlen);\n# else\n\t      memcpy (newp, home_dir, home_len);\n\t      memcpy (&newp[home_len], &dirname[1], dirlen);\n# endif\n\t      dirname = newp;\n\t    }\n\t}\n# if !defined _AMIGA && !MK_OS_W32 && !MK_OS_VMS\n      else\n\t{\n\t  char *end_name = strchr (dirname, '/');\n\t  const char *user_name;\n\t  const char *home_dir;\n\n\t  if (end_name == NULL)\n\t    user_name = dirname + 1;\n\t  else\n\t    {\n\t      char *newp;\n\t      newp = (char *) __alloca (end_name - dirname);\n# ifdef HAVE_MEMPCPY\n\t      *((char *) mempcpy (newp, dirname + 1, end_name - dirname))\n\t\t= '\\0';\n# else\n\t      memcpy (newp, dirname + 1, end_name - dirname);\n\t      newp[end_name - dirname - 1] = '\\0';\n# endif\n\t      user_name = newp;\n\t    }\n\n\t  /* Look up specific user's home directory.  */\n\t  {\n\t    struct passwd *p;\n#  if defined HAVE_GETPWNAM_R\n\t    size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);\n\t    char *pwtmpbuf;\n\t    struct passwd pwbuf;\n\t    int save = errno;\n\n\t    if (buflen == -1)\n\t      /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.  Try a\n\t\t moderate value.  */\n\t      buflen = 1024;\n\t    pwtmpbuf = (char *) __alloca (buflen);\n\n\t    while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)\n\t      {\n\t\tif (errno != ERANGE)\n\t\t  {\n\t\t    p = NULL;\n\t\t    break;\n\t\t  }\n\t\tbuflen *= 2;\n\t\tpwtmpbuf = __alloca (buflen);\n\t\t__set_errno (save);\n\t      }\n#  else\n\t    p = getpwnam (user_name);\n#  endif\n\t    if (p != NULL)\n\t      home_dir = p->pw_dir;\n\t    else\n\t      home_dir = NULL;\n\t  }\n\t  /* If we found a home directory use this.  */\n\t  if (home_dir != NULL)\n\t    {\n\t      char *newp;\n\t      size_t home_len = strlen (home_dir);\n\t      size_t rest_len = end_name == NULL ? 0 : strlen (end_name);\n\t      newp = (char *) __alloca (home_len + rest_len + 1);\n#  ifdef HAVE_MEMPCPY\n\t      *((char *) mempcpy (mempcpy (newp, home_dir, home_len),\n\t\t\t\t  end_name, rest_len)) = '\\0';\n#  else\n\t      memcpy (newp, home_dir, home_len);\n\t      memcpy (&newp[home_len], end_name, rest_len);\n\t      newp[home_len + rest_len] = '\\0';\n#  endif\n\t      dirname = newp;\n\t    }\n\t  else\n\t    if (flags & GLOB_TILDE_CHECK)\n\t      /* We have to regard it as an error if we cannot find the\n\t\t home directory.  */\n\t      return GLOB_NOMATCH;\n\t}\n# endif\t/* Not Amiga && not MK_OS_W32 && not MK_OS_VMS.  */\n    }\n#endif\t/* Not MK_OS_VMS.  */\n\n  /* Now test whether we looked for \"~\" or \"~NAME\".  In this case we\n     can give the answer now.  */\n  if (filename == NULL)\n    {\n      struct stat st;\n\n      /* Return the directory if we don't check for error or if it exists.  */\n      if ((flags & GLOB_NOCHECK)\n\t  || (((flags & GLOB_ALTDIRFUNC)\n\t       ? (*pglob->gl_stat) (dirname, &st)\n\t       : stat (dirname, &st)) == 0\n\t      && S_ISDIR (st.st_mode)))\n\t{\n\t  pglob->gl_pathv\n\t    = (char **) realloc (pglob->gl_pathv,\n\t\t\t\t (pglob->gl_pathc +\n\t\t\t\t  ((flags & GLOB_DOOFFS) ?\n\t\t\t\t   pglob->gl_offs : 0) +\n\t\t\t\t  1 + 1) *\n\t\t\t\t sizeof (char *));\n\t  if (pglob->gl_pathv == NULL)\n\t    return GLOB_NOSPACE;\n\n\t  if (flags & GLOB_DOOFFS)\n\t    while (pglob->gl_pathc < pglob->gl_offs)\n\t      pglob->gl_pathv[pglob->gl_pathc++] = NULL;\n\n#if defined HAVE_STRDUP\n\t  pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname);\n#else\n\t  {\n\t    size_t len = strlen (dirname) + 1;\n\t    char *dircopy = malloc (len);\n\t    if (dircopy != NULL)\n\t      pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname,\n\t\t\t\t\t\t\t len);\n\t  }\n#endif\n\t  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)\n\t    {\n\t      free (pglob->gl_pathv);\n\t      return GLOB_NOSPACE;\n\t    }\n\t  pglob->gl_pathv[++pglob->gl_pathc] = NULL;\n\t  pglob->gl_flags = flags;\n\n\t  return 0;\n\t}\n\n      /* Not found.  */\n      return GLOB_NOMATCH;\n    }\n\n  if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))\n    {\n      /* The directory name contains metacharacters, so we\n\t have to glob for the directory, and then glob for\n\t the pattern in each directory found.  */\n      glob_t dirs;\n      size_t i;\n\n      status = glob (dirname,\n\t\t     ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE))\n\t\t      | GLOB_NOSORT | GLOB_ONLYDIR),\n\t\t     errfunc, &dirs);\n      if (status != 0)\n\treturn status;\n\n      /* We have successfully globbed the preceding directory name.\n\t For each name we found, call glob_in_dir on it and FILENAME,\n\t appending the results to PGLOB.  */\n      for (i = 0; i < dirs.gl_pathc; ++i)\n\t{\n\t  size_t old_pathc;\n\n#ifdef\tSHELL\n\t  {\n\t    /* Make globbing interruptible in the bash shell. */\n\t    extern int interrupt_state;\n\n\t    if (interrupt_state)\n\t      {\n\t\tglobfree (&dirs);\n\t\tglobfree (&files);\n\t\treturn GLOB_ABORTED;\n\t      }\n\t  }\n#endif /* SHELL.  */\n\n\t  old_pathc = pglob->gl_pathc;\n\t  status = glob_in_dir (filename, dirs.gl_pathv[i],\n\t\t\t\t((flags | GLOB_APPEND)\n\t\t\t\t & ~(GLOB_NOCHECK | GLOB_ERR)),\n\t\t\t\terrfunc, pglob);\n\t  if (status == GLOB_NOMATCH)\n\t    /* No matches in this directory.  Try the next.  */\n\t    continue;\n\n\t  if (status != 0)\n\t    {\n\t      globfree (&dirs);\n\t      globfree (pglob);\n\t      return status;\n\t    }\n\n\t  /* Stick the directory on the front of each name.  */\n\t  if (prefix_array (dirs.gl_pathv[i],\n\t\t\t    &pglob->gl_pathv[old_pathc],\n\t\t\t    pglob->gl_pathc - old_pathc))\n\t    {\n\t      globfree (&dirs);\n\t      globfree (pglob);\n\t      return GLOB_NOSPACE;\n\t    }\n\t}\n\n      flags |= GLOB_MAGCHAR;\n\n      /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.\n\t But if we have not found any matching entry and thie GLOB_NOCHECK\n\t flag was set we must return the list consisting of the disrectory\n\t names followed by the filename.  */\n      if (pglob->gl_pathc == oldcount)\n\t{\n\t  /* No matches.  */\n\t  if (flags & GLOB_NOCHECK)\n\t    {\n\t      size_t filename_len = strlen (filename) + 1;\n\t      char **new_pathv;\n\t      struct stat st;\n\n\t      /* This is an pessimistic guess about the size.  */\n\t      pglob->gl_pathv\n\t\t= (char **) realloc (pglob->gl_pathv,\n\t\t\t\t     (pglob->gl_pathc +\n\t\t\t\t      ((flags & GLOB_DOOFFS) ?\n\t\t\t\t       pglob->gl_offs : 0) +\n\t\t\t\t      dirs.gl_pathc + 1) *\n\t\t\t\t     sizeof (char *));\n\t      if (pglob->gl_pathv == NULL)\n\t\t{\n\t\t  globfree (&dirs);\n\t\t  return GLOB_NOSPACE;\n\t\t}\n\n\t      if (flags & GLOB_DOOFFS)\n\t\twhile (pglob->gl_pathc < pglob->gl_offs)\n\t\t  pglob->gl_pathv[pglob->gl_pathc++] = NULL;\n\n\t      for (i = 0; i < dirs.gl_pathc; ++i)\n\t\t{\n\t\t  const char *dir = dirs.gl_pathv[i];\n\t\t  size_t dir_len = strlen (dir);\n\n\t\t  /* First check whether this really is a directory.  */\n\t\t  if (((flags & GLOB_ALTDIRFUNC)\n\t\t       ? (*pglob->gl_stat) (dir, &st) : stat (dir, &st)) != 0\n\t\t      || !S_ISDIR (st.st_mode))\n\t\t    /* No directory, ignore this entry.  */\n\t\t    continue;\n\n\t\t  pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1\n\t\t\t\t\t\t\t     + filename_len);\n\t\t  if (pglob->gl_pathv[pglob->gl_pathc] == NULL)\n\t\t    {\n\t\t      globfree (&dirs);\n\t\t      globfree (pglob);\n\t\t      return GLOB_NOSPACE;\n\t\t    }\n\n#ifdef HAVE_MEMPCPY\n\t\t  mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc],\n\t\t\t\t\t     dir, dir_len),\n\t\t\t\t    \"/\", 1),\n\t\t\t   filename, filename_len);\n#else\n\t\t  memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len);\n\t\t  pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/';\n\t\t  memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1],\n\t\t\t  filename, filename_len);\n#endif\n\t\t  ++pglob->gl_pathc;\n\t\t}\n\n\t      pglob->gl_pathv[pglob->gl_pathc] = NULL;\n\t      pglob->gl_flags = flags;\n\n\t      /* Now we know how large the gl_pathv vector must be.  */\n\t      new_pathv = (char **) realloc (pglob->gl_pathv,\n\t\t\t\t\t     ((pglob->gl_pathc + 1)\n\t\t\t\t\t      * sizeof (char *)));\n\t      if (new_pathv != NULL)\n\t\tpglob->gl_pathv = new_pathv;\n\t    }\n\t  else\n\t    return GLOB_NOMATCH;\n\t}\n\n      globfree (&dirs);\n    }\n  else\n    {\n      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);\n      if (status != 0)\n\treturn status;\n\n      if (dirlen > 0)\n\t{\n\t  /* Stick the directory on the front of each name.  */\n\t  size_t ignore = oldcount;\n\n\t  if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs)\n\t    ignore = pglob->gl_offs;\n\n\t  if (prefix_array (dirname,\n\t\t\t    &pglob->gl_pathv[ignore],\n\t\t\t    pglob->gl_pathc - ignore))\n\t    {\n\t      globfree (pglob);\n\t      return GLOB_NOSPACE;\n\t    }\n\t}\n    }\n\n  if (flags & GLOB_MARK)\n    {\n      /* Append slashes to directory names.  */\n      size_t i;\n      struct stat st;\n      for (i = oldcount; i < pglob->gl_pathc; ++i)\n\tif (((flags & GLOB_ALTDIRFUNC)\n\t     ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st)\n\t     : stat (pglob->gl_pathv[i], &st)) == 0\n\t    && S_ISDIR (st.st_mode))\n\t  {\n \t    size_t len = strlen (pglob->gl_pathv[i]) + 2;\n\t    char *new = realloc (pglob->gl_pathv[i], len);\n \t    if (new == NULL)\n\t      {\n\t\tglobfree (pglob);\n\t\treturn GLOB_NOSPACE;\n\t      }\n\t    strcpy (&new[len - 2], \"/\");\n\t    pglob->gl_pathv[i] = new;\n\t  }\n    }\n\n  if (!(flags & GLOB_NOSORT))\n    {\n      /* Sort the vector.  */\n      size_t non_sort = oldcount;\n\n      if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount)\n\tnon_sort = pglob->gl_offs;\n\n      qsort ((void *) &pglob->gl_pathv[non_sort],\n\t     pglob->gl_pathc - non_sort,\n\t     sizeof (char *), collated_compare);\n    }\n\n  return 0;\n}\n\n\n/* Free storage allocated in PGLOB by a previous `glob' call.  */\nvoid\nglobfree (glob_t *pglob)\n{\n  if (pglob->gl_pathv != NULL)\n    {\n      size_t i;\n      for (i = 0; i < pglob->gl_pathc; ++i)\n\tif (pglob->gl_pathv[i] != NULL)\n\t  free (pglob->gl_pathv[i]);\n      free (pglob->gl_pathv);\n    }\n}\n\n\n/* Do a collated comparison of A and B.  */\nstatic int\ncollated_compare (const void *a, const void *b)\n{\n  const char *const s1 = *(const char *const * const) a;\n  const char *const s2 = *(const char *const * const) b;\n\n  if (s1 == s2)\n    return 0;\n  if (s1 == NULL)\n    return 1;\n  if (s2 == NULL)\n    return -1;\n  return strcoll (s1, s2);\n}\n\n\n/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's\n   elements in place.  Return nonzero if out of memory, zero if successful.\n   A slash is inserted between DIRNAME and each elt of ARRAY,\n   unless DIRNAME is just \"/\".  Each old element of ARRAY is freed.  */\nstatic int\nprefix_array (const char *dirname, char **array, size_t n)\n{\n  size_t i;\n  size_t dirlen = strlen (dirname);\n#if MK_OS_DOS || MK_OS_W32\n  char sep_char = '/';\n# define DIRSEP_CHAR sep_char\n#else\n# define DIRSEP_CHAR '/'\n#endif\n\n  if (dirlen == 1 && dirname[0] == '/')\n    /* DIRNAME is just \"/\", so normal prepending would get us \"//foo\".\n       We want \"/foo\" instead, so don't prepend any chars from DIRNAME.  */\n    dirlen = 0;\n#if MK_OS_DOS || MK_OS_W32\n  else if (dirlen > 1)\n    {\n      if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')\n\t/* DIRNAME is \"d:/\".  Don't prepend the slash from DIRNAME.  */\n\t--dirlen;\n      else if (dirname[dirlen - 1] == ':')\n\t{\n\t  /* DIRNAME is \"d:\".  Use `:' instead of `/'.  */\n\t  --dirlen;\n\t  sep_char = ':';\n\t}\n    }\n#endif\n\n  for (i = 0; i < n; ++i)\n    {\n      size_t eltlen = strlen (array[i]) + 1;\n      char *new = (char *) malloc (dirlen + 1 + eltlen);\n      if (new == NULL)\n\t{\n\t  while (i > 0)\n\t    free (array[--i]);\n\t  return 1;\n\t}\n\n#ifdef HAVE_MEMPCPY\n      {\n\tchar *endp = (char *) mempcpy (new, dirname, dirlen);\n\t*endp++ = DIRSEP_CHAR;\n\tmempcpy (endp, array[i], eltlen);\n      }\n#else\n      memcpy (new, dirname, dirlen);\n      new[dirlen] = DIRSEP_CHAR;\n      memcpy (&new[dirlen + 1], array[i], eltlen);\n#endif\n      free (array[i]);\n      array[i] = new;\n    }\n\n  return 0;\n}\n\n\n/* We must not compile this function twice.  */\n#if !defined NO_GLOB_PATTERN_P\n/* Return nonzero if PATTERN contains any metacharacters.\n   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */\nint\n__glob_pattern_p (const char *pattern, int quote)\n{\n  const char *p;\n  int open = 0;\n\n  for (p = pattern; *p != '\\0'; ++p)\n    switch (*p)\n      {\n      case '?':\n      case '*':\n\treturn 1;\n\n      case '\\\\':\n\tif (quote && p[1] != '\\0')\n\t  ++p;\n\tbreak;\n\n      case '[':\n\topen = 1;\n\tbreak;\n\n      case ']':\n\tif (open)\n\t  return 1;\n\tbreak;\n      }\n\n  return 0;\n}\n#endif\n\n\n/* Like `glob', but PATTERN is a final pathname component,\n   and matches are searched for in DIRECTORY.\n   The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.\n   The GLOB_APPEND flag is assumed to be set (always appends).  */\nstatic int\nglob_in_dir (const char *pattern, const char *directory, int flags,\n\t     int (*errfunc) (const char *, int), glob_t *pglob)\n{\n  void *stream = NULL;\n\n  struct globlink\n    {\n      struct globlink *next;\n      char *name;\n    };\n  struct globlink *names = NULL;\n  size_t nfound;\n  int meta;\n  int save;\n\n#if MK_OS_VMS\n  if (*directory == 0)\n    directory = \"[]\";\n#endif\n  meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE));\n  if (meta == 0)\n    {\n      if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))\n\t/* We need not do any tests.  The PATTERN contains no meta\n\t   characters and we must not return an error therefore the\n\t   result will always contain exactly one name.  */\n\tflags |= GLOB_NOCHECK;\n      else\n\t{\n\t  /* Since we use the normal file functions we can also use stat()\n\t     to verify the file is there.  */\n\t  struct stat st;\n\t  size_t patlen = strlen (pattern);\n\t  size_t dirlen = strlen (directory);\n\t  char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);\n\n# ifdef HAVE_MEMPCPY\n\t  mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),\n\t\t\t    \"/\", 1),\n\t\t   pattern, patlen + 1);\n# else\n\t  memcpy (fullname, directory, dirlen);\n\t  fullname[dirlen] = '/';\n\t  memcpy (&fullname[dirlen + 1], pattern, patlen + 1);\n# endif\n\t  if (((flags & GLOB_ALTDIRFUNC)\n\t       ? (*pglob->gl_stat) (fullname, &st)\n\t       : stat (fullname, &st)) == 0)\n\t    /* We found this file to be existing.  Now tell the rest\n\t       of the function to copy this name into the result.  */\n\t    flags |= GLOB_NOCHECK;\n\t}\n\n      nfound = 0;\n    }\n  else\n    {\n      if (pattern[0] == '\\0')\n\t{\n\t  /* This is a special case for matching directories like in\n\t     \"*a/\".  */\n\t  names = (struct globlink *) __alloca (sizeof (struct globlink));\n\t  names->name = (char *) malloc (1);\n\t  if (names->name == NULL)\n\t    goto memory_error;\n\t  names->name[0] = '\\0';\n\t  names->next = NULL;\n\t  nfound = 1;\n\t  meta = 0;\n\t}\n      else\n\t{\n\t  stream = ((flags & GLOB_ALTDIRFUNC)\n\t\t    ? (*pglob->gl_opendir) (directory)\n\t\t    : (void *) opendir (directory));\n\t  if (stream == NULL)\n\t    {\n\t      if (errno != ENOTDIR\n\t\t  && ((errfunc != NULL && (*errfunc) (directory, errno))\n\t\t      || (flags & GLOB_ERR)))\n\t\treturn GLOB_ABORTED;\n\t      nfound = 0;\n\t      meta = 0;\n\t    }\n\t  else\n\t    {\n\t      int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)\n\t\t\t       | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)\n#if defined HAVE_CASE_INSENSITIVE_FS\n\t\t\t\t   | FNM_CASEFOLD\n#endif\n\t\t\t\t   );\n\t      nfound = 0;\n\t      flags |= GLOB_MAGCHAR;\n\n\t      while (1)\n\t\t{\n\t\t  const char *name;\n\t\t  size_t len;\n\t\t  struct dirent *d = ((flags & GLOB_ALTDIRFUNC)\n\t\t\t\t      ? (*pglob->gl_readdir) (stream)\n\t\t\t\t      : readdir ((DIR *) stream));\n\t\t  if (d == NULL)\n\t\t    break;\n\t\t  if (! REAL_DIR_ENTRY (d))\n\t\t    continue;\n\n#ifdef HAVE_D_TYPE\n\t\t  /* If we shall match only directories use the information\n\t\t     provided by the dirent call if possible.  */\n\t\t  if ((flags & GLOB_ONLYDIR)\n\t\t      && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR && d->d_type != DT_LNK)\n\t\t    continue;\n#endif\n\n\t\t  name = d->d_name;\n\n\t\t  if (fnmatch (pattern, name, fnm_flags) == 0)\n\t\t    {\n\t\t      struct globlink *new = (struct globlink *)\n\t\t\t__alloca (sizeof (struct globlink));\n\t\t      len = NAMLEN (d);\n\t\t      new->name = (char *) malloc (len + 1);\n\t\t      if (new->name == NULL)\n\t\t\tgoto memory_error;\n#ifdef HAVE_MEMPCPY\n\t\t      *((char *) mempcpy (new->name, name, len)) = '\\0';\n#else\n\t\t      memcpy (new->name, name, len);\n\t\t      new->name[len] = '\\0';\n#endif\n\t\t      new->next = names;\n\t\t      names = new;\n\t\t      ++nfound;\n\t\t    }\n\t\t}\n\t    }\n\t}\n    }\n\n  if (nfound == 0 && (flags & GLOB_NOCHECK))\n    {\n      size_t len = strlen (pattern);\n      nfound = 1;\n      names = (struct globlink *) __alloca (sizeof (struct globlink));\n      names->next = NULL;\n      names->name = (char *) malloc (len + 1);\n      if (names->name == NULL)\n\tgoto memory_error;\n#ifdef HAVE_MEMPCPY\n      *((char *) mempcpy (names->name, pattern, len)) = '\\0';\n#else\n      memcpy (names->name, pattern, len);\n      names->name[len] = '\\0';\n#endif\n    }\n\n  if (nfound != 0)\n    {\n      pglob->gl_pathv\n\t= (char **) realloc (pglob->gl_pathv,\n\t\t\t     (pglob->gl_pathc +\n\t\t\t      ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +\n\t\t\t      nfound + 1) *\n\t\t\t     sizeof (char *));\n      if (pglob->gl_pathv == NULL)\n\tgoto memory_error;\n\n      if (flags & GLOB_DOOFFS)\n\twhile (pglob->gl_pathc < pglob->gl_offs)\n\t  pglob->gl_pathv[pglob->gl_pathc++] = NULL;\n\n      for (; names != NULL; names = names->next)\n\tpglob->gl_pathv[pglob->gl_pathc++] = names->name;\n      pglob->gl_pathv[pglob->gl_pathc] = NULL;\n\n      pglob->gl_flags = flags;\n    }\n\n  save = errno;\n  if (stream != NULL)\n    {\n      if (flags & GLOB_ALTDIRFUNC)\n\t(*pglob->gl_closedir) (stream);\n      else\n\tclosedir ((DIR *) stream);\n    }\n  __set_errno (save);\n\n  return nfound == 0 ? GLOB_NOMATCH : 0;\n\n memory_error:\n  {\n    save = errno;\n    if (flags & GLOB_ALTDIRFUNC)\n      (*pglob->gl_closedir) (stream);\n    else\n      closedir ((DIR *) stream);\n    __set_errno (save);\n  }\n  while (names != NULL)\n    {\n      if (names->name != NULL)\n\tfree (names->name);\n      names = names->next;\n    }\n  return GLOB_NOSPACE;\n}\n\n#endif\t/* Not ELIDE_CODE.  */\n"
  },
  {
    "path": "gl/lib/glob.in.h",
    "content": "/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998, 2023 Free Software\nFoundation, Inc.\n\nThe GNU C Library is free software; you can redistribute it and/or\nmodify it under the terms of the GNU Library General Public License as\npublished by the Free Software Foundation; either version 2 of the\nLicense, or (at your option) any later version.\n\nThe GNU C Library is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLibrary General Public License for more details.\n\nYou should have received a copy of the GNU Library General Public License\nalong with this library; see the file COPYING.LIB.  If not, write to the Free\nSoftware Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301\nUSA.  */\n\n#ifndef\t_GLOB_H\n#define\t_GLOB_H\t1\n\n#include <stddef.h>\n\n#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n/* Bits set in the FLAGS argument to `glob'.  */\n#define\tGLOB_ERR\t(1 << 0)/* Return on read errors.  */\n#define\tGLOB_MARK\t(1 << 1)/* Append a slash to each name.  */\n#define\tGLOB_NOSORT\t(1 << 2)/* Don't sort the names.  */\n#define\tGLOB_DOOFFS\t(1 << 3)/* Insert PGLOB->gl_offs NULLs.  */\n#define\tGLOB_NOCHECK\t(1 << 4)/* If nothing matches, return the pattern.  */\n#define\tGLOB_APPEND\t(1 << 5)/* Append to results of a previous call.  */\n#define\tGLOB_NOESCAPE\t(1 << 6)/* Backslashes don't quote metacharacters.  */\n#define\tGLOB_PERIOD\t(1 << 7)/* Leading `.' can be matched by metachars.  */\n\n#if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \\\n     || defined _GNU_SOURCE)\n# define GLOB_MAGCHAR\t (1 << 8)/* Set in gl_flags if any metachars seen.  */\n# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions.  */\n# define GLOB_BRACE\t (1 << 10)/* Expand \"{a,b}\" to \"a\" \"b\".  */\n# define GLOB_NOMAGIC\t (1 << 11)/* If no magic chars, return the pattern.  */\n# define GLOB_TILDE\t (1 << 12)/* Expand ~user and ~ to home directories. */\n# define GLOB_ONLYDIR\t (1 << 13)/* Match only directories.  */\n# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error\n\t\t\t\t      if the user name is not available.  */\n# define __GLOB_FLAGS\t(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \\\n\t\t\t GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \\\n\t\t\t GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE|     \\\n\t\t\t GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK)\n#else\n# define __GLOB_FLAGS\t(GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \\\n\t\t\t GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND|     \\\n\t\t\t GLOB_PERIOD)\n#endif\n\n/* Error returns from `glob'.  */\n#define\tGLOB_NOSPACE\t1\t/* Ran out of memory.  */\n#define\tGLOB_ABORTED\t2\t/* Read error.  */\n#define\tGLOB_NOMATCH\t3\t/* No matches found.  */\n#define GLOB_NOSYS\t4\t/* Not implemented.  */\n#ifdef _GNU_SOURCE\n/* Previous versions of this file defined GLOB_ABEND instead of\n   GLOB_ABORTED.  Provide a compatibility definition here.  */\n# define GLOB_ABEND GLOB_ABORTED\n#endif\n\n/* Structure describing a globbing run.  */\n#if !defined _AMIGA && !MK_OS_VMS /* Buggy compiler.   */\nstruct stat;\n#endif\ntypedef struct\n  {\n    size_t gl_pathc;\t\t/* Count of paths matched by the pattern.  */\n    char **gl_pathv;\t\t/* List of matched pathnames.  */\n    size_t gl_offs;\t\t/* Slots to reserve in `gl_pathv'.  */\n    int gl_flags;\t\t/* Set to FLAGS, maybe | GLOB_MAGCHAR.  */\n\n    /* If the GLOB_ALTDIRFUNC flag is set, the following functions\n       are used instead of the normal file access functions.  */\n    void (*gl_closedir) (void *);\n    struct dirent *(*gl_readdir) (void *);\n    void * (*gl_opendir) (const char *);\n    int (*gl_lstat) (const char *, struct stat *);\n#if MK_OS_VMS && defined(__DECC) && !defined(_POSIX_C_SOURCE)\n    int (*gl_stat) (const char *, struct stat *, ...);\n#else\n    int (*gl_stat) (const char *, struct stat *);\n#endif\n  } glob_t;\n\n#ifdef _LARGEFILE64_SOURCE\nstruct stat64;\ntypedef struct\n  {\n    size_t gl_pathc;\n    char **gl_pathv;\n    size_t gl_offs;\n    int gl_flags;\n\n    /* If the GLOB_ALTDIRFUNC flag is set, the following functions\n       are used instead of the normal file access functions.  */\n    void (*gl_closedir) (void *);\n    struct dirent64 *(*gl_readdir) (void *);\n    void * (*gl_opendir) (const char *);\n    int (*gl_lstat) (const char *, struct stat64 *);\n    int (*gl_stat) (const char *, struct stat64 *);\n  } glob64_t;\n#endif\n\n#if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2\n# define glob glob64\n# define globfree globfree64\n#else\n# ifdef _LARGEFILE64_SOURCE\nextern int glob64 (const char *pattern, int flags,\n\t\t   int (*errfunc) (const char *, int),\n\t\t   glob64_t *pglob);\n\nextern void globfree64 (glob64_t *pglob);\n# endif\n#endif\n\n/* Do glob searching for PATTERN, placing results in PGLOB.\n   The bits defined above may be set in FLAGS.\n   If a directory cannot be opened or read and ERRFUNC is not nil,\n   it is called with the pathname that caused the error, and the\n   `errno' value from the failing call; if it returns non-zero\n   `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.\n   If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.\n   Otherwise, `glob' returns zero.  */\n#if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2\nextern int glob (const char *pattern, int flags,\n\t\t int (*errfunc) (const char *, int),\n\t\t glob_t *pglob);\n\n/* Free storage allocated in PGLOB by a previous `glob' call.  */\nextern void globfree (glob_t *pglob);\n#else\nextern int glob (const char *pattern, int flags,\n\t\t int (*errfunc) (const char *, int),\n\t\t glob_t *pglob) __asm__ (\"glob64\");\n\nextern void globfree (glob_t *pglob) __asm__ (\"globfree64\");\n#endif\n\n\n#ifdef _GNU_SOURCE\n/* Return nonzero if PATTERN contains any metacharacters.\n   Metacharacters can be quoted with backslashes if QUOTE is nonzero.\n\n   This function is not part of the interface specified by POSIX.2\n   but several programs want to use it.  */\nextern int glob_pattern_p (const char *pattern, int quote);\n#endif\n\n#ifdef\t__cplusplus\n}\n#endif\n\n#endif /* glob.h  */\n"
  },
  {
    "path": "gl/m4/acinclude.m4",
    "content": "dnl acinclude.m4 -- Extra macros needed for GNU Make.\ndnl\ndnl Automake will incorporate this into its generated aclocal.m4.\ndnl Copyright (C) 1998-2024 Free Software Foundation, Inc.\ndnl This file is part of GNU Make.\ndnl\ndnl GNU Make is free software; you can redistribute it and/or modify it under\ndnl the terms of the GNU General Public License as published by the Free\ndnl Software Foundation; either version 3 of the License, or (at your option)\ndnl any later version.\ndnl\ndnl GNU Make is distributed in the hope that it will be useful, but WITHOUT\ndnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\ndnl FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.\ndnl more details.\ndnl\ndnl You should have received a copy of the GNU General Public License along\ndnl with this program.  If not, see <https://www.gnu.org/licenses/>.\n\ndnl ---------------------------------------------------------------------------\ndnl Got this from the lynx 2.8 distribution.\ndnl by T.E.Dickey <dickey@clark.net>\ndnl and Jim Spath <jspath@mail.bcpl.lib.md.us>\ndnl and Philippe De Muyter <phdm@macqel.be>\ndnl\ndnl Created: 1997/1/28\ndnl Updated: 1997/12/23\ndnl ---------------------------------------------------------------------------\ndnl After checking for functions in the default $LIBS, make a further check\ndnl for the functions that are netlib-related (these aren't always in the\ndnl libc, etc., and have to be handled specially because there are conflicting\ndnl and broken implementations.\ndnl Common library requirements (in order):\ndnl\t-lresolv -lsocket -lnsl\ndnl\t-lnsl -lsocket\ndnl\t-lsocket\ndnl\t-lbsd\nAC_DEFUN([CF_NETLIBS],[\ncf_test_netlibs=no\nAC_MSG_CHECKING(for network libraries)\nAC_CACHE_VAL(cf_cv_netlibs,[\nAC_MSG_RESULT(working...)\ncf_cv_netlibs=\"\"\ncf_test_netlibs=yes\nAC_CHECK_FUNCS(gethostname,,[\n        CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[\n                CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])\n#\n# FIXME:  sequent needs this library (i.e., -lsocket -linet -lnsl), but\n# I don't know the entrypoints - 97/7/22 TD\nAC_CHECK_LIB(inet,main,cf_cv_netlibs=\"-linet $cf_cv_netlibs\")\n#\nif test \"$ac_cv_func_lsocket\" != no ; then\nAC_CHECK_FUNCS(socket,,[\n        CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[\n                CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])\nfi\n#\nAC_CHECK_FUNCS(gethostbyname,,[\n        CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])\n])\nLIBS=\"$LIBS $cf_cv_netlibs\"\ntest $cf_test_netlibs = no && echo \"$cf_cv_netlibs\" >&AC_FD_MSG\n])dnl\ndnl ---------------------------------------------------------------------------\ndnl Re-check on a function to see if we can pick it up by adding a library.\ndnl\t$1 = function to check\ndnl\t$2 = library to check in\ndnl\t$3 = environment to update (e.g., $LIBS)\ndnl\t$4 = what to do if this fails\ndnl\ndnl This uses 'unset' if the shell happens to support it, but leaves the\ndnl configuration variable set to 'unknown' if not.  This is a little better\ndnl than the normal autoconf test, which gives misleading results if a test\ndnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is\ndnl used (autoconf does not distinguish between a null token and one that is\ndnl set to 'no').\nAC_DEFUN([CF_RECHECK_FUNC],[\nAC_CHECK_LIB($2,$1,[\n        CF_UPPER(cf_tr_func,$1)\n        AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1])\n        ac_cv_func_$1=yes\n        $3=\"-l$2 [$]$3\"],[\n        ac_cv_func_$1=unknown\n        unset ac_cv_func_$1 2>/dev/null\n        $4],\n        [[$]$3])\n])dnl\ndnl ---------------------------------------------------------------------------\ndnl Make an uppercase version of a variable\ndnl $1=uppercase($2)\nAC_DEFUN([CF_UPPER],\n[\nchangequote(,)dnl\n$1=`echo $2 | tr '[a-z]' '[A-Z]'`\nchangequote([,])dnl\n])dnl\n\n\ndnl ---------------------------------------------------------------------------\ndnl From Paul Eggert <eggert@twinsun.com>\ndnl Update for Darwin by Troy Runkel <Troy.Runkel@mathworks.com>\ndnl Update for AIX by Olexiy Buyanskyy (Savannah bug 32485)\n\nAC_DEFUN([AC_STRUCT_ST_MTIM_NSEC],\n [AC_CACHE_CHECK([for nanoseconds field of struct stat],\n   ac_cv_struct_st_mtim_nsec,\n   [ac_save_CPPFLAGS=\"$CPPFLAGS\"\n    ac_cv_struct_st_mtim_nsec=no\n    # st_mtim.tv_nsec -- the usual case\n    # st_mtim._tv_nsec -- Solaris 2.6, if\n    #\t(defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1\n    #\t && !defined __EXTENSIONS__)\n    # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2\n    # st_mtime_n -- AIX 5.2 and above\n    # st_mtimespec.tv_nsec -- Darwin (Mac OSX)\n    for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do\n      CPPFLAGS=\"$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val\"\n      AC_TRY_COMPILE([#include <sys/types.h>\n#include <sys/stat.h>\n        ], [struct stat s; s.ST_MTIM_NSEC;],\n        [ac_cv_struct_st_mtim_nsec=$ac_val; break])\n    done\n    CPPFLAGS=\"$ac_save_CPPFLAGS\"\n   ])\n\n  if test $ac_cv_struct_st_mtim_nsec != no; then\n    AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec],\n        [Define if struct stat contains a nanoseconds field])\n  fi\n ]\n)\n"
  },
  {
    "path": "gl/m4/dospaths.m4",
    "content": "# Test if the system uses DOS-style pathnames (drive specs and backslashes)\n# By Paul Smith <psmith@gnu.org>.  Based on dos.m4 by Jim Meyering.\n#\n# Copyright (C) 1993-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAC_DEFUN([pds_AC_DOS_PATHS], [\n  AC_CACHE_CHECK([whether system uses MSDOS-style paths], [ac_cv_dos_paths], [\n    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[\n#if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __EMX__ && !defined __MSYS__ && !defined __CYGWIN__\nneither MSDOS nor Windows nor OS2\n#endif\n]])],\n        [ac_cv_dos_paths=yes],\n        [ac_cv_dos_paths=no])])\n\n  AS_IF([test x\"$ac_cv_dos_paths\" = xyes],\n  [ AC_DEFINE_UNQUOTED([HAVE_DOS_PATHS], 1,\n                       [Define if the system uses DOS-style pathnames.])])\n])\n"
  },
  {
    "path": "gl/m4/getloadavg.m4",
    "content": "# Check for getloadavg.\n\n# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free\n# Software Foundation, Inc.\n\n# This file is free software; the Free Software Foundation\n# gives unlimited permission to copy and/or distribute it,\n# with or without modifications, as long as this notice is preserved.\n\n#serial 10\n\n# Autoconf defines AC_FUNC_GETLOADAVG, but that is obsolescent.\n# New applications should use gl_GETLOADAVG instead.\n\n# gl_GETLOADAVG\n# -------------\nAC_DEFUN([gl_GETLOADAVG],\n[AC_REQUIRE([gl_STDLIB_H_DEFAULTS])\n\n# Persuade glibc <stdlib.h> to declare getloadavg().\nAC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])\n\ngl_save_LIBS=$LIBS\n\n# getloadavg is present in libc on glibc >= 2.2, Mac OS X, FreeBSD >= 2.0,\n# NetBSD >= 0.9, OpenBSD >= 2.0, Solaris >= 7.\nHAVE_GETLOADAVG=1\nAC_CHECK_FUNC([getloadavg], [],\n  [gl_func_getloadavg_done=no\n\n   # Some systems with -lutil have (and need) -lkvm as well, some do not.\n   # On Solaris, -lkvm requires nlist from -lelf, so check that first\n   # to get the right answer into the cache.\n   # For kstat on solaris, we need to test for libelf and libkvm to force the\n   # definition of SVR4 below.\n   if test $gl_func_getloadavg_done = no; then\n     AC_CHECK_LIB([elf], [elf_begin], [LIBS=\"-lelf $LIBS\"])\n     AC_CHECK_LIB([kvm], [kvm_open], [LIBS=\"-lkvm $LIBS\"])\n     # Check for the 4.4BSD definition of getloadavg.\n     AC_CHECK_LIB([util], [getloadavg],\n       [LIBS=\"-lutil $LIBS\" gl_func_getloadavg_done=yes])\n   fi\n\n   if test $gl_func_getloadavg_done = no; then\n     # There is a commonly available library for RS/6000 AIX.\n     # Since it is not a standard part of AIX, it might be installed locally.\n     gl_getloadavg_LIBS=$LIBS\n     if test $cross_compiling != yes; then\n       LIBS=\"-L/usr/local/lib $LIBS\"\n     fi\n     AC_CHECK_LIB([getloadavg], [getloadavg],\n                  [LIBS=\"-lgetloadavg $LIBS\" gl_func_getloadavg_done=yes],\n                  [LIBS=$gl_getloadavg_LIBS])\n   fi\n\n   # Set up the replacement function if necessary.\n   if test $gl_func_getloadavg_done = no; then\n     HAVE_GETLOADAVG=0\n\n     # Solaris has libkstat which does not require root.\n     AC_CHECK_LIB([kstat], [kstat_open])\n     test $ac_cv_lib_kstat_kstat_open = yes && gl_func_getloadavg_done=yes\n\n     # AIX has libperfstat which does not require root\n     if test $gl_func_getloadavg_done = no; then\n       AC_CHECK_LIB([perfstat], [perfstat_cpu_total])\n       test $ac_cv_lib_perfstat_perfstat_cpu_total = yes && gl_func_getloadavg_done=yes\n     fi\n\n     if test $gl_func_getloadavg_done = no; then\n       AC_CHECK_HEADER([sys/dg_sys_info.h],\n         [gl_func_getloadavg_done=yes\n          AC_DEFINE([DGUX], [1], [Define to 1 for DGUX with <sys/dg_sys_info.h>.])\n          AC_CHECK_LIB([dgc], [dg_sys_info])])\n     fi\n   fi])\n\nif test \"x$gl_save_LIBS\" = x; then\n  GETLOADAVG_LIBS=$LIBS\nelse\n  GETLOADAVG_LIBS=`echo \"$LIBS\" | sed \"s!$gl_save_LIBS!!\"`\nfi\nLIBS=$gl_save_LIBS\n\nAC_SUBST([GETLOADAVG_LIBS])dnl\n\n# Test whether the system declares getloadavg. Solaris has the function\n# but declares it in <sys/loadavg.h>, not <stdlib.h>.\nAC_CHECK_HEADERS([sys/loadavg.h])\nif test $ac_cv_header_sys_loadavg_h = yes; then\n  HAVE_SYS_LOADAVG_H=1\nelse\n  HAVE_SYS_LOADAVG_H=0\nfi\nAC_CHECK_DECL([getloadavg], [], [HAVE_DECL_GETLOADAVG=0],\n  [[#if HAVE_SYS_LOADAVG_H\n    /* OpenIndiana has a bug: <sys/time.h> must be included before\n       <sys/loadavg.h>.  */\n    # include <sys/time.h>\n    # include <sys/loadavg.h>\n    #endif\n    #include <stdlib.h>]])\n])# gl_GETLOADAVG\n\n\n# gl_PREREQ_GETLOADAVG\n# --------------------\n# Set up the AC_LIBOBJ replacement of 'getloadavg'.\nAC_DEFUN([gl_PREREQ_GETLOADAVG],\n[\n# Figure out what our getloadavg.c needs.\n\nAC_CHECK_HEADERS_ONCE([sys/param.h unistd.h])\n\n# On HPUX9, an unprivileged user can get load averages this way.\nif test $gl_func_getloadavg_done = no; then\n  AC_CHECK_FUNCS([pstat_getdynamic], [gl_func_getloadavg_done=yes])\nfi\n\n# We cannot check for <dwarf.h>, because Solaris 2 does not use dwarf (it\n# uses stabs), but it is still SVR4.  We cannot check for <elf.h> because\n# Irix 4.0.5F has the header but not the library.\nif test $gl_func_getloadavg_done = no && test \"$ac_cv_lib_elf_elf_begin\" = yes \\\n    && test \"$ac_cv_lib_kvm_kvm_open\" = yes; then\n  gl_func_getloadavg_done=yes\n  AC_DEFINE([SVR4], [1], [Define to 1 on System V Release 4.])\nfi\n\nif test $gl_func_getloadavg_done = no; then\n  AC_CHECK_HEADER([inq_stats/cpustats.h],\n  [gl_func_getloadavg_done=yes\n   AC_DEFINE([UMAX], [1], [Define to 1 for Encore UMAX.])\n   AC_DEFINE([UMAX4_3], [1],\n             [Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h>\n              instead of <sys/cpustats.h>.])])\nfi\n\nif test $gl_func_getloadavg_done = no; then\n  AC_CHECK_HEADER([sys/cpustats.h],\n  [gl_func_getloadavg_done=yes; AC_DEFINE([UMAX])])\nfi\n\nif test $gl_func_getloadavg_done = no; then\n  AC_CHECK_HEADERS([mach/mach.h])\nfi\n\nAC_CHECK_HEADERS([nlist.h],\n[AC_CHECK_MEMBERS([struct nlist.n_un.n_name],\n                  [], [],\n                  [#include <nlist.h>])\n AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <nlist.h>]],\n                   [[struct nlist x;\n                    #ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME\n                    x.n_un.n_name = \"\";\n                    #else\n                    x.n_name = \"\";\n                    #endif]])],\n                [AC_DEFINE([N_NAME_POINTER], [1],\n                           [Define to 1 if the nlist n_name member is a pointer])])\n])dnl\n])# gl_PREREQ_GETLOADAVG\n\n# ---- GNU Make\n# These macros are imported from stdlib which we don't want to include\n# Only the getloadavg content is imported.\n\nAC_DEFUN_ONCE([gl_STDLIB_H],\n[\n  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])\n\n  dnl Check for declarations of anything we want to poison if the\n  dnl corresponding gnulib module is not in use, and which is not\n  dnl guaranteed by C89.\n  gl_WARN_ON_USE_PREPARE([[#include <stdlib.h>\n#if HAVE_SYS_LOADAVG_H\n/* OpenIndiana has a bug: <sys/time.h> must be included before\n   <sys/loadavg.h>.  */\n# include <sys/time.h>\n# include <sys/loadavg.h>\n#endif\n#if HAVE_RANDOM_H\n# include <random.h>\n#endif\n    ]], [getloadavg])\n])\n\n# gl_STDLIB_MODULE_INDICATOR([modulename])\n# sets the shell variable that indicates the presence of the given module\n# to a C preprocessor expression that will evaluate to 1.\n# This macro invocation must not occur in macros that are AC_REQUIREd.\nAC_DEFUN([gl_STDLIB_MODULE_INDICATOR],\n[\n  dnl Ensure to expand the default settings once only.\n  gl_STDLIB_H_REQUIRE_DEFAULTS\n  gl_MODULE_INDICATOR_SET_VARIABLE([$1])\n  dnl Define it also as a C macro, for the benefit of the unit tests.\n  gl_MODULE_INDICATOR_FOR_TESTS([$1])\n])\n\n# Initializes the default values for AC_SUBSTed shell variables.\n# This macro must not be AC_REQUIREd.  It must only be invoked, and only\n# outside of macros or in macros that are not AC_REQUIREd.\nAC_DEFUN([gl_STDLIB_H_REQUIRE_DEFAULTS],\n[\n  m4_defun(GL_MODULE_INDICATOR_PREFIX[_STDLIB_H_MODULE_INDICATOR_DEFAULTS], [\n    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETLOADAVG])\n  ])\n  m4_require(GL_MODULE_INDICATOR_PREFIX[_STDLIB_H_MODULE_INDICATOR_DEFAULTS])\n  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])\n])\n\nAC_DEFUN([gl_STDLIB_H_DEFAULTS],\n[\n  dnl Assume proper GNU behavior unless another module says otherwise.\n  HAVE_DECL_GETLOADAVG=1;    AC_SUBST([HAVE_DECL_GETLOADAVG])\n])\n"
  },
  {
    "path": "gl/modules/concat-filename",
    "content": "Description:\nConstruct a full filename by concatenating a directory name, a relative\nfilename, and a suffix.\n\nFiles:\nlib/concat-filename.h\nlib/concat-filename.c\n\nDepends-on:\nfilename\n\nconfigure.ac:\n\nMakefile.am:\nlib_SOURCES += concat-filename.c\n\nInclude:\n\"concat-filename.h\"\n\nLicense:\nLGPLv2+\n\nMaintainer:\nall\n"
  },
  {
    "path": "gl/modules/findprog-in",
    "content": "Description:\nLocating a program in a given path.\n\nFiles:\nlib/findprog.h\nlib/findprog-in.c\nm4/findprog-in.m4\nm4/eaccess.m4\n\nDepends-on:\nstdbool\nfilename\nconcat-filename\n\nconfigure.ac:\ngl_FINDPROG_IN\n\nMakefile.am:\nlib_SOURCES += findprog.h findprog-in.c\n\nInclude:\n\"findprog.h\"\n\nLicense:\nLGPLv2+\n\nMaintainer:\nall\n"
  },
  {
    "path": "gl/modules/getloadavg",
    "content": "Description:\nReturn the current system load averages.\n\nFiles:\nlib/getloadavg.c\nm4/getloadavg.m4\n\nDepends-on:\nsnippet/warn-on-use\nextensions\nintprops  [test $HAVE_GETLOADAVG = 0]\nstdbool   [test $HAVE_GETLOADAVG = 0]\n\nconfigure.ac:\ngl_STDLIB_H\ngl_STDLIB_H_REQUIRE_DEFAULTS\nAC_REQUIRE([AC_CANONICAL_HOST])\ngl_GETLOADAVG\ngl_CONDITIONAL([GL_COND_OBJ_GETLOADAVG], [test $HAVE_GETLOADAVG = 0])\nAM_COND_IF([GL_COND_OBJ_GETLOADAVG], [\n  gl_PREREQ_GETLOADAVG\n])\ngl_STDLIB_MODULE_INDICATOR([getloadavg])\n\nMakefile.am:\nif GL_COND_OBJ_GETLOADAVG\nlib_SOURCES += getloadavg.c\nendif\n\nInclude:\n<stdlib.h>\n\nLink:\n$(GETLOADAVG_LIBS)\n\nLicense:\nGPL\n\nMaintainer:\nJim Meyering\n"
  },
  {
    "path": "gl/modules/make-glob",
    "content": "Description:\nGNU Make version of fnmatch()/glob() functions.  This is a holdover from\na very old version of the globbing library.\n\nFiles:\nlib/fnmatch.c\nlib/fnmatch.in.h\nlib/glob.c\nlib/glob.in.h\n\nconfigure.ac:\n# Check the system to see if it provides GNU glob.  If not, use our\n# local version.  Also avoid versions of glibc which have symlink bug\n# https://sourceware.org/bugzilla/show_bug.cgi?id=866 (test from gnulib)\nAC_CACHE_CHECK([if system libc has working GNU glob], [make_cv_sys_gnu_glob],[\n  if ln -s conf-doesntexist conf$$-globtest 2>/dev/null; then\n    make_check_symlink=yes\n  else\n    make_check_symlink=no\n  fi\n  if test $cross_compiling = yes || test $make_check_symlink = no; then\n    # When cross-compiling or without symlink support, check the version\n    AC_COMPILE_IFELSE(\n      [AC_LANG_PROGRAM(\n        [[#include <features.h>\n          #include <gnu-versions.h>\n          #include <glob.h>\n          #include <fnmatch.h>\n        ]],\n        [[\n          #if _GNU_GLOB_INTERFACE_VERSION == 0\n            GNU glob not available in libc\n          #elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 27)\n            GNU glob in libc has dangling symlink bug\n          #endif\n        ]])],\n      [make_cv_sys_gnu_glob=yes],\n      [make_cv_sys_gnu_glob=no])\n  else\n    # Check for GNU glob, and that it handles dangling symlinks properly\n    AC_RUN_IFELSE(\n      [AC_LANG_PROGRAM(\n        [[#include <features.h>\n          #include <gnu-versions.h>\n          #include <glob.h>\n          #include <fnmatch.h>\n        ]],\n        [[\n          #if _GNU_GLOB_INTERFACE_VERSION == 0\n          return 1;\n          #else\n          glob_t found;\n          if (glob (\"conf*-globtest\", 0, 0, &found) == GLOB_NOMATCH)\n            return 1;\n          globfree (&found);\n          #endif\n        ]])],\n      [make_cv_sys_gnu_glob=yes],\n      [make_cv_sys_gnu_glob=no],\n      [dnl We don't get here.\n       :\n      ])\n  fi\n  test $make_check_symlink = no || rm -f conf$$-globtest\n])\n\n# Tell automake about this, so it can build the right .c files.\nAM_CONDITIONAL([USE_SYSTEM_GLOB], [test \"$make_cv_sys_gnu_glob\" = yes])\n\n# Tell build.sh which to use\nUSE_SYSTEM_GLOB=\"$make_cv_sys_gnu_glob\"\nAC_SUBST([USE_SYSTEM_GLOB])\n\nMakefile.am:\nif !USE_SYSTEM_GLOB\nlibgnu_a_SOURCES += fnmatch.c\n\nBUILT_SOURCES += fnmatch.h\n\nfnmatch.h: fnmatch.in.h $(top_builddir)/config.status\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \\\n\t  cat $(srcdir)/fnmatch.in.h; \\\n\t} > $@-t && \\\n\tmv -f $@-t $@\n\nMOSTLYCLEANFILES += fnmatch.h fnmatch.h-t\n\nlibgnu_a_SOURCES += glob.c\n\nBUILT_SOURCES += glob.h\n\nglob.h: glob.in.h $(top_builddir)/config.status\n\t$(AM_V_GEN)rm -f $@-t $@ && \\\n\t{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \\\n\t  cat $(srcdir)/glob.in.h; \\\n\t} > $@-t && \\\n\tmv -f $@-t $@\n\nMOSTLYCLEANFILES += glob.h glob.h-t\nendif\n\nEXTRA_DIST += fnmatch.in.h glob.in.h\n\nInclude:\n<glob.h>\n\nLicense:\nLGPLv2+\n\nMaintainer:\nall, glibc\n"
  },
  {
    "path": "gl/modules/make-macros",
    "content": "Description:\nInstall m4 macros for GNU Make.\n\nFiles:\nm4/acinclude.m4\nm4/dospaths.m4\n\nconfigure.ac:\n# Check for DOS-style pathnames.\npds_AC_DOS_PATHS\n\nLicense:\nGPLv3+\n\nMaintainer:\ngnumake\n"
  },
  {
    "path": "maintMakefile",
    "content": "# Maintainer-only makefile segment.  This contains things that are relevant\n# only if you have the full copy of the GNU Make sources from the Git\n# tree, not a dist copy.\n\n# --------------------- #\n# Updating everything.  #\n# --------------------- #\n\n.PHONY: update\nupdate:\n\nBUGLIST := bug-make@gnu.org\n\n# These are related to my personal setup.\nGPG_KEYID := 80CB727A20C79BB2\n\n# SRCROOTDIR is just a handy location to keep source files in\nSRCROOTDIR ?= $(HOME)/src\n\n# Where to put the CVS checkout of the GNU web repository\nGNUWEBDIR ?= $(SRCROOTDIR)/gnu-www\n\n# Where to put the CVS checkout of the GNU Make web repository\nMAKEWEBDIR ?= $(SRCROOTDIR)/make/make-web\n\n# Enable Perl warnings for the test suite\nPERLFLAGS := -w\n\n# We like mondo-warnings!\n# Also force comments to be preserved.  This helps when using ccache, in\n# combination with GCC 7's implicit-fallthrough warning.\nMAKE_CFLAGS := -C -Wall -Wextra -Werror -Wwrite-strings -Wshadow \\\n\t-Wdeclaration-after-statement -Wbad-function-cast -Wformat-security \\\n\t-Wtype-limits -Wunused-but-set-parameter -Wlogical-op -Wpointer-arith \\\n\t-Wignored-qualifiers -Wformat-signedness -Wduplicated-cond\n\n# Allow extra options without overriding MAKE_CFLAGS\nEXTRA_CFLAGS :=\n\nAM_CFLAGS += $(MAKE_CFLAGS) $(EXTRA_CFLAGS)\n\n# Unfortunately the Guile headers are sometimes broken.  Convince GCC\n# to treat them as system headers so warnings are ignored.\nGUILE_CFLAGS := $(patsubst -I%,-isystem %,$(GUILE_CFLAGS))\n\nMAKE_MAINTAINER_MODE := -DMAKE_MAINTAINER_MODE\nAM_CPPFLAGS += $(MAKE_MAINTAINER_MODE)\n\n# Create preprocessor output files--GCC specific!\n%.i : %.c\n\t$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) -E -dD -o $@ $<\n\n# Create the mkconfig.h file for non-POSIX config headers\n\nall: src/mkconfig.h\nsrc/mkconfig.h: src/mkconfig.h.in config.status\n\t./config.status --header=$@\n\n# Build the README\n\nall: README\nREADME : README.in config.status\n\t./config.status --file=$@\n\n# Construct Makefiles by adding on dependencies, etc.\n#\ncvt = $(patsubst $1/%,$$($1)%,$(filter %.c,$2))\nBasic.mk: Basic.mk.template .dep_segment Makefile\n\trm -f $@\n\tsed -e 's@%make_SOURCES%@$(call cvt,src,$(make_SRCS))@g' \\\n\t    -e 's@%w32_SOURCES%@$(call cvt,src,$(w32_SRCS))@g' \\\n\t    -e 's@%vms_SOURCES%@$(call cvt,src,$(vms_SRCS))@g' \\\n\t    -e 's@%loadavg_SOURCES%@$(call cvt,lib,$(loadavg_SRCS))@g' \\\n\t    -e 's@%alloca_SOURCES%@$(call cvt,lib,$(alloca_SRCS))@g' \\\n\t    -e 's@%glob_SOURCES%@$(call cvt,lib,$(glob_SRCS))@g' \\\n\t  $< > $@\n\techo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \\\n\techo >>$@; echo '$$(OBJECTS): $$(SRCDIR)/src/mkconfig.h' >>$@; \\\n\tsed -e 's@^\\([^ ]*\\)\\.o:@$$(OUTDIR)\\1.$$(OBJEXT):@' \\\n\t    -e 's@\\([^ ]*\\.[ch]\\)@$$(SRCDIR)/\\1@g' \\\n\t    -e 's@$$(SRCDIR)/src/config.h@$$(OUTDIR)src/config.h@g' \\\n\t    -e 's@$$(SRCDIR)/lib/alloca.h@@g' \\\n\t    -e 's@$$(SRCDIR)/lib/stdbool.h@@g' \\\n\t  $(word 2,$^) >>$@\n\tchmod a-w $@\n\n\n# Use automake to build a dependency list file, for Makebase.mk.\n#\n# Automake used to have a --generate-deps flag but it's gone now, so we have\n# to do it ourselves.\n#\nDEP_FILES := $(wildcard src/$(DEPDIR)/*.Po)\n.dep_segment: Makefile.am maintMakefile $(DEP_FILES)\n\trm -f $@\n\t(for f in src/$(DEPDIR)/*.Po; do \\\n\t   echo \"\"; \\\n\t   echo \"# $$f\"; \\\n\t   sed\t-e '/^[^:]*\\.[ch] *:/d' \\\n\t\t-e 's, /usr/[^ ]*,,g' \\\n\t\t-e 's, $(srcdir)/, ,g' \\\n\t\t-e '/^ *\\\\$$/d' \\\n\t\t-e '/^ *$$/d' \\\n\t\t< $$f; \\\n\t done) > $@\n\n# Cleaning\n\nGIT :=\tgit\n\n# git-clean:      Clean all \"ignored\" files.  Leave untracked files.\n# git-very-clean: Clean all files that aren't stored in source control.\n\n.PHONY: git-clean git-very-clean\ngit-clean:\n\t-$(GIT) clean -fdX\ngit-very-clean: git-clean\n\t-$(GIT) clean -fdx\n\n\n## ---------------------- ##\n## Generating ChangeLog.  ##\n## ---------------------- ##\n\n# Where the gnulib project has been locally cloned\nGNULIBDIR ?= $(or $(wildcard $(GNULIB_SRCDIR)),./gnulib)\n\ngl2cl-date := 2013-10-10\ngl2cl := $(GNULIBDIR)/build-aux/gitlog-to-changelog\n\n# Rebuild the changelog whenever a new commit is added\nChangeLog: .check-git-HEAD\n\tif test -f '$(gl2cl)'; then \\\n\t    '$(gl2cl)' --since='$(gl2cl-date)' > '$@'; \\\n\telse \\\n\t    echo \"WARNING: $(gl2cl) is not available.  No $@ generated.\"; \\\n\tfi\n\n.check-git-HEAD: FORCE\n\tsha=\"`git rev-parse HEAD`\"; \\\n\ttest -f '$@' && [ \"`cat '$@' 2>/dev/null`\" = \"$$sha\" ] \\\n\t    || echo \"$$sha\" > '$@'\n\n.PHONY: FORCE\nFORCE:;@:\n\n## ---------------- ##\n## Updating files.  ##\n## ---------------- ##\nRSYNC = rsync -Lrtvz\nWGET = wget --passive-ftp -np -nv\nftp-gnu = ftp://ftp.gnu.org/gnu\n\nmove_if_change =  if test -r $(target) && cmp -s $(target).t $(target); then \\\n\t\t    echo $(target) is unchanged; rm -f $(target).t; \\\n\t\t  else \\\n\t\t    mv -f $(target).t $(target); \\\n\t\t  fi\n\n# ------------------- #\n# Updating PO files.  #\n# ------------------- #\n\n# NOTE: This is handled by the bootstrap script now\n\n#update: po-update\nupdate: po-check\n\n# PO archive mirrors --- Be careful; some might not be fully populated!\n#   ftp://ftp.unex.es/pub/gnu-i18n/po/maint/\n#   ftp://tiger.informatik.hu-berlin.de/pub/po/maint/\n\npo_wget_flags = --recursive --level=1 --no-directories --no-check-certificate\npo_repo = https://translationproject.org/latest/$(PACKAGE)\npo_sync = translationproject.org::tp/latest/$(PACKAGE)/\n\n.PHONY: do-po-update po-update\ndo-po-update:\n\ttmppo=\"/tmp/po-$(PACKAGE)-$(PACKAGE_VERSION).$$$$\" \\\n\t  && rm -rf \"$$tmppo\" \\\n\t  && mkdir \"$$tmppo\" \\\n\t  && $(RSYNC) $(po_sync)  \"$$tmppo\" \\\n\t  && cp \"$$tmppo\"/*.po $(top_srcdir)/po \\\n\t  && rm -rf \"$$tmppo\"\n\tcd po && $(MAKE) update-po\n\t$(MAKE) po-check\n\npo-update:\n\ttest -d \"po\" && $(MAKE) do-po-update\n\n# -------------------------- #\n# Updating GNU build files.  #\n# -------------------------- #\n\n# Note: this is handled by the bootstrap script now\n#update: scm-update\n\n.PHONY: scm-update\nscm-update: get-build-aux/texinfo.tex get-build-aux/config.guess \\\n\t\tget-build-aux/config.sub get-doc/make-stds.texi get-doc/fdl.texi\n\n# The following pseudo table associates a local directory and a URL\n# with each of the files that belongs to some other package and is\n# regularly updated from the specified URL.\n\ncvs-url = https://savannah.gnu.org/cgi-bin/viewcvs/~checkout~\ngit-url = https://git.savannah.gnu.org/cgit\ntarget = $(patsubst get-%,%,$@)\n\nconfig-url = $(git-url)/config.git/plain/$(patsubst get-build-aux/%,%,$@)\nget-build-aux/config.guess get-build-aux/config.sub:\n\t@echo Retrieving $(target) from $(config-url)\n\t$(WGET) $(config-url) -O $(target).t \\\n\t  && $(move_if_change)\n\ngnulib-url = $(git-url)/gnulib.git/plain/build-aux/$(patsubst get-build-aux/%,%,$@)\nget-build-aux/texinfo.tex:\n\t@echo Retrieving $(target) from $(gnulib-url)\n\t$(WGET) $(gnulib-url) -O $(target).t \\\n\t  && $(move_if_change)\n\ngnustandards-url = $(cvs-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@)\nget-doc/make-stds.texi get-doc/fdl.texi:\n\t@echo Retrieving $(target) from $(gnustandards-url)\n\t$(WGET) $(gnustandards-url) -O $(target).t \\\n\t  && $(move_if_change)\n\n\n# ---------------------------- #\n# Extra configuration checks.  #\n# ---------------------------- #\n\n# Make the dist file contents more regular, if we're using GNU tar.\n# Suggested by Tzvetelin Katchov <katchov@gnu.org>\n\nexport TAR_OPTIONS := --mode=u+w,go-w --owner=0 --group=0 --numeric-owner --sort=name\n\n# When I released 4.3 somehow the INSTALL file was missing.\n# When I tried to build it again, it was there.  I have no idea what happened\n# but add a new check to be sure it doesn't happen again.\nmk_dist_files = AUTHORS ChangeLog COPYING INSTALL README src/mkconfig.h\n\ndist: mk-dist mk-distcheck\n\n.PHONY: mk-distcheck\nmk-distcheck: distdir\n\t@echo \"Checking for extra installed files...\"\n\t@for fn in $(mk_dist_files); do \\\n\t    test -f '$(distdir)'/\"$$fn\" \\\n\t\t|| { echo \"Missing dist file: $$fn\"; exit 1; }; \\\n\tdone; true\n\n# Make sure that the files in lib/ have been updated from the files in gl/lib/\n\nGL_LIB_FILES := $(wildcard gl/lib/*)\n\nmk-dist:\n\t@echo \"Checking gl/lib files...\"\n\t@for fn in $(GL_LIB_FILES); do \\\n\t    cmp $$fn $${fn##gl/} \\\n\t\t|| { echo \"Run ./bootstrap --gen ?\"; exit 1; }; \\\n\tdone; true\n\n# ---------------------------------- #\n# Alternative configuration checks.  #\n# ---------------------------------- #\n\nCFGCHECK_CONFIGFLAGS =\nCFGCHECK_BUILDFLAGS  =\n# We can't use our mondo warnings as these are used to compile gnulib modules\n# as well, and that will fail.\nCFGCHECK_MAKEFLAGS   = # CFLAGS='$(AM_CFLAGS)'\n\n# We don't support C90 anymore, strictly, but this test still works (with lots\n# of warnings) and it helps us avoid egregious incompatibilities.\ncheckcfg.strict-c90:  CFGCHECK_CONFIGFLAGS = CFLAGS='-std=c90 -pedantic'\ncheckcfg.strict-c90:  CFGCHECK_MAKEFLAGS   =\n\ncheckcfg.job-pipe:    CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DJOBSERVER_USE_FIFO=0\ncheckcfg.no-jobserver:CFGCHECK_CONFIGFLAGS = --disable-job-server\ncheckcfg.no-load:     CFGCHECK_CONFIGFLAGS = --disable-load\ncheckcfg.no-guile:    CFGCHECK_CONFIGFLAGS = --without-guile\ncheckcfg.no-spawn:    CFGCHECK_CONFIGFLAGS = --disable-posix-spawn\ncheckcfg.no-sysglob:  CFGCHECK_CONFIGFLAGS = make_cv_sys_gnu_glob=no\ncheckcfg.no-loadavg:  CFGCHECK_CONFIGFLAGS = ac_cv_func_getloadavg=no \\\n\t\t\t\t\t     ac_cv_have_decl_getloadavg=no \\\n\t\t\t\t\t     gl_cv_have_raw_decl_getloadavg=no \\\n\t\t\t\t\t     ac_cv_lib_util_getloadavg=no \\\n\t\t\t\t\t     ac_cv_lib_getloadavg_getloadavg=no\ncheckcfg.no-sync:     CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DNO_OUTPUT_SYNC\ncheckcfg.no-archives: CFGCHECK_CONFIGFLAGS = CPPFLAGS=-DNO_ARCHIVES\n\nCONFIG_CHECKS := \\\n\tcheckcfg.strict-c90 \\\n\tcheckcfg.job-pipe \\\n\tcheckcfg.no-jobserver \\\n\tcheckcfg.no-load \\\n\tcheckcfg.no-guile \\\n\tcheckcfg.no-spawn \\\n\tcheckcfg.no-sysglob \\\n\tcheckcfg.no-loadavg \\\n\tcheckcfg.no-sync \\\n\tcheckcfg.no-archives\n\n.PHONY: check-alt-config\ncheck-alt-config: $(CONFIG_CHECKS)\n\t@echo --- $@ SUCCESS\n\n# Trick GNU Make so it doesn't run the submake as a recursive make.\nNR_MAKE = $(MAKE)\n\n# Check builds both with build.sh and with make\nbuild.sh_SCRIPT = exec >>'checkcfg.$*.log' 2>&1; set -x; \\\n\t\tcd $(distdir)/_build \\\n\t\t&& OUTDIR=_bld ../build.sh -k $(CFGCHECK_BUILD_FLAGS) \\\n\t\t&& _bld/make GMK_OUTDIR=../_bld $(AM_MAKEFLAGS) check-local \\\n\t\t&& _bld/make GMK_OUTDIR=../_bld $(AM_MAKEFLAGS) clean\n\nnrmake_SCRIPT = exec >>'checkcfg.$*.log' 2>&1; set -x; \\\n\t\tcd $(distdir)/_build \\\n\t\t&& $(NR_MAKE) $(AM_MAKEFLAGS) $(CFGCHECK_MAKEFLAGS) \\\n\t\t&& ./make $(AM_MAKEFLAGS) check \\\n\t\t&& ./make $(AM_MAKEFLAGS) clean\n\n$(CONFIG_CHECKS): checkcfg.%: distdir\n\t@echo \"Building $@ (output in checkcfg.$*.log)\"\n\texec >'checkcfg.$*.log' 2>&1; \\\n\t   echo \"Testing configure with $(CFGCHECK_CONFIGFLAGS)\"; set -x; \\\n\t   rm -rf $(distdir)/_build \\\n\t&& mkdir $(distdir)/_build \\\n\t&& cd $(distdir)/_build \\\n\t&& ../configure --srcdir=.. $(CFGCHECK_CONFIGFLAGS) \\\n\t       $(AM_DISTCHECK_CONFIGURE_FLAGS) $(DISTCHECK_CONFIGURE_FLAGS)\n\t$(build.sh_SCRIPT)\n\t$(nrmake_SCRIPT)\n\n# Try using Basic.mk.  I can't test this on POSIX systems because it is only\n# used for non-POSIX systems; POSIX systems can just use normal\n# configure/Makefile.in etc.\ncheckcfg.basicmk: checkcfg.% : distdir\n\t@echo \"Building $@ (output in checkcfg.$*.log)\"\n\texec >'checkcfg.$*.log' 2>&1; \\\n\t   echo \"Testing Basic.mk SRCDIR=..\"; set -x; \\\n\t   rm -rf $(distdir)/_build \\\n\t&& mkdir $(distdir)/_build \\\n\t&& cd $(distdir)/_build \\\n\t&& ../configure --srcdir=.. \\\n\t       $(AM_DISTCHECK_CONFIGURE_FLAGS) $(DISTCHECK_CONFIGURE_FLAGS)\n\texec >>'checkcfg.$*.log' 2>&1; set -x; \\\n\t   cd $(distdir)/_build \\\n\t&& $(NR_MAKE) $(AM_MAKEFLAGS) -f ../Basic.mk SRCDIR=.. $(CFGCHECK_MAKEFLAGS)\n\t&& ./make $(AM_MAKEFLAGS) -f ../Basic.mk SRCDIR=.. check \\\n\t&& ./make $(AM_MAKEFLAGS) -f ../Basic.mk SRCDIR=.. clean\n\texec >>'checkcfg.$*.log' 2>&1; \\\n\t   echo \"Testing Basic.mk SRCDIR=.\"; set -x; \\\n\t&& rm -rf $(distdir)/_build \\\n\t&& cd $(distdir) \\\n\t&& ./configure \\\n\t       $(AM_DISTCHECK_CONFIGURE_FLAGS) $(DISTCHECK_CONFIGURE_FLAGS) \\\n\t&& $(NR_MAKE) $(AM_MAKEFLAGS) -f Basic.mk '$(CFGCHECK_MAKEFLAGS)' \\\n\t&& ./make $(AM_MAKEFLAGS) -f Basic.mk check \\\n\t&& ./make $(AM_MAKEFLAGS) -f Basic.mk clean\n\n\n## --------------- ##\n## Sanity checks.  ##\n## --------------- ##\n\n# Before we build a distribution be sure we run our local checks\n#distdir: local-check\n\n.PHONY: local-check po-check changelog-check\n\n# Checks that don't require Git.  Run 'changelog-check' last as\n# previous test may reveal problems requiring new ChangeLog entries.\nlocal-check: po-check changelog-check\n\n# copyright-check writable-files\n\nchangelog-check:\n\tif head $(top_srcdir)/ChangeLog | grep 'Version $(PACKAGE_VERSION)' >/dev/null; then \\\n\t  :; \\\n\telse \\\n\t  echo \"$(PACKAGE_VERSION) not in ChangeLog\" 1>&2; \\\n\t  exit 1; \\\n\tfi\n\n# Verify that all source files using _() are listed in po/POTFILES.in.\n# Ignore src/makeint.h; it defines _().\npo-check:\n\tif test -f po/POTFILES.in; then \\\n\t  grep '^[^#]' po/POTFILES.in | sort > $@-1; \\\n\t  find [a-z]* -name '*.[ch]' | xargs grep -l '\\b_(' | grep -v src/makeint.h | sort > $@-2; \\\n\t  diff -u $@-1 $@-2 || exit 1; \\\n\t  rm -f $@-1 $@-2; \\\n\tfi\n\n\n## --------------- ##\n## Generate docs.  ##\n## --------------- ##\n\n.PHONY: update-makeweb gendocs\n\nCVS = cvs\n\nmakeweb-repo = $(USER)@cvs.sv.gnu.org:/web/make\ngnuweb-repo = :pserver:anonymous@cvs.sv.gnu.org:/web/www\ngnuweb-dir = www/server/standards\n\n# Get the GNU Make web page boilerplate etc.\nupdate-makeweb:\n\ttest -d '$(MAKEWEBDIR)' || mkdir -p '$(MAKEWEBDIR)'\n\ttest -d '$(MAKEWEBDIR)'/CVS \\\n\t    && { cd '$(MAKEWEBDIR)' && $(CVS) update; } \\\n\t    || { mkdir -p '$(dir $(MAKEWEBDIR))' && cd '$(dir $(MAKEWEBDIR))' \\\n\t\t && $(CVS) -d $(makeweb-repo) co -d '$(notdir $(MAKEWEBDIR))' make; }\n\n# Get the GNU web page boilerplate etc.\nupdate-gnuweb:\n\ttest -d '$(GNUWEBDIR)' || mkdir -p '$(GNUWEBDIR)'\n\ttest -d '$(GNUWEBDIR)/$(gnuweb-dir)'/CVS \\\n\t    && { cd '$(GNUWEBDIR)/$(gnuweb-dir)' && $(CVS) update; } \\\n\t    || { cd '$(GNUWEBDIR)' && $(CVS) -d $(gnuweb-repo) co '$(gnuweb-dir)'; }\n\ngendocs: update-gnuweb update-makeweb\n\tcp $(GNULIBDIR)/doc/gendocs_template doc\n\tcd doc \\\n\t  && rm -rf doc/manual \\\n\t  && $(GNULIBDIR)/build-aux/gendocs.sh --email '$(BUGLIST)' \\\n\t\tmake '$(PACKAGE_NAME) Manual'\n\tfind '$(MAKEWEBDIR)'/manual \\( -name CVS -prune \\) -o \\( -name '[!.]*' -type f -exec rm -f '{}' \\; \\)\n\tcp -r doc/manual '$(MAKEWEBDIR)'\n\t@echo 'Status of $(MAKEWEBDIR) repo:' && cd '$(MAKEWEBDIR)' \\\n\t    && cvs -q -n update | grep -v '^M '\n\t@echo '- cvs add <new files>' \\\n\t    && echo '- cvs remove <deleted files>' \\\n\t    && echo '- cvs commit' \\\n\t    && echo '- cvs tag make-$(subst .,-,$(PACKAGE_VERSION))'\n\n\n## --------------------------------------------- ##\n## Submitting Coverity cov-build results to Scan ##\n## --------------------------------------------- ##\n\n# Note you must have set COVERITY_TOKEN and COVERITY_EMAIL properly\n# to submit results.  COVERITY_PATH can be set to the root of the\n# cov-build tools if it's not already on your PATH.\n\nCOV_BUILD_FILE := cov-build.tgz\n\n.PHONY: cov-build cov-submit\n\ncov-build: $(COV_BUILD_FILE)\n\n$(COV_BUILD_FILE): $(filter %.c %.h,$(DISTFILES))\n\t$(MAKE) distdir\n\t@echo \"Running Coverity cov-build\"\n\trm -rf '$(distdir)'/_build\n\tmkdir '$(distdir)'/_build\n\tcd '$(distdir)'/_build \\\n\t    && ../configure --srcdir=.. \\\n\t\t$(AM_DISTCHECK_CONFIGURE_FLAGS) $(DISTCHECK_CONFIGURE_FLAGS) \\\n\t\t$(CFGCHECK_MAKEFLAGS)\n\tPATH=\"$${COVERITY_PATH:+$$COVERITY_PATH/bin:}$$PATH\"; \\\n\t    cd '$(distdir)'/_build \\\n\t\t&& cov-build --dir cov-int ../build.sh\n\trm -f '$@'\n\t(cd '$(distdir)'/_build && tar czf - cov-int) > '$@'\n\ncov-submit: $(COV_BUILD_FILE)-submitted\n\n$(COV_BUILD_FILE)-submitted: $(COV_BUILD_FILE)\n\t@test -n \"$(COVERITY_TOKEN)\" || { echo 'COVERITY_TOKEN not set'; exit 1; }\n\t@test -n \"$(COVERITY_EMAIL)\" || { echo 'COVERITY_EMAIL not set'; exit 1; }\n\trm -f '$@'\n\tcase '$(PACKAGE_VERSION)' in \\\n\t    (*.*.9*) type=\"daily build\"; ext=\".$$(date +%Y%m%d)\" ;; \\\n\t    (*)      type=\"release\"; ext= ;; \\\n\tesac; \\\n\tcurl --form token='$(COVERITY_TOKEN)' \\\n\t     --form email='$(COVERITY_EMAIL)' \\\n\t     --form file='@$<' \\\n\t     --form version=\"$(PACKAGE_VERSION)$$ext\" \\\n\t     --form description=\"$(PACKAGE_NAME) $$type\" \\\n\t     'https://scan.coverity.com/builds?project=gmake'\n\tcp '$<' '$@'\n\n\n## ------------------------- ##\n## Make release targets.     ##\n## ------------------------- ##\n\n.PHONY: tag-release\ntag-release:\n\tcase '$(PACKAGE_VERSION)' in \\\n\t    (*.*.9*) message=\" candidate\" ;; \\\n\t    (*)      message= ;; \\\n\tesac; \\\n\t$(GIT) tag -m \"$(PACKAGE_NAME) release$$message $(PACKAGE_VERSION)\" -u '$(GPG_KEYID)' '$(PACKAGE_VERSION)'\n\n\n## ------------------------- ##\n## GNU FTP upload artifacts. ##\n## ------------------------- ##\n\n# This target creates the upload artifacts.\n# Sign it with my key.  If you don't have my key/passphrase then sorry,\n# you're SOL! :)\n\nGNUPLOAD := $(GNULIBDIR)/build-aux/gnupload\n\nUPLOADS = upload-alpha upload-ftp\n.PHONY: $(UPLOADS)\n$(UPLOADS): upload-%: $(DIST_ARCHIVES)\n\t$(GNUPLOAD) --user \"$(GPG_KEYID)\" --to \"$*.gnu.org:make\" -- $^\n\n\n# Rebuild Makefile.in if this file is modified.\nMakefile.in: maintMakefile\n\n# Copyright (C) 1997-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "make-gdb.py",
    "content": "\"\"\"GDB pretty-printer macros for GNU Make.\"\"\"\n\nimport gdb  # pylint: disable=import-error\nimport gdb.printing  # pylint: disable=import-error\n\n\n# Memoize types we commonly use\n_TYPES = {}\n\n\ndef getType(tname):\n    \"\"\"Given a type name return a GDB type.\"\"\"\n    global _TYPES\n    if tname not in _TYPES:\n        tn = tname.rstrip('*')\n        if tn not in _TYPES:\n            _TYPES[tn] = gdb.lookup_type(tn)\n        while tn != tname:\n            # Want a pointer type\n            t = tn\n            tn += '*'\n            _TYPES[tn] = _TYPES[t].pointer()\n    return _TYPES[tname]\n\n\ndef isNullptr(val):\n    \"\"\"Return True if the value is a null pointer.\"\"\"\n    return int(val.cast(getType('unsigned long long'))) == 0\n\n\nclass ShowArgv(gdb.Command):\n    \"\"\"Print a null-terminated array of strings.\n\n    Argument:\n        A char** where the last one is NULL (e.g., argv)\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"Create the showargv function.\"\"\"\n        gdb.Command.__init__(self, \"showargv\", gdb.COMMAND_USER)\n\n    def invoke(self, arg, from_tty):\n        \"\"\"Show the argv.\"\"\"\n        args = gdb.string_to_argv(arg)\n        if len(args) != 1:\n            raise gdb.GdbError(self._usage)\n\n        val = gdb.parse_and_eval(args[0])\n        if val is None:\n            raise gdb.GdbError('%s is not a valid expression' % (args[0]))\n\n        strs = []\n        while not isNullptr(val.dereference()):\n            strs.append('\"'+val.dereference().string()+'\"')\n            val += 1\n\n        gdb.write(\"[%d] = [%s]\\n\" % (len(strs), ', '.join(strs)))\n        gdb.flush()\n\n\nShowArgv()\n\n\nclass ShowNextList(gdb.Command):\n    \"\"\"Print a structure that has a \"next\" pointer.\n\n    Argument:\n        A pointer to a struct which contains a \"next\" member.\n    \"\"\"\n\n    _usage = 'usage: showlist <listptr>'\n\n    def __init__(self):\n        \"\"\"Create a \"showlist\" function.\"\"\"\n        gdb.Command.__init__(self, \"showlist\", gdb.COMMAND_USER)\n\n    def invoke(self, arg, from_tty):\n        \"\"\"Show the elements in the provided list.\"\"\"\n        args = gdb.string_to_argv(arg)\n        if len(args) != 1:\n            raise gdb.GdbError(self._usage)\n\n        val = gdb.parse_and_eval(args[0])\n        if val is None:\n            raise gdb.GdbError('%s is not a valid expression' % (args[0]))\n        i = 0\n        while not isNullptr(val):\n            gdb.write(\"%s : %s\\n\" % (val, val.dereference()))\n            gdb.flush()\n            i += 1\n            val = val['next']\n        gdb.write(\"%s contains %d elements\\n\" % (args[0], i))\n        gdb.flush()\n\n\nShowNextList()\n\n\nclass FileLocation(object):\n    \"\"\"Print a file location.\"\"\"\n\n    def __init__(self, val):\n        \"\"\"Create a FileLocation object.\"\"\"\n        self.val = val\n\n    def to_string(self):\n        \"\"\"Convert a FileLocation to a string.\"\"\"\n        if int(self.val['filenm']):\n            return \"%s:%d\" % (str(self.val['filenm']), self.val['lineno'])\n        return 'NILF'\n\n\nclass StringListPrinter(object):\n    \"\"\"Print a stringlist.\"\"\"\n\n    def __init__(self, val):\n        \"\"\"Create a StringListPrinter object.\"\"\"\n        self.val = val\n\n    def to_string(self):\n        \"\"\"Convert a HashTable into a string.\"\"\"\n        return \"size=%d, capacity=%d\" % (self.val['idx'], self.val['max'])\n\n    def children(self):\n        \"\"\"Yield each string in the list.\"\"\"\n        i = 0\n        elts = self.val['list']\n        while i < self.val['idx']:\n            nm = '[%d] ' % i\n            yield (nm, elts.dereference())\n            i += 1\n            elts += 1\n\n    def display_hint(self):\n        \"\"\"Show the display hint for the pretty-printer.\"\"\"\n        return 'array'\n\n\nclass VariablePrinter(object):\n    \"\"\"Print a struct variable.\"\"\"\n\n    def __init__(self, val):\n        \"\"\"Create a VariablePrinter object.\"\"\"\n        self.val = val\n\n    def to_string(self):\n        \"\"\"Convert a VariablePrinter object into a string.\"\"\"\n        if self.val['append']:\n            a = '+='\n        elif self.val['conditional']:\n            a = '?='\n        else:\n            a = '='\n        flags = []\n        s = str(self.val['flavor'])\n        if s != 'f_bogus':\n            flags.append(s)\n        s = str(self.val['origin'])\n        if s != 'o_default':\n            flags.append(s)\n        s = str(self.val['export'])\n        if s != 'v_default':\n            flags.append(s)\n        return '%s[%s]: \"%s\" %s \"%s\"' % (\n            self.val['fileinfo'], ','.join(flags),\n            self.val['name'].string(), a, self.val['value'].string())\n\n\nclass HashTablePrinter(object):\n    \"\"\"Pretty-print a hash table.\"\"\"\n\n    DELITEM = None\n\n    def __init__(self, val):\n        \"\"\"Create a HashTablePrinter object.\"\"\"\n        self.val = val\n\n    def to_string(self):\n        \"\"\"Convert a HashTable into a string.\"\"\"\n        return \"size=%d, capacity=%d, empty=%d, collisions=%d, rehashes=%d\" % (\n            self.val['ht_size'], self.val['ht_capacity'],\n            self.val['ht_empty_slots'], self.val['ht_collisions'],\n            self.val['ht_rehashes'])\n\n    def children(self):\n        \"\"\"Yield each ID and value.\"\"\"\n        for (i, v) in self.iterator():\n            nm = '[%d] ' % i\n            yield (nm, i)\n            yield (nm, v)\n\n    def iterator(self):\n        \"\"\"Provide an iterator for HashTable.\"\"\"\n        if HashTablePrinter.DELITEM is None:\n            HashTablePrinter.DELITEM = gdb.lookup_global_symbol('hash_deleted_item').value()\n        lst = self.val['ht_vec']\n        for i in range(0, self.val['ht_size']):\n            v = lst[i]\n            if int(v) != 0 and v != HashTablePrinter.DELITEM:\n                yield (i, v)\n\n    def display_hint(self):\n        \"\"\"Show the display hint for the pretty-printer.\"\"\"\n        return 'map'\n\n\nclass VariableSetPrinter(object):\n    \"\"\"Print a variable_set.\"\"\"\n\n    def __init__(self, val):\n        \"\"\"Create a variable_set pretty-printer.\"\"\"\n        self.tbl = HashTablePrinter(val['table'])\n\n    def to_string(self):\n        \"\"\"Convert a variable_set to string.\"\"\"\n        return self.tbl.to_string()\n\n    def children(self):\n        \"\"\"Iterate through variables and values.\"\"\"\n        for (i, v) in self.tbl.iterator():\n            ptr = v.cast(getType('struct variable*'))\n            nm = '[%d] ' % (i)\n            yield (nm, ptr)\n            yield (nm, str(ptr.dereference()))\n\n    def display_hint(self):\n        \"\"\"Show the display hint for the pretty-printer.\"\"\"\n        return 'map'\n\n\nclass VariableSetListPrinter(object):\n    \"\"\"Print a variable_set_list.\"\"\"\n\n    GLOBALSET = None\n\n    def __init__(self, val):\n        \"\"\"Create a variable_set_list pretty-printer.\"\"\"\n        self.val = val\n\n    def to_string(self):\n        \"\"\"Convert a variable_set_list to string.\"\"\"\n        return str(self.val.address)\n\n    def children(self):\n        \"\"\"Iterate through variables and values.\"\"\"\n        if VariableSetListPrinter.GLOBALSET is None:\n            block = gdb.lookup_global_symbol('init_hash_global_variable_set').symtab.static_block()\n            VariableSetListPrinter.GLOBALSET = gdb.lookup_symbol(\n                'global_variable_set', block)[0].value().address\n        ptr = self.val.address\n        i = 0\n        while not isNullptr(ptr):\n            nm = '[%d] ' % (i)\n            yield (nm, ptr['set'])\n            if int(ptr['set']) == int(VariableSetListPrinter.GLOBALSET):\n                yield (nm, \"global_variable_set\")\n            else:\n                yield (nm, str(ptr['set'].dereference()))\n            i += 1\n            ptr = ptr['next']\n\n    def display_hint(self):\n        \"\"\"Show the display hint for the pretty-printer.\"\"\"\n        return 'map'\n\n\ndef build_pretty_printer():\n    \"\"\"Install all the pretty-printers.\"\"\"\n    pp = gdb.printing.RegexpCollectionPrettyPrinter(\"gnumake\")\n    pp.add_printer('floc', r'^floc$', FileLocation)\n    pp.add_printer('stringlist', r'^stringlist$', StringListPrinter)\n    pp.add_printer('variable', r'^variable$', VariablePrinter)\n    pp.add_printer('hashtable', r'^hash_table$', HashTablePrinter)\n    pp.add_printer('variableset', r'^variable_set$', VariableSetPrinter)\n    pp.add_printer('variablesetlist', r'^variable_set_list$', VariableSetListPrinter)\n    return pp\n\n\n# Use replace=True so we can re-source this file\ngdb.printing.register_pretty_printer(gdb.current_objfile(),\n                                     build_pretty_printer(), replace=True)\n"
  },
  {
    "path": "makefile.com",
    "content": "$!\n$! Makefile.com - builds GNU Make for VMS\n$!\n$! P1 = LIST will provide compiler listings.\n$! P2 = DEBUG will build an image with debug information\n$! P3 = WALL will enable all warning messages (some are suppressed since\n$!      one macro intentionally causes an error condition)\n$!\n$! In case of problems with the install you might contact me at\n$! zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com\n$\n$! hb\n$! But don't ask Martin Zinser about the lines, I added/changed.\n$! In case of an error do some cleanup\n$ on error then $ goto cleanup\n$! in case somebody set up her/his own symbol for cc\n$ set symbol/scope=(nolocal,noglobal)\n$!\n$! Just some general constants...\n$!\n$ true  = 1\n$ false = 0\n$ tmpnam = \"temp_\" + f$getjpi(\"\",\"pid\")\n$ tt = tmpnam + \".txt\"\n$ tc = tmpnam + \".c\"\n$!\n$! Look for the compiler used\n$!\n$ lval = \"\"\n$ if f$search(\"SYS$SYSTEM:DECC$COMPILER.EXE\").eqs.\"\"\n$  then\n$   if f$trnlnm(\"SYS\").eqs.\"\" then def/nolog sys sys$library:\n$   ccopt = \"\"\n$  else\n$   ccopt = \"/decc/prefix=(all,except=(globfree,glob))\"\n$   if f$trnlnm(\"SYS\").eqs.\"\"\n$    then\n$     if f$trnlnm(\"DECC$LIBRARY_INCLUDE\").nes.\"\"\n$      then\n$       define sys decc$library_include:\n$      else\n$       if f$search(\"SYS$COMMON:[DECC$LIB.REFERENCE]DECC$RTLDEF.DIR\").nes.\"\" -\n           then lval = \"SYS$COMMON:[DECC$LIB.REFERENCE.DECC$RTLDEF],\"\n$       if f$search(\"SYS$COMMON:[DECC$LIB.REFERENCE]SYS$STARLET_C.DIR\").nes.\"\" -\n           then lval = lval+\"SYS$COMMON:[DECC$LIB.REFERENCE.SYS$STARLET_C],\"\n$       lval=lval+\"SYS$LIBRARY:\"\n$       define sys 'lval\n$      endif\n$   endif\n$ endif\n$!\n$!\n$ if (p1 .eqs. \"LIST\")\n$ then\n$   ccopt = ccopt + \"/list/show=(expan,inclu)\"\n$ endif\n$!\n$! Should we build a debug image\n$!\n$ if (p2.eqs.\"DEBUG\")\n$  then\n$   ccopt = ccopt + \"/noopt/debug\"\n$   lopt = \"/debug\"\n$ else\n$   lopt = \"\"\n$ endif\n$!\n$! Do we want to see all warnings\n$!\n$ if (p3.nes.\"WALL\")\n$ then\n$   gosub check_cc_qual\n$ endif\n$ filelist = \"[.src]ar [.src]arscan [.src]commands [.src]default [.src]dir \" + -\n             \"[.src]expand [.src]file [.src]function [.src]guile \" + -\n             \"[.src]hash [.src]implicit [.src]job [.src]load [.src]main \" + -\n             \"[.src]misc [.src]read [.src]remake [.src]remote-stub \" + -\n             \"[.src]rule [.src]output [.src]signame [.src]variable \" + -\n             \"[.src]version [.src]shuffle [.src]strcache [.src]vpath \" + -\n             \"[.src]vmsfunctions [.src]vmsify [.src]vms_progname \" + -\n             \"[.src]vms_exit [.src]vms_export_symbol \" + -\n             \"[.lib]alloca [.lib]fnmatch [.lib]glob [.src]getopt1 [.src]getopt\"\n$!\n$ copy [.src]config.h-vms [.src]config.h\n$ copy [.lib]fnmatch.in.h [.lib]fnmatch.h\n$ copy [.lib]glob.in.h [.lib]glob.h\n$ n=0\n$ open/write optf make.opt\n$ loop:\n$ cfile = f$elem(n,\" \",filelist)\n$ if cfile .eqs. \" \" then goto linkit\n$ write sys$output \"Compiling ''cfile'...\"\n$ call compileit 'cfile'\n$ n = n + 1\n$ goto loop\n$ linkit:\n$ close optf\n$ link/exe=make make.opt/opt'lopt\n$ goto cleanup\n$\n$ cleanup:\n$ if f$trnlnm(\"SYS\").nes.\"\" then $ deassign sys\n$ if f$trnlnm(\"OPTF\").nes.\"\" then $ close optf\n$ if f$search(\"make.opt\").nes.\"\" then $ del make.opt;*\n$ exit\n$!\n$!-----------------------------------------------------------------------------\n$!\n$! Check if this is a define relating to the properties of the C/C++\n$! compiler\n$!\n$CHECK_CC_QUAL:\n$ open/write tmpc 'tc\n$ ccqual = \"/warn=(disable=questcompare)\"\n$ write tmpc \"#include <stdio.h>\"\n$ write tmpc \"unsigned int i = 1;\"\n$ write tmpc \"int main(){\"\n$ write tmpc \"if (i < 0){printf(\"\"Mission impossible\\n\"\");}}\"\n$ close tmpc\n$ gosub cc_qual_check\n$ return\n$!\n$!-----------------------------------------------------------------------------\n$!\n$! Check for properties of C/C++ compiler\n$!\n$CC_QUAL_CHECK:\n$ cc_qual = false\n$ set message/nofac/noident/nosever/notext\n$ cc 'ccqual' 'tmpnam'\n$ if $status then cc_qual = true\n$ set message/fac/ident/sever/text\n$ delete/nolog 'tmpnam'.*;*\n$ if cc_qual then ccopt = ccopt + ccqual\n$ return\n$!-----------------------------------------------------------------------------\n$!\n$ compileit : subroutine\n$ ploc = f$locate(\"]\",p1)\n$! filnam = p1\n$ if ploc .lt. f$length(p1)\n$ then\n$   objdir = f$extract(0, ploc+1, p1)\n$   write optf p1\n$ else\n$   objdir := []\n$   write optf objdir+p1\n$ endif\n$ cc'ccopt'/nested=none/include=([],[.src],[.lib])/obj='objdir' -\n  /define=(\"allocated_variable_expand_for_file=alloc_var_expand_for_file\",-\n  \"unlink=remove\",\"HAVE_CONFIG_H\",\"VMS\") -\n  'p1'\n$ exit\n$ endsubroutine : compileit\n$!\n$!-----------------------------------------------------------------------------\n$!Copyright (C) 1996-2024 Free Software Foundation, Inc.\n$!This file is part of GNU Make.\n$!\n$!GNU Make is free software; you can redistribute it and/or modify it under\n$!the terms of the GNU General Public License as published by the Free Software\n$!Foundation; either version 3 of the License, or (at your option) any later\n$!version.\n$!\n$!GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n$!WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n$!FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n$!details.\n$!\n$!You should have received a copy of the GNU General Public License along with\n$!this program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "mk/Posix.mk.in",
    "content": "# GNU -*-Makefile-*- to build GNU Make on POSIX systems\n#\n# POSIX overrides for use with Basic.mk.\n#\n# Copyright (C) 2017-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Very little is needed here since the default Basic.mk assumes POSIX\n\nprog_SOURCES += $(src)/posixos.c\n\nextra_CPPFLAGS += @GUILE_CFLAGS@\nextra_LDFLAGS += @AM_LDFLAGS@\nLDLIBS += @LIBOBJS@ @gl_LIBOBS@ @ALLOCA@\nLDLIBS += @GUILE_LIBS@ @GETLOADAVG_LIBS@ @LIBINTL@ @LIBS@\n"
  },
  {
    "path": "mk/VMS.mk",
    "content": "# GNU -*-Makefile-*- to build GNU Make on VMS\n#\n# VMS overrides for use with Basic.mk.\n#\n# Copyright (C) 2017-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nsrc = [.src]\nlib = [.lib]\nSRCDIR = []\n\nOBJEXT = .obj\nEXEEXT = .exe\n\ne =\ns = $e $e\nc = ,\n\ndefs = HAVE_CONFIG_H\n\nifeq ($(CC),cc)\ndefs += VMS unlink=remove allocated_variable_expand_for_file=alloc_var_expand_for_file\nelse\ndefs += GCC_IS_NATIVE\nifeq ($(ARCH),VAX)\ndefs += VAX\nendif\nendif\n\nextra_CPPFLAGS = /define=($(subst $s,$c,$(patsubst %,\"%\",$(defs))))\n\ncinclude = /nested=none/include=($(src),$(lib))\nifeq ($(CC),cc)\ncprefix = /prefix=(all,except=(glob,globfree))\ncwarn = /standard=relaxed/warn=(disable=questcompare)\nendif\n\nextra_CFLAGS = $(cinclude)$(cprefix)$(cwarn)\n\n#extra_LDFLAGS = /deb\nextra_LDFLAGS =\n\n# If your system needs extra libraries loaded in, define them here.\n# System V probably need -lPW for alloca.\n# if on vax, uncomment the following line\n#LDLIBS = ,c.opt/opt\nifeq ($(CC),cc)\n#LDLIBS =,sys$$library:vaxcrtl.olb/lib\nelse\nLDLIBS =,gnu_cc_library:libgcc.olb/lib\nendif\n\n# If your system doesn't have alloca, or the one provided is bad,\n# uncomment this\n#ALLOCA = $(alloca_SOURCES)\n\n# If your system doesn't have alloca.h, or the one provided is bad,\n# uncomment this\n#BUILT_SOURCES += $(lib)alloca.h\n\nprog_SOURCES += $(ALLOCA) $(glob_SOURCES) $(vms_SOURCES)\n\nBUILT_SOURCES += $(lib)fnmatch.h $(lib)glob.h\n\nCOMPILE.cmd = $(CC) $(extra_CFLAGS)$(CFLAGS)/obj=$@ $(extra_CPPFLAGS)$(CPPFLAGS) $1\n\nLINK.cmd = $(LD)$(extra_LDFLAGS)$(LDFLAGS)/exe=$@ $(subst $s,$c,$1)$(LDLIBS)\n\n# Don't know how to do this\nCHECK.cmd =\n\nMKDIR.cmd = create/dir $1\nRM.cmd = delete $1\nCP.cmd = copy $1 $2\n\ndefine CLEANSPACE\n\t-purge [...]\n\t-delete $(PROG);\n\t-delete $(src)*.$(OBJEXT);\nendef\n\n\n$(OUTDIR)$(src)config.h: $(SRCDIR)$(src)config.h-vms\n\t$(call CP.cmd,$<,$@)\n"
  },
  {
    "path": "mk/Windows32.mk",
    "content": "# GNU -*-Makefile-*- to build GNU Make on Windows\n#\n# Windows overrides for use with Basic.mk.\n#\n# Copyright (C) 2017-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# TARGET_TYPE can be either \"release\" or \"debug\"\nTARGET_TYPE = release\n\n# TOOLCHAIN can be either \"msvc\" or \"gcc\"\nTOOLCHAIN = msvc\n\n# Translate a POSIX path into a Windows path.  Don't bother with drives.\n# Used only inside recipes, with DOS/CMD tools that require it.\nP2W = $(subst /,\\,$1)\n\nprog_SOURCES += $(loadavg_SOURCES) $(glob_SOURCES) $(w32_SOURCES)\n\nutf8_SOURCES = $(src)w32/utf8.rc $(src)w32/utf8.manifest\n\nBUILT_SOURCES += $(lib)alloca.h $(lib)fnmatch.h $(lib)glob.h\n\nw32_LIBS = kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 \\\n\t   oleaut32 uuid odbc32 odbccp32\n\nCPPFLAGS =\nCFLAGS =\nLDFLAGS =\n\n# --- Visual Studio\nmsvc_CC = cl.exe\nmsvc_RC = rc.exe\nmsvc_LD = link.exe\n\nmsvc_CPPFLAGS = /DHAVE_CONFIG_H /DMK_OS_W32=1 /DWIN32 /D_CONSOLE\nmsvc_CPPFLAGS += /I$(OUTDIR)src /I$(SRCDIR)/src /I$(SRCDIR)/src/w32/include /I$(OUTDIR)lib /I$(SRCDIR)/lib\n\nmsvc_CFLAGS = /nologo /MT /W4 /EHsc\nmsvc_CFLAGS += /FR$(OUTDIR) /Fp$(BASE_PROG).pch /Fd$(BASE_PROG).pdb\n\nmsvc_LDFLAGS = /nologo /SUBSYSTEM:console /PDB:$(BASE_PROG).pdb\n\nmsvc_LDLIBS = $(addsuffix .lib,$(w32_LIBS))\n\nmsvc_C_SOURCE = /c\nmsvc_RC_SOURCE =\nmsvc_OUTPUT_OPTION = /Fo$@\nmsvc_LINK_OUTPUT = /OUT:$@\n\nrelease_msvc_OUTDIR = ./WinRel/\nrelease_msvc_CPPFLAGS = /D NDEBUG\nrelease_msvc_CFLAGS = /O2\n\ndebug_msvc_OUTDIR = ./WinDebug/\ndebug_msvc_CPPFLAGS = /D _DEBUG\ndebug_msvc_CFLAGS = /Zi /Od\ndebug_msvc_LDFLAGS = /DEBUG\n\n# --- GCC\ngcc_CC = gcc\ngcc_RC = windres\ngcc_LD = $(gcc_CC)\n\nrelease_gcc_OUTDIR = ./GccRel/\ndebug_gcc_OUTDIR = ./GccDebug/\n\ngcc_CPPFLAGS = -DHAVE_CONFIG_H -I$(OUTDIR)src -I$(SRCDIR)/src -I$(SRCDIR)/src/w32/include -I$(OUTDIR)lib -I$(SRCDIR)/lib\ngcc_CFLAGS = -mthreads -Wall -std=gnu99 -gdwarf-2 -g3\ngcc_LDFLAGS = -mthreads -gdwarf-2 -g3\ngcc_LDLIBS = $(addprefix -l,$(w32_libs))\n\ngcc_C_SOURCE = -c\ngcc_RC_SOURCE = -i\ngcc_OUTPUT_OPTION = -o $@\ngcc_LINK_OUTPUT = -o $@\n\ndebug_gcc_CFLAGS = -O0\nrelease_gcc_CFLAGS = -O2\n\n# ---\n\nRES_COMPILE.cmd = $(RC) $(OUTPUT_OPTION) $(RC_SOURCE) $1\nLINK.cmd = $(LD) $(extra_LDFLAGS) $(LDFLAGS) $(TARGET_ARCH) $1 $(LDLIBS) $(LINK_OUTPUT)\n\nCHECK.cmd = cmd /c cd tests \\& .\\run_make_tests.bat -make ../$(PROG)\n\nMKDIR.cmd = cmd /c mkdir $(call P2W,$1)\nRM.cmd = cmd /c del /F /Q $(call P2W,$1)\nCP.cmd = cmd /c copy /Y $(call P2W,$1 $2)\n\nCC = $($(TOOLCHAIN)_CC)\nRC = $($(TOOLCHAIN)_RC)\nLD = $($(TOOLCHAIN)_LD)\n\nC_SOURCE = $($(TOOLCHAIN)_C_SOURCE)\nRC_SOURCE = $($(TOOLCHAIN)_RC_SOURCE)\nOUTPUT_OPTION = $($(TOOLCHAIN)_OUTPUT_OPTION)\nLINK_OUTPUT = $($(TOOLCHAIN)_LINK_OUTPUT)\n\nOUTDIR = $($(TARGET_TYPE)_$(TOOLCHAIN)_OUTDIR)\n\nOBJEXT\t= obj\nEXEEXT\t= .exe\n\n_CUSTOM = $($(TOOLCHAIN)_$1) $($(TARGET_TYPE)_$1) $($(TARGET_TYPE)_$(TOOLCHAIN)_$1)\n\n# I'm not sure why this builds gnumake rather than make...?\nPROG = $(OUTDIR)gnumake$(EXEEXT)\nBASE_PROG = $(basename $(PROG))\n\nextra_CPPFLAGS = $(call _CUSTOM,CPPFLAGS)\nextra_CFLAGS = $(call _CUSTOM,CFLAGS)\nextra_LDFLAGS = $(call _CUSTOM,LDFLAGS)\nLDLIBS = $(call _CUSTOM,LDLIBS)\n\n$(OUTDIR)src/config.h: $(SRCDIR)/src/config.h.W32\n\t$(call CP.cmd,$<,$@)\n\nw32_UTF8OBJ = $(OUTDIR)src/w32/utf8.$(OBJEXT)\n$(w32_UTF8OBJ): $(utf8_SOURCES)\n\t$(call RES_COMPILE.cmd,$<)\n\nifneq (, $(shell where $(RC) 2>nul))\nRESOURCE_OBJECTS = $(w32_UTF8OBJ)\nendif\n"
  },
  {
    "path": "mk/msdosdjgpp.mk",
    "content": "# GNU -*-Makefile-*- to build GNU Make on MS-DOS with DJGPP\n#\n# MS-DOS overrides for use with Basic.mk.\n#\n# Copyright (C) 2017-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nOBJEXT = o\nEXEEXT = .exe\n\nCC = gcc\n\n# Translate a POSIX path into a Windows path.  Don't bother with drives.\n# Used only inside recipes, with DOS/CMD tools that require it.\nP2W = $(subst /,\\,$1)\n\nprog_SOURCES += $(loadavg_SOURCES) $(glob_SOURCES)\n\nBUILT_SOURCES += $(lib)alloca.h $(lib)fnmatch.h $(lib)glob.h\n\nINCLUDEDIR = c:/djgpp/include\nLIBDIR = c:/djgpp/lib\nLOCALEDIR = c:/djgpp/share\n\nMKDIR.cmd = command.com /c mkdir $(call P2W,$1)\nRM.cmd = command.com /c del /F /Q $(call P2W,$1)\nCP.cmd = command.com /c copy /Y $(call P2W,$1 $2)\n\n$(OUTDIR)src/config.h: $(SRCDIR)/src/configh.dos\n\t$(call CP.cmd,$<,$@)\n"
  },
  {
    "path": "po/.gitignore",
    "content": "*\n!.gitignore\n!LINGUAS\n!POTFILES.in\n"
  },
  {
    "path": "po/LINGUAS",
    "content": "be\nbg\ncs\nda\nde\nes\nfi\nfr\nga\ngl\nhe\nhr\nid\nit\nja\nka\nko\nlt\nnl\npl\npt\npt_BR\nro\nru\nsr\nsv\ntr\nuk\nvi\nzh_CN\nzh_TW\n"
  },
  {
    "path": "po/POTFILES.in",
    "content": "# List of source files containing translatable strings.\n# Copyright (C) 2000-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\nsrc/ar.c\nsrc/arscan.c\nsrc/commands.c\nsrc/dir.c\nsrc/expand.c\nsrc/file.c\nsrc/function.c\nsrc/getopt.c\nsrc/guile.c\nsrc/hash.c\nsrc/implicit.c\nsrc/job.c\nsrc/load.c\nsrc/main.c\nsrc/misc.c\nsrc/output.c\nsrc/posixos.c\nsrc/read.c\nsrc/remake.c\nsrc/remote-cstms.c\nsrc/rule.c\nsrc/shuffle.c\nsrc/signame.c\nsrc/strcache.c\nsrc/variable.c\nsrc/vmsfunctions.c\nsrc/vmsjobs.c\nsrc/vpath.c\nsrc/warning.c\nsrc/warning.h\nsrc/w32/w32os.c\n"
  },
  {
    "path": "prepare_vms.com",
    "content": "$!\n$! prepare_vms.com  - Build config.h-vms from master on VMS.\n$!\n$! This is used for building off the master instead of a release tarball.\n$!\n$!\n$! First try ODS-5, Pathworks V6 or UNZIP name.\n$!\n$ config_template = f$search(\"sys$disk:[.src]mkconfig*h.in\")\n$ if config_template .eqs. \"\"\n$ then\n$!\n$!  Try NFS, VMStar, or Pathworks V5 ODS-2 encoded name.\n$!\n$   config_template = f$search(\"sys$disk:[.src]mkconfig.h*in\")\n$   if config_template .eqs. \"\"\n$   then\n$       write sys$output \"Could not find mkconfig.h.in!\"\n$       exit 44\n$   endif\n$ endif\n$ config_template_file = f$parse(config_template,,,\"name\")\n$ config_template_type = f$parse(config_template,,,\"type\")\n$ config_template = \"sys$disk:[.src]\" + config_template_file + config_template_type\n$!\n$!\n$! Pull the version from configure.ac\n$!\n$ open/read ac_file sys$disk:[]configure.ac\n$ac_read_loop:\n$ read ac_file/end=ac_read_loop_end line_in\n$ key = f$extract(0, 7, line_in)\n$ if key .nes. \"AC_INIT\" then goto ac_read_loop\n$ package = f$element (1,\"[\",line_in)\n$ package = f$element (0,\"]\",package)\n$ version = f$element (2,\"[\",line_in)\n$ version = f$element (0,\"]\",version)\n$ac_read_loop_end:\n$ close ac_file\n$!\n$ if (version .eqs. \"\")\n$ then\n$    write sys$output \"Unable to determine version!\"\n$    exit 44\n$ endif\n$!\n$!\n$ outfile = \"sys$disk:[.src]mkconfig.h\"\n$!\n$! Note the pipe command is close to the length of 255, which is the\n$! maximum token length prior to VMS V8.2:\n$! %DCL-W-TKNOVF, command element is too long - shorten\n$! PDS: Blown out; someone else will have to figure this out\n$ pipe (write sys$output \"sub,@PACKAGE@,make,WHOLE/NOTYPE\" ;-\n        write sys$output \"sub,@PACKAGE_BUGREPORT@,bug-make@gnu.org,WHOLE/NOTYPE\" ;-\n        write sys$output \"sub,@PACKAGE_NAME@,GNU Make,WHOLE/NOTYPE\" ;-\n        write sys$output \"sub,@PACKAGE_TARNAME@,make,WHOLE/NOTYPE\" ;-\n        write sys$output \"sub,@PACKAGE_URL@,https://www.gnu.org/software/make/,WHOLE/NOTYPE\" ;-\n        write sys$output \"sub,@PACKAGE_VERSION@,''version',WHOLE/NOTYPE\" ;-\n        write sys$output \"exit\") |-\n       edit/edt 'config_template'/out='outfile'/command=sys$pipe >nla0:\n$!\n$ write sys$output \"GNU Make version: \", version, \" prepared for VMS\"\n"
  },
  {
    "path": "scripts/copyright-update",
    "content": "#!/bin/sh\n#\n# Copyright (C) 2014-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# Update GNU Make copyrights using gnulib update-copyright\n\nEXCLUDE='^\\(\\.[a-z].*\\|.*/\\.[a-z].*\\|.*COPYING\\|src/hash\\.[ch]\\|ChangeLog.*\\|.*/ChangeLog.*\\|INSTALL\\|doc/make\\.texi\\|bootstrap\\)$'\n\nupdate=${UPDATE_COPYRIGHT:-${GNULIB_SRCDIR:-../../gnulib}/build-aux/update-copyright}\n\ndie () { echo \"$*\"; exit 1; }\n\ngetfiles () {\n    git ls-files | grep -v \"$EXCLUDE\"\n}\n\nrun () {\n    cmd=$(command -v \"$update\") || die \"Cannot locate update-copyright ($update)\"\n    test -x \"$cmd\" || die \"Cannot locate update-copyright ($update)\"\n\n    force=false\n\n    case $1 in\n        (-v) getfiles | sort; exit 0 ;;\n        (-f) force=true ;;\n        (--) : ;;\n        (-*) echo \"usage: $0 [-v]\"; exit 1 ;;\n    esac\n\n    if $force; then\n        : just do it\n    elif test ! -f src/makeint.h; then\n        die \"Run in the root of the GNU Make workspace\"\n    elif test -f configure; then\n        die \"Run in a clean workspace (git clean -fdX)\"\n    fi\n\n    # We use intervals\n    export UPDATE_COPYRIGHT_USE_INTERVALS=1\n\n    \"$cmd\" $(getfiles)\n\n    echo \"*** Update doc/make.texi copyright by hand!\"\n    echo \"*** Update src/main.c:print_version() copyright by hand!\"\n\n    exit 0\n}\n\nrun \"$@\"\n\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "src/ar.c",
    "content": "/* Interface to 'ar' archives for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\n\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#ifndef NO_ARCHIVES\n\n#include \"filedef.h\"\n#include \"dep.h\"\n#include <fnmatch.h>\n#include <intprops.h>\n\n/* Return nonzero if NAME is an archive-member reference, zero if not.  An\n   archive-member reference is a name like 'lib(member)' where member is a\n   non-empty string.\n   If a name like 'lib((entry))' is used, a fatal error is signaled at\n   the attempt to use this unsupported feature.  */\n\nint\nar_name (const char *name)\n{\n  const char *p = strchr (name, '(');\n  const char *end;\n\n  if (p == NULL || p == name)\n    return 0;\n\n  end = p + strlen (p) - 1;\n  if (*end != ')' || end == p + 1)\n    return 0;\n\n  if (p[1] == '(' && end[-1] == ')')\n    OS (fatal, NILF, _(\"attempt to use unsupported feature: '%s'\"), name);\n\n  return 1;\n}\n\n\n/* Parse the archive-member reference NAME into the archive and member names.\n   Creates one allocated string containing both names, pointed to by ARNAME_P.\n   MEMNAME_P points to the member.  */\n\nvoid\nar_parse_name (const char *name, char **arname_p, char **memname_p)\n{\n  char *p;\n\n  *arname_p = xstrdup (name);\n  p = strchr (*arname_p, '(');\n  /* This is never called unless ar_name() is true so p cannot be NULL.  */\n  if (!p)\n    OS (fatal, NILF, \"INTERNAL: ar_parse_name: bad name '%s'\", *arname_p);\n  *(p++) = '\\0';\n  p[strlen (p) - 1] = '\\0';\n  *memname_p = p;\n}\n\f\n\n/* This function is called by 'ar_scan' to find which member to look at.  */\n\n/* ARGSUSED */\nstatic intmax_t\nar_member_date_1 (int desc UNUSED, const char *mem, int truncated,\n                  long int hdrpos UNUSED, long int datapos UNUSED,\n                  long int size UNUSED, intmax_t date,\n                  int uid UNUSED, int gid UNUSED, unsigned int mode UNUSED,\n                  const void *name)\n{\n  return ar_name_equal (name, mem, truncated) ? date : 0;\n}\n\n/* Return the modtime of NAME.  */\n\ntime_t\nar_member_date (const char *name)\n{\n  char *arname;\n  char *memname;\n  intmax_t val;\n\n  ar_parse_name (name, &arname, &memname);\n\n  /* Make sure we know the modtime of the archive itself because we are\n     likely to be called just before commands to remake a member are run,\n     and they will change the archive itself.\n\n     But we must be careful not to enter_file the archive itself if it does\n     not exist, because pattern_search assumes that files found in the data\n     base exist or can be made.  */\n  {\n    struct file *arfile;\n    arfile = lookup_file (arname);\n    if (arfile == 0 && file_exists_p (arname))\n      arfile = enter_file (strcache_add (arname));\n\n    if (arfile != 0)\n      (void) f_mtime (arfile, 0);\n  }\n\n  val = ar_scan (arname, ar_member_date_1, memname);\n\n  free (arname);\n\n  return 0 < val && val <= TYPE_MAXIMUM (time_t) ? val : -1;\n}\n\f\n/* Set the archive-member NAME's modtime to now.  */\n\n#if MK_OS_VMS\nint\nar_touch (const char *name)\n{\n  O (error, NILF, _(\"touch archive member is not available on VMS\"));\n  return -1;\n}\n#else\nint\nar_touch (const char *name)\n{\n  char *arname, *memname;\n  int val;\n\n  ar_parse_name (name, &arname, &memname);\n\n  /* Make sure we know the modtime of the archive itself before we\n     touch the member, since this will change the archive modtime.  */\n  {\n    struct file *arfile;\n    arfile = enter_file (strcache_add (arname));\n    f_mtime (arfile, 0);\n  }\n\n  val = 1;\n  switch (ar_member_touch (arname, memname))\n    {\n    case -1:\n      OS (error, NILF, _(\"touch: archive '%s' does not exist\"), arname);\n      break;\n    case -2:\n      OS (error, NILF, _(\"touch: '%s' is not a valid archive\"), arname);\n      break;\n    case -3:\n      perror_with_name (\"touch: \", arname);\n      break;\n    case 1:\n      OSS (error, NILF,\n           _(\"touch: member '%s' does not exist in '%s'\"), memname, arname);\n      break;\n    case 0:\n      val = 0;\n      break;\n    default:\n      OS (error, NILF,\n          _(\"touch: bad return code from ar_member_touch on '%s'\"), name);\n    }\n\n  free (arname);\n\n  return val;\n}\n#endif /* !MK_OS_VMS */\n\f\n/* State of an 'ar_glob' run, passed to 'ar_glob_match'.  */\n\n/* On VMS, (object) modules in libraries do not have suffixes. That is, to\n   find a match for a pattern, the pattern must not have any suffix. So the\n   suffix of the pattern is saved and the pattern is stripped (ar_glob).\n   If there is a match and the match, which is a module name, is added to\n   the chain, the saved suffix is added back to construct a source filename\n   (ar_glob_match). */\n\nstruct ar_glob_state\n  {\n    const char *arname;\n    const char *pattern;\n#if MK_OS_VMS\n    char *suffix;\n#endif\n    size_t size;\n    struct nameseq *chain;\n    unsigned int n;\n  };\n\n/* This function is called by 'ar_scan' to match one archive\n   element against the pattern in STATE.  */\n\nstatic intmax_t\nar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,\n               long int hdrpos UNUSED, long int datapos UNUSED,\n               long int size UNUSED, intmax_t date UNUSED, int uid UNUSED,\n               int gid UNUSED, unsigned int mode UNUSED, const void *arg)\n{\n  struct ar_glob_state *state = (struct ar_glob_state *)arg;\n\n  if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)\n    {\n      /* We have a match.  Add it to the chain.  */\n      struct nameseq *new = xcalloc (state->size);\n#if MK_OS_VMS\n      if (state->suffix)\n        new->name = strcache_add(\n            concat(5, state->arname, \"(\", mem, state->suffix, \")\"));\n      else\n#endif\n        new->name = strcache_add(concat(4, state->arname, \"(\", mem, \")\"));\n      new->next = state->chain;\n      state->chain = new;\n      ++state->n;\n    }\n\n  return 0;\n}\n\n/* Return nonzero if PATTERN contains any metacharacters.\n   Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */\nstatic int\nar_glob_pattern_p (const char *pattern, int quote)\n{\n  const char *p;\n  int opened = 0;\n\n  for (p = pattern; *p != '\\0'; ++p)\n    switch (*p)\n      {\n      case '?':\n      case '*':\n        return 1;\n\n      case '\\\\':\n        if (quote)\n          ++p;\n        break;\n\n      case '[':\n        opened = 1;\n        break;\n\n      case ']':\n        if (opened)\n          return 1;\n        break;\n      }\n\n  return 0;\n}\n\n/* Glob for MEMBER_PATTERN in archive ARNAME.\n   Return a malloc'd chain of matching elements (or nil if none).  */\n\nstruct nameseq *\nar_glob (const char *arname, const char *member_pattern, size_t size)\n{\n  struct ar_glob_state state;\n  struct nameseq *n;\n  const char **names;\n  unsigned int i;\n#if MK_OS_VMS\n  char *vms_member_pattern;\n#endif\n  if (! ar_glob_pattern_p (member_pattern, 1))\n    return 0;\n\n  /* Scan the archive for matches.\n     ar_glob_match will accumulate them in STATE.chain.  */\n  state.arname = arname;\n  state.pattern = member_pattern;\n#if MK_OS_VMS\n    {\n      /* In a copy of the pattern, find the suffix, save it and  remove it from\n         the pattern */\n      char *lastdot;\n      vms_member_pattern = xstrdup(member_pattern);\n      lastdot = strrchr(vms_member_pattern, '.');\n      state.suffix = lastdot;\n      if (lastdot)\n        {\n          state.suffix = xstrdup(lastdot);\n          *lastdot = 0;\n        }\n      state.pattern = vms_member_pattern;\n    }\n#endif\n  state.size = size;\n  state.chain = 0;\n  state.n = 0;\n  ar_scan (arname, ar_glob_match, &state);\n\n#if MK_OS_VMS\n  /* Deallocate any duplicated string */\n  free(vms_member_pattern);\n  if (state.suffix)\n    {\n      free(state.suffix);\n    }\n#endif\n\n  if (state.chain == 0)\n    return 0;\n\n  /* Now put the names into a vector for sorting.  */\n  names = alloca (state.n * sizeof (const char *));\n  i = 0;\n  for (n = state.chain; n != 0; n = n->next)\n    names[i++] = n->name;\n\n  /* Sort them alphabetically.  */\n  /* MSVC erroneously warns without a cast here.  */\n  qsort ((void *)names, i, sizeof (*names), alpha_compare);\n\n  /* Put them back into the chain in the sorted order.  */\n  i = 0;\n  for (n = state.chain; n != 0; n = n->next)\n    n->name = names[i++];\n\n  return state.chain;\n}\n\n#endif  /* Not NO_ARCHIVES.  */\n"
  },
  {
    "path": "src/arscan.c",
    "content": "/* Library function for scanning an archive file.\nCopyright (C) 1987-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#ifdef TEST\n/* Hack, the real error() routine eventually pulls in die from main.c */\n#define error(a, b, c, d)\n#endif\n\n#ifdef HAVE_FCNTL_H\n#include <fcntl.h>\n#else\n#include <sys/file.h>\n#endif\n\n#ifndef NO_ARCHIVES\n\n#if MK_OS_VMS\n#include <lbrdef.h>\n#include <mhddef.h>\n#include <credef.h>\n#include <descrip.h>\n#include <ctype.h>\n#include <ssdef.h>\n#include <stsdef.h>\n#include <rmsdef.h>\n\n/* This symbol should be present in lbrdef.h. */\n#if !defined LBR$_HDRTRUNC\n#pragma extern_model save\n#pragma extern_model globalvalue\nextern unsigned int LBR$_HDRTRUNC;\n#pragma extern_model restore\n#endif\n\n#include <unixlib.h>\n#include <lbr$routines.h>\n\nconst char *\nvmsify (const char *name, int type);\n\n/* Time conversion from VMS to Unix\n   Conversion from local time (stored in library) to GMT (needed for gmake)\n   Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */\nstatic time_t\nvms_time_to_unix(void *vms_time)\n{\n  struct tm *tmp;\n  time_t unix_time;\n\n  unix_time = decc$fix_time(vms_time);\n  tmp = localtime(&unix_time);\n  unix_time -= tmp->tm_gmtoff;\n\n  return unix_time;\n}\n\n\n/* VMS library routines need static variables for callback */\nstatic void *VMS_lib_idx;\n\nstatic const void *VMS_saved_arg;\n\nstatic intmax_t (*VMS_function) ();\n\nstatic intmax_t VMS_function_ret;\n\n\n/* This is a callback procedure for lib$get_index */\nstatic int\nVMS_get_member_info(struct dsc$descriptor_s *module, unsigned long *rfa)\n{\n  int status, i;\n  const int truncated = 0; /* Member name may be truncated */\n  time_t member_date; /* Member date */\n  char *filename;\n  unsigned int buffer_length; /* Actual buffer length */\n\n  /* Unused constants - Make does not actually use most of these */\n  const int file_desc = -1; /* archive file descriptor for reading the data */\n  const int header_position = 0; /* Header position */\n  const int data_position = 0; /* Data position in file */\n  const int data_size = 0; /* Data size */\n  const int uid = 0; /* member gid */\n  const int gid = 0; /* member gid */\n  const int mode = 0; /* member protection mode */\n  /* End of unused constants */\n\n  static struct dsc$descriptor_s bufdesc =\n    { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };\n\n  /* Only need the module definition */\n  struct mhddef *mhd;\n\n  /* If a previous callback is non-zero, just return that status */\n  if (VMS_function_ret)\n    {\n      return SS$_NORMAL;\n    }\n\n  /* lbr_set_module returns more than just the module header. So allocate\n     a buffer which is big enough: the maximum LBR$C_MAXHDRSIZ. That's at\n     least bigger than the size of struct mhddef.\n     If the request is too small, a buffer truncated warning is issued so\n     it can be reissued with a larger buffer.\n     We do not care if the buffer is truncated, so that is still a success. */\n  mhd = xmalloc(LBR$C_MAXHDRSIZ);\n  bufdesc.dsc$a_pointer = (char *) mhd;\n  bufdesc.dsc$w_length = LBR$C_MAXHDRSIZ;\n\n  status = lbr$set_module(&VMS_lib_idx, rfa, &bufdesc, &buffer_length, 0);\n\n  if ((status != LBR$_HDRTRUNC) && !$VMS_STATUS_SUCCESS(status))\n    {\n      ON(error, NILF,\n          _(\"lbr$set_module() failed to extract module info, status = %d\"),\n          status);\n\n      lbr$close(&VMS_lib_idx);\n\n      return status;\n    }\n\n#ifdef TEST\n  /* When testing this code, it is useful to know the length returned */\n  printf (\"Input length = %d, actual = %u\\n\",\n          bufdesc.dsc$w_length, buffer_length);\n#endif\n\n  /* Conversion from VMS time to C time.\n     VMS defectlet - mhddef is sub-optimal, for the time, it has a 32 bit\n     longword, mhd$l_datim, and a 32 bit fill instead of two longwords, or\n     equivalent. */\n  member_date = vms_time_to_unix(&mhd->mhd$l_datim);\n  free(mhd);\n\n  /* Here we have a problem.  The module name on VMS does not have\n     a file type, but the filename pattern in the \"VMS_saved_arg\"\n     may have one.\n     But only the method being called knows how to interpret the\n     filename pattern.\n     There are currently two different formats being used.\n     This means that we need a VMS specific code in those methods\n     to handle it. */\n  filename = xmalloc(module->dsc$w_length + 1);\n\n  /* TODO: We may need an option to preserve the case of the module\n     For now force the module name to lower case */\n  for (i = 0; i < module->dsc$w_length; i++)\n    filename[i] = _tolower((unsigned char )module->dsc$a_pointer[i]);\n\n  filename[i] = '\\0';\n\n  VMS_function_ret = (*VMS_function)(file_desc, filename, truncated,\n      header_position, data_position, data_size, member_date, uid, gid, mode,\n      VMS_saved_arg);\n\n  free(filename);\n  return SS$_NORMAL;\n}\n\n\n/* Takes three arguments ARCHIVE, FUNCTION and ARG.\n\n   Open the archive named ARCHIVE, find its members one by one,\n   and for each one call FUNCTION with the following arguments:\n     archive file descriptor for reading the data,\n     member name,\n     member name might be truncated flag,\n     member header position in file,\n     member data position in file,\n     member data size,\n     member date,\n     member uid,\n     member gid,\n     member protection mode,\n     ARG.\n\n   NOTE: on VMS systems, only name, date, and arg are meaningful!\n\n   The descriptor is poised to read the data of the member\n   when FUNCTION is called.  It does not matter how much\n   data FUNCTION reads.\n\n   If FUNCTION returns nonzero, we immediately return\n   what FUNCTION returned.\n\n   Returns -1 if archive does not exist,\n   Returns -2 if archive has invalid format.\n   Returns 0 if have scanned successfully.  */\n\nintmax_t\nar_scan (const char *archive, ar_member_func_t function, const void *varg)\n{\n  char *vms_archive;\n\n  static struct dsc$descriptor_s libdesc =\n    { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };\n\n  const unsigned long func = LBR$C_READ;\n  const unsigned long type = LBR$C_TYP_UNK;\n  const unsigned long index = 1;\n  unsigned long lib_idx;\n  int status;\n\n  VMS_saved_arg = varg;\n\n  /* Null archive string can show up in test and cause an access violation */\n  if (archive == NULL)\n    {\n      /* Null filenames do not exist */\n      return -1;\n    }\n\n  /* archive path name must be in VMS format */\n  vms_archive = (char *) vmsify(archive, 0);\n\n  status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0);\n\n  if (!$VMS_STATUS_SUCCESS(status))\n    {\n      ON(error, NILF, _(\"lbr$ini_control() failed with status = %d\"), status);\n      return -2;\n    }\n\n  libdesc.dsc$a_pointer = vms_archive;\n  libdesc.dsc$w_length = strlen(vms_archive);\n\n  status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0);\n\n  if (!$VMS_STATUS_SUCCESS(status))\n    {\n\n      /* TODO: A library format failure could mean that this is a file\n         generated by the GNU AR utility and in that case, we need to\n         take the UNIX codepath.  This will also take a change to the\n         GNV AR wrapper program. */\n\n      switch (status)\n        {\n      case RMS$_FNF:\n        /* Archive does not exist */\n        return -1;\n      default:\n#ifndef TEST\n        OSN(error, NILF,\n            _(\"unable to open library '%s' to lookup member status %d\"),\n            archive, status);\n#endif\n        /* For library format errors, specification says to return -2 */\n        return -2;\n        }\n    }\n\n  VMS_function = function;\n\n  /* Clear the return status, as we are supposed to stop calling the\n     callback function if it becomes non-zero, and this is a static\n     variable. */\n  VMS_function_ret = 0;\n\n  status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0);\n\n  lbr$close(&VMS_lib_idx);\n\n  /* Unless a failure occurred in the lbr$ routines, return the\n     the status from the 'function' routine. */\n  if ($VMS_STATUS_SUCCESS(status))\n    {\n      return VMS_function_ret;\n    }\n\n  /* This must be something wrong with the library and an error\n     message should already have been printed. */\n  return -2;\n}\n\n#else /* !MK_OS_VMS */\n\n/* SCO Unix's compiler defines both of these.  */\n#ifdef M_UNIX\n#undef M_XENIX\n#endif\n\n/* On the sun386i and in System V rel 3, ar.h defines two different archive\n   formats depending upon whether you have defined PORTAR (normal) or PORT5AR\n   (System V Release 1).  There is no default, one or the other must be defined\n   to have a nonzero value.  */\n\n#if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)\n#undef PORTAR\n#ifdef M_XENIX\n/* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining\n   PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the\n   right one.  */\n#define PORTAR 0\n#else\n#define PORTAR 1\n#endif\n#endif\n\n/* On AIX, define these symbols to be sure to get both archive formats.\n   AIX 4.3 introduced the \"big\" archive format to support 64-bit object\n   files, so on AIX 4.3 systems we need to support both the \"normal\" and\n   \"big\" archive formats.  An archive's format is indicated in the\n   \"fl_magic\" field of the \"FL_HDR\" structure.  For a normal archive,\n   this field will be the string defined by the AIAMAG symbol.  For a\n   \"big\" archive, it will be the string defined by the AIAMAGBIG symbol\n   (at least on AIX it works this way).\n\n   Note: we'll define these symbols regardless of which AIX version\n   we're compiling on, but this is okay since we'll use the new symbols\n   only if they're present.  */\n#ifdef _AIX\n# define __AR_SMALL__\n# define __AR_BIG__\n#endif\n\n#if !MK_OS_W32\n# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined(MK_OS_ZOS)\n#  include <ar.h>\n# else\n   /* These platforms don't have <ar.h> but have archives in the same format\n    * as many other Unices.  This was taken from GNU binutils for BeOS.\n    */\n#  define ARMAG \"!<arch>\\n\"     /* String that begins an archive file.  */\n#  define SARMAG 8              /* Size of that string.  */\n#  define ARFMAG \"`\\n\"          /* String in ar_fmag at end of each header.  */\nstruct ar_hdr\n  {\n    char ar_name[16];           /* Member file name, sometimes / terminated. */\n    char ar_date[12];           /* File date, decimal seconds since Epoch.  */\n    char ar_uid[6], ar_gid[6];  /* User and group IDs, in ASCII decimal.  */\n    char ar_mode[8];            /* File mode, in ASCII octal.  */\n    char ar_size[10];           /* File size, in ASCII decimal.  */\n    char ar_fmag[2];            /* Always contains ARFMAG.  */\n  };\n# endif\n# define TOCHAR(_m)     (_m)\n#else\n/* These should allow us to read Windows (VC++) libraries (according to Frank\n * Libbrecht <frankl@abzx.belgium.hp.com>)\n */\n# include <windows.h>\n# include <windef.h>\n# include <io.h>\n# define ARMAG      IMAGE_ARCHIVE_START\n# define SARMAG     IMAGE_ARCHIVE_START_SIZE\n# define ar_hdr     _IMAGE_ARCHIVE_MEMBER_HEADER\n# define ar_name    Name\n# define ar_mode    Mode\n# define ar_size    Size\n# define ar_date    Date\n# define ar_uid     UserID\n# define ar_gid     GroupID\n/* In Windows the member names have type BYTE so we must cast them.  */\n# define TOCHAR(_m)     ((char *)(_m))\n#endif\n\n/* Cray's <ar.h> apparently defines this.  */\n#ifndef AR_HDR_SIZE\n# define   AR_HDR_SIZE  (sizeof (struct ar_hdr))\n#endif\n\n#include \"intprops.h\"\n\n#include \"output.h\"\n\f\n\nstatic uintmax_t\nparse_int (const char *ptr, const size_t len, const int base, uintmax_t max,\n           const char *type, const char *archive, const char *name)\n{\n  const char *const ep = ptr + len;\n  const int maxchar = '0' + base - 1;\n  uintmax_t val = 0;\n\n  /* In all the versions I know of the spaces come last, but be safe.  */\n  while (ptr < ep && *ptr == ' ')\n    ++ptr;\n\n  while (ptr < ep && *ptr != ' ')\n    {\n      if (*ptr < '0' || *ptr > maxchar\n          || INT_MULTIPLY_WRAPV (val, base, &val)\n          || INT_ADD_WRAPV (val, *ptr - '0', &val)\n          || val > max)\n        OSSS (fatal, NILF,\n              _(\"invalid %s for archive %s member %s\"), type, archive, name);\n      ++ptr;\n    }\n\n  return val;\n}\n\n/* Takes three arguments ARCHIVE, FUNCTION and ARG.\n\n   Open the archive named ARCHIVE, find its members one by one,\n   and for each one call FUNCTION with the following arguments:\n     archive file descriptor for reading the data,\n     member name,\n     member name might be truncated flag,\n     member header position in file,\n     member data position in file,\n     member data size,\n     member date,\n     member uid,\n     member gid,\n     member protection mode,\n     ARG.\n\n   The descriptor is poised to read the data of the member\n   when FUNCTION is called.  It does not matter how much\n   data FUNCTION reads.\n\n   If FUNCTION returns nonzero, we immediately return\n   what FUNCTION returned.\n\n   Returns -1 if archive does not exist,\n   Returns -2 if archive has invalid format.\n   Returns 0 if have scanned successfully.  */\n\nintmax_t\nar_scan (const char *archive, ar_member_func_t function, const void *arg)\n{\n#ifdef AIAMAG\n  FL_HDR fl_header;\n# ifdef AIAMAGBIG\n  int big_archive = 0;\n  FL_HDR_BIG fl_header_big;\n# endif\n#endif\n  char *namemap = 0;\n  unsigned int namemap_size = 0;\n  int desc = open (archive, O_RDONLY, 0);\n  if (desc < 0)\n    return -1;\n\n#ifdef SARMAG\n  {\n    char buf[SARMAG];\n    int nread;\n    nread = readbuf (desc, buf, SARMAG);\n    if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))\n      goto invalid;\n  }\n#else\n#ifdef AIAMAG\n  {\n    int nread;\n    nread = readbuf (desc, &fl_header, FL_HSZ);\n    if (nread != FL_HSZ)\n      goto invalid;\n\n#ifdef AIAMAGBIG\n    /* If this is a \"big\" archive, then set the flag and\n       re-read the header into the \"big\" structure. */\n    if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))\n      {\n        off_t o;\n\n        big_archive = 1;\n\n        /* seek back to beginning of archive */\n        EINTRLOOP (o, lseek (desc, 0, 0));\n        if (o < 0)\n          goto invalid;\n\n        /* re-read the header into the \"big\" structure */\n        nread = readbuf (desc, &fl_header_big, FL_HSZ_BIG);\n        if (nread != FL_HSZ_BIG)\n          goto invalid;\n      }\n    else\n#endif\n       /* Check to make sure this is a \"normal\" archive. */\n      if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))\n        goto invalid;\n  }\n#else\n  {\n#ifndef M_XENIX\n    int buf;\n#else\n    unsigned short int buf;\n#endif\n    int nread;\n    nread = readbuf (desc, &buf, sizeof (buf));\n    if (nread != sizeof (buf) || buf != ARMAG)\n      goto invalid;\n  }\n#endif\n#endif\n\n  /* Now find the members one by one.  */\n  {\n#ifdef SARMAG\n    long int member_offset = SARMAG;\n#else\n#ifdef AIAMAG\n    long int member_offset;\n    long int last_member_offset;\n\n#ifdef AIAMAGBIG\n    if ( big_archive )\n      {\n        sscanf (fl_header_big.fl_fstmoff, \"%20ld\", &member_offset);\n        sscanf (fl_header_big.fl_lstmoff, \"%20ld\", &last_member_offset);\n      }\n    else\n#endif\n      {\n        sscanf (fl_header.fl_fstmoff, \"%12ld\", &member_offset);\n        sscanf (fl_header.fl_lstmoff, \"%12ld\", &last_member_offset);\n      }\n\n    if (member_offset == 0)\n      {\n        /* Empty archive.  */\n        close (desc);\n        return 0;\n      }\n#else\n#ifndef M_XENIX\n    long int member_offset = sizeof (int);\n#else   /* Xenix.  */\n    long int member_offset = sizeof (unsigned short int);\n#endif  /* Not Xenix.  */\n#endif\n#endif\n\n    while (1)\n      {\n        ssize_t nread;\n        struct ar_hdr member_header;\n#ifdef AIAMAGBIG\n        struct ar_hdr_big member_header_big;\n#endif\n#ifdef AIAMAG\n# define ARNAME_MAX 255\n        char name[ARNAME_MAX + 1];\n        int name_len;\n        intmax_t dateval;\n        int uidval, gidval;\n        long int data_offset;\n#else\n# define ARNAME_MAX (int)sizeof(member_header.ar_name)\n        char namebuf[ARNAME_MAX + 1];\n        char *name;\n        int is_namemap;         /* Nonzero if this entry maps long names.  */\n        int long_name = 0;\n#endif\n        long int eltsize;\n        unsigned int eltmode;\n        intmax_t eltdate;\n        int eltuid, eltgid;\n        intmax_t fnval;\n        off_t o;\n\n        memset(&member_header, '\\0', sizeof (member_header));\n\n        EINTRLOOP (o, lseek (desc, member_offset, 0));\n        if (o < 0)\n          goto invalid;\n\n#ifdef AIAMAG\n#define       AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))\n\n#ifdef AIAMAGBIG\n        if (big_archive)\n          {\n            nread = readbuf (desc, &member_header_big,\n                             AR_MEMHDR_SZ(member_header_big));\n\n            if (nread != AR_MEMHDR_SZ(member_header_big))\n              goto invalid;\n\n            sscanf (member_header_big.ar_namlen, \"%4d\", &name_len);\n            if (name_len < 1 || name_len > ARNAME_MAX)\n              goto invalid;\n\n            nread = readbuf (desc, name, name_len);\n            if (nread != name_len)\n              goto invalid;\n\n            name[name_len] = '\\0';\n\n            sscanf (member_header_big.ar_date, \"%12\" SCNdMAX, &dateval);\n            sscanf (member_header_big.ar_uid, \"%12d\", &uidval);\n            sscanf (member_header_big.ar_gid, \"%12d\", &gidval);\n            sscanf (member_header_big.ar_mode, \"%12o\", &eltmode);\n            sscanf (member_header_big.ar_size, \"%20ld\", &eltsize);\n\n            data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)\n                           + name_len + 2);\n          }\n        else\n#endif\n          {\n            nread = readbuf (desc, &member_header,\n                             AR_MEMHDR_SZ(member_header));\n\n            if (nread != AR_MEMHDR_SZ(member_header))\n              goto invalid;\n\n            sscanf (member_header.ar_namlen, \"%4d\", &name_len);\n            if (name_len < 1 || name_len > ARNAME_MAX)\n              goto invalid;\n\n            nread = readbuf (desc, name, name_len);\n            if (nread != name_len)\n              goto invalid;\n\n            name[name_len] = '\\0';\n\n            sscanf (member_header.ar_date, \"%12\" SCNdMAX, &dateval);\n            sscanf (member_header.ar_uid, \"%12d\", &uidval);\n            sscanf (member_header.ar_gid, \"%12d\", &gidval);\n            sscanf (member_header.ar_mode, \"%12o\", &eltmode);\n            sscanf (member_header.ar_size, \"%12ld\", &eltsize);\n\n            data_offset = (member_offset + AR_MEMHDR_SZ(member_header)\n                           + name_len + 2);\n          }\n        data_offset += data_offset % 2;\n\n        fnval =\n          (*function) (desc, name, 0,\n                       member_offset, data_offset, eltsize,\n                       dateval, uidval, gidval,\n                       eltmode, arg);\n\n#else   /* Not AIAMAG.  */\n        nread = readbuf (desc, &member_header, AR_HDR_SIZE);\n        if (nread == 0)\n          /* No data left means end of file; that is OK.  */\n          break;\n\n        if (nread != AR_HDR_SIZE\n#if defined(ARFMAG) || defined(ARFZMAG)\n            || (\n# ifdef ARFMAG\n                memcmp (member_header.ar_fmag, ARFMAG, 2)\n# else\n                1\n# endif\n                &&\n# ifdef ARFZMAG\n                memcmp (member_header.ar_fmag, ARFZMAG, 2)\n# else\n                1\n# endif\n               )\n#endif\n            )\n          goto invalid;\n\n        name = namebuf;\n        memcpy (name, member_header.ar_name, sizeof member_header.ar_name);\n        {\n          char *p = name + sizeof member_header.ar_name;\n          do\n            *p = '\\0';\n          while (p > name && *--p == ' ');\n\n#ifndef AIAMAG\n          /* If the member name is \"//\" or \"ARFILENAMES/\" this may be\n             a list of file name mappings.  The maximum file name\n             length supported by the standard archive format is 14\n             characters.  This member will actually always be the\n             first or second entry in the archive, but we don't check\n             that.  */\n          is_namemap = (!strcmp (name, \"//\")\n                        || !strcmp (name, \"ARFILENAMES/\"));\n#endif  /* Not AIAMAG. */\n\n          /* On some systems, there is a slash after each member name.  */\n          if (*p == '/')\n            *p = '\\0';\n\n#ifndef AIAMAG\n          /* If the member name starts with a space or a slash, this\n             is an index into the file name mappings (used by GNU ar).\n             Otherwise if the member name looks like #1/NUMBER the\n             real member name appears in the element data (used by\n             4.4BSD).  */\n          if (! is_namemap\n              && (name[0] == ' ' || name[0] == '/')\n              && namemap != 0)\n            {\n              const char* err;\n              unsigned int name_off = make_toui (name + 1, &err);\n              size_t name_len;\n\n              if (err|| name_off >= namemap_size)\n                goto invalid;\n\n              name = namemap + name_off;\n              name_len = strlen (name);\n              if (name_len < 1)\n                goto invalid;\n              long_name = 1;\n            }\n          else if (name[0] == '#'\n                   && name[1] == '1'\n                   && name[2] == '/')\n            {\n              const char* err;\n              unsigned int name_len = make_toui (name + 3, &err);\n\n              if (err || name_len == 0 || name_len >= MIN (PATH_MAX, INT_MAX))\n                goto invalid;\n\n              name = alloca (name_len + 1);\n              nread = readbuf (desc, name, name_len);\n              if (nread < 0 || (unsigned int) nread != name_len)\n                goto invalid;\n\n              name[name_len] = '\\0';\n\n              long_name = 1;\n            }\n#endif /* Not AIAMAG. */\n        }\n\n#ifndef M_XENIX\n#define PARSE_INT(_m, _t, _b, _n) \\\n        (_t) parse_int (TOCHAR (member_header._m), sizeof (member_header._m), \\\n                        _b, TYPE_MAXIMUM (_t), _n, archive, name)\n\n        eltmode = PARSE_INT (ar_mode, unsigned int, 8, \"mode\");\n        eltsize = PARSE_INT (ar_size, long, 10, \"size\");\n        eltdate = PARSE_INT (ar_date, intmax_t, 10, \"date\");\n        eltuid = PARSE_INT (ar_uid, int, 10, \"uid\");\n        eltgid = PARSE_INT (ar_gid, int, 10, \"gid\");\n#undef PARSE_INT\n#else   /* Xenix.  */\n        eltmode = (unsigned short int) member_header.ar_mode;\n        eltsize = member_header.ar_size;\n#endif  /* Not Xenix.  */\n\n        fnval =\n          (*function) (desc, name, ! long_name, member_offset,\n                       member_offset + AR_HDR_SIZE, eltsize,\n#ifndef M_XENIX\n                       eltdate, eltuid, eltgid,\n#else   /* Xenix.  */\n                       member_header.ar_date,\n                       member_header.ar_uid,\n                       member_header.ar_gid,\n#endif  /* Not Xenix.  */\n                       eltmode, arg);\n\n#endif  /* AIAMAG.  */\n\n        if (fnval)\n          {\n            (void) close (desc);\n            return fnval;\n          }\n\n#ifdef AIAMAG\n        if (member_offset == last_member_offset)\n          /* End of the chain.  */\n          break;\n\n#ifdef AIAMAGBIG\n        if (big_archive)\n         sscanf (member_header_big.ar_nxtmem, \"%20ld\", &member_offset);\n        else\n#endif\n          sscanf (member_header.ar_nxtmem, \"%12ld\", &member_offset);\n\n        if (lseek (desc, member_offset, 0) != member_offset)\n          goto invalid;\n#else\n\n        /* If this member maps archive names, we must read it in.  The\n           name map will always precede any members whose names must\n           be mapped.  */\n        if (is_namemap)\n          {\n            char *clear;\n            char *limit;\n\n            if (eltsize > INT_MAX)\n              goto invalid;\n            namemap = alloca (eltsize + 1);\n            nread = readbuf (desc, namemap, eltsize);\n            if (nread != eltsize)\n              goto invalid;\n            namemap_size = eltsize;\n\n            /* The names are separated by newlines.  Some formats have\n               a trailing slash.  Null terminate the strings for\n               convenience.  */\n            limit = namemap + eltsize;\n            for (clear = namemap; clear < limit; clear++)\n              {\n                if (*clear == '\\n')\n                  {\n                    *clear = '\\0';\n                    if (clear[-1] == '/')\n                      clear[-1] = '\\0';\n                  }\n              }\n            *limit = '\\0';\n\n            is_namemap = 0;\n          }\n\n        member_offset += AR_HDR_SIZE + eltsize;\n        if (member_offset % 2 != 0)\n          member_offset++;\n#endif\n      }\n  }\n\n  close (desc);\n  return 0;\n\n invalid:\n  close (desc);\n  return -2;\n}\n#endif /* !MK_OS_VMS */\n\f\n/* Return nonzero iff NAME matches MEM.\n   If TRUNCATED is nonzero, MEM may be truncated to\n   sizeof (struct ar_hdr.ar_name) - 1.  */\n\nint\nar_name_equal (const char *name, const char *mem, int truncated)\n{\n  const char *p;\n\n  /* GNU ar allows -P to preserve parent paths, so test the literal name\n     before stripping off the directory.  */\n  if (streq (name, mem))\n    return 1;\n\n  p = strrchr (name, '/');\n  if (p != 0)\n    name = p + 1;\n\n#if !MK_OS_VMS\n  if (truncated)\n    {\n#ifdef AIAMAG\n      /* TRUNCATED should never be set on this system.  */\n      abort ();\n#else\n      struct ar_hdr hdr;\n#if !defined (__hpux) && !defined (cray)\n      return strneq (name, mem, sizeof (hdr.ar_name) - 1);\n#else\n      return strneq (name, mem, sizeof (hdr.ar_name) - 2);\n#endif /* !__hpux && !cray */\n#endif /* !AIAMAG */\n    }\n\n  return !strcmp (name, mem);\n#else\n  /* VMS members do not have suffixes, but the filenames usually\n     have.\n     Do we need to strip VMS disk/directory format paths?\n\n     Most VMS compilers etc. by default are case insensitive\n     but produce uppercase external names, incl. module names.\n     However the VMS librarian (ar) and the linker by default\n     are case sensitive: they take what they get, usually\n     uppercase names. So for the non-default settings of the\n     compilers etc. there is a need to have a case sensitive\n     mode. */\n  {\n    int len;\n    len = strlen(mem);\n    int match;\n    char *dot;\n    if ((dot=strrchr(name,'.')))\n      match = (len == dot - name) && !strncasecmp(name, mem, len);\n    else\n      match = !strcasecmp (name, mem);\n    return match;\n  }\n#endif /* !MK_OS_VMS */\n}\n\f\n#if !MK_OS_VMS\n/* ARGSUSED */\nstatic intmax_t\nar_member_pos (int desc UNUSED, const char *mem, int truncated,\n               long int hdrpos, long int datapos UNUSED, long int size UNUSED,\n               intmax_t date UNUSED, int uid UNUSED, int gid UNUSED,\n               unsigned int mode UNUSED, const void *name)\n{\n  if (!ar_name_equal (name, mem, truncated))\n    return 0;\n  return hdrpos;\n}\n\n/* Set date of member MEMNAME in archive ARNAME to current time.\n   Returns 0 if successful,\n   -1 if file ARNAME does not exist,\n   -2 if not a valid archive,\n   -3 if other random system call error (including file read-only),\n   1 if valid but member MEMNAME does not exist.  */\n\nint\nar_member_touch (const char *arname, const char *memname)\n{\n  intmax_t pos = ar_scan (arname, ar_member_pos, memname);\n  off_t opos;\n  int fd;\n  struct ar_hdr ar_hdr;\n  off_t o;\n  int r;\n  int datelen;\n  struct stat statbuf;\n\n  if (pos < 0)\n    return (int) pos;\n  if (!pos)\n    return 1;\n\n  opos = (off_t) pos;\n\n  EINTRLOOP (fd, open (arname, O_RDWR, 0666));\n  if (fd < 0)\n    return -3;\n  /* Read in this member's header */\n  EINTRLOOP (o, lseek (fd, opos, 0));\n  if (o < 0)\n    goto lose;\n  r = readbuf (fd, &ar_hdr, AR_HDR_SIZE);\n  if (r != AR_HDR_SIZE)\n    goto lose;\n  /* The file's mtime is the time we we want.  */\n  EINTRLOOP (r, fstat (fd, &statbuf));\n  if (r < 0)\n    goto lose;\n  /* Advance member's time to that time */\n#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || MK_OS_W32\n  datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date,\n                      \"%\" PRIdMAX, (intmax_t) statbuf.st_mtime);\n  if (! (0 <= datelen && datelen < (int) sizeof ar_hdr.ar_date))\n    goto lose;\n  memset (ar_hdr.ar_date + datelen, ' ', sizeof ar_hdr.ar_date - datelen);\n#else\n  ar_hdr.ar_date = statbuf.st_mtime;\n#endif\n  /* Write back this member's header */\n  EINTRLOOP (o, lseek (fd, opos, 0));\n  if (o < 0)\n    goto lose;\n  r = writebuf (fd, &ar_hdr, AR_HDR_SIZE);\n  if (r != AR_HDR_SIZE)\n    goto lose;\n  close (fd);\n  return 0;\n\n lose:\n  r = errno;\n  close (fd);\n  errno = r;\n  return -3;\n}\n#endif\n\f\n#ifdef TEST\n\nintmax_t\ndescribe_member (int desc, const char *name, int truncated,\n                 long int hdrpos, long int datapos, long int size,\n                 intmax_t date, int uid, int gid, unsigned int mode,\n                 const void *arg)\n{\n  extern char *ctime ();\n  time_t d = date;\n  char const *ds;\n\n  printf (_(\"Member '%s'%s: %ld bytes at %ld (%ld).\\n\"),\n          name, truncated ? _(\" (name might be truncated)\") : \"\",\n          size, hdrpos, datapos);\n  ds = ctime (&d);\n  printf (_(\"  Date %s\"), ds ? ds : \"?\");\n  printf (_(\"  uid = %d, gid = %d, mode = 0%o.\\n\"), uid, gid, mode);\n\n  return 0;\n}\n\nint\nmain (int argc, char **argv)\n{\n  ar_scan (argv[1], describe_member, NULL);\n  return 0;\n}\n\n#endif  /* TEST.  */\n#endif  /* NO_ARCHIVES.  */\n"
  },
  {
    "path": "src/commands.c",
    "content": "/* Command processing for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"os.h\"\n#include \"dep.h\"\n#include \"variable.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#if MK_OS_W32\n#include <windows.h>\n#include \"w32err.h\"\n#endif\n\n#if MK_OS_VMS\n# define FILE_LIST_SEPARATOR (vms_comma_separator ? ',' : ' ')\n#else\n# define FILE_LIST_SEPARATOR ' '\n#endif\n\f\n\nstatic unsigned long\ndep_hash_1 (const void *key)\n{\n  const struct dep *d = key;\n  return_STRING_HASH_1 (dep_name (d));\n}\n\nstatic unsigned long\ndep_hash_2 (const void *key)\n{\n  const struct dep *d = key;\n  return_STRING_HASH_2 (dep_name (d));\n}\n\nstatic int\ndep_hash_cmp (const void *x, const void *y)\n{\n  const struct dep *dx = x;\n  const struct dep *dy = y;\n  return strcmp (dep_name (dx), dep_name (dy));\n}\n\n/* Set FILE's automatic variables up.\n * Use STEM to set $*.\n * If STEM is 0, then set FILE->STEM and $* to the target name with any\n * suffix in the .SUFFIXES list stripped off.  */\n\nvoid\nset_file_variables (struct file *file, const char *stem)\n{\n  struct dep *d;\n  const char *at, *percent, *star, *less;\n\n#ifndef NO_ARCHIVES\n  /* If the target is an archive member 'lib(member)',\n     then $@ is 'lib' and $% is 'member'.  */\n\n  if (ar_name (file->name))\n    {\n      size_t len;\n      const char *cp;\n      char *p;\n\n      cp = strchr (file->name, '(');\n      p = alloca (cp - file->name + 1);\n      memcpy (p, file->name, cp - file->name);\n      p[cp - file->name] = '\\0';\n      at = p;\n      len = strlen (cp + 1);\n      p = alloca (len);\n      memcpy (p, cp + 1, len - 1);\n      p[len - 1] = '\\0';\n      percent = p;\n    }\n  else\n#endif  /* NO_ARCHIVES.  */\n    {\n      at = file->name;\n      percent = \"\";\n    }\n\n  /* $* is the stem from an implicit or static pattern rule.  */\n  if (stem == 0)\n    {\n      /* In Unix make, $* is set to the target name with\n         any suffix in the .SUFFIXES list stripped off for\n         explicit rules.  We store this in the 'stem' member.  */\n      const char *name;\n      size_t len;\n\n#ifndef NO_ARCHIVES\n      if (ar_name (file->name))\n        {\n          name = strchr (file->name, '(') + 1;\n          len = strlen (name) - 1;\n        }\n      else\n#endif\n        {\n          name = file->name;\n          len = strlen (name);\n        }\n\n      for (d = enter_file (strcache_add (\".SUFFIXES\"))->deps; d ; d = d->next)\n        {\n          const char *dn = dep_name (d);\n          size_t slen = strlen (dn);\n          if (len > slen && memcmp (dn, name + (len - slen), slen) == 0)\n            {\n              file->stem = stem = strcache_add_len (name, len - slen);\n              break;\n            }\n        }\n      if (d == 0)\n        file->stem = stem = \"\";\n    }\n  star = stem;\n\n  /* $< is the first not order-only dependency.  */\n  less = \"\";\n  for (d = file->deps; d != 0; d = d->next)\n    if (!d->ignore_mtime && !d->ignore_automatic_vars && !d->need_2nd_expansion)\n      {\n        less = dep_name (d);\n        break;\n      }\n\n  if (file->cmds != 0 && file->cmds == default_file->cmds)\n    /* This file got its commands from .DEFAULT.\n       In this case $< is the same as $@.  */\n    less = at;\n\n#define DEFINE_VARIABLE(name, len, value) \\\n  (void) define_variable_for_file (name,len,value,o_automatic,0,file)\n\n  /* Define the variables.  */\n\n  DEFINE_VARIABLE (\"<\", 1, less);\n  DEFINE_VARIABLE (\"*\", 1, star);\n  DEFINE_VARIABLE (\"@\", 1, at);\n  DEFINE_VARIABLE (\"%\", 1, percent);\n\n  /* Compute the values for $^, $+, $?, and $|.  */\n\n  {\n    static char *plus_value=0, *bar_value=0, *qmark_value=0;\n    static size_t plus_max=0, bar_max=0, qmark_max=0;\n\n    size_t qmark_len, plus_len, bar_len;\n    char *cp;\n    char *caret_value;\n    char *qp;\n    char *bp;\n    size_t len;\n\n    struct hash_table dep_hash;\n    void **slot;\n\n    /* Compute first the value for $+, which is supposed to contain\n       duplicate dependencies as they were listed in the makefile.  */\n\n    plus_len = 0;\n    bar_len = 0;\n    for (d = file->deps; d != 0; d = d->next)\n      {\n        if (!d->need_2nd_expansion && !d->ignore_automatic_vars)\n          {\n            if (d->ignore_mtime)\n              bar_len += strlen (dep_name (d)) + 1;\n            else\n              plus_len += strlen (dep_name (d)) + 1;\n          }\n      }\n\n    if (bar_len == 0)\n      bar_len++;\n\n    if (plus_len == 0)\n      plus_len++;\n\n    if (plus_len > plus_max)\n      plus_value = xrealloc (plus_value, plus_max = plus_len);\n\n    cp = plus_value;\n\n    qmark_len = plus_len + 1;   /* Will be this or less.  */\n    for (d = file->deps; d != 0; d = d->next)\n      if (! d->ignore_mtime && ! d->need_2nd_expansion && ! d->ignore_automatic_vars)\n        {\n          const char *c = dep_name (d);\n\n#ifndef NO_ARCHIVES\n          if (ar_name (c))\n            {\n              c = strchr (c, '(') + 1;\n              len = strlen (c) - 1;\n            }\n          else\n#endif\n            len = strlen (c);\n\n          cp = mempcpy (cp, c, len);\n          *cp++ = FILE_LIST_SEPARATOR;\n          if (! (d->changed || always_make_flag))\n            qmark_len -= len + 1;       /* Don't space in $? for this one.  */\n        }\n\n    /* Kill the last space and define the variable.  */\n\n    cp[cp > plus_value ? -1 : 0] = '\\0';\n    DEFINE_VARIABLE (\"+\", 1, plus_value);\n\n    /* Compute the values for $^, $?, and $|.  */\n\n    cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */\n\n    if (qmark_len > qmark_max)\n      qmark_value = xrealloc (qmark_value, qmark_max = qmark_len);\n    qp = qmark_value;\n\n    if (bar_len > bar_max)\n      bar_value = xrealloc (bar_value, bar_max = bar_len);\n    bp = bar_value;\n\n    /* Make sure that no dependencies are repeated in $^, $?, and $|.  It\n       would be natural to combine the next two loops but we can't do it\n       because of a situation where we have two dep entries, the first\n       is order-only and the second is normal (see below).  */\n\n    hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);\n\n    for (d = file->deps; d != 0; d = d->next)\n      {\n        if (d->need_2nd_expansion || d->ignore_automatic_vars)\n          continue;\n\n        slot = hash_find_slot (&dep_hash, d);\n        if (HASH_VACANT (*slot))\n          hash_insert_at (&dep_hash, d, slot);\n        else\n          {\n            /* Check if the two prerequisites have different ignore_mtime.\n               If so then we need to \"upgrade\" one that is order-only.  */\n\n            struct dep* hd = (struct dep*) *slot;\n\n            if (d->ignore_mtime != hd->ignore_mtime)\n              d->ignore_mtime = hd->ignore_mtime = 0;\n          }\n      }\n\n    for (d = file->deps; d != 0; d = d->next)\n      {\n        const char *c;\n\n        if (d->need_2nd_expansion || d->ignore_automatic_vars || hash_find_item (&dep_hash, d) != d)\n          continue;\n\n        c = dep_name (d);\n#ifndef NO_ARCHIVES\n        if (ar_name (c))\n          {\n            c = strchr (c, '(') + 1;\n            len = strlen (c) - 1;\n          }\n        else\n#endif\n          len = strlen (c);\n\n        if (d->ignore_mtime)\n          {\n            bp = mempcpy (bp, c, len);\n            *bp++ = FILE_LIST_SEPARATOR;\n          }\n        else\n          {\n            cp = mempcpy (cp, c, len);\n            *cp++ = FILE_LIST_SEPARATOR;\n            if (d->changed || always_make_flag)\n              {\n                qp = mempcpy (qp, c, len);\n                *qp++ = FILE_LIST_SEPARATOR;\n              }\n          }\n      }\n\n    hash_free (&dep_hash, 0);\n\n    /* Kill the last spaces and define the variables.  */\n\n    cp[cp > caret_value ? -1 : 0] = '\\0';\n    DEFINE_VARIABLE (\"^\", 1, caret_value);\n\n    qp[qp > qmark_value ? -1 : 0] = '\\0';\n    DEFINE_VARIABLE (\"?\", 1, qmark_value);\n\n    bp[bp > bar_value ? -1 : 0] = '\\0';\n    DEFINE_VARIABLE (\"|\", 1, bar_value);\n  }\n\n#undef DEFINE_VARIABLE\n}\n\f\n/* Chop CMDS up into individual command lines if necessary.\n   Also set the 'lines_flags' and 'any_recurse' members.  */\n\nvoid\nchop_commands (struct commands *cmds)\n{\n  unsigned short nlines;\n  unsigned short i;\n  char **lines;\n\n  /* If we don't have any commands, or we already parsed them, never mind.  */\n  if (!cmds || cmds->command_lines != NULL)\n    return;\n\n  /* Chop CMDS->commands up into lines in CMDS->command_lines.  */\n\n  if (one_shell)\n    {\n      size_t l = strlen (cmds->commands);\n\n      nlines = 1;\n      lines = xmalloc (nlines * sizeof (char *));\n      lines[0] = xstrdup (cmds->commands);\n\n      /* Strip the trailing newline.  */\n      if (l > 0 && lines[0][l-1] == '\\n')\n        lines[0][l-1] = '\\0';\n    }\n  else\n    {\n      const char *p = cmds->commands;\n      size_t max = 5;\n\n      nlines = 0;\n      lines = xmalloc (max * sizeof (char *));\n      while (*p != '\\0')\n        {\n          const char *end = p;\n        find_end:;\n          end = strchr (end, '\\n');\n          if (end == NULL)\n            end = p + strlen (p);\n          else if (end > p && end[-1] == '\\\\')\n            {\n              int backslash = 1;\n              if (end > p + 1)\n                {\n                  const char *b;\n                  for (b = end - 2; b >= p && *b == '\\\\'; --b)\n                    backslash = !backslash;\n                }\n              if (backslash)\n                {\n                  ++end;\n                  goto find_end;\n                }\n            }\n\n          if (nlines == USHRT_MAX)\n            ON (fatal, &cmds->fileinfo,\n                _(\"recipe has too many lines (limit %hu)\"), nlines);\n\n          if (nlines == max)\n            {\n              max += 2;\n              lines = xrealloc (lines, max * sizeof (char *));\n            }\n\n          lines[nlines++] = xstrndup (p, (size_t) (end - p));\n          p = end;\n          if (*p != '\\0')\n            ++p;\n        }\n    }\n\n  /* Finally, set the corresponding CMDS->lines_flags elements and the\n     CMDS->any_recurse flag.  */\n\n  cmds->ncommand_lines = nlines;\n  cmds->command_lines = lines;\n\n  cmds->any_recurse = 0;\n  cmds->lines_flags = xmalloc (nlines);\n\n  for (i = 0; i < nlines; ++i)\n    {\n      unsigned char flags = 0;\n      const char *p = lines[i];\n\n      while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')\n        switch (*(p++))\n          {\n          case '+':\n            flags |= COMMANDS_RECURSE;\n            break;\n          case '@':\n            flags |= COMMANDS_SILENT;\n            break;\n          case '-':\n            flags |= COMMANDS_NOERROR;\n            break;\n          }\n\n      /* If no explicit '+' was given, look for MAKE variable references.  */\n      if (! ANY_SET (flags, COMMANDS_RECURSE)\n          && (strstr (p, \"$(MAKE)\") != 0 || strstr (p, \"${MAKE}\") != 0))\n        flags |= COMMANDS_RECURSE;\n\n      cmds->lines_flags[i] = flags;\n      cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;\n    }\n}\n\f\n/* Execute the commands to remake FILE.  If they are currently executing,\n   return or have already finished executing, just return.  Otherwise,\n   fork off a child process to run the first command line in the sequence.  */\n\nvoid\nexecute_file_commands (struct file *file)\n{\n  const char *p;\n\n  /* Don't go through all the preparations if\n     the commands are nothing but whitespace.  */\n\n  for (p = file->cmds->commands; *p != '\\0'; ++p)\n    if (!ISSPACE (*p) && *p != '-' && *p != '@' && *p != '+')\n      break;\n  if (*p == '\\0')\n    {\n      /* If there are no commands, assume everything worked.  */\n      set_command_state (file, cs_running);\n      file->update_status = us_success;\n      notice_finished_file (file);\n      return;\n    }\n\n  /* First set the automatic variables according to this file.  */\n\n  initialize_file_variables (file, 0);\n\n  set_file_variables (file, file->stem);\n\n  /* Some systems don't support overwriting a loaded object so if this one\n     unload it before remaking.  Keep its name in .LOADED: it will be rebuilt\n     and loaded again.  If rebuilding or loading again fail, then we'll exit\n     anyway and it won't matter.  */\n  if (file->loaded && unload_file (file->name) == 0)\n    {\n      file->loaded = 0;\n      file->unloaded = 1;\n    }\n\n  /* Start the commands running.  */\n  new_job (file);\n}\n\f\n/* This is set while we are inside fatal_error_signal,\n   so things can avoid nonreentrant operations.  */\n\nvolatile sig_atomic_t handling_fatal_signal = 0;\n\n/* Handle fatal signals.  */\n\nvoid\nfatal_error_signal (int sig)\n{\n#if MK_OS_DOS\n  extern int dos_status, dos_command_running;\n\n  if (dos_command_running)\n    {\n      /* That was the child who got the signal, not us.  */\n      dos_status |= (sig << 8);\n      return;\n    }\n  remove_intermediates (1);\n  exit (EXIT_FAILURE);\n#else /* not MK_OS_DOS */\n#if MK_OS_W32\n  extern HANDLE main_thread;\n\n  /* Windows creates a separate thread for handling Ctrl+C, so we need\n     to suspend the main thread, or else we will have race conditions\n     when both threads call reap_children.  */\n  if (main_thread)\n    {\n      DWORD susp_count = SuspendThread (main_thread);\n\n      if (susp_count != 0)\n        fprintf (stderr, \"SuspendThread: suspend count = %lu\\n\", susp_count);\n      else if (susp_count == (DWORD)-1)\n        {\n          DWORD ierr = GetLastError ();\n\n          fprintf (stderr, \"SuspendThread: error %lu: %s\\n\",\n                   ierr, map_windows32_error_to_string (ierr));\n        }\n    }\n#endif\n  handling_fatal_signal = 1;\n\n  /* Set the handling for this signal to the default.\n     It is blocked now while we run this handler.  */\n  signal (sig, SIG_DFL);\n\n  temp_stdin_unlink ();\n  osync_clear ();\n  jobserver_clear ();\n\n  /* A termination signal won't be sent to the entire\n     process group, but it means we want to kill the children.  */\n\n  if (sig == SIGTERM)\n    {\n      struct child *c;\n      for (c = children; c != 0; c = c->next)\n        if (!c->remote && c->pid > 0)\n          (void) kill (c->pid, SIGTERM);\n    }\n\n  /* If we got a signal that means the user\n     wanted to kill make, remove pending targets.  */\n\n  if (sig == SIGTERM || sig == SIGINT\n#ifdef SIGHUP\n    || sig == SIGHUP\n#endif\n#ifdef SIGQUIT\n    || sig == SIGQUIT\n#endif\n    )\n    {\n      struct child *c;\n\n      /* Remote children won't automatically get signals sent\n         to the process group, so we must send them.  */\n      for (c = children; c != 0; c = c->next)\n        if (c->remote && c->pid > 0)\n          (void) remote_kill (c->pid, sig);\n\n      for (c = children; c != 0; c = c->next)\n        delete_child_targets (c);\n\n      /* Clean up the children.  We don't just use the call below because\n         we don't want to print the \"Waiting for children\" message.  */\n      while (job_slots_used > 0)\n        reap_children (1, 0);\n    }\n  else\n    /* Wait for our children to die.  */\n    while (job_slots_used > 0)\n      reap_children (1, 1);\n\n  /* Delete any non-precious intermediate files that were made.  */\n\n  remove_intermediates (1);\n\n#ifdef SIGQUIT\n  if (sig == SIGQUIT)\n    /* We don't want to send ourselves SIGQUIT, because it will\n       cause a core dump.  Just exit instead.  */\n    exit (MAKE_TROUBLE);\n#endif\n\n#if MK_OS_W32\n  if (main_thread)\n    CloseHandle (main_thread);\n  /* Cannot call W32_kill with a pid (it needs a handle).  The exit\n     status of 130 emulates what happens in Bash.  */\n  exit (130);\n#else\n  /* Signal the same code; this time it will really be fatal.  The signal\n     will be unblocked when we return and arrive then to kill us.  */\n  if (kill (make_pid (), sig) < 0)\n    pfatal_with_name (\"kill\");\n#endif /* not MK_OS_W32 */\n#endif /* not MK_OS_DOS  */\n}\n\f\n/* Delete FILE unless it's precious or not actually a file (phony),\n   and it has changed on disk since we last stat'd it.  */\n\nstatic void\ndelete_target (struct file *file, const char *on_behalf_of)\n{\n  struct stat st;\n  int e;\n\n  if (file->precious || file->phony)\n    return;\n\n#ifndef NO_ARCHIVES\n  if (ar_name (file->name))\n    {\n      time_t file_date = (file->last_mtime == NONEXISTENT_MTIME\n                          ? (time_t) -1\n                          : (time_t) FILE_TIMESTAMP_S (file->last_mtime));\n      if (ar_member_date (file->name) != file_date)\n        {\n          if (on_behalf_of)\n            OSS (error, NILF,\n                 _(\"*** [%s] archive member '%s' may be bogus; not deleted\"),\n                 on_behalf_of, file->name);\n          else\n            OS (error, NILF,\n                _(\"*** archive member '%s' may be bogus; not deleted\"),\n                file->name);\n        }\n      return;\n    }\n#endif\n\n  EINTRLOOP (e, stat (file->name, &st));\n  if (e == 0\n      && S_ISREG (st.st_mode)\n      && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime)\n    {\n      if (on_behalf_of)\n        OSS (error, NILF,\n             _(\"*** [%s] deleting file '%s'\"), on_behalf_of, file->name);\n      else\n        OS (error, NILF, _(\"*** deleting file '%s'\"), file->name);\n      if (unlink (file->name) < 0\n          && errno != ENOENT)   /* It disappeared; so what.  */\n        perror_with_name (\"unlink: \", file->name);\n    }\n}\n\n\n/* Delete all non-precious targets of CHILD unless they were already deleted.\n   Set the flag in CHILD to say they've been deleted.  */\n\nvoid\ndelete_child_targets (struct child *child)\n{\n  struct dep *d;\n\n  if (child->deleted || child->pid < 0)\n    return;\n\n  /* Delete the target file if it changed.  */\n  delete_target (child->file, NULL);\n\n  /* Also remove any non-precious targets listed in the 'also_make' member.  */\n  for (d = child->file->also_make; d != 0; d = d->next)\n    delete_target (d->file, child->file->name);\n\n  child->deleted = 1;\n}\n\f\n/* Print out the commands in CMDS.  */\n\nvoid\nprint_commands (const struct commands *cmds)\n{\n  const char *s;\n\n  fputs (_(\"#  recipe to execute\"), stdout);\n\n  if (cmds->fileinfo.filenm == 0)\n    puts (_(\" (built-in):\"));\n  else\n    printf (_(\" (from '%s', line %lu):\\n\"),\n            cmds->fileinfo.filenm, cmds->fileinfo.lineno);\n\n  s = cmds->commands;\n  while (*s != '\\0')\n    {\n      const char *end;\n      int bs;\n\n      /* Print one full logical recipe line: find a non-escaped newline.  */\n      for (end = s, bs = 0; *end != '\\0'; ++end)\n        {\n          if (*end == '\\n' && !bs)\n            break;\n\n          bs = *end == '\\\\' ? !bs : 0;\n        }\n\n      printf (\"%c%.*s\\n\", cmd_prefix, (int) (end - s), s);\n\n      s = end + (end[0] == '\\n');\n    }\n}\n"
  },
  {
    "path": "src/commands.h",
    "content": "/* Definition of data structures describing shell commands for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* Structure that gives the commands to make a file\n   and information about where these commands came from.  */\n\nstruct commands\n  {\n    floc fileinfo;              /* Where commands were defined.  */\n    char *commands;             /* Commands text.  */\n    char **command_lines;       /* Commands chopped up into lines.  */\n    unsigned char *lines_flags; /* One set of flag bits for each line.  */\n    unsigned short ncommand_lines;/* Number of command lines.  */\n    char recipe_prefix;         /* Recipe prefix for this command set.  */\n    unsigned int any_recurse:1; /* Nonzero if any 'lines_flags' elt has */\n                                /* the COMMANDS_RECURSE bit set.  */\n  };\n\n/* Bits in 'lines_flags'.  */\n#define COMMANDS_RECURSE        1 /* Recurses: + or $(MAKE).  */\n#define COMMANDS_SILENT         2 /* Silent: @.  */\n#define COMMANDS_NOERROR        4 /* No errors: -.  */\n\nstruct file;\nstruct child;\n\nvoid fatal_error_signal (int sig);\nvoid execute_file_commands (struct file *file);\nvoid print_commands (const struct commands *cmds);\nvoid delete_child_targets (struct child *child);\nvoid chop_commands (struct commands *cmds);\nvoid set_file_variables (struct file *file, const char *stem);\n"
  },
  {
    "path": "src/config.h-vms",
    "content": "/* config.h-vms. Generated by hand by Klaus Kmpf <kkaempf@rmi.de>      -*-C-*-\n\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"mkconfig.h\"\n\n#define MK_OS_VMS 1\n\n/* Pull in types.h here to get __CRTL_VER defined for old versions of the\n   compiler which don't define it. */\n#ifdef __DECC\n# include <types.h>\n#endif\n\n/* Define to 1 if on AIX 3.\n   System headers sometimes define this.\n   We just want to avoid a redefinition error message.  */\n#ifndef _ALL_SOURCE\n/* #undef _ALL_SOURCE */\n#endif\n\n/* Define to 1 if NLS is requested.  */\n/* #undef ENABLE_NLS */\n\n/* Define as 1 if you have dcgettext.  */\n/* #undef HAVE_DCGETTEXT */\n\n/* Define as 1 if you have gettext and don't want to use GNU gettext.  */\n/* #undef HAVE_GETTEXT */\n\n/* Embed GNU Guile support */\n/* #undef HAVE_GUILE */\n\n/* Define to 1 if your locale.h file contains LC_MESSAGES.  */\n/* #undef HAVE_LC_MESSAGES */\n\n/* Define to the installation directory for locales.  */\n#define LOCALEDIR \"\"\n\n/* Define as 1 if you have the stpcpy function.  */\n/* #undef HAVE_STPCPY */\n\n/* Define to 1 if the closedir function returns void instead of int.  */\n/* #undef CLOSEDIR_VOID */\n\n/* Define to empty if the keyword does not work.  */\n/* #undef const */\n\n/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.\n   This function is required for alloca.c support on those systems.  */\n/* #undef CRAY_STACKSEG_END */\n\n/* Define for DGUX with <sys/dg_sys_info.h>.  */\n/* #undef DGUX */\n\n/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do\n   not define. */\n#define intmax_t unsigned long\n\n/* Define to 'unsigned long' or 'unsigned long long'\n   if <inttypes.h> doesn't define.  */\n#define uintmax_t unsigned long\n\n/* Define to 'int' if <sys/types.h> doesn't define.  */\n/* #undef gid_t */\n\n/* Define to 1 if you have alloca, as a function or macro.  */\n#define HAVE_ALLOCA 1\n\n/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).  */\n/* #undef HAVE_ALLOCA_H */\n\n/* Define to 1 if you have the declaration of 'getloadavg'. */\n/* #undef HAVE_DECL_GETLOADAVG */\n\n/* Define to 1 if you have the fdopen function.  */\n#define HAVE_FDOPEN 1\n\n/* Define to 1 if your system has a working fnmatch function.  */\n/* #undef HAVE_FNMATCH */\n\n/* Define to 1 if you have the getmntent function.  */\n/* #undef HAVE_GETMNTENT */\n\n/* Define to 1 if the 'long double' type works.  */\n/* #undef HAVE_LONG_DOUBLE */\n\n/* Define to 1 if you support file names longer than 14 characters.  */\n#define HAVE_LONG_FILE_NAMES 1\n\n/* Define to 1 if you have a working 'mmap' system call.  */\n/* #undef HAVE_MMAP */\n\n/* Define to 1 if system calls automatically restart after interruption\n   by a signal.  */\n/* #undef HAVE_RESTARTABLE_SYSCALLS */\n\n/* Define to 1 if your struct stat has st_blksize.  */\n/* #undef HAVE_ST_BLKSIZE */\n\n/* Define to 1 if your struct stat has st_blocks.  */\n/* #undef HAVE_ST_BLOCKS */\n\n/* Define to 1 if you have the strcoll function and it is properly defined.  */\n/* #undef HAVE_STRCOLL */\n\n/* Define to 1 if you have the strncasecmp' function. */\n#if __CRTL_VER >= 70000000\n#define HAVE_STRNCASECMP 1\n#endif\n\n/* Define to 1 if your struct stat has st_rdev.  */\n/* #undef HAVE_ST_RDEV */\n\n/* Define to 1 if you have the strftime function.  */\n/* #undef HAVE_STRFTIME */\n\n/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible.  */\n/* #undef HAVE_SYS_WAIT_H */\n\n/* Define to 1 if your struct tm has tm_zone.  */\n/* #undef HAVE_TM_ZONE */\n\n/* Define to 1 if you don't have tm_zone but do have the external array\n   tzname.  */\n/* #undef HAVE_TZNAME */\n\n/* Define to 1 if you have <unistd.h>.  */\n#ifdef __DECC\n#define HAVE_UNISTD_H 1\n#endif\n\n/* Define to 1 if utime(file, NULL) sets file's timestamp to the present.  */\n/* #undef HAVE_UTIME_NULL */\n\n/* Define to 1 if you have the wait3 system call.  */\n/* #undef HAVE_WAIT3 */\n\n/* Define to 1 if on MINIX.  */\n/* #undef _MINIX */\n\n/* Define to 1 if your struct nlist has an n_un member.  */\n/* #undef NLIST_NAME_UNION */\n\n/* Define to 1 if you have <nlist.h>.  */\n/* #undef NLIST_STRUCT */\n\n/* Define to 1 if your C compiler doesn't accept -c and -o together.  */\n/* #undef NO_MINUS_C_MINUS_O */\n\n/* Define to 'int' if <sys/types.h> doesn't define.  */\n/* I assume types.h is available for all 5.0 cc/cxx compilers */\n#if __DECC_VER < 50090000\n#define pid_t int\n#endif\n\n/* Define to 1 if the system does not provide POSIX.1 features except\n   with this defined.  */\n/* #undef _POSIX_1_SOURCE */\n\n/* Define to 1 if you need to in order for stat and other things to work.  */\n/* #undef _POSIX_SOURCE */\n\n/* If using the C implementation of alloca, define if you know the\n   direction of stack growth for your system; otherwise it will be\n   automatically deduced at run-time.\n        STACK_DIRECTION > 0 => grows toward higher addresses\n        STACK_DIRECTION < 0 => grows toward lower addresses\n        STACK_DIRECTION = 0 => direction of growth unknown\n */\n/* #undef STACK_DIRECTION */\n\n/* Define to 1 if the 'S_IS*' macros in <sys/stat.h> do not work properly.  */\n/* #undef STAT_MACROS_BROKEN */\n\n/* Define to 1 if you have the ANSI C header files.  */\n/* #undef STDC_HEADERS */\n\n/* Define on System V Release 4.  */\n/* #undef SVR4 */\n\n/* Define to 1 if 'sys_siglist' is declared by <signal.h>.  */\n/* #undef SYS_SIGLIST_DECLARED */\n\n/* Define to 'int' if <sys/types.h> doesn't define.  */\n#if __DECC_VER < 50090000\n#define uid_t int\n#endif\n\n/* Define for Encore UMAX.  */\n/* #undef UMAX */\n\n/* Define for Encore UMAX 4.3 that has <inq_status/cpustats.h>\n   instead of <sys/cpustats.h>.  */\n/* #undef UMAX4_3 */\n\n/* Define to the name of the SCCS 'get' command.  */\n/* #undef SCCS_GET */\n\n/* Define this if the SCCS 'get' command understands the '-G<file>' option.  */\n/* #undef SCCS_GET_MINUS_G */\n\n/* Define this to enable job server support in GNU Make.  */\n/* #undef MAKE_JOBSERVER */\n\n/* Define to be the nanoseconds member of struct stat's st_mtim,\n   if it exists.  */\n/* #undef ST_MTIM_NSEC */\n\n/* Define to 1 if the C library defines the variable 'sys_siglist'.  */\n/* #undefine HAVE_SYS_SIGLIST */\n\n/* Define to 1 if the C library defines the variable '_sys_siglist'.  */\n/* #undef HAVE__SYS_SIGLIST */\n\n/* Define to 1 if you have the 'union wait' type in <sys/wait.h>.  */\n/* #undef HAVE_UNION_WAIT */\n\n/* Define to 1 if you have the dup2 function.  */\n#define HAVE_DUP2 1\n\n/* Define to 1 if you have the getcwd function.  */\n#define HAVE_GETCWD 1\n\n/* Define to 1 if you have the getgroups function.  */\n/* #undef HAVE_GETGROUPS */\n\n/* Define to 1 if you have the gethostbyname function.  */\n/* #undef HAVE_GETHOSTBYNAME */\n\n/* Define to 1 if you have the gethostname function.  */\n/* #undef HAVE_GETHOSTNAME */\n\n/* Define to 1 if you have the memmove function.  */\n#define HAVE_MEMMOVE 1\n\n/* Define to 1 if you have the 'mkfifo' function.  */\n/* #undef HAVE_MKFIFO */\n\n/* Define to 1 if you have the mktemp function.  */\n#define HAVE_MKTEMP 1\n\n/* Define to 1 if you have the psignal function.  */\n/* #undef HAVE_PSIGNAL */\n\n/* Define to 1 if you have the pstat_getdynamic function.  */\n/* #undef HAVE_PSTAT_GETDYNAMIC */\n\n/* Define to 1 if you have the setegid function.  */\n/* #undef HAVE_SETEGID */\n\n/* Define to 1 if you have the seteuid function.  */\n/* #undef HAVE_SETEUID */\n\n/* Define to 1 if you have the setlinebuf function.  */\n/* #undef HAVE_SETLINEBUF */\n\n/* Define to 1 if you have the setregid function.  */\n/* #undefine HAVE_SETREGID */\n\n/* Define to 1 if you have the setreuid function.  */\n/* #define HAVE_SETREUID */\n\n/* Define to 1 if you have the sigsetmask function.  */\n#define HAVE_SIGSETMASK 1\n\n/* Define to 1 if you have the socket function.  */\n/* #undef HAVE_SOCKET */\n\n/* Define to 1 if you have the strcasecmp function.  */\n#define HAVE_STRCASECMP 1\n\n/* Define to 1 if you have the strcmpi function.  */\n/* #undef HAVE_STRCMPI */\n\n/* Define to 1 if you have the stricmp function.  */\n/* #undef HAVE_STRICMP */\n\n/* Define to 1 if you have the strsignal function.  */\n/* #undef HAVE_STRSIGNAL */\n\n/* Define to 1 if you have the `strtoll' function. */\n#define HAVE_STRTOLL 1\n\n/* Define to 1 if you have the wait3 function.  */\n/* #undef HAVE_WAIT3 */\n\n/* Define to 1 if you have the waitpid function.  */\n/* #undef HAVE_WAITPID */\n\n/* Define to 1 if you have the <dirent.h> header file.  */\n#define HAVE_DIRENT_H 1\n\n/* Define to 1 if you have the <fcntl.h> header file.  */\n#ifdef __DECC\n#define HAVE_FCNTL_H 1\n#endif\n\n/* Define to 1 if you have the <limits.h> header file.  */\n#define HAVE_LIMITS_H 1\n\n/* Define to 1 if you have the <mach/mach.h> header file.  */\n/* #undef HAVE_MACH_MACH_H */\n\n/* Define to 1 if you have the <memory.h> header file.  */\n/* #undef HAVE_MEMORY_H */\n\n/* Define to 1 if you have the `mempcpy' function.  */\n/* #undef HAVE_MEMPCPY */\n\n/* Define to 1 if you have the <ndir.h> header file.  */\n/* #undef HAVE_NDIR_H */\n\n/* Define to 1 if you have the <stdlib.h> header file.  */\n#define HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the <string.h> header file.  */\n#define HAVE_STRING_H 1\n\n/* Define to 1 if you have the <sys/dir.h> header file.  */\n/* #undef HAVE_SYS_DIR_H */\n\n/* Define to 1 if you have the <sys/ndir.h> header file.  */\n/* #undef HAVE_SYS_NDIR_H */\n\n/* Define to 1 if you have the <sys/param.h> header file.  */\n/* #undef HAVE_SYS_PARAM_H */\n\n/* Define to 1 if you have the <sys/wait.h> header file.  */\n/* #undef HAVE_SYS_WAIT_H */\n\n/* Define to 1 if you have the dgc library (-ldgc).  */\n/* #undef HAVE_LIBDGC */\n\n/* Define to 1 if you have the kstat library (-lkstat).  */\n/* #undef HAVE_LIBKSTAT *\n\n/* Define to 1 if you have the sun library (-lsun).  */\n/* #undef HAVE_LIBSUN */\n\n/* Define to 1 if you have the `isatty' function. */\n/* #undef HAVE_ISATTY */\n\n/* Define to 1 if you have the `ttyname' function. */\n/* #undef HAVE_TTYNAME */\n\n/* Use high resolution file timestamps if nonzero. */\n#define FILE_TIMESTAMP_HI_RES 0\n\n/* Define for case insensitve filenames */\n#define HAVE_CASE_INSENSITIVE_FS 1\n\n/* VMS specific, define it if you want to use case sensitive targets */\n/* #undef WANT_CASE_SENSITIVE_TARGETS */\n\n/* VMS specific, V7.0 has opendir() and friends, so it's undefined */\n/* If you want to use non-VMS code for opendir() etc. on V7.0 and greater\n   define the first or both macros AND change the compile command to get the\n   non-VMS versions linked: (prefix=(all,except=(opendir,...  */\n/* #undef HAVE_VMSDIR_H */\n/* #undef _DIRENT_HAVE_D_NAMLEN */\n\n/* On older systems without 7.0 backport of CRTL use non-VMS code for opendir() etc. */\n#if __CRTL_VER < 70000000\n# define HAVE_VMSDIR_H 1\n#endif\n\n#if defined(HAVE_VMSDIR_H) && defined(HAVE_DIRENT_H)\n#undef HAVE_DIRENT_H\n#endif\n\n#define HAVE_STDLIB_H 1\n#define INCLUDEDIR \"sys$sysroot:[syslib]\"\n#define LIBDIR \"sys$sysroot:[syslib]\"\n\n/* Don't use RTL functions of OpenVMS */\n#ifdef __DECC\n#include <stdio.h>\n#include <unistd.h>\n#define getopt   gnu_getopt\n#define optarg   gnu_optarg\n#define optopt   gnu_optopt\n#define optind   gnu_optind\n#define opterr   gnu_opterr\n#define globfree gnu_globfree\n#define glob     gnu_glob\n#endif\n\n/* Define if using alloca.c.  */\n/* #undef C_ALLOCA */\n/* maybe this should be placed into makeint.h */\n#if     defined(__VAX) && defined(__DECC)\n#define alloca(n)       __ALLOCA(n)\n#endif\n\n/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most\n   significant byte first (like Motorola and SPARC, unlike Intel). */\n/* #  undef WORDS_BIGENDIAN */\n\n/* Output sync sypport */\n#define NO_OUTPUT_SYNC\n\n/* Define to 1 to write even short single-line actions into a VMS/DCL command\n   file; this also enables exporting make environment variables into the\n   (sub-)process, which executes the action.\n   The usual make rules apply whether a shell variable - here a DCL symbol or\n   VMS logical [see CRTL getenv()] - is added to the make environment and\n   is exported. */\n#define USE_DCL_COM_FILE 1\n\n/* Build host information. */\n#define MAKE_HOST \"VMS\"\n\n/* Include customized declarations.  */\n#include \"../src/mkcustom.h\"\n"
  },
  {
    "path": "src/config.h.W32",
    "content": "/* config.h.W32 -- hand-massaged config.h file for Windows builds       -*-C-*-\n\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"mkconfig.h\"\n\n/* Build for the Windows32 API. */\n#define MK_OS_W32 1\n\n/* Suppress some Visual C++ warnings.\n   Maybe after the code cleanup for ISO C we can remove some/all of these.  */\n#if _MSC_VER > 1000\n# pragma warning(disable:4100) /* unreferenced formal parameter */\n# pragma warning(disable:4130) /* logical operation on address of string constant */\n# pragma warning(disable:4131) /* uses old-style declarator */\n# pragma warning(disable:4702) /* unreachable code */\n# define _CRT_SECURE_NO_WARNINGS  1 /* function or variable may be unsafe */\n# define _CRT_NONSTDC_NO_WARNINGS 1 /* functions w/o a leading underscore */\n#endif\n\n/* Define to 1 if the 'closedir' function returns void instead of 'int'. */\n/* #undef CLOSEDIR_VOID */\n\n/* Define to 1 if using 'alloca.c'. */\n/* #undef C_ALLOCA */\n\n/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */\n/* #undef DGUX */\n\n/* Define to 1 if translation of program messages to the user's native\n   language is requested. */\n/* #undef ENABLE_NLS */\n\n/* Use high resolution file timestamps if nonzero. */\n#define FILE_TIMESTAMP_HI_RES 0\n\n/* Define to 1 if you have 'alloca' after including <alloca.h>, a header that\n   may be supplied by this distribution. */\n#define HAVE_ALLOCA 1\n\n/* Define to 1 if <alloca.h> works. */\n/* #undef HAVE_ALLOCA_H */\n\n/* Define to 1 if you have the 'atexit' function. */\n#define HAVE_ATEXIT 1\n\n/* Use case insensitive file names */\n/* #undef HAVE_CASE_INSENSITIVE_FS */\n\n/* Define to 1 if you have the clock_gettime function. */\n/* #undef HAVE_CLOCK_GETTIME */\n\n/* Define if the GNU dcgettext() function is already present or preinstalled.\n   */\n/* #undef HAVE_DCGETTEXT */\n\n/* Define to 1 if you have the declaration of 'bsd_signal', and to 0 if you\n   don't. */\n#define HAVE_DECL_BSD_SIGNAL 0\n\n/* Define to 1 if you have the declaration of `dlerror', and to 0 if you\n   don't. */\n#define HAVE_DECL_DLERROR 0\n\n/* Define to 1 if you have the declaration of `dlopen', and to 0 if you don't.\n   */\n#define HAVE_DECL_DLOPEN 0\n\n/* Define to 1 if you have the declaration of `dlsym', and to 0 if you don't.\n   */\n#define HAVE_DECL_DLSYM 0\n\n/* Define to 1 if you have the declaration of 'getloadavg'. */\n/* #undef HAVE_DECL_GETLOADAVG */\n\n/* Define to 1 if you have the declaration of 'sys_siglist', and to 0 if you\n   don't. */\n#define HAVE_DECL_SYS_SIGLIST 0\n\n/* Define to 1 if you have the declaration of '_sys_siglist', and to 0 if you\n   don't. */\n#define HAVE_DECL__SYS_SIGLIST 0\n\n/* Define to 1 if you have the declaration of '__sys_siglist', and to 0 if you\n   don't. */\n#define HAVE_DECL___SYS_SIGLIST 0\n\n/* Define to 1 if you have the <dirent.h> header file, and it defines 'DIR'.\n   */\n#define HAVE_DIRENT_H 1\n\n/* Define to 1 if you have the <direct.h> header file, and it defines getcwd()\n   and chdir().\n   */\n#if (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TINYC__)) && !defined(__INTERIX)\n# define HAVE_DIRECT_H 1\n#endif\n\n/* Support DOS-style pathnames. */\n#define HAVE_DOS_PATHS 1\n\n/* Define to 1 if you have the 'dup' function. */\n#define HAVE_DUP 1\n\n/* Define to 1 if you have the 'dup2' function. */\n#define HAVE_DUP2 1\n\n/* Define to 1 if you have the <fcntl.h> header file. */\n#define HAVE_FCNTL_H 1\n\n/* Define to 1 if you have the 'fdopen' function. */\n#ifdef __MINGW32__\n#define HAVE_FDOPEN 1\n#endif\n\n/* Define to 1 if you have the `fork' function. */\n/* #undef HAVE_FORK */\n\n/* Define to 1 if you have the 'getcwd' function.  */\n#define HAVE_GETCWD 1\n\n/* Define to 1 if you have the 'getgroups' function. */\n/* #undef HAVE_GETGROUPS */\n\n/* Define to 1 if you have the 'gethostbyname' function. */\n/* #undef HAVE_GETHOSTBYNAME */\n\n/* Define to 1 if you have the 'gethostname' function. */\n/* #undef HAVE_GETHOSTNAME */\n\n/* Define to 1 if you have the 'getrlimit' function. */\n/* #undef HAVE_GETRLIMIT */\n\n/* Define if the GNU gettext() function is already present or preinstalled. */\n/* #undef HAVE_GETTEXT */\n\n/* Define to 1 if you have a standard gettimeofday function */\n#ifdef __MINGW32__\n#define HAVE_GETTIMEOFDAY 1\n#endif\n\n/* Embed GNU Guile support.  Windows build sets this on the\n   compilation command line.  */\n/* #undef HAVE_GUILE */\n\n/* Define if you have the iconv() function. */\n/* #undef HAVE_ICONV */\n\n/* Define to 1 if you have the <inttypes.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_INTTYPES_H 1\n#endif\n\n/* Define to 1 if you have the `isatty' function. */\n#define HAVE_ISATTY 1\n\n/* Define to 1 if you have the 'dgc' library (-ldgc). */\n/* #undef HAVE_LIBDGC */\n\n/* Define to 1 if you have the 'kstat' library (-lkstat). */\n/* #undef HAVE_LIBKSTAT */\n\n/* Define to 1 if you have the `perfstat' library (-lperfstat). */\n/* #undef HAVE_LIBPERFSTAT */\n\n/* Define to 1 if you have the <limits.h> header file. */\n#define HAVE_LIMITS_H 1\n\n/* Define to 1 if you have the <locale.h> header file. */\n/* #undef HAVE_LOCALE_H */\n\n/* Define to 1 if the system has the type 'long long int'. */\n#define HAVE_LONG_LONG_INT 1\n\n/* Define to 1 if you have the 'lstat' function. */\n/* #undef HAVE_LSTAT */\n\n/* Define to 1 if you have the <mach/mach.h> header file. */\n/* #undef HAVE_MACH_MACH_H */\n\n/* Define to 1 if you have the <memory.h> header file. */\n#define HAVE_MEMORY_H 1\n\n/* Define to 1 if you have the `mempcpy' function.  */\n/* #undef HAVE_MEMPCPY */\n\n/* Define to 1 if you have the `memrchr' function. */\n/* #undef HAVE_MEMRCHR */\n\n/* Define to 1 if you have the <minix/config.h> header file. */\n/* #undef HAVE_MINIX_CONFIG_H */\n\n/* Define to 1 if you have the 'mkfifo' function. */\n/* #undef HAVE_MKFIFO */\n\n/* Define to 1 if you have the 'mkstemp' function. */\n/* #undef HAVE_MKSTEMP */\n\n/* Define to 1 if you have the `mkstemp' function. */\n/* #undef HAVE_MKSTEMP */\n\n/* Define to 1 if you have the 'mktemp' function. */\n#define HAVE_MKTEMP 1\n\n/* Define to 1 if you have the <ndir.h> header file, and it defines 'DIR'. */\n/* #undef HAVE_NDIR_H */\n\n/* Define to 1 if you have the <nlist.h> header file. */\n/* #undef HAVE_NLIST_H */\n\n/* Define to 1 if you have the 'pipe' function. */\n/* #undef HAVE_PIPE */\n\n/* Define to 1 if you have the `posix_spawn' function. */\n/* #undef HAVE_POSIX_SPAWN */\n\n/* Define to 1 if you have the `posix_spawnattr_setsigmask' function. */\n/* #undef HAVE_POSIX_SPAWNATTR_SETSIGMASK */\n\n/* Define to 1 if you have the `pselect' function. */\n/* #undef HAVE_PSELECT */\n\n/* Define to 1 if you have the 'pstat_getdynamic' function. */\n/* #undef HAVE_PSTAT_GETDYNAMIC */\n\n/* Define to 1 if you have the 'readlink' function. */\n/* #undef HAVE_READLINK */\n\n/* Define to 1 if you have the 'realpath' function. */\n/* #undef HAVE_REALPATH */\n\n/* Define to 1 if <signal.h> defines the SA_RESTART constant. */\n/* #undef HAVE_SA_RESTART */\n\n/* Define to 1 if you have the 'setegid' function. */\n/* #undef HAVE_SETEGID */\n\n/* Define to 1 if you have the 'seteuid' function. */\n/* #undef HAVE_SETEUID */\n\n/* Define to 1 if you have the 'setlinebuf' function. */\n/* #undef HAVE_SETLINEBUF */\n\n/* Define to 1 if you have the 'setregid' function. */\n/* #undef HAVE_SETREGID */\n\n/* Define to 1 if you have the 'setreuid' function. */\n/* #undef HAVE_SETREUID */\n\n/* Define to 1 if you have the 'setrlimit' function. */\n/* #undef HAVE_SETRLIMIT */\n\n/* Define to 1 if you have the 'setvbuf' function. */\n#define HAVE_SETVBUF 1\n\n/* Define to 1 if you have the 'sigaction' function. */\n/* #undef HAVE_SIGACTION */\n\n/* Define to 1 if you have the 'sigsetmask' function. */\n/* #undef HAVE_SIGSETMASK */\n\n/* Define to 1 if you have the 'socket' function. */\n/* #undef HAVE_SOCKET */\n\n/* Define to 1 if you have the <spawn.h> header file. */\n/* #undef HAVE_SPAWN_H */\n\n/* Define to 1 if you have the <stdint.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_STDINT_H 1\n#endif\n\n/* Define to 1 if you have the <stdio.h> header file. */\n#define HAVE_STDIO_H 1\n\n/* Define to 1 if you have the <stdlib.h> header file. */\n#define HAVE_STDLIB_H 1\n\n/* Define to 1 if you have the `stpcpy' function. */\n/* #undef HAVE_STPCPY */\n\n/* Define to 1 if you have the 'strcasecmp' function. */\n#if defined(__MINGW32__) || defined(__TINYC__)\n#define HAVE_STRCASECMP 1\n#endif\n\n/* Define to 1 if you have the 'strcmpi' function. */\n#define HAVE_STRCMPI 1\n\n/* Define to 1 if you have the 'strcoll' function and it is properly defined.\n   */\n#define HAVE_STRCOLL 1\n\n/* Define to 1 if you have the 'strdup' function. */\n#define HAVE_STRDUP 1\n\n/* Define to 1 if you have the `strerror' function. */\n#define HAVE_STRERROR 1\n\n/* Define to 1 if you have the 'stricmp' function. */\n#define HAVE_STRICMP 1\n\n/* Define to 1 if you have the <strings.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_STRINGS_H 1\n#endif\n\n/* Define to 1 if you have the <string.h> header file. */\n#define HAVE_STRING_H 1\n\n/* Define to 1 if you have the 'strncasecmp' function. */\n#if defined(__MINGW32__) || defined(__TINYC__)\n#define HAVE_STRNCASECMP 1\n#endif\n\n/* Define to 1 if you have the 'strncmpi' function. */\n/* #undef HAVE_STRNCMPI */\n\n/* Define to 1 if you have the 'strndup' function. */\n/* #undef HAVE_STRNDUP */\n\n/* Define to 1 if you have the 'strnicmp' function. */\n#ifdef __MINGW32__\n#define HAVE_STRNICMP 1\n#endif\n\n/* Define to 1 if you have the 'strsignal' function. */\n/* #undef HAVE_STRSIGNAL */\n\n/* Define to 1 if you have the `strtoll' function. */\n#define HAVE_STRTOLL 1\n#ifdef __TINYC__\n# ifndef strtoll\n#  define strtoll _strtoi64\n# endif\n# ifndef strtoull\n#  define strtoull _strtoui64\n# endif\n#endif\n\n/* Define to 1 if `d_type' is a member of `struct dirent'. */\n/* SV 57152: MinGW64 version of dirent doesn't support d_type. */\n#ifndef __MINGW64__\n# define HAVE_STRUCT_DIRENT_D_TYPE 1\n#endif\n\n/* Define to 1 if 'n_un.n_name' is a member of 'struct nlist'. */\n/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */\n\n/* Define to 1 if you have the <sys/dir.h> header file, and it defines 'DIR'.\n   */\n/* #undef HAVE_SYS_DIR_H */\n\n/* Define to 1 if you have the <sys/file.h> header file. */\n/* #undef HAVE_SYS_FILE_H */\n\n/* Define to 1 if you have the <sys/loadavg.h> header file. */\n/* #undef HAVE_SYS_LOADAVG_H */\n\n/* Define to 1 if you have the <sys/ndir.h> header file, and it defines 'DIR'.\n   */\n/* #undef HAVE_SYS_NDIR_H */\n\n/* Define to 1 if you have the <sys/param.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_SYS_PARAM_H 1\n#endif\n\n/* Define to 1 if you have the <sys/resource.h> header file. */\n/* #undef HAVE_SYS_RESOURCE_H */\n\n/* Define to 1 if you have the <sys/select.h> header file. */\n/* #undef HAVE_SYS_SELECT_H */\n\n/* Define to 1 if you have the <sys/stat.h> header file. */\n#define HAVE_SYS_STAT_H 1\n\n/* Define to 1 if you have the <sys/time.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_SYS_TIME_H 1\n#endif\n\n/* Define to 1 if you have the <sys/types.h> header file. */\n#define HAVE_SYS_TYPES_H 1\n\n/* Define to 1 if you have the <sys/wait.h> header file. */\n/* #undef HAVE_SYS_WAIT_H */\n\n/* Define to 1 if you have the `ttyname' function. */\n#define HAVE_TTYNAME 1\nchar *ttyname (int);\n\n/* Define to 1 if the system has the type `intmax_t'. */\n#define HAVE_INTMAX_T 1\n\n/* Define to 1 if the system has the type `uintmax_t'. */\n#define HAVE_UINTMAX_T 1\n\n/* Define to 1 if you have the `umask' function. */\n#if defined(__MINGW32__) || defined(__TINYC__)\n# define HAVE_UMASK 1\n#endif\n\n/* Define to 1 if you have the \\'union wait' type in <sys/wait.h>. */\n/* #undef HAVE_UNION_WAIT */\n\n/* Define to 1 if you have the <unistd.h> header file. */\n#ifdef __MINGW32__\n#define HAVE_UNISTD_H 1\n#endif\n\n/* Define to 1 if the system has the type 'unsigned long long int'. */\n#define HAVE_UNSIGNED_LONG_LONG_INT 1\n\n/* Define to 1 if you have the `vfork' function. */\n/* #undef HAVE_VFORK */\n\n/* Define to 1 if you have the <vfork.h> header file. */\n/* #undef HAVE_VFORK_H */\n\n/* Define to 1 if you have the 'wait3' function. */\n/* #undef HAVE_WAIT3 */\n\n/* Define to 1 if you have the 'waitpid' function. */\n/* #undef HAVE_WAITPID */\n\n/* Define to 1 if you have the <wchar.h> header file. */\n/* #undef HAVE_WCHAR_H */\n\n/* Define to 1 if `fork' works. */\n/* #undef HAVE_WORKING_FORK */\n\n/* Define to 1 if `vfork' works. */\n/* #undef HAVE_WORKING_VFORK */\n\n/* Define to 1 if the system has the type `_Bool'. */\n/* #undef HAVE__BOOL */\n\n/* Build host information. */\n#define MAKE_HOST \"Windows32\"\n\n/* Define to 1 to enable job server support in GNU Make. */\n#define MAKE_JOBSERVER 1\n\n/* Define to 1 to enable 'load' support in GNU Make. */\n#define MAKE_LOAD 1\n\n/* Define to 1 to enable symbolic link timestamp checking. */\n/* #undef MAKE_SYMLINKS */\n\n/* Define to 1 if your 'struct nlist' has an 'n_un' member. Obsolete, depend\n   on 'HAVE_STRUCT_NLIST_N_UN_N_NAME */\n/* #undef NLIST_NAME_UNION */\n\n/* Define to 1 if struct nlist.n_name is a pointer rather than an array. */\n/* #undef NLIST_STRUCT */\n\n/* Define to 1 if your C compiler doesn't accept -c and -o together. */\n/* #undef NO_MINUS_C_MINUS_O */\n\n/* Define to the character that separates directories in PATH. */\n#define PATH_SEPARATOR_CHAR ';'\n\n/* Define to the name of the SCCS 'get' command. */\n#define SCCS_GET \"echo no sccs get\"\n\n/* Define this if the SCCS 'get' command understands the '-G<file>' option. */\n/* #undef SCCS_GET_MINUS_G */\n\n/* If using the C implementation of alloca, define if you know the\n   direction of stack growth for your system; otherwise it will be\n   automatically deduced at run time.\n        STACK_DIRECTION > 0 => grows toward higher addresses\n        STACK_DIRECTION < 0 => grows toward lower addresses\n        STACK_DIRECTION = 0 => direction of growth unknown */\n/* #undef STACK_DIRECTION */\n\n/* Define to 1 if the 'S_IS*' macros in <sys/stat.h> do not work properly. */\n/* #undef STAT_MACROS_BROKEN */\n\n/* Define to 1 if you have the ANSI C header files. */\n#define STDC_HEADERS 1\n\n/* Define if struct stat contains a nanoseconds field */\n/* #undef ST_MTIM_NSEC */\n\n/* Define to 1 on System V Release 4. */\n/* #undef SVR4 */\n\n/* Define to 1 for Encore UMAX. */\n/* #undef UMAX */\n\n/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of\n   <sys/cpustats.h>. */\n/* #undef UMAX4_3 */\n\n/* Define if using the dmalloc debugging malloc package */\n/* #undef WITH_DMALLOC */\n\n/* Define to 1 if on AIX 3.\n   System headers sometimes define this.\n   We just want to avoid a redefinition error message.  */\n#ifndef _ALL_SOURCE\n/* # undef _ALL_SOURCE */\n#endif\n\n/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most\n   significant byte first (like Motorola and SPARC, unlike Intel). */\n/* #  undef WORDS_BIGENDIAN */\n\n/* Number of bits in a file offset, on hosts where this is settable. */\n/* #undef _FILE_OFFSET_BITS */\n\n/* Define for large files, on AIX-style hosts. */\n/* #undef _LARGE_FILES */\n\n/* Define to 1 if on MINIX. */\n/* #undef _MINIX */\n\n/* Define to 2 if the system does not provide POSIX.1 features except with\n   this defined. */\n/* #undef _POSIX_1_SOURCE */\n\n/* Define to 1 if you need to in order for 'stat' and other things to work. */\n/* #undef _POSIX_SOURCE */\n\n/* Define to empty if 'const' does not conform to ANSI C. */\n/* #undef const */\n\n#ifdef __MINGW32__\n# undef __USE_MINGW_ANSI_STDIO\n# define __USE_MINGW_ANSI_STDIO 1\n#endif\n\n/* Number of bits in a timestamp, on hosts where this is settable. */\n/* #undef _TIME_BITS */\n\n/* For 64-bit time_t on 32-bit mingw. */\n#ifdef __MINGW32__\n# define __MINGW_USE_VC2005_COMPAT 1\n#endif\n\n#include <sys/types.h>\n\n/* Define to 'int' if <sys/types.h> doesn't define. */\n#define gid_t int\n\n/* Define to 'int' if <sys/types.h> does not define. */\n/* GCC 4.x reportedly defines pid_t.  */\n#ifndef _PID_T_\n#ifdef _WIN64\n#define pid_t __int64\n#else\n#define pid_t int\n#endif\n#endif\n\n/* Define to `int' if <sys/types.h> does not define. */\n#define ssize_t int\n\n/* Define to 'int' if <sys/types.h> doesn't define. */\n#define uid_t int\n\n/* Define {u,}intmax_t if not defined in <stdint.h> or <inttypes.h>. */\n#if !HAVE_STDINT_H && !HAVE_INTTYPES_H\n#define intmax_t long long\n#define uintmax_t unsigned long long\n#endif\n\n/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */\n/* #undef HAVE_SYS_WAIT_H */\n\n/* Define to the installation directory for locales.  */\n#define LOCALEDIR \"\"\n\n/*\n * Refer to README.W32 for info on the following settings\n */\n\n\n/*\n * If you have a shell that does not grok 'sh -c quoted-command-line'\n * correctly, you need this setting; it is the default for tcc.\n * Please see below for specific shell support.\n */\n#if defined(__TINYC__)\n#define BATCH_MODE_ONLY_SHELL 1\n#else\n/*#define BATCH_MODE_ONLY_SHELL 1 */\n#endif\n\n/*\n * Define if you have the Cygnus \"Cygwin\" GNU Windows32 tool set.\n * Do NOT define BATCH_MODE_ONLY_SHELL if you define HAVE_CYGWIN_SHELL\n */\n/*#define HAVE_CYGWIN_SHELL 1 */\n\n/*\n * Define if you have the MKS tool set or shell. Do NOT define\n * BATCH_MODE_ONLY_SHELL if you define HAVE_MKS_SHELL\n */\n/*#define HAVE_MKS_SHELL 1 */\n\n/*\n * Enforce the mutual exclusivity restriction.\n */\n#ifdef HAVE_MKS_SHELL\n#undef BATCH_MODE_ONLY_SHELL\n#endif\n\n#ifdef HAVE_CYGWIN_SHELL\n#undef BATCH_MODE_ONLY_SHELL\n#endif\n\n/* Include customized declarations.  */\n#include \"../src/mkcustom.h\"\n"
  },
  {
    "path": "src/configh.dos",
    "content": "/* configh.dos -- hand-massaged config.h file for MS-DOS builds         -*-C-*-\n\nCopyright (C) 1994-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"mkconfig.h\"\n\n#define MK_OS_DOS 1\n\n/* Include this header to make __DJGPP_MINOR__ available because DJGPP ports\n   of GCC 4.3.0 and later no longer do it automatically.  */\n#include <sys/version.h>\n\n/* Many things are defined already by a system header.  */\n#include <sys/config.h>\n\n#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1\n\n/* Define to 1 if 'sys_siglist' is declared by <signal.h> or <unistd.h>. */\n# define SYS_SIGLIST_DECLARED 1\n\n/* Define to 1 if the C library defines the variable '_sys_siglist'.  */\n# define HAVE_DECL_SYS_SIGLIST 1\n\n#else\n\n/* Define NSIG.  */\n# define NSIG SIGMAX\n\n#endif\n\n/* Use high resolution file timestamps if nonzero. */\n#define FILE_TIMESTAMP_HI_RES 0\n\n/* Define to 1 if you have 'alloca', as a function or macro. */\n#define HAVE_ALLOCA 1\n\n/* Define to 1 if you have the fdopen function.  */\n#define HAVE_FDOPEN 1\n\n/* Define to 1 if you have the 'getgroups' function. */\n#define HAVE_GETGROUPS 1\n\n/* Define to 1 if the system has the type 'long long int'. */\n#define HAVE_LONG_LONG_INT 1\n\n/* Define to 1 if you have the <memory.h> header file.  */\n#define HAVE_MEMORY_H 1\n\n/* Define to 1 if you have the mkstemp function.  */\n#define HAVE_MKSTEMP 1\n\n/* Define to 1 if you have the 'mktemp' function. */\n#define HAVE_MKTEMP 1\n\n/* Define to 1 if you have the 'setlinebuf' function. */\n#define HAVE_SETLINEBUF 1\n\n/* Define to 1 if you have the 'setvbuf' function. */\n#define HAVE_SETVBUF 1\n\n#define SCCS_GET \"get\"\n\n/* Define to 1 if you have the select function.  */\n#define HAVE_SELECT 1\n\n/* Define to 1 if you have the stricmp function.  */\n#define HAVE_STRICMP 1\n\n/* Define to 1 if you have the 'strncasecmp' function. */\n#define HAVE_STRNCASECMP 1\n\n/* Define to 1 if you have the `strtoll' function. */\n#define HAVE_STRTOLL 1\n\n/* Output sync support */\n#define NO_OUTPUT_SYNC 1\n\n/* Build host information. */\n#define MAKE_HOST \"i386-pc-msdosdjgpp\"\n\n/* Grok DOS paths (drive specs and backslash path element separators) */\n#define HAVE_DOS_PATHS 1\n\n/* Define the type of the first arg to select().  */\n#define fd_set_size_t int\n\n/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do\n   not define. */\n#define intmax_t long long\n\n/* Define to `int' if <sys/types.h> does not define. */\n#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 5\n#define ssize_t int\n#endif\n\n/* Define to 'unsigned long' or 'unsigned long long'\n   if <inttypes.h> doesn't define.  */\n#define uintmax_t unsigned long long\n\n/* Include customized declarations.  */\n#include \"../src/mkcustom.h\"\n"
  },
  {
    "path": "src/debug.h",
    "content": "/* Debugging macros and interface.\nCopyright (C) 1999-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#define DB_NONE         (0x000)\n#define DB_BASIC        (0x001)\n#define DB_VERBOSE      (0x002)\n#define DB_JOBS         (0x004)\n#define DB_IMPLICIT     (0x008)\n#define DB_PRINT        (0x010)\n#define DB_WHY          (0x020)\n#define DB_MAKEFILES    (0x100)\n\n#define DB_ALL          (0xfff)\n\nextern int db_level;\n\n#define ISDB(_l)    ((_l)&db_level)\n\n/* When adding macros to this list be sure to update the value of\n   XGETTEXT_OPTIONS in the po/Makevars file.  */\n#define DBS(_l,_x)  do{ if(ISDB(_l)) {print_spaces (depth); \\\n                                      printf _x; fflush (stdout);} }while(0)\n\n#define DBF(_l,_x)  do{ if(ISDB(_l)) {print_spaces (depth); \\\n                                      printf (_x, file->name); \\\n                                      fflush (stdout);} }while(0)\n\n#define DB(_l,_x)   do{ if(ISDB(_l)) {printf _x; fflush (stdout);} }while(0)\n"
  },
  {
    "path": "src/default.c",
    "content": "/* Data base of default implicit rules for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#include \"filedef.h\"\n#include \"variable.h\"\n#include \"rule.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"commands.h\"\n\n/* Define GCC_IS_NATIVE if gcc is the native development environment on\n   your system (gcc/bison/flex vs cc/yacc/lex).  */\n#if MK_OS_DOS || MK_OS_OS2\n# define GCC_IS_NATIVE\n#endif\n\n\n/* This is the default list of suffixes for suffix rules.\n   '.s' must come last, so that a '.o' file will be made from\n   a '.c' or '.p' or ... file rather than from a .s file.  */\n\nstatic char default_suffixes[]\n#if MK_OS_VMS\n  /* VMS should include all UNIX/POSIX + some VMS extensions */\n  = \".out .exe .a .olb .hlb .tlb .mlb .ln .o .obj .c .cxx .cc .cpp .pas .p \\\n.for .f .r .y .l .ym .yl .mar .s .ss .i .ii .mod .sym .def .h .info .dvi \\\n.tex .texinfo .texi .txinfo .mem .hlp .brn .rnh .rno .rnt .rnx .w .ch .cweb \\\n.web .com .sh .elc .el\";\n#elif MK_OS_OS2\n  = \".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \\\n.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \\\n.w .ch .web .sh .elc .el .obj .exe .dll .lib\";\n#else\n  = \".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \\\n.mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \\\n.w .ch .web .sh .elc .el\";\n#endif\n\nstatic struct pspec default_pattern_rules[] =\n  {\n#if MK_OS_VMS\n    { \"(%)\", \"%\",\n        \"@if f$$search(\\\"$@\\\") .eqs. \\\"\\\" then $(LIBRARY)/CREATE/\"\n         \"$(or \"\n          \"$(patsubst %,TEXT,$(filter %.tlb %.TLB,$@)),\"\n          \"$(patsubst %,HELP,$(filter %.hlb %.HLB,$@)),\"\n          \"$(patsubst %,MACRO,$(filter %.mlb %.MLB,$@)),\"\n          \"$(and \"\n           \"$(patsubst %,SHARE,$(filter %.olb %.OLB,$@)),\"\n           \"$(patsubst %,SHARE,$(filter %.exe %.EXE,$<))),\"\n          \"OBJECT)\"\n         \" $@\\n\"\n        \"$(AR) $(ARFLAGS) $@ $<\" },\n\n#else\n    { \"(%)\", \"%\",\n        \"$(AR) $(ARFLAGS) $@ $<\" },\n#endif\n    /* The X.out rules are only in BSD's default set because\n       BSD Make has no null-suffix rules, so 'foo.out' and\n       'foo' are the same thing.  */\n#if MK_OS_VMS\n    { \"%.exe\", \"%\",\n        \"$(CP) $< $@\" },\n\n#endif\n    { \"%.out\", \"%\",\n        \"@rm -f $@ \\n cp $< $@\" },\n\n    /* Syntax is \"ctangle foo.w foo.ch foo.c\".  */\n    { \"%.c\", \"%.w %.ch\",\n        \"$(CTANGLE) $^ $@\" },\n    { \"%.tex\", \"%.w %.ch\",\n        \"$(CWEAVE) $^ $@\" },\n\n    { 0, 0, 0 }\n  };\n\nstatic struct pspec default_terminal_rules[] =\n  {\n#if MK_OS_VMS\n\n    /* RCS.  */\n    { \"%\", \"%$$5lv\", /* Multinet style */\n        \"if f$$search(\\\"$@\\\") .nes. \\\"\\\" then +$(CHECKOUT,v)\" },\n    { \"%\", \"[.$$rcs]%$$5lv\", /* Multinet style */\n        \"if f$$search(\\\"$@\\\") .nes. \\\"\\\" then +$(CHECKOUT,v)\" },\n    { \"%\", \"%_v\", /* Normal style */\n        \"if f$$search(\\\"$@\\\") .nes. \\\"\\\" then +$(CHECKOUT,v)\" },\n    { \"%\", \"[.rcs]%_v\", /* Normal style */\n        \"if f$$search(\\\"$@\\\") .nes. \\\"\\\" then +$(CHECKOUT,v)\" },\n\n    /* SCCS.  */\n        /* ain't no SCCS on vms */\n\n#else\n    /* RCS.  */\n    { \"%\", \"%,v\",\n        \"$(CHECKOUT,v)\" },\n    { \"%\", \"RCS/%,v\",\n        \"$(CHECKOUT,v)\" },\n    { \"%\", \"RCS/%\",\n        \"$(CHECKOUT,v)\" },\n\n    /* SCCS.  */\n    { \"%\", \"s.%\",\n        \"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<\" },\n    { \"%\", \"SCCS/s.%\",\n        \"$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<\" },\n#endif /* !MK_OS_VMS */\n    { 0, 0, 0 }\n  };\n\nstatic const char *default_suffix_rules[] =\n  {\n#if MK_OS_VMS\n    \".o\",\n    \"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".obj\",\n    \"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".s\",\n    \"$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".S\",\n    \"$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".c\",\n    \"$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".cc\",\n    \"$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".C\",\n    \"$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".cpp\",\n    \"$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".f\",\n    \"$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".m\",\n    \"$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".p\",\n    \"$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".F\",\n    \"$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".r\",\n    \"$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".mod\",\n    \"$(COMPILE.mod) -o $@ -e $@ $^\",\n\n    \".def.sym\",\n    \"$(COMPILE.def) -o $@ $<\",\n\n    \".sh\",\n    \"copy $< >$@\",\n\n    \".obj.exe\",\n    \"$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@\",\n    \".mar.exe\",\n    \"$(COMPILE.mar) $^ \\n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@\",\n    \".s.o\",\n    \"$(COMPILE.s) -o $@ $<\",\n    \".s.exe\",\n    \"$(COMPILE.s) $^ \\n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@\",\n    \".c.exe\",\n    \"$(COMPILE.c) $^ \\n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@\",\n    \".cc.exe\",\n#ifdef GCC_IS_NATIVE\n    \"$(COMPILE.cc) $^ \\n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@\",\n#else\n    \"$(COMPILE.cc) $^ \\n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@\",\n    \".cxx.exe\",\n    \"$(COMPILE.cxx) $^ \\n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@\",\n#endif\n    \".for.exe\",\n    \"$(COMPILE.for) $^ \\n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@\",\n    \".pas.exe\",\n    \"$(COMPILE.pas) $^ \\n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@\",\n\n    \".com\",\n    \"copy $< >$@\",\n\n    \".mar.obj\",\n    \"$(COMPILE.mar) /obj=$@ $<\",\n    \".s.obj\",\n    \"$(COMPILE.s) /obj=$@ $<\",\n    \".ss.obj\",\n    \"$(COMPILE.s) /obj=$@ $<\",\n    \".c.i\",\n    \"$(COMPILE.c)/prep /list=$@ $<\",\n    \".c.s\",\n    \"$(COMPILE.c)/noobj/machine /list=$@ $<\",\n    \".i.s\",\n    \"$(COMPILE.c)/noprep/noobj/machine /list=$@ $<\",\n    \".c.obj\",\n    \"$(COMPILE.c) /obj=$@ $<\",\n    \".c.o\",\n    \"$(COMPILE.c) /obj=$@ $<\",\n    \".cc.ii\",\n    \"$(COMPILE.cc)/prep /list=$@ $<\",\n    \".cc.ss\",\n    \"$(COMPILE.cc)/noobj/machine /list=$@ $<\",\n    \".ii.ss\",\n    \"$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<\",\n    \".cc.obj\",\n    \"$(COMPILE.cc) /obj=$@ $<\",\n    \".cc.o\",\n    \"$(COMPILE.cc) /obj=$@ $<\",\n    \".cxx.obj\",\n    \"$(COMPILE.cxx) /obj=$@ $<\",\n    \".cxx.o\",\n    \"$(COMPILE.cxx) /obj=$@ $<\",\n    \".for.obj\",\n    \"$(COMPILE.for) /obj=$@ $<\",\n    \".for.o\",\n    \"$(COMPILE.for) /obj=$@ $<\",\n    \".pas.obj\",\n    \"$(COMPILE.pas) /obj=$@ $<\",\n    \".pas.o\",\n    \"$(COMPILE.pas) /obj=$@ $<\",\n\n    \".y.c\",\n    \"$(YACC.y) $< \\n rename y_tab.c $@\",\n    \".l.c\",\n    \"$(LEX.l) $< \\n rename lexyy.c $@\",\n\n    \".texinfo.info\",\n    \"$(MAKEINFO) $<\",\n\n    \".tex.dvi\",\n    \"$(TEX) $<\",\n\n    \".cpp.o\",\n    \"$(COMPILE.cpp) $(OUTPUT_OPTION) $<\",\n    \".f.o\",\n    \"$(COMPILE.f) $(OUTPUT_OPTION) $<\",\n    \".m.o\",\n    \"$(COMPILE.m) $(OUTPUT_OPTION) $<\",\n    \".p.o\",\n    \"$(COMPILE.p) $(OUTPUT_OPTION) $<\",\n    \".r.o\",\n    \"$(COMPILE.r) $(OUTPUT_OPTION) $<\",\n    \".mod.o\",\n    \"$(COMPILE.mod) -o $@ $<\",\n\n    \".c.ln\",\n    \"$(LINT.c) -C$* $<\",\n    \".y.ln\",\n    \"$(YACC.y) $< \\n rename y_tab.c $@\",\n\n    \".l.ln\",\n    \"@$(RM) $*.c\\n $(LEX.l) $< > $*.c\\n$(LINT.c) -i $*.c -o $@\\n $(RM) $*.c\",\n\n#else /* ! MK_OS_VMS */\n\n    \".o\",\n    \"$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".s\",\n    \"$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".S\",\n    \"$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".c\",\n    \"$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".cc\",\n    \"$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".C\",\n    \"$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".cpp\",\n    \"$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".f\",\n    \"$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".m\",\n    \"$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".p\",\n    \"$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".F\",\n    \"$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".r\",\n    \"$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@\",\n    \".mod\",\n    \"$(COMPILE.mod) -o $@ -e $@ $^\",\n\n    \".def.sym\",\n    \"$(COMPILE.def) -o $@ $<\",\n\n    \".sh\",\n    \"cat $< >$@ \\n chmod a+x $@\",\n\n    \".s.o\",\n    \"$(COMPILE.s) -o $@ $<\",\n    \".S.o\",\n    \"$(COMPILE.S) -o $@ $<\",\n    \".c.o\",\n    \"$(COMPILE.c) $(OUTPUT_OPTION) $<\",\n    \".cc.o\",\n    \"$(COMPILE.cc) $(OUTPUT_OPTION) $<\",\n    \".C.o\",\n    \"$(COMPILE.C) $(OUTPUT_OPTION) $<\",\n    \".cpp.o\",\n    \"$(COMPILE.cpp) $(OUTPUT_OPTION) $<\",\n    \".f.o\",\n    \"$(COMPILE.f) $(OUTPUT_OPTION) $<\",\n    \".m.o\",\n    \"$(COMPILE.m) $(OUTPUT_OPTION) $<\",\n    \".p.o\",\n    \"$(COMPILE.p) $(OUTPUT_OPTION) $<\",\n    \".F.o\",\n    \"$(COMPILE.F) $(OUTPUT_OPTION) $<\",\n    \".r.o\",\n    \"$(COMPILE.r) $(OUTPUT_OPTION) $<\",\n    \".mod.o\",\n    \"$(COMPILE.mod) -o $@ $<\",\n\n    \".c.ln\",\n    \"$(LINT.c) -C$* $<\",\n    \".y.ln\",\n#if MK_OS_DOS\n    \"$(YACC.y) $< \\n $(LINT.c) -C$* y_tab.c \\n $(RM) y_tab.c\",\n#else\n    \"$(YACC.y) $< \\n $(LINT.c) -C$* y.tab.c \\n $(RM) y.tab.c\",\n#endif\n    \".l.ln\",\n    \"@$(RM) $*.c\\n $(LEX.l) $< > $*.c\\n$(LINT.c) -i $*.c -o $@\\n $(RM) $*.c\",\n\n    \".y.c\",\n#if MK_OS_DOS\n    \"$(YACC.y) $< \\n mv -f y_tab.c $@\",\n#else\n    \"$(YACC.y) $< \\n mv -f y.tab.c $@\",\n#endif\n    \".l.c\",\n    \"@$(RM) $@ \\n $(LEX.l) $< > $@\",\n    \".ym.m\",\n    \"$(YACC.m) $< \\n mv -f y.tab.c $@\",\n    \".lm.m\",\n    \"@$(RM) $@ \\n $(LEX.m) $< > $@\",\n\n    \".F.f\",\n    \"$(PREPROCESS.F) $(OUTPUT_OPTION) $<\",\n    \".r.f\",\n    \"$(PREPROCESS.r) $(OUTPUT_OPTION) $<\",\n\n    /* This might actually make lex.yy.c if there's no %R% directive in $*.l,\n       but in that case why were you trying to make $*.r anyway?  */\n    \".l.r\",\n    \"$(LEX.l) $< > $@ \\n mv -f lex.yy.r $@\",\n\n    \".S.s\",\n    \"$(PREPROCESS.S) $< > $@\",\n\n    \".texinfo.info\",\n    \"$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@\",\n\n    \".texi.info\",\n    \"$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@\",\n\n    \".txinfo.info\",\n    \"$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@\",\n\n    \".tex.dvi\",\n    \"$(TEX) $<\",\n\n    \".texinfo.dvi\",\n    \"$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<\",\n\n    \".texi.dvi\",\n    \"$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<\",\n\n    \".txinfo.dvi\",\n    \"$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<\",\n\n    \".w.c\",\n    \"$(CTANGLE) $< - $@\",       /* The '-' says there is no '.ch' file.  */\n\n    \".web.p\",\n    \"$(TANGLE) $<\",\n\n    \".w.tex\",\n    \"$(CWEAVE) $< - $@\",        /* The '-' says there is no '.ch' file.  */\n\n    \".web.tex\",\n    \"$(WEAVE) $<\",\n\n#endif /* !MK_OS_VMS */\n\n    0, 0,\n  };\n\nstatic const char *default_variables[] =\n  {\n#if MK_OS_VMS\n#ifdef __ALPHA\n    \"ARCH\", \"ALPHA\",\n#endif\n#ifdef __ia64\n    \"ARCH\", \"IA64\",\n#endif\n#ifdef __VAX\n    \"ARCH\", \"VAX\",\n#endif\n    \"AR\", \"library\",\n    \"LIBRARY\", \"library\",\n    \"ARFLAGS\", \"/replace\",\n    \"AS\", \"macro\",\n    \"MACRO\", \"macro\",\n#ifdef GCC_IS_NATIVE\n    \"CC\", \"gcc\",\n#else\n    \"CC\", \"cc\",\n#endif\n    \"CD\", \"builtin_cd\",\n    \"ECHO\", \"builtin_echo\",\n#ifdef GCC_IS_NATIVE\n    \"C++\", \"gcc/plus\",\n    \"CXX\", \"gcc/plus\",\n#else\n    \"C++\", \"cxx\",\n    \"CXX\", \"cxx\",\n#ifndef __ia64\n    \"CXXLD\", \"cxxlink\",\n    \"CXXLINK\", \"cxxlink\",\n#else\n    /* CXXLINK is not used on VMS/IA64 */\n    \"CXXLD\", \"link\",\n    \"CXXLINK\", \"link\",\n#endif\n#endif\n    \"CO\", \"co\",\n    \"CPP\", \"$(CC) /preprocess_only\",\n    \"FC\", \"fortran\",\n    /* System V uses these, so explicit rules using them should work.\n       However, there is no way to make implicit rules use them and FC.  */\n    \"F77\", \"$(FC)\",\n    \"F77FLAGS\", \"$(FFLAGS)\",\n    \"LD\", \"link\",\n    \"LEX\", \"lex\",\n    \"PC\", \"pascal\",\n    \"YACC\", \"bison/yacc\",\n    \"YFLAGS\", \"/Define/Verbose\",\n    \"BISON\", \"bison\",\n    \"MAKEINFO\", \"makeinfo\",\n    \"TEX\", \"tex\",\n    \"TEXINDEX\", \"texindex\",\n\n    \"RM\", \"delete/nolog\",\n\n    \"CSTARTUP\", \"\",\n#ifdef GCC_IS_NATIVE\n    \"CRT0\", \",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj\",\n    \"CXXSTARTUP\", \"gnu_cc_library:crtbegin.obj\",\n    \"CXXRT0\", \",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj\",\n    \"LXLIBS\", \",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib\",\n    \"LDLIBS\", \",gnu_cc_library:libgcc.olb/lib\",\n#else\n    \"CRT0\", \"\",\n    \"CXXSTARTUP\", \"\",\n    \"CXXRT0\", \"\",\n    \"LXLIBS\", \"\",\n    \"LDLIBS\", \"\",\n#endif\n\n    \"LINK.o\", \"$(LD) $(LDFLAGS)\",\n    \"LINK.obj\", \"$(LD) $(LDFLAGS)\",\n#ifndef GCC_IS_NATIVE\n    \"CXXLINK.obj\", \"$(CXXLD) $(LDFLAGS)\",\n    \"COMPILE.cxx\", \"$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n#endif\n    \"COMPILE.c\", \"$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n    \"LINK.c\", \"$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.m\", \"$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.m\", \"$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.cc\", \"$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.C\", \"$(COMPILE.cc)\",\n    \"COMPILE.cpp\", \"$(COMPILE.cc)\",\n    \"LINK.C\", \"$(LINK.cc)\",\n    \"LINK.cpp\", \"$(LINK.cc)\",\n    \"YACC.y\", \"$(YACC) $(YFLAGS)\",\n    \"LEX.l\", \"$(LEX) $(LFLAGS)\",\n    \"YACC.m\", \"$(YACC) $(YFLAGS)\",\n    \"LEX.m\", \"$(LEX) $(LFLAGS) -t\",\n    \"COMPILE.for\", \"$(FC) $(FFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.f\", \"$(FC) $(FFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.f\", \"$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.pas\", \"$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.def\", \"$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.mod\", \"$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.p\", \"$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.p\", \"$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.mar\", \"$(MACRO) $(MACROFLAGS)\",\n    \"COMPILE.s\", \"$(AS) $(ASFLAGS) $(TARGET_MACH)\",\n    \"LINK.S\", \"$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)\",\n    \"COMPILE.S\", \"$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c\",\n    \"PREPROCESS.S\", \"$(CPP) $(CPPFLAGS)\",\n    \"PREPROCESS.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F\",\n    \"PREPROCESS.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F\",\n    \"LINT.c\", \"$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n\n    \"MV\", \"rename/new_version\",\n    \"CP\", \"copy\",\n    \".LIBPATTERNS\", \"%.olb lib%.a\",\n\n#else /* !MK_OS_VMS */\n\n    \"AR\", \"ar\",\n#ifdef _AIX\n    /* AIX requires object file format specification: choose -Xany.  */\n    \"ARFLAGS\", \"-Xany -rv\",\n#else\n    \"ARFLAGS\", \"-rv\",\n#endif\n    \"AS\", \"as\",\n#ifdef GCC_IS_NATIVE\n    \"CC\", \"gcc\",\n    \"OBJC\", \"gcc\",\n#else\n    \"CC\", \"cc\",\n    \"OBJC\", \"cc\",\n#endif\n#ifdef MAKE_CXX\n    \"CXX\", MAKE_CXX,\n#else\n# ifdef GCC_IS_NATIVE\n#  ifdef MK_OS_DOS\n    \"CXX\", \"gpp\",       /* g++ is an invalid name on MSDOS */\n#  else\n    \"CXX\", \"gcc\",\n#  endif /* __MSDOS__ */\n# else\n    \"CXX\", \"g++\",\n# endif\n#endif\n    /* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist,\n       and to the empty string if $@ does exist.  */\n    \"CHECKOUT,v\", \"+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)\",\n    \"CO\", \"co\",\n    \"COFLAGS\", \"\",\n\n    \"CPP\", \"$(CC) -E\",\n#ifdef CRAY\n    \"CF77PPFLAGS\", \"-P\",\n    \"CF77PP\", \"/lib/cpp\",\n    \"CFT\", \"cft77\",\n    \"CF\", \"cf77\",\n    \"FC\", \"$(CF)\",\n#else /* Not CRAY.  */\n#ifdef _IBMR2\n    \"FC\", \"xlf\",\n#else\n#ifdef __convex__\n    \"FC\", \"fc\",\n#else\n    \"FC\", \"f77\",\n#endif /* __convex__ */\n#endif /* _IBMR2 */\n    /* System V uses these, so explicit rules using them should work.\n       However, there is no way to make implicit rules use them and FC.  */\n    \"F77\", \"$(FC)\",\n    \"F77FLAGS\", \"$(FFLAGS)\",\n#endif  /* Cray.  */\n    \"GET\", SCCS_GET,\n    \"LD\", \"ld\",\n#ifdef GCC_IS_NATIVE\n    \"LEX\", \"flex\",\n#else\n    \"LEX\", \"lex\",\n#endif\n    \"LINT\", \"lint\",\n    \"M2C\", \"m2c\",\n#ifdef pyr\n    \"PC\", \"pascal\",\n#else\n#ifdef CRAY\n    \"PC\", \"PASCAL\",\n    \"SEGLDR\", \"segldr\",\n#else\n    \"PC\", \"pc\",\n#endif  /* CRAY.  */\n#endif  /* pyr.  */\n#ifdef GCC_IS_NATIVE\n    \"YACC\", \"bison -y\",\n#else\n    \"YACC\", \"yacc\",     /* Or \"bison -y\"  */\n#endif\n    \"MAKEINFO\", \"makeinfo\",\n    \"TEX\", \"tex\",\n    \"TEXI2DVI\", \"texi2dvi\",\n    \"WEAVE\", \"weave\",\n    \"CWEAVE\", \"cweave\",\n    \"TANGLE\", \"tangle\",\n    \"CTANGLE\", \"ctangle\",\n\n    \"RM\", \"rm -f\",\n\n    \"LINK.o\", \"$(CC) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.c\", \"$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.c\", \"$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.m\", \"$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.m\", \"$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.cc\", \"$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n#ifndef HAVE_CASE_INSENSITIVE_FS\n    /* On case-insensitive filesystems, treat *.C files as *.c files,\n       to avoid erroneously compiling C sources as C++, which will\n       probably fail.  */\n    \"COMPILE.C\", \"$(COMPILE.cc)\",\n#else\n    \"COMPILE.C\", \"$(COMPILE.c)\",\n#endif\n    \"COMPILE.cpp\", \"$(COMPILE.cc)\",\n    \"LINK.cc\", \"$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n#ifndef HAVE_CASE_INSENSITIVE_FS\n    \"LINK.C\", \"$(LINK.cc)\",\n#else\n    \"LINK.C\", \"$(LINK.c)\",\n#endif\n    \"LINK.cpp\", \"$(LINK.cc)\",\n    \"YACC.y\", \"$(YACC) $(YFLAGS)\",\n    \"LEX.l\", \"$(LEX) $(LFLAGS) -t\",\n    \"YACC.m\", \"$(YACC) $(YFLAGS)\",\n    \"LEX.m\", \"$(LEX) $(LFLAGS) -t\",\n    \"COMPILE.f\", \"$(FC) $(FFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.f\", \"$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.def\", \"$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.mod\", \"$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)\",\n    \"COMPILE.p\", \"$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c\",\n    \"LINK.p\", \"$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)\",\n    \"LINK.s\", \"$(CC) $(ASFLAGS) $(LDFLAGS) $(TARGET_MACH)\",\n    \"COMPILE.s\", \"$(AS) $(ASFLAGS) $(TARGET_MACH)\",\n    \"LINK.S\", \"$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)\",\n    \"COMPILE.S\", \"$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c\",\n    \"PREPROCESS.S\", \"$(CPP) $(CPPFLAGS)\",\n    \"PREPROCESS.F\", \"$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F\",\n    \"PREPROCESS.r\", \"$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F\",\n    \"LINT.c\", \"$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)\",\n\n#ifndef NO_MINUS_C_MINUS_O\n    \"OUTPUT_OPTION\", \"-o $@\",\n#endif\n\n#ifdef SCCS_GET_MINUS_G\n    \"SCCS_OUTPUT_OPTION\", \"-G$@\",\n#endif\n\n#if MK_OS_DOS\n    \".LIBPATTERNS\", \"lib%.a $(DJDIR)/lib/lib%.a\",\n#elif defined(__APPLE__)\n    \".LIBPATTERNS\", \"lib%.dylib lib%.a\",\n#elif defined(__CYGWIN__) || MK_OS_W32\n    \".LIBPATTERNS\", \"lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll\",\n#else\n    \".LIBPATTERNS\", \"lib%.so lib%.a\",\n#endif\n\n#endif /* !MK_OS_VMS */\n    /* Make this assignment to avoid undefined variable warnings.  */\n    GNUMAKEFLAGS_NAME, \"\",\n    0, 0\n  };\n\f\n/* Set up the default .SUFFIXES list.  */\n\nvoid\nset_default_suffixes (void)\n{\n  suffix_file = enter_file (strcache_add (\".SUFFIXES\"));\n  suffix_file->builtin = 1;\n\n  if (no_builtin_rules_flag)\n    define_variable_cname (\"SUFFIXES\", \"\", o_default, 0);\n  else\n    {\n      struct dep *d;\n      const char *p = default_suffixes;\n      suffix_file->deps = enter_prereqs (PARSE_SIMPLE_SEQ ((char **)&p, struct dep),\n                                         NULL);\n      for (d = suffix_file->deps; d; d = d->next)\n        d->file->builtin = 1;\n\n      define_variable_cname (\"SUFFIXES\", default_suffixes, o_default, 0);\n    }\n}\n\n/* Enter the default suffix rules as file rules.  This used to be done in\n   install_default_implicit_rules, but that loses because we want the\n   suffix rules installed before reading makefiles, and the pattern rules\n   installed after.  */\n\nvoid\ninstall_default_suffix_rules ()\n{\n  const char **s;\n\n  if (no_builtin_rules_flag)\n    return;\n\n  for (s = default_suffix_rules; *s != 0; s += 2)\n    {\n      struct file *f = enter_file (strcache_add (s[0]));\n      /* Install the default rule only if there is no user defined rule.  */\n      if (!f->cmds)\n        {\n          f->cmds = xmalloc (sizeof (struct commands));\n          f->cmds->fileinfo.filenm = NULL;\n          f->cmds->commands = xstrdup (s[1]);\n          f->cmds->command_lines = NULL;\n          f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;\n          f->builtin = 1;\n        }\n    }\n}\n\n\n/* Install the default pattern rules.  */\n\nvoid\ninstall_default_implicit_rules (void)\n{\n  struct pspec *p;\n\n  if (no_builtin_rules_flag)\n    return;\n\n  for (p = default_pattern_rules; p->target != 0; ++p)\n    install_pattern_rule (p, 0);\n\n  for (p = default_terminal_rules; p->target != 0; ++p)\n    install_pattern_rule (p, 1);\n}\n\nvoid\ndefine_default_variables (void)\n{\n  const char **s;\n\n  if (no_builtin_variables_flag)\n    return;\n\n  for (s = default_variables; *s != 0; s += 2)\n    define_variable (s[0], strlen (s[0]), s[1], o_default, 1);\n}\n\nvoid\nundefine_default_variables (void)\n{\n  const char **s;\n\n  for (s = default_variables; *s != 0; s += 2)\n    undefine_variable_global (NILF, s[0], strlen (s[0]), o_default);\n}\n"
  },
  {
    "path": "src/dep.h",
    "content": "/* Definitions of dependency data structures for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Structure used in chains of names, for parsing and globbing.  */\n\n#define NAMESEQ(_t)     \\\n    _t *next;           \\\n    const char *name\n\nstruct nameseq\n  {\n    NAMESEQ (struct nameseq);\n  };\n\n/* Flag bits for the second argument to 'read_makefile'.\n   These flags are saved in the 'flags' field of each\n   'struct goaldep' in the chain returned by 'read_all_makefiles'.  */\n\n#define RM_NOFLAG               0\n#define RM_NO_DEFAULT_GOAL      (1 << 0) /* Do not set default goal.  */\n#define RM_INCLUDED             (1 << 1) /* Search makefile search path.  */\n#define RM_DONTCARE             (1 << 2) /* No error if it doesn't exist.  */\n#define RM_NO_TILDE             (1 << 3) /* Don't expand ~ in file name.  */\n\n/* Structure representing one dependency of a file.\n   Each struct file's 'deps' points to a chain of these, through 'next'.\n   'stem' is the stem for this dep line of static pattern rule or NULL.\n   explicit is set when implicit rule search is performed and the prerequisite\n   does not contain %. When explicit is set the file is not intermediate.  */\n\n#define DEP(_t)                                 \\\n    NAMESEQ (_t);                               \\\n    struct file *file;                          \\\n    _t *shuf;                                   \\\n    const char *stem;                           \\\n    unsigned int flags : 8;                     \\\n    unsigned int changed : 1;                   \\\n    unsigned int ignore_mtime : 1;              \\\n    unsigned int staticpattern : 1;             \\\n    unsigned int need_2nd_expansion : 1;        \\\n    unsigned int ignore_automatic_vars : 1;     \\\n    unsigned int is_explicit : 1;               \\\n    unsigned int wait_here : 1\n\nstruct dep\n  {\n    DEP (struct dep);\n  };\n\n/* Structure representing one goal.\n   The goals to be built constitute a chain of these, chained through 'next'.\n   'stem' is not used, but it's simpler to include and ignore it.  */\n\nstruct goaldep\n  {\n    DEP (struct goaldep);\n    int error;\n    floc floc;\n  };\n\n/* Options for parsing lists of filenames.  */\n\n#define PARSEFS_NONE    0x0000\n#define PARSEFS_NOSTRIP 0x0001\n#define PARSEFS_NOAR    0x0002\n#define PARSEFS_NOGLOB  0x0004\n#define PARSEFS_EXISTS  0x0008\n#define PARSEFS_NOCACHE 0x0010\n#define PARSEFS_ONEWORD 0x0020\n#define PARSEFS_WAIT    0x0040\n\n#define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \\\n            (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f))\n#define PARSE_SIMPLE_SEQ(_s,_t) \\\n            (_t *)parse_file_seq ((_s),sizeof (_t),MAP_NUL,NULL,PARSEFS_NONE)\n\n#if MK_OS_VMS\nvoid *parse_file_seq ();\n#else\nvoid *parse_file_seq (char **stringp, size_t size,\n                      int stopmap, const char *prefix, int flags);\n#endif\n\nchar *tilde_expand (const char *name);\n\n#ifndef NO_ARCHIVES\nstruct nameseq *ar_glob (const char *arname, const char *member_pattern, size_t size);\n#endif\n\n#define dep_name(d)       ((d)->name ? (d)->name : (d)->file->name)\n\n#define alloc_seq_elt(_t) xcalloc (sizeof (_t))\nvoid free_ns_chain (struct nameseq *n);\n\n#if defined(MAKE_MAINTAINER_MODE) && defined(__GNUC__) && !defined(__STRICT_ANSI__)\n/* Use inline to get real type-checking.  */\n#define SI static inline\nSI struct nameseq *alloc_ns (void)    { return alloc_seq_elt (struct nameseq); }\nSI struct dep *alloc_dep (void)       { return alloc_seq_elt (struct dep); }\nSI struct goaldep *alloc_goaldep (void) { return alloc_seq_elt (struct goaldep); }\n\nSI void free_ns (struct nameseq *n)      { free (n); }\nSI void free_dep (struct dep *d)         { free_ns ((struct nameseq *)d); }\nSI void free_goaldep (struct goaldep *g) { free_dep ((struct dep *)g); }\nSI void free_dep_chain (struct dep *d)   { free_ns_chain((struct nameseq *)d); }\nSI void free_goal_chain (struct goaldep *g) { free_dep_chain((struct dep *)g); }\n#else\n# define alloc_ns()          alloc_seq_elt (struct nameseq)\n# define alloc_dep()         alloc_seq_elt (struct dep)\n# define alloc_goaldep()     alloc_seq_elt (struct goaldep)\n\n# define free_ns(_n)         free (_n)\n# define free_dep(_d)        free_ns (_d)\n# define free_goaldep(_g)    free_dep (_g)\n\n# define free_dep_chain(_d)  free_ns_chain ((struct nameseq *)(_d))\n# define free_goal_chain(_g) free_ns_chain ((struct nameseq *)(_g))\n#endif\n\nstruct dep *copy_dep (const struct dep *d);\nstruct dep *copy_dep_chain (const struct dep *d);\n\nstruct goaldep *read_all_makefiles (const char **makefiles);\nvoid eval_buffer (char *buffer, const floc *floc);\nenum update_status update_goal_chain (struct goaldep *goals);\n"
  },
  {
    "path": "src/dir.c",
    "content": "/* Directory hashing for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"hash.h\"\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"debug.h\"\n\n#ifdef HAVE_DIRENT_H\n# include <dirent.h>\n# define NAMLEN(dirent) strlen((dirent)->d_name)\n# if MK_OS_VMS\n/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */\nconst char *vmsify (const char *name, int type);\n# endif\n#else\n# define dirent direct\n# define NAMLEN(dirent) (dirent)->d_namlen\n# ifdef HAVE_SYS_NDIR_H\n#  include <sys/ndir.h>\n# endif\n# ifdef HAVE_SYS_DIR_H\n#  include <sys/dir.h>\n# endif\n# ifdef HAVE_NDIR_H\n#  include <ndir.h>\n# endif\n# ifdef HAVE_VMSDIR_H\n#  include \"vmsdir.h\"\n# endif /* HAVE_VMSDIR_H */\n#endif\n\n/* In GNU systems, <dirent.h> defines this macro for us.  */\n#ifdef _D_NAMLEN\n# undef NAMLEN\n# define NAMLEN(d) _D_NAMLEN(d)\n#endif\n\n#if (defined (POSIX) || MK_OS_VMS || MK_OS_W32) && !defined (__GNU_LIBRARY__)\n/* Posix does not require that the d_ino field be present, and some\n   systems do not provide it. */\n# define REAL_DIR_ENTRY(dp) 1\n# define FAKE_DIR_ENTRY(dp)\n#else\n# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)\n# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)\n#endif /* POSIX */\n\f\n#if MK_OS_DOS\n#include <ctype.h>\n#include <fcntl.h>\n\n/* If it's MSDOS that doesn't have _USE_LFN, disable LFN support.  */\n#ifndef _USE_LFN\n#define _USE_LFN 0\n#endif\n\nstatic const char *\ndosify (const char *filename)\n{\n  static char dos_filename[14];\n  char *df;\n  int i;\n\n  if (filename == NULL || _USE_LFN)\n    return filename;\n\n  /* FIXME: what about filenames which violate\n     8+3 constraints, like \"config.h.in\", or \".emacs\"?  */\n  if (strpbrk (filename, \"\\\"*+,;<=>?[\\\\]|\") != NULL)\n    return filename;\n\n  df = dos_filename;\n\n  /* First, transform the name part.  */\n  for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)\n    *df++ = tolower ((unsigned char)*filename++);\n\n  /* Now skip to the next dot.  */\n  while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))\n    ++filename;\n  if (*filename != '\\0')\n    {\n      *df++ = *filename++;\n      for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)\n        *df++ = tolower ((unsigned char)*filename++);\n    }\n\n  /* Look for more dots.  */\n  while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))\n    ++filename;\n  if (*filename == '.')\n    return filename;\n  *df = '\\0';\n  return dos_filename;\n}\n#endif /* MK_OS_DOS */\n\n#if MK_OS_W32\n#include \"pathstuff.h\"\n#endif\n\n#ifdef HAVE_CASE_INSENSITIVE_FS\nstatic const char *\ndowncase (const char *filename)\n{\n  static PATH_VAR (new_filename);\n  char *df;\n\n  if (filename == NULL)\n    return NULL;\n\n  df = new_filename;\n  while (*filename != '\\0')\n    {\n      *df++ = tolower ((unsigned char)*filename);\n      ++filename;\n    }\n\n  *df = '\\0';\n\n  return new_filename;\n}\n#endif /* HAVE_CASE_INSENSITIVE_FS */\n\n#if MK_OS_VMS\n\nstatic char *\ndowncase_inplace(char *filename)\n{\n  char *name;\n  name = filename;\n  while (*name != '\\0')\n    {\n      *name = tolower ((unsigned char)*name);\n      ++name;\n    }\n  return filename;\n}\n\n#ifndef _USE_STD_STAT\n/* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino\n   when _USE_STD_STAT is used on the compile line.\n\n   Prior to _USE_STD_STAT support, the st_dev is a pointer to thread\n   static memory containing the device of the last filename looked up.\n\n   Todo: find out if the ino_t still needs to be faked on a directory.\n */\n\n/* Define this if the older VMS_INO_T is needed */\n#define VMS_INO_T 1\n\nstatic int\nvms_hash (const char *name)\n{\n  int h = 0;\n\n  while (*name)\n    {\n      unsigned char uc = (unsigned char) *name;\n      int g;\n#ifdef HAVE_CASE_INSENSITIVE_FS\n      h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);\n#else\n      h = (h << 4) + uc;\n#endif\n      name++;\n      g = h & 0xf0000000;\n      if (g)\n        {\n          h = h ^ (g >> 24);\n          h = h ^ g;\n        }\n    }\n  return h;\n}\n\n/* fake stat entry for a directory */\nstatic int\nvmsstat_dir (const char *name, struct stat *st)\n{\n  char *s;\n  int h;\n  DIR *dir;\n\n  dir = opendir (name);\n  if (dir == NULL)\n    return -1;\n  closedir (dir);\n  s = strchr (name, ':');       /* find device */\n  if (s)\n    {\n      /* to keep the compiler happy we said \"const char *name\", now we cheat */\n      *s++ = '\\0';\n      st->st_dev = (char *)vms_hash (name);\n      h = vms_hash (s);\n      *(s-1) = ':';\n    }\n  else\n    {\n      st->st_dev = 0;\n      h = vms_hash (name);\n    }\n\n  st->st_ino[0] = h & 0xff;\n  st->st_ino[1] = h & 0xff00;\n  st->st_ino[2] = h >> 16;\n\n  return 0;\n}\n\n# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)\n\n#endif /* _USE_STD_STAT */\n#endif /* MK_OS_VMS */\n\f\n/* Never have more than this many directories open at once.  */\n\n#define MAX_OPEN_DIRECTORIES 10\n\nstatic unsigned int open_directories = 0;\n\n/* Hash table of directories.  */\n\n#ifndef DIRECTORY_BUCKETS\n#define DIRECTORY_BUCKETS 199\n#endif\n\nstruct directory_contents\n  {\n    dev_t dev;                  /* Device and inode numbers of this dir.  */\n#if MK_OS_W32\n    /* Inode means nothing on Windows32. Even file key information is\n     * unreliable because it is random per file open and undefined for remote\n     * filesystems. The most unique attribute I can come up with is the fully\n     * qualified name of the directory. Beware though, this is also\n     * unreliable. I'm open to suggestion on a better way to emulate inode.  */\n    char *path_key;\n    time_t ctime;\n    time_t mtime;        /* controls check for stale directory cache */\n    int fs_flags;     /* FS_FAT, FS_NTFS, ... */\n# define FS_FAT      0x1\n# define FS_NTFS     0x2\n# define FS_UNKNOWN  0x4\n#else\n# if MK_OS_VMS_INO_T\n    ino_t ino[3];\n# else\n    ino_t ino;\n# endif\n#endif /* MK_OS_W32 */\n    struct hash_table dirfiles; /* Files in this directory.  */\n    unsigned long counter;      /* command_count value when last read. */\n    DIR *dirstream;             /* Stream reading this directory.  */\n  };\n\nstatic struct directory_contents *\nclear_directory_contents (struct directory_contents *dc)\n{\n  dc->counter = 0;\n  if (dc->dirstream)\n    {\n      --open_directories;\n      closedir (dc->dirstream);\n      dc->dirstream = NULL;\n    }\n  if (dc->dirfiles.ht_vec != NULL)\n    hash_free (&dc->dirfiles, 1);\n\n  return NULL;\n}\n\nstatic unsigned long\ndirectory_contents_hash_1 (const void *key_0)\n{\n  const struct directory_contents *key = key_0;\n  unsigned long hash;\n\n#if MK_OS_W32\n  hash = 0;\n  ISTRING_HASH_1 (key->path_key, hash);\n  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;\n#else\n# if MK_OS_VMS_INO_T\n  hash = (((unsigned int) key->dev << 4)\n          ^ ((unsigned int) key->ino[0]\n             + (unsigned int) key->ino[1]\n             + (unsigned int) key->ino[2]));\n# else\n  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;\n# endif\n#endif /* MK_OS_W32 */\n  return hash;\n}\n\nstatic unsigned long\ndirectory_contents_hash_2 (const void *key_0)\n{\n  const struct directory_contents *key = key_0;\n  unsigned long hash;\n\n#if MK_OS_W32\n  hash = 0;\n  ISTRING_HASH_2 (key->path_key, hash);\n  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;\n#else\n# if MK_OS_VMS_INO_T\n  hash = (((unsigned int) key->dev << 4)\n          ^ ~((unsigned int) key->ino[0]\n              + (unsigned int) key->ino[1]\n              + (unsigned int) key->ino[2]));\n# else\n  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;\n# endif\n#endif /* MK_OS_W32 */\n\n  return hash;\n}\n\n/* Sometimes it's OK to use subtraction to get this value:\n     result = X - Y;\n   But, if we're not sure of the type of X and Y they may be too large for an\n   int (on a 64-bit system for example).  So, use ?: instead.\n   See Savannah bug #15534.\n\n   NOTE!  This macro has side-effects!\n*/\n\n#define MAKECMP(_x,_y)  ((_x)<(_y)?-1:((_x)==(_y)?0:1))\n\nstatic int\ndirectory_contents_hash_cmp (const void *xv, const void *yv)\n{\n  const struct directory_contents *x = xv;\n  const struct directory_contents *y = yv;\n  int result;\n\n#if MK_OS_W32\n  ISTRING_COMPARE (x->path_key, y->path_key, result);\n  if (result)\n    return result;\n  result = MAKECMP(x->ctime, y->ctime);\n  if (result)\n    return result;\n#else\n# if MK_OS_VMS_INO_T\n  result = MAKECMP(x->ino[0], y->ino[0]);\n  if (result)\n    return result;\n  result = MAKECMP(x->ino[1], y->ino[1]);\n  if (result)\n    return result;\n  result = MAKECMP(x->ino[2], y->ino[2]);\n  if (result)\n    return result;\n# else\n  result = MAKECMP(x->ino, y->ino);\n  if (result)\n    return result;\n# endif\n#endif /* MK_OS_W32 */\n\n  return MAKECMP(x->dev, y->dev);\n}\n\n/* Table of directory contents hashed by device and inode number.  */\nstatic struct hash_table directory_contents;\n\nstruct directory\n  {\n    const char *name;           /* Name of the directory.  */\n    unsigned long counter;      /* command_count value when last read.\n                                   Used for non-existent directories.  */\n\n    /* The directory's contents.  This data may be shared by several\n       entries in the hash table, which refer to the same directory\n       (identified uniquely by 'dev' and 'ino') under different names.  */\n    struct directory_contents *contents;\n  };\n\nstatic unsigned long\ndirectory_hash_1 (const void *key)\n{\n  return_ISTRING_HASH_1 (((const struct directory *) key)->name);\n}\n\nstatic unsigned long\ndirectory_hash_2 (const void *key)\n{\n  return_ISTRING_HASH_2 (((const struct directory *) key)->name);\n}\n\nstatic int\ndirectory_hash_cmp (const void *x, const void *y)\n{\n  return_ISTRING_COMPARE (((const struct directory *) x)->name,\n                          ((const struct directory *) y)->name);\n}\n\n/* Table of directories hashed by name.  */\nstatic struct hash_table directories;\n\n\n/* Hash table of files in each directory.  */\n\nstruct dirfile\n  {\n    const char *name;           /* Name of the file.  */\n    size_t length;\n    short impossible;           /* This file is impossible.  */\n    unsigned char type;\n  };\n\nstatic unsigned long\ndirfile_hash_1 (const void *key)\n{\n  return_ISTRING_HASH_1 (((struct dirfile const *) key)->name);\n}\n\nstatic unsigned long\ndirfile_hash_2 (const void *key)\n{\n  return_ISTRING_HASH_2 (((struct dirfile const *) key)->name);\n}\n\nstatic int\ndirfile_hash_cmp (const void *xv, const void *yv)\n{\n  const struct dirfile *x = xv;\n  const struct dirfile *y = yv;\n  int result = (int) (x->length - y->length);\n  if (result)\n    return result;\n  return_ISTRING_COMPARE (x->name, y->name);\n}\n\n#ifndef DIRFILE_BUCKETS\n#define DIRFILE_BUCKETS 107\n#endif\n\f\nstatic int dir_contents_file_exists_p (struct directory *dir,\n                                       const char *filename);\nstatic struct directory *find_directory (const char *name);\n\n/* Find the directory named NAME and return its 'struct directory'.  */\n\nstatic struct directory *\nfind_directory (const char *name)\n{\n  struct directory *dir;\n  struct directory **dir_slot;\n  struct directory dir_key;\n  struct directory_contents *dc;\n  struct directory_contents **dc_slot;\n  struct directory_contents dc_key;\n\n  struct stat st;\n  int r;\n#if MK_OS_W32\n  char *w32_path;\n#endif\n\n  dir_key.name = name;\n  dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);\n  dir = *dir_slot;\n\n  if (!HASH_VACANT (dir))\n    {\n      unsigned long ctr = dir->contents ? dir->contents->counter : dir->counter;\n\n      /* No commands have run since we parsed this directory so it's good.  */\n      if (ctr == command_count)\n        return dir;\n\n      DB (DB_VERBOSE, (\"Directory %s cache invalidated (count %lu != command %lu)\\n\",\n                       name, ctr, command_count));\n\n      if (dir->contents)\n        clear_directory_contents (dir->contents);\n    }\n  else\n    {\n      /* The directory was not found.  Create a new entry for it.  */\n      size_t len = strlen (name);\n\n      dir = xmalloc (sizeof (struct directory));\n#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS\n      /* Todo: Why is this only needed on VMS? */\n      {\n        char *lname = downcase_inplace (xstrdup (name));\n        dir->name = strcache_add_len (lname, len);\n        free (lname);\n      }\n#else\n      dir->name = strcache_add_len (name, len);\n#endif\n      hash_insert_at (&directories, dir, dir_slot);\n    }\n\n  dir->contents = NULL;\n  dir->counter = command_count;\n\n  /* See if the directory exists.  */\n#if MK_OS_W32\n  {\n    char tem[MAX_PATH+1], *tstart, *tend;\n    size_t len = strlen (name);\n\n    /* Remove any trailing slashes.  Windows32 stat fails even on\n       valid directories if they end in a slash. */\n    memcpy (tem, name, len + 1);\n    tstart = tem;\n    if (tstart[1] == ':')\n      tstart += 2;\n    for (tend = tem + (len - 1); tend > tstart && ISDIRSEP (*tend); tend--)\n      *tend = '\\0';\n\n    r = stat (tem, &st);\n  }\n#else\n  EINTRLOOP (r, stat (name, &st));\n#endif\n\n  if (r < 0)\n    /* Couldn't stat the directory; nothing else to do.  */\n    return dir;\n\n  /* Search the contents hash table; device and inode are the key.  */\n\n  memset (&dc_key, '\\0', sizeof (dc_key));\n  dc_key.dev = st.st_dev;\n#if MK_OS_W32\n  dc_key.path_key = w32_path = w32ify (name, 1);\n  dc_key.ctime = st.st_ctime;\n#else\n# if MK_OS_VMS_INO_T\n  dc_key.ino[0] = st.st_ino[0];\n  dc_key.ino[1] = st.st_ino[1];\n  dc_key.ino[2] = st.st_ino[2];\n# else\n  dc_key.ino = st.st_ino;\n# endif\n#endif\n  dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);\n  dc = *dc_slot;\n\n  if (HASH_VACANT (dc))\n    {\n      /* Nope; this really is a directory we haven't seen before.  */\n#if MK_OS_W32\n      char  fs_label[BUFSIZ];\n      char  fs_type[BUFSIZ];\n      unsigned long  fs_serno;\n      unsigned long  fs_flags;\n      unsigned long  fs_len;\n#endif\n      /* Enter it in the contents hash table.  */\n      dc = xcalloc (sizeof (struct directory_contents));\n      *dc = dc_key;\n\n#if MK_OS_W32\n      dc->path_key = xstrdup (w32_path);\n      dc->mtime = st.st_mtime;\n\n      /* NTFS is the only Windows32 filesystem that bumps mtime on a\n         directory when files are added/deleted from a directory.  */\n      w32_path[3] = '\\0';\n      if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),\n                                &fs_serno, &fs_len, &fs_flags, fs_type,\n                                sizeof (fs_type)) == FALSE)\n        dc->fs_flags = FS_UNKNOWN;\n      else if (!strcmp (fs_type, \"FAT\"))\n        dc->fs_flags = FS_FAT;\n      else if (!strcmp (fs_type, \"NTFS\"))\n        dc->fs_flags = FS_NTFS;\n      else\n        dc->fs_flags = FS_UNKNOWN;\n#endif /* MK_OS_W32 */\n\n      hash_insert_at (&directory_contents, dc, dc_slot);\n    }\n\n  /* Point the name-hashed entry for DIR at its contents data.  */\n  dir->contents = dc;\n\n  /* If the contents have changed, we need to reseed.  */\n  if (dc->counter != command_count)\n    {\n      if (dc->counter)\n        clear_directory_contents (dc);\n\n      dc->counter = command_count;\n\n      ENULLLOOP (dc->dirstream, opendir (name));\n      if (dc->dirstream == NULL)\n        /* Couldn't open the directory: mark this by setting files to NULL.  */\n        dc->dirfiles.ht_vec = NULL;\n      else\n        {\n          hash_init (&dc->dirfiles, DIRFILE_BUCKETS,\n                     dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);\n          /* Keep track of how many directories are open.  */\n          ++open_directories;\n          if (open_directories == MAX_OPEN_DIRECTORIES)\n            /* We have too many directories open already.\n               Read the entire directory and then close it.  */\n            dir_contents_file_exists_p (dir, NULL);\n        }\n    }\n\n  return dir;\n}\n\f\n/* Return 1 if the name FILENAME is entered in DIR's hash table.\n   FILENAME must contain no slashes.  */\n\nstatic int\ndir_contents_file_exists_p (struct directory *dir,\n                            const char *filename)\n{\n  struct dirfile *df;\n  struct dirent *d;\n  struct directory_contents *dc = dir->contents;\n#if MK_OS_W32\n  struct stat st;\n  int rehash = 0;\n#endif\n\n  if (dc == NULL || dc->dirfiles.ht_vec == NULL)\n    /* The directory could not be stat'd or opened.  */\n    return 0;\n\n#if MK_OS_DOS\n  filename = dosify (filename);\n#endif\n\n#ifdef HAVE_CASE_INSENSITIVE_FS\n  filename = downcase (filename);\n#endif\n\n#if MK_OS_OS2\n  if (filename != NULL)\n    {\n      size_t len = strlen (filename);\n      char *fname = alloca (len + 1);\n      memcpy (fname, filename, len + 1);\n      _fnlwr (fname); /* lower case for FAT drives */\n      filename = fname;\n    }\n#endif\n  if (filename != NULL)\n    {\n      struct dirfile dirfile_key;\n\n      if (*filename == '\\0')\n        {\n          /* Checking if the directory exists.  */\n          return 1;\n        }\n      dirfile_key.name = filename;\n      dirfile_key.length = strlen (filename);\n      df = hash_find_item (&dc->dirfiles, &dirfile_key);\n      if (df)\n        return !df->impossible;\n    }\n\n  /* The file was not found in the hashed list.\n     Try to read the directory further.  */\n\n  if (dc->dirstream == NULL)\n    {\n#if MK_OS_W32\n      /*\n       * Check to see if directory has changed since last read. FAT\n       * filesystems force a rehash always as mtime does not change\n       * on directories (ugh!).\n       */\n      if (dc->path_key)\n        {\n          if ((dc->fs_flags & FS_FAT) != 0)\n            {\n              dc->mtime = time (NULL);\n              rehash = 1;\n            }\n          else if (stat (dc->path_key, &st) == 0 && st.st_mtime > dc->mtime)\n            {\n              /* reset date stamp to show most recent re-process.  */\n              dc->mtime = st.st_mtime;\n              rehash = 1;\n            }\n\n          /* If it has been already read in, all done.  */\n          if (!rehash)\n            return 0;\n\n          /* make sure directory can still be opened; if not return.  */\n          dc->dirstream = opendir (dc->path_key);\n          if (!dc->dirstream)\n            return 0;\n        }\n      else\n#endif\n        /* The directory has been all read in.  */\n        return 0;\n    }\n\n  while (1)\n    {\n      /* Enter the file in the hash table.  */\n      size_t len;\n      struct dirfile dirfile_key;\n      struct dirfile **dirfile_slot;\n\n      ENULLLOOP (d, readdir (dc->dirstream));\n      if (d == NULL)\n        {\n          if (errno)\n            OSS (fatal, NILF, \"readdir %s: %s\", dir->name, strerror (errno));\n          break;\n        }\n\n#if MK_OS_VMS && defined(HAVE_DIRENT_H)\n      /* In VMS we get file versions too, which have to be stripped off.\n         Some versions of VMS return versions on Unix files even when\n         the feature option to strip them is set.  */\n      {\n        char *p = strrchr (d->d_name, ';');\n        if (p)\n          *p = '\\0';\n      }\n#endif\n      if (!REAL_DIR_ENTRY (d))\n        continue;\n\n      len = NAMLEN (d);\n      dirfile_key.name = d->d_name;\n      dirfile_key.length = len;\n      dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key);\n#if MK_OS_W32\n      /*\n       * If re-reading a directory, don't cache files that have\n       * already been discovered.\n       */\n      if (! rehash || HASH_VACANT (*dirfile_slot))\n#endif\n        {\n          df = xmalloc (sizeof (struct dirfile));\n#if MK_OS_VMS && defined(HAVE_CASE_INSENSITIVE_FS)\n          /* TODO: Why is this only needed on VMS? */\n          df->name = strcache_add_len (downcase_inplace (d->d_name), len);\n#else\n          df->name = strcache_add_len (d->d_name, len);\n#endif\n#ifdef HAVE_STRUCT_DIRENT_D_TYPE\n          df->type = d->d_type;\n#endif\n          df->length = len;\n          df->impossible = 0;\n          hash_insert_at (&dc->dirfiles, df, dirfile_slot);\n        }\n      /* Check if the name matches the one we're searching for.  */\n      if (filename != NULL && patheq (d->d_name, filename))\n        return 1;\n    }\n\n  /* If the directory has been completely read in,\n     close the stream and reset the pointer to nil.  */\n  if (d == NULL)\n    {\n      --open_directories;\n      closedir (dc->dirstream);\n      dc->dirstream = NULL;\n    }\n\n  return 0;\n}\n\n/* Return 1 if the name FILENAME in directory DIRNAME\n   is entered in the dir hash table.\n   FILENAME must contain no slashes.  */\n\nint\ndir_file_exists_p (const char *dirname, const char *filename)\n{\n#if MK_OS_VMS\n  if (filename && dirname && strpbrk (dirname, \":<[\") != NULL)\n    filename = vmsify (filename, 0);\n#endif\n  return dir_contents_file_exists_p (find_directory (dirname),\n                                     filename);\n}\n\f\n/* Return 1 if the file named NAME exists.  */\n\nint\nfile_exists_p (const char *name)\n{\n  const char *dirend;\n  const char *dirname;\n  const char *slash;\n\n#ifndef NO_ARCHIVES\n  if (ar_name (name))\n    return ar_member_date (name) != (time_t) -1;\n#endif\n\n  dirend = strrchr (name, '/');\n#if MK_OS_VMS\n  if (dirend == NULL)\n    {\n      dirend = strrchr (name, ']');\n      dirend == NULL ? dirend : dirend++;\n    }\n  if (dirend == NULL)\n    {\n      dirend = strrchr (name, '>');\n      dirend == NULL ? dirend : dirend++;\n    }\n  if (dirend == NULL)\n    {\n      dirend = strrchr (name, ':');\n      dirend == NULL ? dirend : dirend++;\n    }\n#endif /* MK_OS_VMS */\n#ifdef HAVE_DOS_PATHS\n  /* Forward and backslashes might be mixed.  We need the rightmost one.  */\n  {\n    const char *bslash = strrchr (name, '\\\\');\n    if (!dirend || bslash > dirend)\n      dirend = bslash;\n    /* The case of \"d:file\".  */\n    if (!dirend && name[0] && name[1] == ':')\n      dirend = name + 1;\n  }\n#endif /* HAVE_DOS_PATHS */\n  if (dirend == NULL)\n    return dir_file_exists_p (\".\", name);\n\n  slash = dirend;\n  if (dirend == name)\n    dirname = \"/\";\n  else\n    {\n      char *p;\n#ifdef HAVE_DOS_PATHS\n  /* d:/ and d: are *very* different...  */\n      if (dirend < name + 3 && name[1] == ':' &&\n          (ISDIRSEP (*dirend) || *dirend == ':'))\n        dirend++;\n#endif\n      p = alloca (dirend - name + 1);\n      memcpy (p, name, dirend - name);\n      p[dirend - name] = '\\0';\n      dirname = p;\n    }\n#if MK_OS_VMS\n  if (*slash == '/')\n    slash++;\n#else\n  slash++;\n#endif\n  return dir_file_exists_p (dirname, slash);\n}\n\f\n/* Mark FILENAME as 'impossible' for 'file_impossible_p'.\n   This means an attempt has been made to search for FILENAME\n   as an intermediate file, and it has failed.  */\n\nvoid\nfile_impossible (const char *filename)\n{\n  const char *dirend;\n  const char *p = filename;\n  struct directory *dir;\n  struct dirfile *new;\n\n  dirend = strrchr (p, '/');\n#if MK_OS_VMS\n  if (dirend == NULL)\n    {\n      dirend = strrchr (p, ']');\n      dirend == NULL ? dirend : dirend++;\n    }\n  if (dirend == NULL)\n    {\n      dirend = strrchr (p, '>');\n      dirend == NULL ? dirend : dirend++;\n    }\n  if (dirend == NULL)\n    {\n      dirend = strrchr (p, ':');\n      dirend == NULL ? dirend : dirend++;\n    }\n#endif\n#ifdef HAVE_DOS_PATHS\n  /* Forward and backslashes might be mixed.  We need the rightmost one.  */\n  {\n    const char *bslash = strrchr (p, '\\\\');\n    if (!dirend || bslash > dirend)\n      dirend = bslash;\n    /* The case of \"d:file\".  */\n    if (!dirend && p[0] && p[1] == ':')\n      dirend = p + 1;\n  }\n#endif /* HAVE_DOS_PATHS */\n  if (dirend == NULL)\n    dir = find_directory (\".\");\n  else\n    {\n      const char *dirname;\n      const char *slash = dirend;\n      if (dirend == p)\n        dirname = \"/\";\n      else\n        {\n          char *cp;\n#ifdef HAVE_DOS_PATHS\n          /* d:/ and d: are *very* different...  */\n          if (dirend < p + 3 && p[1] == ':' &&\n              (ISDIRSEP (*dirend) || *dirend == ':'))\n            dirend++;\n#endif\n          cp = alloca (dirend - p + 1);\n          memcpy (cp, p, dirend - p);\n          cp[dirend - p] = '\\0';\n          dirname = cp;\n        }\n      dir = find_directory (dirname);\n#if MK_OS_VMS\n      if (*slash == '/')\n        filename = p = slash + 1;\n      else\n        filename = p = slash;\n#else\n      filename = p = slash + 1;\n#endif\n    }\n\n  if (dir->contents == NULL)\n    /* The directory could not be stat'd.  We allocate a contents\n       structure for it, but leave it out of the contents hash table.  */\n    dir->contents = xcalloc (sizeof (struct directory_contents));\n\n  if (dir->contents->dirfiles.ht_vec == NULL)\n    hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,\n               dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);\n\n  /* Make a new entry and put it in the table.  */\n\n  new = xmalloc (sizeof (struct dirfile));\n  new->length = strlen (filename);\n#if defined(HAVE_CASE_INSENSITIVE_FS) && MK_OS_VMS\n  /* todo: Why is this only needed on VMS? */\n  new->name = strcache_add_len (downcase (filename), new->length);\n#else\n  new->name = strcache_add_len (filename, new->length);\n#endif\n  new->impossible = 1;\n  hash_insert (&dir->contents->dirfiles, new);\n}\n\f\n/* Return nonzero if FILENAME has been marked impossible.  */\n\nint\nfile_impossible_p (const char *filename)\n{\n  const char *dirend;\n  struct directory_contents *dir;\n  struct dirfile *dirfile;\n  struct dirfile dirfile_key;\n#if MK_OS_VMS\n  int want_vmsify = 0;\n#endif\n\n  dirend = strrchr (filename, '/');\n#if MK_OS_VMS\n  if (dirend == NULL)\n    {\n      want_vmsify = (strpbrk (filename, \"]>:^\") != NULL);\n      dirend = strrchr (filename, ']');\n    }\n  if (dirend == NULL && want_vmsify)\n    dirend = strrchr (filename, '>');\n  if (dirend == NULL && want_vmsify)\n    dirend = strrchr (filename, ':');\n#endif\n#ifdef HAVE_DOS_PATHS\n  /* Forward and backslashes might be mixed.  We need the rightmost one.  */\n  {\n    const char *bslash = strrchr (filename, '\\\\');\n    if (!dirend || bslash > dirend)\n      dirend = bslash;\n    /* The case of \"d:file\".  */\n    if (!dirend && filename[0] && filename[1] == ':')\n      dirend = filename + 1;\n  }\n#endif /* HAVE_DOS_PATHS */\n  if (dirend == NULL)\n    dir = find_directory (\".\")->contents;\n  else\n    {\n      const char *dirname;\n      const char *slash = dirend;\n      if (dirend == filename)\n        dirname = \"/\";\n      else\n        {\n          char *cp;\n#ifdef HAVE_DOS_PATHS\n          /* d:/ and d: are *very* different...  */\n          if (dirend < filename + 3 && filename[1] == ':' &&\n              (ISDIRSEP (*dirend) || *dirend == ':'))\n            dirend++;\n#endif\n          cp = alloca (dirend - filename + 1);\n          memcpy (cp, filename, dirend - filename);\n          cp[dirend - filename] = '\\0';\n          dirname = cp;\n        }\n      dir = find_directory (dirname)->contents;\n#if MK_OS_VMS\n      if (*slash == '/')\n        filename = slash + 1;\n      else\n        filename = slash;\n#else\n      filename = slash + 1;\n#endif\n    }\n\n  if (dir == NULL || dir->dirfiles.ht_vec == NULL)\n    /* There are no files entered for this directory.  */\n    return 0;\n\n#if MK_OS_DOS\n  filename = dosify (filename);\n#endif\n#ifdef HAVE_CASE_INSENSITIVE_FS\n  filename = downcase (filename);\n#endif\n#if MK_OS_VMS\n  if (want_vmsify)\n    filename = vmsify (filename, 1);\n#endif\n\n  dirfile_key.name = filename;\n  dirfile_key.length = strlen (filename);\n  dirfile = hash_find_item (&dir->dirfiles, &dirfile_key);\n  if (dirfile)\n    return dirfile->impossible;\n\n  return 0;\n}\n\f\n/* Return the already allocated name in the\n   directory hash table that matches DIR.  */\n\nconst char *\ndir_name (const char *dir)\n{\n  return find_directory (dir)->name;\n}\n\f\n/* Print the data base of directories.  */\n\nvoid\nprint_dir_data_base (void)\n{\n  unsigned int files;\n  unsigned int impossible;\n  struct directory **dir_slot;\n  struct directory **dir_end;\n#if MK_OS_W32\n  char buf[INTSTR_LENGTH + 1];\n#endif\n\n  puts (_(\"\\n# Directories\\n\"));\n\n  files = impossible = 0;\n\n  dir_slot = (struct directory **) directories.ht_vec;\n  dir_end = dir_slot + directories.ht_size;\n  for ( ; dir_slot < dir_end; dir_slot++)\n    {\n      struct directory *dir = *dir_slot;\n      if (! HASH_VACANT (dir))\n        {\n          if (dir->contents == NULL)\n            printf (_(\"# %s: could not be stat'd.\\n\"), dir->name);\n          else if (dir->contents->dirfiles.ht_vec == NULL)\n#if MK_OS_W32\n            printf (_(\"# %s (key %s, mtime %s): could not be opened.\\n\"),\n                    dir->name, dir->contents->path_key,\n                    make_ulltoa ((unsigned long long)dir->contents->mtime, buf));\n#elif defined(VMS_INO_T)\n            printf (_(\"# %s (device %d, inode [%d,%d,%d]): could not be opened.\\n\"),\n                    dir->name, dir->contents->dev,\n                    dir->contents->ino[0], dir->contents->ino[1],\n                    dir->contents->ino[2]);\n#else\n            printf (_(\"# %s (device %ld, inode %ld): could not be opened.\\n\"),\n                    dir->name, (long) dir->contents->dev, (long) dir->contents->ino);\n#endif\n          else\n            {\n              unsigned int f = 0;\n              unsigned int im = 0;\n              struct dirfile **files_slot;\n              struct dirfile **files_end;\n\n              files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;\n              files_end = files_slot + dir->contents->dirfiles.ht_size;\n              for ( ; files_slot < files_end; files_slot++)\n                {\n                  struct dirfile *df = *files_slot;\n                  if (! HASH_VACANT (df))\n                    {\n                      if (df->impossible)\n                        ++im;\n                      else\n                        ++f;\n                    }\n                }\n#if MK_OS_W32\n              printf (_(\"# %s (key %s, mtime %s): \"),\n                      dir->name, dir->contents->path_key,\n                      make_ulltoa ((unsigned long long)dir->contents->mtime, buf));\n#elif defined(VMS_INO_T)\n              printf (_(\"# %s (device %d, inode [%d,%d,%d]): \"),\n                      dir->name, dir->contents->dev,\n                      dir->contents->ino[0], dir->contents->ino[1],\n                      dir->contents->ino[2]);\n#else\n              printf (_(\"# %s (device %ld, inode %ld): \"), dir->name,\n                      (long)dir->contents->dev, (long)dir->contents->ino);\n#endif\n              if (f == 0)\n                fputs (_(\"No\"), stdout);\n              else\n                printf (\"%u\", f);\n              fputs (_(\" files, \"), stdout);\n              if (im == 0)\n                fputs (_(\"no\"), stdout);\n              else\n                printf (\"%u\", im);\n              fputs (_(\" impossibilities\"), stdout);\n              if (dir->contents->dirstream == NULL)\n                puts (\".\");\n              else\n                puts (_(\" so far.\"));\n              files += f;\n              impossible += im;\n            }\n        }\n    }\n\n  fputs (\"\\n# \", stdout);\n  if (files == 0)\n    fputs (_(\"No\"), stdout);\n  else\n    printf (\"%u\", files);\n  fputs (_(\" files, \"), stdout);\n  if (impossible == 0)\n    fputs (_(\"no\"), stdout);\n  else\n    printf (\"%u\", impossible);\n  printf (_(\" impossibilities in %lu directories.\\n\"), directories.ht_fill);\n}\n\f\n/* Hooks for globbing.  */\n\n/* Structure describing state of iterating through a directory hash table.  */\n\nstruct dirstream\n  {\n    struct directory_contents *contents; /* The directory being read.  */\n    struct dirfile **dirfile_slot; /* Current slot in table.  */\n  };\n\n/* Forward declarations.  */\nstatic void *open_dirstream (const char *);\nstatic struct dirent *read_dirstream (void *);\n\nstatic void *\nopen_dirstream (const char *directory)\n{\n  struct dirstream *new;\n  struct directory *dir = find_directory (directory);\n\n  if (dir->contents == NULL || dir->contents->dirfiles.ht_vec == NULL)\n    /* DIR->contents is nil if the directory could not be stat'd.\n       DIR->contents->dirfiles is nil if it could not be opened.  */\n    return NULL;\n\n  /* Read all the contents of the directory now.  There is no benefit\n     in being lazy, since glob will want to see every file anyway.  */\n\n  dir_contents_file_exists_p (dir, NULL);\n\n  new = xmalloc (sizeof (struct dirstream));\n  new->contents = dir->contents;\n  new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;\n\n  return new;\n}\n\nstatic struct dirent *\nread_dirstream (void *stream)\n{\n  static char *buf;\n  static size_t bufsz;\n\n  struct dirstream *const ds = (struct dirstream *) stream;\n  struct directory_contents *dc = ds->contents;\n  struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;\n\n  while (ds->dirfile_slot < dirfile_end)\n    {\n      struct dirfile *df = *ds->dirfile_slot++;\n      if (! HASH_VACANT (df) && !df->impossible)\n        {\n          /* The glob interface wants a 'struct dirent', so mock one up.  */\n          struct dirent *d;\n          size_t len = df->length + 1;\n          size_t sz = sizeof (*d) - sizeof (d->d_name) + len;\n          if (sz > bufsz)\n            {\n              bufsz *= 2;\n              if (sz > bufsz)\n                bufsz = sz;\n              buf = xrealloc (buf, bufsz);\n            }\n          d = (struct dirent *) buf;\n#ifdef __MINGW32__\n# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \\\n                                     __MINGW32_MINOR_VERSION == 0)\n          d->d_name = xmalloc (len);\n# endif\n#endif\n          FAKE_DIR_ENTRY (d);\n#ifdef _DIRENT_HAVE_D_NAMLEN\n          d->d_namlen = len - 1;\n#endif\n#ifdef HAVE_STRUCT_DIRENT_D_TYPE\n          d->d_type = df->type;\n#endif\n          memcpy (d->d_name, df->name, len);\n          return d;\n        }\n    }\n\n  return NULL;\n}\n\n/* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a\n * macro for stat64().  If stat is a macro, make a local wrapper function to\n * invoke it.\n *\n * On MS-Windows, stat() \"succeeds\" for foo/bar/. where foo/bar is a\n * regular file; fix that here.\n */\n#if !defined(stat) && !MK_OS_W32 || MK_OS_VMS\n# if !MK_OS_VMS\n#  ifndef HAVE_SYS_STAT_H\nint stat (const char *path, struct stat *sbuf);\n#  endif\n# else\n    /* We are done with the fake stat.  Go back to the real stat */\n#   ifdef stat\n#     undef stat\n#   endif\n# endif\n# define local_stat stat\n#else\nstatic int\nlocal_stat (const char *path, struct stat *buf)\n{\n  int e;\n#if MK_OS_W32\n  size_t plen = strlen (path);\n\n  /* Make sure the parent of \".\" exists and is a directory, not a\n     file.  This is because 'stat' on Windows normalizes the argument\n     foo/. => foo without checking first that foo is a directory.  */\n  if (plen > 2 && path[plen - 1] == '.' && ISDIRSEP (path[plen - 2]))\n    {\n      char parent[MAX_PATH+1];\n\n      strncpy (parent, path, MAX_PATH);\n      parent[MIN(plen - 2, MAX_PATH)] = '\\0';\n      if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode))\n        return -1;\n    }\n#endif\n\n  EINTRLOOP (e, stat (path, buf));\n  return e;\n}\n#endif\n\n/* Similarly for lstat.  */\n#if !defined(lstat) && !MK_OS_W32 || MK_OS_VMS\n# if !MK_OS_VMS\n#  ifndef HAVE_SYS_STAT_H\nint lstat (const char *path, struct stat *sbuf);\n#  endif\n# else\n    /* We are done with the fake lstat.  Go back to the real lstat */\n#   ifdef lstat\n#     undef lstat\n#   endif\n# endif\n# define local_lstat lstat\n#elif MK_OS_W32\n/* Windows doesn't support lstat().  */\n# define local_lstat local_stat\n#else\nstatic int\nlocal_lstat (const char *path, struct stat *buf)\n{\n  int e;\n  EINTRLOOP (e, lstat (path, buf));\n  return e;\n}\n#endif\n\nvoid\ndir_setup_glob (glob_t *gl)\n{\n  gl->gl_offs = 0;\n  gl->gl_opendir = open_dirstream;\n  gl->gl_readdir = read_dirstream;\n  gl->gl_closedir = free;\n  gl->gl_lstat = local_lstat;\n  gl->gl_stat = local_stat;\n}\n\nvoid\nhash_init_directories (void)\n{\n  hash_init (&directories, DIRECTORY_BUCKETS,\n             directory_hash_1, directory_hash_2, directory_hash_cmp);\n  hash_init (&directory_contents, DIRECTORY_BUCKETS,\n             directory_contents_hash_1, directory_contents_hash_2,\n             directory_contents_hash_cmp);\n}\n"
  },
  {
    "path": "src/expand.c",
    "content": "/* Variable expansion functions for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#include \"commands.h\"\n#include \"debug.h\"\n#include \"filedef.h\"\n#include \"job.h\"\n#include \"variable.h\"\n#include \"rule.h\"\n#include \"warning.h\"\n\n/* Initially, any errors reported when expanding strings will be reported\n   against the file where the error appears.  */\nconst floc **expanding_var = &reading_file;\n\n/* The next two describe the variable output buffer.\n   This buffer is used to hold the variable-expansion of a line of the\n   makefile.  It is made bigger with realloc whenever it is too small.\n   variable_buffer_length is the size currently allocated.\n   variable_buffer is the address of the buffer.\n\n   For efficiency, it's guaranteed that the buffer will always have\n   VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few\n   extra chars without having to call a function.  Note you should never use\n   these bytes unless you're _sure_ you have room (you know when the buffer\n   length was last checked.  */\n\n#define VARIABLE_BUFFER_ZONE    5\n\nstatic size_t variable_buffer_length;\nchar *variable_buffer;\n\n/* Append LENGTH chars of STRING at PTR which must point into variable_buffer.\n   The buffer will always be kept nul-terminated.\n   The updated pointer into the buffer is returned as the value.  Thus, the\n   value returned by each call to variable_buffer_output should be the first\n   argument to the following call.  */\n\nchar *\nvariable_buffer_output (char *ptr, const char *string, size_t length)\n{\n  size_t newlen = length + (ptr - variable_buffer);\n\n  assert (ptr >= variable_buffer);\n  assert (ptr < variable_buffer + variable_buffer_length);\n\n  if (newlen + VARIABLE_BUFFER_ZONE + 1 > variable_buffer_length)\n    {\n      size_t offset = ptr - variable_buffer;\n      variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length\n                                ? newlen + 100\n                                : 2 * variable_buffer_length);\n      variable_buffer = xrealloc (variable_buffer, variable_buffer_length + 1);\n      ptr = variable_buffer + offset;\n    }\n\n  ptr = mempcpy (ptr, string, length);\n  *ptr = '\\0';\n  return ptr;\n}\n\n/* Return a pointer to the beginning of the variable buffer.\n   This is called from main() and it should never be null afterward.  */\n\nchar *\ninitialize_variable_output ()\n{\n  /* If we don't have a variable output buffer yet, get one.  */\n\n  if (!variable_buffer)\n    {\n      variable_buffer_length = 200;\n      variable_buffer = xmalloc (variable_buffer_length);\n    }\n\n  variable_buffer[0] = '\\0';\n\n  return variable_buffer;\n}\n\n/* Install a new variable_buffer context, returning the current one for\n   safe-keeping.  */\n\nvoid\ninstall_variable_buffer (char **bufp, size_t *lenp)\n{\n  *bufp = variable_buffer;\n  *lenp = variable_buffer_length;\n\n  variable_buffer = NULL;\n  initialize_variable_output ();\n}\n\n/* Free the current variable_buffer and restore a previously-saved one.\n */\n\nvoid\nrestore_variable_buffer (char *buf, size_t len)\n{\n  free (variable_buffer);\n\n  variable_buffer = buf;\n  variable_buffer_length = len;\n}\n\n/* Restore a previously-saved variable_buffer context, and return the\n   current one.\n */\n\nchar *\nswap_variable_buffer (char *buf, size_t len)\n{\n  char *p = variable_buffer;\n\n  variable_buffer = buf;\n  variable_buffer_length = len;\n\n  return p;\n}\n\f\n\n/* Recursively expand V.  The returned string is malloc'd.  */\n\nstatic char *allocated_variable_append (const struct variable *v);\n\nchar *\nrecursively_expand_for_file (struct variable *v, struct file *file)\n{\n  char *value;\n  const floc *this_var;\n  const floc **saved_varp;\n  struct variable_set_list *savev = 0;\n  int set_reading = 0;\n  size_t nl = strlen (v->name);\n  struct variable *parent = NULL;\n\n  /* If we're expanding to put into the environment of a shell function then\n     ignore any recursion issues: for backward-compatibility we will use\n     the value of the environment variable we were started with.  */\n  if (v->expanding && env_recursion)\n    {\n      char **ep;\n      DB (DB_VERBOSE,\n          (_(\"%s:%lu: not recursively expanding %s to export to shell function\\n\"),\n           v->fileinfo.filenm, v->fileinfo.lineno, v->name));\n\n      /* We could create a hash for the original environment for speed, but a\n         reasonably written makefile shouldn't hit this situation...  */\n      for (ep = environ; *ep != 0; ++ep)\n        if (strncmp (*ep, v->name, nl) == 0 && (*ep)[nl] == '=')\n          return xstrdup ((*ep) + nl + 1);\n\n      /* If there's nothing in the parent environment, use the empty string.\n         This isn't quite correct since the variable should not exist at all,\n         but getting that to work would be involved. */\n      return xstrdup (\"\");\n    }\n\n  /* Don't install a new location if this location is empty.\n     This can happen for command-line variables, builtin variables, etc.  */\n  saved_varp = expanding_var;\n  if (v->fileinfo.filenm)\n    {\n      this_var = &v->fileinfo;\n      expanding_var = &this_var;\n    }\n\n  /* If we have no other file-reading context, use the variable's context. */\n  if (!reading_file)\n    {\n      set_reading = 1;\n      reading_file = &v->fileinfo;\n    }\n\n  if (v->expanding)\n    {\n      if (!v->exp_count)\n        /* Expanding V causes infinite recursion.  Lose.  */\n        OS (fatal, *expanding_var,\n            _(\"recursive variable '%s' references itself (eventually)\"),\n            v->name);\n      --v->exp_count;\n    }\n\n  if (file)\n    install_file_context (file, &savev, NULL);\n\n  v->expanding = 1;\n  if (v->append)\n    {\n      /* Find a parent definition which is marked override.  */\n      struct variable_set_list *sl;\n      for (sl = current_variable_set_list; sl && !parent; sl = sl->next)\n        {\n          struct variable *vp = lookup_variable_in_set (v->name, nl, sl->set);\n          if (vp && vp != v && vp->origin == o_override)\n            parent = vp;\n        }\n    }\n\n  if (parent)\n    /* PARENT is an override, V is appending.  If V is also an override:\n         override hello := first\n         al%: override hello += second\n       Then construct the value from its appended parts in the parent sets.\n       Else if V is not an override:\n         override hello := first\n         al%: hello += second\n       Then ignore the value of V and use the value of PARENT.  */\n    value = v->origin == o_override\n      ? allocated_variable_append (v)\n      : xstrdup (parent->value);\n  else if (v->origin == o_command || v->origin == o_env_override)\n    /* Avoid appending to a pattern-specific variable, unless the origin of this\n       pattern-specific variable beats or equals the origin of one of the parent\n       definitions of this variable.\n       This is needed, because if there is a command line definition or an env\n       override, then the value defined in the makefile should only be appended\n       in the case of a file override.\n       In the presence of command line definition or env override and absence of\n       makefile override, the value should be expanded, rather than appended. In\n       this case, at parse time record_target_var already set the value of this\n       pattern-specific variable to the value defined on the command line or to\n       the env override value.\n       User provided a command line definition or an env override.\n       PARENT does not have an override directive, so ignore it.  */\n    value = allocated_expand_string (v->value);\n  else if (v->append)\n    /* Construct the value from its appended parts in the parent sets.  */\n    value = allocated_variable_append (v);\n  else\n    /* A definition without appending.  */\n    value = allocated_expand_string (v->value);\n  v->expanding = 0;\n\n  if (set_reading)\n    reading_file = 0;\n\n  if (file)\n    restore_file_context (savev, NULL);\n\n  expanding_var = saved_varp;\n\n  return value;\n}\n\n/* Expand a simple reference to variable NAME, which is LENGTH chars long.\n   The result is written to PTR which must point into the variable_buffer.\n   Returns a pointer to the new end of the variable_buffer.  */\n\nchar *\nexpand_variable_output (char *ptr, const char *name, size_t length)\n{\n  struct variable *v;\n  unsigned int recursive;\n  char *value;\n\n  v = lookup_variable (name, length);\n\n  if (!v)\n    warn_undefined (name, length);\n\n  /* If there's no variable by that name or it has no value, stop now.  */\n  if (!v || (v->value[0] == '\\0' && !v->append))\n    return ptr;\n\n  /* Remember this since expansion could change it.  */\n  recursive = v->recursive;\n\n  value = recursive ? recursively_expand (v) : v->value;\n\n  ptr = variable_buffer_output (ptr, value, strlen (value));\n\n  if (recursive)\n    free (value);\n\n  return ptr;\n}\n\n/* Expand a simple reference to variable NAME, which is LENGTH chars long.\n   The result is written to BUF which must point into the variable_buffer.\n   If BUF is NULL, start at the beginning of the current variable_buffer.\n   Returns a pointer to the START of the expanded value of the variable.\n   The returned value is located inside variable_buffer.\n   The returned value is valid until the next call to one of the functions\n   which use variable_buffer.  expand_variable_buf may reallocate\n   variable_buffer and render the passed-in BUF invalid.  */\n\n\nchar *\nexpand_variable_buf (char *buf, const char *name, size_t length)\n{\n  size_t offs;\n\n  if (!buf)\n    buf = initialize_variable_output ();\n\n  assert (buf >= variable_buffer);\n  assert (buf < variable_buffer + variable_buffer_length);\n  offs = buf - variable_buffer;\n\n  expand_variable_output (buf, name, length);\n  return variable_buffer + offs;\n}\n\n/* Expand a simple reference to variable NAME, which is LENGTH chars long.\n   Returns an allocated buffer containing the value.  */\n\nchar *\nallocated_expand_variable (const char *name, size_t length)\n{\n  char *obuf;\n  size_t olen;\n\n  install_variable_buffer (&obuf, &olen);\n\n  expand_variable_output (variable_buffer, name, length);\n\n  return swap_variable_buffer (obuf, olen);\n}\n\n/* Expand a simple reference to variable NAME, which is LENGTH chars long.\n   Error messages refer to the file and line where FILE's commands were found.\n   Expansion uses FILE's variable set list.\n   Returns an allocated buffer containing the value.  */\n\nchar *\nallocated_expand_variable_for_file (const char *name, size_t length, struct file *file)\n{\n  char *result;\n  struct variable_set_list *savev;\n  const floc *savef;\n\n  if (!file)\n    return allocated_expand_variable (name, length);\n\n  install_file_context (file, &savev, &savef);\n\n  result = allocated_expand_variable (name, length);\n\n  restore_file_context (savev, savef);\n\n  return result;\n}\n\f\n/* Scan STRING for variable references and expansion-function calls.  Only\n   LENGTH bytes of STRING are actually scanned.\n   If LENGTH is SIZE_MAX, scan until a null byte is found.\n\n   Write the results to BUF, which must point into variable_buffer.  If\n   BUF is NULL, start at the beginning of the current variable_buffer.\n\n   Return a pointer to BUF, or to the beginning of the new buffer if BUF is\n   NULL.\n */\nchar *\nexpand_string_buf (char *buf, const char *string, size_t length)\n{\n  struct variable *v;\n  const char *p, *p1;\n  char *save;\n  char *o;\n  size_t line_offset;\n\n  if (!buf)\n    buf = initialize_variable_output ();\n  o = buf;\n  line_offset = buf - variable_buffer;\n\n  if (length == 0)\n    return variable_buffer;\n\n  /* We need a copy of STRING: due to eval, it's possible that it will get\n     freed as we process it (it might be the value of a variable that's reset\n     for example).  Also having a nil-terminated string is handy.  */\n  save = length == SIZE_MAX ? xstrdup (string) : xstrndup (string, length);\n  p = save;\n\n  while (1)\n    {\n      /* Copy all following uninteresting chars all at once to the\n         variable output buffer, and skip them.  Uninteresting chars end\n         at the next $ or the end of the input.  */\n\n      p1 = strchr (p, '$');\n\n      o = variable_buffer_output (o, p, p1 != 0 ? (size_t) (p1 - p) : strlen (p) + 1);\n\n      if (p1 == 0)\n        break;\n      p = p1 + 1;\n\n      /* Dispatch on the char that follows the $.  */\n\n      switch (*p)\n        {\n        case '$':\n        case '\\0':\n          /* $$ or $ at the end of the string means output one $ to the\n             variable output buffer.  */\n          o = variable_buffer_output (o, p1, 1);\n          break;\n\n        case '(':\n        case '{':\n          /* $(...) or ${...} is the general case of substitution.  */\n          {\n            char openparen = *p;\n            char closeparen = (openparen == '(') ? ')' : '}';\n            const char *beg = p + 1;\n            char *abeg = NULL;\n            const char *end, *colon;\n\n            if (handle_function (&o, &p))\n              break;\n\n            /* Is there a variable reference inside the parens or braces?\n               If so, expand it before expanding the entire reference.  */\n\n            end = strchr (beg, closeparen);\n            if (end == NULL)\n              /* Unterminated variable reference.  */\n              O (fatal, *expanding_var, _(\"unterminated variable reference\"));\n            p1 = lindex (beg, end, '$');\n            if (p1 != NULL)\n              {\n                /* BEG now points past the opening paren or brace.\n                   Count parens or braces until it is matched.  */\n                int count = 1;\n                for (p = beg; *p != '\\0'; ++p)\n                  {\n                    if (*p == openparen)\n                      ++count;\n                    else if (*p == closeparen && --count == 0)\n                      break;\n                  }\n                /* If COUNT is > 0, there were unmatched opening parens\n                   or braces, so we go to the simple case of a variable name\n                   such as '$($(a)'.  */\n                if (count == 0)\n                  {\n                    /* Expand the name.  */\n                    abeg = expand_argument (beg, p);\n                    beg = abeg;\n                    end = strchr (beg, '\\0');\n                  }\n              }\n            else\n              /* Advance P to the end of this reference.  After we are\n                 finished expanding this one, P will be incremented to\n                 continue the scan.  */\n              p = end;\n\n            /* This is not a reference to a built-in function and\n               any variable references inside are now expanded.\n               Is the resultant text a substitution reference?  */\n\n            colon = lindex (beg, end, ':');\n            if (colon)\n              {\n                /* This looks like a substitution reference: $(FOO:A=B).  */\n                const char *subst_beg = colon + 1;\n                const char *subst_end = lindex (subst_beg, end, '=');\n                if (subst_end == 0)\n                  /* There is no = in sight.  Punt on the substitution\n                     reference and treat this as a variable name containing\n                     a colon, in the code below.  */\n                  colon = 0;\n                else\n                  {\n                    const char *replace_beg = subst_end + 1;\n                    const char *replace_end = end;\n\n                    /* Extract the variable name before the colon\n                       and look up that variable.  */\n                    v = lookup_variable (beg, colon - beg);\n                    if (v == 0)\n                      warn_undefined (beg, colon - beg);\n\n                    /* If the variable is not empty, perform the\n                       substitution.  */\n                    if (v != 0 && *v->value != '\\0')\n                      {\n                        char *pattern, *replace, *ppercent, *rpercent;\n                        char *value = (v->recursive\n                                       ? recursively_expand (v)\n                                       : v->value);\n\n                        /* Copy the pattern and the replacement.  Add in an\n                           extra % at the beginning to use in case there\n                           isn't one in the pattern.  */\n                        pattern = alloca (subst_end - subst_beg + 2);\n                        *(pattern++) = '%';\n                        memcpy (pattern, subst_beg, subst_end - subst_beg);\n                        pattern[subst_end - subst_beg] = '\\0';\n\n                        replace = alloca (replace_end - replace_beg + 2);\n                        *(replace++) = '%';\n                        memcpy (replace, replace_beg,\n                               replace_end - replace_beg);\n                        replace[replace_end - replace_beg] = '\\0';\n\n                        /* Look for %.  Set the percent pointers properly\n                           based on whether we find one or not.  */\n                        ppercent = find_percent (pattern);\n                        if (ppercent)\n                          {\n                            ++ppercent;\n                            rpercent = find_percent (replace);\n                            if (rpercent)\n                              ++rpercent;\n                          }\n                        else\n                          {\n                            ppercent = pattern;\n                            rpercent = replace;\n                            --pattern;\n                            --replace;\n                          }\n\n                        o = patsubst_expand_pat (o, value, pattern, replace,\n                                                 ppercent, rpercent);\n\n                        if (v->recursive)\n                          free (value);\n                      }\n                  }\n              }\n\n            if (colon == 0)\n              /* This is an ordinary variable reference.\n                 Look up the value of the variable.  */\n                o = expand_variable_output (o, beg, end - beg);\n\n            free (abeg);\n          }\n          break;\n\n        default:\n          if (ISSPACE (p[-1]))\n            break;\n\n          /* A $ followed by a random char is a variable reference:\n             $a is equivalent to $(a).  */\n          o = expand_variable_output (o, p, 1);\n\n          break;\n        }\n\n      if (*p == '\\0')\n        break;\n\n      ++p;\n    }\n\n  free (save);\n\n  return (variable_buffer + line_offset);\n}\n\f\n\n/* Expand an argument for an expansion function.\n   The text starting at STR and ending at END is variable-expanded\n   into a null-terminated string that is returned as the value.\n   This is done without clobbering 'variable_buffer' or the current\n   variable-expansion that is in progress.  */\n\nchar *\nexpand_argument (const char *str, const char *end)\n{\n  char *tmp, *alloc = NULL;\n  char *r;\n\n  if (str == end)\n    return xstrdup (\"\");\n\n  if (!end || *end == '\\0')\n    return allocated_expand_string (str);\n\n  if (end - str + 1 > 1000)\n    tmp = alloc = xmalloc (end - str + 1);\n  else\n    tmp = alloca (end - str + 1);\n\n  memcpy (tmp, str, end - str);\n  tmp[end - str] = '\\0';\n\n  r = allocated_expand_string (tmp);\n\n  free (alloc);\n\n  return r;\n}\n\f\n\n/* Expand STRING for FILE, into the current variable_buffer.\n   Error messages refer to the file and line where FILE's commands were found.\n   Expansion uses FILE's variable set list.  */\n\nchar *\nexpand_string_for_file (const char *string, struct file *file)\n{\n  char *result;\n  struct variable_set_list *savev;\n  const floc *savef;\n\n  if (!file)\n    return expand_string (string);\n\n  install_file_context (file, &savev, &savef);\n\n  result = expand_string (string);\n\n  restore_file_context (savev, savef);\n\n  return result;\n}\n\n/* Like expand_string_for_file, but the returned string is malloc'd.  */\n\nchar *\nallocated_expand_string_for_file (const char *string, struct file *file)\n{\n  char *obuf;\n  size_t olen;\n\n  install_variable_buffer (&obuf, &olen);\n\n  expand_string_for_file (string, file);\n\n  return swap_variable_buffer (obuf, olen);\n}\n\f\n/* Like allocated_expand_string, but for += target-specific variables.\n   First recursively construct the variable value from its appended parts in\n   any upper variable sets.  Then expand the resulting value.  */\n\nstatic char *\nvariable_append (const char *name, size_t length,\n                 const struct variable_set_list *set, int local)\n{\n  const struct variable *v;\n  char *buf = 0;\n  int nextlocal;\n\n  /* If there's nothing left to check, return the empty buffer.  */\n  if (!set)\n    return initialize_variable_output ();\n\n  /* If this set is local and the next is not a parent, then next is local.  */\n  nextlocal = local && set->next_is_parent == 0;\n\n  /* Try to find the variable in this variable set.  */\n  v = lookup_variable_in_set (name, length, set->set);\n\n  /* If there isn't one, or this one is private, try the set above us.  */\n  if (!v || (!local && v->private_var))\n    return variable_append (name, length, set->next, nextlocal);\n\n  /* If this variable type is append, first get any upper values.\n     If not, initialize the buffer.  */\n  if (v->append)\n    buf = variable_append (name, length, set->next, nextlocal);\n  else\n    buf = initialize_variable_output ();\n\n  /* Append this value to the buffer, and return it.\n     If we already have a value, first add a space.  */\n  if (buf > variable_buffer)\n    buf = variable_buffer_output (buf, \" \", 1);\n\n  /* Either expand it or copy it, depending.  */\n  if (! v->recursive)\n    return variable_buffer_output (buf, v->value, strlen (v->value));\n\n  buf = expand_string_buf (buf, v->value, strlen (v->value));\n  return (buf + strlen (buf));\n}\n\n\nstatic char *\nallocated_variable_append (const struct variable *v)\n{\n  /* Construct the appended variable value.  */\n  char *obuf;\n  size_t olen;\n\n  install_variable_buffer (&obuf, &olen);\n\n  variable_append (v->name, strlen (v->name), current_variable_set_list, 1);\n\n  return swap_variable_buffer (obuf, olen);\n}\n"
  },
  {
    "path": "src/file.c",
    "content": "/* Target file management for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"variable.h\"\n#include \"debug.h\"\n#include \"hash.h\"\n#include \"shuffle.h\"\n#include \"rule.h\"\n\n\n/* Remember whether snap_deps has been invoked: we need this to be sure we\n   don't add new rules (via $(eval ...)) afterwards.  In the future it would\n   be nice to support this, but it means we'd need to re-run snap_deps() or\n   at least its functionality... it might mean changing snap_deps() to be run\n   per-file, so we can invoke it after the eval... or remembering which files\n   in the hash have been snapped (a new boolean flag?) and having snap_deps()\n   only work on files which have not yet been snapped. */\nint snapped_deps = 0;\n\n/* Hash table of files the makefile knows how to make.  */\n\nstatic unsigned long\nfile_hash_1 (const void *key)\n{\n  return_ISTRING_HASH_1 (((struct file const *) key)->hname);\n}\n\nstatic unsigned long\nfile_hash_2 (const void *key)\n{\n  return_ISTRING_HASH_2 (((struct file const *) key)->hname);\n}\n\nstatic int\nfile_hash_cmp (const void *x, const void *y)\n{\n  return_ISTRING_COMPARE (((struct file const *) x)->hname,\n                          ((struct file const *) y)->hname);\n}\n\nstatic struct hash_table files;\n\n/* We can't free files we take out of the hash table, because they are still\n   likely pointed to in various places.  The check_renamed() will be used if\n   we come across these, to find the new correct file.  This is mainly to\n   prevent leak checkers from complaining.  */\nstatic struct file **rehashed_files = NULL;\nstatic size_t rehashed_files_len = 0;\n#define REHASHED_FILES_INCR 5\n\n/* Whether or not .SECONDARY with no prerequisites was given.  */\nstatic int all_secondary = 0;\n\n/* Access the hash table of all file records.\n   lookup_file  given a name, return the struct file * for that name,\n                or nil if there is none.\n*/\n\nstruct file *\nlookup_file (const char *name)\n{\n  struct file *f;\n  struct file file_key;\n#if MK_OS_VMS\n  int want_vmsify;\n#ifndef WANT_CASE_SENSITIVE_TARGETS\n  char *lname;\n#endif\n#endif\n\n  assert (*name != '\\0');\n\n  /* This is also done in parse_file_seq, so this is redundant\n     for names read from makefiles.  It is here for names passed\n     on the command line.  */\n#if MK_OS_VMS\n   want_vmsify = (strpbrk (name, \"]>:^\") != NULL);\n# ifndef WANT_CASE_SENSITIVE_TARGETS\n  if (*name != '.')\n    {\n      const char *n;\n      char *ln;\n      lname = xstrdup (name);\n      for (n = name, ln = lname; *n != '\\0'; ++n, ++ln)\n        *ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;\n      *ln = '\\0';\n      name = lname;\n    }\n# endif\n\n  while (name[0] == '[' && name[1] == ']' && name[2] != '\\0')\n      name += 2;\n  while (name[0] == '<' && name[1] == '>' && name[2] != '\\0')\n      name += 2;\n#endif\n  while (name[0] == '.' && ISDIRSEP (name[1]) && name[2] != '\\0')\n    {\n      name += 2;\n      while (ISDIRSEP (*name))\n        /* Skip following slashes: \".//foo\" is \"foo\", not \"/foo\".  */\n        ++name;\n    }\n\n  if (*name == '\\0')\n    {\n      /* It was all slashes after a dot.  */\n      name = \"./\";\n#if MK_OS_VMS\n      /* TODO - This section is probably not needed. */\n      if (want_vmsify)\n        name = \"[]\";\n#endif\n    }\n  file_key.hname = name;\n  f = hash_find_item (&files, &file_key);\n#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS)\n  if (*name != '.')\n    free (lname);\n#endif\n\n  return f;\n}\n\n/* Look up a file record for file NAME and return it.\n   Create a new record if one doesn't exist.  NAME will be stored in the\n   new record so it should be constant or in the strcache etc.\n */\n\nstruct file *\nenter_file (const char *name)\n{\n  struct file *f;\n  struct file *new;\n  struct file **file_slot;\n  struct file file_key;\n\n  assert (*name != '\\0');\n  assert (! verify_flag || strcache_iscached (name));\n\n#if MK_OS_VMS && !defined(WANT_CASE_SENSITIVE_TARGETS)\n  if (*name != '.')\n    {\n      const char *n;\n      char *lname, *ln;\n      lname = xstrdup (name);\n      for (n = name, ln = lname; *n != '\\0'; ++n, ++ln)\n        if (isupper ((unsigned char)*n))\n          *ln = tolower ((unsigned char)*n);\n        else\n          *ln = *n;\n\n      *ln = '\\0';\n      name = strcache_add (lname);\n      free (lname);\n    }\n#endif\n\n  file_key.hname = name;\n  file_slot = (struct file **) hash_find_slot (&files, &file_key);\n  f = *file_slot;\n  if (! HASH_VACANT (f) && !f->double_colon)\n    {\n      f->builtin = 0;\n      return f;\n    }\n\n  new = xcalloc (sizeof (struct file));\n  new->name = new->hname = name;\n  new->update_status = us_none;\n\n  if (HASH_VACANT (f))\n    {\n      new->last = new;\n      hash_insert_at (&files, new, file_slot);\n    }\n  else\n    {\n      /* There is already a double-colon entry for this file.  */\n      new->double_colon = f;\n      f->last->prev = new;\n      f->last = new;\n    }\n\n  return new;\n}\n\f\n/* Rehash FILE to NAME.  This is not as simple as resetting\n   the 'hname' member, since it must be put in a new hash bucket,\n   and possibly merged with an existing file called NAME.  */\n\nvoid\nrehash_file (struct file *from_file, const char *to_hname)\n{\n  struct file file_key;\n  struct file **file_slot;\n  struct file *to_file;\n  struct file *deleted_file;\n  struct file *f;\n\n  /* If it's already that name, we're done.  */\n  from_file->builtin = 0;\n  file_key.hname = to_hname;\n  if (! file_hash_cmp (from_file, &file_key))\n    return;\n\n  /* Find the end of the renamed list for the \"from\" file.  */\n  file_key.hname = from_file->hname;\n  check_renamed (from_file);\n  if (file_hash_cmp (from_file, &file_key))\n    /* hname changed unexpectedly!! */\n    abort ();\n\n  /* Remove the \"from\" file from the hash.  */\n  deleted_file = hash_delete (&files, from_file);\n  if (deleted_file != from_file)\n    /* from_file isn't the one stored in files */\n    abort ();\n\n  /* Find where the newly renamed file will go in the hash.  */\n  file_key.hname = to_hname;\n  file_slot = (struct file **) hash_find_slot (&files, &file_key);\n  to_file = *file_slot;\n\n  /* Change the hash name for this file.  */\n  from_file->hname = to_hname;\n  for (f = from_file->double_colon; f != 0; f = f->prev)\n    f->hname = to_hname;\n\n  /* If the new name doesn't exist yet just set it to the renamed file.  */\n  if (HASH_VACANT (to_file))\n    {\n      hash_insert_at (&files, from_file, file_slot);\n      return;\n    }\n\n  /* TO_FILE already exists under TO_HNAME.\n     We must retain TO_FILE and merge FROM_FILE into it.  */\n\n  if (from_file->cmds != 0)\n    {\n      if (to_file->cmds == 0)\n        to_file->cmds = from_file->cmds;\n      else if (from_file->cmds != to_file->cmds)\n        {\n          size_t l = strlen (from_file->name);\n          /* We have two sets of commands.  We will go with the\n             one given in the rule found through directory search,\n             but give a message to let the user know what's going on.  */\n          if (to_file->cmds->fileinfo.filenm != 0)\n            error (&from_file->cmds->fileinfo,\n                   l + strlen (to_file->cmds->fileinfo.filenm) + INTSTR_LENGTH,\n                   _(\"recipe was specified for file '%s' at %s:%lu,\"),\n                   from_file->name, from_file->cmds->fileinfo.filenm,\n                   from_file->cmds->fileinfo.lineno);\n          else\n            error (&from_file->cmds->fileinfo, l,\n                   _(\"recipe for file '%s' was found by implicit rule search,\"),\n                   from_file->name);\n          l += strlen (to_hname);\n          error (&from_file->cmds->fileinfo, l,\n                 _(\"but '%s' is now considered the same file as '%s'\"),\n                 from_file->name, to_hname);\n          error (&from_file->cmds->fileinfo, l,\n                 _(\"recipe for '%s' will be ignored in favor of the one for '%s'\"),\n                 from_file->name, to_hname);\n        }\n    }\n\n  /* Merge the dependencies of the two files.  */\n\n  if (to_file->deps == 0)\n    to_file->deps = from_file->deps;\n  else\n    {\n      struct dep *deps = to_file->deps;\n      while (deps->next != 0)\n        deps = deps->next;\n      deps->next = from_file->deps;\n    }\n\n  merge_variable_set_lists (&to_file->variables, from_file->variables);\n\n  if (to_file->double_colon && from_file->is_target && !from_file->double_colon)\n    OSS (fatal, NILF, _(\"can't rename single-colon '%s' to double-colon '%s'\"),\n         from_file->name, to_hname);\n  if (!to_file->double_colon  && from_file->double_colon)\n    {\n      if (to_file->is_target)\n        OSS (fatal, NILF,\n             _(\"can't rename double-colon '%s' to single-colon '%s'\"),\n             from_file->name, to_hname);\n      else\n        to_file->double_colon = from_file->double_colon;\n    }\n\n  if (from_file->last_mtime > to_file->last_mtime)\n    /* %%% Kludge so -W wins on a file that gets vpathized.  */\n    to_file->last_mtime = from_file->last_mtime;\n\n  to_file->mtime_before_update = from_file->mtime_before_update;\n\n#define MERGE(field) to_file->field |= from_file->field\n  MERGE (precious);\n  MERGE (loaded);\n  MERGE (tried_implicit);\n  MERGE (updating);\n  MERGE (updated);\n  MERGE (is_target);\n  MERGE (cmd_target);\n  MERGE (phony);\n  /* Don't merge intermediate because this file might be pre-existing */\n  MERGE (is_explicit);\n  MERGE (secondary);\n  MERGE (notintermediate);\n  MERGE (ignore_vpath);\n  MERGE (snapped);\n  MERGE (suffix);\n#undef MERGE\n\n  to_file->builtin = 0;\n  from_file->renamed = to_file;\n\n  if (rehashed_files_len % REHASHED_FILES_INCR == 0)\n    rehashed_files = xrealloc (rehashed_files,\n                               sizeof (struct file *) * (rehashed_files_len + REHASHED_FILES_INCR));\n\n  rehashed_files[rehashed_files_len++] = from_file;\n}\n\n/* Rename FILE to NAME.  This is not as simple as resetting\n   the 'name' member, since it must be put in a new hash bucket,\n   and possibly merged with an existing file called NAME.  */\n\nvoid\nrename_file (struct file *from_file, const char *to_hname)\n{\n  rehash_file (from_file, to_hname);\n  while (from_file)\n    {\n      from_file->name = from_file->hname;\n      from_file = from_file->prev;\n    }\n}\n\f\n/* Remove all nonprecious intermediate files.\n   If SIG is nonzero, this was caused by a fatal signal,\n   meaning that a different message will be printed, and\n   the message will go to stderr rather than stdout.  */\n\nvoid\nremove_intermediates (int sig)\n{\n  struct file **file_slot;\n  struct file **file_end;\n  int doneany = 0;\n\n  /* If there's no way we will ever remove anything anyway, punt early.  */\n  if (question_flag || touch_flag || all_secondary || no_intermediates)\n    return;\n\n  if (sig && just_print_flag)\n    return;\n\n  file_slot = (struct file **) files.ht_vec;\n  file_end = file_slot + files.ht_size;\n  for ( ; file_slot < file_end; file_slot++)\n    if (! HASH_VACANT (*file_slot))\n      {\n        struct file *f = *file_slot;\n        /* Is this file eligible for automatic deletion?\n           Yes, IFF: it's marked intermediate, it's not secondary, it wasn't\n           given on the command line, and it's either a -include makefile or\n           it's not precious.  */\n        if (f->intermediate && (f->dontcare || !f->precious)\n            && !f->secondary && !f->notintermediate && !f->cmd_target)\n          {\n            int status;\n            if (f->update_status == us_none)\n              /* If nothing would have created this file yet,\n                 don't print an \"rm\" command for it.  */\n              continue;\n            if (just_print_flag)\n              status = 0;\n            else\n              {\n                status = unlink (f->name);\n                if (status < 0 && errno == ENOENT)\n                  continue;\n              }\n            if (!f->dontcare)\n              {\n                if (sig)\n                  OS (error, NILF,\n                      _(\"*** deleting intermediate file '%s'\"), f->name);\n                else\n                  {\n                    if (! doneany)\n                      DB (DB_BASIC, (_(\"Removing intermediate files...\\n\")));\n                    if (!run_silent)\n                      {\n                        if (! doneany)\n                          {\n                            fputs (\"rm \", stdout);\n                            doneany = 1;\n                          }\n                        else\n                          putchar (' ');\n                        fputs (f->name, stdout);\n                        fflush (stdout);\n                      }\n                  }\n                if (status < 0)\n                  {\n                    perror_with_name (\"\\nunlink: \", f->name);\n                    /* Start printing over.  */\n                    doneany = 0;\n                  }\n              }\n          }\n      }\n\n  if (doneany && !sig)\n    {\n      putchar ('\\n');\n      fflush (stdout);\n    }\n}\n\f\n/* Given a string containing prerequisites (fully expanded), break it up into\n   a struct dep list.  Enter each of these prereqs into the file database.\n */\nstruct dep *\nsplit_prereqs (char *p)\n{\n  struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL, PARSEFS_WAIT);\n\n  if (*p)\n    {\n      /* Files that follow '|' are \"order-only\" prerequisites that satisfy the\n         dependency by existing: their modification times are irrelevant.  */\n      struct dep *ood;\n\n      ++p;\n      ood = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL, PARSEFS_WAIT);\n\n      if (! new)\n        new = ood;\n      else\n        {\n          struct dep *dp;\n          for (dp = new; dp->next != NULL; dp = dp->next)\n            ;\n          dp->next = ood;\n        }\n\n      for (; ood != NULL; ood = ood->next)\n        ood->ignore_mtime = 1;\n    }\n\n  return new;\n}\n\n/* Given a list of prerequisites, enter them into the file database.\n   If STEM is set then first expand patterns using STEM.  */\nstruct dep *\nenter_prereqs (struct dep *deps, const char *stem)\n{\n  struct dep *d1;\n\n  if (deps == 0)\n    return 0;\n\n  /* If we have a stem, expand the %'s.  We use patsubst_expand to translate\n     the prerequisites' patterns into plain prerequisite names.  */\n  if (stem)\n    {\n      const char *pattern = \"%\";\n      struct dep *dp = deps, *dl = 0;\n\n      while (dp != 0)\n        {\n          char *percent;\n          size_t nl = strlen (dp->name) + 1;\n          char *nm = alloca (nl);\n          memcpy (nm, dp->name, nl);\n          percent = find_percent (nm);\n          if (percent)\n            {\n              char *o;\n\n              /* We have to handle empty stems specially, because that\n                 would be equivalent to $(patsubst %,dp->name,) which\n                 will always be empty.  */\n              if (stem[0] == '\\0')\n                {\n                  memmove (percent, percent+1, strlen (percent));\n                  o = variable_buffer_output (variable_buffer, nm,\n                                              strlen (nm) + 1);\n                }\n              else\n                o = patsubst_expand_pat (variable_buffer, stem, pattern, nm,\n                                         pattern+1, percent+1);\n\n              /* If the name expanded to the empty string, ignore it.  */\n              if (variable_buffer[0] == '\\0')\n                {\n                  struct dep *df = dp;\n                  if (dp == deps)\n                    dp = deps = deps->next;\n                  else\n                    dp = dl->next = dp->next;\n                  free_dep (df);\n                  continue;\n                }\n\n              /* Save the name.  */\n              dp->name = strcache_add_len (variable_buffer,\n                                           o - variable_buffer);\n            }\n          dp->stem = stem;\n          dp->staticpattern = 1;\n          dl = dp;\n          dp = dp->next;\n        }\n    }\n\n  /* Enter them as files, unless they need a 2nd expansion.  */\n  for (d1 = deps; d1 != 0; d1 = d1->next)\n    {\n      if (d1->need_2nd_expansion)\n        continue;\n\n      d1->file = lookup_file (d1->name);\n      if (d1->file == 0)\n        d1->file = enter_file (d1->name);\n      d1->staticpattern = 0;\n      d1->name = 0;\n      if (!stem)\n        /* This file is explicitly mentioned as a prereq.  */\n        d1->file->is_explicit = 1;\n    }\n\n  return deps;\n}\n\n/* Expand and parse each dependency line.\n   For each dependency of the file, make the 'struct dep' point\n   at the appropriate 'struct file' (which may have to be created).  */\nvoid\nexpand_deps (struct file *f)\n{\n  struct dep *d;\n  struct dep **dp;\n  const char *fstem;\n  int initialized = 0;\n  int changed_dep = 0;\n\n  if (f->snapped)\n    return;\n  f->snapped = 1;\n\n  /* Walk through the dependencies.  For any dependency that needs 2nd\n     expansion, expand it then insert the result into the list.  */\n  dp = &f->deps;\n  d = f->deps;\n  while (d != 0)\n    {\n      char *p;\n      struct dep *new, *next;\n\n      if (! d->name || ! d->need_2nd_expansion)\n        {\n          /* This one is all set already.  */\n          dp = &d->next;\n          d = d->next;\n          continue;\n        }\n\n      /* If it's from a static pattern rule, convert the initial pattern in\n         each word to \"$*\" so they'll expand properly.  */\n      if (d->staticpattern)\n        {\n          const char *cs = d->name;\n          size_t nperc = 0;\n\n          /* Count the number of % in the string.  */\n          while ((cs = strchr (cs, '%')) != NULL)\n            {\n              ++nperc;\n              ++cs;\n            }\n\n          if (nperc)\n            {\n              /* Allocate enough space to replace all % with $*.  */\n              size_t slen = strlen (d->name) + nperc + 1;\n              const char *pcs = d->name;\n              char *name = xmalloc (slen);\n              char *s = name;\n\n              /* Substitute the first % in each word.  */\n              cs = strchr (pcs, '%');\n\n              while (cs)\n                {\n                  s = mempcpy (s, pcs, cs - pcs);\n                  *(s++) = '$';\n                  *(s++) = '*';\n                  pcs = ++cs;\n\n                  /* Find the first % after the next whitespace.  */\n                  cs = strchr (end_of_token (cs), '%');\n                }\n              strcpy (s, pcs);\n\n              free ((char*)d->name);\n              d->name = name;\n            }\n        }\n\n      /* We're going to do second expansion so initialize file variables for\n         the file. Since the stem for static pattern rules comes from\n         individual dep lines, we will temporarily set f->stem to d->stem.  */\n      if (!initialized)\n        {\n          initialize_file_variables (f, 0);\n          initialized = 1;\n        }\n\n      set_file_variables (f, d->stem ? d->stem : f->stem);\n\n      /* Perform second expansion.  */\n      p = expand_string_for_file (d->name, f);\n\n      /* Free the un-expanded name.  */\n      free ((char*)d->name);\n\n      /* Parse the prerequisites and enter them into the file database.  */\n      new = split_prereqs (p);\n\n      /* If there were no prereqs here (blank!) then throw this one out.  */\n      if (new == 0)\n        {\n          *dp = d->next;\n          changed_dep = 1;\n          free_dep (d);\n          d = *dp;\n          continue;\n        }\n\n      /* Add newly parsed prerequisites.  */\n      fstem = d->stem;\n      next = d->next;\n      changed_dep = 1;\n      free_dep (d);\n      *dp = new;\n      for (dp = &new, d = new; d != 0; dp = &d->next, d = d->next)\n        {\n          d->file = lookup_file (d->name);\n          if (d->file == 0)\n            d->file = enter_file (d->name);\n          d->name = 0;\n          d->stem = fstem;\n          if (!fstem)\n            /* This file is explicitly mentioned as a prereq.  */\n            d->file->is_explicit = 1;\n        }\n      *dp = next;\n      d = *dp;\n    }\n\n    /* Shuffle mode assumes '->next' and '->shuf' links both traverse the same\n       dependencies (in different sequences).  Regenerate '->shuf' so we don't\n       refer to stale data.  */\n    if (changed_dep)\n      shuffle_deps_recursive (f->deps);\n}\n\n/* Add extra prereqs to the file in question.  */\n\nstruct dep *\nexpand_extra_prereqs (const struct variable *extra)\n{\n  struct dep *d;\n  struct dep *prereqs = extra ? split_prereqs (expand_string (extra->value)) : NULL;\n\n  for (d = prereqs; d; d = d->next)\n    {\n      d->file = lookup_file (d->name);\n      if (!d->file)\n        d->file = enter_file (d->name);\n      d->name = NULL;\n      d->ignore_automatic_vars = 1;\n    }\n\n  return prereqs;\n}\n\n/* Perform per-file snap operations. */\n\nstatic void\nsnap_file (const void *item, void *arg)\n{\n  struct file *f = (struct file*)item;\n  struct dep *prereqs = NULL;\n  struct dep *d;\n\n  /* If we're not doing second expansion then reset updating.  */\n  if (!second_expansion)\n    f->updating = 0;\n\n  /* More specific setting has priority.  */\n\n  /* If .SECONDARY is set with no deps, mark all targets as intermediate,\n     unless the target is a prereq of .NOTINTERMEDIATE.  */\n  if (all_secondary && !f->notintermediate)\n    f->intermediate = 1;\n\n  /* If .NOTINTERMEDIATE is set with no deps, mark all targets as\n     notintermediate, unless the target is a prereq of .INTERMEDIATE.  */\n  if (no_intermediates && !f->intermediate && !f->secondary)\n    f->notintermediate = 1;\n\n  /* If .EXTRA_PREREQS is set, add them as ignored by automatic variables.  */\n  if (f->variables)\n    {\n      prereqs = expand_extra_prereqs (lookup_variable_in_set (\n                      STRING_SIZE_TUPLE(\".EXTRA_PREREQS\"), f->variables->set));\n      if (second_expansion)\n        for (d = prereqs; d; d = d->next)\n          {\n            if (!d->name)\n              d->name = xstrdup (d->file->name);\n            d->need_2nd_expansion = 1;\n          }\n    }\n  else if (f->is_target)\n    prereqs = copy_dep_chain (arg);\n\n  if (prereqs)\n    {\n      for (d = prereqs; d; d = d->next)\n        if (streq (f->name, dep_name (d)))\n          /* Skip circular dependencies.  */\n          break;\n\n      if (d)\n        /* We broke early: must have found a circular dependency.  */\n        free_dep_chain (prereqs);\n      else if (!f->deps)\n        f->deps = prereqs;\n      else\n        {\n          d = f->deps;\n          while (d->next)\n            d = d->next;\n          d->next = prereqs;\n        }\n    }\n}\n\n/* Mark the files depended on by .PRECIOUS, .PHONY, .SILENT,\n   and various other special targets.  */\n\nvoid\nsnap_deps (void)\n{\n  struct file *f;\n  struct file *f2;\n  struct dep *d;\n\n  /* Remember that we've done this.  Once we start snapping deps we can no\n     longer define new targets.  */\n  snapped_deps = 1;\n\n  /* Now manage all the special targets.  */\n\n  for (f = lookup_file (\".PRECIOUS\"); f != 0; f = f->prev)\n    for (d = f->deps; d != 0; d = d->next)\n      for (f2 = d->file; f2 != 0; f2 = f2->prev)\n        f2->precious = 1;\n\n  for (f = lookup_file (\".LOW_RESOLUTION_TIME\"); f != 0; f = f->prev)\n    for (d = f->deps; d != 0; d = d->next)\n      for (f2 = d->file; f2 != 0; f2 = f2->prev)\n        f2->low_resolution_time = 1;\n\n  for (f = lookup_file (\".PHONY\"); f != 0; f = f->prev)\n    for (d = f->deps; d != 0; d = d->next)\n      for (f2 = d->file; f2 != 0; f2 = f2->prev)\n        {\n          /* Mark this file as phony nonexistent target.  */\n          f2->phony = 1;\n          f2->is_target = 1;\n          f2->last_mtime = NONEXISTENT_MTIME;\n          f2->mtime_before_update = NONEXISTENT_MTIME;\n        }\n\n  for (f = lookup_file (\".NOTINTERMEDIATE\"); f != 0; f = f->prev)\n    /* Mark .NOTINTERMEDIATE deps as notintermediate files.  */\n    if (f->deps)\n        for (d = f->deps; d != 0; d = d->next)\n          for (f2 = d->file; f2 != 0; f2 = f2->prev)\n            f2->notintermediate = 1;\n    /* .NOTINTERMEDIATE with no deps marks all files as notintermediate.  */\n    else\n      no_intermediates = 1;\n\n  /* The same file cannot be both .INTERMEDIATE and .NOTINTERMEDIATE.\n     However, it is possible for a file to be .INTERMEDIATE and also match a\n     .NOTINTERMEDIATE pattern.  In that case, the intermediate file has\n     priority over the notintermediate pattern.  This priority is enforced by\n     pattern_search.  */\n\n  for (f = lookup_file (\".INTERMEDIATE\"); f != 0; f = f->prev)\n    /* Mark .INTERMEDIATE deps as intermediate files.  */\n    for (d = f->deps; d != 0; d = d->next)\n      for (f2 = d->file; f2 != 0; f2 = f2->prev)\n        if (f2->notintermediate)\n          OS (fatal, NILF,\n              _(\"%s cannot be both .NOTINTERMEDIATE and .INTERMEDIATE\"),\n              f2->name);\n        else\n          f2->intermediate = 1;\n    /* .INTERMEDIATE with no deps does nothing.\n       Marking all files as intermediates is useless since the goal targets\n       would be deleted after they are built.  */\n\n  for (f = lookup_file (\".SECONDARY\"); f != 0; f = f->prev)\n    /* Mark .SECONDARY deps as both intermediate and secondary.  */\n    if (f->deps)\n      for (d = f->deps; d != 0; d = d->next)\n        for (f2 = d->file; f2 != 0; f2 = f2->prev)\n        if (f2->notintermediate)\n          OS (fatal, NILF,\n              _(\"%s cannot be both .NOTINTERMEDIATE and .SECONDARY\"),\n              f2->name);\n        else\n          f2->intermediate = f2->secondary = 1;\n    /* .SECONDARY with no deps listed marks *all* files that way.  */\n    else\n      all_secondary = 1;\n\n  if (no_intermediates && all_secondary)\n    O (fatal, NILF,\n       _(\".NOTINTERMEDIATE and .SECONDARY are mutually exclusive\"));\n\n  f = lookup_file (\".EXPORT_ALL_VARIABLES\");\n  if (f != 0 && f->is_target)\n    export_all_variables = 1;\n\n  f = lookup_file (\".IGNORE\");\n  if (f != 0 && f->is_target)\n    {\n      if (f->deps == 0)\n        ignore_errors_flag = 1;\n      else\n        for (d = f->deps; d != 0; d = d->next)\n          for (f2 = d->file; f2 != 0; f2 = f2->prev)\n            f2->command_flags |= COMMANDS_NOERROR;\n    }\n\n  f = lookup_file (\".SILENT\");\n  if (f != 0 && f->is_target)\n    {\n      if (f->deps == 0)\n        run_silent = 1;\n      else\n        for (d = f->deps; d != 0; d = d->next)\n          for (f2 = d->file; f2 != 0; f2 = f2->prev)\n            f2->command_flags |= COMMANDS_SILENT;\n    }\n\n  f = lookup_file (\".NOTPARALLEL\");\n  if (f != 0 && f->is_target)\n    {\n      struct dep *d2;\n\n      if (!f->deps)\n        not_parallel = 1;\n      else\n        /* Set a wait point between every prerequisite of each target.  */\n        for (d = f->deps; d != NULL; d = d->next)\n          for (f2 = d->file; f2 != NULL; f2 = f2->prev)\n            if (f2->deps)\n              for (d2 = f2->deps->next; d2 != NULL; d2 = d2->next)\n                d2->wait_here = 1;\n    }\n\n  {\n    struct dep *prereqs = expand_extra_prereqs (lookup_variable (STRING_SIZE_TUPLE(\".EXTRA_PREREQS\")));\n\n    /* Perform per-file snap operations.  */\n    hash_map_arg(&files, snap_file, prereqs);\n\n    free_dep_chain (prereqs);\n  }\n\n#ifndef NO_MINUS_C_MINUS_O\n  /* If .POSIX was defined, remove OUTPUT_OPTION to comply.  */\n  /* This needs more work: what if the user sets this in the makefile?\n  if (posix_pedantic)\n    define_variable_cname (\"OUTPUT_OPTION\", \"\", o_default, 1);\n  */\n#endif\n}\n\f\n/* Set the 'command_state' member of FILE and all its 'also_make's.\n   Don't decrease the state of also_make's (e.g., don't downgrade a 'running'\n   also_make to a 'deps_running' also_make).  */\n\nvoid\nset_command_state (struct file *file, enum cmd_state state)\n{\n  struct dep *d;\n\n  file->command_state = state;\n\n  for (d = file->also_make; d != 0; d = d->next)\n    if (state > d->file->command_state)\n      d->file->command_state = state;\n}\n\f\n/* Convert an external file timestamp to internal form.  */\n\nFILE_TIMESTAMP\nfile_timestamp_cons (const char *fname, time_t stamp, long int ns)\n{\n  int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);\n  FILE_TIMESTAMP s = stamp;\n  FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;\n  FILE_TIMESTAMP ts = product + offset;\n\n  if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)\n         && product <= ts && ts <= ORDINARY_MTIME_MAX))\n    {\n      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];\n      const char *f = fname ? fname : _(\"Current time\");\n      ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;\n      file_timestamp_sprintf (buf, ts);\n      OSS (error, NILF,\n           _(\"%s: timestamp out of range: substituting %s\"), f, buf);\n    }\n\n  return ts;\n}\n\f\n/* Return the current time as a file timestamp, setting *RESOLUTION to\n   its resolution.  */\nFILE_TIMESTAMP\nfile_timestamp_now (int *resolution)\n{\n  int r;\n  time_t s;\n  int ns;\n\n  /* Don't bother with high-resolution clocks if file timestamps have\n     only one-second resolution.  The code below should work, but it's\n     not worth the hassle of debugging it on hosts where it fails.  */\n#if FILE_TIMESTAMP_HI_RES\n# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME\n  {\n    struct timespec timespec;\n    if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)\n      {\n        r = 1;\n        s = timespec.tv_sec;\n        ns = timespec.tv_nsec;\n        goto got_time;\n      }\n  }\n# endif\n# if HAVE_GETTIMEOFDAY\n  {\n    struct timeval timeval;\n    if (gettimeofday (&timeval, 0) == 0)\n      {\n        r = 1000;\n        s = timeval.tv_sec;\n        ns = timeval.tv_usec * 1000;\n        goto got_time;\n      }\n  }\n# endif\n#endif\n\n  r = 1000000000;\n  s = time ((time_t *) 0);\n  ns = 0;\n\n#if FILE_TIMESTAMP_HI_RES\n got_time:\n#endif\n  *resolution = r;\n  return file_timestamp_cons (0, s, ns);\n}\n\n/* Place into the buffer P a printable representation of the file\n   timestamp TS.  */\nvoid\nfile_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)\n{\n  time_t t = FILE_TIMESTAMP_S (ts);\n  struct tm *tm = localtime (&t);\n\n  if (tm)\n    {\n      intmax_t year = tm->tm_year;\n      sprintf (p, \"%04\" PRIdMAX \"-%02d-%02d %02d:%02d:%02d\",\n               year + 1900, tm->tm_mon + 1, tm->tm_mday,\n               tm->tm_hour, tm->tm_min, tm->tm_sec);\n    }\n  else if (t < 0)\n    sprintf (p, \"%\" PRIdMAX, (intmax_t) t);\n  else\n    sprintf (p, \"%\" PRIuMAX, (uintmax_t) t);\n  p += strlen (p);\n\n  /* Append nanoseconds as a fraction, but remove trailing zeros.  We don't\n     know the actual timestamp resolution, since clock_getres applies only to\n     local times, whereas this timestamp might come from a remote filesystem.\n     So removing trailing zeros is the best guess that we can do.  */\n  sprintf (p, \".%09d\", FILE_TIMESTAMP_NS (ts));\n  p += strlen (p) - 1;\n  while (*p == '0')\n    p--;\n  p += *p != '.';\n\n  *p = '\\0';\n}\n\f\n/* Print the data base of files.  */\n\nstatic void\nprint_prereqs (const struct dep *deps)\n{\n  const struct dep *ood = 0;\n\n  /* Print all normal dependencies; note any order-only deps.  */\n  for (; deps != 0; deps = deps->next)\n    if (! deps->ignore_mtime)\n      printf (\" %s%s\", deps->wait_here ? \".WAIT \" : \"\", dep_name (deps));\n    else if (! ood)\n      ood = deps;\n\n  /* Print order-only deps, if we have any.  */\n  if (ood)\n    {\n      printf (\" | %s%s\", ood->wait_here ? \".WAIT \" : \"\", dep_name (ood));\n      for (ood = ood->next; ood != 0; ood = ood->next)\n        if (ood->ignore_mtime)\n          printf (\" %s%s\", ood->wait_here ? \".WAIT \" : \"\", dep_name (ood));\n    }\n\n  putchar ('\\n');\n}\n\nstatic void\nprint_file (const void *item)\n{\n  const struct file *f = item;\n\n  /* If we're not using builtin targets, don't show them.\n\n     Ideally we'd be able to delete them altogether but currently there's no\n     facility to ever delete a file once it's been added.  */\n  if (no_builtin_rules_flag && f->builtin)\n    return;\n\n  putchar ('\\n');\n\n  if (f->cmds && f->cmds->recipe_prefix != cmd_prefix)\n    {\n      fputs (\".RECIPEPREFIX = \", stdout);\n      cmd_prefix = f->cmds->recipe_prefix;\n      if (cmd_prefix != RECIPEPREFIX_DEFAULT)\n        putchar (cmd_prefix);\n      putchar ('\\n');\n    }\n\n  if (f->variables != 0)\n    print_target_variables (f);\n\n  if (!f->is_target)\n    puts (_(\"# Not a target:\"));\n  printf (\"%s:%s\", f->name, f->double_colon ? \":\" : \"\");\n  print_prereqs (f->deps);\n\n  if (f->precious)\n    puts (_(\"#  Precious file (prerequisite of .PRECIOUS).\"));\n  if (f->phony)\n    puts (_(\"#  Phony target (prerequisite of .PHONY).\"));\n  if (f->cmd_target)\n    puts (_(\"#  Command line target.\"));\n  if (f->dontcare)\n    puts (_(\"#  A default, MAKEFILES, or -include/sinclude makefile.\"));\n  if (f->builtin)\n    puts (_(\"#  Builtin rule\"));\n  puts (f->tried_implicit\n        ? _(\"#  Implicit rule search has been done.\")\n        : _(\"#  Implicit rule search has not been done.\"));\n  if (f->stem != 0)\n    printf (_(\"#  Implicit/static pattern stem: '%s'\\n\"), f->stem);\n  if (f->intermediate)\n    puts (_(\"#  File is an intermediate prerequisite.\"));\n  if (f->notintermediate)\n    puts (_(\"#  File is a prerequisite of .NOTINTERMEDIATE.\"));\n  if (f->secondary)\n    puts (_(\"#  File is secondary (prerequisite of .SECONDARY).\"));\n  if (f->also_make != 0)\n    {\n      const struct dep *d;\n      fputs (_(\"#  Also makes:\"), stdout);\n      for (d = f->also_make; d != 0; d = d->next)\n        printf (\" %s\", dep_name (d));\n      putchar ('\\n');\n    }\n  if (f->last_mtime == UNKNOWN_MTIME)\n    puts (_(\"#  Modification time never checked.\"));\n  else if (f->last_mtime == NONEXISTENT_MTIME)\n    puts (_(\"#  File does not exist.\"));\n  else if (f->last_mtime == OLD_MTIME)\n    puts (_(\"#  File is very old.\"));\n  else\n    {\n      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];\n      file_timestamp_sprintf (buf, f->last_mtime);\n      printf (_(\"#  Last modified %s\\n\"), buf);\n    }\n  puts (f->updated\n        ? _(\"#  File has been updated.\") : _(\"#  File has not been updated.\"));\n  switch (f->command_state)\n    {\n    case cs_running:\n      puts (_(\"#  Recipe currently running (THIS IS A BUG).\"));\n      break;\n    case cs_deps_running:\n      puts (_(\"#  Dependencies recipe running (THIS IS A BUG).\"));\n      break;\n    case cs_not_started:\n    case cs_finished:\n      switch (f->update_status)\n        {\n        case us_none:\n          break;\n        case us_success:\n          puts (_(\"#  Successfully updated.\"));\n          break;\n        case us_question:\n          assert (question_flag);\n          puts (_(\"#  Needs to be updated (-q is set).\"));\n          break;\n        case us_failed:\n          puts (_(\"#  Failed to be updated.\"));\n          break;\n        }\n      break;\n    default:\n      puts (_(\"#  Invalid value in 'command_state' member!\"));\n      fflush (stdout);\n      fflush (stderr);\n      abort ();\n    }\n\n  if (f->variables != 0)\n    print_file_variables (f);\n\n  if (f->cmds != 0)\n    print_commands (f->cmds);\n\n  if (f->prev)\n    print_file ((const void *) f->prev);\n}\n\nvoid\nprint_file_data_base (void)\n{\n  puts (_(\"\\n# Files\"));\n\n  hash_map (&files, print_file);\n\n  fputs (_(\"\\n# files hash-table stats:\\n# \"), stdout);\n  hash_print_stats (&files, stdout);\n}\n\nstatic void\nprint_target (const void *item)\n{\n  const struct file *f = item;\n\n  if (!f->is_target || f->suffix)\n    return;\n\n  /* Ignore any special targets, as defined by POSIX. */\n  if (f->name[0] == '.' && isupper ((unsigned char)f->name[1]))\n    {\n      const char *cp = f->name + 1;\n      while (*(++cp) != '\\0')\n        if (!isupper ((unsigned char)*cp))\n          break;\n      if (*cp == '\\0')\n        return;\n    }\n\n  puts (f->name);\n}\n\nvoid\nprint_targets (void)\n{\n  hash_map (&files, print_target);\n}\n\f\n/* Verify the integrity of the data base of files.  */\n\n#define VERIFY_CACHED(_p,_n) \\\n    do{                                                                       \\\n        if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n))               \\\n          error (NULL, strlen (_p->name) + CSTRLEN (# _n) + strlen (_p->_n),  \\\n                 _(\"%s: field '%s' not cached: %s\"), _p->name, # _n, _p->_n); \\\n    }while(0)\n\nstatic void\nverify_file (const void *item)\n{\n  const struct file *f = item;\n  const struct dep *d;\n\n  VERIFY_CACHED (f, name);\n  VERIFY_CACHED (f, hname);\n  VERIFY_CACHED (f, vpath);\n  VERIFY_CACHED (f, stem);\n\n  /* Check the deps.  */\n  for (d = f->deps; d != 0; d = d->next)\n    {\n      if (! d->need_2nd_expansion)\n        VERIFY_CACHED (d, name);\n      VERIFY_CACHED (d, stem);\n    }\n}\n\nvoid\nverify_file_data_base (void)\n{\n  hash_map (&files, verify_file);\n}\n\n#define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500)\n\nchar *\nbuild_target_list (char *value)\n{\n  static unsigned long last_targ_count = 0;\n\n  if (files.ht_fill != last_targ_count)\n    {\n      size_t max = EXPANSION_INCREMENT (strlen (value));\n      size_t len;\n      char *p;\n      struct file **fp = (struct file **) files.ht_vec;\n      struct file **end = &fp[files.ht_size];\n\n      /* Make sure we have at least MAX bytes in the allocated buffer.  */\n      value = xrealloc (value, max);\n\n      p = value;\n      len = 0;\n      for (; fp < end; ++fp)\n        if (!HASH_VACANT (*fp) && (*fp)->is_target)\n          {\n            struct file *f = *fp;\n            size_t l = strlen (f->name);\n\n            len += l + 1;\n            if (len > max)\n              {\n                size_t off = p - value;\n\n                max += EXPANSION_INCREMENT (l + 1);\n                value = xrealloc (value, max);\n                p = &value[off];\n              }\n\n            p = mempcpy (p, f->name, l);\n            *(p++) = ' ';\n          }\n      *(p-1) = '\\0';\n\n      last_targ_count = files.ht_fill;\n    }\n\n  return value;\n}\n\nvoid\ninit_hash_files (void)\n{\n  hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);\n}\n\n/* EOF */\n"
  },
  {
    "path": "src/filedef.h",
    "content": "/* Definition of target file data structures for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Structure that represents the info on one file\n   that the makefile says how to make.\n   All of these are chained together through 'next'.  */\n\n#include \"hash.h\"\n\nstruct commands;\nstruct dep;\nstruct variable;\nstruct variable_set_list;\n\nstruct file\n  {\n    const char *name;\n    const char *hname;          /* Hashed filename */\n    const char *vpath;          /* VPATH/vpath pathname */\n    struct dep *deps;           /* all dependencies, including duplicates */\n    struct commands *cmds;      /* Commands to execute for this target.  */\n    const char *stem;           /* Implicit stem, if an implicit\n                                   rule has been used */\n    struct dep *also_make;      /* Targets that are made by making this.  */\n    struct file *prev;          /* Previous entry for same file name;\n                                   used when there are multiple double-colon\n                                   entries for the same file.  */\n    struct file *last;          /* Last entry for the same file name.  */\n\n    /* File that this file was renamed to.  After any time that a\n       file could be renamed, call 'check_renamed' (below).  */\n    struct file *renamed;\n\n    /* List of variable sets used for this file.  */\n    struct variable_set_list *variables;\n\n    /* Pattern-specific variable reference for this target, or null if there\n       isn't one.  Also see the pat_searched flag, below.  */\n    struct variable_set_list *pat_variables;\n\n    /* Immediate dependent that caused this target to be remade,\n       or nil if there isn't one.  */\n    struct file *parent;\n\n    /* For a double-colon entry, this is the first double-colon entry for\n       the same file.  Otherwise this is null.  */\n    struct file *double_colon;\n\n    FILE_TIMESTAMP last_mtime;  /* File's modtime, if already known.  */\n    FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating\n                                           has been performed.  */\n    unsigned int considered;    /* equal to 'considered' if file has been\n                                   considered on current scan of goal chain */\n    int command_flags;          /* Flags OR'd in for cmds; see commands.h.  */\n    enum update_status          /* Status of the last attempt to update.  */\n      {\n        us_success = 0,         /* Successfully updated.  Must be 0!  */\n        us_none,                /* No attempt to update has been made.  */\n        us_question,            /* Needs to be updated (-q is is set).  */\n        us_failed               /* Update failed.  */\n      } update_status ENUM_BITFIELD (2);\n    enum cmd_state              /* State of commands.  ORDER IS IMPORTANT!  */\n      {\n        cs_not_started = 0,     /* Not yet started.  Must be 0!  */\n        cs_deps_running,        /* Dep commands running.  */\n        cs_running,             /* Commands running.  */\n        cs_finished             /* Commands finished.  */\n      } command_state ENUM_BITFIELD (2);\n\n    unsigned int builtin:1;     /* True if the file is a builtin rule. */\n    unsigned int precious:1;    /* Non-0 means don't delete file on quit */\n    unsigned int loaded:1;      /* True if the file is a loaded object. */\n    unsigned int unloaded:1;    /* True if this loaded object was unloaded. */\n    unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp\n                                           has only one-second resolution.  */\n    unsigned int tried_implicit:1; /* Nonzero if have searched\n                                      for implicit rule for making\n                                      this file; don't search again.  */\n    unsigned int updating:1;    /* Nonzero while updating deps of this file */\n    unsigned int updated:1;     /* Nonzero if this file has been remade.  */\n    unsigned int is_target:1;   /* Nonzero if file is described as target.  */\n    unsigned int cmd_target:1;  /* Nonzero if file was given on cmd line.  */\n    unsigned int phony:1;       /* Nonzero if this is a phony file\n                                   i.e., a prerequisite of .PHONY.  */\n    unsigned int intermediate:1;/* Nonzero if this is an intermediate file.  */\n    unsigned int is_explicit:1; /* Nonzero if explicitly mentioned. */\n    unsigned int secondary:1;   /* Nonzero means remove_intermediates should\n                                   not delete it.  */\n    unsigned int notintermediate:1; /* Nonzero means a file is a prereq to\n                                       .NOTINTERMEDIATE.  */\n    unsigned int dontcare:1;    /* Nonzero if no complaint is to be made if\n                                   this target cannot be remade.  */\n    unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name.  */\n    unsigned int pat_searched:1;/* Nonzero if we already searched for\n                                   pattern-specific variables.  */\n    unsigned int no_diag:1;     /* True if the file failed to update and no\n                                   diagnostics has been issued (dontcare). */\n    unsigned int was_shuffled:1; /* Did we already shuffle 'deps'? used when\n                                    --shuffle passes through the graph.  */\n    unsigned int snapped:1;     /* True if the deps of this file have been\n                                   secondary expanded.  */\n    unsigned int suffix:1;      /* True if this is a suffix rule. */\n  };\n\n\nextern struct file *default_file;\n\n\nstruct file *lookup_file (const char *name);\nstruct file *enter_file (const char *name);\nstruct dep *split_prereqs (char *prereqstr);\nstruct dep *enter_prereqs (struct dep *prereqs, const char *stem);\nvoid expand_deps (struct file *f);\nstruct dep *expand_extra_prereqs (const struct variable *extra);\nvoid remove_intermediates (int sig);\nvoid snap_deps (void);\nvoid rename_file (struct file *file, const char *name);\nvoid rehash_file (struct file *file, const char *name);\nvoid set_command_state (struct file *file, enum cmd_state state);\nvoid notice_finished_file (struct file *file);\nvoid init_hash_files (void);\nvoid verify_file_data_base (void);\nchar *build_target_list (char *old_list);\nvoid print_file_data_base (void);\nvoid print_targets (void);\nint try_implicit_rule (struct file *file, unsigned int depth);\nint stemlen_compare (const void *v1, const void *v2);\n\n#if FILE_TIMESTAMP_HI_RES\n# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \\\n    file_timestamp_cons (fname, (st).st_mtime, (st).ST_MTIM_NSEC)\n#else\n# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \\\n    file_timestamp_cons (fname, (st).st_mtime, 0)\n#endif\n\n/* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution.\n   (Multiply by 2**30 instead of by 10**9 to save time at the cost of\n   slightly decreasing the number of available timestamps.)  With\n   64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04\n   UTC, but by then uintmax_t should be larger than 64 bits.  */\n#define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1)\n#define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0)\n\n#define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \\\n                              >> FILE_TIMESTAMP_LO_BITS)\n#define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \\\n                                      & ((1 << FILE_TIMESTAMP_LO_BITS) - 1)))\n\n/* Upper bound on length of string \"YYYY-MM-DD HH:MM:SS.NNNNNNNNN\"\n   representing a file timestamp.  The upper bound is not necessarily 29,\n   since the year might be less than -999 or greater than 9999.\n\n   Subtract one for the sign bit if in case file timestamps can be negative;\n   subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many\n   file timestamp bits might affect the year;\n   302 / 1000 is log10 (2) rounded up;\n   add one for integer division truncation;\n   add one more for a minus sign if file timestamps can be negative;\n   add 4 to allow for any 4-digit epoch year (e.g. 1970);\n   add 25 to allow for \"-MM-DD HH:MM:SS.NNNNNNNNN\".  */\n#define FLOOR_LOG2_SECONDS_PER_YEAR 24\n#define FILE_TIMESTAMP_PRINT_LEN_BOUND \\\n  (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \\\n    * 302 / 1000) \\\n   + 1 + 1 + 4 + 25)\n\nFILE_TIMESTAMP file_timestamp_cons (char const *, time_t, long int);\nFILE_TIMESTAMP file_timestamp_now (int *);\nvoid file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts);\n\n/* Return the mtime of file F (a struct file *), caching it.\n   The value is NONEXISTENT_MTIME if the file does not exist.  */\n#define file_mtime(f) file_mtime_1 ((f), 1)\n/* Return the mtime of file F (a struct file *), caching it.\n   Don't search using vpath for the file--if it doesn't actually exist,\n   we don't find it.\n   The value is NONEXISTENT_MTIME if the file does not exist.  */\n#define file_mtime_no_search(f) file_mtime_1 ((f), 0)\nFILE_TIMESTAMP f_mtime (struct file *file, int search);\n#define file_mtime_1(f, v) \\\n  ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime)\n\n/* Special timestamp values.  */\n\n/* The file's timestamp is not yet known.  */\n#define UNKNOWN_MTIME 0\n\n/* The file does not exist.  */\n#define NONEXISTENT_MTIME 1\n\n/* The file does not exist, and we assume that it is older than any\n   actual file.  */\n#define OLD_MTIME 2\n\n/* The smallest and largest ordinary timestamps.  */\n#define ORDINARY_MTIME_MIN (OLD_MTIME + 1)\n#define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \\\n                             << FILE_TIMESTAMP_LO_BITS) \\\n                            + ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1)\n\n#define is_ordinary_mtime(_t) ((_t) >= ORDINARY_MTIME_MIN && (_t) <= ORDINARY_MTIME_MAX)\n\n/* Modtime value to use for 'infinitely new'.  We used to get the current time\n   from the system and use that whenever we wanted 'new'.  But that causes\n   trouble when the machine running make and the machine holding a file have\n   different ideas about what time it is; and can also lose for 'force'\n   targets, which need to be considered newer than anything that depends on\n   them, even if said dependents' modtimes are in the future.  */\n#define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP)\n\n#define check_renamed(file) \\\n  while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here.  */\n\n/* Have we snapped deps yet?  */\nextern int snapped_deps;\n"
  },
  {
    "path": "src/function.c",
    "content": "/* Builtin function expansion for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"variable.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"os.h\"\n#include \"commands.h\"\n#include \"debug.h\"\n\n\nstruct function_table_entry\n  {\n    union {\n      char *(*func_ptr) (char *output, char **argv, const char *fname);\n      gmk_func_ptr alloc_func_ptr;\n    } fptr;\n    const char *name;\n    unsigned char len;\n    unsigned char minimum_args;\n    unsigned char maximum_args;\n    unsigned int expand_args:1;\n    unsigned int alloc_fn:1;\n    unsigned int adds_command:1;\n  };\n\nstatic unsigned long\nfunction_table_entry_hash_1 (const void *keyv)\n{\n  const struct function_table_entry *key = keyv;\n  return_STRING_N_HASH_1 (key->name, key->len);\n}\n\nstatic unsigned long\nfunction_table_entry_hash_2 (const void *keyv)\n{\n  const struct function_table_entry *key = keyv;\n  return_STRING_N_HASH_2 (key->name, key->len);\n}\n\nstatic int\nfunction_table_entry_hash_cmp (const void *xv, const void *yv)\n{\n  const struct function_table_entry *x = xv;\n  const struct function_table_entry *y = yv;\n  int result = x->len - y->len;\n  if (result)\n    return result;\n  return_STRING_N_COMPARE (x->name, y->name, x->len);\n}\n\nstatic struct hash_table function_table;\n\f\n\n/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing\n   each occurrence of SUBST with REPLACE. TEXT is null-terminated.  SLEN is\n   the length of SUBST and RLEN is the length of REPLACE.  If BY_WORD is\n   nonzero, substitutions are done only on matches which are complete\n   whitespace-delimited words.  */\n\nchar *\nsubst_expand (char *o, const char *text, const char *subst, const char *replace,\n              size_t slen, size_t rlen, int by_word)\n{\n  const char *t = text;\n  const char *p;\n\n  if (slen == 0 && !by_word)\n    {\n      /* The first occurrence of \"\" in any string is its end.  */\n      o = variable_buffer_output (o, t, strlen (t));\n      if (rlen > 0)\n        o = variable_buffer_output (o, replace, rlen);\n      return o;\n    }\n\n  do\n    {\n      if (by_word && slen == 0)\n        /* When matching by words, the empty string should match\n           the end of each word, rather than the end of the whole text.  */\n        p = end_of_token (next_token (t));\n      else\n        {\n          p = strstr (t, subst);\n          if (p == 0)\n            {\n              /* No more matches.  Output everything left on the end.  */\n              o = variable_buffer_output (o, t, strlen (t));\n              return o;\n            }\n        }\n\n      /* Output everything before this occurrence of the string to replace.  */\n      if (p > t)\n        o = variable_buffer_output (o, t, p - t);\n\n      /* If we're substituting only by fully matched words,\n         or only at the ends of words, check that this case qualifies.  */\n      if (by_word\n          && ((p > text && !ISSPACE (p[-1]))\n              || ! STOP_SET (p[slen], MAP_SPACE|MAP_NUL)))\n        /* Struck out.  Output the rest of the string that is\n           no longer to be replaced.  */\n        o = variable_buffer_output (o, subst, slen);\n      else if (rlen > 0)\n        /* Output the replacement string.  */\n        o = variable_buffer_output (o, replace, rlen);\n\n      /* Advance T past the string to be replaced.  */\n      t = p + slen;\n    } while (*t != '\\0');\n\n  return o;\n}\n\f\n\n/* Store into VARIABLE_BUFFER at O the result of scanning TEXT\n   and replacing strings matching PATTERN with REPLACE.\n   If PATTERN_PERCENT is not nil, PATTERN has already been\n   run through find_percent, and PATTERN_PERCENT is the result.\n   If REPLACE_PERCENT is not nil, REPLACE has already been\n   run through find_percent, and REPLACE_PERCENT is the result.\n   Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the\n   character _AFTER_ the %, not to the % itself.\n*/\n\nchar *\npatsubst_expand_pat (char *o, const char *text,\n                     const char *pattern, const char *replace,\n                     const char *pattern_percent, const char *replace_percent)\n{\n  size_t pattern_prepercent_len, pattern_postpercent_len;\n  size_t replace_prepercent_len, replace_postpercent_len;\n  const char *t;\n  size_t len;\n  int doneany = 0;\n\n  /* Record the length of REPLACE before and after the % so we don't have to\n     compute these lengths more than once.  */\n  if (replace_percent)\n    {\n      replace_prepercent_len = replace_percent - replace - 1;\n      replace_postpercent_len = strlen (replace_percent);\n    }\n  else\n    {\n      replace_prepercent_len = strlen (replace);\n      replace_postpercent_len = 0;\n    }\n\n  if (!pattern_percent)\n    /* With no % in the pattern, this is just a simple substitution.  */\n    return subst_expand (o, text, pattern, replace,\n                         strlen (pattern), strlen (replace), 1);\n\n  /* Record the length of PATTERN before and after the %\n     so we don't have to compute it more than once.  */\n  pattern_prepercent_len = pattern_percent - pattern - 1;\n  pattern_postpercent_len = strlen (pattern_percent);\n\n  while ((t = find_next_token (&text, &len)) != 0)\n    {\n      int fail = 0;\n\n      /* Is it big enough to match?  */\n      if (len < pattern_prepercent_len + pattern_postpercent_len)\n        fail = 1;\n\n      /* Does the prefix match? */\n      if (!fail && pattern_prepercent_len > 0\n          && (*t != *pattern\n              || t[pattern_prepercent_len - 1] != pattern_percent[-2]\n              || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1)))\n        fail = 1;\n\n      /* Does the suffix match? */\n      if (!fail && pattern_postpercent_len > 0\n          && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1]\n              || t[len - pattern_postpercent_len] != *pattern_percent\n              || !strneq (&t[len - pattern_postpercent_len],\n                          pattern_percent, pattern_postpercent_len - 1)))\n        fail = 1;\n\n      if (fail)\n        /* It didn't match.  Output the string.  */\n        o = variable_buffer_output (o, t, len);\n      else\n        {\n          /* It matched.  Output the replacement.  */\n\n          /* Output the part of the replacement before the %.  */\n          o = variable_buffer_output (o, replace, replace_prepercent_len);\n\n          if (replace_percent != 0)\n            {\n              /* Output the part of the matched string that\n                 matched the % in the pattern.  */\n              o = variable_buffer_output (o, t + pattern_prepercent_len,\n                                          len - (pattern_prepercent_len\n                                                 + pattern_postpercent_len));\n              /* Output the part of the replacement after the %.  */\n              o = variable_buffer_output (o, replace_percent,\n                                          replace_postpercent_len);\n            }\n        }\n\n      /* Output a space, but not if the replacement is \"\".  */\n      if (fail || replace_prepercent_len > 0\n          || (replace_percent != 0 && len + replace_postpercent_len > 0))\n        {\n          o = variable_buffer_output (o, \" \", 1);\n          doneany = 1;\n        }\n    }\n  if (doneany)\n    /* Kill the last space.  */\n    --o;\n\n  return o;\n}\n\n/* Store into VARIABLE_BUFFER at O the result of scanning TEXT\n   and replacing strings matching PATTERN with REPLACE.\n   If PATTERN_PERCENT is not nil, PATTERN has already been\n   run through find_percent, and PATTERN_PERCENT is the result.\n   If REPLACE_PERCENT is not nil, REPLACE has already been\n   run through find_percent, and REPLACE_PERCENT is the result.\n   Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the\n   character _AFTER_ the %, not to the % itself.\n*/\n\nchar *\npatsubst_expand (char *o, const char *text, char *pattern, char *replace)\n{\n  const char *pattern_percent = find_percent (pattern);\n  const char *replace_percent = find_percent (replace);\n\n  /* If there's a percent in the pattern or replacement skip it.  */\n  if (replace_percent)\n    ++replace_percent;\n  if (pattern_percent)\n    ++pattern_percent;\n\n  return patsubst_expand_pat (o, text, pattern, replace,\n                              pattern_percent, replace_percent);\n}\n\f\n\n/* Look up a function by name.  */\n\nstatic const struct function_table_entry *\nlookup_function (const char *s)\n{\n  struct function_table_entry function_table_entry_key;\n  const char *e = s;\n\n  while (STOP_SET (*e, MAP_USERFUNC))\n    e++;\n\n  if (e == s || !STOP_SET(*e, MAP_NUL|MAP_SPACE))\n    return NULL;\n\n  function_table_entry_key.name = s;\n  function_table_entry_key.len = (unsigned char) (e - s);\n\n  return hash_find_item (&function_table, &function_table_entry_key);\n}\n\f\n\n/* Return 1 if PATTERN matches STR, 0 if not.  */\n\nint\npattern_matches (const char *pattern, const char *percent, const char *str)\n{\n  size_t sfxlen, strlength;\n\n  if (percent == 0)\n    {\n      size_t len = strlen (pattern) + 1;\n      char *new_chars = alloca (len);\n      memcpy (new_chars, pattern, len);\n      percent = find_percent (new_chars);\n      if (percent == 0)\n        return streq (new_chars, str);\n      pattern = new_chars;\n    }\n\n  sfxlen = strlen (percent + 1);\n  strlength = strlen (str);\n\n  if (strlength < (percent - pattern) + sfxlen\n      || !strneq (pattern, str, percent - pattern))\n    return 0;\n\n  return !strcmp (percent + 1, str + (strlength - sfxlen));\n}\n\f\n\n/* Find the next comma or ENDPAREN (counting nested STARTPAREN and\n   ENDPARENtheses), starting at PTR before END.  Return a pointer to\n   next character.\n\n   If no next argument is found, return NULL.\n*/\n\nstatic char *\nfind_next_argument (char startparen, char endparen,\n                    const char *ptr, const char *end)\n{\n  int count = 0;\n\n  for (; ptr < end; ++ptr)\n    if (!STOP_SET (*ptr, MAP_VARSEP|MAP_COMMA))\n      continue;\n\n    else if (*ptr == startparen)\n      ++count;\n\n    else if (*ptr == endparen)\n      {\n        --count;\n        if (count < 0)\n          return NULL;\n      }\n\n    else if (*ptr == ',' && !count)\n      return (char *)ptr;\n\n  /* We didn't find anything.  */\n  return NULL;\n}\n\f\n\n/* Glob-expand LINE.  The returned pointer is\n   only good until the next call to string_glob.  */\n\nstatic char *\nstring_glob (char *line)\n{\n  static char *result = 0;\n  static size_t length;\n  struct nameseq *chain;\n  size_t idx;\n\n  chain = PARSE_FILE_SEQ (&line, struct nameseq, MAP_NUL, NULL,\n                          /* We do not want parse_file_seq to strip './'s.\n                             That would break examples like:\n                             $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)).  */\n                          PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS);\n\n  if (result == 0)\n    {\n      length = 100;\n      result = xmalloc (100);\n    }\n\n  idx = 0;\n  while (chain != 0)\n    {\n      struct nameseq *next = chain->next;\n      size_t len = strlen (chain->name);\n\n      if (idx + len + 1 > length)\n        {\n          length += (len + 1) * 2;\n          result = xrealloc (result, length);\n        }\n      memcpy (&result[idx], chain->name, len);\n      idx += len;\n      result[idx++] = ' ';\n\n      /* Because we used PARSEFS_NOCACHE above, we have to free() NAME.  */\n      free ((char *)chain->name);\n      free (chain);\n      chain = next;\n    }\n\n  /* Kill the last space and terminate the string.  */\n  if (idx == 0)\n    result[0] = '\\0';\n  else\n    result[idx - 1] = '\\0';\n\n  return result;\n}\n\f\n/*\n  Builtin functions\n */\n\nstatic char *\nfunc_patsubst (char *o, char **argv, const char *funcname UNUSED)\n{\n  o = patsubst_expand (o, argv[2], argv[0], argv[1]);\n  return o;\n}\n\n\nstatic char *\nfunc_join (char *o, char **argv, const char *funcname UNUSED)\n{\n  int doneany = 0;\n\n  /* Write each word of the first argument directly followed\n     by the corresponding word of the second argument.\n     If the two arguments have a different number of words,\n     the excess words are just output separated by blanks.  */\n  const char *tp;\n  const char *pp;\n  const char *list1_iterator = argv[0];\n  const char *list2_iterator = argv[1];\n  do\n    {\n      size_t len1, len2;\n\n      tp = find_next_token (&list1_iterator, &len1);\n      if (tp != 0)\n        o = variable_buffer_output (o, tp, len1);\n\n      pp = find_next_token (&list2_iterator, &len2);\n      if (pp != 0)\n        o = variable_buffer_output (o, pp, len2);\n\n      if (tp != 0 || pp != 0)\n        {\n          o = variable_buffer_output (o, \" \", 1);\n          doneany = 1;\n        }\n    }\n  while (tp != 0 || pp != 0);\n  if (doneany)\n    /* Kill the last blank.  */\n    --o;\n\n  return o;\n}\n\n\nstatic char *\nfunc_origin (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* Expand the argument.  */\n  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));\n  if (v == 0)\n    o = variable_buffer_output (o, \"undefined\", 9);\n  else\n    switch (v->origin)\n      {\n      case o_invalid:\n        abort ();\n        break;\n      case o_default:\n        o = variable_buffer_output (o, \"default\", 7);\n        break;\n      case o_env:\n        o = variable_buffer_output (o, \"environment\", 11);\n        break;\n      case o_file:\n        o = variable_buffer_output (o, \"file\", 4);\n        break;\n      case o_env_override:\n        o = variable_buffer_output (o, \"environment override\", 20);\n        break;\n      case o_command:\n        o = variable_buffer_output (o, \"command line\", 12);\n        break;\n      case o_override:\n        o = variable_buffer_output (o, \"override\", 8);\n        break;\n      case o_automatic:\n        o = variable_buffer_output (o, \"automatic\", 9);\n        break;\n      }\n\n  return o;\n}\n\nstatic char *\nfunc_flavor (char *o, char **argv, const char *funcname UNUSED)\n{\n  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));\n\n  if (v == 0)\n    o = variable_buffer_output (o, \"undefined\", 9);\n  else\n    if (v->recursive)\n      o = variable_buffer_output (o, \"recursive\", 9);\n    else\n      o = variable_buffer_output (o, \"simple\", 6);\n\n  return o;\n}\n\n\nstatic char *\nfunc_notdir_suffix (char *o, char **argv, const char *funcname)\n{\n  /* Expand the argument.  */\n  const char *list_iterator = argv[0];\n  const char *p2;\n  int doneany =0;\n  size_t len=0;\n\n  int is_suffix = funcname[0] == 's';\n  int is_notdir = !is_suffix;\n  int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0);\n#if MK_OS_VMS\n  /* For VMS list_iterator points to a comma separated list. To use the common\n     [find_]next_token, create a local copy and replace the commas with\n     spaces. Obviously, there is a problem if there is a ',' in the VMS filename\n     (can only happen on ODS5), the same problem as with spaces in filenames,\n     which seems to be present in make on all platforms. */\n  char *vms_list_iterator = alloca(strlen(list_iterator) + 1);\n  int i;\n  for (i = 0; list_iterator[i]; i++)\n    if (list_iterator[i] == ',')\n      vms_list_iterator[i] = ' ';\n    else\n      vms_list_iterator[i] = list_iterator[i];\n  vms_list_iterator[i] = list_iterator[i];\n  while ((p2 = find_next_token((const char**) &vms_list_iterator, &len)) != 0)\n#else\n  while ((p2 = find_next_token (&list_iterator, &len)) != 0)\n#endif\n    {\n      const char *p = p2 + len - 1;\n\n      while (p >= p2 && ! STOP_SET (*p, stop))\n        --p;\n\n      if (p >= p2)\n        {\n          if (is_notdir)\n            ++p;\n          else if (*p != '.')\n            continue;\n          o = variable_buffer_output (o, p, len - (p - p2));\n        }\n#ifdef HAVE_DOS_PATHS\n      /* Handle the case of \"d:foo/bar\".  */\n      else if (is_notdir && p2[0] && p2[1] == ':')\n        {\n          p = p2 + 2;\n          o = variable_buffer_output (o, p, len - (p - p2));\n        }\n#endif\n      else if (is_notdir)\n        o = variable_buffer_output (o, p2, len);\n\n      if (is_notdir || p >= p2)\n        {\n#if MK_OS_VMS\n          if (vms_comma_separator)\n            o = variable_buffer_output (o, \",\", 1);\n          else\n#endif\n          o = variable_buffer_output (o, \" \", 1);\n\n          doneany = 1;\n        }\n    }\n\n  if (doneany)\n    /* Kill last space.  */\n    --o;\n\n  return o;\n}\n\n\nstatic char *\nfunc_basename_dir (char *o, char **argv, const char *funcname)\n{\n  /* Expand the argument.  */\n  const char *p3 = argv[0];\n  const char *p2;\n  int doneany = 0;\n  size_t len = 0;\n\n  int is_basename = funcname[0] == 'b';\n  int is_dir = !is_basename;\n  int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL;\n#if MK_OS_VMS\n  /* As in func_notdir_suffix ... */\n  char *vms_p3 = alloca (strlen(p3) + 1);\n  int i;\n  for (i = 0; p3[i]; i++)\n    if (p3[i] == ',')\n      vms_p3[i] = ' ';\n    else\n      vms_p3[i] = p3[i];\n  vms_p3[i] = p3[i];\n  while ((p2 = find_next_token((const char**) &vms_p3, &len)) != 0)\n#else\n  while ((p2 = find_next_token (&p3, &len)) != 0)\n#endif\n    {\n      const char *p = p2 + len - 1;\n      while (p >= p2 && ! STOP_SET (*p, stop))\n        --p;\n\n      if (p >= p2 && (is_dir))\n        o = variable_buffer_output (o, p2, ++p - p2);\n      else if (p >= p2 && (*p == '.'))\n        o = variable_buffer_output (o, p2, p - p2);\n#ifdef HAVE_DOS_PATHS\n      /* Handle the \"d:foobar\" case */\n      else if (p2[0] && p2[1] == ':' && is_dir)\n        o = variable_buffer_output (o, p2, 2);\n#endif\n      else if (is_dir)\n#if MK_OS_VMS\n        {\n          extern int vms_report_unix_paths;\n          if (vms_report_unix_paths)\n            o = variable_buffer_output (o, \"./\", 2);\n          else\n            o = variable_buffer_output (o, \"[]\", 2);\n        }\n#else\n      o = variable_buffer_output (o, \"./\", 2);\n#endif /* !MK_OS_VMS */\n      else\n        /* The entire name is the basename.  */\n        o = variable_buffer_output (o, p2, len);\n\n#if MK_OS_VMS\n      if (vms_comma_separator)\n        o = variable_buffer_output (o, \",\", 1);\n      else\n#endif\n        o = variable_buffer_output (o, \" \", 1);\n\n      doneany = 1;\n    }\n\n  if (doneany)\n    /* Kill last space.  */\n    --o;\n\n  return o;\n}\n\nstatic char *\nfunc_addsuffix_addprefix (char *o, char **argv, const char *funcname)\n{\n  size_t fixlen = strlen (argv[0]);\n  const char *list_iterator = argv[1];\n  int is_addprefix = funcname[3] == 'p';\n  int is_addsuffix = !is_addprefix;\n\n  int doneany = 0;\n  const char *p;\n  size_t len;\n\n  while ((p = find_next_token (&list_iterator, &len)) != 0)\n    {\n      if (is_addprefix)\n        o = variable_buffer_output (o, argv[0], fixlen);\n      o = variable_buffer_output (o, p, len);\n      if (is_addsuffix)\n        o = variable_buffer_output (o, argv[0], fixlen);\n      o = variable_buffer_output (o, \" \", 1);\n      doneany = 1;\n    }\n\n  if (doneany)\n    /* Kill last space.  */\n    --o;\n\n  return o;\n}\n\nstatic char *\nfunc_subst (char *o, char **argv, const char *funcname UNUSED)\n{\n  o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]),\n                    strlen (argv[1]), 0);\n\n  return o;\n}\n\n\nstatic char *\nfunc_firstword (char *o, char **argv, const char *funcname UNUSED)\n{\n  size_t i;\n  const char *words = argv[0];    /* Use a temp variable for find_next_token */\n  const char *p = find_next_token (&words, &i);\n\n  if (p != 0)\n    o = variable_buffer_output (o, p, i);\n\n  return o;\n}\n\nstatic char *\nfunc_lastword (char *o, char **argv, const char *funcname UNUSED)\n{\n  size_t i;\n  const char *words = argv[0];    /* Use a temp variable for find_next_token */\n  const char *p = NULL;\n  const char *t;\n\n  while ((t = find_next_token (&words, &i)) != NULL)\n    p = t;\n\n  if (p != 0)\n    o = variable_buffer_output (o, p, i);\n\n  return o;\n}\n\nstatic char *\nfunc_words (char *o, char **argv, const char *funcname UNUSED)\n{\n  unsigned int i = 0;\n  const char *word_iterator = argv[0];\n  char buf[INTSTR_LENGTH];\n\n  while (find_next_token (&word_iterator, NULL) != 0)\n    ++i;\n\n  sprintf (buf, \"%u\", i);\n  o = variable_buffer_output (o, buf, strlen (buf));\n\n  return o;\n}\n\n/* Set begpp to point to the first non-whitespace character of the string,\n * and endpp to point to the last non-whitespace character of the string.\n * If the string is empty or contains nothing but whitespace, endpp will be\n * begpp-1.\n */\nchar *\nstrip_whitespace (const char **begpp, const char **endpp)\n{\n  while (*begpp <= *endpp && ISSPACE (**begpp))\n    (*begpp) ++;\n  while (*endpp >= *begpp && ISSPACE (**endpp))\n    (*endpp) --;\n  return (char *)*begpp;\n}\n\nstatic long long\nparse_numeric (const char *s, const char *msg)\n{\n  const char *beg = s;\n  const char *end = s + strlen (s) - 1;\n  char *endp;\n  long long num;\n  strip_whitespace (&beg, &end);\n\n  if (beg > end)\n    OS (fatal, *expanding_var, _(\"%s: empty value\"), msg);\n\n  errno = 0;\n  num = strtoll (beg, &endp, 10);\n  if (errno == ERANGE)\n    OSS (fatal, *expanding_var, _(\"%s: '%s' out of range\"), msg, s);\n  else if (endp == beg || endp <= end)\n    /* Empty or non-numeric input */\n    OSS (fatal, *expanding_var, \"%s: '%s'\", msg, s);\n\n  return num;\n}\n\nstatic char *\nfunc_word (char *o, char **argv, const char *funcname UNUSED)\n{\n  const char *end_p;\n  const char *p;\n  long long i;\n\n  i = parse_numeric (argv[0],\n                     _(\"invalid first argument to 'word' function\"));\n  if (i < 1)\n    O (fatal, *expanding_var,\n       _(\"first argument to 'word' function must be greater than 0\"));\n\n  end_p = argv[1];\n  while ((p = find_next_token (&end_p, 0)) != 0)\n    if (--i == 0)\n      break;\n\n  if (i == 0)\n    o = variable_buffer_output (o, p, end_p - p);\n\n  return o;\n}\n\nstatic char *\nfunc_wordlist (char *o, char **argv, const char *funcname UNUSED)\n{\n  char buf[INTSTR_LENGTH + 1];\n  long long start, stop, count;\n  const char* badfirst = _(\"invalid first argument to 'wordlist' function\");\n  const char* badsecond = _(\"invalid second argument to 'wordlist' function\");\n\n  start = parse_numeric (argv[0], badfirst);\n  if (start < 1)\n    OSS (fatal, *expanding_var, \"%s: '%s'\", badfirst, make_lltoa (start, buf));\n\n  stop = parse_numeric (argv[1], badsecond);\n  if (stop < 0)\n    OSS (fatal, *expanding_var, \"%s: '%s'\", badsecond, make_lltoa (stop, buf));\n\n  count = stop - start + 1;\n\n  if (count > 0)\n    {\n      const char *p;\n      const char *end_p = argv[2];\n\n      /* Find the beginning of the \"start\"th word.  */\n      while (((p = find_next_token (&end_p, 0)) != 0) && --start)\n        ;\n\n      if (p)\n        {\n          /* Find the end of the \"count\"th word from start.  */\n          while (--count && (find_next_token (&end_p, 0) != 0))\n            ;\n\n          /* Return the stuff in the middle.  */\n          o = variable_buffer_output (o, p, end_p - p);\n        }\n    }\n\n  return o;\n}\n\nstatic char *\nfunc_findstring (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* Find the first occurrence of the first string in the second.  */\n  if (strstr (argv[1], argv[0]) != 0)\n    o = variable_buffer_output (o, argv[0], strlen (argv[0]));\n\n  return o;\n}\n\nstatic char *\nfunc_foreach (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* expand only the first two.  */\n  char *varname = expand_argument (argv[0], NULL);\n  char *list = expand_argument (argv[1], NULL);\n  const char *body = argv[2];\n\n  int doneany = 0;\n  const char *list_iterator = list;\n  const char *p;\n  size_t len;\n  struct variable *var;\n\n  /* Clean up the variable name by removing whitespace.  */\n  char *vp = next_token (varname);\n  end_of_token (vp)[0] = '\\0';\n\n  push_new_variable_scope ();\n  var = define_variable (vp, strlen (vp), \"\", o_automatic, 0);\n\n  /* loop through LIST,  put the value in VAR and expand BODY */\n  while ((p = find_next_token (&list_iterator, &len)) != 0)\n    {\n      char *result = 0;\n\n      free (var->value);\n      var->value = xstrndup (p, len);\n\n      result = allocated_expand_string (body);\n\n      o = variable_buffer_output (o, result, strlen (result));\n      o = variable_buffer_output (o, \" \", 1);\n      doneany = 1;\n      free (result);\n    }\n\n  if (doneany)\n    /* Kill the last space.  */\n    --o;\n\n  pop_variable_scope ();\n  free (varname);\n  free (list);\n\n  return o;\n}\n\nstatic char *\nfunc_let (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* expand only the first two.  */\n  char *varnames = expand_argument (argv[0], NULL);\n  char *list = expand_argument (argv[1], NULL);\n  const char *body = argv[2];\n\n  const char *vp;\n  const char *vp_next = varnames;\n  const char *list_iterator = list;\n  size_t vlen;\n\n  push_new_variable_scope ();\n\n  /* loop through LIST for all but the last VARNAME */\n  vp = find_next_token (&vp_next, &vlen);\n  NEXT_TOKEN (vp_next);\n  while (*vp_next != '\\0')\n    {\n      size_t len;\n      char *p = find_next_token (&list_iterator, &len);\n      if (p && *list_iterator != '\\0')\n        {\n          ++list_iterator;\n          p[len] = '\\0';\n        }\n      define_variable (vp, vlen, p ? p : \"\", o_automatic, 0);\n\n      vp = find_next_token (&vp_next, &vlen);\n      NEXT_TOKEN (vp_next);\n    }\n\n  /* set the last VARNAME to the remainder of LIST */\n  if (vp)\n    define_variable (vp, vlen, next_token (list_iterator), o_automatic, 0);\n\n  /* Expand the body in the context of the arguments, adding the result to\n     the variable buffer.  */\n\n  o = expand_string_buf (o, body, SIZE_MAX);\n\n  pop_variable_scope ();\n  free (varnames);\n  free (list);\n\n  return o + strlen (o);\n}\n\nstruct a_word\n{\n  struct a_word *chain;\n  char *str;\n  size_t length;\n  int matched;\n};\n\nstatic unsigned long\na_word_hash_1 (const void *key)\n{\n  return_STRING_HASH_1 (((struct a_word const *) key)->str);\n}\n\nstatic unsigned long\na_word_hash_2 (const void *key)\n{\n  return_STRING_HASH_2 (((struct a_word const *) key)->str);\n}\n\nstatic int\na_word_hash_cmp (const void *x, const void *y)\n{\n  const struct a_word *ax = x;\n  const struct a_word *ay = y;\n\n  if (ax->length != ay->length)\n    return ax->length > ay->length ? 1 : -1;\n\n  return_STRING_N_COMPARE (ax->str, ay->str, ax->length);\n}\n\nstruct a_pattern\n{\n  char *str;\n  char *percent;\n  size_t length;\n};\n\nstatic char *\nfunc_filter_filterout (char *o, char **argv, const char *funcname)\n{\n  struct a_word *words;\n  struct a_word *word_end;\n  struct a_word *wp;\n  struct a_pattern *patterns;\n  struct a_pattern *pat_end;\n  struct a_pattern *pp;\n  unsigned long pat_count = 0, word_count = 0;\n\n  struct hash_table a_word_table;\n  int is_filter = funcname[CSTRLEN (\"filter\")] == '\\0';\n  const char *cp;\n  int literals = 0;\n  int hashing = 0;\n  char *p;\n  size_t len;\n  int doneany = 0;\n\n  /* Find the number of words and get memory for them.  */\n  cp = argv[1];\n  while ((p = find_next_token (&cp, NULL)) != 0)\n    ++word_count;\n\n  if (!word_count)\n    return o;\n\n  words = xcalloc (word_count * sizeof (struct a_word));\n  word_end = words + word_count;\n\n  /* Find the number of patterns and get memory for them.  */\n  cp = argv[0];\n  while ((p = find_next_token (&cp, NULL)) != 0)\n    ++pat_count;\n\n  patterns = xcalloc (pat_count * sizeof (struct a_pattern));\n  pat_end = patterns + pat_count;\n\n  /* Chop argv[0] up into patterns to match against the words.  */\n\n  cp = argv[0];\n  pp = patterns;\n  while ((p = find_next_token (&cp, &len)) != 0)\n    {\n      if (*cp != '\\0')\n        ++cp;\n\n      p[len] = '\\0';\n      pp->str = p;\n      pp->percent = find_percent (p);\n      if (pp->percent == 0)\n        literals++;\n      /* find_percent() might shorten the string so LEN is wrong.  */\n      pp->length = strlen (pp->str);\n\n      ++pp;\n    }\n\n  /* Chop ARGV[1] up into words to match against the patterns.  */\n\n  cp = argv[1];\n  wp = words;\n  while ((p = find_next_token (&cp, &len)) != 0)\n    {\n      if (*cp != '\\0')\n        ++cp;\n\n      p[len] = '\\0';\n      wp->str = p;\n      wp->length = len;\n      ++wp;\n    }\n\n  /* Only use a hash table if arg list lengths justifies the cost.  */\n  hashing = (literals > 1 && (literals * word_count) >= 10);\n  if (hashing)\n    {\n      hash_init (&a_word_table, word_count, a_word_hash_1, a_word_hash_2,\n                 a_word_hash_cmp);\n      for (wp = words; wp < word_end; ++wp)\n        {\n          struct a_word *owp = hash_insert (&a_word_table, wp);\n          if (owp)\n            wp->chain = owp;\n        }\n    }\n\n  /* Run each pattern through the words, killing words.  */\n  for (pp = patterns; pp < pat_end; ++pp)\n    {\n      if (pp->percent)\n        for (wp = words; wp < word_end; ++wp)\n          wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);\n      else if (hashing)\n        {\n          struct a_word a_word_key;\n          a_word_key.str = pp->str;\n          a_word_key.length = pp->length;\n          wp = hash_find_item (&a_word_table, &a_word_key);\n          while (wp)\n            {\n              wp->matched |= 1;\n              wp = wp->chain;\n            }\n        }\n      else\n        for (wp = words; wp < word_end; ++wp)\n          wp->matched |= (wp->length == pp->length\n                          && memcmp (pp->str, wp->str, wp->length) == 0);\n    }\n\n  /* Output the words that matched (or didn't, for filter-out).  */\n  for (wp = words; wp < word_end; ++wp)\n    if (is_filter ? wp->matched : !wp->matched)\n      {\n        o = variable_buffer_output (o, wp->str, strlen (wp->str));\n        o = variable_buffer_output (o, \" \", 1);\n        doneany = 1;\n      }\n\n  if (doneany)\n    /* Kill the last space.  */\n    --o;\n\n  if (hashing)\n    hash_free (&a_word_table, 0);\n\n  free (patterns);\n  free (words);\n\n  return o;\n}\n\n\nstatic char *\nfunc_strip (char *o, char **argv, const char *funcname UNUSED)\n{\n  const char *p = argv[0];\n  int doneany = 0;\n\n  while (*p != '\\0')\n    {\n      int i=0;\n      const char *word_start;\n\n      NEXT_TOKEN (p);\n      word_start = p;\n      for (i=0; *p != '\\0' && !ISSPACE (*p); ++p, ++i)\n        {}\n      if (!i)\n        break;\n      o = variable_buffer_output (o, word_start, i);\n      o = variable_buffer_output (o, \" \", 1);\n      doneany = 1;\n    }\n\n  if (doneany)\n    /* Kill the last space.  */\n    --o;\n\n  return o;\n}\n\n/*\n  Print a warning or fatal message.\n*/\nstatic char *\nfunc_error (char *o, char **argv, const char *funcname)\n{\n  switch (*funcname)\n    {\n    case 'e':\n      OS (fatal, reading_file, \"%s\", argv[0]);\n\n    case 'w':\n      OS (error, reading_file, \"%s\", argv[0]);\n      break;\n\n    case 'i':\n      {\n        size_t len = strlen (argv[0]);\n        char *msg = xmalloc (len + 2);\n        memcpy (msg, argv[0], len);\n        msg[len] = '\\n';\n        msg[len + 1] = '\\0';\n        outputs (0, msg);\n        free (msg);\n        break;\n      }\n\n    default:\n      OS (fatal, *expanding_var, \"INTERNAL: func_error: '%s'\", funcname);\n    }\n\n  /* The warning function expands to the empty string.  */\n  return o;\n}\n\n\n/*\n  chop argv[0] into words, and sort them.\n */\nstatic char *\nfunc_sort (char *o, char **argv, const char *funcname UNUSED)\n{\n  const char *t;\n  char **words;\n  int wordi;\n  char *p;\n  size_t len;\n\n  /* Find the maximum number of words we'll have.  */\n  t = argv[0];\n  wordi = 0;\n  while ((p = find_next_token (&t, NULL)) != 0)\n    {\n      ++t;\n      ++wordi;\n    }\n\n  words = xmalloc ((wordi == 0 ? 1 : wordi) * sizeof (char *));\n\n  /* Now assign pointers to each string in the array.  */\n  t = argv[0];\n  wordi = 0;\n  while ((p = find_next_token (&t, &len)) != 0)\n    {\n      ++t;\n      p[len] = '\\0';\n      words[wordi++] = p;\n    }\n\n  if (wordi)\n    {\n      int i;\n\n      /* Now sort the list of words.  */\n      qsort (words, wordi, sizeof (char *), alpha_compare);\n\n      /* Now write the sorted list, uniquified.  */\n      for (i = 0; i < wordi; ++i)\n        {\n          len = strlen (words[i]);\n          if (i == wordi - 1 || strlen (words[i + 1]) != len\n              || memcmp (words[i], words[i + 1], len))\n            {\n              o = variable_buffer_output (o, words[i], len);\n              o = variable_buffer_output (o, \" \", 1);\n            }\n        }\n\n      /* Kill the last space.  */\n      --o;\n    }\n\n  free (words);\n\n  return o;\n}\n\n/*\n  Traverse NUMBER consisting of optional leading white space, optional\n  sign, digits, and optional trailing white space.\n  If number is not of the proper form, diagnose with MSG.  Otherwise,\n  return the address of of the first character after NUMBER, store\n  into *SIGN an integer consistent with the number's sign (-1, 0, or 1)\n  and store into *NUMSTART the address of NUMBER's first nonzero digit\n  (if NUMBER contains only zero digits, store the address of the first\n  character after NUMBER).\n*/\nstatic const char *\nparse_textint (const char *number, const char *msg,\n               int *sign, const char **numstart)\n{\n  const char *after_sign, *after_number;\n  const char *p = next_token (number);\n  int negative = *p == '-';\n  int nonzero;\n\n  if (*p == '\\0')\n    OS (fatal, *expanding_var, _(\"%s: empty value\"), msg);\n\n  p += negative || *p == '+';\n  after_sign = p;\n\n  while (*p == '0')\n    p++;\n  *numstart = p;\n\n  while (ISDIGIT (*p))\n    ++p;\n  after_number = p;\n  nonzero = *numstart != after_number;\n  *sign = negative ? -nonzero : nonzero;\n\n  /* Check for extra non-whitespace stuff after the value.  */\n  if (after_number == after_sign || *next_token (p) != '\\0')\n    OSS (fatal, *expanding_var, \"%s: '%s'\", msg, number);\n\n  return after_number;\n}\n\n\n/*\n  $(intcmp lhs,rhs[,lt-part[,eq-part[,gt-part]]])\n\n  LHS and RHS must be integer values (leading/trailing whitespace is ignored).\n  If none of LT-PART, EQ-PART, or GT-PART are given then the function expands\n  to empty if LHS and RHS are not equal, or the numeric value if they are equal.\n  LT-PART is evaluated when LHS is strictly less than RHS, EQ-PART is evaluated\n  when LHS is equal to RHS, and GT-part is evaluated when LHS is strictly\n  greater than RHS.\n  If GT-PART is not provided, it defaults to EQ-PART.  When neither EQ-PART\n  nor GT-PART are provided, the function expands to empty if LHS is not\n  strictly less than RHS.\n*/\n\nstatic char *\nfunc_intcmp (char *o, char **argv, const char *funcname UNUSED)\n{\n  int lsign, rsign;\n  const char *lnum, *rnum;\n  char *lhs_str = expand_argument (argv[0], NULL);\n  char *rhs_str = expand_argument (argv[1], NULL);\n  const char *llim = parse_textint (lhs_str, _(\"non-numeric first argument to 'intcmp' function\"), &lsign, &lnum);\n  const char *rlim = parse_textint (rhs_str, _(\"non-numeric second argument to 'intcmp' function\"), &rsign, &rnum);\n  ptrdiff_t llen = llim - lnum;\n  ptrdiff_t rlen = rlim - rnum;\n  int cmp = lsign - rsign;\n\n  if (cmp == 0)\n    {\n      cmp = (llen > rlen) - (llen < rlen);\n      if (cmp == 0)\n        cmp = memcmp (lnum, rnum, llen);\n      if (lsign < 0)\n        cmp *= -1;\n    }\n\n  argv += 2;\n\n  /* Handle the special case where there are only two arguments.  */\n  if (!*argv && cmp == 0)\n    {\n      if (lsign < 0)\n        o = variable_buffer_output (o, \"-\", 1);\n      o = variable_buffer_output(o, lnum - !lsign, llen + !lsign);\n    }\n\n  free (lhs_str);\n  free (rhs_str);\n\n  if (*argv && cmp >= 0)\n    {\n      ++argv;\n      if (cmp > 0 && *argv && *(argv + 1))\n        ++argv;\n    }\n\n  if (*argv)\n    {\n      char *expansion = expand_argument (*argv, NULL);\n\n      o = variable_buffer_output (o, expansion, strlen (expansion));\n\n      free (expansion);\n    }\n\n  return o;\n}\n\n/*\n  $(if condition,true-part[,false-part])\n\n  CONDITION is false iff it evaluates to an empty string.  White\n  space before and after condition are stripped before evaluation.\n\n  If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is\n  evaluated (if it exists).  Because only one of the two PARTs is evaluated,\n  you can use $(if ...) to create side-effects (with $(shell ...), for\n  example).\n*/\n\nstatic char *\nfunc_if (char *o, char **argv, const char *funcname UNUSED)\n{\n  const char *begp = argv[0];\n  const char *endp = begp + strlen (argv[0]) - 1;\n  int result = 0;\n\n  /* Find the result of the condition: if we have a value, and it's not\n     empty, the condition is true.  If we don't have a value, or it's the\n     empty string, then it's false.  */\n\n  strip_whitespace (&begp, &endp);\n\n  if (begp <= endp)\n    {\n      char *expansion = expand_argument (begp, endp+1);\n\n      result = expansion[0] != '\\0';\n      free (expansion);\n    }\n\n  /* If the result is true (1) we want to eval the first argument, and if\n     it's false (0) we want to eval the second.  If the argument doesn't\n     exist we do nothing, otherwise expand it and add to the buffer.  */\n\n  argv += 1 + !result;\n\n  if (*argv)\n    {\n      char *expansion = expand_argument (*argv, NULL);\n\n      o = variable_buffer_output (o, expansion, strlen (expansion));\n\n      free (expansion);\n    }\n\n  return o;\n}\n\n/*\n  $(or condition1[,condition2[,condition3[...]]])\n\n  A CONDITION is false iff it evaluates to an empty string.  White\n  space before and after CONDITION are stripped before evaluation.\n\n  CONDITION1 is evaluated.  If it's true, then this is the result of\n  expansion.  If it's false, CONDITION2 is evaluated, and so on.  If none of\n  the conditions are true, the expansion is the empty string.\n\n  Once a CONDITION is true no further conditions are evaluated\n  (short-circuiting).\n*/\n\nstatic char *\nfunc_or (char *o, char **argv, const char *funcname UNUSED)\n{\n  for ( ; *argv ; ++argv)\n    {\n      const char *begp = *argv;\n      const char *endp = begp + strlen (*argv) - 1;\n      char *expansion;\n      size_t result = 0;\n\n      /* Find the result of the condition: if it's false keep going.  */\n\n      strip_whitespace (&begp, &endp);\n\n      if (begp > endp)\n        continue;\n\n      expansion = expand_argument (begp, endp+1);\n      result = strlen (expansion);\n\n      /* If the result is false keep going.  */\n      if (!result)\n        {\n          free (expansion);\n          continue;\n        }\n\n      /* It's true!  Keep this result and return.  */\n      o = variable_buffer_output (o, expansion, result);\n      free (expansion);\n      break;\n    }\n\n  return o;\n}\n\n/*\n  $(and condition1[,condition2[,condition3[...]]])\n\n  A CONDITION is false iff it evaluates to an empty string.  White\n  space before and after CONDITION are stripped before evaluation.\n\n  CONDITION1 is evaluated.  If it's false, then this is the result of\n  expansion.  If it's true, CONDITION2 is evaluated, and so on.  If all of\n  the conditions are true, the expansion is the result of the last condition.\n\n  Once a CONDITION is false no further conditions are evaluated\n  (short-circuiting).\n*/\n\nstatic char *\nfunc_and (char *o, char **argv, const char *funcname UNUSED)\n{\n  char *expansion;\n\n  while (1)\n    {\n      const char *begp = *argv;\n      const char *endp = begp + strlen (*argv) - 1;\n      size_t result;\n\n      /* An empty condition is always false.  */\n      strip_whitespace (&begp, &endp);\n      if (begp > endp)\n        return o;\n\n      expansion = expand_argument (begp, endp+1);\n      result = strlen (expansion);\n\n      /* If the result is false, stop here: we're done.  */\n      if (!result)\n        break;\n\n      /* Otherwise the result is true.  If this is the last one, keep this\n         result and quit.  Otherwise go on to the next one!  */\n\n      if (*(++argv))\n        free (expansion);\n      else\n        {\n          o = variable_buffer_output (o, expansion, result);\n          break;\n        }\n    }\n\n  free (expansion);\n\n  return o;\n}\n\nstatic char *\nfunc_wildcard (char *o, char **argv, const char *funcname UNUSED)\n{\n   char *p = string_glob (argv[0]);\n   o = variable_buffer_output (o, p, strlen (p));\n   return o;\n}\n\n/*\n  $(eval <makefile string>)\n\n  Always resolves to the empty string.\n\n  Treat the arguments as a segment of makefile, and parse them.\n*/\n\nstatic char *\nfunc_eval (char *o, char **argv, const char *funcname UNUSED)\n{\n  char *buf;\n  size_t len;\n\n  /* Eval the buffer.  Pop the current variable buffer setting so that the\n     eval'd code can use its own without conflicting.  */\n\n  install_variable_buffer (&buf, &len);\n\n  eval_buffer (argv[0], NULL);\n\n  restore_variable_buffer (buf, len);\n\n  return o;\n}\n\n\nstatic char *\nfunc_value (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* Look up the variable.  */\n  struct variable *v = lookup_variable (argv[0], strlen (argv[0]));\n\n  /* Copy its value into the output buffer without expanding it.  */\n  if (v)\n    o = variable_buffer_output (o, v->value, strlen (v->value));\n\n  return o;\n}\n\n/*\n  \\r is replaced on UNIX as well. Is this desirable?\n */\nstatic void\nfold_newlines (char *buffer, size_t *length, int trim_newlines)\n{\n  char *dst = buffer;\n  char *src = buffer;\n  char *last_nonnl = buffer - 1;\n  src[*length] = 0;\n  for (; *src != '\\0'; ++src)\n    {\n      if (src[0] == '\\r' && src[1] == '\\n')\n        continue;\n      if (*src == '\\n')\n        {\n          *dst++ = ' ';\n        }\n      else\n        {\n          last_nonnl = dst;\n          *dst++ = *src;\n        }\n    }\n\n  if (!trim_newlines && (last_nonnl < (dst - 2)))\n    last_nonnl = dst - 2;\n\n  *(++last_nonnl) = '\\0';\n  *length = last_nonnl - buffer;\n}\n\npid_t shell_function_pid = 0;\nstatic int shell_function_completed;\n\nvoid\nshell_completed (int exit_code, int exit_sig)\n{\n  char buf[INTSTR_LENGTH];\n\n  shell_function_pid = 0;\n  if (exit_sig == 0 && exit_code == 127)\n    shell_function_completed = -1;\n  else\n    shell_function_completed = 1;\n\n  if (exit_code == 0 && exit_sig > 0)\n    exit_code = 128 + exit_sig;\n\n  sprintf (buf, \"%d\", exit_code);\n  define_variable_cname (\".SHELLSTATUS\", buf, o_override, 0);\n}\n\n#if MK_OS_W32\n/*untested*/\n\n#include <windows.h>\n#include <io.h>\n#include \"sub_proc.h\"\n\n\nint\nwindows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, char **envp)\n{\n  SECURITY_ATTRIBUTES saAttr;\n  HANDLE hIn = INVALID_HANDLE_VALUE;\n  HANDLE hErr = INVALID_HANDLE_VALUE;\n  HANDLE hChildOutRd;\n  HANDLE hChildOutWr;\n  HANDLE hProcess, tmpIn, tmpErr;\n  DWORD e;\n\n  /* Set status for return.  */\n  pipedes[0] = pipedes[1] = -1;\n  *pid_p = (pid_t)-1;\n\n  saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);\n  saAttr.bInheritHandle = TRUE;\n  saAttr.lpSecurityDescriptor = NULL;\n\n  /* Standard handles returned by GetStdHandle can be NULL or\n     INVALID_HANDLE_VALUE if the parent process closed them.  If that\n     happens, we open the null device and pass its handle to\n     process_begin below as the corresponding handle to inherit.  */\n  tmpIn = GetStdHandle (STD_INPUT_HANDLE);\n  if (DuplicateHandle (GetCurrentProcess (), tmpIn,\n                       GetCurrentProcess (), &hIn,\n                       0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)\n    {\n      e = GetLastError ();\n      if (e == ERROR_INVALID_HANDLE)\n        {\n          tmpIn = CreateFile (\"NUL\", GENERIC_READ,\n                              FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n          if (tmpIn != INVALID_HANDLE_VALUE\n              && DuplicateHandle (GetCurrentProcess (), tmpIn,\n                                  GetCurrentProcess (), &hIn,\n                                  0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)\n            CloseHandle (tmpIn);\n        }\n      if (hIn == INVALID_HANDLE_VALUE)\n        {\n          ON (error, NILF,\n              _(\"windows32_openpipe: DuplicateHandle(In) failed (e=%lu)\"), e);\n          return -1;\n        }\n    }\n  tmpErr = get_handle_for_fd (errfd);\n  if (DuplicateHandle (GetCurrentProcess (), tmpErr,\n                       GetCurrentProcess (), &hErr,\n                       0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)\n    {\n      e = GetLastError ();\n      if (e == ERROR_INVALID_HANDLE)\n        {\n          tmpErr = CreateFile (\"NUL\", GENERIC_WRITE,\n                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n          if (tmpErr != INVALID_HANDLE_VALUE\n              && DuplicateHandle (GetCurrentProcess (), tmpErr,\n                                  GetCurrentProcess (), &hErr,\n                                  0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE)\n            CloseHandle (tmpErr);\n        }\n      if (hErr == INVALID_HANDLE_VALUE)\n        {\n          ON (error, NILF,\n              _(\"windows32_openpipe: DuplicateHandle(Err) failed (e=%lu)\"), e);\n          return -1;\n        }\n    }\n\n  if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0))\n    {\n      ON (error, NILF, _(\"CreatePipe() failed (e=%lu)\"), GetLastError());\n      return -1;\n    }\n\n  hProcess = process_init_fd (hIn, hChildOutWr, hErr);\n\n  if (!hProcess)\n    {\n      O (error, NILF, _(\"windows32_openpipe(): process_init_fd() failed\"));\n      return -1;\n    }\n\n  if (! process_begin (hProcess, command_argv, envp, command_argv[0], NULL))\n    {\n      /* register process for wait */\n      process_register (hProcess);\n\n      /* set the pid for returning to caller */\n      *pid_p = (pid_t) hProcess;\n\n      /* set up to read data from child */\n      pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY);\n\n      /* this will be closed almost right away */\n      pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND);\n      return 0;\n    }\n  else\n    {\n      /* reap/cleanup the failed process */\n      process_cleanup (hProcess);\n\n      /* close handles which were duplicated, they weren't used */\n      if (hIn != INVALID_HANDLE_VALUE)\n        CloseHandle (hIn);\n      if (hErr != INVALID_HANDLE_VALUE)\n        CloseHandle (hErr);\n\n      /* close pipe handles, they won't be used */\n      CloseHandle (hChildOutRd);\n      CloseHandle (hChildOutWr);\n\n      return -1;\n    }\n}\n#endif\n\n\n#if MK_OS_DOS\nFILE *\nmsdos_openpipe (int* pipedes, int *pidp, char *text)\n{\n  FILE *fpipe=0;\n  /* MSDOS can't fork, but it has 'popen'.  */\n  struct variable *sh = lookup_variable (\"SHELL\", 5);\n  int e;\n  extern int dos_command_running, dos_status;\n\n  /* Make sure not to bother processing an empty line.  */\n  NEXT_TOKEN (text);\n  if (*text == '\\0')\n    return 0;\n\n  if (sh)\n    {\n      char buf[PATH_MAX + 7];\n      /* This makes sure $SHELL value is used by $(shell), even\n         though the target environment is not passed to it.  */\n      sprintf (buf, \"SHELL=%s\", sh->value);\n      putenv (buf);\n    }\n\n  e = errno;\n  errno = 0;\n  dos_command_running = 1;\n  dos_status = 0;\n  /* If dos_status becomes non-zero, it means the child process\n     was interrupted by a signal, like SIGINT or SIGQUIT.  See\n     fatal_error_signal in commands.c.  */\n  fpipe = popen (text, \"rt\");\n  dos_command_running = 0;\n  if (!fpipe || dos_status)\n    {\n      pipedes[0] = -1;\n      *pidp = -1;\n      if (dos_status)\n        errno = EINTR;\n      else if (errno == 0)\n        errno = ENOMEM;\n      if (fpipe)\n        pclose (fpipe);\n      shell_completed (127, 0);\n    }\n  else\n    {\n      pipedes[0] = fileno (fpipe);\n      *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */\n      errno = e;\n    }\n  return fpipe;\n}\n#endif\n\n/*\n  Do shell spawning, with the naughty bits for different OSes.\n */\n\n#if MK_OS_VMS\n\n/* VMS can't do $(shell ...)  */\n\nchar *\nfunc_shell_base (char *o, char **argv, int trim_newlines)\n{\n  fprintf (stderr, \"This platform does not support shell\\n\");\n  die (MAKE_TROUBLE);\n  return NULL;\n}\n\n#define func_shell 0\n\n#else\nchar *\nfunc_shell_base (char *o, char **argv, int trim_newlines)\n{\n  struct childbase child = {0};\n  char *batch_filename = NULL;\n  int errfd;\n#if MK_OS_DOS\n  FILE *fpipe;\n#endif\n  char **command_argv = NULL;\n  int pipedes[2];\n  pid_t pid;\n\n#if !MK_OS_DOS\n#if MK_OS_W32\n  /* Reset just_print_flag.  This is needed on Windows when batch files\n     are used to run the commands, because we normally refrain from\n     creating batch files under -n.  */\n  int j_p_f = just_print_flag;\n  just_print_flag = 0;\n#endif\n\n  /* Construct the argument list.  */\n  command_argv = construct_command_argv (argv[0], NULL, NULL, 0,\n                                         &batch_filename);\n  if (command_argv == 0)\n    {\n#if MK_OS_W32\n      just_print_flag = j_p_f;\n#endif\n      return o;\n    }\n#endif /* !MK_OS_DOS */\n\n  /* Set up the output in case the shell writes something.  */\n  output_start ();\n\n  errfd = (output_context && output_context->err >= 0\n           ? output_context->err : FD_STDERR);\n\n  child.environment = target_environment (NULL, 0);\n\n#if MK_OS_DOS\n  fpipe = msdos_openpipe (pipedes, &pid, argv[0]);\n  if (pipedes[0] < 0)\n    {\n      OS (error, reading_file, \"pipe: %s\", strerror (errno));\n      pid = -1;\n      goto done;\n    }\n\n#elif MK_OS_W32\n  windows32_openpipe (pipedes, errfd, &pid, command_argv, child.environment);\n  /* Restore the value of just_print_flag.  */\n  just_print_flag = j_p_f;\n\n  if (pipedes[0] < 0)\n    {\n      /* Open of the pipe failed, mark as failed execution.  */\n      shell_completed (127, 0);\n      OS (error, reading_file, \"pipe: %s\", strerror (errno));\n      pid = -1;\n      goto done;\n    }\n\n#else\n  if (pipe (pipedes) < 0)\n    {\n      OS (error, reading_file, \"pipe: %s\", strerror (errno));\n      pid = -1;\n      goto done;\n    }\n\n  /* Close handles that are unnecessary for the child process.  */\n  fd_noinherit (pipedes[1]);\n  fd_noinherit (pipedes[0]);\n\n  child.output.syncout = 1;\n  child.output.out = pipedes[1];\n  child.output.err = errfd;\n\n  pid = child_execute_job (&child, 1, command_argv);\n\n  if (pid < 0)\n    {\n      shell_completed (127, 0);\n      goto done;\n    }\n#endif\n\n  {\n    char *buffer;\n    size_t maxlen, i;\n    int cc;\n\n    /* Record the PID for reap_children.  */\n    shell_function_pid = pid;\n#if !MK_OS_DOS\n    shell_function_completed = 0;\n\n    /* Close the write side of the pipe.  We test for -1, since\n       pipedes[1] is -1 on MS-Windows, and some versions of MS\n       libraries barf when 'close' is called with -1.  */\n    if (pipedes[1] >= 0)\n      close (pipedes[1]);\n#endif\n\n    /* Set up and read from the pipe.  */\n\n    maxlen = 200;\n    buffer = xmalloc (maxlen + 1);\n\n    /* Read from the pipe until it gets EOF.  */\n    for (i = 0; ; i += cc)\n      {\n        if (i == maxlen)\n          {\n            maxlen += 512;\n            buffer = xrealloc (buffer, maxlen + 1);\n          }\n\n        EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));\n        if (cc <= 0)\n          break;\n      }\n    buffer[i] = '\\0';\n\n    /* Close the read side of the pipe.  */\n#if MK_OS_DOS\n    if (fpipe)\n      {\n        int st = pclose (fpipe);\n        shell_completed (st, 0);\n      }\n#else\n    (void) close (pipedes[0]);\n#endif\n\n    /* Loop until child_handler or reap_children()  sets\n       shell_function_completed to the status of our child shell.  */\n    while (shell_function_completed == 0)\n      reap_children (1, 0);\n\n    if (batch_filename)\n      {\n        DB (DB_VERBOSE, (_(\"Cleaning up temporary batch file %s\\n\"),\n                         batch_filename));\n        remove (batch_filename);\n        free (batch_filename);\n      }\n    shell_function_pid = 0;\n\n    /* Replace all newlines in the command's output with spaces, and put that\n       in the variable output buffer.  */\n    fold_newlines (buffer, &i, trim_newlines);\n    o = variable_buffer_output (o, buffer, i);\n\n    free (buffer);\n  }\n\n done:\n  if (command_argv)\n    {\n      /* Free the storage only the child needed.  */\n      free (command_argv[0]);\n      free (command_argv);\n    }\n\n  free_childbase (&child);\n\n  return o;\n}\n\nstatic char *\nfunc_shell (char *o, char **argv, const char *funcname UNUSED)\n{\n  return func_shell_base (o, argv, 1);\n}\n#endif  /* !MK_OS_VMS */\n\n#ifdef EXPERIMENTAL\n\n/*\n  equality. Return is string-boolean, i.e., the empty string is false.\n */\nstatic char *\nfunc_eq (char *o, char **argv, char *funcname UNUSED)\n{\n  int result = ! strcmp (argv[0], argv[1]);\n  if (result)\n    o = variable_buffer_output (o,  \"1\", 1);\n  return o;\n}\n\n\n/*\n  string-boolean not operator.\n */\nstatic char *\nfunc_not (char *o, char **argv, char *funcname UNUSED)\n{\n  const char *s = argv[0];\n  int result = 0;\n  NEXT_TOKEN (s);\n  result = ! (*s);\n  if (result)\n    o = variable_buffer_output (o,  \"1\", 1);\n  return o;\n}\n#endif\n\f\n\n#ifdef HAVE_DOS_PATHS\n# ifdef __CYGWIN__\n#  define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || ISDIRSEP (n[0]))\n# else\n#  define IS_ABSOLUTE(n) (n[0] && n[1] == ':')\n# endif\n# define ROOT_LEN 3\n#else\n# define IS_ABSOLUTE(n) (n[0] == '/')\n# define ROOT_LEN 1\n#endif\n\n/* Return the absolute name of file NAME which does not contain any '.',\n   '..' components nor any repeated path separators ('/').   */\n\nstatic char *\nabspath (const char *name, char *apath)\n{\n  char *dest;\n  const char *start, *end, *apath_limit;\n  unsigned long root_len = ROOT_LEN;\n\n  if (name[0] == '\\0')\n    return NULL;\n\n  apath_limit = apath + GET_PATH_MAX;\n\n  if (!IS_ABSOLUTE(name))\n    {\n      /* It is unlikely we would make it until here but just to make sure. */\n      if (!starting_directory)\n        return NULL;\n\n      strcpy (apath, starting_directory);\n\n#ifdef HAVE_DOS_PATHS\n      if (ISDIRSEP (name[0]))\n        {\n          if (ISDIRSEP (name[1]))\n            {\n              /* A UNC.  Don't prepend a drive letter.  */\n              apath[0] = name[0];\n              apath[1] = name[1];\n              root_len = 2;\n            }\n          /* We have /foo, an absolute file name except for the drive\n             letter.  Assume the missing drive letter is the current\n             drive, which we can get if we remove from starting_directory\n             everything past the root directory.  */\n          apath[root_len] = '\\0';\n        }\n#endif\n\n      dest = strchr (apath, '\\0');\n    }\n  else\n    {\n#if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)\n      if (ISDIRSEP (name[0]))\n        root_len = 1;\n#endif\n      memcpy (apath, name, root_len);\n      apath[root_len] = '\\0';\n      dest = apath + root_len;\n      /* Get past the root, since we already copied it.  */\n      name += root_len;\n#ifdef HAVE_DOS_PATHS\n      if (! ISDIRSEP (apath[root_len - 1]))\n        {\n          /* Convert d:foo into d:./foo and increase root_len.  */\n          apath[2] = '.';\n          apath[3] = '/';\n          dest++;\n          root_len++;\n          /* strncpy above copied one character too many.  */\n          name--;\n        }\n      else\n        apath[root_len - 1] = '/'; /* make sure it's a forward slash */\n#endif\n    }\n\n  for (start = end = name; *start != '\\0'; start = end)\n    {\n      size_t len;\n\n      /* Skip sequence of multiple path-separators.  */\n      while (ISDIRSEP (*start))\n        ++start;\n\n      /* Find end of path component.  */\n      for (end = start; ! STOP_SET (*end, MAP_DIRSEP|MAP_NUL); ++end)\n        ;\n\n      len = end - start;\n\n      if (len == 0)\n        break;\n      else if (len == 1 && start[0] == '.')\n        /* nothing */;\n      else if (len == 2 && start[0] == '.' && start[1] == '.')\n        {\n          /* Back up to previous component, ignore if at root already.  */\n          if (dest > apath + root_len)\n            for (--dest; ! ISDIRSEP (dest[-1]); --dest)\n              ;\n        }\n      else\n        {\n          if (! ISDIRSEP (dest[-1]))\n            *dest++ = '/';\n\n          if (dest + len >= apath_limit)\n            return NULL;\n\n          dest = mempcpy (dest, start, len);\n          *dest = '\\0';\n        }\n    }\n\n  /* Unless it is root strip trailing separator.  */\n  if (dest > apath + root_len && ISDIRSEP (dest[-1]))\n    --dest;\n\n  *dest = '\\0';\n\n  return apath;\n}\n\n\nstatic char *\nfunc_realpath (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* Expand the argument.  */\n  const char *p = argv[0];\n  const char *path = 0;\n  int doneany = 0;\n  size_t len = 0;\n\n  while ((path = find_next_token (&p, &len)) != 0)\n    {\n      if (len < GET_PATH_MAX)\n        {\n          char *rp;\n          struct stat st;\n          PATH_VAR (in);\n          PATH_VAR (out);\n\n          strncpy (in, path, len);\n          in[len] = '\\0';\n\n#ifdef HAVE_REALPATH\n          ENULLLOOP (rp, realpath (in, out));\n# if defined _AIX\n          /* AIX realpath() doesn't remove trailing slashes correctly.  */\n          if (rp)\n            {\n              char *ep = rp + strlen (rp) - 1;\n              while (ep > rp && ep[0] == '/')\n                *(ep--) = '\\0';\n            }\n# endif\n#else\n          rp = abspath (in, out);\n#endif\n\n          if (rp)\n            {\n              int r;\n              EINTRLOOP (r, stat (out, &st));\n              if (r == 0)\n                {\n                  o = variable_buffer_output (o, out, strlen (out));\n                  o = variable_buffer_output (o, \" \", 1);\n                  doneany = 1;\n                }\n            }\n        }\n    }\n\n  /* Kill last space.  */\n  if (doneany)\n    --o;\n\n  return o;\n}\n\nstatic char *\nfunc_file (char *o, char **argv, const char *funcname UNUSED)\n{\n  char *fn = argv[0];\n\n  if (fn[0] == '>')\n    {\n      size_t len;\n      const char *end;\n      const char *start;\n      char *nm;\n      FILE *fp;\n      const char *mode = \"w\";\n\n      /* We are writing a file.  */\n      ++fn;\n      if (fn[0] == '>')\n        {\n          mode = \"a\";\n          ++fn;\n        }\n\n      start = next_token (fn);\n\n      if (start[0] == '\\0')\n        O (fatal, *expanding_var, _(\"file: missing filename\"));\n\n      end = end_of_token (start);\n      len = end - start;\n      nm = alloca (len + 1);\n      memcpy (nm, start, len);\n      nm[len] = '\\0';\n\n      ENULLLOOP (fp, fopen (nm, mode));\n      if (fp == NULL)\n        OSS (fatal, reading_file, _(\"open: %s: %s\"), nm, strerror (errno));\n\n      /* We've changed the contents of a directory, possibly.\n         Another option would be to look up the directory we changed and reset\n         its counter to 0.  */\n      ++command_count;\n\n      if (argv[1])\n        {\n          size_t l = strlen (argv[1]);\n          int nl = l == 0 || argv[1][l-1] != '\\n';\n\n          if (fputs (argv[1], fp) == EOF || (nl && fputc ('\\n', fp) == EOF))\n            OSS (fatal, reading_file, _(\"write: %s: %s\"), nm, strerror (errno));\n        }\n      if (fclose (fp))\n        OSS (fatal, reading_file, _(\"close: %s: %s\"), nm, strerror (errno));\n    }\n  else if (fn[0] == '<')\n    {\n      size_t n = 0;\n      size_t len;\n      const char *end;\n      const char *start;\n      char *nm;\n      FILE *fp;\n\n      start = next_token (fn + 1);\n\n      if (start[0] == '\\0')\n        O (fatal, *expanding_var, _(\"file: missing filename\"));\n\n      if (argv[1])\n        O (fatal, *expanding_var, _(\"file: too many arguments\"));\n\n      end = end_of_token (start);\n      len = end - start;\n      nm = alloca (len + 1);\n      memcpy (nm, start, len);\n      nm[len] = '\\0';\n\n      ENULLLOOP (fp, fopen (nm, \"r\"));\n      if (fp == NULL)\n        {\n          if (errno == ENOENT)\n            {\n              DB (DB_VERBOSE, (_(\"file: Failed to open '%s': %s\\n\"),\n                               nm, strerror (errno)));\n              return o;\n            }\n          OSS (fatal, reading_file, _(\"open: %s: %s\"), nm, strerror (errno));\n        }\n\n      while (1)\n        {\n          char buf[1024];\n          size_t l = fread (buf, 1, sizeof (buf), fp);\n          if (l > 0)\n            {\n              o = variable_buffer_output (o, buf, l);\n              n += l;\n            }\n          if (ferror (fp))\n            if (errno != EINTR)\n              OSS (fatal, reading_file, _(\"read: %s: %s\"), nm, strerror (errno));\n          if (feof (fp))\n            break;\n        }\n      if (fclose (fp))\n        OSS (fatal, reading_file, _(\"close: %s: %s\"), nm, strerror (errno));\n\n      /* Remove trailing newline.  */\n      if (n && o[-1] == '\\n')\n        o -= 1 + (n > 1 && o[-2] == '\\r');\n    }\n  else\n    OS (fatal, *expanding_var, _(\"file: invalid file operation: %s\"), fn);\n\n  return o;\n}\n\nstatic char *\nfunc_abspath (char *o, char **argv, const char *funcname UNUSED)\n{\n  /* Expand the argument.  */\n  const char *p = argv[0];\n  const char *path = 0;\n  int doneany = 0;\n  size_t len = 0;\n\n  while ((path = find_next_token (&p, &len)) != 0)\n    {\n      if (len < GET_PATH_MAX)\n        {\n          PATH_VAR (in);\n          PATH_VAR (out);\n\n          strncpy (in, path, len);\n          in[len] = '\\0';\n\n          if (abspath (in, out))\n            {\n              o = variable_buffer_output (o, out, strlen (out));\n              o = variable_buffer_output (o, \" \", 1);\n              doneany = 1;\n            }\n        }\n    }\n\n  /* Kill last space.  */\n  if (doneany)\n    --o;\n\n  return o;\n}\n\n/* Lookup table for builtin functions.\n\n   This doesn't have to be sorted; we use a straight lookup.  We might gain\n   some efficiency by moving most often used functions to the start of the\n   table.\n\n   If MAXIMUM_ARGS is 0, that means there is no maximum and all\n   comma-separated values are treated as arguments.\n\n   EXPAND_ARGS means that all arguments should be expanded before invocation.\n   Functions that do namespace tricks (foreach, let) don't automatically\n   expand.  */\n\nstatic char *func_call (char *o, char **argv, const char *funcname);\n\n#define FT_ENTRY(_name, _min, _max, _exp, _func) \\\n  { { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0, 0 }\n\nstatic struct function_table_entry function_table_init[] =\n{\n /*         Name            MIN MAX EXP? Function */\n  FT_ENTRY (\"abspath\",       0,  1,  1,  func_abspath),\n  FT_ENTRY (\"addprefix\",     2,  2,  1,  func_addsuffix_addprefix),\n  FT_ENTRY (\"addsuffix\",     2,  2,  1,  func_addsuffix_addprefix),\n  FT_ENTRY (\"and\",           1,  0,  0,  func_and),\n  FT_ENTRY (\"basename\",      0,  1,  1,  func_basename_dir),\n  FT_ENTRY (\"call\",          1,  0,  1,  func_call),\n  FT_ENTRY (\"dir\",           0,  1,  1,  func_basename_dir),\n  FT_ENTRY (\"error\",         0,  1,  1,  func_error),\n  FT_ENTRY (\"eval\",          0,  1,  1,  func_eval),\n  FT_ENTRY (\"file\",          1,  2,  1,  func_file),\n  FT_ENTRY (\"filter\",        2,  2,  1,  func_filter_filterout),\n  FT_ENTRY (\"filter-out\",    2,  2,  1,  func_filter_filterout),\n  FT_ENTRY (\"findstring\",    2,  2,  1,  func_findstring),\n  FT_ENTRY (\"firstword\",     0,  1,  1,  func_firstword),\n  FT_ENTRY (\"flavor\",        0,  1,  1,  func_flavor),\n  FT_ENTRY (\"foreach\",       3,  3,  0,  func_foreach),\n  FT_ENTRY (\"if\",            2,  3,  0,  func_if),\n  FT_ENTRY (\"info\",          0,  1,  1,  func_error),\n  FT_ENTRY (\"intcmp\",        2,  5,  0,  func_intcmp),\n  FT_ENTRY (\"join\",          2,  2,  1,  func_join),\n  FT_ENTRY (\"lastword\",      0,  1,  1,  func_lastword),\n  FT_ENTRY (\"let\",           3,  3,  0,  func_let),\n  FT_ENTRY (\"notdir\",        0,  1,  1,  func_notdir_suffix),\n  FT_ENTRY (\"or\",            1,  0,  0,  func_or),\n  FT_ENTRY (\"origin\",        0,  1,  1,  func_origin),\n  FT_ENTRY (\"patsubst\",      3,  3,  1,  func_patsubst),\n  FT_ENTRY (\"realpath\",      0,  1,  1,  func_realpath),\n  FT_ENTRY (\"shell\",         0,  1,  1,  func_shell),\n  FT_ENTRY (\"sort\",          0,  1,  1,  func_sort),\n  FT_ENTRY (\"strip\",         0,  1,  1,  func_strip),\n  FT_ENTRY (\"subst\",         3,  3,  1,  func_subst),\n  FT_ENTRY (\"suffix\",        0,  1,  1,  func_notdir_suffix),\n  FT_ENTRY (\"value\",         0,  1,  1,  func_value),\n  FT_ENTRY (\"warning\",       0,  1,  1,  func_error),\n  FT_ENTRY (\"wildcard\",      0,  1,  1,  func_wildcard),\n  FT_ENTRY (\"word\",          2,  2,  1,  func_word),\n  FT_ENTRY (\"wordlist\",      3,  3,  1,  func_wordlist),\n  FT_ENTRY (\"words\",         0,  1,  1,  func_words),\n#ifdef EXPERIMENTAL\n  FT_ENTRY (\"eq\",            2,  2,  1,  func_eq),\n  FT_ENTRY (\"not\",           0,  1,  1,  func_not),\n#endif\n};\n\f\n\n/* These must come after the definition of function_table.  */\n\nstatic char *\nexpand_builtin_function (char *o, unsigned int argc, char **argv,\n                         const struct function_table_entry *entry_p)\n{\n  char *p;\n\n  if (argc < entry_p->minimum_args)\n    fatal (*expanding_var, strlen (entry_p->name),\n           _(\"insufficient number of arguments (%u) to function '%s'\"),\n           argc, entry_p->name);\n\n  /* I suppose technically some function could do something with no arguments,\n     but so far no internal ones do, so just test it for all functions here\n     rather than in each one.  We can change it later if necessary.  */\n\n  if (!argc && !entry_p->alloc_fn)\n    return o;\n\n  if (!entry_p->fptr.func_ptr)\n    OS (fatal, *expanding_var,\n        _(\"unimplemented on this platform: function '%s'\"), entry_p->name);\n\n  if (entry_p->adds_command)\n    ++command_count;\n\n  if (!entry_p->alloc_fn)\n    return entry_p->fptr.func_ptr (o, argv, entry_p->name);\n\n  /* This function allocates memory and returns it to us.\n     Write it to the variable buffer, then free it.  */\n\n  p = entry_p->fptr.alloc_func_ptr (entry_p->name, argc, argv);\n  if (p)\n    {\n      o = variable_buffer_output (o, p, strlen (p));\n      free (p);\n    }\n\n  return o;\n}\n\n/* Check for a function invocation in *STRINGP.  *STRINGP points at the\n   opening ( or { and is not null-terminated.  If a function invocation\n   is found, expand it into the buffer at *OP, updating *OP, incrementing\n   *STRINGP past the reference, and return nonzero.\n   If no function is found, return zero and don't change *OP or *STRINGP.  */\n\nint\nhandle_function (char **op, const char **stringp)\n{\n  const struct function_table_entry *entry_p;\n  char openparen = (*stringp)[0];\n  char closeparen = openparen == '(' ? ')' : '}';\n  const char *beg;\n  const char *end;\n  int count = 0;\n  char *abeg = NULL;\n  char **argv, **argvp;\n  unsigned int nargs;\n\n  beg = *stringp + 1;\n\n  entry_p = lookup_function (beg);\n\n  if (!entry_p)\n    return 0;\n\n  /* We found a builtin function.  Find the beginning of its arguments (skip\n     whitespace after the name).  */\n\n  beg += entry_p->len;\n  NEXT_TOKEN (beg);\n\n  /* Find the end of the function invocation, counting nested use of whichever\n     kind of parens we use.  Don't use skip_reference so we can count commas\n     to get a rough estimate of how many arguments we might have.  The count\n     might be high, but it'll never be low.  */\n\n  for (nargs=1, end=beg; *end != '\\0'; ++end)\n    if (!STOP_SET (*end, MAP_VARSEP|MAP_COMMA))\n      continue;\n    else if (*end == ',')\n      ++nargs;\n    else if (*end == openparen)\n      ++count;\n    else if (*end == closeparen && --count < 0)\n      break;\n\n  if (count >= 0)\n    fatal (*expanding_var, strlen (entry_p->name),\n           _(\"unterminated call to function '%s': missing '%c'\"),\n           entry_p->name, closeparen);\n\n  *stringp = end;\n\n  /* Get some memory to store the arg pointers.  */\n  argvp = argv = alloca (sizeof (char *) * (nargs + 2));\n\n  /* Chop the string into arguments, then a nul.  As soon as we hit\n     MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the\n     last argument.\n\n     If we're expanding, store pointers to the expansion of each one.  If\n     not, make a duplicate of the string and point into that, nul-terminating\n     each argument.  */\n\n  if (entry_p->expand_args)\n    {\n      const char *p;\n      for (p=beg, nargs=0; p <= end; ++argvp)\n        {\n          const char *next;\n\n          ++nargs;\n\n          if (nargs == entry_p->maximum_args\n              || ((next = find_next_argument (openparen, closeparen, p, end)) == NULL))\n            next = end;\n\n          *argvp = expand_argument (p, next);\n          p = next + 1;\n        }\n    }\n  else\n    {\n      size_t len = end - beg;\n      char *p, *aend;\n\n      abeg = xmalloc (len+1);\n      aend = mempcpy (abeg, beg, len);\n      *aend = '\\0';\n\n      for (p=abeg, nargs=0; p <= aend; ++argvp)\n        {\n          char *next;\n\n          ++nargs;\n\n          if (nargs == entry_p->maximum_args\n              || ((next = find_next_argument (openparen, closeparen, p, aend)) == NULL))\n            next = aend;\n\n          *argvp = p;\n          *next = '\\0';\n          p = next + 1;\n        }\n    }\n  *argvp = NULL;\n\n  /* Finally!  Run the function...  */\n  *op = expand_builtin_function (*op, nargs, argv, entry_p);\n\n  /* Free memory.  */\n  if (entry_p->expand_args)\n    for (argvp=argv; *argvp != 0; ++argvp)\n      free (*argvp);\n  else\n    free (abeg);\n\n  return 1;\n}\n\f\n\n/* User-defined functions.  Expand the first argument as either a builtin\n   function or a make variable, in the context of the rest of the arguments\n   assigned to $1, $2, ... $N.  $0 is the name of the function.  */\n\nstatic char *\nfunc_call (char *o, char **argv, const char *funcname UNUSED)\n{\n  static unsigned int max_args = 0;\n  char *fname;\n  size_t flen;\n  unsigned int i;\n  int saved_args;\n  const struct function_table_entry *entry_p;\n  struct variable *v;\n\n  /* Clean up the name of the variable to be invoked.  */\n  fname = next_token (argv[0]);\n  end_of_token (fname)[0] = '\\0';\n\n  /* Calling nothing is a no-op */\n  if (*fname == '\\0')\n    return o;\n\n  /* Are we invoking a builtin function?  */\n\n  entry_p = lookup_function (fname);\n  if (entry_p)\n    {\n      /* How many arguments do we have?  */\n      for (i=0; argv[i+1]; ++i)\n        ;\n      return expand_builtin_function (o, i, argv+1, entry_p);\n    }\n\n  /* Not a builtin, so the first argument is the name of a variable to be\n     expanded and interpreted as a function.  Find it.  */\n  flen = strlen (fname);\n\n  v = lookup_variable (fname, flen);\n\n  if (v == 0)\n    warn_undefined (fname, flen);\n\n  if (v == 0 || *v->value == '\\0')\n    return o;\n\n  /* Set up arguments $(1) .. $(N).  $(0) is the function name.  */\n\n  push_new_variable_scope ();\n\n  for (i=0; *argv; ++i, ++argv)\n    {\n      char num[INTSTR_LENGTH];\n\n      sprintf (num, \"%u\", i);\n      define_variable (num, strlen (num), *argv, o_automatic, 0);\n    }\n\n  /* If the number of arguments we have is < max_args, it means we're inside\n     a recursive invocation of $(call ...).  Fill in the remaining arguments\n     in the new scope with the empty value, to hide them from this\n     invocation.  */\n\n  for (; i < max_args; ++i)\n    {\n      char num[INTSTR_LENGTH];\n\n      sprintf (num, \"%u\", i);\n      define_variable (num, strlen (num), \"\", o_automatic, 0);\n    }\n\n  /* Expand the function in the context of the arguments, adding the result to\n     the variable buffer.  */\n\n  v->exp_count = EXP_COUNT_MAX;\n\n  saved_args = max_args;\n  max_args = i;\n  o = expand_variable_output (o, fname, flen);\n  max_args = saved_args;\n\n  v->exp_count = 0;\n\n  pop_variable_scope ();\n\n  return o + strlen (o);\n}\n\nvoid\ndefine_new_function (const floc *flocp, const char *name,\n                     unsigned int min, unsigned int max, unsigned int flags,\n                     gmk_func_ptr func)\n{\n  const char *e = name;\n  struct function_table_entry *ent;\n  size_t len;\n\n  while (STOP_SET (*e, MAP_USERFUNC))\n    e++;\n  len = e - name;\n\n  if (len == 0)\n    O (fatal, flocp, _(\"empty function name\"));\n  if (*name == '.' || *e != '\\0')\n    OS (fatal, flocp, _(\"invalid function name: %s\"), name);\n  if (len > 255)\n    OS (fatal, flocp, _(\"function name too long: %s\"), name);\n  if (min > 255)\n    ONS (fatal, flocp,\n         _(\"invalid minimum argument count (%u) for function %s\"), min, name);\n  if (max > 255 || (max && max < min))\n    ONS (fatal, flocp,\n         _(\"invalid maximum argument count (%u) for function %s\"), max, name);\n\n  ent = xmalloc (sizeof (struct function_table_entry));\n  ent->name = strcache_add (name);\n  ent->len = (unsigned char) len;\n  ent->minimum_args = (unsigned char) min;\n  ent->maximum_args = (unsigned char) max;\n  ent->expand_args = ANY_SET(flags, GMK_FUNC_NOEXPAND) ? 0 : 1;\n  ent->alloc_fn = 1;\n  /* We don't know what this function will do.  */\n  ent->adds_command = 1;\n  ent->fptr.alloc_func_ptr = func;\n\n  ent = hash_insert (&function_table, ent);\n  free (ent);\n}\n\nvoid\nhash_init_function_table (void)\n{\n  hash_init (&function_table, ARRAYLEN (function_table_init) * 2,\n             function_table_entry_hash_1, function_table_entry_hash_2,\n             function_table_entry_hash_cmp);\n  hash_load (&function_table, function_table_init,\n             ARRAYLEN (function_table_init), sizeof (struct function_table_entry));\n}\n"
  },
  {
    "path": "src/getopt.c",
    "content": "/* Getopt for GNU.\nNOTE: getopt is now part of the C library, so if you don't know what\n\"Keep this file name-space clean\" means, talk to drepper@gnu.org\nbefore changing it!\n\nCopyright (C) 1987-2024 Free Software Foundation, Inc.\n\nNOTE: The canonical source of this file is maintained with the GNU C Library.\nBugs can be reported to bug-glibc@gnu.org.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.\n   Ditto for AIX 3.2 and <stdlib.h>.  */\n#ifndef _NO_PROTO\n# define _NO_PROTO\n#endif\n\n#ifdef HAVE_CONFIG_H\n# include <config.h>\n#endif\n\n#if !defined __STDC__ || !__STDC__\n/* This is a separate conditional since some stdc systems\n   reject `defined (const)'.  */\n# ifndef const\n#  define const\n# endif\n#endif\n\n#include <stdio.h>\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#define GETOPT_INTERFACE_VERSION 2\n#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2\n# include <gnu-versions.h>\n# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION\n#  define ELIDE_CODE\n# endif\n#endif\n\n#ifndef ELIDE_CODE\n\n\n/* This needs to come after some library #include\n   to get __GNU_LIBRARY__ defined.  */\n#ifdef\t__GNU_LIBRARY__\n/* Don't include stdlib.h for non-GNU C libraries because some of them\n   contain conflicting prototypes for getopt.  */\n# include <stdlib.h>\n# include <unistd.h>\n#endif\t/* GNU C library.  */\n\n#if MK_OS_VMS\n# include <unixlib.h>\n# if HAVE_STRING_H - 0\n#  include <string.h>\n# endif\n#endif\n\n/* This is for other GNU distributions with internationalized messages.\n   When compiling libc, the _ macro is predefined.  */\n#include \"gettext.h\"\n#define _(msgid)    gettext (msgid)\n\n\n/* This version of `getopt' appears to the caller like standard Unix 'getopt'\n   but it behaves differently for the user, since it allows the user\n   to intersperse the options with the other arguments.\n\n   As `getopt' works, it permutes the elements of ARGV so that,\n   when it is done, all the options precede everything else.  Thus\n   all application programs are extended to handle flexible argument order.\n\n   Setting the environment variable POSIXLY_CORRECT disables permutation.\n   Then the behavior is completely standard.\n\n   GNU application programs can use a third alternative mode in which\n   they can distinguish the relative order of options and other arguments.  */\n\n#include \"getopt.h\"\n\n/* For communication from `getopt' to the caller.\n   When `getopt' finds an option that takes an argument,\n   the argument value is returned here.\n   Also, when `ordering' is RETURN_IN_ORDER,\n   each non-option ARGV-element is returned here.  */\n\nchar *optarg = NULL;\n\n/* Index in ARGV of the next element to be scanned.\n   This is used for communication to and from the caller\n   and for communication between successive calls to `getopt'.\n\n   On entry to `getopt', zero means this is the first call; initialize.\n\n   When `getopt' returns -1, this is the index of the first of the\n   non-option elements that the caller should itself scan.\n\n   Otherwise, `optind' communicates from one call to the next\n   how much of ARGV has been scanned so far.  */\n\n/* 1003.2 says this must be 1 before any call.  */\nint optind = 1;\n\n/* Formerly, initialization of getopt depended on optind==0, which\n   causes problems with re-calling getopt as programs generally don't\n   know that. */\n\nint __getopt_initialized = 0;\n\n/* The next char to be scanned in the option-element\n   in which the last option character we returned was found.\n   This allows us to pick up the scan where we left off.\n\n   If this is zero, or a null string, it means resume the scan\n   by advancing to the next ARGV-element.  */\n\nstatic char *nextchar;\n\n/* Callers store zero here to inhibit the error message\n   for unrecognized options.  */\n\nint opterr = 1;\n\n/* Set to an option character which was unrecognized.\n   This must be initialized on some systems to avoid linking in the\n   system's own getopt implementation.  */\n\nint optopt = '?';\n\n/* Describe how to deal with options that follow non-option ARGV-elements.\n\n   If the caller did not specify anything,\n   the default is REQUIRE_ORDER if the environment variable\n   POSIXLY_CORRECT is defined, PERMUTE otherwise.\n\n   REQUIRE_ORDER means don't recognize them as options;\n   stop option processing when the first non-option is seen.\n   This is what Unix does.\n   This mode of operation is selected by either setting the environment\n   variable POSIXLY_CORRECT, or using `+' as the first character\n   of the list of option characters.\n\n   PERMUTE is the default.  We permute the contents of ARGV as we scan,\n   so that eventually all the non-options are at the end.  This allows options\n   to be given in any order, even with programs that were not written to\n   expect this.\n\n   RETURN_IN_ORDER is an option available to programs that were written\n   to expect options and other ARGV-elements in any order and that care about\n   the ordering of the two.  We describe each non-option ARGV-element\n   as if it were the argument of an option with character code 1.\n   Using `-' as the first character of the list of option characters\n   selects this mode of operation.\n\n   The special argument `--' forces an end of option-scanning regardless\n   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only\n   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */\n\nstatic enum\n{\n  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER\n} ordering;\n\n/* Value of POSIXLY_CORRECT environment variable.  */\nstatic char *posixly_correct;\n\f\n#ifdef\t__GNU_LIBRARY__\n/* We want to avoid inclusion of string.h with non-GNU libraries\n   because there are many ways it can cause trouble.\n   On some systems, it contains special magic macros that don't work\n   in GCC.  */\n# include <string.h>\n# define my_index\tstrchr\n#else\n\n# if HAVE_STRING_H\n#  include <string.h>\n# else\n#  include <strings.h>\n# endif\n\n/* Avoid depending on library functions or files\n   whose names are inconsistent.  */\n\n#ifndef getenv\nextern char *getenv ();\n#endif\n\nstatic char *\nmy_index (const char *str, int chr)\n{\n  while (*str)\n    {\n      if (*str == chr)\n\treturn (char *) str;\n      str++;\n    }\n  return 0;\n}\n\n/* If using GCC, we can safely declare strlen this way.\n   If not using GCC, it is ok not to declare it.  */\n#ifdef __GNUC__\n/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.\n   That was relevant to code that was here before.  */\n# if (!defined __STDC__ || !__STDC__) && !defined strlen\n/* gcc with -traditional declares the built-in strlen to return int,\n   and has done so at least since version 2.4.5. -- rms.  */\nextern int strlen (const char *);\n# endif /* not __STDC__ */\n#endif /* __GNUC__ */\n\n#endif /* not __GNU_LIBRARY__ */\n\f\n/* Handle permutation of arguments.  */\n\n/* Describe the part of ARGV that contains non-options that have\n   been skipped.  `first_nonopt' is the index in ARGV of the first of them;\n   `last_nonopt' is the index after the last of them.  */\n\nstatic int first_nonopt;\nstatic int last_nonopt;\n\n#ifdef _LIBC\n/* Bash 2.0 gives us an environment variable containing flags\n   indicating ARGV elements that should not be considered arguments.  */\n\n/* Defined in getopt_init.c  */\nextern char *__getopt_nonoption_flags;\n\nstatic int nonoption_flags_max_len;\nstatic int nonoption_flags_len;\n\nstatic int original_argc;\nstatic char *const *original_argv;\n\n/* Make sure the environment variable bash 2.0 puts in the environment\n   is valid for the getopt call we must make sure that the ARGV passed\n   to getopt is that one passed to the process.  */\nstatic void __attribute__ ((unused))\nstore_args_and_env (int argc, char *const *argv)\n{\n  /* XXX This is no good solution.  We should rather copy the args so\n     that we can compare them later.  But we must not use malloc(3).  */\n  original_argc = argc;\n  original_argv = argv;\n}\n# ifdef text_set_element\ntext_set_element (__libc_subinit, store_args_and_env);\n# endif /* text_set_element */\n\n# define SWAP_FLAGS(ch1, ch2) \\\n  if (nonoption_flags_len > 0)\t\t\t\t\t\t      \\\n    {\t\t\t\t\t\t\t\t\t      \\\n      char __tmp = __getopt_nonoption_flags[ch1];\t\t\t      \\\n      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];\t      \\\n      __getopt_nonoption_flags[ch2] = __tmp;\t\t\t\t      \\\n    }\n#else\t/* !_LIBC */\n# define SWAP_FLAGS(ch1, ch2)\n#endif\t/* _LIBC */\n\n/* Exchange two adjacent subsequences of ARGV.\n   One subsequence is elements [first_nonopt,last_nonopt)\n   which contains all the non-options that have been skipped so far.\n   The other is elements [last_nonopt,optind), which contains all\n   the options processed since those non-options were skipped.\n\n   `first_nonopt' and `last_nonopt' are relocated so that they describe\n   the new indices of the non-options in ARGV after they are moved.  */\n\n#if defined __STDC__ && __STDC__\nstatic void exchange (char **);\n#endif\n\nstatic void\nexchange (char **argv)\n{\n  int bottom = first_nonopt;\n  int middle = last_nonopt;\n  int top = optind;\n  char *tem;\n\n  /* Exchange the shorter segment with the far end of the longer segment.\n     That puts the shorter segment into the right place.\n     It leaves the longer segment in the right place overall,\n     but it consists of two parts that need to be swapped next.  */\n\n#ifdef _LIBC\n  /* First make sure the handling of the `__getopt_nonoption_flags'\n     string can work normally.  Our top argument must be in the range\n     of the string.  */\n  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)\n    {\n      /* We must extend the array.  The user plays games with us and\n\t presents new arguments.  */\n      char *new_str = malloc (top + 1);\n      if (new_str == NULL)\n\tnonoption_flags_len = nonoption_flags_max_len = 0;\n      else\n\t{\n\t  memset (__mempcpy (new_str, __getopt_nonoption_flags,\n\t\t\t     nonoption_flags_max_len),\n\t\t  '\\0', top + 1 - nonoption_flags_max_len);\n\t  nonoption_flags_max_len = top + 1;\n\t  __getopt_nonoption_flags = new_str;\n\t}\n    }\n#endif\n\n  while (top > middle && middle > bottom)\n    {\n      if (top - middle > middle - bottom)\n\t{\n\t  /* Bottom segment is the short one.  */\n\t  int len = middle - bottom;\n\t  register int i;\n\n\t  /* Swap it with the top part of the top segment.  */\n\t  for (i = 0; i < len; i++)\n\t    {\n\t      tem = argv[bottom + i];\n\t      argv[bottom + i] = argv[top - (middle - bottom) + i];\n\t      argv[top - (middle - bottom) + i] = tem;\n\t      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);\n\t    }\n\t  /* Exclude the moved bottom segment from further swapping.  */\n\t  top -= len;\n\t}\n      else\n\t{\n\t  /* Top segment is the short one.  */\n\t  int len = top - middle;\n\t  register int i;\n\n\t  /* Swap it with the bottom part of the bottom segment.  */\n\t  for (i = 0; i < len; i++)\n\t    {\n\t      tem = argv[bottom + i];\n\t      argv[bottom + i] = argv[middle + i];\n\t      argv[middle + i] = tem;\n\t      SWAP_FLAGS (bottom + i, middle + i);\n\t    }\n\t  /* Exclude the moved top segment from further swapping.  */\n\t  bottom += len;\n\t}\n    }\n\n  /* Update records for the slots the non-options now occupy.  */\n\n  first_nonopt += (optind - last_nonopt);\n  last_nonopt = optind;\n}\n\n/* Initialize the internal data when the first call is made.  */\n\n#if defined __STDC__ && __STDC__\nstatic const char *_getopt_initialize (int, char *const *, const char *);\n#endif\nstatic const char *\n_getopt_initialize (int argc, char *const *argv, const char *optstring)\n{\n  /* Start processing options with ARGV-element 1 (since ARGV-element 0\n     is the program name); the sequence of previously skipped\n     non-option ARGV-elements is empty.  */\n\n  first_nonopt = last_nonopt = optind;\n\n  nextchar = NULL;\n\n  posixly_correct = getenv (\"POSIXLY_CORRECT\");\n\n  /* Determine how to handle the ordering of options and nonoptions.  */\n\n  if (optstring[0] == '-')\n    {\n      ordering = RETURN_IN_ORDER;\n      ++optstring;\n    }\n  else if (optstring[0] == '+')\n    {\n      ordering = REQUIRE_ORDER;\n      ++optstring;\n    }\n  else if (posixly_correct != NULL)\n    ordering = REQUIRE_ORDER;\n  else\n    ordering = PERMUTE;\n\n#ifdef _LIBC\n  if (posixly_correct == NULL\n      && argc == original_argc && argv == original_argv)\n    {\n      if (nonoption_flags_max_len == 0)\n\t{\n\t  if (__getopt_nonoption_flags == NULL\n\t      || __getopt_nonoption_flags[0] == '\\0')\n\t    nonoption_flags_max_len = -1;\n\t  else\n\t    {\n\t      const char *orig_str = __getopt_nonoption_flags;\n\t      int len = nonoption_flags_max_len = strlen (orig_str);\n\t      if (nonoption_flags_max_len < argc)\n\t\tnonoption_flags_max_len = argc;\n\t      __getopt_nonoption_flags =\n\t\t(char *) malloc (nonoption_flags_max_len);\n\t      if (__getopt_nonoption_flags == NULL)\n\t\tnonoption_flags_max_len = -1;\n\t      else\n\t\tmemset (__mempcpy (__getopt_nonoption_flags, orig_str, len),\n\t\t\t'\\0', nonoption_flags_max_len - len);\n\t    }\n\t}\n      nonoption_flags_len = nonoption_flags_max_len;\n    }\n  else\n    nonoption_flags_len = 0;\n#endif\n\n  /* Make the compiler happy.  */\n  (void)argc;\n  (void)argv;\n\n  return optstring;\n}\n\f\n/* Scan elements of ARGV (whose length is ARGC) for option characters\n   given in OPTSTRING.\n\n   If an element of ARGV starts with '-', and is not exactly \"-\" or \"--\",\n   then it is an option element.  The characters of this element\n   (aside from the initial '-') are option characters.  If `getopt'\n   is called repeatedly, it returns successively each of the option characters\n   from each of the option elements.\n\n   If `getopt' finds another option character, it returns that character,\n   updating `optind' and `nextchar' so that the next call to `getopt' can\n   resume the scan with the following option character or ARGV-element.\n\n   If there are no more option characters, `getopt' returns -1.\n   Then `optind' is the index in ARGV of the first ARGV-element\n   that is not an option.  (The ARGV-elements have been permuted\n   so that those that are not options now come last.)\n\n   OPTSTRING is a string containing the legitimate option characters.\n   If an option character is seen that is not listed in OPTSTRING,\n   return '?' after printing an error message.  If you set `opterr' to\n   zero, the error message is suppressed but we still return '?'.\n\n   If a char in OPTSTRING is followed by a colon, that means it wants an arg,\n   so the following text in the same ARGV-element, or the text of the following\n   ARGV-element, is returned in `optarg'.  Two colons mean an option that\n   wants an optional arg; if there is text in the current ARGV-element,\n   it is returned in `optarg', otherwise `optarg' is set to zero.\n\n   If OPTSTRING starts with `-' or `+', it requests different methods of\n   handling the non-option ARGV-elements.\n   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.\n\n   Long-named options begin with `--' instead of `-'.\n   Their names may be abbreviated as long as the abbreviation is unique\n   or is an exact match for some defined option.  If they have an\n   argument, it follows the option name in the same ARGV-element, separated\n   from the option name by a `=', or else the in next ARGV-element.\n   When `getopt' finds a long-named option, it returns 0 if that option's\n   `flag' field is nonzero, the value of the option's `val' field\n   if the `flag' field is zero.\n\n   The elements of ARGV aren't really const, because we permute them.\n   But we pretend they're const in the prototype to be compatible\n   with other systems.\n\n   LONGOPTS is a vector of `struct option' terminated by an\n   element containing a name which is zero.\n\n   LONGIND returns the index in LONGOPT of the long-named option found.\n   It is only valid when a long-named option has been found by the most\n   recent call.\n\n   If LONG_ONLY is nonzero, '-' as well as '--' can introduce\n   long-named options.  */\n\nint\n_getopt_internal (int argc, char *const *argv, const char *optstring,\n                  const struct option *longopts, int *longind, int long_only)\n{\n  optarg = NULL;\n\n  if (optind == 0 || !__getopt_initialized)\n    {\n      if (optind == 0)\n\toptind = 1;\t/* Don't scan ARGV[0], the program name.  */\n      optstring = _getopt_initialize (argc, argv, optstring);\n      __getopt_initialized = 1;\n    }\n\n  /* Test whether ARGV[optind] points to a non-option argument.\n     Either it does not have option syntax, or there is an environment flag\n     from the shell indicating it is not an option.  The later information\n     is only used when the used in the GNU libc.  */\n#ifdef _LIBC\n# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\\0'\t      \\\n\t\t      || (optind < nonoption_flags_len\t\t\t      \\\n\t\t\t  && __getopt_nonoption_flags[optind] == '1'))\n#else\n# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\\0')\n#endif\n\n  if (nextchar == NULL || *nextchar == '\\0')\n    {\n      /* Advance to the next ARGV-element.  */\n\n      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been\n\t moved back by the user (who may also have changed the arguments).  */\n      if (last_nonopt > optind)\n\tlast_nonopt = optind;\n      if (first_nonopt > optind)\n\tfirst_nonopt = optind;\n\n      if (ordering == PERMUTE)\n\t{\n\t  /* If we have just processed some options following some non-options,\n\t     exchange them so that the options come first.  */\n\n\t  if (first_nonopt != last_nonopt && last_nonopt != optind)\n\t    exchange ((char **) argv);\n\t  else if (last_nonopt != optind)\n\t    first_nonopt = optind;\n\n\t  /* Skip any additional non-options\n\t     and extend the range of non-options previously skipped.  */\n\n\t  while (optind < argc && NONOPTION_P)\n\t    optind++;\n\t  last_nonopt = optind;\n\t}\n\n      /* The special ARGV-element `--' means premature end of options.\n\t Skip it like a null option,\n\t then exchange with previous non-options as if it were an option,\n\t then skip everything else like a non-option.  */\n\n      if (optind != argc && !strcmp (argv[optind], \"--\"))\n\t{\n\t  optind++;\n\n\t  if (first_nonopt != last_nonopt && last_nonopt != optind)\n\t    exchange ((char **) argv);\n\t  else if (first_nonopt == last_nonopt)\n\t    first_nonopt = optind;\n\t  last_nonopt = argc;\n\n\t  optind = argc;\n\t}\n\n      /* If we have done all the ARGV-elements, stop the scan\n\t and back over any non-options that we skipped and permuted.  */\n\n      if (optind == argc)\n\t{\n\t  /* Set the next-arg-index to point at the non-options\n\t     that we previously skipped, so the caller will digest them.  */\n\t  if (first_nonopt != last_nonopt)\n\t    optind = first_nonopt;\n\t  return -1;\n\t}\n\n      /* If we have come to a non-option and did not permute it,\n\t either stop the scan or describe it to the caller and pass it by.  */\n\n      if (NONOPTION_P)\n\t{\n\t  if (ordering == REQUIRE_ORDER)\n\t    return -1;\n\t  optarg = argv[optind++];\n\t  return 1;\n\t}\n\n      /* We have found another option-ARGV-element.\n\t Skip the initial punctuation.  */\n\n      nextchar = (argv[optind] + 1\n\t\t  + (longopts != NULL && argv[optind][1] == '-'));\n    }\n\n  /* Decode the current option-ARGV-element.  */\n\n  /* Check whether the ARGV-element is a long option.\n\n     If long_only and the ARGV-element has the form \"-f\", where f is\n     a valid short option, don't consider it an abbreviated form of\n     a long option that starts with f.  Otherwise there would be no\n     way to give the -f short option.\n\n     On the other hand, if there's a long option \"fubar\" and\n     the ARGV-element is \"-fu\", do consider that an abbreviation of\n     the long option, just like \"--fu\", and not \"-f\" with arg \"u\".\n\n     This distinction seems to be the most useful approach.  */\n\n  if (longopts != NULL\n      && (argv[optind][1] == '-'\n\t  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))\n    {\n      char *nameend;\n      const struct option *p;\n      const struct option *pfound = NULL;\n      int exact = 0;\n      int ambig = 0;\n      int indfound = -1;\n      int option_index;\n\n      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)\n\t/* Do nothing.  */ ;\n\n      /* Test all long options for either exact match\n\t or abbreviated matches.  */\n      for (p = longopts, option_index = 0; p->name; p++, option_index++)\n\tif (!strncmp (p->name, nextchar, nameend - nextchar))\n\t  {\n\t    if ((unsigned int) (nameend - nextchar)\n\t\t== (unsigned int) strlen (p->name))\n\t      {\n\t\t/* Exact match found.  */\n\t\tpfound = p;\n\t\tindfound = option_index;\n\t\texact = 1;\n\t\tbreak;\n\t      }\n\t    else if (pfound == NULL)\n\t      {\n\t\t/* First nonexact match found.  */\n\t\tpfound = p;\n\t\tindfound = option_index;\n\t      }\n\t    else\n\t      /* Second or later nonexact match found.  */\n\t      ambig = 1;\n\t  }\n\n      if (ambig && !exact)\n\t{\n\t  if (opterr)\n\t    fprintf (stderr, _(\"%s: option '%s' is ambiguous\\n\"),\n\t\t     argv[0], argv[optind]);\n\t  nextchar += strlen (nextchar);\n\t  optind++;\n\t  optopt = 0;\n\t  return '?';\n\t}\n\n      if (pfound != NULL)\n\t{\n\t  option_index = indfound;\n\t  optind++;\n\t  if (*nameend)\n\t    {\n\t      /* Don't test has_arg with >, because some C compilers don't\n\t\t allow it to be used on enums.  */\n\t      if (pfound->has_arg)\n\t\toptarg = nameend + 1;\n\t      else\n\t\t{\n\t\t  if (opterr)\n\t\t    {\n\t\t      if (argv[optind - 1][1] == '-')\n\t\t        /* --option */\n\t\t        fprintf (stderr,\n\t\t                 _(\"%s: option '--%s' doesn't allow an argument\\n\"),\n\t\t                 argv[0], pfound->name);\n\t\t      else\n\t\t        /* +option or -option */\n\t\t        fprintf (stderr,\n\t\t                 _(\"%s: option '%c%s' doesn't allow an argument\\n\"),\n\t\t                 argv[0], argv[optind - 1][0], pfound->name);\n\t\t    }\n\t\t  nextchar += strlen (nextchar);\n\n\t\t  optopt = pfound->val;\n\t\t  return '?';\n\t\t}\n\t    }\n\t  else if (pfound->has_arg == 1)\n\t    {\n\t      if (optind < argc)\n\t\toptarg = argv[optind++];\n\t      else\n\t\t{\n\t\t  if (opterr)\n\t\t    fprintf (stderr,\n\t\t\t   _(\"%s: option '%s' requires an argument\\n\"),\n\t\t\t   argv[0], argv[optind - 1]);\n\t\t  nextchar += strlen (nextchar);\n\t\t  optopt = pfound->val;\n\t\t  return optstring[0] == ':' ? ':' : '?';\n\t\t}\n\t    }\n\t  nextchar += strlen (nextchar);\n\t  if (longind != NULL)\n\t    *longind = option_index;\n\t  if (pfound->flag)\n\t    {\n\t      *(pfound->flag) = pfound->val;\n\t      return 0;\n\t    }\n\t  return pfound->val;\n\t}\n\n      /* Can't find it as a long option.  If this is not getopt_long_only,\n\t or the option starts with '--' or is not a valid short\n\t option, then it's an error.\n\t Otherwise interpret it as a short option.  */\n      if (!long_only || argv[optind][1] == '-'\n\t  || my_index (optstring, *nextchar) == NULL)\n\t{\n\t  if (opterr)\n\t    {\n\t      if (argv[optind][1] == '-')\n\t\t/* --option */\n\t\tfprintf (stderr, _(\"%s: unrecognized option '--%s'\\n\"),\n\t\t\t argv[0], nextchar);\n\t      else\n\t\t/* +option or -option */\n\t\tfprintf (stderr, _(\"%s: unrecognized option '%c%s'\\n\"),\n\t\t\t argv[0], argv[optind][0], nextchar);\n\t    }\n\t  nextchar = (char *) \"\";\n\t  optind++;\n\t  optopt = 0;\n\t  return '?';\n\t}\n    }\n\n  /* Look at and handle the next short option-character.  */\n\n  {\n    char c = *nextchar++;\n    char *temp = my_index (optstring, c);\n\n    /* Increment `optind' when we start to process its last character.  */\n    if (*nextchar == '\\0')\n      ++optind;\n\n    if (temp == NULL || c == ':')\n      {\n\tif (opterr)\n\t  {\n\t    if (posixly_correct)\n\t      /* 1003.2 specifies the format of this message.  */\n\t      fprintf (stderr, _(\"%s: illegal option -- %c\\n\"),\n\t\t       argv[0], c);\n\t    else\n\t      fprintf (stderr, _(\"%s: invalid option -- %c\\n\"),\n\t\t       argv[0], c);\n\t  }\n\toptopt = c;\n\treturn '?';\n      }\n    /* Convenience. Treat POSIX -W foo same as long option --foo */\n    if (temp[0] == 'W' && temp[1] == ';')\n      {\n\tchar *nameend;\n\tconst struct option *p;\n\tconst struct option *pfound = NULL;\n\tint exact = 0;\n\tint ambig = 0;\n\tint indfound = 0;\n\tint option_index;\n\n\t/* This is an option that requires an argument.  */\n\tif (*nextchar != '\\0')\n\t  {\n\t    optarg = nextchar;\n\t    /* If we end this ARGV-element by taking the rest as an arg,\n\t       we must advance to the next element now.  */\n\t    optind++;\n\t  }\n\telse if (optind == argc)\n\t  {\n\t    if (opterr)\n\t      {\n\t\t/* 1003.2 specifies the format of this message.  */\n\t\tfprintf (stderr, _(\"%s: option requires an argument -- %c\\n\"),\n\t\t\t argv[0], c);\n\t      }\n\t    optopt = c;\n\t    if (optstring[0] == ':')\n\t      c = ':';\n\t    else\n\t      c = '?';\n\t    return c;\n\t  }\n\telse\n\t  /* We already incremented `optind' once;\n\t     increment it again when taking next ARGV-elt as argument.  */\n\t  optarg = argv[optind++];\n\n\t/* optarg is now the argument, see if it's in the\n\t   table of longopts.  */\n\n\tfor (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)\n\t  /* Do nothing.  */ ;\n\n\t/* Test all long options for either exact match\n\t   or abbreviated matches.  */\n\tfor (p = longopts, option_index = 0; p->name; p++, option_index++)\n\t  if (!strncmp (p->name, nextchar, nameend - nextchar))\n\t    {\n\t      if ((unsigned int) (nameend - nextchar) == strlen (p->name))\n\t\t{\n\t\t  /* Exact match found.  */\n\t\t  pfound = p;\n\t\t  indfound = option_index;\n\t\t  exact = 1;\n\t\t  break;\n\t\t}\n\t      else if (pfound == NULL)\n\t\t{\n\t\t  /* First nonexact match found.  */\n\t\t  pfound = p;\n\t\t  indfound = option_index;\n\t\t}\n\t      else\n\t\t/* Second or later nonexact match found.  */\n\t\tambig = 1;\n\t    }\n\tif (ambig && !exact)\n\t  {\n\t    if (opterr)\n\t      fprintf (stderr, _(\"%s: option '-W %s' is ambiguous\\n\"),\n\t\t       argv[0], argv[optind]);\n\t    nextchar += strlen (nextchar);\n\t    optind++;\n\t    return '?';\n\t  }\n\tif (pfound != NULL)\n\t  {\n\t    option_index = indfound;\n\t    if (*nameend)\n\t      {\n\t\t/* Don't test has_arg with >, because some C compilers don't\n\t\t   allow it to be used on enums.  */\n\t\tif (pfound->has_arg)\n\t\t  optarg = nameend + 1;\n\t\telse\n\t\t  {\n\t\t    if (opterr)\n\t\t      fprintf (stderr, _(\"\\\n%s: option '-W %s' doesn't allow an argument\\n\"),\n\t\t\t       argv[0], pfound->name);\n\n\t\t    nextchar += strlen (nextchar);\n\t\t    return '?';\n\t\t  }\n\t      }\n\t    else if (pfound->has_arg == 1)\n\t      {\n\t\tif (optind < argc)\n\t\t  optarg = argv[optind++];\n\t\telse\n\t\t  {\n\t\t    if (opterr)\n\t\t      fprintf (stderr,\n\t\t\t       _(\"%s: option '%s' requires an argument\\n\"),\n\t\t\t       argv[0], argv[optind - 1]);\n\t\t    nextchar += strlen (nextchar);\n\t\t    return optstring[0] == ':' ? ':' : '?';\n\t\t  }\n\t      }\n\t    nextchar += strlen (nextchar);\n\t    if (longind != NULL)\n\t      *longind = option_index;\n\t    if (pfound->flag)\n\t      {\n\t\t*(pfound->flag) = pfound->val;\n\t\treturn 0;\n\t      }\n\t    return pfound->val;\n\t  }\n\t  nextchar = NULL;\n\t  return 'W';\t/* Let the application handle it.   */\n      }\n    if (temp[1] == ':')\n      {\n\tif (temp[2] == ':')\n\t  {\n\t    /* This is an option that accepts an argument optionally.  */\n\t    if (*nextchar != '\\0')\n\t      {\n\t\toptarg = nextchar;\n\t\toptind++;\n\t      }\n\t    else\n\t      optarg = NULL;\n\t    nextchar = NULL;\n\t  }\n\telse\n\t  {\n\t    /* This is an option that requires an argument.  */\n\t    if (*nextchar != '\\0')\n\t      {\n\t\toptarg = nextchar;\n\t\t/* If we end this ARGV-element by taking the rest as an arg,\n\t\t   we must advance to the next element now.  */\n\t\toptind++;\n\t      }\n\t    else if (optind == argc)\n\t      {\n\t\tif (opterr)\n\t\t  {\n\t\t    /* 1003.2 specifies the format of this message.  */\n\t\t    fprintf (stderr,\n\t\t\t   _(\"%s: option requires an argument -- %c\\n\"),\n\t\t\t   argv[0], c);\n\t\t  }\n\t\toptopt = c;\n\t\tif (optstring[0] == ':')\n\t\t  c = ':';\n\t\telse\n\t\t  c = '?';\n\t      }\n\t    else\n\t      /* We already incremented `optind' once;\n\t\t increment it again when taking next ARGV-elt as argument.  */\n\t      optarg = argv[optind++];\n\t    nextchar = NULL;\n\t  }\n      }\n    return c;\n  }\n}\n\nint\ngetopt (int argc, char *const *argv, const char *optstring)\n{\n  return _getopt_internal (argc, argv, optstring,\n\t\t\t   (const struct option *) 0,\n\t\t\t   (int *) 0,\n\t\t\t   0);\n}\n\n#endif\t/* Not ELIDE_CODE.  */\n\f\n#ifdef TEST\n\n/* Compile with -DTEST to make an executable for use in testing\n   the above definition of `getopt'.  */\n\nint\nmain (int argc, char **argv)\n{\n  int c;\n  int digit_optind = 0;\n\n  while (1)\n    {\n      int this_option_optind = optind ? optind : 1;\n\n      c = getopt (argc, argv, \"abc:d:0123456789\");\n      if (c == -1)\n\tbreak;\n\n      switch (c)\n\t{\n\tcase '0':\n\tcase '1':\n\tcase '2':\n\tcase '3':\n\tcase '4':\n\tcase '5':\n\tcase '6':\n\tcase '7':\n\tcase '8':\n\tcase '9':\n\t  if (digit_optind != 0 && digit_optind != this_option_optind)\n\t    printf (\"digits occur in two different argv-elements.\\n\");\n\t  digit_optind = this_option_optind;\n\t  printf (\"option %c\\n\", c);\n\t  break;\n\n\tcase 'a':\n\t  printf (\"option a\\n\");\n\t  break;\n\n\tcase 'b':\n\t  printf (\"option b\\n\");\n\t  break;\n\n\tcase 'c':\n\t  printf (\"option c with value '%s'\\n\", optarg);\n\t  break;\n\n\tcase '?':\n\t  break;\n\n\tdefault:\n\t  printf (\"?? getopt returned character code 0%o ??\\n\", c);\n\t}\n    }\n\n  if (optind < argc)\n    {\n      printf (\"non-option ARGV-elements: \");\n      while (optind < argc)\n\tprintf (\"%s \", argv[optind++]);\n      printf (\"\\n\");\n    }\n\n  exit (0);\n}\n\n#endif /* TEST */\n"
  },
  {
    "path": "src/getopt.h",
    "content": "/* Declarations for getopt.\nCopyright (C) 1989-2024 Free Software Foundation, Inc.\n\nNOTE: The canonical source of this file is maintained with the GNU C Library.\nBugs can be reported to bug-glibc@gnu.org.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _GETOPT_H\n#define _GETOPT_H 1\n\n#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n/* For communication from `getopt' to the caller.\n   When `getopt' finds an option that takes an argument,\n   the argument value is returned here.\n   Also, when `ordering' is RETURN_IN_ORDER,\n   each non-option ARGV-element is returned here.  */\n\nextern char *optarg;\n\n/* Index in ARGV of the next element to be scanned.\n   This is used for communication to and from the caller\n   and for communication between successive calls to `getopt'.\n\n   On entry to `getopt', zero means this is the first call; initialize.\n\n   When `getopt' returns -1, this is the index of the first of the\n   non-option elements that the caller should itself scan.\n\n   Otherwise, `optind' communicates from one call to the next\n   how much of ARGV has been scanned so far.  */\n\nextern int optind;\n\n/* Callers store zero here to inhibit the error message `getopt' prints\n   for unrecognized options.  */\n\nextern int opterr;\n\n/* Set to an option character which was unrecognized.  */\n\nextern int optopt;\n\n/* Describe the long-named options requested by the application.\n   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector\n   of `struct option' terminated by an element containing a name which is\n   zero.\n\n   The field `has_arg' is:\n   no_argument\t\t(or 0) if the option does not take an argument,\n   required_argument\t(or 1) if the option requires an argument,\n   optional_argument \t(or 2) if the option takes an optional argument.\n\n   If the field `flag' is not NULL, it points to a variable that is set\n   to the value given in the field `val' when the option is found, but\n   left unchanged if the option is not found.\n\n   To have a long-named option do something other than set an `int' to\n   a compiled-in constant, such as set a value from `optarg', set the\n   option's `flag' field to zero and its `val' field to a nonzero\n   value (the equivalent single-letter option character, if there is\n   one).  For long options that have a zero `flag' field, `getopt'\n   returns the contents of the `val' field.  */\n\nstruct option\n{\n#if defined (__STDC__) && __STDC__\n  const char *name;\n#else\n  char *name;\n#endif\n  /* has_arg can't be an enum because some compilers complain about\n     type mismatches in all the code that assumes it is an int.  */\n  int has_arg;\n  int *flag;\n  int val;\n};\n\n/* Names for the values of the `has_arg' field of `struct option'.  */\n\n#define\tno_argument\t\t0\n#define required_argument\t1\n#define optional_argument\t2\n\n#if defined (__STDC__) && __STDC__\n#ifdef __GNU_LIBRARY__\n/* Many other libraries have conflicting prototypes for getopt, with\n   differences in the consts, in stdlib.h.  To avoid compilation\n   errors, only prototype getopt for the GNU C library.  */\nextern int getopt (int argc, char *const *argv, const char *shortopts);\n#else /* not __GNU_LIBRARY__ */\nextern int getopt ();\n#endif /* __GNU_LIBRARY__ */\nextern int getopt_long (int argc, char *const *argv, const char *shortopts,\n\t\t        const struct option *longopts, int *longind);\nextern int getopt_long_only (int argc, char *const *argv,\n\t\t\t     const char *shortopts,\n\t\t             const struct option *longopts, int *longind);\n\n/* Internal only.  Users should not call this directly.  */\nextern int _getopt_internal (int argc, char *const *argv,\n\t\t\t     const char *shortopts,\n\t\t             const struct option *longopts, int *longind,\n\t\t\t     int long_only);\n#else /* not __STDC__ */\nextern int getopt ();\nextern int getopt_long ();\nextern int getopt_long_only ();\n\nextern int _getopt_internal ();\n#endif /* __STDC__ */\n\n#ifdef\t__cplusplus\n}\n#endif\n\n#endif /* getopt.h */\n"
  },
  {
    "path": "src/getopt1.c",
    "content": "/* getopt_long and getopt_long_only entry points for GNU getopt.\nCopyright (C) 1987-1994, 1996-2024 Free Software Foundation, Inc.\n\nNOTE: The canonical source of this file is maintained with the GNU C Library.\nBugs can be reported to bug-glibc@gnu.org.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\f\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"getopt.h\"\n\n#if !defined __STDC__ || !__STDC__\n/* This is a separate conditional since some stdc systems\n   reject `defined (const)'.  */\n#ifndef const\n#define const\n#endif\n#endif\n\n#include <stdio.h>\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#define GETOPT_INTERFACE_VERSION 2\n#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2\n#include <gnu-versions.h>\n#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION\n#define ELIDE_CODE\n#endif\n#endif\n\n#ifndef ELIDE_CODE\n\n\n/* This needs to come after some library #include\n   to get __GNU_LIBRARY__ defined.  */\n#ifdef __GNU_LIBRARY__\n#include <stdlib.h>\n#endif\n\n#ifndef\tNULL\n#define NULL 0\n#endif\n\nint\ngetopt_long (int argc, char *const *argv, const char *options,\n             const struct option *long_options, int *opt_index)\n{\n  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);\n}\n\n/* Like getopt_long, but '-' as well as '--' can indicate a long option.\n   If an option that starts with '-' (not '--') doesn't match a long option,\n   but does match a short option, it is parsed as a short option\n   instead.  */\n\nint\ngetopt_long_only (int argc, char *const *argv, const char *options,\n                  const struct option *long_options, int *opt_index)\n{\n  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);\n}\n\n\n#endif\t/* Not ELIDE_CODE.  */\n\f\n#ifdef TEST\n\n#include <stdio.h>\n\nint\nmain (int argc, char **argv)\n{\n  int c;\n  int digit_optind = 0;\n\n  while (1)\n    {\n      int this_option_optind = optind ? optind : 1;\n      int option_index = 0;\n      static struct option long_options[] =\n      {\n\t{\"add\", 1, 0, 0},\n\t{\"append\", 0, 0, 0},\n\t{\"delete\", 1, 0, 0},\n\t{\"verbose\", 0, 0, 0},\n\t{\"create\", 0, 0, 0},\n\t{\"file\", 1, 0, 0},\n\t{0, 0, 0, 0}\n      };\n\n      c = getopt_long (argc, argv, \"abc:d:0123456789\",\n\t\t       long_options, &option_index);\n      if (c == -1)\n\tbreak;\n\n      switch (c)\n\t{\n\tcase 0:\n\t  printf (\"option %s\", long_options[option_index].name);\n\t  if (optarg)\n\t    printf (\" with arg %s\", optarg);\n\t  printf (\"\\n\");\n\t  break;\n\n\tcase '0':\n\tcase '1':\n\tcase '2':\n\tcase '3':\n\tcase '4':\n\tcase '5':\n\tcase '6':\n\tcase '7':\n\tcase '8':\n\tcase '9':\n\t  if (digit_optind != 0 && digit_optind != this_option_optind)\n\t    printf (\"digits occur in two different argv-elements.\\n\");\n\t  digit_optind = this_option_optind;\n\t  printf (\"option %c\\n\", c);\n\t  break;\n\n\tcase 'a':\n\t  printf (\"option a\\n\");\n\t  break;\n\n\tcase 'b':\n\t  printf (\"option b\\n\");\n\t  break;\n\n\tcase 'c':\n\t  printf (\"option c with value '%s'\\n\", optarg);\n\t  break;\n\n\tcase 'd':\n\t  printf (\"option d with value '%s'\\n\", optarg);\n\t  break;\n\n\tcase '?':\n\t  break;\n\n\tdefault:\n\t  printf (\"?? getopt returned character code 0%o ??\\n\", c);\n\t}\n    }\n\n  if (optind < argc)\n    {\n      printf (\"non-option ARGV-elements: \");\n      while (optind < argc)\n\tprintf (\"%s \", argv[optind++]);\n      printf (\"\\n\");\n    }\n\n  exit (0);\n}\n\n#endif /* TEST */\n"
  },
  {
    "path": "src/gettext.h",
    "content": "/* Convenience header for conditional use of GNU <libintl.h>.\nCopyright (C) 1995-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _LIBGETTEXT_H\n#define _LIBGETTEXT_H 1\n\n/* NLS can be disabled through the configure --disable-nls option.  */\n#if ENABLE_NLS\n\n/* Get declarations of GNU message catalog functions.  */\n# include <libintl.h>\n\n#else\n\n/* Disabled NLS.\n   The casts to 'const char *' serve the purpose of producing warnings\n   for invalid uses of the value returned from these functions.\n   On pre-ANSI systems without 'const', the config.h file is supposed to\n   contain \"#define const\".  */\n# define gettext(Msgid) ((const char *) (Msgid))\n# define dgettext(Domainname, Msgid) ((const char *) (Msgid))\n# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))\n# define ngettext(Msgid1, Msgid2, N) \\\n    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))\n# define dngettext(Domainname, Msgid1, Msgid2, N) \\\n    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))\n# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \\\n    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))\n# define textdomain(Domainname) ((const char *) (Domainname))\n# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))\n# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))\n\n#endif\n\n/* A pseudo function call that serves as a marker for the automated\n   extraction of messages, but does not call gettext().  The run-time\n   translation is done at a different place in the code.\n   The argument, String, should be a literal string.  Concatenated strings\n   and other string expressions won't work.\n   The macro's expansion is not parenthesized, so that it is suitable as\n   initializer for static 'char[]' or 'const char[]' variables.  */\n#define gettext_noop(String) String\n\n#endif /* _LIBGETTEXT_H */\n"
  },
  {
    "path": "src/gmk-default.scm",
    "content": ";; Contents of the (GNU Make) Guile module\n;; Copyright (C) 2011-2024 Free Software Foundation, Inc.\n;; This file is part of GNU Make.\n;;\n;; GNU Make is free software; you can redistribute it and/or modify it under\n;; the terms of the GNU General Public License as published by the Free\n;; Software Foundation; either version 3 of the License, or (at your option)\n;; any later version.\n;;\n;; GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n;; FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n;; details.\n;;\n;; You should have received a copy of the GNU General Public License along\n;; with this program.  If not, see <https://www.gnu.org/licenses/>.\n\n(define (to-string-maybe x)\n  (cond\n   ;; In GNU Make, \"false\" is the empty string\n   ((or (not x)\n        (unspecified? x)\n        (variable? x)\n        (null? x)\n        (and (string? x) (string-null? x)))\n    #f)\n   ;; We want something not false... not sure about this\n   ((eq? x #t) \"#t\")\n   ;; Basics\n   ((or (symbol? x) (number? x))\n    (object->string x))\n   ((char? x)\n    (string x))\n   ;; Printable string (no special characters)\n   ((and (string? x) (string-every char-set:printing x))\n    x)\n   ;; No idea: fail\n   (else (error \"Unknown object:\" x))))\n\n(define (obj-to-str x)\n  (let ((acc '()))\n    (define (walk x)\n      (cond ((pair? x) (walk (car x)) (walk (cdr x)))\n            ((to-string-maybe x) => (lambda (s) (set! acc (cons s acc))))))\n    (walk x)\n    (string-join (reverse! acc))))\n\n;; Return the value of the GNU Make variable V\n(define (gmk-var v)\n  (gmk-expand (format #f \"$(~a)\" (obj-to-str v))))\n\n;; Export the public interfaces\n(export gmk-expand gmk-eval gmk-var)\n"
  },
  {
    "path": "src/gnumake.h",
    "content": "/* External interfaces usable by dynamic objects loaded into GNU Make.\n\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _GNUMAKE_H_\n#define _GNUMAKE_H_\n\n#define GMK_ABI_VERSION 1\n\n/* Specify the location of elements read from makefiles.  */\ntypedef struct\n  {\n    const char *filenm;\n    unsigned long lineno;\n  } gmk_floc;\n\ntypedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv);\n\n/* When an object is loaded by GNU Make, a setup method will be invoked.\n   The name of the method is either derived from the filename of the object,\n   or specified explicitly in the makefile.  It has the signature:\n\n     int <setup_fn> (unsigned int abi_version, const gmk_floc *flocp);\n\n   The abi_version will be set to GMK_ABI_VERSION.\n\n   When an object is unloaded by GNU Make, an unload method will be invoked.\n   The name of the method is derived from the filename of the object, with\n   _gmk_unload appended.  It has the signature:\n\n     void <object>_gmk_unload (void);\n\n  There will only be one unload method invoked regardless of the number of\n  setup methods within the object.  */\n\n#ifdef _WIN32\n# ifdef GMK_BUILDING_MAKE\n#  define GMK_EXPORT  __declspec(dllexport)\n# else\n#  define GMK_EXPORT  __declspec(dllimport)\n# endif\n#else\n# define GMK_EXPORT\n#endif\n\n/* Free memory returned by the gmk_expand() and gmk_free() functions.  */\nGMK_EXPORT void gmk_free (char *str);\n\n/* Allocate memory in GNU Make's context.  */\nGMK_EXPORT char *gmk_alloc (unsigned int len);\n\n/* Run $(eval ...) on the provided string BUFFER.  */\nGMK_EXPORT void gmk_eval (const char *buffer, const gmk_floc *floc);\n\n/* Run GNU Make expansion on the provided string STR.\n   Returns an allocated buffer that the caller must free with gmk_free().  */\nGMK_EXPORT char *gmk_expand (const char *str);\n\n/* Register a new GNU Make function NAME (maximum of 255 chars long).\n   When the function is expanded in the makefile, FUNC will be invoked with\n   the appropriate arguments.\n\n   The return value of FUNC must be either NULL, in which case it expands to\n   the empty string, or a pointer to the result of the expansion in a string\n   created by gmk_alloc().  GNU Make will free the memory when it's done.\n\n   MIN_ARGS is the minimum number of arguments the function requires.\n   MAX_ARGS is the maximum number of arguments (or 0 if there's no maximum).\n   MIN_ARGS and MAX_ARGS may not exceed 255.\n\n   The FLAGS value may be GMK_FUNC_DEFAULT, or one or more of the following\n   flags OR'd together:\n\n     GMK_FUNC_NOEXPAND: the arguments to the function will be not be expanded\n                        before FUNC is called.\n*/\nGMK_EXPORT void gmk_add_function (const char *name, gmk_func_ptr func,\n                                  unsigned int min_args, unsigned int max_args,\n                                  unsigned int flags);\n\n#define GMK_FUNC_DEFAULT    0x00\n#define GMK_FUNC_NOEXPAND   0x01\n\n#endif  /* _GNUMAKE_H_ */\n"
  },
  {
    "path": "src/guile.c",
    "content": "/* GNU Guile interface for GNU Make.\nCopyright (C) 2011-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#ifdef HAVE_GUILE\n\n#include \"gnumake.h\"\n\n#include \"debug.h\"\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"variable.h\"\n\n#include <libguile.h>\n\n/* Pre-2.0 versions of Guile don't have a typedef for gsubr function types.  */\n#if SCM_MAJOR_VERSION < 2\n# define GSUBR_TYPE         SCM (*) ()\n/* Guile 1.x doesn't really support i18n.  */\n# define EVAL_STRING(_s)    scm_c_eval_string (_s)\n#else\n# define GSUBR_TYPE         scm_t_subr\n# define EVAL_STRING(_s)    scm_eval_string (scm_from_utf8_string (_s))\n#endif\n\nstatic SCM make_mod = SCM_EOL;\nstatic SCM obj_to_str = SCM_EOL;\n\n/* Convert an SCM object into a string.  */\nstatic char *\ncvt_scm_to_str (SCM obj)\n{\n  return scm_to_locale_string (scm_call_1 (obj_to_str, obj));\n}\n\n/* Perform the GNU Make expansion function.  */\nstatic SCM\nguile_expand_wrapper (SCM obj)\n{\n  char *str = cvt_scm_to_str (obj);\n  SCM ret;\n  char *res;\n\n  DB (DB_BASIC, (_(\"guile: Expanding '%s'\\n\"), str));\n  res = gmk_expand (str);\n  ret = scm_from_locale_string (res);\n\n  free (str);\n  free (res);\n\n  return ret;\n}\n\n/* Perform the GNU Make eval function.  */\nstatic SCM\nguile_eval_wrapper (SCM obj)\n{\n  char *str = cvt_scm_to_str (obj);\n\n  DB (DB_BASIC, (_(\"guile: Evaluating '%s'\\n\"), str));\n  gmk_eval (str, 0);\n\n  return SCM_BOOL_F;\n}\n\n/* Invoked by scm_c_define_module(), in the context of the GNU Make module.  */\nstatic void\nguile_define_module (void *data UNUSED)\n{\n/* Ingest the predefined Guile module for GNU Make.  */\n#include \"gmk-default.h\"\n\n  /* Register a subr for GNU Make's eval capability.  */\n  scm_c_define_gsubr (\"gmk-expand\", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper);\n\n  /* Register a subr for GNU Make's eval capability.  */\n  scm_c_define_gsubr (\"gmk-eval\", 1, 0, 0, (GSUBR_TYPE) guile_eval_wrapper);\n\n  /* Define the rest of the module.  */\n  scm_c_eval_string (GUILE_module_defn);\n}\n\n/* Initialize the GNU Make Guile module.  */\nstatic void *\nguile_init (void *arg UNUSED)\n{\n  /* Define the module.  */\n  make_mod = scm_c_define_module (\"gnu make\", guile_define_module, NULL);\n\n  /* Get a reference to the object-to-string translator, for later.  */\n  obj_to_str = scm_variable_ref (scm_c_module_lookup (make_mod, \"obj-to-str\"));\n\n  /* Import the GNU Make module exports into the generic space.  */\n  scm_c_eval_string (\"(use-modules (gnu make))\");\n\n  return NULL;\n}\n\nstatic void *\ninternal_guile_eval (void *arg)\n{\n  return cvt_scm_to_str (EVAL_STRING (arg));\n}\n\n/* This is the function registered with make  */\nstatic char *\nfunc_guile (const char *funcname UNUSED, unsigned int argc UNUSED, char **argv)\n{\n  static int init = 0;\n\n  if (! init)\n    {\n      /* Initialize the Guile interpreter.  */\n      scm_with_guile (guile_init, NULL);\n      init = 1;\n    }\n\n  if (argv[0] && argv[0][0] != '\\0')\n    return scm_with_guile (internal_guile_eval, argv[0]);\n\n  return NULL;\n}\n\n/* ----- Public interface ----- */\n\n/* We could send the flocp to define_new_function(), but since guile is\n   \"kind of\" built-in, that didn't seem so useful.  */\nint\nguile_gmake_setup (const floc *flocp UNUSED)\n{\n  /* Create a make function \"guile\".  */\n  gmk_add_function (\"guile\", func_guile, 0, 1, GMK_FUNC_DEFAULT);\n\n  return 1;\n}\n\n#else\n\nint\nguile_gmake_setup (const floc *flocp UNUSED)\n{\n  return 1;\n}\n\n#endif\n"
  },
  {
    "path": "src/hash.c",
    "content": "/* hash.c -- hash table maintenance\nCopyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc.\nWritten by Greg McGary <gkm@gnu.org> <greg@mcgary.org>\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"hash.h\"\n#include <assert.h>\n\n#define CALLOC(t, n) ((t *) xcalloc (sizeof (t) * (n)))\n#define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))\n#define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n)))\n#define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n)))\n\nstatic void hash_rehash __P((struct hash_table* ht));\nstatic unsigned long round_up_2 __P((unsigned long rough));\n\n/* Implement double hashing with open addressing.  The table size is\n   always a power of two.  The secondary ('increment') hash function\n   is forced to return an odd-value, in order to be relatively prime\n   to the table size.  This guarantees that the increment can\n   potentially hit every slot in the table during collision\n   resolution.  */\n\nvoid *hash_deleted_item = &hash_deleted_item;\n\n/* Force the table size to be a power of two, possibly rounding up the\n   given size.  */\n\nvoid\nhash_init (struct hash_table *ht, unsigned long size,\n           hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp)\n{\n  ht->ht_size = round_up_2 (size);\n  ht->ht_empty_slots = ht->ht_size;\n  ht->ht_vec = CALLOC (void *, ht->ht_size);\n  if (ht->ht_vec == 0)\n    {\n      fprintf (stderr, _(\"can't allocate %lu bytes for hash table: memory exhausted\"),\n               ht->ht_size * (unsigned long) sizeof (void *));\n      exit (MAKE_TROUBLE);\n    }\n\n  ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */\n  ht->ht_fill = 0;\n  ht->ht_collisions = 0;\n  ht->ht_lookups = 0;\n  ht->ht_rehashes = 0;\n  ht->ht_hash_1 = hash_1;\n  ht->ht_hash_2 = hash_2;\n  ht->ht_compare = hash_cmp;\n}\n\n/* Load an array of items into 'ht'.  */\n\nvoid\nhash_load (struct hash_table *ht, void *item_table,\n           unsigned long cardinality, unsigned long size)\n{\n  char *items = (char *) item_table;\n  while (cardinality--)\n    {\n      hash_insert (ht, items);\n      items += size;\n    }\n}\n\n/* Returns the address of the table slot matching 'key'.  If 'key' is\n   not found, return the address of an empty slot suitable for\n   inserting 'key'.  The caller is responsible for incrementing\n   ht_fill on insertion.  */\n\nvoid **\nhash_find_slot (struct hash_table *ht, const void *key)\n{\n  void **slot;\n  void **deleted_slot = 0;\n  unsigned int hash_2 = 0;\n  unsigned int hash_1 = (*ht->ht_hash_1) (key);\n\n  ht->ht_lookups++;\n  for (;;)\n    {\n      hash_1 &= (ht->ht_size - 1);\n      slot = &ht->ht_vec[hash_1];\n\n      if (*slot == 0)\n        return (deleted_slot ? deleted_slot : slot);\n      if (*slot == hash_deleted_item)\n        {\n          if (deleted_slot == 0)\n            deleted_slot = slot;\n        }\n      else\n        {\n          if (key == *slot)\n            return slot;\n          if ((*ht->ht_compare) (key, *slot) == 0)\n            return slot;\n          ht->ht_collisions++;\n        }\n      if (!hash_2)\n          hash_2 = (*ht->ht_hash_2) (key) | 1;\n      hash_1 += hash_2;\n    }\n}\n\nvoid *\nhash_find_item (struct hash_table *ht, const void *key)\n{\n  void **slot = hash_find_slot (ht, key);\n  return ((HASH_VACANT (*slot)) ? 0 : *slot);\n}\n\nvoid *\nhash_insert (struct hash_table *ht, const void *item)\n{\n  void **slot = hash_find_slot (ht, item);\n  const void *old_item = *slot;\n  hash_insert_at (ht, item, slot);\n  return (void *)((HASH_VACANT (old_item)) ? 0 : old_item);\n}\n\nvoid *\nhash_insert_at (struct hash_table *ht, const void *item, const void *slot)\n{\n  const void *old_item = *(void **) slot;\n  if (HASH_VACANT (old_item))\n    {\n      ht->ht_fill++;\n      if (old_item == 0)\n        ht->ht_empty_slots--;\n      old_item = item;\n    }\n  *(void const **) slot = item;\n  if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity)\n    {\n      hash_rehash (ht);\n      return (void *) hash_find_slot (ht, item);\n    }\n  else\n    return (void *) slot;\n}\n\nvoid *\nhash_delete (struct hash_table *ht, const void *item)\n{\n  void **slot = hash_find_slot (ht, item);\n  return hash_delete_at (ht, slot);\n}\n\nvoid *\nhash_delete_at (struct hash_table *ht, const void *slot)\n{\n  void *item = *(void **) slot;\n  if (!HASH_VACANT (item))\n    {\n      *(void const **) slot = hash_deleted_item;\n      ht->ht_fill--;\n      return item;\n    }\n  else\n    return 0;\n}\n\nvoid\nhash_free_items (struct hash_table *ht)\n{\n  void **vec = ht->ht_vec;\n  void **end = &vec[ht->ht_size];\n  for (; vec < end; vec++)\n    {\n      void *item = *vec;\n      if (!HASH_VACANT (item))\n        free (item);\n      *vec = 0;\n    }\n  ht->ht_fill = 0;\n  ht->ht_empty_slots = ht->ht_size;\n}\n\nvoid\nhash_delete_items (struct hash_table *ht)\n{\n  void **vec = ht->ht_vec;\n  void **end = &vec[ht->ht_size];\n  for (; vec < end; vec++)\n    *vec = 0;\n  ht->ht_fill = 0;\n  ht->ht_collisions = 0;\n  ht->ht_lookups = 0;\n  ht->ht_rehashes = 0;\n  ht->ht_empty_slots = ht->ht_size;\n}\n\nvoid\nhash_free (struct hash_table *ht, int free_items)\n{\n  if (free_items)\n    hash_free_items (ht);\n  else\n    {\n      ht->ht_fill = 0;\n      ht->ht_empty_slots = ht->ht_size;\n    }\n  free (ht->ht_vec);\n  ht->ht_vec = 0;\n  ht->ht_capacity = 0;\n}\n\nvoid\nhash_map (struct hash_table *ht, hash_map_func_t map)\n{\n  void **slot;\n  void **end = &ht->ht_vec[ht->ht_size];\n\n  for (slot = ht->ht_vec; slot < end; slot++)\n    {\n      if (!HASH_VACANT (*slot))\n        (*map) (*slot);\n    }\n}\n\nvoid\nhash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg)\n{\n  void **slot;\n  void **end = &ht->ht_vec[ht->ht_size];\n\n  for (slot = ht->ht_vec; slot < end; slot++)\n    {\n      if (!HASH_VACANT (*slot))\n        (*map) (*slot, arg);\n    }\n}\n\n/* Double the size of the hash table in the event of overflow... */\n\nstatic void\nhash_rehash (struct hash_table *ht)\n{\n  unsigned long old_ht_size = ht->ht_size;\n  void **old_vec = ht->ht_vec;\n  void **ovp;\n\n  if (ht->ht_fill >= ht->ht_capacity)\n    {\n      ht->ht_size *= 2;\n      ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4);\n    }\n  ht->ht_rehashes++;\n  ht->ht_vec = CALLOC (void *, ht->ht_size);\n\n  for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)\n    {\n      if (! HASH_VACANT (*ovp))\n        {\n          void **slot = hash_find_slot (ht, *ovp);\n          *slot = *ovp;\n        }\n    }\n  ht->ht_empty_slots = ht->ht_size - ht->ht_fill;\n  free (old_vec);\n}\n\nvoid\nhash_print_stats (struct hash_table *ht, FILE *out_FILE)\n{\n  fprintf (out_FILE, _(\"Load=%lu/%lu=%.0f%%, \"), ht->ht_fill, ht->ht_size,\n           100.0 * (double) ht->ht_fill / (double) ht->ht_size);\n  fprintf (out_FILE, _(\"Rehash=%u, \"), ht->ht_rehashes);\n  fprintf (out_FILE, _(\"Collisions=%lu/%lu=%.0f%%\"), ht->ht_collisions, ht->ht_lookups,\n           (ht->ht_lookups\n            ? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups)\n            : 0));\n}\n\n/* Dump all items into a NULL-terminated vector.  Use the\n   user-supplied vector, or malloc one.  */\n\nvoid **\nhash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare)\n{\n  void **vector;\n  void **slot;\n  void **end = &ht->ht_vec[ht->ht_size];\n\n  if (vector_0 == 0)\n    vector_0 = MALLOC (void *, ht->ht_fill + 1);\n  vector = vector_0;\n\n  for (slot = ht->ht_vec; slot < end; slot++)\n    if (!HASH_VACANT (*slot))\n      *vector++ = *slot;\n  *vector = 0;\n\n  if (compare)\n    qsort (vector_0, ht->ht_fill, sizeof (void *), compare);\n  return vector_0;\n}\n\n/* Round a given number up to the nearest power of 2. */\n\nstatic unsigned long\nround_up_2 (unsigned long n)\n{\n  n |= (n >> 1);\n  n |= (n >> 2);\n  n |= (n >> 4);\n  n |= (n >> 8);\n  n |= (n >> 16);\n\n#if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295\n  /* We only need this on systems where unsigned long is >32 bits.  */\n  n |= (n >> 32);\n#endif\n\n  return n + 1;\n}\n\n#define rol32(v, n) \\\n        ((v) << (n) | ((v) >> (32 - (n))))\n\n/* jhash_mix -- mix 3 32-bit values reversibly. */\n#define jhash_mix(a, b, c)                      \\\n{                                               \\\n        a -= c;  a ^= rol32(c, 4);  c += b;     \\\n        b -= a;  b ^= rol32(a, 6);  a += c;     \\\n        c -= b;  c ^= rol32(b, 8);  b += a;     \\\n        a -= c;  a ^= rol32(c, 16); c += b;     \\\n        b -= a;  b ^= rol32(a, 19); a += c;     \\\n        c -= b;  c ^= rol32(b, 4);  b += a;     \\\n}\n\n/* jhash_final - final mixing of 3 32-bit values (a,b,c) into c */\n#define jhash_final(a, b, c)                    \\\n{                                               \\\n        c ^= b; c -= rol32(b, 14);              \\\n        a ^= c; a -= rol32(c, 11);              \\\n        b ^= a; b -= rol32(a, 25);              \\\n        c ^= b; c -= rol32(b, 16);              \\\n        a ^= c; a -= rol32(c, 4);               \\\n        b ^= a; b -= rol32(a, 14);              \\\n        c ^= b; c -= rol32(b, 24);              \\\n}\n\n/* An arbitrary initial parameter */\n#define JHASH_INITVAL           0xdeadbeef\n\n#define sum_get_unaligned_32(r, p)              \\\n  do {                                          \\\n    unsigned int val;                           \\\n    memcpy (&val, (p), 4);                      \\\n    r += val;                                   \\\n  } while(0);\n\nunsigned int\njhash(unsigned const char *k, int length)\n{\n  unsigned int a, b, c;\n\n  /* Set up the internal state */\n  a = b = c = JHASH_INITVAL + length;\n\n  /* All but the last block: affect some 32 bits of (a,b,c) */\n  while (length > 12) {\n    sum_get_unaligned_32(a, k);\n    sum_get_unaligned_32(b, k + 4);\n    sum_get_unaligned_32(c, k + 8);\n    jhash_mix(a, b, c);\n    length -= 12;\n    k += 12;\n  }\n\n  if (!length)\n    return c;\n\n  if (length > 8)\n    {\n      sum_get_unaligned_32(a, k);\n      length -= 4;\n      k += 4;\n    }\n  if (length > 4)\n    {\n      sum_get_unaligned_32(b, k);\n      length -= 4;\n      k += 4;\n    }\n\n  if (length == 4)\n    c += (unsigned)k[3]<<24;\n  if (length >= 3)\n    c += (unsigned)k[2]<<16;\n  if (length >= 2)\n    c += (unsigned)k[1]<<8;\n  c += k[0];\n  jhash_final(a, b, c);\n  return c;\n}\n\n#define UINTSZ sizeof (unsigned int)\n\n#ifdef WORDS_BIGENDIAN\n/* The ifs are ordered from the first byte in memory to the last.\n   Help the compiler optimize by using static memcpy length.  */\n#define sum_up_to_nul(r, p, plen, flag)   \\\n  do {                                    \\\n    unsigned int val = 0;                 \\\n    size_t pn = (plen);                   \\\n    if (pn >= UINTSZ)                     \\\n      memcpy (&val, (p), UINTSZ);         \\\n    else                                  \\\n      memcpy (&val, (p), pn);             \\\n    if ((val & 0xFF000000) == 0)          \\\n      flag = 1;                           \\\n    else if ((val & 0xFF0000) == 0)       \\\n      r += val & ~0xFFFF, flag = 1;       \\\n    else if ((val & 0xFF00) == 0)         \\\n      r += val & ~0xFF, flag = 1;         \\\n    else                                  \\\n      r += val, flag = (val & 0xFF) == 0; \\\n  } while (0)\n#else\n/* First detect the presence of zeroes.  If there is none, we can\n   sum the 4 bytes directly.  Otherwise, the ifs are ordered as in the\n   big endian case, from the first byte in memory to the last.\n   Help the compiler optimize by using static memcpy length.  */\n#define sum_up_to_nul(r, p, plen, flag)              \\\n  do {                                               \\\n    unsigned int val = 0;                            \\\n    size_t pn = (plen);                              \\\n    if (pn >= UINTSZ)                                \\\n      memcpy (&val, (p), UINTSZ);                    \\\n    else                                             \\\n      memcpy (&val, (p), pn);                        \\\n    flag = ((val - 0x01010101) & ~val) & 0x80808080; \\\n    if (!flag)                                       \\\n      r += val;                                      \\\n    else if (val & 0xFF)                             \\\n      {                                              \\\n        if ((val & 0xFF00) == 0)                     \\\n          r += val & 0xFF;                           \\\n        else if ((val & 0xFF0000) == 0)              \\\n          r += val & 0xFFFF;                         \\\n        else                                         \\\n          r += val;                                  \\\n      }                                              \\\n  } while (0)\n#endif\n\nunsigned int\njhash_string(unsigned const char *k)\n{\n  unsigned int a, b, c;\n  unsigned int have_nul = 0;\n  unsigned const char *start = k;\n  size_t klen = strlen ((const char*)k);\n\n  /* Set up the internal state */\n  a = b = c = JHASH_INITVAL;\n\n  /* All but the last block: affect some 32 bits of (a,b,c) */\n  for (;;) {\n    sum_up_to_nul(a, k, klen, have_nul);\n    if (have_nul)\n      break;\n    k += UINTSZ;\n    assert (klen >= UINTSZ);\n    klen -= UINTSZ;\n\n    sum_up_to_nul(b, k, klen, have_nul);\n    if (have_nul)\n      break;\n    k += UINTSZ;\n    assert (klen >= UINTSZ);\n    klen -= UINTSZ;\n\n    sum_up_to_nul(c, k, klen, have_nul);\n    if (have_nul)\n      break;\n    k += UINTSZ;\n    assert (klen >= UINTSZ);\n    klen -= UINTSZ;\n    jhash_mix(a, b, c);\n  }\n\n  jhash_final(a, b, c);\n  return c + (unsigned) (k - start);\n}\n"
  },
  {
    "path": "src/hash.h",
    "content": "/* hash.h -- decls for hash table\nCopyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc.\nWritten by Greg McGary <gkm@gnu.org> <greg@mcgary.org>\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _hash_h_\n#define _hash_h_\n\n#include <stdio.h>\n#include <ctype.h>\n\n#if defined __cplusplus || (defined __STDC__ && __STDC__) || MK_OS_W32\n# if !defined __GLIBC__ || !defined __P\n#  undef\t__P\n#  define __P(protos)\tprotos\n# endif\n#else /* Not C++ or ANSI C.  */\n# undef\t__P\n# define __P(protos)\t()\n/* We can get away without defining 'const' here only because in this file\n   it is used only inside the prototype for 'fnmatch', which is elided in\n   non-ANSI C where 'const' is problematical.  */\n#endif /* C++ or ANSI C.  */\n\ntypedef unsigned long (*hash_func_t) __P((void const *key));\ntypedef int (*hash_cmp_func_t) __P((void const *x, void const *y));\ntypedef void (*hash_map_func_t) __P((void const *item));\ntypedef void (*hash_map_arg_func_t) __P((void const *item, void *arg));\n\nstruct hash_table\n{\n  void **ht_vec;\n  hash_func_t ht_hash_1;\t/* primary hash function */\n  hash_func_t ht_hash_2;\t/* secondary hash function */\n  hash_cmp_func_t ht_compare;\t/* comparison function */\n  unsigned long ht_size;\t/* total number of slots (power of 2) */\n  unsigned long ht_capacity;\t/* usable slots, limited by loading-factor */\n  unsigned long ht_fill;\t/* items in table */\n  unsigned long ht_empty_slots;\t/* empty slots not including deleted slots */\n  unsigned long ht_collisions;\t/* # of failed calls to comparison function */\n  unsigned long ht_lookups;\t/* # of queries */\n  unsigned int ht_rehashes;\t/* # of times we've expanded table */\n};\n\ntypedef int (*qsort_cmp_t) __P((void const *, void const *));\n\nvoid hash_init __P((struct hash_table *ht, unsigned long size,\n                    hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp));\nvoid hash_load __P((struct hash_table *ht, void *item_table,\n                    unsigned long cardinality, unsigned long size));\nvoid **hash_find_slot __P((struct hash_table *ht, void const *key));\nvoid *hash_find_item __P((struct hash_table *ht, void const *key));\nvoid *hash_insert __P((struct hash_table *ht, const void *item));\nvoid *hash_insert_at __P((struct hash_table *ht, const void *item, void const *slot));\nvoid *hash_delete __P((struct hash_table *ht, void const *item));\nvoid *hash_delete_at __P((struct hash_table *ht, void const *slot));\nvoid hash_delete_items __P((struct hash_table *ht));\nvoid hash_free_items __P((struct hash_table *ht));\nvoid hash_free __P((struct hash_table *ht, int free_items));\nvoid hash_map __P((struct hash_table *ht, hash_map_func_t map));\nvoid hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg));\nvoid hash_print_stats __P((struct hash_table *ht, FILE *out_FILE));\nvoid **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare));\n\nextern unsigned jhash(unsigned char const *key, int n);\nextern unsigned jhash_string(unsigned char const *key);\n\nextern void *hash_deleted_item;\n#define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item)\n\n\f\n/* hash and comparison macros for case-sensitive string keys. */\n\n/* Due to the strcache, it's not uncommon for the string pointers to\n   be identical.  Take advantage of that to short-circuit string compares.  */\n\n#define STRING_HASH_1(KEY, RESULT) do { \\\n  unsigned char const *_key_ = (unsigned char const *) (KEY); \\\n  (RESULT) += jhash_string(_key_); \\\n} while (0)\n#define return_STRING_HASH_1(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  STRING_HASH_1 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n/* No need for a second hash because jhash already provides\n   pretty good results.  However, do evaluate the arguments\n   to avoid warnings.  */\n#define STRING_HASH_2(KEY, RESULT) do { \\\n  (void)(KEY); \\\n} while (0)\n#define return_STRING_HASH_2(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  STRING_HASH_2 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define STRING_COMPARE(X, Y, RESULT) do { \\\n    RESULT = (X) == (Y) ? 0 : strcmp ((X), (Y)); \\\n} while (0)\n#define return_STRING_COMPARE(X, Y) do { \\\n  return (X) == (Y) ? 0 : strcmp ((X), (Y)); \\\n} while (0)\n\n\n#define STRING_N_HASH_1(KEY, N, RESULT) do { \\\n  unsigned char const *_key_ = (unsigned char const *) (KEY); \\\n  (RESULT) += jhash(_key_, N); \\\n} while (0)\n\n#define return_STRING_N_HASH_1(KEY, N) do { \\\n  unsigned long _result_ = 0; \\\n  STRING_N_HASH_1 ((KEY), (N), _result_); \\\n  return _result_; \\\n} while (0)\n\n/* No need for a second hash because jhash already provides\n   pretty good results.  However, do evaluate the arguments\n   to avoid warnings.  */\n#define STRING_N_HASH_2(KEY, N, RESULT) do { \\\n  (void)(KEY); \\\n  (void)(N); \\\n} while (0)\n\n#define return_STRING_N_HASH_2(KEY, N) do { \\\n  unsigned long _result_ = 0; \\\n  STRING_N_HASH_2 ((KEY), (N), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define STRING_N_COMPARE(X, Y, N, RESULT) do { \\\n  RESULT = (X) == (Y) ? 0 : memcmp ((X), (Y), (N)); \\\n} while (0)\n#define return_STRING_N_COMPARE(X, Y, N) do { \\\n  return (X) == (Y) ? 0 : memcmp ((X), (Y), (N)); \\\n} while (0)\n\n#ifdef HAVE_CASE_INSENSITIVE_FS\n\n/* hash and comparison macros for case-insensitive string _key_s. */\n\n#define ISTRING_HASH_1(KEY, RESULT) do { \\\n  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \\\n  while (*++_key_) \\\n    (RESULT) += (tolower (*_key_) << (_key_[1] & 0xf)); \\\n} while (0)\n#define return_ISTRING_HASH_1(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  ISTRING_HASH_1 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define ISTRING_HASH_2(KEY, RESULT) do { \\\n  unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \\\n  while (*++_key_) \\\n    (RESULT) += (tolower (*_key_) << (_key_[1] & 0x7)); \\\n} while (0)\n#define return_ISTRING_HASH_2(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  ISTRING_HASH_2 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define ISTRING_COMPARE(X, Y, RESULT) do { \\\n  RESULT = (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \\\n} while (0)\n#define return_ISTRING_COMPARE(X, Y) do { \\\n  return (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \\\n} while (0)\n\n#else\n\n#define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT))\n#define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY)\n\n#define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT))\n#define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY)\n\n#define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT))\n#define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y))\n\n#endif\n\n/* hash and comparison macros for integer _key_s. */\n\n#define INTEGER_HASH_1(KEY, RESULT) do { \\\n  (RESULT) += ((unsigned long)(KEY)); \\\n} while (0)\n#define return_INTEGER_HASH_1(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  INTEGER_HASH_1 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define INTEGER_HASH_2(KEY, RESULT) do { \\\n  (RESULT) += ~((unsigned long)(KEY)); \\\n} while (0)\n#define return_INTEGER_HASH_2(KEY) do { \\\n  unsigned long _result_ = 0; \\\n  INTEGER_HASH_2 ((KEY), _result_); \\\n  return _result_; \\\n} while (0)\n\n#define INTEGER_COMPARE(X, Y, RESULT) do { \\\n  (RESULT) = X - Y; \\\n} while (0)\n#define return_INTEGER_COMPARE(X, Y) do { \\\n  int _result_; \\\n  INTEGER_COMPARE (X, Y, _result_); \\\n  return _result_; \\\n} while (0)\n\n/* hash and comparison macros for address keys. */\n\n#define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT))\n#define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT))\n#define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT))\n#define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3)\n#define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3)\n#define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y))\n\n#endif /* not _hash_h_ */\n"
  },
  {
    "path": "src/implicit.c",
    "content": "/* Implicit rule searching for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"rule.h\"\n#include \"dep.h\"\n#include \"debug.h\"\n#include \"variable.h\"\n#include \"job.h\"      /* struct child, used inside commands.h */\n#include \"commands.h\" /* set_file_variables */\n#include \"shuffle.h\"\n#include <assert.h>\n\nstatic int pattern_search (struct file *file, int archive,\n                           unsigned int depth, unsigned int recursions,\n                           int allow_compat_rules);\n\f\n/* For a FILE which has no commands specified, try to figure out some\n   from the implicit pattern rules.\n   Returns 1 if a suitable implicit rule was found,\n   after modifying FILE to contain the appropriate commands and deps,\n   or returns 0 if no implicit rule was found.  */\n\nint\ntry_implicit_rule (struct file *file, unsigned int depth)\n{\n  DBF (DB_IMPLICIT, _(\"Looking for an implicit rule for '%s'.\\n\"));\n\n  /* The order of these searches was previously reversed.  My logic now is\n     that since the non-archive search uses more information in the target\n     (the archive search omits the archive name), it is more specific and\n     should come first.  */\n\n  if (pattern_search (file, 0, depth, 0, 0))\n    return 1;\n\n#ifndef NO_ARCHIVES\n  /* If this is an archive member reference, use just the\n     archive member name to search for implicit rules.  */\n  if (ar_name (file->name))\n    {\n      DBF (DB_IMPLICIT,\n           _(\"Looking for archive-member implicit rule for '%s'.\\n\"));\n      if (pattern_search (file, 1, depth, 0, 0))\n        return 1;\n      DBS (DB_IMPLICIT,\n           (_(\"No archive-member implicit rule found for '%s'.\\n\"),\n            file->name));\n    }\n#endif\n\n  return 0;\n}\n\f\n\n/* Scans the BUFFER for the next word with whitespace as a separator.\n   Returns the pointer to the beginning of the word. LENGTH hold the\n   length of the word.  */\n\nstatic const char *\nget_next_word (const char *buffer, size_t *length)\n{\n  const char *p = buffer, *beg;\n  char c;\n\n  /* Skip any leading whitespace.  */\n  NEXT_TOKEN (p);\n\n  beg = p;\n  c = *(p++);\n\n  if (c == '\\0')\n    return 0;\n\n\n  while (1)\n    {\n      /* Each time through the loop, \"c\" has the current char\n         and \"p\" points to the next char.  */\n      switch (c)\n        {\n        case '\\0':\n        case ' ':\n        case '\\t':\n          goto done_word;\n\n        case '$':\n          /* This is a variable reference, so skip it.  */\n          p = skip_reference (p);\n          break;\n\n        case '|':\n          goto done;\n\n        default:\n          break;\n        }\n\n      c = *(p++);\n    }\n done_word:\n  --p;\n\n done:\n  if (length)\n    *length = p - beg;\n\n  return beg;\n}\n\n/* This structure stores information about the expanded prerequisites for a\n   pattern rule.  NAME is always set to the strcache'd name of the prereq.\n   FILE and PATTERN will be set for intermediate files only.  IGNORE_MTIME is\n   copied from the prerequisite we expanded.\n */\nstruct patdeps\n  {\n    const char *name;\n    const char *pattern;\n    struct file *file;\n    unsigned int ignore_mtime : 1;\n    unsigned int ignore_automatic_vars : 1;\n    unsigned int is_explicit : 1;\n    unsigned int wait_here : 1;\n  };\n\n/* This structure stores information about pattern rules that we need\n   to try.\n*/\nstruct tryrule\n  {\n    struct rule *rule;\n\n    /* Stem length for this match. */\n    size_t stemlen;\n\n    /* Index of the target in this rule that matched the file. */\n    unsigned int matches;\n\n    /* Definition order of this rule. Used to implement stable sort.*/\n    unsigned int order;\n\n    /* Nonzero if the LASTSLASH logic was used in matching this rule. */\n    char checked_lastslash;\n  };\n\nint\nstemlen_compare (const void *v1, const void *v2)\n{\n  const struct tryrule *r1 = v1;\n  const struct tryrule *r2 = v2;\n  int r = (int) (r1->stemlen - r2->stemlen);\n  return r != 0 ? r : (int) (r1->order - r2->order);\n}\n\n/* Search the pattern rules for a rule with an existing dependency to make\n   FILE.  If a rule is found, the appropriate commands and deps are put in FILE\n   and 1 is returned.  If not, 0 is returned.\n\n   If ARCHIVE is nonzero, FILE->name is of the form \"LIB(MEMBER)\".  A rule for\n   \"(MEMBER)\" will be searched for, and \"(MEMBER)\" will not be chopped up into\n   directory and filename parts.\n\n   If an intermediate file is found by pattern search, the intermediate file\n   is set up as a target by the recursive call and is also made a dependency\n   of FILE.\n\n   DEPTH is used for debugging messages.  */\n\nstatic int\npattern_search (struct file *file, int archive,\n                unsigned int depth, unsigned int recursions,\n                int allow_compat_rules)\n{\n  /* Filename we are searching for a rule for.  */\n  const char *filename = archive ? strchr (file->name, '(') : file->name;\n\n  /* Length of FILENAME.  */\n  size_t namelen = strlen (filename);\n\n  /* The last slash in FILENAME (or nil if there is none).  */\n  const char *lastslash;\n\n  /* This is a file-object used as an argument in\n     recursive calls.  It never contains any data\n     except during a recursive call.  */\n  struct file *int_file = 0;\n\n  /* List of dependencies found recursively.  */\n  unsigned int max_deps = max_pattern_deps;\n  struct patdeps *deplist = xmalloc (max_deps * sizeof (struct patdeps));\n  struct patdeps *pat = deplist;\n\n  /* Names of possible dependencies are constructed in this buffer.\n     We may replace % by $(*F) for second expansion, increasing the length.  */\n  size_t deplen = namelen + max_pattern_dep_length + 4;\n  char *depname = alloca (deplen);\n#ifndef NDEBUG\n  char *dend = depname + deplen;\n#endif\n\n  /* The start and length of the stem of FILENAME for the current rule.  */\n  const char *stem = 0;\n  size_t stemlen = 0;\n  size_t fullstemlen = 0;\n\n  /* Buffer in which we store all the rules that are possibly applicable.  */\n  struct tryrule *tryrules = xmalloc (num_pattern_rules * max_pattern_targets\n                                      * sizeof (struct tryrule));\n\n  /* Number of valid elements in TRYRULES.  */\n  unsigned int nrules;\n\n  /* The index in TRYRULES of the rule we found.  */\n  unsigned int foundrule;\n\n  /* Nonzero if should consider intermediate files as dependencies.  */\n  int intermed_ok;\n\n  /* Nonzero if we have initialized file variables for this target.  */\n  int file_vars_initialized = 0;\n\n  /* Nonzero if we have matched a pattern-rule target\n     that is not just '%'.  */\n  int specific_rule_matched = 0;\n\n  unsigned int ri;  /* uninit checks OK */\n  int found_compat_rule = 0;\n  struct rule *rule;\n\n  char *pathdir = NULL;\n  size_t pathlen;\n\n  PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */\n\n  ++depth;\n\n#ifndef NO_ARCHIVES\n  if (archive || ar_name (filename))\n    lastslash = 0;\n  else\n#endif\n    {\n      /* Set LASTSLASH to point at the last slash in FILENAME\n         but not counting any slash at the end.  (foo/bar/ counts as\n         bar/ in directory foo/, not empty in directory foo/bar/.)  */\n      lastslash = memrchr (filename, '/', namelen - 1);\n#if MK_OS_VMS\n      if (lastslash == NULL)\n        lastslash = strrchr (filename, ']');\n      if (lastslash == NULL)\n        lastslash = strrchr (filename, '>');\n      if (lastslash == NULL)\n        lastslash = strrchr (filename, ':');\n#endif\n#ifdef HAVE_DOS_PATHS\n      /* Handle backslashes (possibly mixed with forward slashes)\n         and the case of \"d:file\".  */\n      {\n        char *bslash = memrchr (filename, '\\\\', namelen - 1);\n        if (lastslash == 0 || bslash > lastslash)\n          lastslash = bslash;\n        if (lastslash == 0 && filename[0] && filename[1] == ':')\n          lastslash = filename + 1;\n      }\n#endif\n    }\n\n  pathlen = lastslash ? lastslash - filename + 1 : 0;\n\n  /* First see which pattern rules match this target and may be considered.\n     Put them in TRYRULES.  */\n\n  nrules = 0;\n  for (rule = pattern_rules; rule != 0; rule = rule->next)\n    {\n      unsigned int ti;\n\n      /* If the pattern rule has deps but no commands, ignore it.\n         Users cancel built-in rules by redefining them without commands.  */\n      if (rule->deps != 0 && rule->cmds == 0)\n        continue;\n\n      /* If this rule is in use by a parent pattern_search,\n         don't use it here.  */\n      if (rule->in_use)\n        {\n          DBS (DB_IMPLICIT,\n               (_(\"Avoiding implicit rule recursion for rule '%s'.\\n\"),\n                get_rule_defn (rule)));\n          continue;\n        }\n\n      for (ti = 0; ti < rule->num; ++ti)\n        {\n          const char *target = rule->targets[ti];\n          const char *suffix = rule->suffixes[ti];\n          char check_lastslash;\n\n          /* Rules that can match any filename and are not terminal\n             are ignored if we're recursing, so that they cannot be\n             intermediate files.  */\n          if (recursions > 0 && target[1] == '\\0' && !rule->terminal)\n            continue;\n\n          if (rule->lens[ti] > namelen)\n            /* It can't possibly match.  */\n            continue;\n\n          /* From the lengths of the filename and the pattern parts,\n             find the stem: the part of the filename that matches the %.  */\n          stem = filename + (suffix - target - 1);\n          stemlen = namelen - rule->lens[ti] + 1;\n\n          /* Set CHECK_LASTSLASH if FILENAME contains a directory\n             prefix and the target pattern does not contain a slash.  */\n\n          check_lastslash = 0;\n          if (lastslash)\n            {\n#if MK_OS_VMS\n              check_lastslash = strpbrk (target, \"/]>:\") == NULL;\n#else\n              check_lastslash = strchr (target, '/') == 0;\n#endif\n#ifdef HAVE_DOS_PATHS\n              /* Didn't find it yet: check for DOS-type directories.  */\n              if (check_lastslash)\n                {\n                  char *b = strchr (target, '\\\\');\n                  check_lastslash = !(b || (target[0] && target[1] == ':'));\n                }\n#endif\n            }\n          if (check_lastslash)\n            {\n              /* If so, don't include the directory prefix in STEM here.  */\n              if (pathlen > stemlen)\n                continue;\n              stemlen -= pathlen;\n              stem += pathlen;\n            }\n\n          /* Check that the rule pattern matches the text before the stem.  */\n          if (check_lastslash)\n            {\n              if (stem > (lastslash + 1)\n                  && !strneq (target, lastslash + 1, stem - lastslash - 1))\n                continue;\n            }\n          else if (stem > filename\n                   && !strneq (target, filename, stem - filename))\n            continue;\n\n          /* Check that the rule pattern matches the text after the stem.\n             We could test simply use streq, but this way we compare the\n             first two characters immediately.  This saves time in the very\n             common case where the first character matches because it is a\n             period.  */\n          if (*suffix != stem[stemlen]\n              || (*suffix != '\\0' && !streq (&suffix[1], &stem[stemlen + 1])))\n            continue;\n\n          /* Record if we match a rule that not all filenames will match.  */\n          if (target[1] != '\\0')\n            specific_rule_matched = 1;\n\n          /* A rule with no dependencies and no commands exists solely to set\n             specific_rule_matched when it matches.  Don't try to use it.  */\n          if (rule->deps == 0 && rule->cmds == 0)\n            continue;\n\n          /* Record this rule in TRYRULES and the index of the matching\n             target in MATCHES.  If several targets of the same rule match,\n             that rule will be in TRYRULES more than once.  */\n          tryrules[nrules].rule = rule;\n          tryrules[nrules].matches = ti;\n          tryrules[nrules].stemlen = stemlen + (check_lastslash ? pathlen : 0);\n          tryrules[nrules].order = nrules;\n          tryrules[nrules].checked_lastslash = check_lastslash;\n          ++nrules;\n        }\n    }\n\n  /* Bail out early if we haven't found any rules. */\n  if (nrules == 0)\n    goto done;\n\n  /* Sort the rules to place matches with the shortest stem first. This\n     way the most specific rules will be tried first. */\n  if (nrules > 1)\n    qsort (tryrules, nrules, sizeof (struct tryrule), stemlen_compare);\n\n  /* If we have found a matching rule that won't match all filenames,\n     retroactively reject any non-\"terminal\" rules that do always match.  */\n  if (specific_rule_matched)\n    for (ri = 0; ri < nrules; ++ri)\n      if (!tryrules[ri].rule->terminal)\n        {\n          unsigned int j;\n          for (j = 0; j < tryrules[ri].rule->num; ++j)\n            if (tryrules[ri].rule->targets[j][1] == '\\0')\n              {\n                tryrules[ri].rule = 0;\n                break;\n              }\n        }\n\n  /* Try each rule once without intermediate files, then once with them.  */\n  for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok)\n    {\n      pat = deplist;\n      if (intermed_ok)\n        DBS (DB_IMPLICIT, (_(\"Trying harder.\\n\")));\n\n      /* Try each pattern rule till we find one that applies.  If it does,\n         expand its dependencies (as substituted) and chain them in DEPS.  */\n      for (ri = 0; ri < nrules; ri++)\n        {\n          struct dep *dep;\n          char check_lastslash;\n          unsigned int failed = 0;\n          int file_variables_set = 0;\n          unsigned int deps_found = 0;\n          /* NPTR points to the part of the prereq we haven't processed.  */\n          const char *nptr = 0;\n          int order_only = 0;\n          unsigned int matches;\n\n          rule = tryrules[ri].rule;\n\n          /* RULE is nil when we discover that a rule, already placed in\n             TRYRULES, should not be applied.  */\n          if (rule == 0)\n            continue;\n\n          /* Reject any terminal rules if we're looking to make intermediate\n             files.  */\n          if (intermed_ok && rule->terminal)\n            continue;\n\n          /* From the lengths of the filename and the matching pattern parts,\n             find the stem: the part of the filename that matches the %.  */\n          matches = tryrules[ri].matches;\n          stem = filename + (rule->suffixes[matches]\n                             - rule->targets[matches]) - 1;\n          stemlen = (namelen - rule->lens[matches]) + 1;\n          check_lastslash = tryrules[ri].checked_lastslash;\n          if (check_lastslash)\n            {\n              stem += pathlen;\n              stemlen -= pathlen;\n\n              /* We need to add the directory prefix, so set it up.  */\n              if (! pathdir)\n                {\n                  pathdir = alloca (pathlen + 1);\n                  memcpy (pathdir, filename, pathlen);\n                  pathdir[pathlen] = '\\0';\n                }\n            }\n\n          DBS (DB_IMPLICIT,\n               (_(\"Trying pattern rule '%s' with stem '%.*s'.\\n\"),\n                get_rule_defn (rule), (int) stemlen, stem));\n\n          if (stemlen + (check_lastslash ? pathlen : 0) > GET_PATH_MAX)\n            {\n              DBS (DB_IMPLICIT, (_(\"Stem too long: '%s%.*s'.\\n\"),\n                                 check_lastslash ? pathdir : \"\",\n                                 (int) stemlen, stem));\n              continue;\n            }\n\n          if (!check_lastslash)\n            {\n              memcpy (stem_str, stem, stemlen);\n              stem_str[stemlen] = '\\0';\n            }\n          else\n            {\n              /* We want to prepend the directory from\n                 the original FILENAME onto the stem.  */\n              memcpy (stem_str, filename, pathlen);\n              memcpy (stem_str + pathlen, stem, stemlen);\n              stem_str[pathlen + stemlen] = '\\0';\n            }\n\n          /* If there are no prerequisites, then this rule matches.  */\n          if (rule->deps == 0)\n            break;\n\n          /* Mark this rule as in use so a recursive pattern_search won't try\n             to use it.  */\n          rule->in_use = 1;\n\n          /* Try each prerequisite; see if it exists or can be created.  We'll\n             build a list of prereq info in DEPLIST.  Due to 2nd expansion we\n             may have to process multiple prereqs for a single dep entry.  */\n\n          pat = deplist;\n          dep = rule->deps;\n          nptr = dep_name (dep);\n          while (1)\n            {\n              struct dep *dl, *d;\n\n              /* If we're out of name to parse, start the next prereq.  */\n              if (! nptr)\n                {\n                  dep = dep->next;\n                  if (dep == 0)\n                    break;\n                  nptr = dep_name (dep);\n                }\n\n              /* If we don't need a second expansion, just replace the %.  */\n              if (! dep->need_2nd_expansion)\n                {\n                  char *p;\n                  int is_explicit = 1;\n                  const char *cp = strchr (nptr, '%');\n                  if (cp == 0)\n                    strcpy (depname, nptr);\n                  else\n                    {\n                      char *o = depname;\n                      if (check_lastslash)\n                        o = mempcpy (o, filename, pathlen);\n                      o = mempcpy (o, nptr, cp - nptr);\n                      o = mempcpy (o, stem, stemlen);\n                      strcpy (o, cp + 1);\n                      is_explicit = 0;\n                    }\n\n                  /* Parse the expanded string.  It might have wildcards.  */\n                  p = depname;\n                  dl = PARSE_FILE_SEQ (&p, struct dep, MAP_NUL, NULL,\n                                       PARSEFS_ONEWORD|PARSEFS_WAIT);\n                  for (d = dl; d != NULL; d = d->next)\n                    {\n                      ++deps_found;\n                      d->ignore_mtime = dep->ignore_mtime;\n                      d->ignore_automatic_vars = dep->ignore_automatic_vars;\n                      d->wait_here |= dep->wait_here;\n                      d->is_explicit = is_explicit;\n                    }\n\n                  /* We've used up this dep, so next time get a new one.  */\n                  nptr = 0;\n                }\n\n              /* We have to perform second expansion on this prereq.  In an\n                 ideal world we would take the dependency line, substitute the\n                 stem, re-expand the whole line and chop it into individual\n                 prerequisites.  Unfortunately this won't work because of the\n                 \"check_lastslash\" twist.  Instead, we will have to go word by\n                 word, taking $()'s into account.  For each word we will\n                 substitute the stem, re-expand, chop it up, and, if\n                 check_lastslash != 0, add the directory part to each\n                 resulting prerequisite.  */\n              else\n                {\n                  int add_dir = 0;\n                  size_t len;\n                  const char *end;\n                  struct dep **dptr;\n                  int is_explicit;\n                  const char *cp;\n                  char *p;\n\n                  nptr = get_next_word (nptr, &len);\n                  if (nptr == 0)\n                    continue;\n                  end = nptr + len;\n\n                  /* See if this is a transition to order-only prereqs.  */\n                  if (! order_only && len == 1 && nptr[0] == '|')\n                    {\n                      order_only = 1;\n                      nptr = end;\n                      continue;\n                    }\n\n                  /* If the dependency name has %, substitute the stem.  If we\n                     just replace % with the stem value then later, when we do\n                     the 2nd expansion, we will re-expand this stem value\n                     again.  This is not good if you have certain characters\n                     in your stem (like $).\n\n                     Instead, we will replace % with $* or $(*F) and allow the\n                     second expansion to take care of it for us.  This way\n                     (since $* and $(*F) are simple variables) there won't be\n                     additional re-expansion of the stem.  */\n\n                  cp = lindex (nptr, end, '%');\n                  if (cp == 0)\n                    {\n                      memcpy (depname, nptr, len);\n                      depname[len] = '\\0';\n                      is_explicit = 1;\n                    }\n                  else\n                    {\n                      /* Go through all % between NPTR and END.\n                         Copy contents of [NPTR, END) to depname, with the\n                         first % after NPTR and then each first % after white\n                         space replaced with $* or $(*F).  depname has enough\n                         room to substitute each % with $(*F).  */\n                      char *o = depname;\n\n                      is_explicit = 0;\n                      for (;;)\n                        {\n                          size_t i = cp - nptr;\n                          assert (o + i < dend);\n                          o = mempcpy (o, nptr, i);\n                          if (check_lastslash)\n                            {\n                              add_dir = 1;\n                              assert (o + 5 < dend);\n                              o = mempcpy (o, \"$(*F)\", 5);\n                            }\n                          else\n                            {\n                              assert (o + 2 < dend);\n                              o = mempcpy (o, \"$*\", 2);\n                            }\n                          assert (o < dend);\n                          ++cp;\n                          assert (cp <= end);\n                          nptr = cp;\n                          if (nptr == end)\n                            break;\n\n                          /* Skip the rest of this word then find the next %.\n                             No need to worry about order-only, or nested\n                             functions: NPTR went though get_next_word.  */\n                          while (cp < end && ! END_OF_TOKEN (*cp))\n                            ++cp;\n                          cp = lindex (cp, end, '%');\n                          if (cp == 0)\n                            break;\n                        }\n                        len = end - nptr;\n                        memcpy (o, nptr, len);\n                        o[len] = '\\0';\n                    }\n\n                  /* Set up for the next word.  */\n                  nptr = end;\n\n                  /* Initialize and set file variables if we haven't already\n                     done so. */\n                  if (!file_vars_initialized)\n                    {\n                      initialize_file_variables (file, 0);\n                      set_file_variables (file, stem_str);\n                      file_vars_initialized = 1;\n                    }\n                  /* Update the stem value in $* for this rule.  */\n                  else if (!file_variables_set)\n                    {\n                      define_variable_for_file (\n                        \"*\", 1, stem_str, o_automatic, 0, file);\n                      file_variables_set = 1;\n                    }\n\n                  /* Perform the 2nd expansion.  */\n                  p = expand_string_for_file (depname, file);\n                  dptr = &dl;\n\n                  /* Parse the results into a deps list.  */\n                  do\n                    {\n                      /* Parse the expanded string. */\n                      struct dep *dp = PARSE_FILE_SEQ (&p, struct dep,\n                                                       order_only ? MAP_NUL : MAP_PIPE,\n                                                       add_dir ? pathdir : NULL,\n                                                       PARSEFS_WAIT);\n                      *dptr = dp;\n\n                      for (d = dp; d != NULL; d = d->next)\n                        {\n                          ++deps_found;\n                          if (order_only)\n                            d->ignore_mtime = 1;\n                          d->is_explicit = is_explicit;\n                          dptr = &d->next;\n                        }\n\n                      /* If we stopped due to an order-only token, note it.  */\n                      if (*p == '|')\n                        {\n                          order_only = 1;\n                          ++p;\n                        }\n                    }\n                  while (*p != '\\0');\n                }\n\n              /* If there are more than max_pattern_deps prerequisites (due to\n                 2nd expansion), reset it and realloc the arrays.  */\n\n              if (deps_found > max_deps)\n                {\n                  size_t l = pat - deplist;\n                  /* This might have changed due to recursion.  */\n                  max_pattern_deps = MAX(max_pattern_deps, deps_found);\n                  max_deps = max_pattern_deps;\n                  deplist = xrealloc (deplist,\n                                      max_deps * sizeof (struct patdeps));\n                  pat = deplist + l;\n                }\n\n              /* Go through the nameseq and handle each as a prereq name.  */\n              for (d = dl; d != 0; d = d->next)\n                {\n                  struct file *df;\n                  int is_rule = d->name == dep_name (dep);\n                  int explicit = 0;\n                  struct dep *dp = 0;\n\n                  if (file_impossible_p (d->name))\n                    {\n                      /* If this prereq has already been ruled \"impossible\",\n                         then the rule fails.  Don't bother trying it on the\n                         second pass either since we know that will fail.  */\n                      DBS (DB_IMPLICIT,\n                           (is_rule\n                            ? _(\"Rejecting rule '%s' due to impossible rule\"\n                                \" prerequisite '%s'.\\n\")\n                            : _(\"Rejecting rule '%s' due to impossible implicit\"\n                                \" prerequisite '%s'.\\n\"),\n                            get_rule_defn (rule), d->name));\n                      tryrules[ri].rule = 0;\n\n                      failed = 1;\n                      break;\n                    }\n\n                  memset (pat, '\\0', sizeof (struct patdeps));\n                  pat->ignore_mtime = d->ignore_mtime;\n                  pat->ignore_automatic_vars = d->ignore_automatic_vars;\n                  pat->wait_here = d->wait_here;\n                  pat->is_explicit = d->is_explicit;\n\n                  DBS (DB_IMPLICIT,\n                       (is_rule\n                        ? _(\"Trying rule prerequisite '%s'.\\n\")\n                        : _(\"Trying implicit prerequisite '%s'.\\n\"), d->name));\n\n                  df = lookup_file (d->name);\n\n                  if (df && df->is_explicit)\n                    pat->is_explicit = 1;\n\n                  /* If we found a file for the dep, set its intermediate flag.\n                     df->is_explicit is set when the dep file is mentioned\n                     explicitly on some other rule.  d->is_explicit is set when\n                     the dep file is mentioned explicitly on this rule.  E.g.:\n                       %.x : %.y ; ...\n                     then:\n                       one.x:\n                       one.y:        # df->is_explicit\n                     vs.\n                       one.x: one.y  # d->is_explicit\n                  */\n                  if (df && !df->is_explicit && !d->is_explicit)\n                    df->intermediate = 1;\n\n                  /* If the pattern prereq is also explicitly mentioned for\n                     FILE, skip all tests below since it must be built no\n                     matter which implicit rule we choose. */\n                  if (df && df->is_target)\n                    /* This prerequisite is mentioned explicitly as a target of\n                       some rule.  */\n                    explicit = 1;\n                  else\n                    for (dp = file->deps; dp != 0; dp = dp->next)\n                      if (streq (d->name, dep_name (dp)))\n                        break;\n\n                  /* If dp is set, this prerequisite is mentioned explicitly as\n                     a prerequisite of the current target.  */\n\n                  if (explicit || dp)\n                    {\n                      (pat++)->name = d->name;\n                      DBS (DB_IMPLICIT, (_(\"'%s' ought to exist.\\n\"), d->name));\n                      continue;\n                    }\n\n                  if (file_exists_p (d->name))\n                    {\n                      (pat++)->name = d->name;\n                      DBS (DB_IMPLICIT, (_(\"Found '%s'.\\n\"), d->name));\n                      continue;\n                    }\n\n                  if (df && allow_compat_rules)\n                    {\n                      (pat++)->name = d->name;\n                      DBS (DB_IMPLICIT,\n                           (_(\"Using compatibility rule '%s' due to '%s'.\\n\"),\n                            get_rule_defn (rule), d->name));\n                      continue;\n                    }\n\n                  if (df)\n                    {\n                      /* This prerequisite is mentioned explicitly as a\n                         prerequisite on some rule, but it is not a\n                         prerequisite of the current target. Therefore, this\n                         prerequisite does not qualify as ought-to-exist. Keep\n                         note of this rule and continue the search.  If a more\n                         suitable rule is not found, then use this rule.  */\n                      DBS (DB_IMPLICIT,\n                           (_(\"Prerequisite '%s' of rule '%s' does not qualify\"\n                              \" as ought to exist.\\n\"),\n                            d->name, get_rule_defn (rule)));\n                      found_compat_rule = 1;\n                    }\n\n                  /* This code, given FILENAME = \"lib/foo.o\", dependency name\n                     \"lib/foo.c\", and VPATH=src, searches for\n                     \"src/lib/foo.c\".  */\n                  {\n                    const char *vname = vpath_search (d->name, 0, NULL, NULL);\n                    if (vname)\n                      {\n                        DBS (DB_IMPLICIT,\n                             (_(\"Found prerequisite '%s' as VPATH '%s'.\\n\"),\n                              d->name, vname));\n                        (pat++)->name = d->name;\n                        continue;\n                      }\n                  }\n\n                  /* We could not find the file in any place we should look.\n                     Look for an implicit rule to make this dependency, but\n                     only on the second pass.  */\n\n                  if (intermed_ok)\n                    {\n                      DBS (DB_IMPLICIT,\n                           (d->is_explicit || (df && df->is_explicit)\n                            ? _(\"Looking for a rule with explicit file '%s'.\\n\")\n                            : _(\"Looking for a rule with intermediate file '%s'.\\n\"),\n                            d->name));\n\n                      if (int_file == 0)\n                        int_file = alloca (sizeof (struct file));\n                      memset (int_file, '\\0', sizeof (struct file));\n                      int_file->name = d->name;\n\n                      if (pattern_search (int_file,\n                                          0,\n                                          depth,\n                                          recursions + 1,\n                                          allow_compat_rules))\n                        {\n                          pat->pattern = int_file->name;\n                          int_file->name = d->name;\n                          pat->file = int_file;\n                          int_file = 0;\n                          (pat++)->name = d->name;\n                          continue;\n                        }\n\n                      /* If we have tried to find P as an intermediate file\n                         and failed, mark that name as impossible so we won't\n                         go through the search again later.  */\n                      if (int_file->variables)\n                        free_variable_set (int_file->variables);\n                      if (int_file->pat_variables)\n                        free_variable_set (int_file->pat_variables);\n\n                      /* Keep prerequisites explicitly mentioned on unrelated\n                         rules as \"possible\" to let compatibility search find\n                         such prerequisites.  */\n                      if (df == 0)\n                        file_impossible (d->name);\n                    }\n\n                  /* A dependency of this rule does not exist. Therefore, this\n                     rule fails.  */\n                  if (intermed_ok)\n                    DBS (DB_IMPLICIT,\n                         (_(\"Rejecting rule '%s' \"\n                            \"due to impossible prerequisite '%s'.\\n\"),\n                          get_rule_defn (rule), d->name));\n                  else\n                    DBS (DB_IMPLICIT, (_(\"Not found '%s'.\\n\"), d->name));\n\n                  failed = 1;\n                  break;\n                }\n\n              /* Free the ns chain.  */\n              free_dep_chain (dl);\n\n              if (failed)\n                break;\n            }\n\n          /* This rule is no longer 'in use' for recursive searches.  */\n          rule->in_use = 0;\n\n          if (! failed)\n            /* This pattern rule does apply.  Stop looking for one.  */\n            break;\n\n          /* This pattern rule does not apply.  Keep looking.  */\n        }\n\n      /* If we found an applicable rule without intermediate files, don't try\n         with them.  */\n      if (ri < nrules)\n        break;\n\n      rule = 0;\n    }\n\n  /* RULE is nil if the loop went through the list but everything failed.  */\n  if (rule == 0)\n    goto done;\n\n  foundrule = ri;\n\n  /* If we are recursing, store the pattern that matched FILENAME in\n     FILE->name for use in upper levels.  */\n\n  if (recursions > 0)\n    /* Kludge-o-matic */\n    file->name = rule->targets[tryrules[foundrule].matches];\n\n  /* DEPLIST lists the prerequisites for the rule we found.  This includes the\n     intermediate files, if any.  Convert them into entries on the deps-chain\n     of FILE.  */\n\n  while (pat-- > deplist)\n    {\n      struct dep *dep;\n      const char *s;\n\n      if (pat->file != 0)\n        {\n          /* If we need to use an intermediate file, make sure it is entered\n             as a target, with the info that was found for it in the recursive\n             pattern_search call.  We know that the intermediate file did not\n             already exist as a target; therefore we can assume that the deps\n             and cmds of F below are null before we change them.  */\n\n          struct file *imf = pat->file;\n          struct file *f = lookup_file (imf->name);\n\n          if (!f)\n            f = enter_file (imf->name);\n\n          f->deps = imf->deps;\n          f->cmds = imf->cmds;\n          f->stem = imf->stem;\n          /* Setting target specific variables for a file causes the file to be\n             entered to the database as a prerequisite. Implicit search then\n             treats this file as explicitly mentioned. Preserve target specific\n             variables of this file.  */\n          merge_variable_set_lists(&f->variables, imf->variables);\n          f->pat_variables = imf->pat_variables;\n          f->pat_searched = imf->pat_searched;\n          f->also_make = imf->also_make;\n          f->is_target = 1;\n          f->is_explicit |= imf->is_explicit || pat->is_explicit;\n          f->notintermediate |= imf->notintermediate || no_intermediates;\n          f->intermediate |= !f->is_explicit && !f->notintermediate;\n          f->tried_implicit = 1;\n\n          imf = lookup_file (pat->pattern);\n          if (imf != 0 && imf->precious)\n            f->precious = 1;\n\n          for (dep = f->deps; dep != 0; dep = dep->next)\n            {\n              dep->file = enter_file (dep->name);\n              dep->name = 0;\n              dep->file->tried_implicit |= dep->changed;\n            }\n        }\n\n      dep = alloc_dep ();\n      dep->ignore_mtime = pat->ignore_mtime;\n      dep->is_explicit = pat->is_explicit;\n      dep->ignore_automatic_vars = pat->ignore_automatic_vars;\n      dep->wait_here = pat->wait_here;\n      s = strcache_add (pat->name);\n      if (recursions)\n        dep->name = s;\n      else\n        {\n          dep->file = lookup_file (s);\n          if (dep->file == 0)\n            dep->file = enter_file (s);\n        }\n\n      if (pat->file == 0 && tryrules[foundrule].rule->terminal)\n        {\n          /* If the file actually existed (was not an intermediate file), and\n             the rule that found it was a terminal one, then we want to mark\n             the found file so that it will not have implicit rule search done\n             for it.  If we are not entering a 'struct file' for it now, we\n             indicate this with the 'changed' flag.  */\n          if (dep->file == 0)\n            dep->changed = 1;\n          else\n            dep->file->tried_implicit = 1;\n        }\n\n      dep->next = file->deps;\n      file->deps = dep;\n\n      /* The file changed its dependencies; schedule the shuffle.  */\n      file->was_shuffled = 0;\n    }\n\n  if (!file->was_shuffled)\n    shuffle_deps_recursive (file->deps);\n\n  if (!tryrules[foundrule].checked_lastslash)\n    {\n      /* Always allocate new storage, since STEM might be on the stack for an\n         intermediate file.  */\n      file->stem = strcache_add_len (stem, stemlen);\n      fullstemlen = stemlen;\n    }\n  else\n    {\n      /* We want to prepend the directory from\n         the original FILENAME onto the stem.  */\n      fullstemlen = pathlen + stemlen;\n      memcpy (stem_str, filename, pathlen);\n      memcpy (stem_str + pathlen, stem, stemlen);\n      stem_str[fullstemlen] = '\\0';\n      file->stem = strcache_add (stem_str);\n    }\n\n  file->cmds = rule->cmds;\n  file->is_target = 1;\n\n  /* Set precious and notintermediate flags. */\n  {\n    struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]);\n    if (f)\n      {\n        if (f->precious)\n          file->precious = 1;\n        if (f->notintermediate || no_intermediates)\n          file->notintermediate = 1;\n      }\n  }\n\n  /* If this rule builds other targets, too, put the others into FILE's\n     'also_make' member.  */\n\n  if (rule->num > 1)\n    for (ri = 0; ri < rule->num; ++ri)\n      if (ri != tryrules[foundrule].matches)\n        {\n          char *nm = alloca (rule->lens[ri] + fullstemlen + 1);\n          char *p = nm;\n          struct file *f;\n          struct dep *new = alloc_dep ();\n\n          /* GKM FIMXE: handle '|' here too */\n          p = mempcpy (p, rule->targets[ri],\n                       rule->suffixes[ri] - rule->targets[ri] - 1);\n          p = mempcpy (p, file->stem, fullstemlen);\n          memcpy (p, rule->suffixes[ri],\n                  rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1);\n          new->name = strcache_add (nm);\n          new->file = enter_file (new->name);\n          new->next = file->also_make;\n\n          /* Set precious flag. */\n          f = lookup_file (rule->targets[ri]);\n          if (f)\n            {\n              if (f->precious)\n                new->file->precious = 1;\n              if (f->notintermediate || no_intermediates)\n                new->file->notintermediate = 1;\n            }\n\n          /* Set the is_target flag so that this file is not treated as\n             intermediate by the pattern rule search algorithm and\n             file_exists_p cannot pick it up yet.  */\n          new->file->is_target = 1;\n\n          file->also_make = new;\n        }\n\n done:\n  free (tryrules);\n  free (deplist);\n\n  --depth;\n\n  if (rule)\n    {\n      DBS (DB_IMPLICIT, (_(\"Found implicit rule '%s' for '%s'.\\n\"),\n                         get_rule_defn (rule), filename));\n      return 1;\n    }\n\n  if (found_compat_rule)\n    {\n      DBS (DB_IMPLICIT, (_(\"Searching for a compatibility rule for '%s'.\\n\"),\n                         filename));\n      assert (allow_compat_rules == 0);\n      return pattern_search (file, archive, depth, recursions, 1);\n    }\n\n  DBS (DB_IMPLICIT, (_(\"No implicit rule found for '%s'.\\n\"), filename));\n  return 0;\n}\n"
  },
  {
    "path": "src/job.c",
    "content": "/* Job execution and handling for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n#include <string.h>\n\n/* Default shell to use.  */\n#if MK_OS_W32\n# include <windows.h>\n\nconst char *default_shell = \"sh.exe\";\nint no_default_sh_exe = 1;\nint batch_mode_shell = 1;\nHANDLE main_thread;\n\n#elif MK_OS_DOS\n\n/* The default shell is a pointer so we can change it if Makefile\n   says so.  It is without an explicit path so we get a chance\n   to search the $PATH for it (since MSDOS doesn't have standard\n   directories we could trust).  */\nconst char *default_shell = \"command.com\";\nint batch_mode_shell = 0;\n\n#elif MK_OS_OS2\n\nconst char *default_shell = \"/bin/sh\";\nint batch_mode_shell = 0;\n\n#elif MK_OS_VMS\n\n# include <descrip.h>\n# include <stsdef.h>\nconst char *default_shell = \"\";\nint batch_mode_shell = 0;\n\n#define strsignal vms_strsignal\nchar * vms_strsignal (int status);\n\n#ifndef C_FACILITY_NO\n# define C_FACILITY_NO 0x350000\n#endif\n#ifndef VMS_POSIX_EXIT_MASK\n# define VMS_POSIX_EXIT_MASK (C_FACILITY_NO | 0xA000)\n#endif\n\n#else\n\nconst char *default_shell = \"/bin/sh\";\nint batch_mode_shell = 0;\n\n#endif\n\n#if MK_OS_DOS\n# include <process.h>\nstatic int execute_by_shell;\nstatic int dos_pid = 123;\nint dos_status;\nint dos_command_running;\n#endif /* MK_OS_DOS */\n\n#if MK_OS_VMS\n# ifndef __GNUC__\n#   include <processes.h>\n# endif\n# include <starlet.h>\n# include <lib$routines.h>\nstatic void vmsWaitForChildren (int *);\n#endif\n\n#if MK_OS_W32\n# include <windows.h>\n# include <io.h>\n# include <process.h>\n# include \"sub_proc.h\"\n# include \"w32err.h\"\n# include \"pathstuff.h\"\n# define WAIT_NOHANG 1\n#endif /* MK_OS_W32 */\n\n#if MK_OS_OS2\n# include <process.h>\n#endif\n\n#if defined (HAVE_FCNTL_H)\n# include <fcntl.h>\n#endif\n\n#if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT)\n# include <sys/wait.h>\n#endif\n\n#ifdef HAVE_WAITPID\n# define WAIT_NOHANG(status)    waitpid (-1, (status), WNOHANG)\n#else   /* Don't have waitpid.  */\n# ifdef HAVE_WAIT3\n#  ifndef wait3\nextern int wait3 ();\n#  endif\n#  define WAIT_NOHANG(status)   wait3 ((status), WNOHANG, (struct rusage *) 0)\n# endif /* Have wait3.  */\n#endif /* Have waitpid.  */\n\n#ifdef USE_POSIX_SPAWN\n# include <spawn.h>\n# include \"findprog.h\"\n#endif\n\n#if !defined (wait) && !defined (POSIX)\nint wait ();\n#endif\n\n#ifndef HAVE_UNION_WAIT\n\n# define WAIT_T int\n\n# ifndef WTERMSIG\n#  define WTERMSIG(x) ((x) & 0x7f)\n# endif\n# ifndef WCOREDUMP\n#  define WCOREDUMP(x) ((x) & 0x80)\n# endif\n# ifndef WEXITSTATUS\n#  define WEXITSTATUS(x) (((x) >> 8) & 0xff)\n# endif\n# ifndef WIFSIGNALED\n#  define WIFSIGNALED(x) (WTERMSIG (x) != 0)\n# endif\n# ifndef WIFEXITED\n#  define WIFEXITED(x) (WTERMSIG (x) == 0)\n# endif\n\n#else   /* Have 'union wait'.  */\n\n# define WAIT_T union wait\n# ifndef WTERMSIG\n#  define WTERMSIG(x) ((x).w_termsig)\n# endif\n# ifndef WCOREDUMP\n#  define WCOREDUMP(x) ((x).w_coredump)\n# endif\n# ifndef WEXITSTATUS\n#  define WEXITSTATUS(x) ((x).w_retcode)\n# endif\n# ifndef WIFSIGNALED\n#  define WIFSIGNALED(x) (WTERMSIG(x) != 0)\n# endif\n# ifndef WIFEXITED\n#  define WIFEXITED(x) (WTERMSIG(x) == 0)\n# endif\n\n#endif  /* Don't have 'union wait'.  */\n\n#if !defined(HAVE_UNISTD_H) && !MK_OS_W32\nint dup2 ();\nint execve ();\nvoid _exit ();\n# if !MK_OS_VMS\nint geteuid ();\nint getegid ();\nint setgid ();\nint getgid ();\n# endif\n#endif\n\n#if HAVE_SYS_LOADAVG_H\n# include <sys/loadavg.h>\n#endif\n\n#if HAVE_DECL_GETLOADAVG == 0\nint getloadavg (double loadavg[], int nelem);\n#endif\n\n#include \"job.h\"\n#include \"debug.h\"\n#include \"filedef.h\"\n#include \"commands.h\"\n#include \"variable.h\"\n#include \"os.h\"\n#include \"dep.h\"\n#include \"shuffle.h\"\n#include \"warning.h\"\n\n/* Different systems have different requirements for pid_t.\n   Plus we have to support gettext string translation... Argh.  */\nstatic const char *\npid2str (pid_t pid)\n{\n  static char pidstring[100];\n#if MK_OS_W32 && (__GNUC__ > 3 || _MSC_VER > 1300)\n  /* %Id is only needed for 64-builds, which were not supported by\n      older versions of Windows compilers.  */\n  sprintf (pidstring, \"%Id\", pid);\n#else\n  sprintf (pidstring, \"%lu\", (unsigned long) pid);\n#endif\n  return pidstring;\n}\n\nstatic void free_child (struct child *);\nstatic void start_job_command (struct child *child);\nstatic int load_too_high (void);\nstatic int job_next_command (struct child *);\nstatic int start_waiting_job (struct child *);\n\f\n/* Chain of all live (or recently deceased) children.  */\n\nstruct child *children = 0;\n\n/* Number of children currently running.  */\n\nunsigned int job_slots_used = 0;\n\n/* Nonzero if the 'good' standard input is in use.  */\n\nstatic int good_stdin_used = 0;\n\n/* Chain of children waiting to run until the load average goes down.  */\n\nstatic struct child *waiting_jobs = 0;\n\n/* Non-zero if we use a *real* shell (always so on Unix).  */\n\nint unixy_shell = 1;\n\n/* Number of jobs started in the current second.  */\n\nunsigned long job_counter = 0;\n\n/* Number of jobserver tokens this instance is currently using.  */\n\nunsigned int jobserver_tokens = 0;\n\f\n\n#if MK_OS_W32\n/*\n * The macro which references this function is defined in makeint.h.\n */\nint\nw32_kill (pid_t pid, int sig)\n{\n  return ((process_kill ((HANDLE)pid, sig) == TRUE) ? 0 : -1);\n}\n\n/* This function creates a temporary file name with an extension specified\n * by the unixy arg.\n * Return an xmalloc'ed string of a newly created temp file and its\n * file descriptor, or die.  */\nstatic char *\ncreate_batch_file (char const *base, int unixy, int *fd)\n{\n  const char *const ext = unixy ? \"sh\" : \"bat\";\n  const char *error_string = NULL;\n  char temp_path[MAX_PATH+1]; /* need to know its length */\n  unsigned path_size = GetTempPath (sizeof temp_path, temp_path);\n  int path_is_dot = 0;\n  /* The following variable is static so we won't try to reuse a name\n     that was generated a little while ago, because that file might\n     not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below,\n     which tells the OS it doesn't need to flush the cache to disk.\n     If the file is not yet on disk, we might think the name is\n     available, while it really isn't.  This happens in parallel\n     builds, where Make doesn't wait for one job to finish before it\n     launches the next one.  */\n  static unsigned uniq = 0;\n  static int second_loop = 0;\n  const size_t sizemax = strlen (base) + strlen (ext) + 10;\n\n  if (path_size == 0)\n    {\n      path_size = GetCurrentDirectory (sizeof temp_path, temp_path);\n      path_is_dot = 1;\n    }\n\n  ++uniq;\n  if (uniq >= 0x10000 && !second_loop)\n    {\n      /* If we already had 64K batch files in this\n         process, make a second loop through the numbers,\n         looking for free slots, i.e. files that were\n         deleted in the meantime.  */\n      second_loop = 1;\n      uniq = 1;\n    }\n  while (path_size > 0 &&\n         path_size + sizemax < sizeof temp_path &&\n         !(uniq >= 0x10000 && second_loop))\n    {\n      unsigned size = sprintf (temp_path + path_size,\n                               \"%s%s-%x.%s\",\n                               temp_path[path_size - 1] == '\\\\' ? \"\" : \"\\\\\",\n                               base, uniq, ext);\n      HANDLE h = CreateFile (temp_path,  /* file name */\n                             GENERIC_READ | GENERIC_WRITE, /* desired access */\n                             0,                            /* no share mode */\n                             NULL,                         /* default security attributes */\n                             CREATE_NEW,                   /* creation disposition */\n                             FILE_ATTRIBUTE_NORMAL |       /* flags and attributes */\n                             FILE_ATTRIBUTE_TEMPORARY,     /* we'll delete it */\n                             NULL);                        /* no template file */\n\n      if (h == INVALID_HANDLE_VALUE)\n        {\n          const DWORD er = GetLastError ();\n\n          if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)\n            {\n              ++uniq;\n              if (uniq == 0x10000 && !second_loop)\n                {\n                  second_loop = 1;\n                  uniq = 1;\n                }\n            }\n\n          /* the temporary path is not guaranteed to exist */\n          else if (path_is_dot == 0)\n            {\n              path_size = GetCurrentDirectory (sizeof temp_path, temp_path);\n              path_is_dot = 1;\n            }\n\n          else\n            {\n              error_string = map_windows32_error_to_string (er);\n              break;\n            }\n        }\n      else\n        {\n          const unsigned final_size = path_size + size + 1;\n          char *const path = xmalloc (final_size);\n          memcpy (path, temp_path, final_size);\n          *fd = _open_osfhandle ((intptr_t)h, 0);\n          if (unixy)\n            {\n              char *p;\n              int ch;\n              for (p = path; (ch = *p) != 0; ++p)\n                if (ch == '\\\\')\n                  *p = '/';\n            }\n          return path; /* good return */\n        }\n    }\n\n  *fd = -1;\n  if (error_string == NULL)\n    error_string = _(\"Cannot create a temporary file\");\n  OS (fatal, NILF, \"%s\", error_string);\n\n  /* not reached */\n  return NULL;\n}\n#endif /* MK_OS_W32 */\n\n#if MK_OS_OS2\n/* returns whether path is assumed to be a unix like shell. */\nint\n_is_unixy_shell (const char *path)\n{\n  /* list of non unix shells */\n  const char *known_os2shells[] = {\n    \"cmd.exe\",\n    \"cmd\",\n    \"4os2.exe\",\n    \"4os2\",\n    \"4dos.exe\",\n    \"4dos\",\n    \"command.com\",\n    \"command\",\n    NULL\n  };\n\n  /* find the rightmost '/' or '\\\\' */\n  const char *name = strrchr (path, '/');\n  const char *p = strrchr (path, '\\\\');\n  unsigned i;\n\n  if (name && p)    /* take the max */\n    name = (name > p) ? name : p;\n  else if (p)       /* name must be 0 */\n    name = p;\n  else if (!name)   /* name and p must be 0 */\n    name = path;\n\n  if (ISDIRSEP (*name))\n    name++;\n\n  i = 0;\n  while (known_os2shells[i] != NULL)\n    {\n      if (strcasecmp (name, known_os2shells[i]) == 0)\n        return 0; /* not a unix shell */\n      i++;\n    }\n\n  /* in doubt assume a unix like shell */\n  return 1;\n}\n#endif /* MK_OS_OS2 */\n\n/* determines whether path looks to be a Bourne-like shell. */\nint\nis_bourne_compatible_shell (const char *path)\n{\n  /* List of known POSIX (or POSIX-ish) shells.  */\n  static const char *unix_shells[] = {\n    \"sh\",\n    \"bash\",\n    \"dash\",\n    \"ksh\",\n    \"rksh\",\n    \"zsh\",\n    \"ash\",\n    NULL\n  };\n  const char **s;\n\n  /* find the last directory separator, or the beginning of the string.  */\n  const char *cp = path + strlen (path);\n\n  while (cp > path && !ISDIRSEP (cp[-1]))\n    --cp;\n\n  /* this should be able to deal with extensions on Windows-like systems */\n  for (s = unix_shells; *s != NULL; ++s)\n    {\n#if MK_OS_W32 || MK_OS_DOS\n      size_t len = strlen (*s);\n      if ((strlen (cp) >= len && STOP_SET (cp[len], MAP_DOT|MAP_NUL))\n          && strncasecmp (cp, *s, len) == 0)\n#else\n      if (strcmp (cp, *s) == 0)\n#endif\n        return 1; /* a known unix-style shell */\n    }\n\n  /* if not on the list, assume it's not a Bourne-like shell */\n  return 0;\n}\n\n#ifdef POSIX\nextern sigset_t fatal_signal_set;\n\nstatic void\nblock_sigs ()\n{\n  sigprocmask (SIG_BLOCK, &fatal_signal_set, (sigset_t *) 0);\n}\n\nstatic void\nunblock_sigs ()\n{\n  sigprocmask (SIG_UNBLOCK, &fatal_signal_set, (sigset_t *) 0);\n}\n\nvoid\nunblock_all_sigs ()\n{\n  sigset_t empty;\n  sigemptyset (&empty);\n  sigprocmask (SIG_SETMASK, &empty, (sigset_t *) 0);\n}\n\n#elif defined(HAVE_SIGSETMASK)\n\nextern int fatal_signal_mask;\n\nstatic void\nblock_sigs ()\n{\n  sigblock (fatal_signal_mask);\n}\n\nstatic void\nunblock_sigs ()\n{\n  sigsetmask (siggetmask () & ~fatal_signal_mask);\n}\n\nvoid\nunblock_all_sigs ()\n{\n  sigsetmask (0);\n}\n\n#else\n\n#define block_sigs()\n#define unblock_sigs()\n\nvoid\nunblock_all_sigs ()\n{\n}\n\n#endif\n\f\n/* Write an error message describing the exit status given in\n   EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME.\n   Append \"(ignored)\" if IGNORED is nonzero.  */\n\nstatic void\nchild_error (struct child *child,\n             int exit_code, int exit_sig, int coredump, int ignored)\n{\n  const char *pre = \"*** \";\n  const char *post = \"\";\n  const char *dump = \"\";\n  const struct file *f = child->file;\n  const floc *flocp = &f->cmds->fileinfo;\n  const char *nm;\n  const char *smode;\n  size_t l;\n\n  if (ignored && run_silent)\n    return;\n\n  if (exit_sig && coredump)\n    dump = _(\" (core dumped)\");\n\n  if (ignored)\n    {\n      pre = \"\";\n      post = _(\" (ignored)\");\n    }\n\n  if (! flocp->filenm)\n    nm = _(\"<builtin>\");\n  else\n    {\n      char *a = alloca (strlen (flocp->filenm) + 6 + INTSTR_LENGTH + 1);\n      sprintf (a, \"%s:%lu\", flocp->filenm, flocp->lineno + flocp->offset);\n      nm = a;\n    }\n\n  l = strlen (pre) + strlen (nm) + strlen (f->name) + strlen (post);\n\n  smode = shuffle_get_mode ();\n  if (smode)\n    {\n#define SHUFFLE_PREFIX \" shuffle=\"\n      char *a = alloca (CSTRLEN(SHUFFLE_PREFIX) + strlen (smode) + 1);\n      sprintf (a, SHUFFLE_PREFIX \"%s\", smode);\n      smode = a;\n      l += strlen (smode);\n#undef SHUFFLE_PREFIX\n    }\n\n  OUTPUT_SET (&child->output);\n\n  show_goal_error ();\n\n  if (exit_sig == 0)\n    error (NILF, l + INTSTR_LENGTH, _(\"%s[%s: %s] Error %d%s%s\"),\n           pre, nm, f->name, exit_code, post, smode ? smode : \"\");\n  else\n    {\n      const char *s = strsignal (exit_sig);\n      error (NILF, l + strlen (s) + strlen (dump), \"%s[%s: %s] %s%s%s%s\",\n             pre, nm, f->name, s, dump, post, smode ? smode : \"\");\n    }\n\n  OUTPUT_UNSET ();\n}\n\f\n\n/* Handle a dead child.  This handler may or may not ever be installed.\n\n   If we're using the jobserver feature without pselect(), we need it.\n   First, installing it ensures the read will interrupt on SIGCHLD.  Second,\n   we close the dup'd read FD to ensure we don't enter another blocking read\n   without reaping all the dead children.  In this case we don't need the\n   dead_children count.\n\n   If we don't have either waitpid or wait3, then make is unreliable, but we\n   use the dead_children count to reap children as best we can.  */\n\nstatic unsigned int dead_children = 0;\n\nvoid\nchild_handler (int sig UNUSED)\n{\n  ++dead_children;\n\n  jobserver_signal ();\n\n#if MK_OS_OS2\n  /* The signal handler must called only once! */\n  signal (SIGCHLD, SIG_DFL);\n#endif\n}\n\nextern pid_t shell_function_pid;\n\n/* Reap all dead children, storing the returned status and the new command\n   state ('cs_finished') in the 'file' member of the 'struct child' for the\n   dead child, and removing the child from the chain.  In addition, if BLOCK\n   nonzero, we block in this function until we've reaped at least one\n   complete child, waiting for it to die if necessary.  If ERR is nonzero,\n   print an error message first.  */\n\nvoid\nreap_children (int block, int err)\n{\n#if !MK_OS_W32\n  WAIT_T status;\n#endif\n  /* Initially, assume we have some.  */\n  int reap_more = 1;\n\n#ifdef WAIT_NOHANG\n# define REAP_MORE reap_more\n#else\n# define REAP_MORE dead_children\n#endif\n\n  /* As long as:\n\n       We have at least one child outstanding OR a shell function in progress,\n         AND\n       We're blocking for a complete child OR there are more children to reap\n\n     we'll keep reaping children.  */\n\n  while ((children != 0 || shell_function_pid != 0)\n         && (block || REAP_MORE))\n    {\n      unsigned int remote = 0;\n      pid_t pid;\n      int exit_code, exit_sig, coredump;\n      struct child *lastc, *c;\n      int child_failed;\n      int any_remote, any_local;\n      int dontcare;\n\n      if (err && block)\n        {\n          static int printed = 0;\n\n          /* We might block for a while, so let the user know why.\n             Only print this message once no matter how many jobs are left.  */\n          fflush (stdout);\n          if (!printed)\n            O (error, NILF, _(\"*** Waiting for unfinished jobs....\"));\n          printed = 1;\n        }\n\n      /* We have one less dead child to reap.  As noted in\n         child_handler() above, this count is completely unimportant for\n         all modern, POSIX-y systems that support wait3() or waitpid().\n         The rest of this comment below applies only to early, broken\n         pre-POSIX systems.  We keep the count only because... it's there...\n\n         The test and decrement are not atomic; if it is compiled into:\n                register = dead_children - 1;\n                dead_children = register;\n         a SIGCHLD could come between the two instructions.\n         child_handler increments dead_children.\n         The second instruction here would lose that increment.  But the\n         only effect of dead_children being wrong is that we might wait\n         longer than necessary to reap a child, and lose some parallelism;\n         and we might print the \"Waiting for unfinished jobs\" message above\n         when not necessary.  */\n\n      if (dead_children > 0)\n        --dead_children;\n\n      any_remote = 0;\n      any_local = shell_function_pid != 0;\n      lastc = 0;\n      for (c = children; c != 0; lastc = c, c = c->next)\n        {\n          any_remote |= c->remote;\n          any_local |= ! c->remote;\n\n          /* If pid < 0, this child never even started.  Handle it.  */\n          if (c->pid < 0)\n            {\n              exit_sig = 0;\n              coredump = 0;\n              /* According to POSIX, 127 is used for command not found.  */\n              exit_code = 127;\n              goto process_child;\n            }\n\n          DB (DB_JOBS, (_(\"Live child %p (%s) PID %s %s\\n\"),\n                        c, c->file->name, pid2str (c->pid),\n                        c->remote ? _(\" (remote)\") : \"\"));\n#if MK_OS_VMS\n          break;\n#endif\n        }\n\n      /* First, check for remote children.  */\n      if (any_remote)\n        pid = remote_status (&exit_code, &exit_sig, &coredump, 0);\n      else\n        pid = 0;\n\n      if (pid > 0)\n        /* We got a remote child.  */\n        remote = 1;\n      else if (pid < 0)\n        {\n          /* A remote status command failed miserably.  Punt.  */\n          pfatal_with_name (\"remote_status\");\n        }\n      else\n        {\n          /* No remote children.  Check for local children.  */\n#if !MK_OS_DOS && !MK_OS_W32\n          if (any_local)\n            {\n#if MK_OS_VMS\n              /* Todo: This needs more untangling multi-process support */\n              /* Just do single child process support now */\n              vmsWaitForChildren (&status);\n              pid = c->pid;\n\n              /* VMS failure status can not be fully translated */\n              status = $VMS_STATUS_SUCCESS (c->cstatus) ? 0 : (1 << 8);\n\n              /* A Posix failure can be exactly translated */\n              if ((c->cstatus & VMS_POSIX_EXIT_MASK) == VMS_POSIX_EXIT_MASK)\n                status = (c->cstatus >> 3 & 255) << 8;\n#else\n#ifdef WAIT_NOHANG\n              if (!block)\n                pid = WAIT_NOHANG (&status);\n              else\n#endif\n                EINTRLOOP (pid, wait (&status));\n#endif /* !MK_OS_VMS */\n            }\n          else\n            pid = 0;\n\n          if (pid < 0)\n            {\n              /* The wait*() failed miserably.  Punt.  */\n              pfatal_with_name (\"wait\");\n            }\n          else if (pid > 0)\n            {\n              /* We got a child exit; chop the status word up.  */\n              exit_code = WEXITSTATUS (status);\n              exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;\n              coredump = WCOREDUMP (status);\n            }\n          else\n            {\n              /* No local children are dead.  */\n              reap_more = 0;\n\n              if (!block || !any_remote)\n                break;\n\n              /* Now try a blocking wait for a remote child.  */\n              pid = remote_status (&exit_code, &exit_sig, &coredump, 1);\n              if (pid < 0)\n                pfatal_with_name (\"remote_status\");\n\n              if (pid == 0)\n                /* No remote children either.  Finally give up.  */\n                break;\n\n              /* We got a remote child.  */\n              remote = 1;\n            }\n#endif /* !MK_OS_DOS, !MK_OS_W32.  */\n\n#if MK_OS_DOS\n          /* Life is very different on MSDOS.  */\n          pid = dos_pid - 1;\n          status = dos_status;\n          exit_code = WEXITSTATUS (status);\n          if (exit_code == 0xff)\n            exit_code = -1;\n          exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0;\n          coredump = 0;\n#endif /* MK_OS_DOS */\n#if MK_OS_W32\n          {\n            HANDLE hPID;\n            HANDLE hcTID, hcPID;\n            DWORD dwWaitStatus = 0;\n            exit_code = 0;\n            exit_sig = 0;\n            coredump = 0;\n\n            /* Record the thread ID of the main process, so that we\n               could suspend it in the signal handler.  */\n            if (!main_thread)\n              {\n                hcTID = GetCurrentThread ();\n                hcPID = GetCurrentProcess ();\n                if (!DuplicateHandle (hcPID, hcTID, hcPID, &main_thread, 0,\n                                      FALSE, DUPLICATE_SAME_ACCESS))\n                  {\n                    DWORD e = GetLastError ();\n                    fprintf (stderr,\n                             \"Determine main thread ID (Error %lu: %s)\\n\",\n                             e, map_windows32_error_to_string (e));\n                  }\n                else\n                  DB (DB_VERBOSE, (\"Main thread handle = %p\\n\", main_thread));\n              }\n\n            /* wait for anything to finish */\n            hPID = process_wait_for_any (block, &dwWaitStatus);\n            if (hPID)\n              {\n                /* was an error found on this process? */\n                int werr = process_last_err (hPID);\n\n                /* get exit data */\n                exit_code = process_exit_code (hPID);\n\n                /* the extra tests of exit_code are here to prevent\n                   map_windows32_error_to_string from calling 'fatal',\n                   which will then call reap_children again */\n                if (werr && exit_code > 0 && exit_code < WSABASEERR)\n                  fprintf (stderr, \"make (e=%d): %s\\n\", exit_code,\n                           map_windows32_error_to_string (exit_code));\n\n                /* signal */\n                exit_sig = process_signal (hPID);\n\n                /* cleanup process */\n                process_cleanup (hPID);\n\n                coredump = 0;\n              }\n            else if (dwWaitStatus == WAIT_FAILED)\n              {\n                /* The WaitForMultipleObjects() failed miserably.  Punt.  */\n                pfatal_with_name (\"WaitForMultipleObjects\");\n              }\n            else if (dwWaitStatus == WAIT_TIMEOUT)\n              {\n                /* No child processes are finished.  Give up waiting. */\n                reap_more = 0;\n                break;\n              }\n\n            pid = (pid_t) hPID;\n          }\n#endif /* MK_OS_W32 */\n        }\n\n      /* Some child finished: increment the command count.  */\n      ++command_count;\n\n      /* Check if this is the child of the 'shell' function.  */\n      if (!remote && pid == shell_function_pid)\n        {\n          shell_completed (exit_code, exit_sig);\n          break;\n        }\n\n      /* Search for a child matching the deceased one.  */\n      lastc = 0;\n      for (c = children; c != 0; lastc = c, c = c->next)\n        if (c->pid == pid && c->remote == remote)\n          break;\n\n      if (c == 0)\n        /* An unknown child died.\n           Ignore it; it was inherited from our invoker.  */\n        continue;\n\n      DB (DB_JOBS, (exit_sig == 0 && exit_code == 0\n                    ? _(\"Reaping winning child %p PID %s %s\\n\")\n                    : _(\"Reaping losing child %p PID %s %s\\n\"),\n                    c, pid2str (c->pid), c->remote ? _(\" (remote)\") : \"\"));\n\n      /* If we have started jobs in this second, remove one.  */\n      if (job_counter)\n        --job_counter;\n\n    process_child:\n\n#if defined(USE_POSIX_SPAWN)\n      /* Some versions of posix_spawn() do not detect errors such as command\n         not found until after they fork.  In that case they will exit with a\n         code of 127.  Try to detect that and provide a useful error message.\n         Otherwise we'll just show the error below, as normal.  */\n      if (exit_sig == 0 && exit_code == 127 && c->cmd_name)\n        {\n          const char *e = NULL;\n          struct stat st;\n          int r;\n\n          /* There are various ways that this will show a different error than\n             fork/exec.  To really get the right error we'd have to fall back\n             to fork/exec but I don't want to bother with that.  Just do the\n             best we can.  */\n\n          EINTRLOOP(r, stat (c->cmd_name, &st));\n          if (r < 0)\n            e = strerror (errno);\n          else if (S_ISDIR(st.st_mode) || !(st.st_mode & S_IXUSR))\n            e = strerror (EACCES);\n          else if (st.st_size == 0)\n            e = strerror (ENOEXEC);\n\n          if (e)\n            OSS(error, NILF, \"%s: %s\", c->cmd_name, e);\n        }\n#endif\n\n      /* Determine the failure status: 0 for success, 1 for updating target in\n         question mode, 2 for anything else.  */\n      if (exit_sig == 0 && exit_code == 0)\n        child_failed = MAKE_SUCCESS;\n      else if (exit_sig == 0 && exit_code == 1 && question_flag && c->recursive)\n        child_failed = MAKE_TROUBLE;\n      else\n        child_failed = MAKE_FAILURE;\n\n      if (c->sh_batch_file)\n        {\n          int rm_status;\n\n          DB (DB_JOBS, (_(\"Cleaning up temp batch file %s\\n\"),\n                        c->sh_batch_file));\n\n          errno = 0;\n          rm_status = remove (c->sh_batch_file);\n          if (rm_status)\n            DB (DB_JOBS, (_(\"Cleaning up temp batch file %s failed (%d)\\n\"),\n                          c->sh_batch_file, errno));\n\n          /* all done with memory */\n          free (c->sh_batch_file);\n          c->sh_batch_file = NULL;\n        }\n\n      /* If this child had the good stdin, say it is now free.  */\n      if (c->good_stdin)\n        good_stdin_used = 0;\n\n      dontcare = c->dontcare;\n\n      if (child_failed && !c->noerror && !ignore_errors_flag)\n        {\n          /* The commands failed.  Write an error message,\n             delete non-precious targets, and abort.  */\n          static int delete_on_error = -1;\n\n          if (!dontcare && child_failed == MAKE_FAILURE)\n            child_error (c, exit_code, exit_sig, coredump, 0);\n\n          c->file->update_status = child_failed == MAKE_FAILURE ? us_failed : us_question;\n          if (delete_on_error == -1)\n            {\n              struct file *f = lookup_file (\".DELETE_ON_ERROR\");\n              delete_on_error = f != 0 && f->is_target;\n            }\n          if (exit_sig != 0 || delete_on_error)\n            delete_child_targets (c);\n        }\n      else\n        {\n          if (child_failed)\n            {\n              /* The commands failed, but we don't care.  */\n              child_error (c, exit_code, exit_sig, coredump, 1);\n              child_failed = 0;\n            }\n\n          /* If there are more commands to run, try to start them.  */\n          if (job_next_command (c))\n            {\n              if (handling_fatal_signal)\n                {\n                  /* Never start new commands while we are dying.\n                     Since there are more commands that wanted to be run,\n                     the target was not completely remade.  So we treat\n                     this as if a command had failed.  */\n                  c->file->update_status = us_failed;\n                }\n              else\n                {\n                  /* If we're sync'ing per line, write the previous line's\n                     output before starting the next one.  */\n                  if (output_sync == OUTPUT_SYNC_LINE)\n                    output_dump (&c->output);\n                  /* Check again whether to start remotely.\n                     Whether or not we want to changes over time.\n                     Also, start_remote_job may need state set up\n                     by start_remote_job_p.  */\n                  c->remote = start_remote_job_p (0);\n                  start_job_command (c);\n                  /* Fatal signals are left blocked in case we were\n                     about to put that child on the chain.  But it is\n                     already there, so it is safe for a fatal signal to\n                     arrive now; it will clean up this child's targets.  */\n                  unblock_sigs ();\n                  if (c->file->command_state == cs_running)\n                    /* We successfully started the new command.\n                       Loop to reap more children.  */\n                    continue;\n                }\n\n              if (c->file->update_status != us_success)\n                /* We failed to start the commands.  */\n                delete_child_targets (c);\n            }\n          else\n            /* There are no more commands.  We got through them all\n               without an unignored error.  Now the target has been\n               successfully updated.  */\n            c->file->update_status = us_success;\n        }\n\n      /* When we get here, all the commands for c->file are finished.  */\n\n      /* Synchronize any remaining parallel output.  */\n      output_dump (&c->output);\n\n      /* At this point c->file->update_status is success or failed.  But\n         c->file->command_state is still cs_running if all the commands\n         ran; notice_finished_file looks for cs_running to tell it that\n         it's interesting to check the file's modtime again now.  */\n\n      if (! handling_fatal_signal)\n        /* Notice if the target of the commands has been changed.\n           This also propagates its values for command_state and\n           update_status to its also_make files.  */\n        notice_finished_file (c->file);\n\n      /* Block fatal signals while frobnicating the list, so that\n         children and job_slots_used are always consistent.  Otherwise\n         a fatal signal arriving after the child is off the chain and\n         before job_slots_used is decremented would believe a child was\n         live and call reap_children again.  */\n      block_sigs ();\n\n      if (c->pid > 0)\n        {\n          DB (DB_JOBS, (_(\"Removing child %p PID %s%s from chain.\\n\"),\n                        c, pid2str (c->pid), c->remote ? _(\" (remote)\") : \"\"));\n        }\n\n      /* There is now another slot open.  */\n      if (job_slots_used > 0)\n        job_slots_used -= c->jobslot;\n\n      /* Remove the child from the chain and free it.  */\n      if (lastc == 0)\n        children = c->next;\n      else\n        lastc->next = c->next;\n\n      free_child (c);\n\n      unblock_sigs ();\n\n      /* If the job failed, and the -k flag was not given, die,\n         unless we are already in the process of dying.  */\n      if (!err && child_failed && !dontcare && !keep_going_flag &&\n          /* fatal_error_signal will die with the right signal.  */\n          !handling_fatal_signal)\n        die (child_failed);\n\n      /* Only block for one child.  */\n      block = 0;\n    }\n\n  return;\n}\n\f\n/* Free the storage allocated for CHILD.  */\n\nvoid\nfree_childbase (struct childbase *child)\n{\n  if (child->environment != 0)\n    {\n      char **ep = child->environment;\n      while (*ep != 0)\n        free (*ep++);\n      free (child->environment);\n    }\n\n  free (child->cmd_name);\n}\n\nstatic void\nfree_child (struct child *child)\n{\n  output_close (&child->output);\n\n  if (!jobserver_tokens)\n    ONS (fatal, NILF, \"INTERNAL: freeing child %p (%s) but no tokens left\",\n         child, child->file->name);\n\n  /* If we're using the jobserver and this child is not the only outstanding\n     job, put a token back into the pipe for it.  */\n\n  if (jobserver_enabled () && jobserver_tokens > 1)\n    {\n      jobserver_release (1);\n      DB (DB_JOBS, (_(\"Released token for child %p (%s).\\n\"),\n                    child, child->file->name));\n    }\n\n  --jobserver_tokens;\n\n  if (handling_fatal_signal) /* Don't bother free'ing if about to die.  */\n    return;\n\n  if (child->command_lines != 0)\n    {\n      unsigned int i;\n      for (i = 0; i < child->file->cmds->ncommand_lines; ++i)\n        free (child->command_lines[i]);\n      free (child->command_lines);\n    }\n\n  free_childbase ((struct childbase*)child);\n\n  free (child);\n}\n\f\n\n/* Start a job to run the commands specified in CHILD.\n   CHILD is updated to reflect the commands and ID of the child process.\n\n   NOTE: On return fatal signals are blocked!  The caller is responsible\n   for calling 'unblock_sigs', once the new child is safely on the chain so\n   it can be cleaned up in the event of a fatal signal.  */\n\nstatic void\nstart_job_command (struct child *child)\n{\n  int flags;\n  char *p;\n#if MK_OS_VMS\n# define FREE_ARGV(_a)\n  char *argv;\n#else\n# define FREE_ARGV(_a) do{ if (_a) { free ((_a)[0]); free (_a); } }while(0)\n  char **argv;\n#endif\n\n  /* If we have a completely empty commandset, stop now.  */\n  if (!child->command_ptr)\n    goto next_command;\n\n  /* Combine the flags parsed for the line itself with\n     the flags specified globally for this target.  */\n  flags = (child->file->command_flags\n           | child->file->cmds->lines_flags[child->command_line - 1]);\n\n  p = child->command_ptr;\n  child->noerror = ANY_SET (flags, COMMANDS_NOERROR);\n\n  while (*p != '\\0')\n    {\n      if (*p == '@')\n        flags |= COMMANDS_SILENT;\n      else if (*p == '+')\n        flags |= COMMANDS_RECURSE;\n      else if (*p == '-')\n        child->noerror = 1;\n      /* Don't skip newlines.  */\n      else if (!ISBLANK (*p))\n        break;\n      ++p;\n    }\n\n  child->recursive = ANY_SET (flags, COMMANDS_RECURSE);\n\n  /* Update the file's command flags with any new ones we found.  We only\n     keep the COMMANDS_RECURSE setting.  Even this isn't 100% correct; we are\n     now marking more commands recursive than should be in the case of\n     multiline define/endef scripts where only one line is marked \"+\".  In\n     order to really fix this, we'll have to keep a lines_flags for every\n     actual line, after expansion.  */\n  child->file->cmds->lines_flags[child->command_line - 1] |= flags & COMMANDS_RECURSE;\n\n  /* POSIX requires that a recipe prefix after a backslash-newline should\n     be ignored.  Remove it now so the output is correct.  */\n  {\n    char prefix = child->file->cmds->recipe_prefix;\n    char *p1, *p2;\n    p1 = p2 = p;\n    while (*p1 != '\\0')\n      {\n        *(p2++) = *p1;\n        if (p1[0] == '\\n' && p1[1] == prefix)\n          ++p1;\n        ++p1;\n      }\n    *p2 = *p1;\n  }\n\n  /* Figure out an argument list from this command line.  */\n  {\n    char *end = 0;\n#if MK_OS_VMS\n    /* Skip any leading whitespace */\n    while (*p)\n      {\n        if (!ISSPACE (*p))\n          {\n            if (*p != '\\\\')\n              break;\n            if ((p[1] != '\\n') && (p[1] != 'n') && (p[1] != 't'))\n              break;\n          }\n        p++;\n      }\n\n    argv = p;\n    /* Please note, for VMS argv is a string (not an array of strings) which\n       contains the complete command line, which for multi-line variables\n       still includes the newlines.  So detect newlines and set 'end' (which\n       is used for child->command_ptr) instead of (re-)writing\n       construct_command_argv */\n    if (!one_shell)\n      {\n        char *s = p;\n        int instring = 0;\n        while (*s)\n          {\n            if (*s == '\"')\n              instring = !instring;\n            else if (*s == '\\\\' && !instring && *(s+1) != 0)\n              s++;\n            else if (*s == '\\n' && !instring)\n              {\n                end = s;\n                break;\n              }\n            ++s;\n          }\n      }\n#else\n    argv = construct_command_argv (p, &end, child->file,\n                                   child->file->cmds->lines_flags[child->command_line - 1] | child->file->command_flags,\n                                   &child->sh_batch_file);\n#endif\n    if (end == NULL)\n      child->command_ptr = NULL;\n    else\n      {\n        *end++ = '\\0';\n        child->command_ptr = end;\n      }\n  }\n\n  /* If -q was given, say that updating 'failed' if there was any text on the\n     command line, or 'succeeded' otherwise.  The exit status of 1 tells the\n     user that -q is saying 'something to do'; the exit status for a random\n     error is 2.  */\n  if (argv != 0 && question_flag && NONE_SET (flags, COMMANDS_RECURSE))\n    {\n      FREE_ARGV (argv);\n#if MK_OS_VMS\n      /* On VMS, argv[0] can be a null string here */\n      if (argv[0] != 0)\n        {\n#endif\n          child->file->update_status = us_question;\n          notice_finished_file (child->file);\n          return;\n#if MK_OS_VMS\n        }\n#endif\n    }\n\n  if (touch_flag && NONE_SET (flags, COMMANDS_RECURSE))\n    {\n      /* Go on to the next command.  It might be the recursive one.\n         We construct ARGV only to find the end of the command line.  */\n      FREE_ARGV (argv);\n      argv = 0;\n    }\n\n  if (argv == 0)\n    {\n    next_command:\n#if MK_OS_DOS\n      execute_by_shell = 0;   /* in case construct_command_argv sets it */\n#endif\n      /* This line has no commands.  Go to the next.  */\n      if (job_next_command (child))\n        start_job_command (child);\n      else\n        {\n          /* No more commands.  Make sure we're \"running\"; we might not be if\n             (e.g.) all commands were skipped due to -n.  */\n          set_command_state (child->file, cs_running);\n          child->file->update_status = us_success;\n          notice_finished_file (child->file);\n        }\n\n      OUTPUT_UNSET();\n      return;\n    }\n\n  /* Are we going to synchronize this command's output?  Do so if either we're\n     in SYNC_RECURSE mode or this command is not recursive.  We'll also check\n     output_sync separately below in case it changes due to error.  */\n  child->output.syncout = output_sync && (output_sync == OUTPUT_SYNC_RECURSE\n                                          || NONE_SET (flags, COMMANDS_RECURSE));\n\n  OUTPUT_SET (&child->output);\n\n  if (! child->output.syncout)\n    /* We don't want to sync this command: to avoid misordered\n       output ensure any already-synced content is written.  */\n    output_dump (&child->output);\n\n  /* Print the command if appropriate.  */\n  if (just_print_flag || ISDB (DB_PRINT)\n      || (NONE_SET (flags, COMMANDS_SILENT) && !run_silent))\n    OS (message, 0, \"%s\", p);\n\n  /* Tell update_goal_chain that a command has been started on behalf of\n     this target.  It is important that this happens here and not in\n     reap_children (where we used to do it), because reap_children might be\n     reaping children from a different target.  We want this increment to\n     guaranteedly indicate that a command was started for the dependency\n     chain (i.e., update_file recursion chain) we are processing.  */\n\n  ++commands_started;\n\n  /* Optimize an empty command.  People use this for timestamp rules,\n     so avoid forking a useless shell.  Do this after we increment\n     commands_started so make still treats this special case as if it\n     performed some action (makes a difference as to what messages are\n     printed, etc.  */\n\n#if !MK_OS_VMS\n  if (\n#if MK_OS_DOS || MK_OS_OS2\n      unixy_shell       /* the test is complicated and we already did it */\n#else\n      (argv[0] && is_bourne_compatible_shell (argv[0]))\n#endif\n      && (argv[1] && argv[1][0] == '-'\n        &&\n            ((argv[1][1] == 'c' && argv[1][2] == '\\0')\n          ||\n             (argv[1][1] == 'e' && argv[1][2] == 'c' && argv[1][3] == '\\0')))\n      && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\\0')\n      && argv[3] == NULL)\n    {\n      FREE_ARGV (argv);\n      goto next_command;\n    }\n#endif  /* !MK_OS_VMS */\n\n  /* If -n was given, recurse to get the next line in the sequence.  */\n\n  if (just_print_flag && NONE_SET (flags, COMMANDS_RECURSE))\n    {\n      FREE_ARGV (argv);\n      goto next_command;\n    }\n\n  /* We're sure we're going to invoke a command: set up the output.  */\n  output_start ();\n\n  /* Flush the output streams so they won't have things written twice.  */\n\n  fflush (stdout);\n  fflush (stderr);\n\n  /* Decide whether to give this child the 'good' standard input\n     (one that points to the terminal or whatever), or the 'bad' one\n     that points to the read side of a broken pipe.  */\n\n  child->good_stdin = !good_stdin_used;\n  if (child->good_stdin)\n    good_stdin_used = 1;\n\n  child->deleted = 0;\n\n  /* Set up the environment for the child.\n     It's a slight inaccuracy to set the environment for recursive make even\n     for command lines that aren't recursive, but I don't want to have to\n     recompute the target environment for each command.  Better would be to\n     keep a separate entry for MAKEFLAGS in the environment so it could be\n     replaced on its own.  For now just set it for all lines.\n   */\n  if (child->environment == 0)\n    child->environment = target_environment (child->file,\n                                             child->file->cmds->any_recurse);\n\n#if !MK_OS_DOS && !MK_OS_W32\n\n#if !MK_OS_VMS\n  /* start_waiting_job has set CHILD->remote if we can start a remote job.  */\n  if (child->remote)\n    {\n      int is_remote, used_stdin;\n      pid_t id;\n      if (start_remote_job (argv, child->environment,\n                            child->good_stdin ? 0 : get_bad_stdin (),\n                            &is_remote, &id, &used_stdin))\n        /* Don't give up; remote execution may fail for various reasons.  If\n           so, simply run the job locally.  */\n        goto run_local;\n      else\n        {\n          if (child->good_stdin && !used_stdin)\n            {\n              child->good_stdin = 0;\n              good_stdin_used = 0;\n            }\n          child->remote = is_remote;\n          child->pid = id;\n        }\n    }\n  else\n#endif /* !MK_OS_VMS */\n    {\n      /* Fork the child process.  */\n    run_local:\n      block_sigs ();\n\n      child->remote = 0;\n\n#if MK_OS_VMS\n      child->pid = child_execute_job ((struct childbase *)child, 1, argv);\n\n#else\n\n      jobserver_pre_child (ANY_SET (flags, COMMANDS_RECURSE));\n\n      child->pid = child_execute_job ((struct childbase *)child,\n                                      child->good_stdin, argv);\n\n      jobserver_post_child (ANY_SET (flags, COMMANDS_RECURSE));\n\n#endif /* !MK_OS_VMS */\n    }\n\n#else   /* MK_OS_DOS or MK_OS_W32 */\n#if MK_OS_DOS\n  {\n    int proc_return;\n\n    block_sigs ();\n    dos_status = 0;\n\n    /* We call 'system' to do the job of the SHELL, since stock DOS\n       shell is too dumb.  Our 'system' knows how to handle long\n       command lines even if pipes/redirection is needed; it will only\n       call COMMAND.COM when its internal commands are used.  */\n    if (execute_by_shell)\n      {\n        char *cmdline = argv[0];\n        /* We don't have a way to pass environment to 'system',\n           so we need to save and restore ours, sigh...  */\n        char **parent_env = environ;\n\n        environ = child->environment;\n\n        /* If we have a *real* shell, tell 'system' to call\n           it to do everything for us.  */\n        if (unixy_shell)\n          {\n            /* A *real* shell on MSDOS may not support long\n               command lines the DJGPP way, so we must use 'system'.  */\n            cmdline = argv[2];  /* get past \"shell -c\" */\n          }\n\n        dos_command_running = 1;\n        proc_return = system (cmdline);\n        environ = parent_env;\n        execute_by_shell = 0;   /* for the next time */\n      }\n    else\n      {\n        dos_command_running = 1;\n        proc_return = spawnvpe (P_WAIT, argv[0], argv, child->environment);\n      }\n\n    /* Need to unblock signals before turning off\n       dos_command_running, so that child's signals\n       will be treated as such (see fatal_error_signal).  */\n    unblock_sigs ();\n    dos_command_running = 0;\n\n    /* If the child got a signal, dos_status has its\n       high 8 bits set, so be careful not to alter them.  */\n    if (proc_return == -1)\n      dos_status |= 0xff;\n    else\n      dos_status |= (proc_return & 0xff);\n    ++dead_children;\n    child->pid = dos_pid++;\n  }\n#endif /* MK_OS_DOS */\n#if MK_OS_W32\n  {\n      HANDLE hPID;\n      char* arg0;\n      int outfd = -1;\n      int errfd = -1;\n\n      /* make UNC paths safe for CreateProcess -- backslash format */\n      arg0 = argv[0];\n      if (arg0 && arg0[0] == '/' && arg0[1] == '/')\n        for ( ; arg0 && *arg0; arg0++)\n          if (*arg0 == '/')\n            *arg0 = '\\\\';\n\n      /* make sure CreateProcess() has Path it needs */\n      sync_Path_environment ();\n\n      /* Divert child output if output_sync in use.  */\n      if (child->output.syncout)\n        {\n          if (child->output.out >= 0)\n            outfd = child->output.out;\n          if (child->output.err >= 0)\n            errfd = child->output.err;\n        }\n\n      hPID = process_easy (argv, child->environment, outfd, errfd);\n\n      if (hPID != INVALID_HANDLE_VALUE)\n        child->pid = (pid_t) hPID;\n      else\n        {\n          int i;\n          unblock_sigs ();\n          fprintf (stderr,\n                   _(\"process_easy() failed to launch process (e=%ld)\\n\"),\n                   process_last_err (hPID));\n          for (i = 0; argv[i]; i++)\n            fprintf (stderr, \"%s \", argv[i]);\n          fprintf (stderr, _(\"\\nCounted %d args in failed launch\\n\"), i);\n          child->pid = -1;\n        }\n  }\n#endif /* MK_OS_W32 */\n#endif  /* MK_OS_DOS or MK_OS_W32 */\n\n  /* Bump the number of jobs started in this second.  */\n  if (child->pid >= 0)\n    ++job_counter;\n\n  /* Set the state to running.  */\n  set_command_state (child->file, cs_running);\n\n  /* Free the storage used by the child's argument list.  */\n  FREE_ARGV (argv);\n\n  OUTPUT_UNSET();\n\n#undef FREE_ARGV\n}\n\n/* Try to start a child running.\n   Returns nonzero if the child was started (and maybe finished), or zero if\n   the load was too high and the child was put on the 'waiting_jobs' chain.  */\n\nstatic int\nstart_waiting_job (struct child *c)\n{\n  struct file *f = c->file;\n\n  /* If we can start a job remotely, we always want to, and don't care about\n     the local load average.  We record that the job should be started\n     remotely in C->remote for start_job_command to test.  */\n\n  c->remote = start_remote_job_p (1);\n\n  /* If we are running at least one job already and the load average\n     is too high, make this one wait.  */\n  if (!c->remote\n      && ((job_slots_used > 0 && load_too_high ())\n#if MK_OS_W32\n          || process_table_full ()\n#endif\n          ))\n    {\n      /* Put this child on the chain of children waiting for the load average\n         to go down.  */\n      set_command_state (f, cs_running);\n      c->next = waiting_jobs;\n      waiting_jobs = c;\n      return 0;\n    }\n\n  /* Start the first command; reap_children will run later command lines.  */\n  start_job_command (c);\n\n  switch (f->command_state)\n    {\n    case cs_running:\n      c->next = children;\n      if (c->pid > 0)\n        {\n          DB (DB_JOBS, (_(\"Putting child %p (%s) PID %s%s on the chain.\\n\"),\n                        c, c->file->name, pid2str (c->pid),\n                        c->remote ? _(\" (remote)\") : \"\"));\n          /* One more job slot is in use.  */\n          ++job_slots_used;\n          assert (c->jobslot == 0);\n          c->jobslot = 1;\n        }\n      children = c;\n      unblock_sigs ();\n      break;\n\n    case cs_not_started:\n      /* All the command lines turned out to be empty.  */\n      f->update_status = us_success;\n      /* FALLTHROUGH */\n\n    case cs_finished:\n      notice_finished_file (f);\n      free_child (c);\n      break;\n\n    default:\n      assert (f->command_state == cs_finished);\n      break;\n    }\n\n  return 1;\n}\n\n/* Create a 'struct child' for FILE and start its commands running.  */\n\nvoid\nnew_job (struct file *file)\n{\n  struct commands *cmds = file->cmds;\n  struct child *c;\n  char **lines;\n  unsigned int i;\n\n  /* Let any previously decided-upon jobs that are waiting\n     for the load to go down start before this new one.  */\n  start_waiting_jobs ();\n\n  /* Reap any children that might have finished recently.  */\n  reap_children (0, 0);\n\n  /* Chop the commands up into lines if they aren't already.  */\n  chop_commands (cmds);\n\n  /* Start the command sequence, record it in a new\n     'struct child', and add that to the chain.  */\n\n  c = xcalloc (sizeof (struct child));\n  output_init (&c->output);\n\n  c->file = file;\n  c->sh_batch_file = NULL;\n\n  /* Cache dontcare flag because file->dontcare can be changed once we\n     return. Check dontcare inheritance mechanism for details.  */\n  c->dontcare = file->dontcare;\n\n  /* Start saving output in case the expansion uses $(info ...) etc.  */\n  OUTPUT_SET (&c->output);\n\n  /* Expand the command lines and store the results in LINES.  */\n  lines = xmalloc (cmds->ncommand_lines * sizeof (char *));\n  for (i = 0; i < cmds->ncommand_lines; ++i)\n    {\n      /* Collapse backslash-newline combinations that are inside variable\n         or function references.  These are left alone by the parser so\n         that they will appear in the echoing of commands (where they look\n         nice); and collapsed by construct_command_argv when it tokenizes.\n         But letting them survive inside function invocations loses because\n         we don't want the functions to see them as part of the text.  */\n\n      char *in, *out, *ref;\n\n      /* IN points to where in the line we are scanning.\n         OUT points to where in the line we are writing.\n         When we collapse a backslash-newline combination,\n         IN gets ahead of OUT.  */\n\n      in = out = cmds->command_lines[i];\n      while ((ref = strchr (in, '$')) != 0)\n        {\n          ++ref;                /* Move past the $.  */\n\n          if (out != in)\n            /* Copy the text between the end of the last chunk\n               we processed (where IN points) and the new chunk\n               we are about to process (where REF points).  */\n            memmove (out, in, ref - in);\n\n          /* Move both pointers past the boring stuff.  */\n          out += ref - in;\n          in = ref;\n\n          if (*ref == '(' || *ref == '{')\n            {\n              char openparen = *ref;\n              char closeparen = openparen == '(' ? ')' : '}';\n              char *outref;\n              int count;\n              char *p;\n\n              *out++ = *in++;   /* Copy OPENPAREN.  */\n              outref = out;\n              /* IN now points past the opening paren or brace.  Count parens\n                 or braces until it is matched.  We don't use skip_reference\n                 since we want to handle internal backslash/newlines.  */\n              count = 0;\n              while (*in != '\\0')\n                {\n                  if (*in == '\\\\' && in[1] == '\\n')\n                    {\n                      /* We have found a backslash-newline inside a\n                         variable or function reference.  Eat it and\n                         any following whitespace.  */\n\n                      int quoted = 0;\n                      for (p = in - 1; p > ref && *p == '\\\\'; --p)\n                        quoted = !quoted;\n\n                      if (quoted)\n                        /* There were an even number of backslashes, so this\n                           is not really a continuation line.  We don't\n                           collapse the quoting backslashes here as is done in\n                           collapse_continuations, because the line will be\n                           collapsed again after expansion.  */\n                        *out++ = *in++;\n                      else\n                        {\n                          /* Skip the backslash, newline, and whitespace.  */\n                          in += 2;\n                          NEXT_TOKEN (in);\n\n                          /* Discard any preceding whitespace that has\n                             already been written to the output.  */\n                          while (out > outref && ISBLANK (out[-1]))\n                            --out;\n\n                          /* Replace it all with a single space.  */\n                          *out++ = ' ';\n                        }\n                      continue;\n                    }\n                  if (*in == closeparen && --count < 0)\n                    break;\n                  if (*in == openparen)\n                    ++count;\n\n                  *out++ = *in++;\n                }\n            }\n        }\n\n      /* There are no more references in this line to worry about.\n         Copy the remaining uninteresting text to the output.  */\n      if (out != in)\n        memmove (out, in, strlen (in) + 1);\n\n      /* Finally, expand the line.  */\n      cmds->fileinfo.offset = i;\n      lines[i] = allocated_expand_string_for_file (cmds->command_lines[i],\n                                                   file);\n    }\n\n  cmds->fileinfo.offset = 0;\n  c->command_lines = lines;\n\n  /* Fetch the first command line to be run.  */\n  job_next_command (c);\n\n  /* Wait for a job slot to be freed up.  If we allow an infinite number\n     don't bother; also job_slots will == 0 if we're using the jobserver.  */\n\n  if (job_slots != 0)\n    while (job_slots_used == job_slots)\n      reap_children (1, 0);\n\n#ifdef MAKE_JOBSERVER\n  /* If we are controlling multiple jobs make sure we have a token before\n     starting the child. */\n\n  /* This can be inefficient.  There's a decent chance that this job won't\n     actually have to run any subprocesses: the command script may be empty\n     or otherwise optimized away.  It would be nice if we could defer\n     obtaining a token until just before we need it, in start_job_command.\n     To do that we'd need to keep track of whether we'd already obtained a\n     token (since start_job_command is called for each line of the job, not\n     just once).  Also more thought needs to go into the entire algorithm;\n     this is where the old parallel job code waits, so...  */\n\n  else if (jobserver_enabled ())\n    while (1)\n      {\n        int got_token;\n\n        DB (DB_JOBS, (\"Need a job token; we %shave children\\n\",\n                      children ? \"\" : \"don't \"));\n\n        /* If we don't already have a job started, use our \"free\" token.  */\n        if (!jobserver_tokens)\n          break;\n\n        /* Prepare for jobserver token acquisition.  */\n        jobserver_pre_acquire ();\n\n        /* Reap anything that's currently waiting.  */\n        reap_children (0, 0);\n\n        /* Kick off any jobs we have waiting for an opportunity that\n           can run now (i.e., waiting for load). */\n        start_waiting_jobs ();\n\n        /* If our \"free\" slot is available, use it; we don't need a token.  */\n        if (!jobserver_tokens)\n          break;\n\n        /* There must be at least one child already, or we have no business\n           waiting for a token. */\n        if (!children)\n          O (fatal, NILF, \"INTERNAL: no children as we go to sleep on read\");\n\n        /* Get a token.  */\n        got_token = jobserver_acquire (waiting_jobs != NULL);\n\n        /* If we got one, we're done here.  */\n        if (got_token == 1)\n          {\n            DB (DB_JOBS, (_(\"Obtained token for child %p (%s).\\n\"),\n                          c, c->file->name));\n            break;\n          }\n      }\n#endif\n\n  ++jobserver_tokens;\n\n  /* Trace the build.\n     Use message here so that changes to working directories are logged.  */\n  if (ISDB (DB_WHY))\n    {\n      char *nmbuf = NULL;\n      const char *nm;\n      const char *tp;\n\n      if (! cmds->fileinfo.filenm)\n        nm = _(\"<builtin>\");\n      else\n        {\n          char *n = alloca (strlen (cmds->fileinfo.filenm) + 1 + 11 + 1);\n          sprintf (n, \"%s:%lu\", cmds->fileinfo.filenm, cmds->fileinfo.lineno);\n          nm = n;\n        }\n\n      if (c->file->also_make == NULL)\n        tp = c->file->name;\n      else\n        {\n          const struct dep *dp;\n          char *cp;\n          size_t len = strlen (c->file->name);\n          for (dp = c->file->also_make; dp; dp = dp->next)\n            /* space for \"', '<name>\".  */\n            len += strlen (dp->file->name) + 4;\n          tp = nmbuf = xmalloc (len + 1);\n          cp = stpcpy (nmbuf, c->file->name);\n          for (dp = c->file->also_make; dp; dp = dp->next)\n            cp = stpcpy (stpcpy (cp, \"', '\"), dp->file->name);\n        }\n\n      if (c->file->phony)\n        OSS (message, 0, _(\"%s: update target '%s' due to: target is .PHONY\"),\n             nm, tp);\n      else if (c->file->last_mtime == NONEXISTENT_MTIME)\n        OSS (message, 0,\n             _(\"%s: update target '%s' due to: target does not exist\"),\n             nm, tp);\n      else\n        {\n          char *newer = allocated_expand_variable_for_file (STRING_SIZE_TUPLE (\"?\"), c->file);\n          if (newer[0] != '\\0')\n            {\n              OSSS (message, 0, _(\"%s: update target '%s' due to: %s\"),\n                    nm, tp, newer);\n              free (newer);\n            }\n          else\n            {\n              /* One or more files didn't exist, and didn't get created.  */\n              size_t len = 0;\n              struct dep *d;\n\n              for (d = c->file->deps; d != NULL; d = d->next)\n                if (d->file->last_mtime == NONEXISTENT_MTIME)\n                  len += strlen (d->file->name) + 1;\n\n              if (!len)\n                OSS (message, 0,\n                     _(\"%s: update target '%s' due to: unknown reasons\"),\n                     nm, tp);\n              else\n                {\n                  char *cp = newer = alloca (len);\n                  for (d = c->file->deps; d != NULL; d = d->next)\n                    if (d->file->last_mtime == NONEXISTENT_MTIME)\n                      {\n                        if (cp > newer)\n                          *(cp++) = ' ';\n                        cp = stpcpy (cp, d->file->name);\n                      }\n                  OSSS (message, 0, _(\"%s: update target '%s' due to: %s\"),\n                        nm, tp, newer);\n                }\n            }\n        }\n\n      free (nmbuf);\n    }\n\n  /* The job is now primed.  Start it running.\n     (This will notice if there is in fact no recipe.)  */\n  start_waiting_job (c);\n\n  if (job_slots == 1 || not_parallel)\n    /* Since there is only one job slot, make things run linearly.\n       Wait for the child to die, setting the state to 'cs_finished'.  */\n    while (file->command_state == cs_running)\n      reap_children (1, 0);\n\n  OUTPUT_UNSET ();\n  return;\n}\n\f\n/* Move CHILD's pointers to the next command for it to execute.\n   Returns nonzero if there is another command.  */\n\nstatic int\njob_next_command (struct child *child)\n{\n  while (child->command_ptr == 0 || *child->command_ptr == '\\0')\n    {\n      /* There are no more lines in the expansion of this line.  */\n      if (child->command_line == child->file->cmds->ncommand_lines)\n        {\n          /* There are no more lines to be expanded.  */\n          child->command_ptr = 0;\n          child->file->cmds->fileinfo.offset = 0;\n          return 0;\n        }\n      else\n        /* Get the next line to run.  */\n        child->command_ptr = child->command_lines[child->command_line++];\n    }\n\n  child->file->cmds->fileinfo.offset = child->command_line - 1;\n  return 1;\n}\n\n/* Determine if the load average on the system is too high to start a new job.\n\n   On systems which provide /proc/loadavg (e.g., Linux), we use an idea\n   provided by Sven C. Dack <sven.c.dack@sky.com>: retrieve the current number\n   of runnable processes, if it's greater than the requested load we don't\n   allow another job to start.  We allow a job to start with equal processes\n   since one of those will be for make itself, which will then pause waiting\n   for jobs to clear.\n\n   If /proc/loadavg is not available for some reason, we obtain the system\n   load average and compare that.\n\n   The system load average is only recomputed once every N (N>=1) seconds.\n   However, a very parallel make can easily start tens or even hundreds of\n   jobs in a second, which brings the system to its knees for a while until\n   that first batch of jobs clears out.\n\n   To avoid this we use a weighted algorithm to try to account for jobs which\n   have been started since the last second, and guess what the load average\n   would be now if it were computed.\n\n   This algorithm was provided by Thomas Riedl <thomas.riedl@siemens.com>,\n   based on load average being recomputed once per second, which is\n   (apparently) how Solaris operates.  Linux recomputes only once every 5\n   seconds, but Linux is handled by the /proc/loadavg algorithm above.\n\n   Thomas writes:\n\n!      calculate something load-oid and add to the observed sys.load,\n!      so that latter can catch up:\n!      - every job started increases jobctr;\n!      - every dying job decreases a positive jobctr;\n!      - the jobctr value gets zeroed every change of seconds,\n!        after its value*weight_b is stored into the 'backlog' value last_sec\n!      - weight_a times the sum of jobctr and last_sec gets\n!        added to the observed sys.load.\n!\n!      The two weights have been tried out on 24 and 48 proc. Sun Solaris-9\n!      machines, using a several-thousand-jobs-mix of cpp, cc, cxx and smallish\n!      sub-shelled commands (rm, echo, sed...) for tests.\n!      lowering the 'direct influence' factor weight_a (e.g. to 0.1)\n!      resulted in significant excession of the load limit, raising it\n!      (e.g. to 0.5) took bad to small, fast-executing jobs and didn't\n!      reach the limit in most test cases.\n!\n!      lowering the 'history influence' weight_b (e.g. to 0.1) resulted in\n!      exceeding the limit for longer-running stuff (compile jobs in\n!      the .5 to 1.5 sec. range),raising it (e.g. to 0.5) overrepresented\n!      small jobs' effects.\n\n */\n\n#define LOAD_WEIGHT_A           0.25\n#define LOAD_WEIGHT_B           0.25\n\nstatic int\nload_too_high (void)\n{\n#if MK_OS_DOS || MK_OS_VMS || defined(__riscos__)\n  return 1;\n#else\n  static double last_sec;\n  static time_t last_now;\n  static int proc_fd = -2;\n\n  double load, guess;\n  time_t now;\n\n#if MK_OS_W32\n  /* sub_proc.c is limited in the number of objects it can wait for. */\n  if (process_table_full ())\n    return 1;\n#endif\n\n  if (max_load_average < 0)\n    return 0;\n\n  /* If we haven't tried to open /proc/loadavg, try now.  */\n#define LOADAVG \"/proc/loadavg\"\n  if (proc_fd == -2)\n    {\n      EINTRLOOP (proc_fd, open (LOADAVG, O_RDONLY));\n      if (proc_fd < 0)\n        DB (DB_JOBS, (\"Using system load detection method.\\n\"));\n      else\n        {\n          DB (DB_JOBS, (\"Using \" LOADAVG \" load detection method.\\n\"));\n          fd_noinherit (proc_fd);\n        }\n    }\n\n  /* Try to read /proc/loadavg if we managed to open it.  */\n  if (proc_fd >= 0)\n    {\n      int r;\n\n      EINTRLOOP (r, lseek (proc_fd, 0, SEEK_SET));\n      if (r >= 0)\n        {\n#define PROC_LOADAVG_SIZE 64\n          char avg[PROC_LOADAVG_SIZE+1];\n\n          EINTRLOOP (r, read (proc_fd, avg, PROC_LOADAVG_SIZE));\n          if (r >= 0)\n            {\n              const char *p;\n\n              /* The syntax of /proc/loadavg is:\n                    <1m> <5m> <15m> <running>/<total> <pid>\n                 The load is considered too high if there are more jobs\n                 running than the requested average.  */\n\n              avg[r] = '\\0';\n              p = strchr (avg, ' ');\n              if (p)\n                p = strchr (p+1, ' ');\n              if (p)\n                p = strchr (p+1, ' ');\n\n              if (p && ISDIGIT(p[1]))\n                {\n                  unsigned int cnt = make_toui (p+1, NULL);\n                  DB (DB_JOBS, (\"Running: system = %u / make = %u (max requested = %f)\\n\",\n                                cnt, job_slots_used, max_load_average));\n                  return (double)cnt > max_load_average;\n                }\n\n              DB (DB_JOBS, (\"Failed to parse \" LOADAVG \": %s\\n\", avg));\n            }\n        }\n\n      /* If we got here, something went wrong.  Give up on this method.  */\n      if (r < 0)\n        DB (DB_JOBS, (\"Failed to read \" LOADAVG \": %s\\n\", strerror (errno)));\n\n      close (proc_fd);\n      proc_fd = -1;\n    }\n\n  /* Find the real system load average.  */\n  errno = 0;\n  if (getloadavg (&load, 1) != 1)\n    {\n      static int lossage = -1;\n      /* Complain only once for the same error.  */\n      if (lossage == -1 || errno != lossage)\n        {\n          if (errno == 0)\n            /* An errno value of zero means getloadavg is just unsupported.  */\n            O (error, NILF,\n               _(\"cannot enforce load limits on this operating system\"));\n          else\n            perror_with_name (_(\"cannot enforce load limit: \"), \"getloadavg\");\n        }\n      lossage = errno;\n      load = 0;\n    }\n\n  /* If we're in a new second zero the counter and correct the backlog\n     value.  Only keep the backlog for one extra second; after that it's 0.  */\n  now = time (NULL);\n  if (last_now < now)\n    {\n      if (last_now == now - 1)\n        last_sec = LOAD_WEIGHT_B * job_counter;\n      else\n        last_sec = 0.0;\n\n      job_counter = 0;\n      last_now = now;\n    }\n\n  /* Try to guess what the load would be right now.  */\n  guess = load + (LOAD_WEIGHT_A * (job_counter + last_sec));\n\n  DB (DB_JOBS, (\"Estimated system load = %f (actual = %f) (max requested = %f)\\n\",\n                guess, load, max_load_average));\n\n  return guess >= max_load_average;\n#endif\n}\n\n/* Start jobs that are waiting for the load to be lower.  */\n\nvoid\nstart_waiting_jobs (void)\n{\n  struct child *job;\n\n  if (waiting_jobs == 0)\n    return;\n\n  do\n    {\n      /* Check for recently deceased descendants.  */\n      reap_children (0, 0);\n\n      /* Take a job off the waiting list.  */\n      job = waiting_jobs;\n      waiting_jobs = job->next;\n\n      /* Try to start that job.  We break out of the loop as soon\n         as start_waiting_job puts one back on the waiting list.  */\n    }\n  while (start_waiting_job (job) && waiting_jobs != 0);\n\n  return;\n}\n\f\n#if !MK_OS_W32\n\n/* EMX: Start a child process. This function returns the new pid.  */\n# if MK_OS_OS2\npid_t\nchild_execute_job (struct childbase *child, int good_stdin, char **argv)\n{\n  pid_t pid;\n  int fdin = good_stdin ? FD_STDIN : get_bad_stdin ();\n  int fdout = FD_STDOUT;\n  int fderr = FD_STDERR;\n  int save_fdin = -1;\n  int save_fdout = -1;\n  int save_fderr = -1;\n\n  /* Divert child output if we want to capture output.  */\n  if (child->output.syncout)\n    {\n      if (child->output.out >= 0)\n        fdout = child->output.out;\n      if (child->output.err >= 0)\n        fderr = child->output.err;\n    }\n\n  /* For each FD which needs to be redirected first make a dup of the standard\n     FD to save and mark it close on exec so our child won't see it.  Then\n     dup2() the standard FD to the redirect FD, and also mark the redirect FD\n     as close on exec. */\n  if (fdin != FD_STDIN)\n    {\n      save_fdin = dup (FD_STDIN);\n      if (save_fdin < 0)\n        O (fatal, NILF, _(\"no more file handles: could not duplicate stdin\"));\n      fd_noinherit (save_fdin);\n\n      dup2 (fdin, FD_STDIN);\n      fd_noinherit (fdin);\n    }\n\n  if (fdout != FD_STDOUT)\n    {\n      save_fdout = dup (FD_STDOUT);\n      if (save_fdout < 0)\n        O (fatal, NILF,\n           _(\"no more file handles: could not duplicate stdout\"));\n      fd_noinherit (save_fdout);\n\n      dup2 (fdout, FD_STDOUT);\n      fd_noinherit (fdout);\n    }\n\n  if (fderr != FD_STDERR)\n    {\n      if (fderr != fdout)\n        {\n          save_fderr = dup (FD_STDERR);\n          if (save_fderr < 0)\n            O (fatal, NILF,\n               _(\"no more file handles: could not duplicate stderr\"));\n          fd_noinherit (save_fderr);\n        }\n\n      dup2 (fderr, FD_STDERR);\n      fd_noinherit (fderr);\n    }\n\n  /* Run the command.  */\n  pid = exec_command (argv, child->environment);\n\n  /* Restore stdout/stdin/stderr of the parent and close temporary FDs.  */\n  if (save_fdin >= 0)\n    {\n      if (dup2 (save_fdin, FD_STDIN) != FD_STDIN)\n        O (fatal, NILF, _(\"could not restore stdin\"));\n      else\n        close (save_fdin);\n    }\n\n  if (save_fdout >= 0)\n    {\n      if (dup2 (save_fdout, FD_STDOUT) != FD_STDOUT)\n        O (fatal, NILF, _(\"could not restore stdout\"));\n      else\n        close (save_fdout);\n    }\n\n  if (save_fderr >= 0)\n    {\n      if (dup2 (save_fderr, FD_STDERR) != FD_STDERR)\n        O (fatal, NILF, _(\"could not restore stderr\"));\n      else\n        close (save_fderr);\n    }\n\n  if (pid < 0)\n    OSS (error, NILF, \"%s: %s\", argv[0], strerror (errno));\n\n  return pid;\n}\n\n#elif !MK_OS_DOS && !MK_OS_VMS\n\n/* POSIX:\n   Create a child process executing the command in ARGV.\n   Returns the PID or -1.  */\npid_t\nchild_execute_job (struct childbase *child, int good_stdin, char **argv)\n{\n  const int fdin = good_stdin ? FD_STDIN : get_bad_stdin ();\n  int fdout = FD_STDOUT;\n  int fderr = FD_STDERR;\n  pid_t pid = -1;\n  int r;\n#if defined(USE_POSIX_SPAWN)\n  char *cmd;\n  posix_spawnattr_t attr;\n  posix_spawn_file_actions_t fa;\n  short flags = 0;\n#endif\n\n  /* Divert child output if we want to capture it.  */\n  if (child->output.syncout)\n    {\n      if (child->output.out >= 0)\n        fdout = child->output.out;\n      if (child->output.err >= 0)\n        fderr = child->output.err;\n    }\n\n#if !defined(USE_POSIX_SPAWN)\n\n  {\n    /* The child may clobber environ so remember ours and restore it.  */\n    char **parent_env = environ;\n    pid = vfork ();\n    if (pid != 0)\n      {\n        environ = parent_env;\n        return pid;\n      }\n  }\n\n  /* We are the child.  */\n  unblock_all_sigs ();\n\n#ifdef SET_STACK_SIZE\n  /* Reset limits, if necessary.  */\n  if (stack_limit.rlim_cur)\n    setrlimit (RLIMIT_STACK, &stack_limit);\n#endif\n\n  /* For any redirected FD, dup2() it to the standard FD.\n     They are all marked close-on-exec already.  */\n  if (fdin >= 0 && fdin != FD_STDIN)\n    EINTRLOOP (r, dup2 (fdin, FD_STDIN));\n  if (fdout != FD_STDOUT)\n    EINTRLOOP (r, dup2 (fdout, FD_STDOUT));\n  if (fderr != FD_STDERR)\n    EINTRLOOP (r, dup2 (fderr, FD_STDERR));\n\n  /* Run the command.  */\n  exec_command (argv, child->environment);\n  _exit (127);\n\n#else /* USE_POSIX_SPAWN */\n\n  if ((r = posix_spawnattr_init (&attr)) != 0)\n    goto done;\n\n  if ((r = posix_spawn_file_actions_init (&fa)) != 0)\n    {\n      posix_spawnattr_destroy (&attr);\n      goto done;\n    }\n\n  /* Unblock all signals.  */\n#ifdef HAVE_POSIX_SPAWNATTR_SETSIGMASK\n  {\n    sigset_t mask;\n    sigemptyset (&mask);\n    r = posix_spawnattr_setsigmask (&attr, &mask);\n    if (r != 0)\n      goto cleanup;\n    flags |= POSIX_SPAWN_SETSIGMASK;\n  }\n#endif /* have posix_spawnattr_setsigmask() */\n\n  /* USEVFORK can give significant speedup on systems where it's available.  */\n#ifdef POSIX_SPAWN_USEVFORK\n  flags |= POSIX_SPAWN_USEVFORK;\n#endif\n\n  /* For any redirected FD, dup2() it to the standard FD.\n     They are all marked close-on-exec already.  */\n  if (fdin >= 0 && fdin != FD_STDIN)\n    if ((r = posix_spawn_file_actions_adddup2 (&fa, fdin, FD_STDIN)) != 0)\n      goto cleanup;\n  if (fdout != FD_STDOUT)\n    if ((r = posix_spawn_file_actions_adddup2 (&fa, fdout, FD_STDOUT)) != 0)\n      goto cleanup;\n  if (fderr != FD_STDERR)\n    if ((r = posix_spawn_file_actions_adddup2 (&fa, fderr, FD_STDERR)) != 0)\n      goto cleanup;\n\n  /* We can't use the POSIX_SPAWN_RESETIDS flag: when make is invoked under\n     restrictive environments like unshare it will fail with EINVAL.  */\n\n  /* Apply the spawn flags.  */\n  if ((r = posix_spawnattr_setflags (&attr, flags)) != 0)\n    goto cleanup;\n\n  /* Look up the program on the child's PATH, if needed.  */\n  {\n    const char *p = NULL;\n    char **pp;\n\n    for (pp = child->environment; *pp != NULL; ++pp)\n      if ((*pp)[0] == 'P' && (*pp)[1] == 'A' && (*pp)[2] == 'T'\n          && (*pp)[3] == 'H' &&(*pp)[4] == '=')\n        {\n          p = (*pp) + 5;\n          break;\n        }\n\n    /* execvp() will use a default PATH if none is set; emulate that.  */\n    if (p == NULL)\n      {\n        size_t l = confstr (_CS_PATH, NULL, 0);\n        if (l)\n          {\n            char *dp = alloca (l);\n            confstr (_CS_PATH, dp, l);\n            p = dp;\n          }\n      }\n\n    cmd = (char *)find_in_given_path (argv[0], p, NULL, 0);\n  }\n\n  if (!cmd)\n    {\n      r = errno;\n      goto cleanup;\n    }\n\n  /* Start the program.  */\n  while ((r = posix_spawn (&pid, cmd, &fa, &attr, argv,\n                           child->environment)) == EINTR)\n    ;\n\n  /* posix_spawn() doesn't provide sh fallback like exec() does; implement\n     it here.  POSIX doesn't specify the path to sh so use the default.  */\n\n  if (r == ENOEXEC)\n    {\n      char **nargv;\n      char **pp;\n      size_t l = 0;\n\n      for (pp = argv; *pp != NULL; ++pp)\n        ++l;\n\n      nargv = xmalloc (sizeof (char *) * (l + 3));\n      nargv[0] = (char *)default_shell;\n      nargv[1] = cmd;\n      memcpy (&nargv[2], &argv[1], sizeof (char *) * l);\n\n      while ((r = posix_spawn (&pid, nargv[0], &fa, &attr, nargv,\n                               child->environment)) == EINTR)\n        ;\n\n      free (nargv);\n    }\n\n  if (r == 0)\n    {\n      /* Spawn succeeded but may fail later: remember the command.  */\n      free (child->cmd_name);\n      if (cmd != argv[0])\n        child->cmd_name = cmd;\n      else\n        child->cmd_name = xstrdup(cmd);\n    }\n\n cleanup:\n  posix_spawn_file_actions_destroy (&fa);\n  posix_spawnattr_destroy (&attr);\n\n done:\n  if (r != 0)\n    pid = -1;\n\n#endif /* USE_POSIX_SPAWN */\n\n  if (pid < 0)\n    OSS (error, NILF, \"%s: %s\", argv[0], strerror (r));\n\n  return pid;\n}\n#endif /* !MK_OS_DOS && !MK_OS_VMS */\n#endif /* !MK_OS_W32 */\n\f\n/* Replace the current process with one running the command in ARGV,\n   with environment ENVP.  This function does not return.  */\n\npid_t\nexec_command (char **argv, char **envp)\n{\n#if MK_OS_VMS\n  /* to work around a problem with signals and execve: ignore them */\n#ifdef SIGCHLD\n  signal (SIGCHLD,SIG_IGN);\n#endif\n  /* Run the program.  */\n  execve (argv[0], argv, envp);\n  OSS (error, NILF, \"%s: %s\", argv[0], strerror (errno));\n  _exit (EXIT_FAILURE);\n#else\n#if MK_OS_W32\n  HANDLE hPID;\n  HANDLE hWaitPID;\n  int exit_code = EXIT_FAILURE;\n\n  /* make sure CreateProcess() has Path it needs */\n  sync_Path_environment ();\n\n  /* launch command */\n  hPID = process_easy (argv, envp, -1, -1);\n\n  /* make sure launch ok */\n  if (hPID == INVALID_HANDLE_VALUE)\n    {\n      int i;\n      fprintf (stderr, _(\"process_easy() failed to launch process (e=%ld)\\n\"),\n               process_last_err (hPID));\n      for (i = 0; argv[i]; i++)\n          fprintf (stderr, \"%s \", argv[i]);\n      fprintf (stderr, _(\"\\nCounted %d args in failed launch\\n\"), i);\n      exit (EXIT_FAILURE);\n    }\n\n  /* wait and reap last child */\n  hWaitPID = process_wait_for_any (1, 0);\n  while (hWaitPID)\n    {\n      /* was an error found on this process? */\n      int err = process_last_err (hWaitPID);\n\n      /* get exit data */\n      exit_code = process_exit_code (hWaitPID);\n\n      if (err)\n          fprintf (stderr, \"make (e=%d, rc=%d): %s\\n\",\n                   err, exit_code, map_windows32_error_to_string (err));\n\n      /* cleanup process */\n      process_cleanup (hWaitPID);\n\n      /* expect to find only last pid, warn about other pids reaped */\n      if (hWaitPID == hPID)\n          break;\n      else\n        {\n          char *pidstr = xstrdup (pid2str ((pid_t)hWaitPID));\n\n          fprintf (stderr,\n                   _(\"make reaped child pid %s, still waiting for pid %s\\n\"),\n                   pidstr, pid2str ((pid_t)hPID));\n          free (pidstr);\n        }\n    }\n\n  /* Use the child's exit code as our exit code */\n  exit (exit_code);\n\n#else  /* !MK_OS_W32 */\n\n  pid_t pid = -1;\n\n# if MK_OS_OS2\n  /* Run the program.  */\n  pid = spawnvpe (P_NOWAIT, argv[0], argv, envp);\n  if (pid >= 0)\n    return pid;\n\n  /* the file might have a strange shell extension */\n  if (errno == ENOENT)\n    errno = ENOEXEC;\n\n# elif MK_OS_ZOS\n  /* In z/OS we can't set environ in ASCII mode. */\n  environ = envp;\n  execvpe(argv[0], argv, envp);\n\n# else\n\n  /* Run the program.  Don't use execvpe() as we want the search for argv[0]\n     to use the new PATH, but execvpe() searches before resetting PATH.  */\n  environ = envp;\n  execvp (argv[0], argv);\n\n# endif /* !MK_OS_OS2 */\n\n  switch (errno)\n    {\n    case ENOENT:\n      OSS (error, NILF, \"%s: %s\", argv[0], strerror (errno));\n      break;\n    case ENOEXEC:\n      {\n        /* The file was not a program.  Try it as a shell script.  */\n        const char *shell;\n        char **new_argv;\n        int argc;\n        int i=1;\n\n# if MK_OS_OS2\n        /* Do not use $SHELL from the environment */\n        struct variable *p = lookup_variable (\"SHELL\", 5);\n        if (p)\n          shell = p->value;\n        else\n          shell = 0;\n# else\n        shell = getenv (\"SHELL\");\n# endif\n        if (shell == 0)\n          shell = default_shell;\n\n        argc = 1;\n        while (argv[argc] != 0)\n          ++argc;\n\n# if MK_OS_OS2\n        if (!unixy_shell)\n          ++argc;\n# endif\n\n        new_argv = alloca ((1 + argc + 1) * sizeof (char *));\n        new_argv[0] = (char *)shell;\n\n# if MK_OS_OS2\n        if (!unixy_shell)\n          {\n            new_argv[1] = (char *)\"/c\";\n            ++i;\n            --argc;\n          }\n# endif\n\n        new_argv[i] = argv[0];\n        while (argc > 0)\n          {\n            new_argv[i + argc] = argv[argc];\n            --argc;\n          }\n\n# if MK_OS_OS2\n        pid = spawnvpe (P_NOWAIT, shell, new_argv, envp);\n        if (pid >= 0)\n          break;\n# elif MK_OS_ZOS\n        /* In z/OS we can't set environ in ASCII mode. */\n        execvpe(shell, new_argv, envp);\n# else\n        execvp (shell, new_argv);\n# endif\n        OSS (error, NILF, \"%s: %s\", new_argv[0], strerror (errno));\n        break;\n      }\n\n# if MK_OS_OS2\n    case EINVAL:\n      /* this nasty error was driving me nuts :-( */\n      O (error, NILF, _(\"spawnvpe: environment space might be exhausted\"));\n      /* FALLTHROUGH */\n# endif\n\n    default:\n      OSS (error, NILF, \"%s: %s\", argv[0], strerror (errno));\n      break;\n    }\n\n  return pid;\n#endif /* !MK_OS_W32 */\n#endif /* !MK_OS_VMS */\n}\n\f\n#if !MK_OS_VMS\n/* Figure out the argument list necessary to run LINE as a command.  Try to\n   avoid using a shell.  This routine handles only ' quoting, and \" quoting\n   when no backslash, $ or ' characters are seen in the quotes.  Starting\n   quotes may be escaped with a backslash.  If any of the characters in\n   sh_chars is seen, or any of the builtin commands listed in sh_cmds is the\n   first word of a line, the shell is used.\n\n   If RESTP is not NULL, *RESTP is set to point to the first newline in LINE.\n   If *RESTP is NULL, newlines will be ignored.\n\n   SHELL is the shell to use, or nil to use the default shell.\n   IFS is the value of $IFS, or nil (meaning the default).\n\n   FLAGS is the value of lines_flags for this command line.  It is used in the\n   Windows32 port to check whether + or $(MAKE) were found in this command\n   line, in which case the effect of just_print_flag is overridden.\n\n   The returned value is either NULL if the line was empty, or else a pointer\n   to an array of strings.  The fist pointer points to the memory used by all\n   the strings, so to free you free the 0'th element then the returned pointer\n   (see the FREE_ARGV macro).  */\n\nstatic char **\nconstruct_command_argv_internal (char *line, char **restp, const char *shell,\n                                 const char *shellflags, const char *ifs,\n                                 int flags, char **batch_filename UNUSED)\n{\n#if MK_OS_DOS\n  /* MSDOS supports both the stock DOS shell and ports of Unixy shells.\n     We call 'system' for anything that requires ''slow'' processing,\n     because DOS shells are too dumb.  When $SHELL points to a real\n     (unix-style) shell, 'system' just calls it to do everything.  When\n     $SHELL points to a DOS shell, 'system' does most of the work\n     internally, calling the shell only for its internal commands.\n     However, it looks on the $PATH first, so you can e.g. have an\n     external command named 'mkdir'.\n\n     Since we call 'system', certain characters and commands below are\n     actually not specific to COMMAND.COM, but to the DJGPP implementation\n     of 'system'.  In particular:\n\n       The shell wildcard characters are in DOS_CHARS because they will\n       not be expanded if we call the child via 'spawnXX'.\n\n       The ';' is in DOS_CHARS, because our 'system' knows how to run\n       multiple commands on a single line.\n\n       DOS_CHARS also include characters special to 4DOS/NDOS, so we\n       won't have to tell one from another and have one more set of\n       commands and special characters.  */\n  static const char *sh_chars_dos = \"*?[];|<>%^&()\";\n  static const char *sh_cmds_dos[] =\n    { \"break\", \"call\", \"cd\", \"chcp\", \"chdir\", \"cls\", \"copy\", \"ctty\", \"date\",\n      \"del\", \"dir\", \"echo\", \"erase\", \"exit\", \"for\", \"goto\", \"if\", \"md\",\n      \"mkdir\", \"path\", \"pause\", \"prompt\", \"rd\", \"rmdir\", \"rem\", \"ren\",\n      \"rename\", \"set\", \"shift\", \"time\", \"type\", \"ver\", \"verify\", \"vol\", \":\",\n      0 };\n\n  static const char *sh_chars_sh = \"#;\\\"*?[]&|<>(){}$`^\";\n  static const char *sh_cmds_sh[] =\n    { \"cd\", \"echo\", \"eval\", \"exec\", \"exit\", \"login\", \"logout\", \"set\", \"umask\",\n      \"wait\", \"while\", \"for\", \"case\", \"if\", \":\", \".\", \"break\", \"continue\",\n      \"export\", \"read\", \"readonly\", \"shift\", \"times\", \"trap\", \"switch\",\n      \"unset\", \"ulimit\", \"command\", 0 };\n\n  const char *sh_chars;\n  const char **sh_cmds;\n\n#elif MK_OS_OS2\n  static const char *sh_chars_dos = \"*?[];|<>%^&()\";\n  static const char *sh_cmds_dos[] =\n    { \"break\", \"call\", \"cd\", \"chcp\", \"chdir\", \"cls\", \"copy\", \"ctty\", \"date\",\n      \"del\", \"dir\", \"echo\", \"erase\", \"exit\", \"for\", \"goto\", \"if\", \"md\",\n      \"mkdir\", \"path\", \"pause\", \"prompt\", \"rd\", \"rmdir\", \"rem\", \"ren\",\n      \"rename\", \"set\", \"shift\", \"time\", \"type\", \"ver\", \"verify\", \"vol\", \":\",\n      0 };\n\n  static const char *sh_chars_os2 = \"*?[];|<>%^()\\\"'&\";\n  static const char *sh_cmds_os2[] =\n    { \"call\", \"cd\", \"chcp\", \"chdir\", \"cls\", \"copy\", \"date\", \"del\", \"detach\",\n      \"dir\", \"echo\", \"endlocal\", \"erase\", \"exit\", \"for\", \"goto\", \"if\", \"keys\",\n      \"md\", \"mkdir\", \"move\", \"path\", \"pause\", \"prompt\", \"rd\", \"rem\", \"ren\",\n      \"rename\", \"rmdir\", \"set\", \"setlocal\", \"shift\", \"start\", \"time\", \"type\",\n      \"ver\", \"verify\", \"vol\", \":\", 0 };\n\n  static const char *sh_chars_sh = \"#;\\\"*?[]&|<>(){}$`^~'\";\n  static const char *sh_cmds_sh[] =\n    { \"echo\", \"cd\", \"eval\", \"exec\", \"exit\", \"login\", \"logout\", \"set\", \"umask\",\n      \"wait\", \"while\", \"for\", \"case\", \"if\", \":\", \".\", \"break\", \"continue\",\n      \"export\", \"read\", \"readonly\", \"shift\", \"times\", \"trap\", \"switch\",\n      \"unset\", \"command\", 0 };\n\n  const char *sh_chars;\n  const char **sh_cmds;\n\n#elif MK_OS_W32\n  /* We used to have a double quote (\") in sh_chars_dos[] below, but\n     that caused any command line with quoted file names be run\n     through a temporary batch file, which introduces command-line\n     limit of 4K characters imposed by cmd.exe.  Since CreateProcess\n     can handle quoted file names just fine, removing the quote lifts\n     the limit from a very frequent use case, because using quoted\n     file names is commonplace on MS-Windows.  */\n  static const char *sh_chars_dos = \"|&<>\";\n  static const char *sh_cmds_dos[] =\n    { \"assoc\", \"break\", \"call\", \"cd\", \"chcp\", \"chdir\", \"cls\", \"color\", \"copy\",\n      \"ctty\", \"date\", \"del\", \"dir\", \"echo\", \"echo.\", \"endlocal\", \"erase\",\n      \"exit\", \"for\", \"ftype\", \"goto\", \"if\", \"if\", \"md\", \"mkdir\", \"move\",\n      \"path\", \"pause\", \"prompt\", \"rd\", \"rem\", \"ren\", \"rename\", \"rmdir\",\n      \"set\", \"setlocal\", \"shift\", \"time\", \"title\", \"type\", \"ver\", \"verify\",\n      \"vol\", \":\", 0 };\n\n  static const char *sh_chars_sh = \"#;\\\"*?[]&|<>(){}$`^\";\n  static const char *sh_cmds_sh[] =\n    { \"cd\", \"eval\", \"exec\", \"exit\", \"login\", \"logout\", \"set\", \"umask\", \"wait\",\n      \"while\", \"for\", \"case\", \"if\", \":\", \".\", \"break\", \"continue\", \"export\",\n      \"read\", \"readonly\", \"shift\", \"times\", \"trap\", \"switch\", \"test\", \"command\",\n#ifdef BATCH_MODE_ONLY_SHELL\n      \"echo\",\n#endif\n      0 };\n\n  const char *sh_chars;\n  const char **sh_cmds;\n#elif defined(__riscos__)\n  static const char *sh_chars = \"\";\n  static const char *sh_cmds[] = { 0 };\n#else  /* must be UNIX-ish */\n  static const char *sh_chars = \"#;\\\"*?[]&|<>(){}$`^~!\";\n  static const char *sh_cmds[] =\n    { \".\", \":\", \"alias\", \"bg\", \"break\", \"case\", \"cd\", \"command\", \"continue\",\n      \"eval\", \"exec\", \"exit\", \"export\", \"fc\", \"fg\", \"for\", \"getopts\", \"hash\",\n      \"if\", \"jobs\", \"login\", \"logout\", \"read\", \"readonly\", \"return\", \"set\",\n      \"shift\", \"test\", \"times\", \"trap\", \"type\", \"ulimit\", \"umask\", \"unalias\",\n      \"unset\", \"wait\", \"while\", 0 };\n\n# ifdef HAVE_DOS_PATHS\n  /* This is required if the MSYS/Cygwin ports (which do not define\n     MK_OS_W32) are compiled with HAVE_DOS_PATHS defined, which uses\n     sh_chars_sh directly (see below).  The value must be identical\n     to that of sh_chars immediately above.  */\n  static const char *sh_chars_sh =  \"#;\\\"*?[]&|<>(){}$`^~!\";\n# endif  /* HAVE_DOS_PATHS */\n#endif\n  size_t i;\n  char *p;\n#ifndef NDEBUG\n  char *end;\n#endif\n  char *ap;\n  const char *cap;\n  const char *cp;\n  int instring, word_has_equals, seen_nonequals, last_argument_was_empty;\n  char **new_argv = 0;\n  char *argstr = 0;\n#if MK_OS_W32\n  int slow_flag = 0;\n\n  if (!unixy_shell)\n    {\n      sh_cmds = sh_cmds_dos;\n      sh_chars = sh_chars_dos;\n    }\n  else\n    {\n      sh_cmds = sh_cmds_sh;\n      sh_chars = sh_chars_sh;\n    }\n#endif /* MK_OS_W32 */\n\n  if (restp != NULL)\n    *restp = NULL;\n\n  /* Make sure not to bother processing an empty line but stop at newline.  */\n  while (ISBLANK (*line))\n    ++line;\n  if (*line == '\\0')\n    return 0;\n\n  /* See if it is safe to parse commands internally.  */\n  if (shell == 0)\n    shell = default_shell;\n#if MK_OS_W32\n  else if (strcmp (shell, default_shell))\n  {\n    char *s1 = _fullpath (NULL, shell, 0);\n    char *s2 = _fullpath (NULL, default_shell, 0);\n\n    slow_flag = strcmp ((s1 ? s1 : \"\"), (s2 ? s2 : \"\"));\n\n    free (s1);\n    free (s2);\n  }\n  if (slow_flag)\n    goto slow;\n#else  /* not MK_OS_W32 */\n#if MK_OS_DOS || MK_OS_OS2\n  else if (strcasecmp (shell, default_shell))\n    {\n      extern int _is_unixy_shell (const char *_path);\n\n      DB (DB_BASIC, (_(\"$SHELL changed (was '%s', now '%s')\\n\"),\n                     default_shell, shell));\n      unixy_shell = _is_unixy_shell (shell);\n      /* we must allocate a copy of shell: construct_command_argv() will free\n       * shell after this function returns.  */\n      default_shell = xstrdup (shell);\n    }\n  if (unixy_shell)\n    {\n      sh_chars = sh_chars_sh;\n      sh_cmds  = sh_cmds_sh;\n    }\n  else\n    {\n      sh_chars = sh_chars_dos;\n      sh_cmds  = sh_cmds_dos;\n# if MK_OS_OS2\n      if (_osmode == OS2_MODE)\n        {\n          sh_chars = sh_chars_os2;\n          sh_cmds = sh_cmds_os2;\n        }\n# endif\n    }\n#else  /* !MK_OS_DOS */\n  else if (strcmp (shell, default_shell))\n    goto slow;\n#endif /* !MK_OS_DOS && !MK_OS_OS2 */\n#endif /* not MK_OS_W32 */\n\n  if (ifs)\n    for (cap = ifs; *cap != '\\0'; ++cap)\n      if (*cap != ' ' && *cap != '\\t' && *cap != '\\n')\n        goto slow;\n\n  if (shellflags)\n    if (shellflags[0] != '-'\n        || ((shellflags[1] != 'c' || shellflags[2] != '\\0')\n            && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\\0')))\n      goto slow;\n\n  i = strlen (line) + 1;\n\n  /* More than 1 arg per character is impossible.  */\n  new_argv = xmalloc (i * sizeof (char *));\n\n  /* All the args can fit in a buffer as big as LINE is.   */\n  ap = new_argv[0] = argstr = xmalloc (i);\n#ifndef NDEBUG\n  end = ap + i;\n#endif\n\n  /* I is how many complete arguments have been found.  */\n  i = 0;\n  instring = word_has_equals = seen_nonequals = last_argument_was_empty = 0;\n  for (p = line; *p != '\\0'; ++p)\n    {\n      assert (ap <= end);\n\n      if (instring)\n        {\n          /* Inside a string, just copy any char except a closing quote\n             or a backslash-newline combination.  */\n          if (*p == instring)\n            {\n              instring = 0;\n              if (ap == new_argv[0] || *(ap-1) == '\\0')\n                last_argument_was_empty = 1;\n            }\n          else if (*p == '\\\\' && p[1] == '\\n')\n            {\n              /* Backslash-newline is handled differently depending on what\n                 kind of string we're in: inside single-quoted strings you\n                 keep them; in double-quoted strings they disappear.  For\n                 DOS/Windows/OS2, if we don't have a POSIX shell, we keep the\n                 pre-POSIX behavior of removing the backslash-newline.  */\n              if (instring == '\"'\n#if MK_OS_DOS || MK_OS_OS2 || MK_OS_W32\n                  || !unixy_shell\n#endif\n                  )\n                ++p;\n              else\n                {\n                  *(ap++) = *(p++);\n                  *(ap++) = *p;\n                }\n            }\n          else if (*p == '\\n' && restp != NULL)\n            {\n              /* End of the command line.  */\n              *restp = p;\n              goto end_of_line;\n            }\n          /* Backslash, $, and ` are special inside double quotes.\n             If we see any of those, punt.\n             But on MSDOS, if we use COMMAND.COM, double and single\n             quotes have the same effect.  */\n          else if (instring == '\"' && strchr (\"\\\\$`\", *p) != 0 && unixy_shell)\n            goto slow;\n#if MK_OS_W32\n          /* Quoted wildcard characters must be passed quoted to the\n             command, so give up the fast route.  */\n          else if (instring == '\"' && strchr (\"*?\", *p) != 0 && !unixy_shell)\n            goto slow;\n          else if (instring == '\"' && strncmp (p, \"\\\\\\\"\", 2) == 0)\n            *ap++ = *++p;\n#endif\n          else\n            *ap++ = *p;\n        }\n      else if (strchr (sh_chars, *p) != 0)\n        /* Not inside a string, but it's a special char.  */\n        goto slow;\n      else if (one_shell && *p == '\\n')\n        /* In .ONESHELL mode \\n is a separator like ; or && */\n        goto slow;\n#if MK_OS_DOS\n      else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.')\n        /* '...' is a wildcard in DJGPP.  */\n        goto slow;\n#endif\n      else\n        /* Not a special char.  */\n        switch (*p)\n          {\n          case '=':\n            /* Equals is a special character in leading words before the\n               first word with no equals sign in it.  This is not the case\n               with sh -k, but we never get here when using nonstandard\n               shell flags.  */\n            if (! seen_nonequals && unixy_shell)\n              goto slow;\n            word_has_equals = 1;\n            *ap++ = '=';\n            break;\n\n          case '\\\\':\n            /* Backslash-newline has special case handling, ref POSIX.\n               We're in the fastpath, so emulate what the shell would do.  */\n            if (p[1] == '\\n')\n              {\n                /* Throw out the backslash and newline.  */\n                ++p;\n\n                /* At the beginning of the argument, skip any whitespace other\n                   than newline before the start of the next word.  */\n                if (ap == new_argv[i])\n                  while (ISBLANK (p[1]))\n                    ++p;\n              }\n#if MK_OS_W32\n            /* Backslash before whitespace is not special if our shell\n               is not Unixy.  */\n            else if (ISSPACE (p[1]) && !unixy_shell)\n              {\n                *ap++ = *p;\n                break;\n              }\n#endif\n            else if (p[1] != '\\0')\n              {\n#ifdef HAVE_DOS_PATHS\n                /* Only remove backslashes before characters special to Unixy\n                   shells.  All other backslashes are copied verbatim, since\n                   they are probably DOS-style directory separators.  This\n                   still leaves a small window for problems, but at least it\n                   should work for the vast majority of naive users.  */\n\n#if MK_OS_DOS\n                /* A dot is only special as part of the \"...\"\n                   wildcard.  */\n                if (strneq (p + 1, \".\\\\.\\\\.\", 5))\n                  {\n                    *ap++ = '.';\n                    *ap++ = '.';\n                    p += 4;\n                  }\n                else\n#endif\n                  if (p[1] != '\\\\' && p[1] != '\\'' && !ISSPACE (p[1])\n                      && strchr (sh_chars_sh, p[1]) == 0)\n                    /* back up one notch, to copy the backslash */\n                    --p;\n#endif  /* HAVE_DOS_PATHS */\n\n                /* Copy and skip the following char.  */\n                *ap++ = *++p;\n              }\n            break;\n\n          case '\\'':\n          case '\"':\n            instring = *p;\n            break;\n\n          case '\\n':\n            if (restp != NULL)\n              {\n                /* End of the command line.  */\n                *restp = p;\n                goto end_of_line;\n              }\n            else\n              /* Newlines are not special.  */\n              *ap++ = '\\n';\n            break;\n\n          case ' ':\n          case '\\t':\n            /* We have the end of an argument.\n               Terminate the text of the argument.  */\n            *ap++ = '\\0';\n            new_argv[++i] = ap;\n            last_argument_was_empty = 0;\n\n            /* Update SEEN_NONEQUALS, which tells us if every word\n               heretofore has contained an '='.  */\n            seen_nonequals |= ! word_has_equals;\n            if (word_has_equals && ! seen_nonequals)\n              /* An '=' in a word before the first\n                 word without one is magical.  */\n              goto slow;\n            word_has_equals = 0; /* Prepare for the next word.  */\n\n            /* If this argument is the command name,\n               see if it is a built-in shell command.\n               If so, have the shell handle it.  */\n            if (i == 1)\n              {\n                int j;\n                for (j = 0; sh_cmds[j] != 0; ++j)\n                  {\n                    if (streq (sh_cmds[j], new_argv[0]))\n                      goto slow;\n#if MK_OS_OS2 || MK_OS_W32\n                    /* Non-Unix shells are case insensitive.  */\n                    if (!unixy_shell\n                        && strcasecmp (sh_cmds[j], new_argv[0]) == 0)\n                      goto slow;\n#endif\n                  }\n              }\n\n            /* Skip whitespace chars, but not newlines.  */\n            while (ISBLANK (p[1]))\n              ++p;\n            break;\n\n          default:\n            *ap++ = *p;\n            break;\n          }\n    }\n end_of_line:\n\n  if (instring)\n    /* Let the shell deal with an unterminated quote.  */\n    goto slow;\n\n  /* Terminate the last argument and the argument list.  */\n\n  *ap = '\\0';\n  if (new_argv[i][0] != '\\0' || last_argument_was_empty)\n    ++i;\n  new_argv[i] = 0;\n\n  if (i == 1)\n    {\n      int j;\n      for (j = 0; sh_cmds[j] != 0; ++j)\n        if (streq (sh_cmds[j], new_argv[0]))\n          goto slow;\n    }\n\n  if (new_argv[0] == 0)\n    {\n      /* Line was empty.  */\n      free (argstr);\n      free (new_argv);\n      return 0;\n    }\n\n  return new_argv;\n\n slow:;\n  /* We must use the shell.  */\n\n  if (new_argv != 0)\n    {\n      /* Free the old argument list we were working on.  */\n      free (argstr);\n      free (new_argv);\n    }\n\n#if MK_OS_DOS\n  execute_by_shell = 1; /* actually, call 'system' if shell isn't unixy */\n#endif\n\n#if MK_OS_W32\n  /*\n   * Not eating this whitespace caused things like\n   *\n   *    sh -c \"\\n\"\n   *\n   * which gave the shell fits. I think we have to eat\n   * whitespace here, but this code should be considered\n   * suspicious if things start failing....\n   */\n\n  /* Make sure not to bother processing an empty line.  */\n  NEXT_TOKEN (line);\n  if (*line == '\\0')\n    return 0;\n#endif /* MK_OS_W32 */\n\n  {\n    /* SHELL may be a multi-word command.  Construct a command line\n       \"$(SHELL) $(.SHELLFLAGS) LINE\", with all special chars in LINE escaped.\n       Then recurse, expanding this command line to get the final\n       argument list.  */\n\n    char *new_line;\n    size_t shell_len = strlen (shell);\n    size_t line_len = strlen (line);\n    size_t sflags_len = shellflags ? strlen (shellflags) : 0;\n#if MK_OS_W32\n    char *command_ptr = NULL; /* used for batch_mode_shell mode */\n#endif\n\n# if MK_OS_OS2 /* is this necessary? */\n    if (!unixy_shell && shellflags)\n      {\n        size_t len = strlen (shellflags);\n        char *shflags = alloca (len + 1);\n        memcpy (shflags, shellflags, len + 1);\n        shflags[0] = '/'; /* \"/c\" */\n        shellflags = shflags;\n      }\n# endif\n\n    /* In .ONESHELL mode we are allowed to throw the entire current\n        recipe string at a single shell and trust that the user\n        has configured the shell and shell flags, and formatted\n        the string, appropriately. */\n    if (one_shell)\n      {\n        /* If the shell is Bourne compatible, we must remove and ignore\n           interior special chars [@+-] because they're meaningless to\n           the shell itself. If, however, we're in .ONESHELL mode and\n           have changed SHELL to something non-standard, we should\n           leave those alone because they could be part of the\n           script. In this case we must also leave in place\n           any leading [@+-] for the same reason.  */\n\n        /* Remove and ignore interior prefix chars [@+-] because they're\n             meaningless given a single shell. */\n#if MK_OS_DOS || MK_OS_OS2\n        if (unixy_shell)     /* the test is complicated and we already did it */\n#else\n        if (is_bourne_compatible_shell (shell)\n#if MK_OS_W32\n            /* If we didn't find any sh.exe, don't behave is if we did!  */\n            && !no_default_sh_exe\n#endif\n            )\n#endif\n          {\n            const char *f = line;\n            char *t = line;\n\n            /* Copy the recipe, removing and ignoring interior prefix chars\n               [@+-]: they're meaningless in .ONESHELL mode.  */\n            while (f[0] != '\\0')\n              {\n                int esc = 0;\n\n                /* This is the start of a new recipe line.  Skip whitespace\n                   and prefix characters but not newlines.  */\n                while (ISBLANK (*f) || *f == '-' || *f == '@' || *f == '+')\n                  ++f;\n\n                /* Copy until we get to the next logical recipe line.  */\n                while (*f != '\\0')\n                  {\n                    *(t++) = *(f++);\n                    if (f[-1] == '\\\\')\n                      esc = !esc;\n                    else\n                      {\n                        /* On unescaped newline, we're done with this line.  */\n                        if (f[-1] == '\\n' && ! esc)\n                          break;\n\n                        /* Something else: reset the escape sequence.  */\n                        esc = 0;\n                      }\n                  }\n              }\n            *t = '\\0';\n          }\n#if MK_OS_W32\n        else    /* non-Posix shell (cmd.exe etc.) */\n          {\n            const char *f = line;\n            char *t = line;\n            char *tstart = t;\n            int temp_fd;\n            FILE* batch = NULL;\n            int id = GetCurrentProcessId ();\n            PATH_VAR(fbuf);\n\n            /* Generate a file name for the temporary batch file.  */\n            sprintf (fbuf, \"make%d\", id);\n            *batch_filename = create_batch_file (fbuf, 0, &temp_fd);\n            DB (DB_JOBS, (_(\"Creating temporary batch file %s\\n\"),\n                          *batch_filename));\n\n            /* Create a FILE object for the batch file, and write to it the\n               commands to be executed.  Put the batch file in TEXT mode.  */\n            _setmode (temp_fd, _O_TEXT);\n            batch = _fdopen (temp_fd, \"wt\");\n            fputs (\"@echo off\\n\", batch);\n            DB (DB_JOBS, (_(\"Batch file contents:\\n\\t@echo off\\n\")));\n\n            /* Copy the recipe, removing and ignoring interior prefix chars\n               [@+-]: they're meaningless in .ONESHELL mode.  */\n            while (*f != '\\0')\n              {\n                /* This is the start of a new recipe line.  Skip whitespace\n                   and prefix characters but not newlines.  */\n                while (ISBLANK (*f) || *f == '-' || *f == '@' || *f == '+')\n                  ++f;\n\n                /* Copy until we get to the next logical recipe line.  */\n                while (*f != '\\0')\n                  {\n                    /* Remove the escaped newlines in the command, and the\n                       blanks that follow them.  Windows shells cannot handle\n                       escaped newlines.  */\n                    if (*f == '\\\\' && f[1] == '\\n')\n                      {\n                        f += 2;\n                        while (ISBLANK (*f))\n                          ++f;\n                      }\n                    *(t++) = *(f++);\n                    /* On an unescaped newline, we're done with this\n                       line.  */\n                    if (f[-1] == '\\n')\n                      break;\n                  }\n                /* Write another line into the batch file.  */\n                if (t > tstart)\n                  {\n                    char c = *t;\n                    *t = '\\0';\n                    fputs (tstart, batch);\n                    DB (DB_JOBS, (\"\\t%s\", tstart));\n                    tstart = t;\n                    *t = c;\n                  }\n              }\n            DB (DB_JOBS, (\"\\n\"));\n            fclose (batch);\n\n            /* Create an argv list for the shell command line that\n               will run the batch file.  */\n            new_argv = xmalloc (2 * sizeof (char *));\n            new_argv[0] = xstrdup (*batch_filename);\n            new_argv[1] = NULL;\n            return new_argv;\n          }\n#endif /* MK_OS_W32 */\n        /* Create an argv list for the shell command line.  */\n        {\n          int n = 1;\n          char *nextp;\n\n          new_argv = xmalloc ((4 + sflags_len/2) * sizeof (char *));\n\n          nextp = new_argv[0] = xmalloc (shell_len + sflags_len + line_len + 3);\n          nextp = mempcpy (nextp, shell, shell_len + 1);\n\n          /* Chop up the shellflags (if any) and assign them.  */\n          if (! shellflags)\n            {\n              new_argv[n++] = nextp;\n              *(nextp++) = '\\0';\n            }\n          else\n            {\n              /* Parse shellflags using construct_command_argv_internal to\n                 handle quotes. */\n              char **argv;\n              char *f = alloca (sflags_len + 1);\n              memcpy (f, shellflags, sflags_len + 1);\n              argv = construct_command_argv_internal (f, 0, 0, 0, 0, flags, 0);\n              if (argv)\n                {\n                  char **a;\n                  for (a = argv; *a; ++a)\n                    {\n                      new_argv[n++] = nextp;\n                      nextp = stpcpy (nextp, *a) + 1;\n                    }\n                  free (argv[0]);\n                  free (argv);\n                }\n            }\n\n          /* Set the command to invoke.  */\n          new_argv[n++] = nextp;\n          memcpy(nextp, line, line_len + 1);\n          new_argv[n++] = NULL;\n        }\n        return new_argv;\n      }\n\n    new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1\n                        + (line_len*2) + 1);\n    ap = new_line;\n    /* Copy SHELL, escaping any characters special to the shell.  If\n       we don't escape them, construct_command_argv_internal will\n       recursively call itself ad nauseam, or until stack overflow,\n       whichever happens first.  */\n    for (cp = shell; *cp != '\\0'; ++cp)\n      {\n        if (strchr (sh_chars, *cp) != 0)\n          *(ap++) = '\\\\';\n        *(ap++) = *cp;\n      }\n    *(ap++) = ' ';\n    if (shellflags)\n      {\n        ap = mempcpy (ap, shellflags, sflags_len);\n        *(ap++) = ' ';\n      }\n#if MK_OS_W32\n    command_ptr = ap;\n#endif\n    for (p = line; *p != '\\0'; ++p)\n      {\n        if (restp != NULL && *p == '\\n')\n          {\n            *restp = p;\n            break;\n          }\n        else if (*p == '\\\\' && p[1] == '\\n')\n          {\n            /* POSIX says we keep the backslash-newline.  If we don't have a\n               POSIX shell on DOS/Windows/OS2, mimic the pre-POSIX behavior\n               and remove the backslash/newline.  */\n#if MK_OS_DOS || MK_OS_OS2 || MK_OS_W32\n# define PRESERVE_BSNL  unixy_shell\n#else\n# define PRESERVE_BSNL  1\n#endif\n            if (PRESERVE_BSNL)\n              {\n                *(ap++) = '\\\\';\n                /* Only non-batch execution needs another backslash,\n                   because it will be passed through a recursive\n                   invocation of this function.  */\n                if (!batch_mode_shell)\n                  *(ap++) = '\\\\';\n                *(ap++) = '\\n';\n              }\n            ++p;\n            continue;\n          }\n\n        /* DOS shells don't know about backslash-escaping.  */\n        if (unixy_shell && !batch_mode_shell &&\n            (*p == '\\\\' || *p == '\\'' || *p == '\"'\n             || ISSPACE (*p)\n             || strchr (sh_chars, *p) != 0))\n          *ap++ = '\\\\';\n#if MK_OS_DOS\n        else if (unixy_shell && strneq (p, \"...\", 3))\n          {\n            /* The case of '...' wildcard again.  */\n            ap = stpcpy (ap, \"\\\\.\\\\.\\\\\");\n            p  += 2;\n          }\n#endif\n        *ap++ = *p;\n      }\n    if (ap == new_line + shell_len + sflags_len + 2)\n      {\n        /* Line was empty.  */\n        free (new_line);\n        return 0;\n      }\n    *ap = '\\0';\n\n#if MK_OS_W32\n    /* Some shells do not work well when invoked as 'sh -c xxx' to run a\n       command line (e.g. Cygnus GNUWIN32 sh.exe on W32 systems).  In these\n       cases, run commands via a script file.  */\n    if (just_print_flag && NONE_SET (flags, COMMANDS_RECURSE))\n      {\n        /* Need to allocate new_argv, although it's unused, because\n           start_job_command will want to free it and its 0'th element.  */\n        new_argv = xmalloc (2 * sizeof (char *));\n        new_argv[0] = xstrdup (\"\");\n        new_argv[1] = NULL;\n      }\n    else if ((no_default_sh_exe || batch_mode_shell) && batch_filename)\n      {\n        int temp_fd;\n        FILE* batch = NULL;\n        int id = GetCurrentProcessId ();\n        PATH_VAR (fbuf);\n\n        /* create a file name */\n        sprintf (fbuf, \"make%d\", id);\n        *batch_filename = create_batch_file (fbuf, unixy_shell, &temp_fd);\n\n        DB (DB_JOBS, (_(\"Creating temporary batch file %s\\n\"),\n                      *batch_filename));\n\n        /* Create a FILE object for the batch file, and write to it the\n           commands to be executed.  Put the batch file in TEXT mode.  */\n        _setmode (temp_fd, _O_TEXT);\n        batch = _fdopen (temp_fd, \"wt\");\n        if (!unixy_shell)\n          fputs (\"@echo off\\n\", batch);\n        fputs (command_ptr, batch);\n        fputc ('\\n', batch);\n        fclose (batch);\n        DB (DB_JOBS, (_(\"Batch file contents:%s\\n\\t%s\\n\"),\n                      !unixy_shell ? \"\\n\\t@echo off\" : \"\", command_ptr));\n\n        /* create argv */\n        new_argv = xmalloc (3 * sizeof (char *));\n        if (unixy_shell)\n          {\n            new_argv[0] = xstrdup (shell);\n            new_argv[1] = *batch_filename; /* only argv[0] gets freed later */\n          }\n        else\n          {\n            new_argv[0] = xstrdup (*batch_filename);\n            new_argv[1] = NULL;\n          }\n        new_argv[2] = NULL;\n      }\n    else\n#endif /* MK_OS_W32 */\n\n    if (unixy_shell)\n      new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0,\n                                                  flags, 0);\n\n#if MK_OS_OS2\n    else if (!unixy_shell)\n      {\n        /* new_line is local, must not be freed therefore\n           We use line here instead of new_line because we run the shell\n           manually.  */\n        char *q = new_line;\n        line_len = strlen (line);\n        p = new_line;\n        memcpy (new_line, line, line_len + 1);\n        /* Replace all backslash-newline combination and also following tabs.\n           Important: stop at the first '\\n' because that's what the loop above\n           did. The next line starting at restp[0] will be executed during the\n           next call of this function. */\n        while (*q != '\\0' && *q != '\\n')\n          {\n            if (q[0] == '\\\\' && q[1] == '\\n')\n              q += 2; /* remove '\\\\' and '\\n' */\n            else\n              *p++ = *q++;\n          }\n        *p = '\\0';\n\n# ifndef NO_CMD_DEFAULT\n        if (strnicmp (new_line, \"echo\", 4) == 0\n            && (new_line[4] == ' ' || new_line[4] == '\\t'))\n          {\n            /* the builtin echo command: handle it separately */\n            size_t echo_len = line_len - 5;\n            char *echo_line = new_line + 5;\n\n            /* special case: echo 'x=\"y\"'\n               cmd works this way: a string is printed as is, i.e., no quotes\n               are removed. But autoconf uses a command like echo 'x=\"y\"' to\n               determine whether make works. autoconf expects the output x=\"y\"\n               so we will do exactly that.\n               Note: if we do not allow cmd to be the default shell\n               we do not need this kind of voodoo */\n            if (echo_line[0] == '\\''\n                && echo_line[echo_len - 1] == '\\''\n                && strncmp (echo_line + 1, \"ac_maketemp=\",\n                            strlen (\"ac_maketemp=\")) == 0)\n              {\n                /* remove the enclosing quotes */\n                memmove (echo_line, echo_line + 1, echo_len - 2);\n                echo_line[echo_len - 2] = '\\0';\n              }\n          }\n# endif\n\n        {\n          /* Let the shell decide what to do. Put the command line into the\n             2nd command line argument and hope for the best ;-)  */\n          size_t sh_len = strlen (shell);\n\n          /* exactly 3 arguments + NULL */\n          new_argv = xmalloc (4 * sizeof (char *));\n          /* Exactly strlen(shell) + strlen(\"/c\") + strlen(line) + 3 times\n             the trailing '\\0' */\n          new_argv[0] = xmalloc (sh_len + line_len + 5);\n          memcpy (new_argv[0], shell, sh_len + 1);\n          new_argv[1] = new_argv[0] + sh_len + 1;\n          memcpy (new_argv[1], \"/c\", 3);\n          new_argv[2] = new_argv[1] + 3;\n          memcpy (new_argv[2], new_line, line_len + 1);\n          new_argv[3] = NULL;\n        }\n      }\n#elif MK_OS_DOS\n    else\n      {\n        /* With MSDOS shells, we must construct the command line here\n           instead of recursively calling ourselves, because we\n           cannot backslash-escape the special characters (see above).  */\n        new_argv = xmalloc (sizeof (char *));\n        line_len = strlen (new_line) - shell_len - sflags_len - 2;\n        new_argv[0] = xmalloc (line_len + 1);\n        strncpy (new_argv[0],\n                 new_line + shell_len + sflags_len + 2, line_len);\n        new_argv[0][line_len] = '\\0';\n      }\n#else\n    else\n      fatal (NILF, CSTRLEN (__FILE__) + INTSTR_LENGTH,\n             _(\"%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\\n\"),\n            __FILE__, __LINE__);\n#endif\n\n    free (new_line);\n  }\n\n  return new_argv;\n}\n#endif /* !MK_OS_VMS */\n\n/* Figure out the argument list necessary to run LINE as a command.  Try to\n   avoid using a shell.  This routine handles only ' quoting, and \" quoting\n   when no backslash, $ or ' characters are seen in the quotes.  Starting\n   quotes may be escaped with a backslash.  If any of the characters in\n   sh_chars is seen, or any of the builtin commands listed in sh_cmds\n   is the first word of a line, the shell is used.\n\n   If RESTP is not NULL, *RESTP is set to point to the first newline in LINE.\n   If *RESTP is NULL, newlines will be ignored.\n\n   FILE is the target whose commands these are.  It is used for\n   variable expansion for $(SHELL) and $(IFS).  */\n\nchar **\nconstruct_command_argv (char *line, char **restp, struct file *file,\n                        int cmd_flags, char **batch_filename)\n{\n  char *shell, *ifs;\n  char *allocflags = NULL;\n  const char *shellflags;\n  char **argv;\n\n  {\n    struct variable *var;\n    /* Turn off undefined variables warning while we expand HOME.  */\n    enum warning_action save = warn_get (wt_undefined_var);\n    warn_set (wt_undefined_var, w_ignore);\n\n    shell = allocated_expand_variable_for_file (STRING_SIZE_TUPLE (\"SHELL\"), file);\n#if MK_OS_W32\n    /*\n     * Convert to forward slashes so that construct_command_argv_internal()\n     * is not confused.\n     */\n    if (shell)\n      {\n        char *p = w32ify (shell, 0);\n        strcpy (shell, p);\n      }\n#endif\n#if MK_OS_OS2\n    {\n      static const char *unixroot = NULL;\n      static const char *last_shell = \"\";\n      static int init = 0;\n      if (init == 0)\n        {\n          unixroot = getenv (\"UNIXROOT\");\n          /* unixroot must be NULL or not empty */\n          if (unixroot && unixroot[0] == '\\0') unixroot = NULL;\n          init = 1;\n        }\n\n      /* if we have an unixroot drive and if shell is not default_shell\n         (which means it's either cmd.exe or the test has already been\n         performed) and if shell is an absolute path without drive letter,\n         try whether it exists e.g.: if \"/bin/sh\" does not exist use\n         \"$UNIXROOT/bin/sh\" instead.  */\n      if (unixroot && shell && ISDIRSEP (shell[0]) && !streq (shell, last_shell))\n        {\n          /* trying a new shell, check whether it exists */\n          size_t size = strlen (shell);\n          char *buf = xmalloc (size + 7);\n          memcpy (buf, shell, size);\n          memcpy (buf + size, \".exe\", 5); /* including the trailing '\\0' */\n          if (access (shell, F_OK) != 0 && access (buf, F_OK) != 0)\n            {\n              /* try the same for the unixroot drive */\n              memmove (buf + 2, buf, size + 5);\n              buf[0] = unixroot[0];\n              buf[1] = unixroot[1];\n              if (access (buf, F_OK) == 0)\n                /* we have found a shell! */\n                /* free(shell); */\n                shell = buf;\n              else\n                free (buf);\n            }\n          else\n            free (buf);\n        }\n    }\n#endif /* MK_OS_OS2 */\n\n    var = lookup_variable_for_file (STRING_SIZE_TUPLE (\".SHELLFLAGS\"), file);\n    if (!var)\n      shellflags = \"\";\n    else if (var->origin != o_default)\n      shellflags = allocflags = allocated_expand_string_for_file (var->value, file);\n    else if (posix_pedantic && !ignore_errors_flag && NONE_SET (cmd_flags, COMMANDS_NOERROR))\n      /* In POSIX mode we default to -ec, unless we're ignoring errors.  */\n      shellflags = \"-ec\";\n    else\n      shellflags = \"-c\";\n\n    ifs = allocated_expand_variable_for_file (STRING_SIZE_TUPLE (\"IFS\"), file);\n\n    warn_set (wt_undefined_var, save);\n  }\n\n  argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,\n                                          cmd_flags, batch_filename);\n\n  free (shell);\n  free (allocflags);\n  free (ifs);\n\n  return argv;\n}\n\f\n#if !defined(HAVE_DUP2)\nint\ndup2 (int old, int new)\n{\n  int fd;\n\n  (void) close (new);\n  EINTRLOOP (fd, dup (old));\n  if (fd != new)\n    {\n      (void) close (fd);\n      errno = EMFILE;\n      return -1;\n    }\n\n  return fd;\n}\n#endif /* !HAVE_DUP2 */\n\n/* On VMS systems, include special VMS functions.  */\n\n#if MK_OS_VMS\n#include \"vmsjobs.c\"\n#endif\n"
  },
  {
    "path": "src/job.h",
    "content": "/* Definitions for managing subprocesses in GNU Make.\nCopyright (C) 1992-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"output.h\"\n\n/* Structure describing a running or dead child process.  */\n\n#if MK_OS_VMS\n#define VMSCHILD                                                        \\\n    char *comname;              /* Temporary command file name */       \\\n    int efn;                    /* Completion event flag number */      \\\n    int cstatus;                /* Completion status */                 \\\n    int vms_launch_status;      /* non-zero if lib$spawn, etc failed */\n#else\n#define VMSCHILD\n#endif\n\n#define CHILDBASE                                               \\\n    char *cmd_name;       /* Allocated copy of command run.  */ \\\n    char **environment;   /* Environment for commands. */       \\\n    VMSCHILD                                                    \\\n    struct output output  /* Output for this child.  */\n\n\nstruct childbase\n  {\n    CHILDBASE;\n  };\n\nstruct child\n  {\n    CHILDBASE;\n\n    struct child *next;         /* Link in the chain.  */\n\n    struct file *file;          /* File being remade.  */\n\n    char *sh_batch_file;        /* Script file for shell commands */\n    char **command_lines;       /* Array of variable-expanded cmd lines.  */\n    char *command_ptr;          /* Ptr into command_lines[command_line].  */\n\n    unsigned int  command_line; /* Index into command_lines.  */\n\n    pid_t pid;                  /* Child process's ID number.  */\n\n    unsigned int  remote:1;     /* Nonzero if executing remotely.  */\n    unsigned int  noerror:1;    /* Nonzero if commands contained a '-'.  */\n    unsigned int  good_stdin:1; /* Nonzero if this child has a good stdin.  */\n    unsigned int  deleted:1;    /* Nonzero if targets have been deleted.  */\n    unsigned int  recursive:1;  /* Nonzero for recursive command ('+' etc.)  */\n    unsigned int  jobslot:1;    /* Nonzero if it's reserved a job slot.  */\n    unsigned int  dontcare:1;   /* Saved dontcare flag.  */\n  };\n\nextern struct child *children;\n\n/* A signal handler for SIGCHLD, if needed.  */\nvoid child_handler (int sig);\nint is_bourne_compatible_shell(const char *path);\nvoid new_job (struct file *file);\nvoid reap_children (int block, int err);\nvoid start_waiting_jobs (void);\nvoid free_childbase (struct childbase* child);\n\nchar **construct_command_argv (char *line, char **restp, struct file *file,\n                               int cmd_flags, char** batch_file);\n\npid_t child_execute_job (struct childbase *child, int good_stdin, char **argv);\n\npid_t exec_command (char **argv, char **envp);\n\nvoid unblock_all_sigs (void);\n\nextern unsigned int job_slots_used;\nextern unsigned int jobserver_tokens;\n"
  },
  {
    "path": "src/load.c",
    "content": "/* Loading dynamic objects for GNU Make.\nCopyright (C) 2012-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#if MAKE_LOAD\n\n#include <string.h>\n#include <ctype.h>\n#include <stdlib.h>\n#include <dlfcn.h>\n#include <errno.h>\n\n#include \"debug.h\"\n#include \"filedef.h\"\n#include \"variable.h\"\n\n/* Tru64 V4.0 does not have this flag */\n#ifndef RTLD_GLOBAL\n# define RTLD_GLOBAL 0\n#endif\n\n#define GMK_SETUP       \"_gmk_setup\"\n#define GMK_UNLOAD      \"_gmk_unload\"\n\ntypedef int (*setup_func_t)(unsigned int abi, const floc *flocp);\ntypedef void (*unload_func_t)(void);\n\nstruct load_list\n  {\n    struct load_list *next;\n    const char *name;\n    void *dlp;\n    unload_func_t unload;\n  };\n\nstatic struct load_list *loaded_syms = NULL;\n\nstatic setup_func_t\nload_object (const floc *flocp, int noerror, const char *ldname,\n             const char *setupnm)\n{\n  static void *global_dl = NULL;\n  char *buf;\n  const char *fp;\n  char *endp;\n  void *dlp;\n  struct load_list *new;\n  setup_func_t symp;\n\n  if (! global_dl)\n    {\n      global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL);\n      if (! global_dl)\n        {\n          const char *err = dlerror ();\n          OS (fatal, flocp, _(\"failed to open global symbol table: %s\"), err);\n        }\n    }\n\n  /* Find the prefix of the ldname.  */\n  fp = strrchr (ldname, '/');\n#ifdef HAVE_DOS_PATHS\n  if (fp)\n    {\n      const char *fp2 = strchr (fp, '\\\\');\n\n      if (fp2 > fp)\n        fp = fp2;\n    }\n  else\n    fp = strrchr (ldname, '\\\\');\n  /* The (improbable) case of d:foo.  */\n  if (fp && *fp && fp[1] == ':')\n    fp++;\n#endif\n  if (!fp)\n    fp = ldname;\n  else\n    ++fp;\n\n  endp = buf = alloca (strlen (fp) + CSTRLEN (GMK_UNLOAD) + 1);\n  while (isalnum ((unsigned char) *fp) || *fp == '_')\n    *(endp++) = *(fp++);\n\n  /* If we didn't find a symbol name yet, construct it from the prefix.  */\n  if (! setupnm)\n    {\n      memcpy (endp, GMK_SETUP, CSTRLEN (GMK_SETUP) + 1);\n      setupnm = buf;\n    }\n\n  DB (DB_VERBOSE, (_(\"Loading symbol %s from %s\\n\"), setupnm, ldname));\n\n  symp = (setup_func_t) dlsym (global_dl, setupnm);\n  if (symp)\n    return symp;\n\n  /* If the path has no \"/\", try the current directory first.  */\n  dlp = NULL;\n  if (! strchr (ldname, '/')\n#ifdef HAVE_DOS_PATHS\n      && ! strchr (ldname, '\\\\')\n#endif\n      )\n    dlp = dlopen (concat (2, \"./\", ldname), RTLD_LAZY|RTLD_GLOBAL);\n\n  /* If we haven't opened it yet, try the default search path.  */\n  if (! dlp)\n    dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL);\n\n  /* Still no?  Then fail.  */\n  if (! dlp)\n    {\n      const char *err = dlerror ();\n      if (noerror)\n        DB (DB_BASIC, (\"%s\\n\", err));\n      else\n        OS (error, flocp, \"%s\", err);\n      return NULL;\n    }\n\n  DB (DB_VERBOSE, (_(\"Loaded shared object %s\\n\"), ldname));\n\n  /* Assert that the GPL license symbol is defined.  */\n  symp = (setup_func_t) dlsym (dlp, \"plugin_is_GPL_compatible\");\n  if (! symp)\n    OS (fatal, flocp,\n        _(\"loaded object %s is not declared to be GPL compatible\"), ldname);\n\n  symp = (setup_func_t) dlsym (dlp, setupnm);\n  if (! symp)\n    {\n      const char *err = dlerror ();\n      OSSS (fatal, flocp, _(\"failed to load symbol %s from %s: %s\"),\n            setupnm, ldname, err);\n    }\n\n  new = xcalloc (sizeof (struct load_list));\n  new->next = loaded_syms;\n  loaded_syms = new;\n  new->name = ldname;\n  new->dlp = dlp;\n\n  /* Compute the name of the unload function and look it up.  */\n  memcpy (endp, GMK_UNLOAD, CSTRLEN (GMK_UNLOAD) + 1);\n\n  new->unload = (unload_func_t) dlsym (dlp, buf);\n  if (new->unload)\n    DB (DB_VERBOSE, (_(\"Detected symbol %s in %s\\n\"), buf, ldname));\n\n  return symp;\n}\n\nint\nload_file (const floc *flocp, struct file *file, int noerror)\n{\n  const char *ldname = file->name;\n  char *buf;\n  char *setupnm = NULL;\n  const char *fp;\n  int r;\n  setup_func_t symp;\n\n  /* Break the input into an object file name and a symbol name.  If no symbol\n     name was provided, compute one from the object file name.  */\n  fp = strchr (ldname, '(');\n  if (fp)\n    {\n      const char *ep;\n\n      /* There's an open paren, so see if there's a close paren: if so use\n         that as the symbol name.  We can't have whitespace: it would have\n         been chopped up before this function is called.  */\n      ep = strchr (fp+1, ')');\n      if (ep && ep[1] == '\\0')\n        {\n          size_t l = fp - ldname;\n\n          ++fp;\n          if (fp == ep)\n            OS (fatal, flocp, _(\"empty symbol name for load: %s\"), ldname);\n\n          /* Make a copy of the ldname part.  */\n          buf = alloca (strlen (ldname) + 1);\n          memcpy (buf, ldname, l);\n          buf[l] = '\\0';\n          ldname = buf;\n\n          /* Make a copy of the symbol name part.  */\n          setupnm = buf + l + 1;\n          memcpy (setupnm, fp, ep - fp);\n          setupnm[ep - fp] = '\\0';\n        }\n    }\n\n  /* Make sure this name is in the string cache.  */\n  ldname = file->name = strcache_add (ldname);\n\n  /* If this object has been loaded, we're done: return -1 to ensure make does\n     not rebuild again.  If a rebuild is allowed it was set up when this\n     object was initially loaded.  */\n  file = lookup_file (ldname);\n  if (file && file->loaded)\n    return -1;\n\n  /* Load it!  */\n  symp = load_object (flocp, noerror, ldname, setupnm);\n  if (! symp)\n    return 0;\n\n  /* Invoke the setup function.  */\n  {\n    unsigned int abi = GMK_ABI_VERSION;\n    r = (*symp) (abi, flocp);\n  }\n\n  /* If the load didn't fail, add the file to the .LOADED variable.  */\n  if (r)\n    do_variable_definition(flocp, \".LOADED\", ldname, o_file, f_append_value, 0,\n                           s_global);\n\n  return r;\n}\n\nint\nunload_file (const char *name)\n{\n  struct load_list **dp = &loaded_syms;\n\n  /* Unload and remove the entry for this file.  */\n  while (*dp != NULL)\n    {\n      struct load_list *d = *dp;\n\n      if (streq (d->name, name))\n        {\n          int rc;\n\n          DB (DB_VERBOSE, (_(\"Unloading shared object %s\\n\"), name));\n\n          if (d->unload)\n            (*d->unload) ();\n\n          rc = dlclose (d->dlp);\n          if (rc)\n            perror_with_name (\"dlclose: \", d->name);\n\n          *dp = d->next;\n          free (d);\n          return rc;\n        }\n\n      dp = &d->next;\n    }\n\n  return 0;\n}\n\nvoid\nunload_all ()\n{\n  while (loaded_syms)\n    {\n      struct load_list *d = loaded_syms;\n      loaded_syms = loaded_syms->next;\n\n      if (d->unload)\n        (*d->unload) ();\n\n      if (dlclose (d->dlp))\n        perror_with_name (\"dlclose: \", d->name);\n\n      free (d);\n    }\n}\n\n#else\n\nint\nload_file (const floc *flocp, struct file *file UNUSED, int noerror)\n{\n  if (! noerror)\n    O (fatal, flocp,\n       _(\"'load' is not supported on this platform\"));\n\n  return 0;\n}\n\nint\nunload_file (const char *name UNUSED)\n{\n  O (fatal, NILF, \"INTERNAL: cannot unload when load is not supported\");\n}\n\nvoid\nunload_all ()\n{\n}\n\n#endif  /* MAKE_LOAD */\n"
  },
  {
    "path": "src/loadapi.c",
    "content": "/* API for GNU Make dynamic objects.\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include \"filedef.h\"\n#include \"variable.h\"\n#include \"dep.h\"\n\n/* Allocate a buffer in our context, so we can free it.  */\nchar *\ngmk_alloc (unsigned int len)\n{\n  return xmalloc (len);\n}\n\n/* Free a buffer returned by gmk_expand().  */\nvoid\ngmk_free (char *s)\n{\n  free (s);\n}\n\n/* Evaluate a buffer as make syntax.\n   Ideally eval_buffer() will take const char *, but not yet.  */\nvoid\ngmk_eval (const char *buffer, const gmk_floc *gfloc)\n{\n  /* Preserve existing variable buffer context.  */\n  char *pbuf;\n  size_t plen;\n  char *s;\n  floc fl;\n  floc *flp;\n\n  if (gfloc)\n    {\n      fl.filenm = gfloc->filenm;\n      fl.lineno = gfloc->lineno;\n      fl.offset = 0;\n      flp = &fl;\n    }\n  else\n    flp = NULL;\n\n  install_variable_buffer (&pbuf, &plen);\n\n  s = xstrdup (buffer);\n  eval_buffer (s, flp);\n  free (s);\n\n  restore_variable_buffer (pbuf, plen);\n}\n\n/* Expand a string and return an allocated buffer.\n   Caller must call gmk_free() with this buffer.  */\nchar *\ngmk_expand (const char *ref)\n{\n  return allocated_expand_string (ref);\n}\n\n/* Register a function to be called from makefiles.  */\nvoid\ngmk_add_function (const char *name, gmk_func_ptr func,\n                  unsigned int min, unsigned int max, unsigned int flags)\n{\n  define_new_function (reading_file, name, min, max, flags, func);\n}\n"
  },
  {
    "path": "src/main.c",
    "content": "/* Argument parsing and main program of GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n#if MK_OS_W32\n# include <windows.h>\n# include <io.h>\n# include \"pathstuff.h\"\n# include \"sub_proc.h\"\n# include \"w32err.h\"\n#endif\n#if MK_OS_OS2\n# include <sys/types.h>\n# include <sys/wait.h>\n#endif\n#ifdef HAVE_FCNTL_H\n# include <fcntl.h>\n#endif\n\n#if MK_OS_VMS\nint vms_use_mcr_command = 0;\nint vms_always_use_cmd_file = 0;\nint vms_gnv_shell = 0;\nint vms_legacy_behavior = 0;\nint vms_comma_separator = 0;\nint vms_unix_simulation = 0;\nint vms_report_unix_paths = 0;\n\n/* Evaluates if a VMS environment option is set, only look at first character */\nstatic int\nget_vms_env_flag (const char *name, int default_value)\n{\nchar * value;\nchar x;\n\n  value = getenv (name);\n  if (value == NULL)\n    return default_value;\n\n  x = toupper (value[0]);\n  switch (x)\n    {\n    case '1':\n    case 'T':\n    case 'E':\n      return 1;\n      break;\n    case '0':\n    case 'F':\n    case 'D':\n      return 0;\n    }\n}\n#endif\n\n#if defined HAVE_WAITPID || defined HAVE_WAIT3\n# define HAVE_WAIT_NOHANG\n#endif\n\n#ifndef HAVE_UNISTD_H\nint chdir ();\n#endif\n#ifndef STDC_HEADERS\n# ifndef sun                    /* Sun has an incorrect decl in a header.  */\nvoid exit (int) NORETURN;\n# endif\ndouble atof ();\n#endif\n\n#include \"os.h\"\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"variable.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"rule.h\"\n#include \"debug.h\"\n#include \"getopt.h\"\n#include \"shuffle.h\"\n#include \"warning.h\"\n\nstatic void clean_jobserver (int status);\nstatic void print_data_base (void);\nstatic void print_version (void);\nstatic void decode_switches (int argc, const char **argv,\n                             enum variable_origin origin);\nstatic void decode_env_switches (const char *envar, size_t len,\n                                 enum variable_origin origin);\nstatic void disable_builtins ();\nstatic char *quote_for_env (char *out, const char *in);\nstatic void initialize_global_hash_tables (void);\n\n\f\n/* True if C is a switch value that corresponds to a short option.  */\n\n#define short_option(c) ((c) <= CHAR_MAX)\n\n/* The structure used to hold the list of strings given\n   in command switches of a type that takes strlist arguments.  */\n\nstruct stringlist\n  {\n    const char **list;  /* Nil-terminated list of strings.  */\n    unsigned int idx;   /* Index into above.  */\n    unsigned int max;   /* Number of pointers allocated.  */\n  };\n\n\n/* The recognized command switches.  */\n\n/* Nonzero means do extra verification (that may slow things down).  */\n\nint verify_flag;\n\n/* Nonzero means do not print commands to be executed (-s).  */\n\nstatic int silent_flag;\nstatic const int default_silent_flag = 0;\nstatic enum variable_origin silent_origin = o_default;\n\n/* Nonzero means either -s was given, or .SILENT-with-no-deps was seen.  */\n\nint run_silent = 0;\n\n/* Nonzero means just touch the files\n   that would appear to need remaking (-t)  */\n\nint touch_flag;\n\n/* Nonzero means just print what commands would need to be executed,\n   don't actually execute them (-n).  */\n\nint just_print_flag;\n\n/* Print debugging info (--debug).  */\n\nstatic struct stringlist *db_flags = 0;\nstatic int debug_flag = 0;\n\nint db_level = 0;\n\n/* Synchronize output (--output-sync).  */\n\nchar *output_sync_option = 0;\n\n/* Environment variables override makefile definitions.  */\n\nint env_overrides = 0;\n\n/* Nonzero means ignore status codes returned by commands\n   executed to remake files.  Just treat them all as successful (-i).  */\n\nint ignore_errors_flag = 0;\n\n/* Nonzero means print the data base that results from reading the makefile.\n   (-p or --print-data-base).  */\n\nint print_data_base_flag = 0;\n\n/* Nonzero means don't remake anything, just print a list of targets defined\n   by reading the makefile (--print-targets).  */\n\nint print_targets_flag = 0;\n\n/* Nonzero means don't remake anything; just return a nonzero status\n   if the specified targets are not up to date (-q).  */\n\nint question_flag = 0;\n\n/* Nonzero means do not use any of the builtin rules (-r) / variables (-R).  */\n\nint no_builtin_rules_flag = 0;\nint no_builtin_variables_flag = 0;\nstatic int old_builtin_rules_flag;\nstatic int old_builtin_variables_flag;\n\n/* Nonzero means all variables are automatically exported.  */\n\nint export_all_variables = 0;\n\n/* Nonzero means keep going even if remaking some file fails (-k).  */\n\nint keep_going_flag;\nstatic const int default_keep_going_flag = 0;\nstatic enum variable_origin keep_going_origin = o_default;\n\n/* Nonzero means check symlink mtimes.  */\n\nint check_symlink_flag = 0;\n\nstatic int print_directory_flag = -1;\nstatic const int default_print_directory_flag = -1;\nstatic enum variable_origin print_directory_origin = o_default;\n\n/* Nonzero means print version information.  */\n\nint print_version_flag = 0;\n\n/* List of makefiles given with -f switches.  */\n\nstatic struct stringlist *makefiles = 0;\n\n/* Size of the stack when we started.  */\n\n#ifdef SET_STACK_SIZE\nstruct rlimit stack_limit;\n#endif\n\n\n/* Number of job slots for parallelism.  */\n\nunsigned int job_slots;\n\n#define INVALID_JOB_SLOTS (-1)\nstatic unsigned int master_job_slots = 0;\nstatic int arg_job_slots = INVALID_JOB_SLOTS;\n\nstatic const int default_job_slots = INVALID_JOB_SLOTS;\n\n/* Value of job_slots that means no limit.  */\n\nstatic const int inf_jobs = 0;\n\n/* Authorization for the jobserver.  */\n\nchar *jobserver_auth = NULL;\n\n/* Style for the jobserver.  */\n\nstatic char *jobserver_style = NULL;\n\n/* Shuffle mode for goals and prerequisites.  */\n\nstatic char *shuffle_mode = NULL;\n\n/* Handle for the mutex to synchronize output of our children under -O.  */\n\nstatic char *sync_mutex = NULL;\n\n/* Maximum load average at which multiple jobs will be run.\n   Negative values mean unlimited, while zero means limit to\n   zero load (which could be useful to start infinite jobs remotely\n   but one at a time locally).  */\ndouble max_load_average = -1.0;\ndouble default_load_average = -1.0;\n\n/* List of directories given with -C switches.  */\n\nstatic struct stringlist *directories = 0;\n\n/* List of include directories given with -I switches.  */\n\nstatic struct stringlist *include_dirs = 0;\n\n/* List of files given with -o switches.  */\n\nstatic struct stringlist *old_files = 0;\n\n/* List of files given with -W switches.  */\n\nstatic struct stringlist *new_files = 0;\n\n/* List of strings to be eval'd.  */\nstatic struct stringlist *eval_strings = 0;\n\n/* If nonzero, we should just print usage and exit.  */\n\nstatic int print_usage_flag = 0;\n\n/* Command line warning flags.  */\n\nstatic struct stringlist *warn_flags = 0;\n\n/* If nonzero, we should print a warning message\n   for each reference to an undefined variable.  */\n\nstatic int warn_undefined_variables_flag;\n\n/* If nonzero, always build all targets, regardless of whether\n   they appear out of date or not.  */\n\nstatic int always_make_set = 0;\nint always_make_flag = 0;\n\n/* If nonzero, we're in the \"try to rebuild makefiles\" phase.  */\n\nint rebuilding_makefiles = 0;\n\n/* Remember the original value of the SHELL variable, from the environment.  */\n\nstruct variable shell_var;\n\n/* This character introduces a command: it's the first char on the line.  */\n\nchar cmd_prefix = '\\t';\n\n/* Whether or not .NOTINTERMEDIATE with no prerequisites was given.  */\nunsigned int no_intermediates;\n\n/* Count the number of commands we've invoked, that might change something in\n   the filesystem.  Start with 1 so calloc'd memory never matches.  */\n\nunsigned long command_count = 1;\n\n/* Remember the location of the name of the batch file from stdin.  */\n\nstatic int stdin_offset = -1;\n\n\f\n/* The usage output.  We write it this way to make life easier for the\n   translators, especially those trying to translate to right-to-left\n   languages like Hebrew.  */\n\nstatic const char *const usage[] =\n  {\n    N_(\"Options:\\n\"),\n    N_(\"\\\n  -b, -m                      Ignored for compatibility.\\n\"),\n    N_(\"\\\n  -B, --always-make           Unconditionally make all targets.\\n\"),\n    N_(\"\\\n  -C DIRECTORY, --directory=DIRECTORY\\n\\\n                              Change to DIRECTORY before doing anything.\\n\"),\n    N_(\"\\\n  -d                          Print lots of debugging information.\\n\"),\n    N_(\"\\\n  --debug[=FLAGS]             Print various types of debugging information.\\n\"),\n    N_(\"\\\n  -e, --environment-overrides\\n\\\n                              Environment variables override makefiles.\\n\"),\n    N_(\"\\\n  -E STRING, --eval=STRING    Evaluate STRING as a makefile statement.\\n\"),\n    N_(\"\\\n  -f FILE, --file=FILE, --makefile=FILE\\n\\\n                              Read FILE as a makefile.\\n\"),\n    N_(\"\\\n  -h, --help                  Print this message and exit.\\n\"),\n    N_(\"\\\n  -i, --ignore-errors         Ignore errors from recipes.\\n\"),\n    N_(\"\\\n  -I DIRECTORY, --include-dir=DIRECTORY\\n\\\n                              Search DIRECTORY for included makefiles.\\n\"),\n    N_(\"\\\n  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.\\n\"),\n    N_(\"\\\n  --jobserver-style=STYLE     Select the style of jobserver to use.\\n\"),\n    N_(\"\\\n  -k, --keep-going            Keep going when some targets can't be made.\\n\"),\n    N_(\"\\\n  -l [N], --load-average[=N], --max-load[=N]\\n\\\n                              Don't start multiple jobs unless load is below N.\\n\"),\n    N_(\"\\\n  -L, --check-symlink-times   Use the latest mtime between symlinks and target.\\n\"),\n    N_(\"\\\n  -n, --just-print, --dry-run, --recon\\n\\\n                              Don't actually run any recipe; just print them.\\n\"),\n    N_(\"\\\n  -o FILE, --old-file=FILE, --assume-old=FILE\\n\\\n                              Consider FILE to be very old and don't remake it.\\n\"),\n    N_(\"\\\n  -O[TYPE], --output-sync[=TYPE]\\n\\\n                              Synchronize output of parallel jobs by TYPE.\\n\"),\n    N_(\"\\\n  -p, --print-data-base       Print make's internal database.\\n\"),\n    N_(\"\\\n  -q, --question              Run no recipe; exit status says if up to date.\\n\"),\n    N_(\"\\\n  -r, --no-builtin-rules      Disable the built-in implicit rules.\\n\"),\n    N_(\"\\\n  -R, --no-builtin-variables  Disable the built-in variable settings.\\n\"),\n    N_(\"\\\n  --shuffle[={SEED|random|reverse|none}]\\n\\\n                              Perform shuffle of prerequisites and goals.\\n\"),\n    N_(\"\\\n  -s, --silent, --quiet       Don't echo recipes.\\n\"),\n    N_(\"\\\n  --no-silent                 Echo recipes (disable --silent mode).\\n\"),\n    N_(\"\\\n  -S, --no-keep-going, --stop\\n\\\n                              Turns off -k.\\n\"),\n    N_(\"\\\n  -t, --touch                 Touch targets instead of remaking them.\\n\"),\n    N_(\"\\\n  --trace                     Print tracing information.\\n\"),\n    N_(\"\\\n  -v, --version               Print the version number of make and exit.\\n\"),\n    N_(\"\\\n  -w, --print-directory       Print the current directory.\\n\"),\n    N_(\"\\\n  --no-print-directory        Turn off -w, even if it was turned on implicitly.\\n\"),\n    N_(\"\\\n  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\\n\\\n                              Consider FILE to be infinitely new.\\n\"),\n    N_(\"\\\n  --warn[=CONTROL]            Control warnings for makefile issues.\\n\"),\n    NULL\n  };\n\n/* Nonzero if the \"--trace\" option was given.  */\n\nstatic int trace_flag = 0;\n\n/* The structure that describes an accepted command switch.  */\n\nstruct command_switch\n  {\n    int c;                        /* The switch character.  */\n\n    enum                          /* Type of the value.  */\n      {\n        flag,                     /* Turn int flag on.  */\n        flag_off,                 /* Turn int flag off.  */\n        string,                   /* One string per invocation.  */\n        strlist,                  /* One string per switch.  */\n        filename,                 /* A string containing a file name.  */\n        positive_int,             /* A positive integer.  */\n        floating,                 /* A floating-point number (double).  */\n        ignore                    /* Ignored.  */\n      } type;\n\n    void *value_ptr;              /* Pointer to the value-holding variable.  */\n\n    unsigned int env:1;           /* Can come from MAKEFLAGS.  */\n    unsigned int toenv:1;         /* Should be put in MAKEFLAGS.  */\n    unsigned int no_makefile:1;   /* Don't propagate when remaking makefiles. */\n    unsigned int specified:1;     /* Set if the switch was specified somewhere.\n                                     Allows switches that are ON by default to\n                                     appear in MAKEFLAGS when set explicitly. */\n\n    const void *noarg_value;      /* Pointer to value used if no arg given.  */\n    const void *default_value;    /* Pointer to default value.  */\n\n    const char *long_name;        /* Long option name.  */\n    enum variable_origin *origin; /* Origin of the value.  */\n  };\n\n/* The table of command switches.\n   Order matters here: this is the order MAKEFLAGS will be constructed.\n   So be sure all simple flags (single char, no argument) come first.  */\n\n#define TEMP_STDIN_OPT  (CHAR_MAX+10)\n#define WARN_OPT        (CHAR_MAX+13)\n\nstatic struct command_switch switches[] =\n  {\n    { 'b', ignore, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n    { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, 0, \"always-make\", 0 },\n    { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0, 0, 0 },\n    { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, 0, \"environment-overrides\", 0 },\n    { 'E', strlist, &eval_strings, 1, 0, 0, 0, 0, 0, \"eval\", 0 },\n    { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, 0, \"help\", 0 },\n    { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, 0, \"ignore-errors\", 0 },\n    { 'k', flag, &keep_going_flag, 1, 1, 0, 0, 0, &default_keep_going_flag,\n      \"keep-going\", &keep_going_origin },\n    { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, 0, \"check-symlink-times\", 0 },\n    { 'm', ignore, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n    { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, 0, \"just-print\", 0 },\n    { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, 0, \"print-data-base\", 0 },\n    { 'q', flag, &question_flag, 1, 1, 1, 0, 0, 0, \"question\", 0 },\n    { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, 0, \"no-builtin-rules\", 0 },\n    { 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0, 0,\n      \"no-builtin-variables\", 0 },\n    { 's', flag, &silent_flag, 1, 1, 0, 0, 0, &default_silent_flag, \"silent\",\n      &silent_origin },\n    { 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, 0, &default_keep_going_flag,\n      \"no-keep-going\", &keep_going_origin },\n    { 't', flag, &touch_flag, 1, 1, 1, 0, 0, 0, \"touch\", 0 },\n    { 'v', flag, &print_version_flag, 1, 0, 0, 0, 0, 0, \"version\", 0 },\n    { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0,\n      &default_print_directory_flag, \"print-directory\", &print_directory_origin },\n\n    /* These options take arguments.  */\n    { 'C', filename, &directories, 0, 0, 0, 0, 0, 0, \"directory\", 0 },\n    { 'f', filename, &makefiles, 0, 0, 0, 0, 0, 0, \"file\", 0 },\n    { 'I', filename, &include_dirs, 1, 1, 0, 0, 0, 0,\n      \"include-dir\", 0 },\n    { 'j', positive_int, &arg_job_slots, 1, 1, 0, 0, &inf_jobs, &default_job_slots,\n      \"jobs\", 0 },\n    { 'l', floating, &max_load_average, 1, 1, 0, 0, &default_load_average,\n      &default_load_average, \"load-average\", 0 },\n    { 'o', filename, &old_files, 0, 0, 0, 0, 0, 0, \"old-file\", 0 },\n    { 'O', string, &output_sync_option, 1, 1, 0, 0, \"target\", 0, \"output-sync\", 0 },\n    { 'W', filename, &new_files, 0, 0, 0, 0, 0, 0, \"what-if\", 0 },\n\n    /* These are long-style options.  */\n    { CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, 0, \"basic\", 0, \"debug\", 0 },\n    { CHAR_MAX+2, string, &jobserver_auth, 1, 1, 0, 0, 0, 0, JOBSERVER_AUTH_OPT, 0 },\n    { CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, 0, \"trace\", 0 },\n    { CHAR_MAX+4, flag_off, &print_directory_flag, 1, 1, 0, 0, 0,\n      &default_print_directory_flag, \"no-print-directory\", &print_directory_origin },\n    { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, 0,\n      \"warn-undefined-variables\", 0 },\n    { CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, 0, \"sync-mutex\", 0 },\n    { CHAR_MAX+8, flag_off, &silent_flag, 1, 1, 0, 0, 0, &default_silent_flag,\n      \"no-silent\", &silent_origin },\n    { CHAR_MAX+9, string, &jobserver_auth, 1, 0, 0, 0, 0, 0, \"jobserver-fds\", 0 },\n    /* There is special-case handling for this in decode_switches() as well.  */\n    { TEMP_STDIN_OPT, filename, &makefiles, 0, 0, 0, 0, 0, 0, \"temp-stdin\", 0 },\n    { CHAR_MAX+11, string, &shuffle_mode, 1, 1, 0, 0, \"random\", 0, \"shuffle\", 0 },\n    { CHAR_MAX+12, string, &jobserver_style, 1, 0, 0, 0, 0, 0, \"jobserver-style\", 0 },\n    { WARN_OPT, strlist, &warn_flags, 1, 1, 0, 0, \"warn\", NULL, \"warn\", NULL },\n    { CHAR_MAX+14, flag, &print_targets_flag, 1, 1, 0, 0, 0, 0, \"print-targets\", 0 },\n    { 0, 0, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }\n  };\n\n/* Secondary long names for options.  */\n\nstatic struct option long_option_aliases[] =\n  {\n    { \"quiet\",          no_argument,            0, 's' },\n    { \"stop\",           no_argument,            0, 'S' },\n    { \"new-file\",       required_argument,      0, 'W' },\n    { \"assume-new\",     required_argument,      0, 'W' },\n    { \"assume-old\",     required_argument,      0, 'o' },\n    { \"max-load\",       optional_argument,      0, 'l' },\n    { \"dry-run\",        no_argument,            0, 'n' },\n    { \"recon\",          no_argument,            0, 'n' },\n    { \"makefile\",       required_argument,      0, 'f' },\n  };\n\n/* List of goal targets.  */\n\nstatic struct goaldep *goals, *lastgoal;\n\n/* List of variables which were defined on the command line\n   (or, equivalently, in MAKEFLAGS).  */\n\nstruct command_variable\n  {\n    struct command_variable *next;\n    struct variable *variable;\n  };\nstatic struct command_variable *command_variables;\n\f\n/* The name we were invoked with.  */\n\nconst char *program;\n\n/* Our current directory before processing any -C options.  */\n\nchar *directory_before_chdir;\n\n/* Our current directory after processing all -C options.  */\n\nchar *starting_directory;\n\n/* Value of the MAKELEVEL variable at startup (or 0).  */\n\nunsigned int makelevel;\n\n/* Pointer to the value of the .DEFAULT_GOAL special variable.\n   The value will be the name of the goal to remake if the command line\n   does not override it.  It can be set by the makefile, or else it's\n   the first target defined in the makefile whose name does not start\n   with '.'.  */\n\nstruct variable * default_goal_var;\n\n/* Pointer to structure for the file .DEFAULT\n   whose commands are used for any file that has none of its own.\n   This is zero if the makefiles do not define .DEFAULT.  */\n\nstruct file *default_file;\n\n/* Nonzero if we have seen the magic '.POSIX' target.\n   This turns on pedantic compliance with POSIX.2.  */\n\nint posix_pedantic;\n\n/* Nonzero if we have seen the '.SECONDEXPANSION' target.\n   This turns on secondary expansion of prerequisites.  */\n\nint second_expansion;\n\n/* Nonzero if we have seen the '.ONESHELL' target.\n   This causes the entire recipe to be handed to SHELL\n   as a single string, potentially containing newlines.  */\n\nint one_shell;\n\n/* One of OUTPUT_SYNC_* if the \"--output-sync\" option was given.  This\n   attempts to synchronize the output of parallel jobs such that the results\n   of each job stay together.  */\n\nint output_sync = OUTPUT_SYNC_NONE;\n\n/* Nonzero if we have seen the '.NOTPARALLEL' target.\n   This turns off parallel builds for this invocation of make.  */\n\nint not_parallel;\n\n/* Nonzero if some rule detected clock skew; we keep track so (a) we only\n   print one warning about it during the run, and (b) we can print a final\n   warning at the end of the run. */\n\nint clock_skew_detected;\n\n/* Map of possible stop characters for searching strings.  */\n#ifndef UCHAR_MAX\n# define UCHAR_MAX 255\n#endif\nunsigned short stopchar_map[UCHAR_MAX + 1] = {0};\n\n/* If output-sync is enabled we'll collect all the output generated due to\n   options, while reading makefiles, etc.  */\n\nstruct output make_sync;\n\n\f\n/* Mask of signals that are being caught with fatal_error_signal.  */\n\n#if defined(POSIX)\nsigset_t fatal_signal_set;\n#elif defined(HAVE_SIGSETMASK)\nint fatal_signal_mask;\n#endif\n\n#if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal\n# if !defined HAVE_SIGACTION\n#  define bsd_signal signal\n# else\ntypedef void (*bsd_signal_ret_t) (int);\n\nstatic bsd_signal_ret_t\nbsd_signal (int sig, bsd_signal_ret_t func)\n{\n  struct sigaction act, oact;\n  act.sa_handler = func;\n  act.sa_flags = SA_RESTART;\n  sigemptyset (&act.sa_mask);\n  sigaddset (&act.sa_mask, sig);\n  if (sigaction (sig, &act, &oact) != 0)\n    return SIG_ERR;\n  return oact.sa_handler;\n}\n# endif\n#endif\n\nstatic void\ninitialize_global_hash_tables (void)\n{\n  init_hash_global_variable_set ();\n  strcache_init ();\n  init_hash_files ();\n  hash_init_directories ();\n  hash_init_function_table ();\n}\n\n/* This character map locate stop chars when parsing GNU makefiles.\n   Each element is true if we should stop parsing on that character.  */\n\nstatic void\ninitialize_stopchar_map (void)\n{\n  int i;\n\n  stopchar_map[(int)'\\0'] = MAP_NUL;\n  stopchar_map[(int)'#'] = MAP_COMMENT;\n  stopchar_map[(int)';'] = MAP_SEMI;\n  stopchar_map[(int)'='] = MAP_EQUALS;\n  stopchar_map[(int)':'] = MAP_COLON;\n  stopchar_map[(int)'|'] = MAP_PIPE;\n  stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC;\n  stopchar_map[(int)','] = MAP_COMMA;\n  stopchar_map[(int)'('] = MAP_VARSEP;\n  stopchar_map[(int)'{'] = MAP_VARSEP;\n  stopchar_map[(int)'}'] = MAP_VARSEP;\n  stopchar_map[(int)')'] = MAP_VARSEP;\n  stopchar_map[(int)'$'] = MAP_VARIABLE;\n\n  stopchar_map[(int)'-'] = MAP_USERFUNC;\n  stopchar_map[(int)'_'] = MAP_USERFUNC;\n\n  stopchar_map[(int)' '] = MAP_BLANK;\n  stopchar_map[(int)'\\t'] = MAP_BLANK;\n\n  stopchar_map[(int)'/'] = MAP_DIRSEP;\n#if MK_OS_VMS\n  stopchar_map[(int)':'] |= MAP_DIRSEP;\n  stopchar_map[(int)']'] |= MAP_DIRSEP;\n  stopchar_map[(int)'>'] |= MAP_DIRSEP;\n#elif defined(HAVE_DOS_PATHS)\n  stopchar_map[(int)'\\\\'] |= MAP_DIRSEP;\n#endif\n\n  for (i = 1; i <= UCHAR_MAX; ++i)\n    {\n      if (isspace (i) && NONE_SET (stopchar_map[i], MAP_BLANK))\n        /* Don't mark blank characters as newline characters.  */\n        stopchar_map[i] |= MAP_NEWLINE;\n      else if (isalnum (i))\n        stopchar_map[i] |= MAP_USERFUNC;\n    }\n}\n\n/* This code is stolen from gnulib.\n   If/when we abandon the requirement to work with K&R compilers, we can\n   remove this (and perhaps other parts of GNU Make!) and migrate to using\n   gnulib directly.\n\n   This is called only through atexit(), which means die() has already been\n   invoked.  So, call exit() here directly.  Apparently that works...?\n*/\n\n/* Close standard output, exiting with status 'exit_failure' on failure.\n   If a program writes *anything* to stdout, that program should close\n   stdout and make sure that it succeeds before exiting.  Otherwise,\n   suppose that you go to the extreme of checking the return status\n   of every function that does an explicit write to stdout.  The last\n   printf can succeed in writing to the internal stream buffer, and yet\n   the fclose(stdout) could still fail (due e.g., to a disk full error)\n   when it tries to write out that buffered data.  Thus, you would be\n   left with an incomplete output file and the offending program would\n   exit successfully.  Even calling fflush is not always sufficient,\n   since some file systems (NFS and CODA) buffer written/flushed data\n   until an actual close call.\n\n   Besides, it's wasteful to check the return value from every call\n   that writes to stdout -- just let the internal stream state record\n   the failure.  That's what the ferror test is checking below.\n\n   It's important to detect such failures and exit nonzero because many\n   tools (most notably 'make' and other build-management systems) depend\n   on being able to detect failure in other tools via their exit status.  */\n\nstatic void\nclose_stdout (void)\n{\n  int prev_fail = ferror (stdout);\n  int fclose_fail = fclose (stdout);\n\n  if (prev_fail || fclose_fail)\n    {\n      if (fclose_fail)\n        perror_with_name (_(\"write error: stdout\"), \"\");\n      else\n        O (error, NILF, _(\"write error: stdout\"));\n      exit (MAKE_TROUBLE);\n    }\n}\n\nstatic const char *\nexpand_command_line_file (const char *name)\n{\n  const char *cp;\n  char *expanded = 0;\n\n  if (name[0] == '\\0')\n    O (fatal, NILF, _(\"empty string invalid as file name\"));\n\n  if (name[0] == '~')\n    {\n      expanded = tilde_expand (name);\n      if (expanded && expanded[0] != '\\0')\n        name = expanded;\n    }\n\n  /* This is also done in parse_file_seq, so this is redundant\n     for names read from makefiles.  It is here for names passed\n     on the command line.  */\n  while (name[0] == '.' && name[1] == '/')\n    {\n      name += 2;\n      while (name[0] == '/')\n        /* Skip following slashes: \".//foo\" is \"foo\", not \"/foo\".  */\n        ++name;\n    }\n\n  if (name[0] == '\\0')\n    {\n      /* Nothing else but one or more \"./\", maybe plus slashes!  */\n      name = \"./\";\n    }\n\n  cp = strcache_add (name);\n\n  free (expanded);\n\n  return cp;\n}\n\n/* Toggle -d on receipt of SIGUSR1.  */\n\n#ifdef SIGUSR1\nstatic void\ndebug_signal_handler (int sig UNUSED)\n{\n  db_level = db_level ? DB_NONE : DB_BASIC;\n}\n#endif\n\nstatic void\ndecode_debug_flags (void)\n{\n  const char **pp;\n\n  if (debug_flag)\n    db_level = DB_ALL;\n\n  if (trace_flag)\n    db_level |= DB_PRINT | DB_WHY;\n\n  if (db_flags)\n    for (pp=db_flags->list; *pp; ++pp)\n      {\n        const char *p = *pp;\n\n        while (1)\n          {\n            switch (tolower (p[0]))\n              {\n              case 'a':\n                db_level |= DB_ALL;\n                break;\n              case 'b':\n                db_level |= DB_BASIC;\n                break;\n              case 'i':\n                db_level |= DB_BASIC | DB_IMPLICIT;\n                break;\n              case 'j':\n                db_level |= DB_JOBS;\n                break;\n              case 'm':\n                db_level |= DB_BASIC | DB_MAKEFILES;\n                break;\n              case 'n':\n                db_level = 0;\n                break;\n              case 'p':\n                db_level |= DB_PRINT;\n                break;\n              case 'v':\n                db_level |= DB_BASIC | DB_VERBOSE;\n                break;\n              case 'w':\n                db_level |= DB_WHY;\n                break;\n              default:\n                OS (fatal, NILF,\n                    _(\"unknown debug level specification '%s'\"), p);\n              }\n\n            while (*(++p) != '\\0')\n              if (*p == ',' || *p == ' ')\n                {\n                  ++p;\n                  break;\n                }\n\n            if (*p == '\\0')\n              break;\n          }\n      }\n\n  if (db_level)\n    verify_flag = 1;\n\n  if (! db_level)\n    debug_flag = 0;\n}\n\nstatic void\ndecode_output_sync_flags (void)\n{\n#ifdef NO_OUTPUT_SYNC\n  output_sync = OUTPUT_SYNC_NONE;\n#else\n  if (output_sync_option)\n    {\n      if (streq (output_sync_option, \"none\"))\n        output_sync = OUTPUT_SYNC_NONE;\n      else if (streq (output_sync_option, \"line\"))\n        output_sync = OUTPUT_SYNC_LINE;\n      else if (streq (output_sync_option, \"target\"))\n        output_sync = OUTPUT_SYNC_TARGET;\n      else if (streq (output_sync_option, \"recurse\"))\n        output_sync = OUTPUT_SYNC_RECURSE;\n      else\n        OS (fatal, NILF,\n            _(\"unknown output-sync type '%s'\"), output_sync_option);\n    }\n\n  if (sync_mutex)\n    osync_parse_mutex (sync_mutex);\n#endif\n}\n\n/* Print a nice usage method and exit.  */\n\nstatic void NORETURN\nprint_usage (int bad)\n{\n  const char *const *cpp;\n  FILE *usageto;\n\n  if (print_version_flag)\n    {\n      print_version ();\n      fputs (\"\\n\", stdout);\n    }\n\n  usageto = bad ? stderr : stdout;\n\n  fprintf (usageto, _(\"Usage: %s [options] [target] ...\\n\"), program);\n\n  for (cpp = usage; *cpp; ++cpp)\n    fputs (_(*cpp), usageto);\n\n  if (!remote_description || *remote_description == '\\0')\n    fprintf (usageto, _(\"\\nThis program built for %s\\n\"), make_host);\n  else\n    fprintf (usageto, _(\"\\nThis program built for %s (%s)\\n\"),\n             make_host, remote_description);\n\n  fprintf (usageto, _(\"Report bugs to <bug-make@gnu.org>\\n\"));\n\n  die (bad ? MAKE_FAILURE : MAKE_SUCCESS);\n}\n\n#if MK_OS_W32\n\n/*\n * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture\n * exception and print it to stderr instead.\n *\n * If ! DB_VERBOSE, just print a simple message and exit.\n * If DB_VERBOSE, print a more verbose message.\n * If compiled for DEBUG, let exception pass through to GUI so that\n *   debuggers can attach.\n */\nLONG WINAPI\nhandle_runtime_exceptions (struct _EXCEPTION_POINTERS *exinfo)\n{\n  PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord;\n  LPSTR cmdline = GetCommandLine ();\n  LPSTR prg = strtok (cmdline, \" \");\n  CHAR errmsg[1024];\n#ifdef USE_EVENT_LOG\n  HANDLE hEventSource;\n  LPTSTR lpszStrings[1];\n#endif\n\n  if (! ISDB (DB_VERBOSE))\n    {\n      sprintf (errmsg,\n               _(\"%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\\n\"),\n               prg, exrec->ExceptionCode, exrec->ExceptionAddress);\n      fputs (errmsg, stderr);\n      exit (255);\n    }\n\n  sprintf (errmsg,\n           _(\"\\nUnhandled exception filter called from program %s\\nExceptionCode = %lx\\nExceptionFlags = %lx\\nExceptionAddress = 0x%p\\n\"),\n           prg, exrec->ExceptionCode, exrec->ExceptionFlags,\n           exrec->ExceptionAddress);\n\n  if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION\n      && exrec->NumberParameters >= 2)\n    sprintf (&errmsg[strlen(errmsg)],\n             (exrec->ExceptionInformation[0]\n              ? _(\"Access violation: write operation at address 0x%p\\n\")\n              : _(\"Access violation: read operation at address 0x%p\\n\")),\n             (PVOID)exrec->ExceptionInformation[1]);\n\n  /* turn this on if we want to put stuff in the event log too */\n#ifdef USE_EVENT_LOG\n  hEventSource = RegisterEventSource (NULL, \"GNU Make\");\n  lpszStrings[0] = errmsg;\n\n  if (hEventSource != NULL)\n    {\n      ReportEvent (hEventSource,         /* handle of event source */\n                   EVENTLOG_ERROR_TYPE,  /* event type */\n                   0,                    /* event category */\n                   0,                    /* event ID */\n                   NULL,                 /* current user's SID */\n                   1,                    /* strings in lpszStrings */\n                   0,                    /* no bytes of raw data */\n                   lpszStrings,          /* array of error strings */\n                   NULL);                /* no raw data */\n\n      (VOID) DeregisterEventSource (hEventSource);\n    }\n#endif\n\n  /* Write the error to stderr too */\n  fputs (errmsg, stderr);\n\n#ifdef DEBUG\n  return EXCEPTION_CONTINUE_SEARCH;\n#else\n  exit (255);\n  return (255); /* not reached */\n#endif\n}\n\n/*\n * On W32 systems we don't have the luxury of a /bin directory that\n * is mapped globally to every drive mounted to the system. Since make could\n * be invoked from any drive, and we don't want to propagate /bin/sh\n * to every single drive. Allow ourselves a chance to search for\n * a value for default shell here (if the default path does not exist).\n */\n\nint\nfind_and_set_default_shell (const char *token)\n{\n  int sh_found = 0;\n  char *atoken = 0;\n  const char *search_token;\n  const char *tokend;\n  extern const char *default_shell;\n\n  if (!token)\n    search_token = default_shell;\n  else\n    search_token = atoken = xstrdup (token);\n\n  /* If the user explicitly requests the DOS cmd shell, obey that request.\n     However, make sure that's what they really want by requiring the value\n     of SHELL either equal, or have a final path element of, \"cmd\" or\n     \"cmd.exe\" case-insensitive.  */\n  tokend = search_token + strlen (search_token) - 3;\n  if (((tokend == search_token\n        || (tokend > search_token && ISDIRSEP (tokend[-1])))\n       && !strcasecmp (tokend, \"cmd\"))\n      || ((tokend - 4 == search_token\n           || (tokend - 4 > search_token && ISDIRSEP (tokend[-5])))\n          && !strcasecmp (tokend - 4, \"cmd.exe\")))\n    {\n      batch_mode_shell = 1;\n      unixy_shell = 0;\n      default_shell = xstrdup (w32ify (search_token, 0));\n      DB (DB_VERBOSE, (_(\"find_and_set_shell() setting default_shell = %s\\n\"),\n                       default_shell));\n      sh_found = 1;\n    }\n  else if (!no_default_sh_exe\n           && (token == NULL || !strcmp (search_token, default_shell)))\n    {\n      /* no new information, path already set or known */\n      sh_found = 1;\n    }\n  else if (_access (search_token, 0) == 0)\n    {\n      /* search token path was found */\n      default_shell = xstrdup (w32ify (search_token, 0));\n      DB (DB_VERBOSE, (_(\"find_and_set_shell() setting default_shell = %s\\n\"),\n                       default_shell));\n      sh_found = 1;\n    }\n  else\n    {\n      char *p;\n      struct variable *v = lookup_variable (STRING_SIZE_TUPLE (\"PATH\"));\n\n      /* Search Path for shell */\n      if (v && v->value)\n        {\n          char *ep;\n\n          p  = v->value;\n          ep = strchr (p, PATH_SEPARATOR_CHAR);\n\n          while (ep && *ep)\n            {\n              PATH_VAR (sh_path);\n\n              *ep = '\\0';\n\n              snprintf (sh_path, GET_PATH_MAX, \"%s/%s\", p, search_token);\n              if (_access (sh_path, 0) == 0)\n                {\n                  default_shell = xstrdup (w32ify (sh_path, 0));\n                  sh_found = 1;\n                  *ep = PATH_SEPARATOR_CHAR;\n\n                  /* terminate loop */\n                  p += strlen (p);\n                }\n              else\n                {\n                  *ep = PATH_SEPARATOR_CHAR;\n                  p = ++ep;\n                }\n\n              ep = strchr (p, PATH_SEPARATOR_CHAR);\n            }\n\n          /* be sure to check last element of Path */\n          if (p && *p)\n            {\n              PATH_VAR (sh_path);\n              snprintf (sh_path, GET_PATH_MAX, \"%s/%s\", p, search_token);\n              if (_access (sh_path, 0) == 0)\n                {\n                  default_shell = xstrdup (w32ify (sh_path, 0));\n                  sh_found = 1;\n                }\n            }\n\n          if (sh_found)\n            DB (DB_VERBOSE,\n                (_(\"find_and_set_shell() path search set default_shell = %s\\n\"),\n                 default_shell));\n        }\n    }\n\n  /* naive test */\n  if (!unixy_shell && sh_found\n      && (strstr (default_shell, \"sh\") || strstr (default_shell, \"SH\")))\n    {\n      unixy_shell = 1;\n      batch_mode_shell = 0;\n    }\n\n#ifdef BATCH_MODE_ONLY_SHELL\n  batch_mode_shell = 1;\n#endif\n\n  free (atoken);\n\n  return (sh_found);\n}\n#endif  /* MK_OS_W32 */\n\n#if MK_OS_DOS\nstatic void\nmsdos_return_to_initial_directory (void)\n{\n  if (directory_before_chdir)\n    chdir (directory_before_chdir);\n}\n#endif  /* MK_OS_DOS */\n\nstatic void\nreset_jobserver (void)\n{\n  jobserver_clear ();\n  free (jobserver_auth);\n  jobserver_auth = NULL;\n}\n\nvoid\ntemp_stdin_unlink ()\n{\n  /* This function is called from a signal handler.  Keep async-signal-safe.\n     If there is a temp file from reading from stdin, get rid of it.  */\n  if (stdin_offset >= 0)\n    {\n      const char *nm = makefiles->list[stdin_offset];\n      int r = 0;\n\n      stdin_offset = -1;\n      EINTRLOOP(r, unlink (nm));\n      if (r < 0 && errno != ENOENT && !handling_fatal_signal)\n        perror_with_name (_(\"unlink (temporary file): \"), nm);\n    }\n}\n\n#ifdef MK_OS_ZOS\nextern char **environ;\n#endif\n\n#if defined(MK_OS_ZOS)\nint\nmain (int argc, char **argv)\n#else\nint\nmain (int argc, char **argv, char **envp)\n#endif\n{\n  int makefile_status = MAKE_SUCCESS;\n  struct goaldep *read_files;\n  PATH_VAR (current_directory);\n  unsigned int restarts = 0;\n  unsigned int syncing = 0;\n  int argv_slots;  /* The jobslot info we got from our parent process.  */\n#if MK_OS_W32\n  const char *unix_path = NULL;\n  const char *windows32_path = NULL;\n\n  SetUnhandledExceptionFilter (handle_runtime_exceptions);\n\n  /* start off assuming we have no shell */\n  unixy_shell = 0;\n  no_default_sh_exe = 1;\n#endif\n\n  initialize_variable_output ();\n\n  /* Useful for attaching debuggers, etc.  */\n  SPIN (\"main-entry\");\n\n#ifdef HAVE_ATEXIT\n  if (ANY_SET (check_io_state (), IO_STDOUT_OK))\n    atexit (close_stdout);\n#endif\n\n  output_init (&make_sync);\n\n  initialize_stopchar_map ();\n\n  warn_init ();\n\n#ifdef SET_STACK_SIZE\n /* Get rid of any avoidable limit on stack size.  */\n  {\n    struct rlimit rlim;\n\n    /* Set the stack limit huge so that alloca does not fail.  */\n    if (getrlimit (RLIMIT_STACK, &rlim) == 0\n        && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max)\n      {\n        stack_limit = rlim;\n        rlim.rlim_cur = rlim.rlim_max;\n        setrlimit (RLIMIT_STACK, &rlim);\n      }\n    else\n      stack_limit.rlim_cur = 0;\n  }\n#endif\n\n  /* Needed for OS/2 */\n  initialize_main (&argc, &argv);\n\n#ifdef MAKE_MAINTAINER_MODE\n  /* In maintainer mode we always enable verification.  */\n  verify_flag = 1;\n#endif\n\n#if MK_OS_DOS && !defined (_POSIX_SOURCE)\n  /* Request the most powerful version of 'system', to\n     make up for the dumb default shell.  */\n  __system_flags = (__system_redirect\n                    | __system_use_shell\n                    | __system_allow_multiple_cmds\n                    | __system_allow_long_cmds\n                    | __system_handle_null_commands\n                    | __system_emulate_chdir);\n\n#endif\n\n  /* Set up gettext/internationalization support.  */\n  setlocale (LC_ALL, \"\");\n  /* The cast to void shuts up compiler warnings on systems that\n     disable NLS.  */\n  (void)bindtextdomain (PACKAGE, LOCALEDIR);\n  (void)textdomain (PACKAGE);\n\n#ifdef POSIX\n  sigemptyset (&fatal_signal_set);\n#define ADD_SIG(sig)    sigaddset (&fatal_signal_set, sig)\n#else\n#ifdef HAVE_SIGSETMASK\n  fatal_signal_mask = 0;\n#define ADD_SIG(sig)    fatal_signal_mask |= sigmask (sig)\n#else\n#define ADD_SIG(sig)    (void)sig\n#endif\n#endif\n\n#define FATAL_SIG(sig)                                                        \\\n  if (bsd_signal (sig, fatal_error_signal) == SIG_IGN)                        \\\n    bsd_signal (sig, SIG_IGN);                                                \\\n  else                                                                        \\\n    ADD_SIG (sig);\n\n#ifdef SIGHUP\n  FATAL_SIG (SIGHUP);\n#endif\n#ifdef SIGQUIT\n  FATAL_SIG (SIGQUIT);\n#endif\n#ifdef SIGPIPE\n  FATAL_SIG (SIGPIPE);\n#endif\n  FATAL_SIG (SIGINT);\n  FATAL_SIG (SIGTERM);\n\n#if MK_OS_DOS\n  /* Windows 9X delivers FP exceptions in child programs to their\n     parent!  We don't want Make to die when a child divides by zero,\n     so we work around that lossage by catching SIGFPE.  */\n  FATAL_SIG (SIGFPE);\n#endif\n\n#ifdef SIGDANGER\n  FATAL_SIG (SIGDANGER);\n#endif\n#ifdef SIGXCPU\n  FATAL_SIG (SIGXCPU);\n#endif\n#ifdef SIGXFSZ\n  FATAL_SIG (SIGXFSZ);\n#endif\n\n#undef FATAL_SIG\n\n  /* Do not ignore the child-death signal.  This must be done before\n     any children could possibly be created; otherwise, the wait\n     functions won't work on systems with the SVR4 ECHILD brain\n     damage, if our invoker is ignoring this signal.  */\n\n#ifdef HAVE_WAIT_NOHANG\n# if defined SIGCHLD\n  (void) bsd_signal (SIGCHLD, SIG_DFL);\n# endif\n# if defined SIGCLD && SIGCLD != SIGCHLD\n  (void) bsd_signal (SIGCLD, SIG_DFL);\n# endif\n#endif\n\n  output_init (NULL);\n\n  /* Figure out where this program lives.  */\n\n  if (argv[0] == 0)\n    argv[0] = (char *)\"\";\n  if (argv[0][0] == '\\0')\n    program = \"make\";\n  else\n    {\n#if defined(HAVE_DOS_PATHS)\n      const char* start = argv[0];\n\n      /* Skip an initial drive specifier if present.  */\n      if (isalpha ((unsigned char)start[0]) && start[1] == ':')\n        start += 2;\n\n      if (start[0] == '\\0')\n        program = \"make\";\n      else\n        {\n          program = start + strlen (start);\n          while (program > start && ! ISDIRSEP (program[-1]))\n            --program;\n\n          /* Remove the .exe extension if present.  */\n          {\n            size_t len = strlen (program);\n            if (len > 4 && streq (&program[len - 4], \".exe\"))\n              program = xstrndup (program, len - 4);\n          }\n        }\n#elif MK_OS_VMS\n      set_program_name (argv[0]);\n      program = program_name;\n      {\n        const char *shell;\n        char pwdbuf[256];\n        char *pwd;\n        shell = getenv (\"SHELL\");\n        if (shell != NULL)\n          vms_gnv_shell = 1;\n\n        /* Need to know if CRTL set to report UNIX paths.  Use getcwd as\n           it works on all versions of VMS. */\n        pwd = getcwd(pwdbuf, 256);\n        if (pwd[0] == '/')\n          vms_report_unix_paths = 1;\n\n        vms_use_mcr_command = get_vms_env_flag (\"GNV$MAKE_USE_MCR\", 0);\n\n        vms_always_use_cmd_file = get_vms_env_flag (\"GNV$MAKE_USE_CMD_FILE\", 0);\n\n        /* Legacy behavior is on VMS is older behavior that needed to be\n           changed to be compatible with standard make behavior.\n           For now only completely disable when running under a Bash shell.\n           TODO: Update VMS built in recipes and macros to not need this\n           behavior, at which time the default may change. */\n        vms_legacy_behavior = get_vms_env_flag (\"GNV$MAKE_OLD_VMS\",\n                                                !vms_gnv_shell);\n\n        /* VMS was changed to use a comma separator in the past, but that is\n           incompatible with built in functions that expect space separated\n           lists.  Allow this to be selectively turned off. */\n        vms_comma_separator = get_vms_env_flag (\"GNV$MAKE_COMMA\",\n                                                vms_legacy_behavior);\n\n        /* Some Posix shell syntax options are incompatible with VMS syntax.\n           VMS requires double quotes for strings and escapes quotes\n           differently.  When this option is active, VMS will try\n           to simulate Posix shell simulations instead of using\n           VMS DCL behavior. */\n        vms_unix_simulation = get_vms_env_flag (\"GNV$MAKE_SHELL_SIM\",\n                                                !vms_legacy_behavior);\n\n      }\n      if (need_vms_symbol () && !vms_use_mcr_command)\n        create_foreign_command (program_name, argv[0]);\n#else\n      program = strrchr (argv[0], '/');\n      if (program == 0)\n        program = argv[0];\n      else\n        ++program;\n#endif\n    }\n\n  initialize_global_hash_tables ();\n\n  /* Ensure the temp directory is set up: we don't want the first time we use\n     it to be in a forked process.  */\n  get_tmpdir ();\n\n  /* Figure out where we are.  */\n\n#if MK_OS_W32\n  if (getcwd_fs (current_directory, GET_PATH_MAX) == 0)\n#else\n  if (getcwd (current_directory, GET_PATH_MAX) == 0)\n#endif\n    {\n#ifdef HAVE_GETCWD\n      perror_with_name (\"getcwd\", \"\");\n#else\n      OS (error, NILF, \"getwd: %s\", current_directory);\n#endif\n      current_directory[0] = '\\0';\n      directory_before_chdir = 0;\n    }\n  else\n    directory_before_chdir = xstrdup (current_directory);\n\n#if MK_OS_DOS\n  /* Make sure we will return to the initial directory, come what may.  */\n  atexit (msdos_return_to_initial_directory);\n#endif\n\n  /* Initialize the special variables.  */\n  define_variable_cname (\"MAKEFLAGS\", \"\", o_default, 0)->special = 1;\n  define_variable_cname (\".VARIABLES\", \"\", o_default, 0)->special = 1;\n  /* define_variable_cname (\".TARGETS\", \"\", o_default, 0)->special = 1; */\n  define_variable_cname (\".RECIPEPREFIX\", \"\", o_default, 0)->special = 1;\n  define_variable_cname (WARNINGS_NAME, \"\", o_default, 0)->special = 1;\n  define_variable_cname (\".SHELLFLAGS\", \"-c\", o_default, 0);\n  define_variable_cname (\".LOADED\", \"\", o_default, 0);\n\n  /* Set up .FEATURES\n     Use a separate variable because define_variable_cname() is a macro and\n     some compilers (MSVC) don't like conditionals in macros.  */\n  {\n    const char *features = \"target-specific order-only second-expansion\"\n                           \" else-if shortest-stem undefine oneshell nocomment\"\n                           \" grouped-target extra-prereqs notintermediate\"\n                           \" shell-export\"\n#ifndef NO_ARCHIVES\n                           \" archives\"\n#endif\n#ifdef MAKE_JOBSERVER\n                           \" jobserver\"\n# if JOBSERVER_USE_FIFO\n                           \" jobserver-fifo\"\n# endif\n#endif\n#ifndef NO_OUTPUT_SYNC\n                           \" output-sync\"\n#endif\n#ifdef MAKE_SYMLINKS\n                           \" check-symlink\"\n#endif\n#ifdef HAVE_GUILE\n                           \" guile\"\n#endif\n#ifdef MAKE_LOAD\n                           \" load\"\n#endif\n#ifdef HAVE_DOS_PATHS\n                           \" dospaths\"\n#endif\n#ifdef MAKE_MAINTAINER_MODE\n                           \" maintainer\"\n#endif\n#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_MEMORY__)\n                           \" sanitize\"\n#endif\n                           ;\n\n    define_variable_cname (\".FEATURES\", features, o_default, 0);\n  }\n\n  /* Configure GNU Guile support */\n  guile_gmake_setup (NILF);\n\n  /* Read in variables from the environment.  It is important that this be\n     done before $(MAKE) is figured out so its definitions will not be\n     from the environment.  */\n\n#ifdef MK_OS_ZOS\n  char **envp = environ;\n#endif\n\n  {\n    unsigned int i;\n\n    for (i = 0; envp[i] != 0; ++i)\n      {\n        struct variable *v;\n        const char *ep = envp[i];\n        /* By default, export all variables culled from the environment.  */\n        enum variable_export export = v_export;\n        size_t len;\n\n        while (! STOP_SET (*ep, MAP_EQUALS|MAP_NUL))\n          ++ep;\n\n        /* If there's no equals sign it's a malformed environment.  Ignore.  */\n        if (*ep == '\\0')\n          continue;\n\n#if MK_OS_W32\n        if (!unix_path && strneq (envp[i], \"PATH=\", 5))\n          unix_path = ep+1;\n        else if (!strnicmp (envp[i], \"Path=\", 5))\n          {\n            if (!windows32_path)\n              windows32_path = ep+1;\n            /* PATH gets defined after the loop exits.  */\n            continue;\n          }\n#endif\n\n        /* Length of the variable name, and skip the '='.  */\n        len = ep++ - envp[i];\n\n        /* If this is MAKE_RESTARTS, check to see if the \"already printed\n           the enter statement\" flag is set.  */\n        if (len == 13 && memcmp (envp[i], \"MAKE_RESTARTS\", CSTRLEN (\"MAKE_RESTARTS\")) == 0)\n          {\n            if (*ep == '-')\n              {\n                OUTPUT_TRACED ();\n                ++ep;\n              }\n            restarts = make_toui (ep, NULL);\n            export = v_noexport;\n          }\n\n        v = define_variable (envp[i], len, ep, o_env, 1);\n\n        /* POSIX says the value of SHELL set in the makefile won't change the\n           value of SHELL given to subprocesses.  */\n        if (streq (v->name, \"SHELL\"))\n          {\n#if !MK_OS_DOS\n            export = v_noexport;\n#endif\n            shell_var.name = xstrdup (\"SHELL\");\n            shell_var.length = 5;\n            shell_var.value = xstrdup (ep);\n          }\n\n        v->export = export;\n      }\n  }\n#if MK_OS_W32\n  /* If we didn't find a correctly spelled PATH we define PATH as\n   * either the first misspelled value or an empty string\n   */\n  if (!unix_path)\n    define_variable_cname (\"PATH\", windows32_path ? windows32_path : \"\",\n                           o_env, 1)->export = v_export;\n#endif\n\n  /* Decode the switches.  */\n  if (lookup_variable (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME)))\n    {\n      decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME), o_command);\n\n      /* Clear GNUMAKEFLAGS to avoid duplication.  */\n      define_variable_cname (GNUMAKEFLAGS_NAME, \"\", o_env, 0);\n    }\n\n   /* Set MAKEFLAGS's origin to command line: in submakes MAKEFLAGS will carry\n      command line switches.  This causes env variable MAKEFLAGS to beat\n      makefile modifications to MAKEFLAGS.  */\n  decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME), o_command);\n\n#if 0\n  /* People write things like:\n        MFLAGS=\"CC=gcc -pipe\" \"CFLAGS=-g\"\n     and we set the -p, -i and -e switches.  Doesn't seem quite right.  */\n  decode_env_switches (STRING_SIZE_TUPLE (\"MFLAGS\"));\n#endif\n\n  /* In output sync mode we need to sync any output generated by reading the\n     makefiles, such as in $(info ...) or stderr from $(shell ...) etc.  */\n\n  syncing = make_sync.syncout = (output_sync == OUTPUT_SYNC_LINE\n                                 || output_sync == OUTPUT_SYNC_TARGET);\n  OUTPUT_SET (&make_sync);\n\n  /* Parse the command line options.  Remember the job slots set this way.  */\n  {\n    int env_slots = arg_job_slots;\n    arg_job_slots = INVALID_JOB_SLOTS;\n\n    decode_switches (argc, (const char **)argv, o_command);\n    argv_slots = arg_job_slots;\n\n    if (arg_job_slots == INVALID_JOB_SLOTS)\n      arg_job_slots = env_slots;\n  }\n\n  if (print_usage_flag)\n    print_usage (0);\n\n  /* Print version information, and exit.  */\n  if (print_version_flag)\n    {\n      print_version ();\n      die (MAKE_SUCCESS);\n    }\n\n  /* Now that we know we'll be running, force stdout to be line-buffered.  */\n#ifdef HAVE_SETVBUF\n  setvbuf (stdout, 0, _IOLBF, BUFSIZ);\n#elif HAVE_SETLINEBUF\n  setlinebuf (stdout);\n#endif\n\n  /* Handle shuffle mode argument.  */\n  if (shuffle_mode)\n    {\n      const char *effective_mode;\n      shuffle_set_mode (shuffle_mode);\n\n      /* Write fixed seed back to argument list to propagate mode and\n         fixed seed to child $(MAKE) runs.  */\n      free (shuffle_mode);\n      effective_mode = shuffle_get_mode ();\n      if (effective_mode)\n        shuffle_mode = xstrdup (effective_mode);\n      else\n        shuffle_mode = NULL;\n    }\n\n  /* Set a variable specifying whether stdout/stdin is hooked to a TTY.  */\n#ifdef HAVE_ISATTY\n  if (isatty (fileno (stdout)))\n    if (! lookup_variable (STRING_SIZE_TUPLE (\"MAKE_TERMOUT\")))\n      {\n        const char *tty = TTYNAME (fileno (stdout));\n        define_variable_cname (\"MAKE_TERMOUT\", tty ? tty : DEFAULT_TTYNAME,\n                               o_default, 0)->export = v_export;\n      }\n  if (isatty (fileno (stderr)))\n    if (! lookup_variable (STRING_SIZE_TUPLE (\"MAKE_TERMERR\")))\n      {\n        const char *tty = TTYNAME (fileno (stderr));\n        define_variable_cname (\"MAKE_TERMERR\", tty ? tty : DEFAULT_TTYNAME,\n                               o_default, 0)->export = v_export;\n      }\n#endif\n\n  /* Reset in case the switches changed our minds.  */\n  syncing = (output_sync == OUTPUT_SYNC_LINE\n             || output_sync == OUTPUT_SYNC_TARGET);\n\n  if (make_sync.syncout && ! syncing)\n    output_close (&make_sync);\n\n  make_sync.syncout = syncing;\n  OUTPUT_SET (&make_sync);\n\n  /* Figure out the level of recursion.  */\n  {\n    struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));\n    if (v && v->value[0] != '\\0' && v->value[0] != '-')\n      makelevel = make_toui (v->value, NULL);\n    else\n      makelevel = 0;\n  }\n\n  /* Set always_make_flag if -B was given and we've not restarted already.  */\n  always_make_flag = always_make_set && (restarts == 0);\n\n  /* If -R was given, set -r too (doesn't make sense otherwise!)  */\n  if (no_builtin_variables_flag)\n    no_builtin_rules_flag = 1;\n\n  if (ISDB (DB_BASIC))\n    {\n      print_version ();\n\n      /* Flush stdout so the user doesn't have to wait to see the\n         version information while make thinks about things.  */\n      fflush (stdout);\n    }\n\n#if !MK_OS_VMS\n  /* Set the \"MAKE_COMMAND\" variable to the name we were invoked with.\n     (If it is a relative pathname with a slash, prepend our directory name\n     so the result will run the same program regardless of the current dir.\n     If it is a name with no slash, we can only hope that PATH did not\n     find it in the current directory.)  */\n#if MK_OS_W32\n  /*\n   * Convert from backslashes to forward slashes for\n   * programs like sh which don't like them. Shouldn't\n   * matter if the path is one way or the other for\n   * CreateProcess().\n   */\n  if (strpbrk (argv[0], \"/:\\\\\") || strstr (argv[0], \"..\")\n      || strneq (argv[0], \"//\", 2))\n    argv[0] = xstrdup (w32ify (argv[0], 1));\n#elif MK_OS_DOS || MK_OS_OS2\n  if (strchr (argv[0], '\\\\'))\n    {\n      char *p;\n\n      argv[0] = xstrdup (argv[0]);\n      for (p = argv[0]; *p; p++)\n        if (*p == '\\\\')\n          *p = '/';\n    }\n  /* If argv[0] is not in absolute form, prepend the current\n     directory.  This can happen when Make is invoked by another DJGPP\n     program that uses a non-absolute name.  */\n  if (current_directory[0] != '\\0'\n      && argv[0] != 0\n      && (argv[0][0] != '/' && (argv[0][0] == '\\0' || argv[0][1] != ':'))\n# if MK_OS_OS2\n      /* do not prepend cwd if argv[0] contains no '/', e.g. \"make\" */\n      && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\\\') != 0)\n# endif\n      )\n    argv[0] = xstrdup (concat (3, current_directory, \"/\", argv[0]));\n#else  /* !MK_OS_DOS */\n  if (current_directory[0] != '\\0'\n      && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0\n#ifdef HAVE_DOS_PATHS\n      && (argv[0][0] != '\\\\' && (!argv[0][0] || argv[0][1] != ':'))\n      && strchr (argv[0], '\\\\') != 0\n#endif\n      )\n    argv[0] = xstrdup (concat (3, current_directory, \"/\", argv[0]));\n#endif /* !MK_OS_DOS */\n#endif /* MK_OS_W32 */\n\n  /* We may move, but until we do, here we are.  */\n  starting_directory = current_directory;\n\n  /* If there were -C flags, move ourselves about.  */\n  if (directories != 0)\n    {\n      unsigned int i;\n      for (i = 0; directories->list[i] != 0; ++i)\n        {\n          const char *dir = directories->list[i];\n#if MK_OS_W32\n          /* Windows32 chdir() doesn't work if the directory has a trailing '/'\n             But allow -C/ just in case someone wants that.  */\n          {\n            char *p = (char *)dir + strlen (dir) - 1;\n            while (p > dir && ISDIRSEP (p[0]))\n              --p;\n            p[1] = '\\0';\n          }\n#endif\n          if (chdir (dir) < 0)\n            pfatal_with_name (dir);\n        }\n    }\n\n#if MK_OS_W32\n  /*\n   * THIS BLOCK OF CODE MUST COME AFTER chdir() CALL ABOVE IN ORDER\n   * TO NOT CONFUSE THE DEPENDENCY CHECKING CODE IN implicit.c.\n   *\n   * The functions in dir.c can incorrectly cache information for \".\"\n   * before we have changed directory and this can cause file\n   * lookups to fail because the current directory (.) was pointing\n   * at the wrong place when it was first evaluated.\n   */\n  no_default_sh_exe = !find_and_set_default_shell (NULL);\n#endif /* MK_OS_W32 */\n\n  /* If we chdir'ed, figure out where we are now.  */\n  if (directories)\n    {\n#if MK_OS_W32\n      if (getcwd_fs (current_directory, GET_PATH_MAX) == 0)\n#else\n      if (getcwd (current_directory, GET_PATH_MAX) == 0)\n#endif\n        {\n#ifdef HAVE_GETCWD\n          perror_with_name (\"getcwd\", \"\");\n#else\n          OS (error, NILF, \"getwd: %s\", current_directory);\n#endif\n          starting_directory = 0;\n        }\n      else\n        starting_directory = current_directory;\n    }\n\n  define_variable_cname (\"CURDIR\", current_directory, o_file, 0);\n\n  /* Construct the list of include directories to search.\n     This will check for existence so it must be done after chdir.  */\n  construct_include_path (include_dirs ? include_dirs->list : NULL);\n\n  /* Validate the arg_job_slots configuration before we define MAKEFLAGS so\n     users get an accurate value in their makefiles.\n     At this point arg_job_slots is the argv setting, if there is one, else\n     the MAKEFLAGS env setting, if there is one.  */\n\n  if (jobserver_auth)\n    {\n      /* We're a child in an existing jobserver group.  */\n      if (argv_slots == INVALID_JOB_SLOTS)\n        {\n          /* There's no -j option on the command line: check authorization.  */\n          if (jobserver_parse_auth (jobserver_auth))\n            /* Success!  Use the jobserver.  */\n            goto job_setup_complete;\n\n          /* Oops: we have jobserver-auth but it's invalid :(.  */\n          O (error, NILF, _(\"warning: jobserver unavailable: using -j1 (add '+' to parent make rule)\"));\n          arg_job_slots = 1;\n        }\n\n      /* The user provided a -j setting on the command line so use it: we're\n         the master make of a new jobserver group.  */\n      else if (!restarts && argv_slots != 1)\n        ON (error, NILF,\n            _(\"warning: -j%d forced in submake: resetting jobserver mode\"),\n            argv_slots);\n\n      /* We can't use our parent's jobserver, so reset.  */\n      reset_jobserver ();\n    }\n\n job_setup_complete:\n\n  /* The extra indirection through $(MAKE_COMMAND) is done\n     for hysterical raisins.  */\n\n#if MK_OS_VMS\n  if (vms_use_mcr_command)\n    define_variable_cname (\"MAKE_COMMAND\", vms_command (argv[0]), o_default, 0);\n  else\n    define_variable_cname (\"MAKE_COMMAND\", program, o_default, 0);\n#else\n  define_variable_cname (\"MAKE_COMMAND\", argv[0], o_default, 0);\n#endif\n  define_variable_cname (\"MAKE\", \"$(MAKE_COMMAND)\", o_default, 1);\n\n  if (command_variables != 0)\n    {\n      struct command_variable *cv;\n      struct variable *v;\n      size_t len = 0;\n      char *value, *p;\n\n      /* Figure out how much space will be taken up by the command-line\n         variable definitions.  */\n      for (cv = command_variables; cv != 0; cv = cv->next)\n        {\n          v = cv->variable;\n          len += 2 * strlen (v->name);\n          if (! v->recursive)\n            ++len;\n          ++len;\n          len += 2 * strlen (v->value);\n          ++len;\n        }\n\n      /* Now allocate a buffer big enough and fill it.  */\n      p = value = xmalloc (len);\n      for (cv = command_variables; cv != 0; cv = cv->next)\n        {\n          v = cv->variable;\n          p = quote_for_env (p, v->name);\n          if (! v->recursive)\n            *p++ = ':';\n          *p++ = '=';\n          p = quote_for_env (p, v->value);\n          *p++ = ' ';\n        }\n      p[-1] = '\\0';             /* Kill the final space and terminate.  */\n\n      /* Define an unchangeable variable with a name that no POSIX.2\n         makefile could validly use for its own variable.  */\n      define_variable_cname (\"-*-command-variables-*-\", value, o_automatic, 0);\n      free (value);\n\n      /* Define the variable; this will not override any user definition.\n         Normally a reference to this variable is written into the value of\n         MAKEFLAGS, allowing the user to override this value to affect the\n         exported value of MAKEFLAGS.  In POSIX-pedantic mode, we cannot\n         allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so\n         a reference to this hidden variable is written instead. */\n      define_variable_cname (\"MAKEOVERRIDES\", \"${-*-command-variables-*-}\",\n                             o_default, 1);\n#if MK_OS_VMS\n      vms_export_dcl_symbol (\"MAKEOVERRIDES\", \"${-*-command-variables-*-}\");\n#endif\n    }\n\n  /* Read any stdin makefiles into temporary files.  */\n\n  if (makefiles != 0)\n    {\n      unsigned int i;\n      for (i = 0; i < makefiles->idx; ++i)\n        if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\\0')\n          {\n            /* This makefile is standard input.  Since we may re-exec\n               and thus re-read the makefiles, we read standard input\n               into a temporary file and read from that.  */\n            FILE *outfile;\n            char *newnm;\n\n            if (stdin_offset >= 0)\n              O (fatal, NILF,\n                 _(\"Makefile from standard input specified twice\"));\n\n            outfile = get_tmpfile (&newnm);\n            if (!outfile)\n              O (fatal, NILF,\n                 _(\"cannot store makefile from stdin to a temporary file\"));\n\n            while (!feof (stdin) && ! ferror (stdin))\n              {\n                char buf[2048];\n                size_t n = fread (buf, 1, sizeof (buf), stdin);\n                if (n > 0 && fwrite (buf, 1, n, outfile) != n)\n                  OSS (fatal, NILF,\n                       _(\"fwrite: temporary file %s: %s\"), newnm, strerror (errno));\n              }\n            fclose (outfile);\n\n            /* Replace the name that read_all_makefiles will see with the name\n               of the temporary file.  */\n            makefiles->list[i] = strcache_add (newnm);\n            stdin_offset = i;\n\n            free (newnm);\n          }\n    }\n\n  /* Make sure the temporary file is never considered updated.  */\n  if (stdin_offset >= 0)\n    {\n      struct file *f = enter_file (makefiles->list[stdin_offset]);\n      f->updated = 1;\n      f->update_status = us_success;\n      f->command_state = cs_finished;\n      /* Can't be intermediate, or it'll be removed before make re-exec.  */\n      f->intermediate = 0;\n      f->dontcare = 0;\n      /* Avoid re-exec due to stdin temp file timestamps.  */\n      f->last_mtime = f->mtime_before_update = f_mtime (f, 0);\n    }\n\n#if !MK_OS_OS2 /* Don't use a SIGCHLD handler for OS/2 */\n#if !defined(HAVE_WAIT_NOHANG) || defined(MAKE_JOBSERVER)\n  /* Set up to handle children dying.  This must be done before\n     reading in the makefiles so that 'shell' function calls will work.\n\n     If we don't have a hanging wait we have to fall back to old, broken\n     functionality here and rely on the signal handler and counting\n     children.\n\n     If we're using the jobs pipe we need a signal handler so that SIGCHLD is\n     not ignored; we need it to interrupt the read(2) of the jobserver pipe if\n     we're waiting for a token.\n\n     If none of these are true, we don't need a signal handler at all.  */\n  {\n# if defined SIGCHLD\n    bsd_signal (SIGCHLD, child_handler);\n# endif\n# if defined SIGCLD && SIGCLD != SIGCHLD\n    bsd_signal (SIGCLD, child_handler);\n# endif\n  }\n\n#if defined(HAVE_PSELECT) && !defined(MK_OS_ZOS)\n  /* If we have pselect() then we need to block SIGCHLD so it's deferred.  */\n  {\n    sigset_t block;\n    sigemptyset (&block);\n    sigaddset (&block, SIGCHLD);\n    if (sigprocmask (SIG_SETMASK, &block, NULL) < 0)\n      pfatal_with_name (\"sigprocmask(SIG_SETMASK, SIGCHLD)\");\n  }\n#endif\n\n#endif\n#endif\n\n  /* Let the user send us SIGUSR1 to toggle the -d flag during the run.  */\n#ifdef SIGUSR1\n  bsd_signal (SIGUSR1, debug_signal_handler);\n#endif\n\n  /* Define the initial list of suffixes for old-style rules.  */\n  set_default_suffixes ();\n\n  /* Define some internal and special variables.  */\n  define_automatic_variables ();\n\n  /* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see.\n     Initialize it to be exported but allow the makefile to reset it.  */\n  define_makeflags (0)->export = v_export;\n\n  /* Define the default variables.  */\n  define_default_variables ();\n\n  default_file = enter_file (strcache_add (\".DEFAULT\"));\n\n  default_goal_var = define_variable_cname (\".DEFAULT_GOAL\", \"\", o_file, 0);\n\n  /* Evaluate all strings provided with --eval.\n     Also set up the $(-*-eval-flags-*-) variable.  */\n\n  if (eval_strings)\n    {\n      char *p, *endp, *value;\n      unsigned int i;\n      size_t len = (CSTRLEN (\"--eval=\") + 1) * eval_strings->idx;\n\n      for (i = 0; i < eval_strings->idx; ++i)\n        {\n          p = xstrdup (eval_strings->list[i]);\n          len += 2 * strlen (p);\n          eval_buffer (p, NULL);\n          free (p);\n        }\n\n      p = endp = value = xmalloc (len);\n      for (i = 0; i < eval_strings->idx; ++i)\n        {\n          p = stpcpy (p, \"--eval=\");\n          p = quote_for_env (p, eval_strings->list[i]);\n          endp = p++;\n          *endp = ' ';\n        }\n      *endp = '\\0';\n\n      define_variable_cname (\"-*-eval-flags-*-\", value, o_automatic, 0);\n      free (value);\n    }\n\n  {\n    int old_arg_job_slots = arg_job_slots;\n    old_builtin_rules_flag = no_builtin_rules_flag;\n    old_builtin_variables_flag = no_builtin_variables_flag;\n\n    /* Read all the makefiles.  */\n    read_files = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);\n\n    arg_job_slots = INVALID_JOB_SLOTS;\n\n    /* Decode switches again, for variables set by the makefile.  */\n    decode_env_switches (STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME), o_env);\n\n    /* Clear GNUMAKEFLAGS to avoid duplication.  */\n    define_variable_cname (GNUMAKEFLAGS_NAME, \"\", o_override, 0);\n\n    decode_env_switches (STRING_SIZE_TUPLE (MAKEFLAGS_NAME), o_env);\n#if 0\n    decode_env_switches (STRING_SIZE_TUPLE (\"MFLAGS\"));\n#endif\n\n    /* If -j is not set in the makefile, or it was set on the command line,\n       reset to use the previous value.  */\n    if (arg_job_slots == INVALID_JOB_SLOTS || argv_slots != INVALID_JOB_SLOTS)\n      arg_job_slots = old_arg_job_slots;\n\n    else if (jobserver_auth && arg_job_slots != old_arg_job_slots)\n      {\n        /* Makefile MAKEFLAGS set -j, but we already have a jobserver.\n           Make us the master of a new jobserver group.  */\n        if (!restarts)\n          ON (error, NILF,\n              _(\"warning: -j%d forced in makefile: resetting jobserver mode\"),\n              arg_job_slots);\n\n        /* We can't use our parent's jobserver, so reset.  */\n        reset_jobserver ();\n      }\n\n    /* Reset in case the switches changed our mind.  */\n    syncing = (output_sync == OUTPUT_SYNC_LINE\n               || output_sync == OUTPUT_SYNC_TARGET);\n\n    if (make_sync.syncout && ! syncing)\n      output_close (&make_sync);\n\n    make_sync.syncout = syncing;\n    OUTPUT_SET (&make_sync);\n\n    disable_builtins ();\n  }\n\n#if MK_OS_W32\n  /* look one last time after reading all Makefiles */\n  if (no_default_sh_exe)\n    no_default_sh_exe = !find_and_set_default_shell (NULL);\n#endif /* MK_OS_W32 */\n\n#if MK_OS_DOS || MK_OS_OS2 || MK_OS_VMS\n  /* We need to know what kind of shell we will be using.  */\n  {\n    extern int _is_unixy_shell (const char *_path);\n    struct variable *shv = lookup_variable (STRING_SIZE_TUPLE (\"SHELL\"));\n    extern int unixy_shell;\n    extern const char *default_shell;\n\n    if (shv && *shv->value)\n      {\n        char *shell_path = recursively_expand (shv);\n\n        if (shell_path && _is_unixy_shell (shell_path))\n          unixy_shell = 1;\n        else\n          unixy_shell = 0;\n        if (shell_path)\n          default_shell = shell_path;\n      }\n  }\n#endif /* MK_OS_DOS || MK_OS_OS2 */\n\n  /* Final jobserver configuration.\n\n     If we have jobserver_auth then we are a client in an existing jobserver\n     group, that's already been verified OK above.  If we don't have\n     jobserver_auth and jobserver is enabled, then start a new jobserver.\n\n     arg_job_slots = INVALID_JOB_SLOTS if we don't want -j in MAKEFLAGS\n\n     arg_job_slots = # of jobs of parallelism\n\n     job_slots = 0 for no limits on jobs, or when limiting via jobserver.\n\n     job_slots = 1 for standard non-parallel mode.\n\n     job_slots >1 for old-style parallelism without jobservers.  */\n\n  if (jobserver_auth)\n    job_slots = 0;\n  else if (arg_job_slots == INVALID_JOB_SLOTS)\n    job_slots = 1;\n  else\n    job_slots = arg_job_slots;\n\n#if MK_OS_DOS || MK_OS_OS2 || MK_OS_VMS\n  if (job_slots != 1\n# if MK_OS_OS2\n      && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */\n# endif\n      )\n    {\n      O (error, NILF,\n         _(\"parallel jobs (-j) are not supported on this platform\"));\n      O (error, NILF, _(\"resetting to single job (-j1) mode\"));\n      arg_job_slots = INVALID_JOB_SLOTS;\n      job_slots = 1;\n    }\n#endif\n\n  /* If we have >1 slot at this point, then we're a top-level make.\n     Set up the jobserver.\n\n     Every make assumes that it always has one job it can run.  For the\n     submakes it's the token they were given by their parent.  For the top\n     make, we just subtract one from the number the user wants.  */\n\n  if (job_slots > 1 && jobserver_setup (job_slots - 1, jobserver_style))\n    {\n      /* Fill in the jobserver_auth for our children.  */\n      jobserver_auth = jobserver_get_auth ();\n\n      if (jobserver_auth)\n        {\n          /* We're using the jobserver so set job_slots to 0.  */\n          master_job_slots = job_slots;\n          job_slots = 0;\n        }\n    }\n\n  /* If we're not using parallel jobs, then we don't need output sync.\n     This is so people can enable output sync in GNUMAKEFLAGS or similar, but\n     not have it take effect unless parallel builds are enabled.  */\n  if (syncing && job_slots == 1)\n    {\n      OUTPUT_UNSET ();\n      output_close (&make_sync);\n      syncing = 0;\n      output_sync = OUTPUT_SYNC_NONE;\n    }\n\n  if (syncing)\n    {\n      /* If there is no mutex we're the base: create one.  Else parse it.  */\n      if (!sync_mutex)\n        {\n          osync_setup ();\n          sync_mutex = osync_get_mutex ();\n        }\n      else if (!osync_parse_mutex (sync_mutex))\n        {\n          /* Parsing failed; continue without output sync.  */\n          osync_clear ();\n          free (sync_mutex);\n          sync_mutex = NULL;\n          syncing = 0;\n        }\n    }\n\n  if (jobserver_auth)\n    DB (DB_VERBOSE|DB_JOBS, (_(\"Using jobserver controller %s\\n\"), jobserver_auth));\n  if (sync_mutex)\n    DB (DB_VERBOSE, (_(\"Using output-sync mutex %s\\n\"), sync_mutex));\n\n#ifndef MAKE_SYMLINKS\n  if (check_symlink_flag)\n    {\n      O (error, NILF, _(\"symbolic links not supported: disabling -L\"));\n      check_symlink_flag = 0;\n    }\n#endif\n\n  /* Set up MAKEFLAGS and MFLAGS again, so they will be right.  */\n\n  define_makeflags (0);\n\n  /* Make each 'struct goaldep' point at the 'struct file' for the file\n     depended on.  Also do magic for special targets.  */\n\n  snap_deps ();\n\n  /* Define the file rules for the built-in suffix rules.  These will later\n     be converted into pattern rules.  */\n\n  install_default_suffix_rules ();\n\n  /* Convert old-style suffix rules to pattern rules.  It is important to\n     do this before installing the built-in pattern rules below, so that\n     makefile-specified suffix rules take precedence over built-in pattern\n     rules.  */\n\n  convert_to_pattern ();\n\n  /* Install the default implicit pattern rules.\n     This used to be done before reading the makefiles.\n     But in that case, built-in pattern rules were in the chain\n     before user-defined ones, so they matched first.  */\n\n  install_default_implicit_rules ();\n\n  /* Compute implicit rule limits and do magic for pattern rules.  */\n\n  snap_implicit_rules ();\n\n  /* Construct the listings of directories in VPATH lists.  */\n\n  build_vpath_lists ();\n\n  /* Mark files given with -o flags as very old and as having been updated\n     already, and files given with -W flags as brand new (time-stamp as far\n     as possible into the future).  If restarts is set we'll do -W later.  */\n\n  if (old_files != 0)\n    {\n      const char **p;\n      for (p = old_files->list; *p != 0; ++p)\n        {\n          struct file *f = enter_file (*p);\n          f->last_mtime = f->mtime_before_update = OLD_MTIME;\n          f->updated = 1;\n          f->update_status = us_success;\n          f->command_state = cs_finished;\n        }\n    }\n\n  /* If the user wants to see a list of targets show it now then quit.\n     We do this before rebuilding makefiles to avoid extraneous output.  */\n  if (print_targets_flag)\n    {\n      print_targets ();\n      die (EXIT_SUCCESS);\n    }\n\n  if (!restarts && new_files != 0)\n    {\n      const char **p;\n      for (p = new_files->list; *p != 0; ++p)\n        {\n          struct file *f = enter_file (*p);\n          f->last_mtime = f->mtime_before_update = NEW_MTIME;\n        }\n    }\n\n  /* Initialize the remote job module.  */\n  remote_setup ();\n\n  /* Dump any output we've collected.  */\n\n  OUTPUT_UNSET ();\n  output_close (&make_sync);\n\n  if (shuffle_mode)\n    DB (DB_BASIC, (_(\"Enabled shuffle mode: %s\\n\"), shuffle_mode));\n\n  if (read_files)\n    {\n      /* Update any makefiles if necessary.  */\n\n      FILE_TIMESTAMP *makefile_mtimes;\n      struct goaldep *skipped_makefiles = NULL;\n      const char **nargv = (const char **) argv;\n      int any_failed = 0;\n      enum update_status status;\n\n      DB (DB_BASIC, (_(\"Updating makefiles....\\n\")));\n\n      /* Count the makefiles, and reverse the order so that we attempt to\n         rebuild them in the order they were read.  */\n      {\n        unsigned int num_mkfiles = 0;\n        struct goaldep *d = read_files;\n        read_files = NULL;\n        while (d != NULL)\n          {\n            struct goaldep *t = d;\n            d = d->next;\n            t->next = read_files;\n            read_files = t;\n            ++num_mkfiles;\n          }\n\n        makefile_mtimes = alloca (num_mkfiles * sizeof (FILE_TIMESTAMP));\n      }\n\n      /* Remove any makefiles we don't want to try to update.  Record the\n         current modtimes of the others so we can compare them later.  */\n      {\n        struct goaldep *d = read_files;\n        struct goaldep *last = NULL;\n        unsigned int mm_idx = 0;\n\n        while (d != 0)\n          {\n            int skip = 0;\n            struct file *f = d->file;\n\n            /* Check for makefiles that are either phony or a :: target with\n               commands, but no dependencies.  These will always be remade,\n               which will cause an infinite restart loop, so don't try to\n               remake it (this will only happen if your makefiles are written\n               exceptionally stupidly; but if you work for Athena, that's how\n               you write your makefiles.)  */\n\n            if (f->phony)\n              skip = 1;\n            else\n              for (f = f->double_colon; f != NULL; f = f->prev)\n                if (f->deps == NULL && f->cmds != NULL)\n                  {\n                    skip = 1;\n                    break;\n                  }\n\n            if (!skip)\n              {\n                makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file);\n                last = d;\n                d = d->next;\n              }\n            else\n              {\n                DB (DB_VERBOSE,\n                    (_(\"Makefile '%s' might loop; not remaking it.\\n\"),\n                     f->name));\n\n                if (last)\n                  last->next = d->next;\n                else\n                  read_files = d->next;\n\n                if (d->error && ! (d->flags & RM_DONTCARE))\n                  {\n                    /* This file won't be rebuilt, was not found, and we care,\n                       so remember it to report later.  */\n                    d->next = skipped_makefiles;\n                    skipped_makefiles = d;\n                    any_failed = 1;\n                  }\n                else\n                  free_goaldep (d);\n\n                d = last ? last->next : read_files;\n              }\n          }\n      }\n\n      /* Set up 'MAKEFLAGS' specially while remaking makefiles.  */\n      define_makeflags (1);\n\n      {\n        int orig_db_level = db_level;\n\n        if (! ISDB (DB_MAKEFILES))\n          db_level = DB_NONE;\n\n        rebuilding_makefiles = 1;\n        status = update_goal_chain (read_files);\n        rebuilding_makefiles = 0;\n\n        db_level = orig_db_level;\n      }\n\n      /* Report errors for makefiles that needed to be remade but were not.  */\n      while (skipped_makefiles != NULL)\n        {\n          struct goaldep *d = skipped_makefiles;\n          const char *err = strerror (d->error);\n\n          OSS (error, &d->floc, _(\"%s: %s\"), dep_name (d), err);\n\n          skipped_makefiles = skipped_makefiles->next;\n          free_goaldep (d);\n        }\n\n      /* If we couldn't build something we need but otherwise we succeeded,\n         reset the status.  */\n      if (any_failed && status == us_success)\n        status = us_none;\n\n      switch (status)\n        {\n        case us_question:\n          /* The only way this can happen is if the user specified -q and asked\n             for one of the makefiles to be remade as a target on the command\n             line.  Since we're not actually updating anything with -q we can\n             treat this as \"did nothing\".  */\n          break;\n\n        case us_none:\n          {\n             /* Reload any unloaded shared objects.  Do not re-exec to have\n                that shared object loaded: a re-exec would cause an infinite\n                loop, because the shared object was not updated.  */\n            struct goaldep *d;\n\n            for (d = read_files; d; d = d->next)\n              if (d->file->unloaded)\n                {\n                  struct file *f = d->file;\n                  /* Load the file.  0 means failure.  */\n                  if (load_file (&d->floc, f, 0) == 0)\n                    OS (fatal, &d->floc, _(\"%s: failed to load\"), f->name);\n                  f->unloaded = 0;\n                  f->loaded = 1;\n                }\n          }\n\n          /* No makefiles needed to be updated.  If we couldn't read some\n             included file that we care about, fail.  */\n          if (0)\n            {\n              /* This runs afoul of https://savannah.gnu.org/bugs/?61226\n                 The problem is that many makefiles use a \"dummy rule\" to\n                 pretend that an included file is rebuilt, without actually\n                 rebuilding it, and this has always worked.  There are a\n                 number of solutions proposed in that bug but for now we'll\n                 put things back so they work the way they did before.  */\n              struct goaldep *d;\n\n              for (d = read_files; d != 0; d = d->next)\n                if (d->error && ! (d->flags & RM_DONTCARE))\n                  {\n                    /* This makefile couldn't be loaded, and we care.  */\n                    const char *err = strerror (d->error);\n                    OSS (error, &d->floc, _(\"%s: %s\"), dep_name (d), err);\n                    any_failed = 1;\n                  }\n            }\n          break;\n\n        case us_failed:\n          /* Failed to update.  Figure out if we care.  */\n          {\n            /* Nonzero if any makefile was successfully remade.  */\n            int any_remade = 0;\n            unsigned int i;\n            struct goaldep *d;\n\n            for (i = 0, d = read_files; d != 0; ++i, d = d->next)\n              {\n                if (d->file->updated)\n                  {\n                    /* This makefile was updated.  */\n                    if (d->file->update_status == us_success)\n                      /* It was successfully updated.  */\n                      any_remade |= (file_mtime_no_search (d->file)\n                                     != makefile_mtimes[i]);\n                    else if (! (d->flags & RM_DONTCARE))\n                      {\n                        FILE_TIMESTAMP mtime;\n                        /* The update failed and this makefile was not\n                           from the MAKEFILES variable, so we care.  */\n                        OS (error, &d->floc,\n                            _(\"failed to remake makefile '%s'\"), d->file->name);\n                        mtime = file_mtime_no_search (d->file);\n                        any_remade |= (mtime != NONEXISTENT_MTIME\n                                       && mtime != makefile_mtimes[i]);\n                        makefile_status = MAKE_FAILURE;\n                        any_failed = 1;\n                      }\n                  }\n\n                /* This makefile was not found at all.  */\n                else if (! (d->flags & RM_DONTCARE))\n                  {\n                    const char *dnm = dep_name (d);\n\n                    /* This is a makefile we care about.  See how much.  */\n                    if (d->flags & RM_INCLUDED)\n                      /* An included makefile.  We don't need to die, but we\n                         do want to complain.  */\n                      OS (error, &d->floc,\n                          _(\"included makefile '%s' was not found\"), dnm);\n                    else\n                      {\n                        /* A normal makefile.  We must die later.  */\n                        OS (error, NILF, _(\"makefile '%s' was not found\"), dnm);\n                        any_failed = 1;\n                      }\n                  }\n              }\n\n            if (any_remade)\n              goto re_exec;\n\n            break;\n          }\n\n        case us_success:\n        re_exec:\n          /* Updated successfully.  Re-exec ourselves.  */\n\n          remove_intermediates (0);\n\n          if (print_data_base_flag)\n            print_data_base ();\n\n          clean_jobserver (0);\n\n          if (makefiles != 0)\n            {\n              /* Makefile names might have changed due to expansion.\n                 It's possible we'll need one extra argument:\n                   make -Rf-\n                 will expand to:\n                   make -R --temp-stdin=<tmpfile>\n                 so allocate more space.\n              */\n              int mfidx = 0;\n              char** av = argv;\n              const char** nv;\n\n              nv = nargv = alloca (sizeof (char*) * (argc + 1 + 1));\n              *(nv++) = *(av++);\n\n              for (; *av; ++av, ++nv)\n                {\n                  char *f;\n                  char *a = *av;\n                  const char *mf = makefiles->list[mfidx];\n\n                  assert (strlen (a) > 0);\n\n                  *nv = a;\n\n                  /* Not an option: we handled option args earlier.  */\n                  if (a[0] != '-')\n                    continue;\n\n                  /* See if this option specifies a filename.  If so we need\n                     to replace it with the value from makefiles->list.\n\n                     To simplify, we'll replace all possible versions of this\n                     flag with a simple \"-f<name>\".  */\n\n                  /* Handle long options.  */\n                  if (a[1] == '-')\n                    {\n                      if (strcmp (a, \"--file\") == 0 || strcmp (a, \"--makefile\") == 0)\n                        /* Skip the next arg as we'll combine them.  */\n                        ++av;\n                      else if (!strneq (a, \"--file=\", 7)\n                               && !strneq (a, \"--makefile=\", 11))\n                        continue;\n\n                      if (mfidx == stdin_offset)\n                        {\n                          char *na = alloca (CSTRLEN (\"--temp-stdin=\")\n                                             + strlen (mf) +  1);\n                          sprintf (na, \"--temp-stdin=%s\", mf);\n                          *nv = na;\n                        }\n                      else\n                        {\n                          char *na = alloca (strlen (mf) + 3);\n                          sprintf (na, \"-f%s\", mf);\n                          *nv = na;\n                        }\n\n                      ++mfidx;\n                      continue;\n                    }\n\n                  /* Handle short options.  If 'f' is the last option, it may\n                     be followed by <name>.  */\n                  f = strchr (a, 'f');\n                  if (!f)\n                    continue;\n\n                  /* If there's an extra argument option skip it.  */\n                  if (f[1] == '\\0')\n                    ++av;\n\n                  if (mfidx == stdin_offset)\n                    {\n                      const size_t al = f - a;\n                      char *na;\n\n                      if (al > 1)\n                        {\n                          /* Preserve the prior options.  */\n                          na = alloca (al + 1);\n                          memcpy (na, a, al);\n                          na[al] = '\\0';\n                          *(nv++) = na;\n                        }\n\n                      /* Remove the \"f\" and any subsequent content.  */\n                      na = alloca (CSTRLEN (\"--temp-stdin=\") + strlen (mf) + 1);\n                      sprintf (na, \"--temp-stdin=%s\", mf);\n                      *nv = na;\n                    }\n                  else if (f[1] == '\\0')\n                    /* -f <name> or -xyzf <name>.  Replace the name.  */\n                    *(++nv) = mf;\n                  else\n                    {\n                      /* -f<name> or -xyzf<name>. */\n                      const size_t al = f - a + 1;\n                      const size_t ml = strlen (mf) + 1;\n                      char *na = alloca (al + ml);\n                      memcpy (na, a, al);\n                      memcpy (na + al, mf, ml);\n                      *nv = na;\n                    }\n\n                  ++mfidx;\n                }\n\n              *nv = NULL;\n            }\n\n          if (directories != 0 && directories->idx > 0)\n            {\n              int bad = 1;\n              if (directory_before_chdir != 0)\n                {\n                  if (chdir (directory_before_chdir) < 0)\n                      perror_with_name (\"chdir\", \"\");\n                  else\n                    bad = 0;\n                }\n              if (bad)\n                O (fatal, NILF,\n                   _(\"couldn't change back to original directory\"));\n            }\n\n          ++restarts;\n\n          if (ISDB (DB_BASIC))\n            {\n              const char **p;\n              printf (_(\"Re-executing[%u]:\"), restarts);\n              for (p = nargv; *p != 0; ++p)\n                printf (\" %s\", *p);\n              putchar ('\\n');\n              fflush (stdout);\n            }\n\n          {\n            char **p;\n            for (p = environ; *p != 0; ++p)\n              {\n                if (strneq (*p, MAKELEVEL_NAME \"=\", MAKELEVEL_LENGTH+1))\n                  {\n                    *p = alloca (40);\n                    sprintf (*p, \"%s=%u\", MAKELEVEL_NAME, makelevel);\n#if MK_OS_VMS\n                    vms_putenv_symbol (*p);\n#endif\n                  }\n                else if (strneq (*p, \"MAKE_RESTARTS=\", CSTRLEN (\"MAKE_RESTARTS=\")))\n                  {\n                    *p = alloca (40);\n                    sprintf (*p, \"MAKE_RESTARTS=%s%u\",\n                             OUTPUT_IS_TRACED () ? \"-\" : \"\", restarts);\n                    restarts = 0;\n                  }\n              }\n          }\n\n          /* If we didn't set the restarts variable yet, add it.  */\n          if (restarts)\n            {\n              char *b = alloca (40);\n              sprintf (b, \"MAKE_RESTARTS=%s%u\",\n                       OUTPUT_IS_TRACED () ? \"-\" : \"\", restarts);\n              putenv (b);\n            }\n\n          fflush (stdout);\n          fflush (stderr);\n\n          osync_clear();\n\n          /* The exec'd \"child\" will be another make, of course.  */\n          jobserver_pre_child(1);\n\n#if MK_OS_OS2\n          {\n            /* It is not possible to use execve() here because this\n               would cause the parent process to be terminated with\n               exit code 0 before the child process has been terminated.\n               Therefore it may be the best solution simply to spawn the\n               child process including all file handles and to wait for its\n               termination. */\n            pid_t pid;\n            int r;\n            struct childbase child;\n            child.cmd_name = NULL;\n            child.output.syncout = 0;\n            child.environment = environ;\n\n            pid = child_execute_job (&child, 1, (char **)nargv);\n\n            /* is this loop really necessary? */\n            do {\n              pid = wait (&r);\n            } while (pid <= 0);\n            /* use the exit code of the child process */\n            exit (WIFEXITED(r) ? WEXITSTATUS(r) : EXIT_FAILURE);\n          }\n#else\n#ifdef SET_STACK_SIZE\n          /* Reset limits, if necessary.  */\n          if (stack_limit.rlim_cur)\n            setrlimit (RLIMIT_STACK, &stack_limit);\n#endif\n          exec_command ((char **)nargv, environ);\n#endif\n          jobserver_post_child(1);\n\n          temp_stdin_unlink ();\n\n          _exit (127);\n        }\n\n      if (any_failed)\n        die (MAKE_FAILURE);\n    }\n\n  /* Set up 'MAKEFLAGS' again for the normal targets.  */\n  define_makeflags (0);\n\n  /* Set always_make_flag if -B was given.  */\n  always_make_flag = always_make_set;\n\n  /* If restarts is set we haven't set up -W files yet, so do that now.  */\n  if (restarts && new_files != 0)\n    {\n      const char **p;\n      for (p = new_files->list; *p != 0; ++p)\n        {\n          struct file *f = enter_file (*p);\n          f->last_mtime = f->mtime_before_update = NEW_MTIME;\n        }\n    }\n\n  temp_stdin_unlink ();\n\n  /* If there were no command-line goals, use the default.  */\n  if (goals == 0)\n    {\n      char *p;\n\n      if (default_goal_var->recursive)\n        p = expand_string (default_goal_var->value);\n      else\n        {\n          p = variable_buffer_output (variable_buffer, default_goal_var->value,\n                                      strlen (default_goal_var->value));\n          *p = '\\0';\n          p = variable_buffer;\n        }\n\n      if (*p != '\\0')\n        {\n          struct file *f = lookup_file (p);\n\n          /* If .DEFAULT_GOAL is a non-existent target, enter it into the\n             table and let the standard logic sort it out. */\n          if (f == 0)\n            {\n              struct nameseq *ns;\n\n              ns = PARSE_SIMPLE_SEQ (&p, struct nameseq);\n              if (ns)\n                {\n                  /* .DEFAULT_GOAL should contain one target. */\n                  if (ns->next != 0)\n                    O (fatal, NILF,\n                       _(\".DEFAULT_GOAL contains more than one target\"));\n\n                  f = enter_file (strcache_add (ns->name));\n\n                  ns->name = 0; /* It was reused by enter_file(). */\n                  free_ns_chain (ns);\n                }\n            }\n\n          if (f)\n            {\n              goals = alloc_goaldep ();\n              goals->file = f;\n            }\n        }\n    }\n  else\n    lastgoal->next = 0;\n\n\n  if (!goals)\n    {\n      struct variable *v = lookup_variable (STRING_SIZE_TUPLE (\"MAKEFILE_LIST\"));\n      if (v && v->value && v->value[0] != '\\0')\n        O (fatal, NILF, _(\"No targets\"));\n\n      O (fatal, NILF, _(\"No targets specified and no makefile found\"));\n    }\n\n  /* Shuffle prerequisites to catch makefiles with incomplete depends. */\n\n  shuffle_goaldeps_recursive (goals);\n\n  /* Update the goals.  */\n\n  DB (DB_BASIC, (_(\"Updating goal targets....\\n\")));\n\n  {\n    switch (update_goal_chain (goals))\n    {\n      case us_none:\n        /* Nothing happened.  */\n        /* FALLTHROUGH */\n      case us_success:\n        /* Keep the previous result.  */\n        break;\n      case us_question:\n        /* We are under -q and would run some commands.  */\n        makefile_status = MAKE_TROUBLE;\n        break;\n      case us_failed:\n        /* Updating failed.  POSIX.2 specifies exit status >1 for this; */\n        makefile_status = MAKE_FAILURE;\n        break;\n    }\n\n    /* If we detected some clock skew, generate one last warning */\n    if (clock_skew_detected)\n      O (error, NILF,\n         _(\"warning: clock skew detected: your build may be incomplete\"));\n\n    /* Exit.  */\n    die (makefile_status);\n  }\n\n  /* NOTREACHED */\n  exit (MAKE_SUCCESS);\n}\n\f\n/* Parsing of arguments, decoding of switches.  */\n\nstatic char options[1 + ARRAYLEN (switches) * 3];\nstatic struct option long_options[ARRAYLEN (switches) + ARRAYLEN (long_option_aliases)];\n\n/* Fill in the string and vector for getopt.  */\nstatic void\ninit_switches (void)\n{\n  char *p;\n  unsigned int c;\n  unsigned int i;\n\n  if (options[0] != '\\0')\n    /* Already done.  */\n    return;\n\n  p = options;\n\n  /* Return switch and non-switch args in order, regardless of\n     POSIXLY_CORRECT.  Non-switch args are returned as option 1.  */\n  *p++ = '-';\n\n  for (i = 0; switches[i].c != '\\0'; ++i)\n    {\n      long_options[i].name = (char *) (switches[i].long_name == 0 ? \"\" :\n                                       switches[i].long_name);\n      long_options[i].flag = 0;\n      long_options[i].val = switches[i].c;\n      if (short_option (switches[i].c))\n        *p++ = (char) switches[i].c;\n      switch (switches[i].type)\n        {\n        case flag:\n        case flag_off:\n        case ignore:\n          long_options[i].has_arg = no_argument;\n          break;\n\n        case string:\n        case strlist:\n        case filename:\n        case positive_int:\n        case floating:\n          if (short_option (switches[i].c))\n            *p++ = ':';\n          if (switches[i].noarg_value != 0)\n            {\n              if (short_option (switches[i].c))\n                *p++ = ':';\n              long_options[i].has_arg = optional_argument;\n            }\n          else\n            long_options[i].has_arg = required_argument;\n          break;\n        }\n    }\n  *p = '\\0';\n  for (c = 0; c < ARRAYLEN (long_option_aliases); ++c)\n    long_options[i++] = long_option_aliases[c];\n  long_options[i].name = 0;\n}\n\n\n/* Non-option argument.  It might be a variable definition.\n   Returns 1 if the argument we read was .WAIT, else 0.\n */\nstatic unsigned int\nhandle_non_switch_argument (const char *arg, enum variable_origin origin)\n{\n  struct variable *v;\n\n  if (arg[0] == '-' && arg[1] == '\\0')\n    /* Ignore plain '-' for compatibility.  */\n    return 0;\n\n#if MK_OS_VMS\n  {\n    /* VMS DCL quoting can result in foo=\"bar baz\" showing up here.\n       Need to remove the double quotes from the value. */\n    char * eq_ptr;\n    char * new_arg;\n    eq_ptr = strchr (arg, '=');\n    if ((eq_ptr != NULL) && (eq_ptr[1] == '\"'))\n      {\n         int len;\n         int seg1;\n         int seg2;\n         len = strlen(arg);\n         new_arg = alloca(len);\n         seg1 = eq_ptr - arg + 1;\n         strncpy(new_arg, arg, (seg1));\n         seg2 = len - seg1 - 1;\n         strncpy(&new_arg[seg1], &eq_ptr[2], seg2);\n         new_arg[seg1 + seg2] = 0;\n         if (new_arg[seg1 + seg2 - 1] == '\"')\n           new_arg[seg1 + seg2 - 1] = 0;\n         arg = new_arg;\n      }\n  }\n#endif\n  v = try_variable_definition (0, arg, origin, s_global);\n  if (v != 0)\n    {\n      /* It is indeed a variable definition.  If we don't already have this\n         one, record a pointer to the variable for later use in\n         define_makeflags.  */\n      struct command_variable *cv;\n\n      for (cv = command_variables; cv != 0; cv = cv->next)\n        if (cv->variable == v)\n          break;\n\n      if (! cv)\n        {\n          cv = xmalloc (sizeof (*cv));\n          cv->variable = v;\n          cv->next = command_variables;\n          command_variables = cv;\n        }\n    }\n  else if (arg[0] != '\\0' && origin == o_command)\n    {\n      /* Not an option or variable definition; it must be a goal target.\n         Enter it as a file and add it to the dep chain of goals.\n         Check ARG[0] because if the top makefile resets MAKEOVERRIDES\n         then ARG points to an empty string in the submake.  */\n      struct file *f;\n\n      if (strcmp (arg, \".WAIT\") == 0)\n        return 1;\n\n      f = enter_file (strcache_add (expand_command_line_file (arg)));\n      f->cmd_target = 1;\n\n      if (goals == 0)\n        {\n          goals = alloc_goaldep ();\n          lastgoal = goals;\n        }\n      else\n        {\n          lastgoal->next = alloc_goaldep ();\n          lastgoal = lastgoal->next;\n        }\n\n      lastgoal->file = f;\n\n      {\n        /* Add this target name to the MAKECMDGOALS variable. */\n        struct variable *gv;\n        const char *value;\n\n        gv = lookup_variable (STRING_SIZE_TUPLE (\"MAKECMDGOALS\"));\n        if (gv == 0)\n          value = f->name;\n        else\n          {\n            /* Paste the old and new values together */\n            size_t oldlen, newlen;\n            char *vp;\n\n            oldlen = strlen (gv->value);\n            newlen = strlen (f->name);\n            vp = alloca (oldlen + 1 + newlen + 1);\n            memcpy (vp, gv->value, oldlen);\n            vp[oldlen] = ' ';\n            memcpy (&vp[oldlen + 1], f->name, newlen + 1);\n            value = vp;\n          }\n        define_variable_cname (\"MAKECMDGOALS\", value, o_default, 0);\n      }\n    }\n  return 0;\n}\n\n/* Called if the makefile resets the MAKEFLAGS variable.  */\nvoid\nreset_makeflags (enum variable_origin origin)\n{\n  /* Reset to default values.  */\n  env_overrides = 0;\n  decode_env_switches (STRING_SIZE_TUPLE(MAKEFLAGS_NAME), origin);\n  construct_include_path (include_dirs ? include_dirs->list : NULL);\n  disable_builtins ();\n  define_makeflags (rebuilding_makefiles);\n}\n\n/* Decode switches from ARGC and ARGV.\n   They came from the environment if ORIGIN is o_env.  */\n\nstatic void\ndecode_switches (int argc, const char **argv, enum variable_origin origin)\n{\n  int bad = 0;\n  struct command_switch *cs;\n  struct stringlist *sl;\n  struct stringlist targets;\n  int c;\n  unsigned int found_wait = 0;\n  const char **a;\n\n  /* This is for safety/double-checking.  */\n  static int using_getopt = 0;\n  assert (using_getopt == 0);\n  using_getopt = 1;\n\n  /* Get enough space for all the arguments, just in case.  */\n  targets.max = argc + 1;\n  targets.list = alloca (targets.max * sizeof (const char **));\n  targets.idx = 0;\n\n  /* getopt does most of the parsing for us.\n     First, get its vectors set up.  */\n\n  init_switches ();\n\n  /* Let getopt produce error messages for the command line,\n     but not for options from the environment.  */\n  opterr = origin == o_command;\n  /* Reset getopt's state.  */\n  optind = 0;\n\n  while (optind < argc)\n    {\n      const char *coptarg;\n\n      /* Parse the next argument.  */\n      c = getopt_long (argc, (char *const *)argv, options, long_options, NULL);\n      coptarg = optarg;\n      if (c == EOF)\n        /* End of arguments, or \"--\" marker seen.  */\n        break;\n      else if (c == '?')\n        /* Bad option.  We will print a usage message and die later.\n           But continue to parse the other options so the user can\n           see all he did wrong.  */\n        bad = 1;\n      else if (c == 1)\n        /* An argument not starting with a dash.  Defer handling until later,\n           since handle_non_switch_argument() might corrupt getopt().  */\n        targets.list[targets.idx++] = coptarg;\n      else\n        /* An option starting with a dash.  */\n        for (cs = switches; cs->c != '\\0'; ++cs)\n          if (cs->c == c)\n            {\n              /* Whether or not we will actually do anything with\n                 this switch.  We test this individually inside the\n                 switch below rather than just once outside it, so that\n                 options which are to be ignored still consume args.  */\n              int doit = (origin == o_command\n                          || (cs->env &&\n                              (cs->origin == NULL || origin >= *cs->origin)));\n\n              if (doit)\n                cs->specified = 1;\n\n              switch (cs->type)\n                {\n                default:\n                  abort ();\n\n                case ignore:\n                  break;\n\n                case flag:\n                case flag_off:\n                  if (doit)\n                    {\n                      *(int *) cs->value_ptr = cs->type == flag;\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n                  break;\n\n                case string:\n                case strlist:\n                case filename:\n                  if (!doit)\n                    break;\n\n                  if (! coptarg)\n                    coptarg = cs->noarg_value;\n                  else if (*coptarg == '\\0')\n                    {\n                      char opt[2] = \"c\";\n                      const char *op = opt;\n\n                      if (short_option (cs->c))\n                        opt[0] = (char) cs->c;\n                      else\n                        op = cs->long_name;\n\n                      error (NILF, strlen (op),\n                             _(\"the '%s%s' option requires a non-empty string argument\"),\n                             short_option (cs->c) ? \"-\" : \"--\", op);\n                      bad = 1;\n                      break;\n                    }\n\n                  if (cs->type == string)\n                    {\n                      char **val = (char **)cs->value_ptr;\n                      free (*val);\n                      *val = xstrdup (coptarg);\n                      if (cs->origin)\n                        *cs->origin = origin;\n                      break;\n                    }\n\n                  sl = *(struct stringlist **) cs->value_ptr;\n                  if (sl == 0)\n                    {\n                      sl = xmalloc (sizeof (struct stringlist));\n                      sl->max = 5;\n                      sl->idx = 0;\n                      sl->list = xmalloc (5 * sizeof (char *));\n                      *(struct stringlist **) cs->value_ptr = sl;\n                    }\n                  else if (sl->idx == sl->max - 1)\n                    {\n                      sl->max += 5;\n                      /* MSVC erroneously warns without a cast here.  */\n                      sl->list = xrealloc ((void *)sl->list,\n                                           sl->max * sizeof (char *));\n                    }\n\n                  /* Filter out duplicate options.\n                     Order matters for warnings.\n                     Allow duplicate makefiles for backward compatibility.  */\n                  if (cs->c != 'f' && cs->c != WARN_OPT)\n                    {\n                      unsigned int k;\n                      for (k = 0; k < sl->idx; ++k)\n                        if (streq (sl->list[k], coptarg))\n                          break;\n                      if (k < sl->idx)\n                        break;\n                    }\n\n                  if (cs->type == strlist)\n                    {\n                      sl->list[sl->idx++] = xstrdup (coptarg);\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n                  else if (cs->c == TEMP_STDIN_OPT)\n                    {\n                      if (stdin_offset > 0)\n                        fatal (NILF, 0, \"INTERNAL: multiple --temp-stdin options provided!\");\n                      /* We don't need to expand the temp file.  */\n                      stdin_offset = sl->idx;\n                      sl->list[sl->idx++] = strcache_add (coptarg);\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n                  else\n                    {\n                      sl->list[sl->idx++] = expand_command_line_file (coptarg);\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n                  sl->list[sl->idx] = 0;\n                  break;\n\n                case positive_int:\n                  /* See if we have an option argument; if we do require that\n                     it's all digits, not something like \"10foo\".  */\n                  if (coptarg == 0 && argc > optind)\n                    {\n                      const char *cp;\n                      for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp)\n                        ;\n                      if (cp[0] == '\\0')\n                        coptarg = argv[optind++];\n                    }\n\n                  if (!doit)\n                    break;\n\n                  if (coptarg)\n                    {\n                      const char *err;\n                      unsigned int i = make_toui (coptarg, &err);\n\n                      if (err || i == 0)\n                        {\n                          error (NILF, 0,\n                                 _(\"the '-%c' option requires a positive integer argument\"),\n                                 cs->c);\n                          bad = 1;\n                        }\n                      else\n                        {\n                          *(unsigned int *) cs->value_ptr = i;\n                          if (cs->origin)\n                            *cs->origin = origin;\n                        }\n                    }\n                  else\n                    {\n                      *(unsigned int *) cs->value_ptr\n                        = *(unsigned int *) cs->noarg_value;\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n                  break;\n\n                case floating:\n                  if (coptarg == 0 && optind < argc\n                      && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))\n                    coptarg = argv[optind++];\n\n                  if (doit)\n                    {\n                      *(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg)\n                                                   : *(double *) cs->noarg_value);\n                      if (cs->origin)\n                        *cs->origin = origin;\n                    }\n\n                  break;\n                }\n\n              /* We've found the switch.  Stop looking.  */\n              break;\n            }\n    }\n\n  /* There are no more options according to getting getopt, but there may\n     be some arguments left.  Since we have asked for non-option arguments\n     to be returned in order, this only happens when there is a \"--\"\n     argument to prevent later arguments from being options.  */\n  while (optind < argc)\n    targets.list[targets.idx++] = argv[optind++];\n  targets.list[targets.idx] = NULL;\n\n  /* Cannot call getopt below this line.  */\n  using_getopt = 0;\n\n  /* handle_non_switch_argument() can only be called after getopt is done;\n     if one of the arguments is MAKEFLAGS=<value> then it will recurse here\n     and call getopt() again, corrupting the state if the outer method.  */\n  for (a = targets.list; *a; ++a)\n    {\n      const int prior_found_wait = found_wait;\n      found_wait = handle_non_switch_argument (*a, origin);\n      if (prior_found_wait && lastgoal)\n        lastgoal->wait_here = 1;\n    }\n\n  if (bad && origin == o_command)\n    print_usage (bad);\n\n  /* If there are any options that need to be decoded do it now.  */\n  decode_debug_flags ();\n  decode_output_sync_flags ();\n\n  /* Support old-style option.  */\n  if (warn_undefined_variables_flag)\n    {\n      decode_warn_actions (\"undefined-var\", NULL);\n      warn_undefined_variables_flag = 0;\n    }\n\n  if (warn_flags)\n    for (const char **pp = warn_flags->list; *pp; ++pp)\n      decode_warn_actions (*pp, NULL);\n\n  /* Perform any special switch handling.  */\n  run_silent = silent_flag;\n\n  /* Check variable priorities.  */\n  reset_env_override ();\n}\n\n/* Decode switches from environment variable ENVAR (which is LEN chars long).\n   We do this by chopping the value into a vector of words, prepending a\n   dash to the first word if it lacks one, and passing the vector to\n   decode_switches.  */\n\nstatic void\ndecode_env_switches (const char *envar, size_t len, enum variable_origin origin)\n{\n  char *value, *p, *buf;\n  int argc;\n  const char **argv;\n\n  /* Get the variable's value.  */\n  value = expand_variable (envar, len);\n\n  /* Skip whitespace, and check for an empty value.  */\n  NEXT_TOKEN (value);\n  len = strlen (value);\n  if (len == 0)\n    return;\n\n  /* Allocate an array that is definitely big enough.  */\n  argv = xmalloc ((1 + len + 1) * sizeof (char *));\n\n  /* getopt will look at the arguments starting at ARGV[1].\n     Prepend a spacer word.  */\n  argv[0] = \"\";\n  argc = 1;\n\n  /* We need a buffer to copy the value into while we split it into words\n     and unquote it.  Set up in case we need to prepend a dash later.  */\n  buf = xmalloc (1 + len + 1);\n  buf[0] = '-';\n  p = buf+1;\n  argv[argc] = p;\n  while (*value != '\\0')\n    {\n      if (*value == '\\\\' && value[1] != '\\0')\n        ++value;                /* Skip the backslash.  */\n      else if (ISBLANK (*value))\n        {\n          /* End of the word.  */\n          *p++ = '\\0';\n          argv[++argc] = p;\n          do\n            ++value;\n          while (ISBLANK (*value));\n          continue;\n        }\n      *p++ = *value++;\n    }\n  *p = '\\0';\n  argv[++argc] = 0;\n  assert (p < buf + len + 2);\n\n  if (argv[1][0] != '-' && strchr (argv[1], '=') == 0)\n    /* The first word doesn't start with a dash and isn't a variable\n       definition, so add a dash.  */\n    argv[1] = buf;\n\n  /* Parse those words.  */\n  decode_switches (argc, argv, origin);\n  free (buf);\n  free (argv);\n}\n\f\n/* Quote the string IN so that it will be interpreted as a single word with\n   no magic by decode_env_switches; also double dollar signs to avoid\n   variable expansion in make itself.  Write the result into OUT, returning\n   the address of the next character to be written.\n   Allocating space for OUT twice the length of IN is always sufficient.  */\n\nstatic char *\nquote_for_env (char *out, const char *in)\n{\n  while (*in != '\\0')\n    {\n      if (*in == '$')\n        *out++ = '$';\n      else if (ISBLANK (*in) || *in == '\\\\')\n        *out++ = '\\\\';\n      *out++ = *in++;\n    }\n\n  return out;\n}\n\n/* Disable builtin variables and rules, if -R or -r is specified.\n   This function is called at parse time whenever MAKEFLAGS is modified and\n   also when the parsing phase is over.  */\n\nstatic\nvoid disable_builtins ()\n{\n    /* If -R was given, set -r too (doesn't make sense otherwise!)  */\n    if (no_builtin_variables_flag)\n      no_builtin_rules_flag = 1;\n\n    /* If we've disabled builtin rules, get rid of them.  */\n    if (no_builtin_rules_flag && ! old_builtin_rules_flag)\n      {\n        old_builtin_rules_flag = 1;\n        if (suffix_file && suffix_file->builtin)\n          {\n            free_dep_chain (suffix_file->deps);\n            suffix_file->deps = 0;\n          }\n        define_variable_cname (\"SUFFIXES\", \"\", o_default, 0);\n      }\n\n    /* If we've disabled builtin variables, get rid of them.  */\n    if (no_builtin_variables_flag && ! old_builtin_variables_flag)\n      {\n        old_builtin_variables_flag = 1;\n        undefine_default_variables ();\n      }\n}\n\n/* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the\n   command switches. Always include options with args.\n   Don't include options with the 'no_makefile' flag set if MAKEFILE.  */\n\nstruct variable *\ndefine_makeflags (int makefile)\n{\n  const char ref[] = \"MAKEOVERRIDES\";\n  const char posixref[] = \"-*-command-variables-*-\";\n  const char evalref[] = \" $(-*-eval-flags-*-)\";\n  const struct command_switch *cs;\n  struct variable *v;\n  char *bufsave;\n  size_t lensave;\n  char *fp;\n  char c[3];\n\n  install_variable_buffer (&bufsave, &lensave);\n\n  /* Start with a dash, for MFLAGS.  */\n  fp = variable_buffer_output (variable_buffer, \"-\", 1);\n\n#define SHORT_NOT_DEFAULT(_c)                                           \\\n    ((!*(int *) (_c)->value_ptr) == ((_c)->type == flag_off)            \\\n     && ((_c)->default_value == NULL || (_c)->specified                 \\\n         || *(int *) (_c)->value_ptr != *(int *) (_c)->default_value))\n\n  /* Add simple options as a group.  These can't have args by definion.  */\n  for (cs = switches; cs->c != '\\0'; ++cs)\n    if (cs->toenv && short_option (cs->c) && (!makefile || !cs->no_makefile)\n        && (cs->type == flag || cs->type == flag_off)\n        && SHORT_NOT_DEFAULT (cs))\n      {\n        c[0] = (char)cs->c;\n        fp = variable_buffer_output (fp, c, 1);\n      }\n\n  memcpy (c, \" --\", 3);\n\n#define ADD_OPT(_c)                                                     \\\n  do{                                                                   \\\n    if (short_option (cs->c))                                           \\\n      {                                                                 \\\n        c[2] = (char)cs->c;                                             \\\n        fp = variable_buffer_output (fp, c, 3);                         \\\n      }                                                                 \\\n    else                                                                \\\n      {                                                                 \\\n        c[2] = '-';                                                     \\\n        fp = variable_buffer_output (fp, c, 3);                         \\\n        fp = variable_buffer_output (fp, cs->long_name,                 \\\n                                     strlen (cs->long_name));           \\\n      }                                                                 \\\n  }while(0)\n\n  /* Now add more complex flags: ones with options and/or long names.  */\n  for (cs = switches; cs->c != '\\0'; ++cs)\n    if (cs->toenv && (!makefile || !cs->no_makefile))\n      switch (cs->type)\n        {\n        case ignore:\n          break;\n\n        case flag:\n        case flag_off:\n          /* We did the short flags above.  */\n          if (!short_option (cs->c) && SHORT_NOT_DEFAULT (cs))\n            ADD_OPT (cs);\n          break;\n\n        case positive_int:\n          if ((cs->default_value != 0\n               && (*(unsigned int *) cs->value_ptr\n                   == *(unsigned int *) cs->default_value)))\n            break;\n          ADD_OPT (cs);\n          if (!cs->noarg_value || (*(unsigned int *) cs->value_ptr\n                                   != *(unsigned int *) cs->noarg_value))\n            {\n              /* Add the value if not omitted.  */\n              char *buf = alloca (30);\n              sprintf (buf, \"%u\", *(unsigned int *) cs->value_ptr);\n              if (!short_option (cs->c))\n                fp = variable_buffer_output (fp, \"=\", 1);\n              fp = variable_buffer_output (fp, buf, strlen (buf));\n            }\n          break;\n\n        case floating:\n          if (cs->default_value != 0\n              && (*(double *) cs->value_ptr == *(double *) cs->default_value))\n            break;\n          ADD_OPT (cs);\n          if (!cs->noarg_value\n              || (*(double *) cs->value_ptr != *(double *) cs->noarg_value))\n            {\n              char *buf = alloca (100);\n              sprintf (buf, \"%g\", *(double *) cs->value_ptr);\n              if (!short_option (cs->c))\n                fp = variable_buffer_output (fp, \"=\", 1);\n              fp = variable_buffer_output (fp, buf, strlen (buf));\n            }\n          break;\n\n        case string:\n          {\n            char *p = *((char **)cs->value_ptr);\n            if (p)\n              {\n                ADD_OPT (cs);\n                if (!short_option (cs->c))\n                  fp = variable_buffer_output (fp, \"=\", 1);\n                fp = variable_buffer_output(fp, p, strlen (p));\n              }\n          }\n          break;\n\n        case filename:\n        case strlist:\n          if (cs->c == WARN_OPT)\n            fp = encode_warn_flag (fp);\n          else\n            {\n              struct stringlist *sl = *(struct stringlist **) cs->value_ptr;\n              if (sl != 0)\n                {\n                  unsigned int i;\n                  for (i = 0; i < sl->idx; ++i)\n                    {\n                      ADD_OPT (cs);\n                      if (!short_option (cs->c))\n                        fp = variable_buffer_output (fp, \"=\", 1);\n                      fp = variable_buffer_output (fp, sl->list[i], strlen (sl->list[i]));\n                    }\n                }\n            }\n          break;\n\n        default:\n          abort ();\n        }\n\n#undef ADD_OPT\n#undef SHORT_NOT_DEFAULT\n\n  /* If no flags at all, get rid of the initial dash.  */\n  if (fp == variable_buffer + 1)\n    fp = variable_buffer;\n\n  *fp = '\\0';\n\n  /* Define MFLAGS before appending variable definitions.  Omit an initial\n     empty dash.  Since MFLAGS is not parsed for flags, there is no reason to\n     override any makefile redefinition.  */\n  define_variable_cname (\"MFLAGS\",\n                         variable_buffer + (variable_buffer[0] == '-' && variable_buffer[1] == ' ' ? 2 : 0),\n                         o_env, 1);\n\n  /* Write a reference to -*-eval-flags-*-, which contains all the --eval\n     flag options.  */\n  if (eval_strings)\n    fp = variable_buffer_output (fp, evalref, CSTRLEN (evalref));\n\n  {\n    /* If there are any overrides to add, write a reference to\n       $(MAKEOVERRIDES), which contains command-line variable definitions.\n       Separate the variables from the switches with a \"--\" arg.  */\n\n    const char *r = posix_pedantic ? posixref : ref;\n    size_t l = strlen (r);\n    v = lookup_variable (r, l);\n    if (v && v->value && v->value[0] != '\\0')\n      {\n        fp = variable_buffer_output (fp, \" -- $(\", 6);\n        fp = variable_buffer_output (fp, r, l);\n        fp = variable_buffer_output (fp, \")\", 1);\n      }\n  }\n\n  *fp = '\\0';\n\n  /* If there is a leading dash, omit it.  */\n  fp = variable_buffer;\n  if (fp[0] == '-')\n    ++fp;\n\n  /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS.\n     Makefiles set MAKEFLAGS to add switches, but we still want to redefine\n     its value with the full set of switches.  Then we used o_file, but that\n     lost when users added -e, causing a previous MAKEFLAGS env. var. to take\n     precedence over the new one.  Of course, an override or command\n     definition will still take precedence.  */\n  v = define_variable_cname (MAKEFLAGS_NAME, fp,\n                             env_overrides ? o_env_override : o_file, 1);\n  v->special = 1;\n\n  restore_variable_buffer (bufsave, lensave);\n\n  return v;\n}\n\n/* Return 1 if the working directory change message should be printed.\n   Otherwise, return 0.  */\nint\nshould_print_dir (void)\n{\n    if (print_directory_flag >= 0)\n        return print_directory_flag;\n\n    /* If the user didn't specify any print-directory options, compute the\n       default setting: disable under -s / print in sub-makes and under -C.  */\n    return !silent_flag && (makelevel > 0 || directories != NULL);\n}\n\f\n/* Print version information.  */\n\nstatic void\nprint_version (void)\n{\n  static int printed_version = 0;\n\n  const char *precede = print_data_base_flag ? \"# \" : \"\";\n\n  if (printed_version)\n    /* Do it only once.  */\n    return;\n\n  printf (\"%sGNU Make %s\\n\", precede, version_string);\n\n  if (!remote_description || *remote_description == '\\0')\n    printf (_(\"%sBuilt for %s\\n\"), precede, make_host);\n  else\n    printf (_(\"%sBuilt for %s (%s)\\n\"),\n            precede, make_host, remote_description);\n\n#if MK_OS_W32\n  printf (_(\"%sANSI code page: %u\\n\"), precede, GetACP ());\n  printf (_(\"%sConsole code page: %u\\n\"), precede, GetConsoleOutputCP ());\n#endif\n\n  /* Print this untranslated.  The coding standards recommend translating the\n     (C) to the copyright symbol, but this string is going to change every\n     year, and none of the rest of it should be translated (including the\n     word \"Copyright\"), so it hardly seems worth it.  */\n\n  printf (\"%sCopyright (C) 1988-2024 Free Software Foundation, Inc.\\n\",\n          precede);\n\n  printf (_(\"%sLicense GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>\\n\\\n%sThis is free software: you are free to change and redistribute it.\\n\\\n%sThere is NO WARRANTY, to the extent permitted by law.\\n\"),\n            precede, precede, precede);\n\n  printed_version = 1;\n}\n\n/* Print a bunch of information about this and that.  */\n\nstatic void\nprint_data_base (void)\n{\n  int resolution;\n  char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];\n  file_timestamp_sprintf (buf, file_timestamp_now (&resolution));\n\n  print_version ();\n\n  printf (_(\"\\n# Make data base, printed on %s\\n\"), buf);\n\n  print_variable_data_base ();\n  print_dir_data_base ();\n  print_rule_data_base ();\n  print_file_data_base ();\n  print_vpath_data_base ();\n  strcache_print_stats (\"#\");\n\n  file_timestamp_sprintf (buf, file_timestamp_now (&resolution));\n  printf (_(\"\\n# Finished Make data base on %s\\n\\n\"), buf);\n}\n\nstatic void\nclean_jobserver (int status)\n{\n  /* Sanity: have we written all our jobserver tokens back?  If our\n     exit status is 2 that means some kind of syntax error; we might not\n     have written all our tokens so do that now.  If tokens are left\n     after any other error code, that's bad.  */\n\n  if (jobserver_enabled() && jobserver_tokens)\n    {\n      if (status != 2)\n        ON (error, NILF,\n            \"INTERNAL: exiting with %u jobserver tokens (should be 0)!\",\n            jobserver_tokens);\n      else\n        /* Don't write back the \"free\" token */\n        while (--jobserver_tokens)\n          jobserver_release (0);\n    }\n\n\n  /* Sanity: If we're the master, were all the tokens written back?  */\n\n  if (master_job_slots)\n    {\n      /* We didn't write one for ourself, so start at 1.  */\n      unsigned int tokens = 1 + jobserver_acquire_all ();\n\n      if (tokens != master_job_slots)\n        ONN (error, NILF,\n             \"INTERNAL: exiting with %u jobserver tokens available; should be %u!\",\n             tokens, master_job_slots);\n\n      reset_jobserver ();\n    }\n}\n\f\n/* Exit with STATUS, cleaning up as necessary.  */\n\nvoid\ndie (int status)\n{\n  static char dying = 0;\n\n  if (!dying)\n    {\n      int err;\n\n      dying = 1;\n\n      if (print_version_flag)\n        print_version ();\n\n      /* Get rid of a temp file from reading a makefile from stdin.  */\n      temp_stdin_unlink ();\n\n      /* Wait for children to die.  */\n      err = (status != 0);\n      while (job_slots_used > 0)\n        reap_children (1, err);\n\n      /* Let the remote job module clean up its state.  */\n      remote_cleanup ();\n\n      /* Remove the intermediate files.  */\n      remove_intermediates (0);\n\n      if (print_data_base_flag)\n        print_data_base ();\n\n      if (verify_flag)\n        verify_file_data_base ();\n\n      /* Unload plugins before jobserver integrity check in case a plugin\n         participates in jobserver.  */\n      unload_all ();\n\n      clean_jobserver (status);\n\n      if (output_context)\n        {\n          /* die() might be called in a recipe output context due to an\n             $(error ...) function.  */\n          output_close (output_context);\n\n          if (output_context != &make_sync)\n            output_close (&make_sync);\n\n          OUTPUT_UNSET ();\n        }\n\n      output_close (NULL);\n\n      osync_clear ();\n\n      /* Try to move back to the original directory.  This is essential on\n         MS-DOS (where there is really only one process), and on Unix it\n         puts core files in the original directory instead of the -C\n         directory.  Must wait until after remove_intermediates(), or unlinks\n         of relative pathnames fail.  */\n      if (directory_before_chdir != 0)\n        {\n          /* If it fails we don't care: shut up GCC.  */\n          int _x UNUSED;\n          _x = chdir (directory_before_chdir);\n        }\n    }\n\n  exit (status);\n}\n"
  },
  {
    "path": "src/makeint.h",
    "content": "/* Miscellaneous global declarations and portability cruft for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* We use <config.h> instead of \"config.h\" so that a compilation\n   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h\n   (which it would do because makeint.h was found in $srcdir).  */\n#include <config.h>\n\n/* Some versions of GCC (e.g., 10.x) set the warn_unused_result attribute on\n   __builtin_alloca.  This causes alloca(0) to fail and is not easily worked\n   around so avoid it via the preprocessor.\n   See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98055  */\n\n#if defined (__has_builtin)\n# if __has_builtin (__builtin_alloca)\n#   define free_alloca()\n# else\n#  define free_alloca() alloca (0)\n# endif\n#else\n# define free_alloca() alloca (0)\n#endif\n\n/* Disable assert() unless we're a maintainer.\n   Some asserts are compute-intensive.  */\n#ifndef MAKE_MAINTAINER_MODE\n# define NDEBUG 1\n#endif\n\n/* Include the externally-visible content.\n   Be sure to use the local one, and not one installed on the system.\n   Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport\n   declarations for MS-Windows.  */\n#if MK_OS_W32\n# define GMK_BUILDING_MAKE\n#endif\n#include \"gnumake.h\"\n\n#ifdef CRAY\n/* This must happen before #include <signal.h> so\n   that the declaration therein is changed.  */\n# define signal bsdsignal\n#endif\n\n/* If we're compiling for the dmalloc debugger, turn off string inlining.  */\n#if defined(HAVE_DMALLOC_H) && defined(__GNUC__)\n# define __NO_STRING_INLINES\n#endif\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <signal.h>\n#include <stdio.h>\n#include <ctype.h>\n\n#if HAVE_SYS_TIME_H\n# include <sys/time.h>\n#endif\n#include <time.h>\n\n#include <errno.h>\n\n#ifndef errno\nextern int errno;\n#endif\n\n/* Define macros specifying which OS we are building for.  */\n#if __gnu_hurd__\n# define MK_OS_HURD 1\n#endif\n#if __CYGWIN__\n# define MK_OS_CYGWIN 1\n#endif\n#if defined(__MVS__)\n# define MK_OS_ZOS 1\n#endif\n\n#if defined(__EMX__)\n# define MK_OS_OS2 1\n#endif\n\n#ifdef __VMS\n# define MK_OS_VMS 1\n/* In strict ANSI mode, VMS compilers should not be defining the\n   VMS macro.  Define it here instead of a bulk edit for the correct code.\n */\n# ifndef VMS\n#  define VMS\n# endif\n#endif\n\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n/* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get\n   POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself!  */\n# if defined (_POSIX_VERSION) && !defined (ultrix) && !MK_OS_VMS\n#  define POSIX 1\n# endif\n#endif\n\n/* Some systems define _POSIX_VERSION but are not really POSIX.1.  */\n#if (defined (butterfly) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386)))\n# undef POSIX\n#endif\n\n#if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE)\n# define POSIX 1\n#endif\n\n#ifndef sigmask\n# define sigmask(sig)   (1 << ((sig) - 1))\n#endif\n\n#ifndef HAVE_SA_RESTART\n# define SA_RESTART 0\n#endif\n\n#ifdef HAVE_VFORK_H\n# include <vfork.h>\n#endif\n\n#ifdef HAVE_LIMITS_H\n# include <limits.h>\n#endif\n#ifdef HAVE_SYS_PARAM_H\n# include <sys/param.h>\n#endif\n\n#ifndef PATH_MAX\n# ifdef MAXPATHLEN\n#  define PATH_MAX      MAXPATHLEN\n# else\n/* Some systems (HURD) have fully dynamic pathnames with no maximum.\n   Ideally we'd support this but it will take some work.  */\n#  define PATH_MAX      4096\n# endif\n#endif\n\n#ifdef PATH_MAX\n# define GET_PATH_MAX   PATH_MAX\n# define PATH_VAR(var)  char var[PATH_MAX+1]\n#else\n# define NEED_GET_PATH_MAX 1\n# define GET_PATH_MAX   (get_path_max ())\n# define PATH_VAR(var)  char *var = alloca (GET_PATH_MAX+1)\nunsigned int get_path_max (void);\n#endif\n\n#ifndef CHAR_BIT\n# define CHAR_BIT 8\n#endif\n\n#ifndef USHRT_MAX\n# define USHRT_MAX 65535\n#endif\n\n#ifndef SIZE_MAX\n# define SIZE_MAX ((size_t)~(size_t)0)\n#endif\n\n/* Nonzero if the integer type T is signed.\n   Use <= to avoid GCC warnings about always-false expressions.  */\n#define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0)\n\n/* The minimum and maximum values for the integer type T.\n   Use ~ (t) 0, not -1, for portability to 1's complement hosts.  */\n#define INTEGER_TYPE_MINIMUM(t) \\\n  (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))\n#define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t))\n\n#ifndef CHAR_MAX\n# define CHAR_MAX INTEGER_TYPE_MAXIMUM (char)\n#endif\n\n#ifdef STAT_MACROS_BROKEN\n# ifdef S_ISREG\n#  undef S_ISREG\n# endif\n# ifdef S_ISDIR\n#  undef S_ISDIR\n# endif\n#endif  /* STAT_MACROS_BROKEN.  */\n\n#ifndef S_ISREG\n# define S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)\n#endif\n#ifndef S_ISDIR\n# define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)\n#endif\n\n#if MK_OS_VMS\n# include <fcntl.h>\n# include <types.h>\n# include <unixlib.h>\n# include <unixio.h>\n# include <perror.h>\n/* Needed to use alloca on VMS.  */\n# include <builtins.h>\n\nextern int vms_use_mcr_command;\nextern int vms_always_use_cmd_file;\nextern int vms_gnv_shell;\nextern int vms_comma_separator;\nextern int vms_legacy_behavior;\nextern int vms_unix_simulation;\n#endif\n\n#if !defined(__attribute__) && (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__)\n/* Don't use __attribute__ if it's not supported.  */\n# define ATTRIBUTE(x)\n#else\n# define ATTRIBUTE(x) __attribute__ (x)\n#endif\n\n/* The __-protected variants of 'format' and 'printf' attributes\n   are accepted by gcc versions 2.6.4 (effectively 2.7) and later.  */\n#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)\n# define __format__ format\n# define __printf__ printf\n#endif\n\n#define UNUSED   ATTRIBUTE ((unused))\n#define NORETURN ATTRIBUTE ((noreturn))\n\n#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)\n# include <stdlib.h>\n# include <string.h>\n# define ANSI_STRING 1\n#else   /* No standard headers.  */\n# ifdef HAVE_STRING_H\n#  include <string.h>\n#  define ANSI_STRING 1\n# endif\n# ifdef HAVE_MEMORY_H\n#  include <memory.h>\n# endif\n# ifdef HAVE_STDLIB_H\n#  include <stdlib.h>\n# else\nvoid *malloc (int);\nvoid *realloc (void *, int);\nvoid free (void *);\n\nvoid abort (void) NORETURN;\nvoid exit (int) NORETURN;\n# endif /* HAVE_STDLIB_H.  */\n\n#endif /* Standard headers.  */\n\n/* These should be in stdlib.h.  Make sure we have them.  */\n#ifndef EXIT_SUCCESS\n# define EXIT_SUCCESS 0\n#endif\n#ifndef EXIT_FAILURE\n# define EXIT_FAILURE 1\n#endif\n\n#ifndef ANSI_STRING\n\n/* SCO Xenix has a buggy macro definition in <string.h>.  */\n#undef strerror\n#if !defined(__DECC)\nchar *strerror (int errnum);\n#endif\n\n#endif  /* !ANSI_STRING.  */\n#undef ANSI_STRING\n\n#if HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#if HAVE_STDINT_H\n# include <stdint.h>\n#endif\n\n#if HAVE_STRINGS_H\n# include <strings.h>  /* Needed for strcasecmp / strncasecmp.  */\n#endif\n\n#if defined _MSC_VER || defined __MINGW32__\n# define MK_PRI64_PREFIX \"I64\"\n#else\n# define MK_PRI64_PREFIX \"ll\"\n#endif\n#ifndef PRIdMAX\n# define PRIdMAX MK_PRI64_PREFIX \"d\"\n#endif\n#ifndef PRIuMAX\n# define PRIuMAX MK_PRI64_PREFIX \"u\"\n#endif\n#ifndef SCNdMAX\n# define SCNdMAX PRIdMAX\n#endif\n#define FILE_TIMESTAMP uintmax_t\n\n#if !defined(HAVE_STRSIGNAL)\nchar *strsignal (int signum);\n#endif\n\n#if !defined(HAVE_UMASK)\ntypedef int mode_t;\nextern mode_t umask (mode_t);\n#endif\n\n/* ISDIGIT offers the following features:\n   - Its arg may be any int or unsigned int; it need not be an unsigned char.\n   - It's guaranteed to evaluate its argument exactly once.\n      NOTE!  Make relies on this behavior, don't change it!\n   - It's typically faster.\n   POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that\n   only '0' through '9' are digits.  Prefer ISDIGIT to isdigit() unless\n   it's important to use the locale's definition of 'digit' even when the\n   host does not conform to POSIX.  */\n#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)\n\n/* Test if two strings are equal. Is this worthwhile?  Should be profiled.  */\n#define streq(a, b) \\\n   ((a) == (b) || \\\n    (*(a) == *(b) && (*(a) == '\\0' || !strcmp ((a) + 1, (b) + 1))))\n\n/* Test if two strings are equal, but match case-insensitively on systems\n   which have case-insensitive filesystems.  Should only be used for\n   filenames!  */\n#ifdef HAVE_CASE_INSENSITIVE_FS\n# define patheq(a, b) \\\n    ((a) == (b) \\\n     || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \\\n         && (*(a) == '\\0' || !strcasecmp ((a) + 1, (b) + 1))))\n#else\n# define patheq(a, b) streq(a, b)\n#endif\n\n#define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)\n\n#if defined(ENUM_BITFIELDS) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))\n# define ENUM_BITFIELD(bits)    :bits\n#else\n# define ENUM_BITFIELD(bits)\n#endif\n\n/* Handle gettext and locales.  */\n\n#if HAVE_LOCALE_H\n# include <locale.h>\n#else\n# define setlocale(category, locale)\n#endif\n\n#include <gettext.h>\n\n#define _(msgid)            gettext (msgid)\n#define N_(msgid)           gettext_noop (msgid)\n#define S_(msg1,msg2,num)   ngettext (msg1,msg2,num)\n\n/* This is needed for getcwd() and chdir(), on some W32 systems.  */\n#if defined(HAVE_DIRECT_H)\n# include <direct.h>\n#endif\n\n#if MK_OS_W32\n# include <fcntl.h>\n# include <malloc.h>\n# define pipe(_p)        _pipe((_p), 512, O_BINARY)\n# define kill(_pid,_sig) w32_kill((_pid),(_sig))\n/* MSVC and Watcom C don't have ftruncate.  */\n# if defined(_MSC_VER) || defined(__WATCOMC__)\n#  define ftruncate(_fd,_len) _chsize(_fd,_len)\n# endif\n/* MinGW64 doesn't have _S_ISDIR.  */\n# ifndef _S_ISDIR\n#  define _S_ISDIR(m)  S_ISDIR(m)\n# endif\n\nvoid sync_Path_environment (void);\nint w32_kill (pid_t pid, int sig);\nint find_and_set_default_shell (const char *token);\n\n/* indicates whether or not we have Bourne shell */\nextern int no_default_sh_exe;\n\n/* is default_shell unixy? */\nextern int unixy_shell;\n\n/* We don't have a preferred fixed value for LOCALEDIR.  */\n# ifndef LOCALEDIR\n#  define LOCALEDIR NULL\n# endif\n\n/* Include only the minimal stuff from windows.h.   */\n# ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n# endif\n#endif  /* MK_OS_W32 */\n\n/* ALL_SET() evaluates the second argument twice.  */\n#define ANY_SET(_v,_m)  (((_v)&(_m)) != 0)\n#define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m)))\n#define ALL_SET(_v,_m)  (((_v)&(_m)) == (_m))\n\n/* Bitmasks for the STOPCHAR array.  */\n#define MAP_NUL         0x0001\n#define MAP_BLANK       0x0002  /* space, TAB */\n#define MAP_NEWLINE     0x0004\n#define MAP_COMMENT     0x0008\n#define MAP_SEMI        0x0010\n#define MAP_EQUALS      0x0020\n#define MAP_COLON       0x0040\n#define MAP_VARSEP      0x0080\n#define MAP_PIPE        0x0100\n#define MAP_DOT         0x0200\n#define MAP_COMMA       0x0400\n\n/* These are the valid characters for a user-defined function.  */\n#define MAP_USERFUNC    0x2000\n/* This means not only a '$', but skip the variable reference.  */\n#define MAP_VARIABLE    0x4000\n/* The set of characters which are directory separators is OS-specific.  */\n#define MAP_DIRSEP      0x8000\n\n#if MK_OS_VMS\n# define MAP_VMSCOMMA   MAP_COMMA\n#else\n# define MAP_VMSCOMMA   0x0000\n#endif\n\n#define MAP_SPACE       (MAP_BLANK|MAP_NEWLINE)\n\n/* Handle other OSs.\n   To overcome an issue parsing paths in a DOS/Windows environment when\n   built in a unix based environment, override the PATH_SEPARATOR_CHAR\n   definition unless being built for Cygwin. */\n#if defined(HAVE_DOS_PATHS) && !defined(__CYGWIN__)\n# undef PATH_SEPARATOR_CHAR\n# define PATH_SEPARATOR_CHAR ';'\n# define MAP_PATHSEP    MAP_SEMI\n#elif !defined(PATH_SEPARATOR_CHAR)\n# if MK_OS_VMS\n#  define PATH_SEPARATOR_CHAR (vms_comma_separator ? ',' : ':')\n#  define MAP_PATHSEP    (vms_comma_separator ? MAP_COMMA : MAP_SEMI)\n# else\n#  define PATH_SEPARATOR_CHAR ':'\n#  define MAP_PATHSEP    MAP_COLON\n# endif\n#elif PATH_SEPARATOR_CHAR == ':'\n# define MAP_PATHSEP     MAP_COLON\n#elif PATH_SEPARATOR_CHAR == ';'\n# define MAP_PATHSEP     MAP_SEMI\n#elif PATH_SEPARATOR_CHAR == ','\n# define MAP_PATHSEP     MAP_COMMA\n\n#else\n# error \"Unknown PATH_SEPARATOR_CHAR\"\n#endif\n\n#define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m))\n\n/* True if C is whitespace but not newline.  */\n#define ISBLANK(c)      STOP_SET((c),MAP_BLANK)\n/* True if C is whitespace including newlines.  */\n#define ISSPACE(c)      STOP_SET((c),MAP_SPACE)\n/* True if C is nul or whitespace (including newline).  */\n#define END_OF_TOKEN(c) STOP_SET((c),MAP_SPACE|MAP_NUL)\n/* Move S past all whitespace (including newlines).  */\n#define NEXT_TOKEN(s)   while (ISSPACE (*(s))) ++(s)\n\n/* True if C is a directory separator on the current system.  */\n#define ISDIRSEP(c)     STOP_SET((c),MAP_DIRSEP)\n\n/* True if S starts with a drive specifier.  */\n#if defined(HAVE_DOS_PATHS)\n# define HAS_DRIVESPEC(_s) ((((_s)[0] >= 'a' && (_s)[0] <= 'z')          \\\n                             || ((_s)[0] >= 'A' && (_s)[0] <= 'Z'))      \\\n                            && (_s)[1] == ':')\n#else\n# define HAS_DRIVESPEC(_s) 0\n#endif\n\n/* We can't run setrlimit when using posix_spawn.  */\n#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && !defined(USE_POSIX_SPAWN)\n# define SET_STACK_SIZE\n#endif\n#ifdef SET_STACK_SIZE\n# include <sys/resource.h>\nextern struct rlimit stack_limit;\n#endif\n\n#include <glob.h>\n\n#define NILF ((floc *)0)\n\n/* Number of elements in an array.  */\n#define ARRAYLEN(_a)          (sizeof (_a) / sizeof ((_a)[0]))\n\n/* Number of characters in a string constant.  Does NOT include the \\0 byte.  */\n#define CSTRLEN(_s)           (sizeof (_s)-1)\n\n/* Only usable when NOT calling a macro: only use it for local functions.  */\n#define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)\n\n/* The number of bytes needed to represent the largest signed and unsigned\n   integers as a string.\n   Does NOT include space for \\0 so be sure to add it if needed.\n   Math suggested by Edward Welbourne <edward.welbourne@qt.io>  */\n#define INTSTR_LENGTH   (53 * sizeof(uintmax_t) / 22 + 3)\n\n#define DEFAULT_TTYNAME \"true\"\n#ifdef HAVE_TTYNAME\n# define TTYNAME(_f) ttyname (_f)\n#else\n# define TTYNAME(_f) DEFAULT_TTYNAME\n#endif\n\n#if MK_OS_VMS\n# define DEFAULT_TMPDIR     \"/sys$scratch/\"\n#elif defined(P_tmpdir)\n# define DEFAULT_TMPDIR     P_tmpdir\n#else\n# define DEFAULT_TMPDIR     \"/tmp\"\n#endif\n\n\n\f\n\nstruct file;\n\n/* Specify the location of elements read from makefiles.  */\ntypedef struct\n  {\n    const char *filenm;\n    unsigned long lineno;\n    unsigned long offset;\n  } floc;\n\nconst char *concat (unsigned int, ...);\nvoid message (int prefix, size_t length, const char *fmt, ...)\n              ATTRIBUTE ((__format__ (__printf__, 3, 4)));\nvoid error (const floc *flocp, size_t length, const char *fmt, ...)\n            ATTRIBUTE ((__format__ (__printf__, 3, 4)));\nvoid fatal (const floc *flocp, size_t length, const char *fmt, ...)\n            ATTRIBUTE ((noreturn, __format__ (__printf__, 3, 4)));\nchar *format (const char *prefix, size_t length, const char *fmt, ...)\n              ATTRIBUTE ((__format__ (__printf__, 3, 4)));\nvoid out_of_memory (void) NORETURN;\n\n/* When adding macros to this list be sure to update the value of\n   XGETTEXT_OPTIONS in the po/Makevars file.  */\n#define O(_t,_a,_f)           _t((_a), 0, (_f))\n#define OS(_t,_a,_f,_s)       _t((_a), strlen (_s), (_f), (_s))\n#define OSS(_t,_a,_f,_s1,_s2) _t((_a), strlen (_s1) + strlen (_s2), \\\n                                 (_f), (_s1), (_s2))\n#define OSSS(_t,_a,_f,_s1,_s2,_s3) _t((_a), strlen (_s1) + strlen (_s2) + strlen (_s3), \\\n                                      (_f), (_s1), (_s2), (_s3))\n#define ON(_t,_a,_f,_n)       _t((_a), INTSTR_LENGTH, (_f), (_n))\n#define ONN(_t,_a,_f,_n1,_n2) _t((_a), INTSTR_LENGTH*2, (_f), (_n1), (_n2))\n\n#define OSN(_t,_a,_f,_s,_n)   _t((_a), strlen (_s) + INTSTR_LENGTH, \\\n                                 (_f), (_s), (_n))\n#define ONS(_t,_a,_f,_n,_s)   _t((_a), INTSTR_LENGTH + strlen (_s), \\\n                                 (_f), (_n), (_s))\n\nenum variable_origin;\nstruct variable;\n\nvoid reset_makeflags (enum variable_origin origin);\nstruct variable *define_makeflags (int makefile);\nint should_print_dir (void);\nvoid temp_stdin_unlink (void);\nvoid die (int) NORETURN;\nvoid pfatal_with_name (const char *) NORETURN;\nvoid perror_with_name (const char *, const char *);\n#define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s))\nunsigned int make_toui (const char*, const char**);\nchar *make_lltoa (long long, char *);\nchar *make_ulltoa (unsigned long long, char *);\nvoid make_seed (unsigned int);\nunsigned int make_rand (void);\npid_t make_pid (void);\nvoid *xmalloc (size_t);\nvoid *xcalloc (size_t);\nvoid *xrealloc (void *, size_t);\nchar *xstrdup (const char *);\nchar *xstrndup (const char *, size_t);\nchar *find_next_token (const char **, size_t *);\nchar *next_token (const char *);\nchar *end_of_token (const char *);\nchar *skip_reference (const char *);\nvoid collapse_continuations (char *);\nchar *lindex (const char *, const char *, int);\nint alpha_compare (const void *, const void *);\nvoid print_spaces (unsigned int);\nchar *find_percent (char *);\nconst char *find_percent_cached (const char **);\nconst char *get_tmpdir (void);\nint get_tmpfd (char **);\nFILE *get_tmpfile (char **);\nssize_t writebuf (int, const void *, size_t);\nssize_t readbuf (int, void *, size_t);\n\n#ifndef HAVE_MEMRCHR\nvoid *memrchr(const void *, int, size_t);\n#endif\n\n#ifndef NO_ARCHIVES\nint ar_name (const char *);\nvoid ar_parse_name (const char *, char **, char **);\nint ar_touch (const char *);\ntime_t ar_member_date (const char *);\n\ntypedef intmax_t (*ar_member_func_t) (int desc, const char *mem, int truncated,\n                                      long int hdrpos, long int datapos,\n                                      long int size, intmax_t date, int uid,\n                                      int gid, unsigned int mode,\n                                      const void *arg);\n\nintmax_t ar_scan (const char *archive, ar_member_func_t function,\n                  const void *arg);\nint ar_name_equal (const char *name, const char *mem, int truncated);\n#if !MK_OS_VMS\nint ar_member_touch (const char *arname, const char *memname);\n#endif\n#endif\n\nint dir_file_exists_p (const char *, const char *);\nint file_exists_p (const char *);\nint file_impossible_p (const char *);\nvoid file_impossible (const char *);\nconst char *dir_name (const char *);\nvoid print_dir_data_base (void);\nvoid dir_setup_glob (glob_t *);\nvoid hash_init_directories (void);\n\nvoid define_default_variables (void);\nvoid undefine_default_variables (void);\nvoid set_default_suffixes (void);\nvoid install_default_suffix_rules (void);\nvoid install_default_implicit_rules (void);\n\nvoid build_vpath_lists (void);\nvoid construct_vpath_list (char *pattern, char *dirpath);\nconst char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,\n                          unsigned int* vpath_index, unsigned int* path_index);\nint gpath_search (const char *file, size_t len);\n\nvoid construct_include_path (const char **arg_dirs);\n\nchar *strip_whitespace (const char **begpp, const char **endpp);\n\nvoid show_goal_error (void);\n\n/* String caching  */\nvoid strcache_init (void);\nvoid strcache_print_stats (const char *prefix);\nint strcache_iscached (const char *str);\nconst char *strcache_add (const char *str);\nconst char *strcache_add_len (const char *str, size_t len);\n\n/* Guile support  */\nint guile_gmake_setup (const floc *flocp);\n\n/* Loadable object support.  Sets to the strcached name of the loaded file.  */\nint load_file (const floc *flocp, struct file *file, int noerror);\nint unload_file (const char *name);\nvoid unload_all (void);\n\n/* Maintainer mode support */\n#ifdef MAKE_MAINTAINER_MODE\n# define SPIN(_s) spin (_s)\nvoid spin (const char* suffix);\n# define DBG(_f) dbg _f\nvoid dbg (const char *fmt, ...);\n#else\n# define SPIN(_s)\n/* Never put this code into Git or a release.  */\n# define DBG(_f) compile-error\n#endif\n\n/* We omit these declarations on non-POSIX systems which define _POSIX_VERSION,\n   because such systems often declare them in header files anyway.  */\n\n#if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !MK_OS_W32\n\n# if !MK_OS_VMS\nlong int lseek ();\n# endif\n\n# ifdef HAVE_GETCWD\n#  if !MK_OS_VMS && !defined(__DECC)\nchar *getcwd (void);\n#  endif\n# else\nchar *getwd (void);\n#  define getcwd(buf, len)       getwd (buf)\n# endif\n\n#endif  /* Not GNU C library or POSIX.  */\n\n#if !HAVE_STRCASECMP\n# if HAVE_STRICMP\n#  define strcasecmp stricmp\n# elif HAVE_STRCMPI\n#  define strcasecmp strcmpi\n# endif\n#endif\n\n#if !HAVE_STRNCASECMP\n# if HAVE_STRNICMP\n#  define strncasecmp strnicmp\n# elif HAVE_STRNCMPI\n#  define strncasecmp strncmpi\n# endif\n#endif\n\n#define OUTPUT_SYNC_NONE    0\n#define OUTPUT_SYNC_LINE    1\n#define OUTPUT_SYNC_TARGET  2\n#define OUTPUT_SYNC_RECURSE 3\n\n/* Non-GNU systems may not declare this in unistd.h.  */\nextern char **environ;\n\nextern const floc *reading_file;\nextern const floc **expanding_var;\n\nextern unsigned short stopchar_map[];\n\nextern int just_print_flag, run_silent, ignore_errors_flag, keep_going_flag;\nextern int print_data_base_flag, question_flag, touch_flag, always_make_flag;\nextern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;\nextern int print_version_flag, check_symlink_flag, posix_pedantic;\nextern int not_parallel, second_expansion, clock_skew_detected;\nextern int rebuilding_makefiles, one_shell, output_sync, verify_flag;\nextern int export_all_variables;\nextern unsigned long command_count;\n\nextern const char *default_shell;\n\n/* can we run commands via 'sh -c xxx' or must we use batch files? */\nextern int batch_mode_shell;\n\n#define GNUMAKEFLAGS_NAME       \"GNUMAKEFLAGS\"\n#define MAKEFLAGS_NAME          \"MAKEFLAGS\"\n\n#define MAKELEVEL_NAME \"MAKELEVEL\"\n#define MAKELEVEL_LENGTH (CSTRLEN (MAKELEVEL_NAME))\n\n/* Resetting the command script introduction prefix character.  */\n#define RECIPEPREFIX_NAME       \".RECIPEPREFIX\"\n#define RECIPEPREFIX_DEFAULT    '\\t'\nextern char cmd_prefix;\n\n/* Setting warning actions.  */\n#define WARNINGS_NAME           \".WARNINGS\"\n\nextern unsigned int no_intermediates;\n\n#if HAVE_MKFIFO\n/* It seems that mkfifo() is not working correctly, or at least not the way\n   GNU make wants it to work, on: GNU/Hurd, Cygwin, OS2; don't use it there.  */\n# if !defined(JOBSERVER_USE_FIFO) && !MK_OS_HURD && !MK_OS_CYGWIN && !MK_OS_OS2\n#  define JOBSERVER_USE_FIFO 1\n# endif\n#endif\n\n#define JOBSERVER_AUTH_OPT      \"jobserver-auth\"\n\nextern char *jobserver_auth;\nextern unsigned int job_slots;\nextern double max_load_average;\n\nextern const char *program;\n\n#if MK_OS_VMS\nconst char *vms_command (const char *argv0);\nconst char *vms_progname (const char *argv0);\n\nvoid vms_exit (int);\n# define _exit(foo) vms_exit(foo)\n# define exit(foo) vms_exit(foo)\n\nextern char *program_name;\n\nvoid\nset_program_name (const char *arv0);\n\nint\nneed_vms_symbol (void);\n\nint\ncreate_foreign_command (const char *command, const char *image);\n\nint\nvms_export_dcl_symbol (const char *name, const char *value);\n\nint\nvms_putenv_symbol (const char *string);\n\nvoid\nvms_restore_symbol (const char *string);\n\n#endif\n\nvoid remote_setup (void);\nvoid remote_cleanup (void);\nint start_remote_job_p (int);\nint start_remote_job (char **, char **, int, int *, pid_t *, int *);\nint remote_status (int *, int *, int *, int);\nvoid block_remote_children (void);\nvoid unblock_remote_children (void);\nint remote_kill (pid_t id, int sig);\nvoid print_variable_data_base (void);\nvoid print_vpath_data_base (void);\n\nextern char *starting_directory;\nextern unsigned int makelevel;\nextern char *version_string, *remote_description, *make_host;\n\nextern unsigned int commands_started;\n\nextern volatile sig_atomic_t handling_fatal_signal;\n\n#ifndef MIN\n#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))\n#endif\n#ifndef MAX\n#define MAX(_a,_b) ((_a)>(_b)?(_a):(_b))\n#endif\n\n#define MAKE_SUCCESS 0\n#define MAKE_TROUBLE 1\n#define MAKE_FAILURE 2\n\n/* Set up heap debugging library dmalloc.  */\n\n#ifdef HAVE_DMALLOC_H\n#include <dmalloc.h>\n#endif\n\n#ifndef initialize_main\n# if MK_OS_OS2\n#  define initialize_main(pargc, pargv) \\\n                          { _wildcard(pargc, pargv); _response(pargc, pargv); }\n# else\n#  define initialize_main(pargc, pargv)\n# endif\n#endif\n\n#if MK_OS_OS2\n# if !defined chdir\n#  define chdir _chdir2\n# endif\n# if !defined getcwd\n#  define getcwd _getcwd2\n# endif\n\n/* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of\n   chdir() and getcwd(). This avoids some error messages for the\n   make testsuite but restricts the drive letter support. */\n# ifdef NO_CHDIR2\n#  warning NO_CHDIR2: usage of drive letters restricted\n#  undef chdir\n#  undef getcwd\n# endif\n#endif\n\n#ifndef initialize_main\n# define initialize_main(pargc, pargv)\n#endif\n\n\n/* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag\n   properly according to POSIX.  So, we try to wrap common system calls with\n   checks for EINTR.  Note that there are still plenty of system calls that\n   can fail with EINTR but this, reportedly, gets the vast majority of\n   failure cases.  If you still experience failures you'll need to either get\n   a system where SA_RESTART works, or you need to avoid -j.  */\n\n#define EINTRLOOP(_v,_c)   while (((_v)=_c)==-1 && errno==EINTR)\n\n/* While system calls that return integers are pretty consistent about\n   returning -1 on failure and setting errno in that case, functions that\n   return pointers are not always so well behaved.  Sometimes they return\n   NULL for expected behavior: one good example is readdir() which returns\n   NULL at the end of the directory--and _doesn't_ reset errno.  So, we have\n   to do it ourselves here.  */\n\n#define ENULLLOOP(_v,_c)   do { errno = 0; (_v) = _c; } \\\n                           while((_v)==0 && errno==EINTR)\n"
  },
  {
    "path": "src/misc.c",
    "content": "/* Miscellaneous generic support functions for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"os.h\"\n#include \"debug.h\"\n\n#include <assert.h>\n#include <stdarg.h>\n\n#if MK_OS_W32\n# include <windows.h>\n# include <io.h>\n#endif\n\n#if MK_OS_OS2\n# define INCL_DOS\n# include <os2.h>\n#endif\n\n#ifdef HAVE_FCNTL_H\n# include <fcntl.h>\n#else\n# include <sys/file.h>\n#endif\n\nunsigned int\nmake_toui (const char *str, const char **error)\n{\n  char *end;\n  unsigned long val = strtoul (str, &end, 10);\n\n  if (error)\n    {\n      if (str[0] == '\\0')\n        *error = \"Missing value\";\n      else if (*end != '\\0')\n        *error = \"Invalid value\";\n      else\n        *error = NULL;\n    }\n\n  return val;\n}\n\n/* Convert val into a string, written to buf.  buf must be large enough\n   to hold the largest possible value, plus a nul byte.  Returns buf.\n   We can't use standard PRI* here: those are based on intNN_t types.  */\n\nchar *\nmake_lltoa (long long val, char *buf)\n{\n  sprintf (buf, \"%\" MK_PRI64_PREFIX \"d\", val);\n  return buf;\n}\n\nchar *\nmake_ulltoa (unsigned long long val, char *buf)\n{\n  sprintf (buf, \"%\" MK_PRI64_PREFIX \"u\", val);\n  return buf;\n}\n\n/* Simple random number generator, for use with shuffle.\n   This doesn't need to be truly random, just pretty random.  Use our own\n   implementation rather than relying on the C runtime's rand() so we always\n   get the same results for a given seed, regardless of C runtime.  */\n\nstatic unsigned int mk_state = 0;\n\nvoid\nmake_seed (unsigned int seed)\n{\n  mk_state = seed;\n}\n\nunsigned int\nmake_rand ()\n{\n  /* mk_state must never be 0.  */\n  if (mk_state == 0)\n    mk_state = (unsigned int)(time (NULL) ^ make_pid ()) + 1;\n\n  /* A simple xorshift RNG.  */\n  mk_state ^= mk_state << 13;\n  mk_state ^= mk_state >> 17;\n  mk_state ^= mk_state << 5;\n\n  return mk_state;\n}\n\n/* Compare strings *S1 and *S2.\n   Return negative if the first is less, positive if it is greater,\n   zero if they are equal.  */\n\nint\nalpha_compare (const void *v1, const void *v2)\n{\n  const char *s1 = *((char **)v1);\n  const char *s2 = *((char **)v2);\n\n  if (*s1 != *s2)\n    return *s1 - *s2;\n  return strcmp (s1, s2);\n}\n\f\n/* Discard each backslash-newline combination from LINE.\n   Backslash-backslash-newline combinations become backslash-newlines.\n   This is done by copying the text at LINE into itself.  */\n\nvoid\ncollapse_continuations (char *line)\n{\n  char *out = line;\n  char *in = line;\n  char *q;\n\n  q = strchr(in, '\\n');\n  if (!q)\n    return;\n\n  do\n    {\n      char *p = q;\n      int i;\n      size_t out_line_length;\n\n      if (q > line && q[-1] == '\\\\')\n        {\n          /* Search for more backslashes.  */\n          i = -2;\n          while (&p[i] >= line && p[i] == '\\\\')\n            --i;\n          ++i;\n        }\n      else\n        i = 0;\n\n      /* The number of backslashes is now -I, keep half of them.  */\n      out_line_length = (p - in) + i - i/2;\n      if (out != in)\n        memmove (out, in, out_line_length);\n      out += out_line_length;\n\n      /* When advancing IN, skip the newline too.  */\n      in = q + 1;\n\n      if (i & 1)\n        {\n          unsigned int dollar;\n\n          /* Backslash/newline handling: out points to the final \"\\\".\n             In POSIX, each backslash/newline is replaced by a space.\n             In GNU Make all trailing whitespace, consecutive backslash +\n             newlines, and any leading non-newline whitespace on the next line\n             is reduced to a single space.\n             As a special case, replace \"$\\\" with the empty string.  */\n          while (ISBLANK (*in))\n            ++in;\n\n          {\n            const char *dp = out;\n            while (dp > line && dp[-1] == '$')\n              --dp;\n            dollar = (out - dp) % 2;\n          }\n\n          if (dollar)\n            --out;\n\n          if (!posix_pedantic)\n            while (out > line && ISBLANK (out[-1]))\n              --out;\n\n          if (!dollar)\n            *out++ = ' ';\n        }\n      else\n        {\n          /* If the newline isn't quoted, put it in the output.  */\n          *out++ = '\\n';\n        }\n\n      q = strchr(in, '\\n');\n    }\n  while (q);\n\n  memmove(out, in, strlen(in) + 1);\n}\n\f\n/* Print N spaces (used in debug for target-depth).  */\n\nvoid\nprint_spaces (unsigned int n)\n{\n  while (n-- > 0)\n    putchar (' ');\n}\n\n\f\n/* Return a string whose contents concatenate the NUM strings provided\n   This string lives in static, re-used memory.  */\n\nconst char *\nconcat (unsigned int num, ...)\n{\n  static size_t rlen = 0;\n  static char *result = NULL;\n  size_t ri = 0;\n  va_list args;\n\n  va_start (args, num);\n\n  while (num-- > 0)\n    {\n      const char *s = va_arg (args, const char *);\n      size_t l = xstrlen (s);\n\n      if (l == 0)\n        continue;\n\n      if (ri + l > rlen)\n        {\n          rlen = ((rlen ? rlen : 60) + l) * 2;\n          result = xrealloc (result, rlen);\n        }\n\n      memcpy (result + ri, s, l);\n      ri += l;\n    }\n\n  va_end (args);\n\n  /* Get some more memory if we don't have enough space for the\n     terminating '\\0'.   */\n  if (ri == rlen)\n    {\n      rlen = (rlen ? rlen : 60) * 2;\n      result = xrealloc (result, rlen);\n    }\n\n  result[ri] = '\\0';\n\n  return result;\n}\n\f\n\n#ifndef HAVE_UNISTD_H\npid_t getpid ();\n#endif\n\npid_t make_pid ()\n{\n  return getpid ();\n}\n\n/* Like malloc but get fatal error if memory is exhausted.  */\n/* Don't bother if we're using dmalloc; it provides these for us.  */\n\n#ifndef HAVE_DMALLOC_H\n\n#undef xmalloc\n#undef xcalloc\n#undef xrealloc\n#undef xstrdup\n\nvoid *\nxmalloc (size_t size)\n{\n  /* Make sure we don't allocate 0, for pre-ISO implementations.  */\n  void *result = malloc (size ? size : 1);\n  if (result == 0)\n    out_of_memory ();\n  return result;\n}\n\n\nvoid *\nxcalloc (size_t size)\n{\n  /* Make sure we don't allocate 0, for pre-ISO implementations.  */\n  void *result = calloc (size ? size : 1, 1);\n  if (result == 0)\n    out_of_memory ();\n  return result;\n}\n\n\nvoid *\nxrealloc (void *ptr, size_t size)\n{\n  void *result;\n\n  /* Some older implementations of realloc() don't conform to ISO.  */\n  if (! size)\n    size = 1;\n  result = ptr ? realloc (ptr, size) : malloc (size);\n  if (result == 0)\n    out_of_memory ();\n  return result;\n}\n\n\nchar *\nxstrdup (const char *ptr)\n{\n  char *result;\n\n#ifdef HAVE_STRDUP\n  result = strdup (ptr);\n#else\n  result = malloc (strlen (ptr) + 1);\n#endif\n\n  if (result == 0)\n    out_of_memory ();\n\n#ifdef HAVE_STRDUP\n  return result;\n#else\n  return strcpy (result, ptr);\n#endif\n}\n\n#endif  /* HAVE_DMALLOC_H */\n\nchar *\nxstrndup (const char *str, size_t length)\n{\n  char *result;\n\n#ifdef HAVE_STRNDUP\n  result = strndup (str, length);\n  if (result == 0)\n    out_of_memory ();\n#else\n  result = xmalloc (length + 1);\n  if (length > 0)\n    strncpy (result, str, length);\n  result[length] = '\\0';\n#endif\n\n  return result;\n}\n\n#ifndef HAVE_MEMRCHR\nvoid *\nmemrchr(const void* str, int ch, size_t len)\n{\n  const char* sp = str;\n  const char* cp = sp;\n\n  if (len == 0)\n    return NULL;\n\n  cp += len - 1;\n\n  while (cp[0] != ch)\n    {\n      if (cp == sp)\n        return NULL;\n      --cp;\n    }\n\n  return (void*)cp;\n}\n#endif\n\n\f\n\n/* Limited INDEX:\n   Search through the string STRING, which ends at LIMIT, for the character C.\n   Returns a pointer to the first occurrence, or nil if none is found.\n   Like INDEX except that the string searched ends where specified\n   instead of at the first null.  */\n\nchar *\nlindex (const char *s, const char *limit, int c)\n{\n  while (s < limit)\n    if (*s++ == c)\n      return (char *)(s - 1);\n\n  return 0;\n}\n\f\n/* Return the address of the first whitespace or null in the string S.  */\n\nchar *\nend_of_token (const char *s)\n{\n  while (! END_OF_TOKEN (*s))\n    ++s;\n  return (char *)s;\n}\n\n/* Return the address of the first nonwhitespace or null in the string S.  */\n\nchar *\nnext_token (const char *s)\n{\n  NEXT_TOKEN (s);\n  return (char *)s;\n}\n\n/* This function returns P if P points to EOS, or P+1 if P is NOT an open\n   paren or brace, or a pointer to the character after the matching close\n   paren or brace, skipping matched internal parens or braces.\n\n   It is typically called when we have seen a '$' in a string and we want to\n   treat it as a variable reference and find the end of it: in that case P\n   should point to the character after the '$'.  */\n\nchar *\nskip_reference (const char *p)\n{\n  char openparen = *p;\n  char closeparen;\n  int count = 1;\n\n  if (openparen == '\\0')\n    return (char*)p;\n\n  if (openparen == '(')\n    closeparen = ')';\n  else if (openparen == '{')\n    closeparen = '}';\n  else\n    return (char*)(p+1);\n\n  while (1)\n    {\n      ++p;\n      if (!STOP_SET (*p, MAP_NUL|MAP_VARSEP))\n        continue;\n      if (*p == '\\0')\n        break;\n      if (*p == openparen)\n        ++count;\n      else if (*p == closeparen && --count == 0)\n        {\n          ++p;\n          break;\n        }\n    }\n\n  return (char*)p;\n}\n\n/* Find the next token in PTR; return the address of it, and store the length\n   of the token into *LENGTHPTR if LENGTHPTR is not nil.  Set *PTR to the end\n   of the token, so this function can be called repeatedly in a loop.  */\n\nchar *\nfind_next_token (const char **ptr, size_t *lengthptr)\n{\n  const char *p = next_token (*ptr);\n\n  if (*p == '\\0')\n    return 0;\n\n  *ptr = end_of_token (p);\n  if (lengthptr != 0)\n    *lengthptr = *ptr - p;\n\n  return (char *)p;\n}\n\f\n\n/* Write a BUFFER of size LEN to file descriptor FD.\n   Retry short writes from EINTR.  Return LEN, or -1 on error.  */\nssize_t\nwritebuf (int fd, const void *buffer, size_t len)\n{\n  const char *msg = buffer;\n  size_t l = len;\n  while (l)\n    {\n      ssize_t r;\n\n      EINTRLOOP (r, write (fd, msg, l));\n      if (r < 0)\n        return -1;\n\n      l -= r;\n      msg += r;\n    }\n\n  return (ssize_t)len;\n}\n\n/* Read until we get LEN bytes from file descriptor FD, into BUFFER.\n   Retry short reads on EINTR. Return 0 at EOF and -1 on error.  */\nssize_t\nreadbuf (int fd, void *buffer, size_t len)\n{\n  char *msg = buffer;\n  while (len)\n    {\n      ssize_t r;\n\n      EINTRLOOP (r, read (fd, msg, len));\n      if (r < 0)\n        return -1;\n      if (r == 0)\n        break;\n\n      len -= r;\n      msg += r;\n    }\n\n  return (ssize_t)(msg - (char*)buffer);\n}\n\f\n\n/* Copy a 'struct dep'.  For 2nd expansion deps, dup the name.  */\n\nstruct dep *\ncopy_dep (const struct dep *d)\n{\n  struct dep *new = NULL;\n\n  if (d)\n    {\n      new = xmalloc (sizeof (struct dep));\n      memcpy (new, d, sizeof (struct dep));\n\n      if (new->need_2nd_expansion)\n        new->name = xstrdup (new->name);\n      new->next = 0;\n    }\n\n  return new;\n}\n\n/* Copy a chain of 'struct dep'.  For 2nd expansion deps, dup the name.  */\n\nstruct dep *\ncopy_dep_chain (const struct dep *d)\n{\n  struct dep *firstnew = NULL;\n  struct dep *lastnew = NULL;\n\n  while (d != 0)\n    {\n      struct dep *c = copy_dep (d);\n\n      if (firstnew == 0)\n        firstnew = lastnew = c;\n      else\n        lastnew = lastnew->next = c;\n\n      d = d->next;\n    }\n\n  return firstnew;\n}\n\n/* Free a chain of struct nameseq.\n   For struct dep chains use free_dep_chain.  */\n\nvoid\nfree_ns_chain (struct nameseq *ns)\n{\n  while (ns != NULL)\n    {\n      struct nameseq *t = ns;\n      ns = ns->next;\n      free_ns (t);\n    }\n}\n\f\n\n#ifdef MAKE_MAINTAINER_MODE\n\nvoid\nspin (const char* type)\n{\n  char filenm[256];\n  struct stat dummy;\n\n  sprintf (filenm, \".make-spin-%s\", type);\n\n  if (stat (filenm, &dummy) == 0)\n    {\n      fprintf (stderr, \"SPIN on %s\\n\", filenm);\n      do\n#if MK_OS_W32\n        Sleep (1000);\n#else\n        sleep (1);\n#endif\n      while (stat (filenm, &dummy) == 0);\n    }\n}\n\nvoid\ndbg (const char *fmt, ...)\n{\n  FILE *fp = fopen (\"/tmp/gmkdebug.log\", \"a+\");\n  va_list args;\n  char buf[4096];\n\n  va_start (args, fmt);\n  vsprintf (buf, fmt, args);\n  va_end (args);\n\n  fprintf(fp, \"%u: %s\\n\", (unsigned) make_pid (), buf);\n  fflush (fp);\n  fclose (fp);\n}\n\n#endif\n\n\f\n\n/* Provide support for temporary files.  */\n\n#ifndef HAVE_STDLIB_H\n# ifdef HAVE_MKSTEMP\nint mkstemp (char *template);\n# else\nchar *mktemp (char *template);\n# endif\n#endif\n\n#ifndef HAVE_UMASK\nmode_t\numask (mode_t mask)\n{\n  return 0;\n}\n#endif\n\n#if MK_OS_VMS\n# define DEFAULT_TMPFILE    \"sys$scratch:gnv$make_cmdXXXXXX.com\"\n#else\n# define DEFAULT_TMPFILE    \"GmXXXXXX\"\n#endif\n\nconst char *\nget_tmpdir ()\n{\n  static const char *tmpdir = NULL;\n\n  if (!tmpdir)\n    {\n#if MK_OS_DOS || MK_OS_W32 || MK_OS_OS2\n# define TMP_EXTRAS   \"TMP\", \"TEMP\",\n#else\n# define TMP_EXTRAS\n#endif\n      const char *tlist[] = { \"MAKE_TMPDIR\", \"TMPDIR\", TMP_EXTRAS NULL };\n      const char **tp;\n      unsigned int found = 0;\n\n      for (tp = tlist; *tp; ++tp)\n        if ((tmpdir = getenv (*tp)) != NULL && *tmpdir != '\\0')\n          {\n            struct stat st;\n            int r;\n            found = 1;\n            EINTRLOOP(r, stat (tmpdir, &st));\n            if (r < 0)\n              OSSS (error, NILF,\n                    _(\"%s value %s: %s\"), *tp, tmpdir, strerror (errno));\n            else if (! S_ISDIR (st.st_mode))\n              OSS (error, NILF,\n                   _(\"%s value %s: not a directory\"), *tp, tmpdir);\n            else\n              return tmpdir;\n          }\n\n      tmpdir = DEFAULT_TMPDIR;\n\n      if (found)\n        OS (error, NILF, _(\"using default temporary directory '%s'\"), tmpdir);\n    }\n\n  return tmpdir;\n}\n\nstatic char *\nget_tmptemplate ()\n{\n  const char *tmpdir = get_tmpdir ();\n  char *template;\n  char *cp;\n\n  template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);\n  cp = stpcpy (template, tmpdir);\n\n#if !MK_OS_VMS\n  /* It's not possible for tmpdir to be empty.  */\n  if (! ISDIRSEP (cp[-1]))\n    *(cp++) = '/';\n#endif\n\n  strcpy (cp, DEFAULT_TMPFILE);\n\n  return template;\n}\n\n#if !HAVE_MKSTEMP || !HAVE_FDOPEN\n/* Generate a temporary filename.  This is not safe as another program could\n   snipe our filename after we've generated it: use this only on systems\n   without more secure alternatives.  */\n\nstatic char *\nget_tmppath ()\n{\n  char *path;\n\n# ifdef HAVE_MKTEMP\n  path = get_tmptemplate ();\n  if (*mktemp (path) == '\\0')\n    {\n      OSS (error, NILF,\n           _(\"cannot generate temp path from %s: %s\"), path, strerror (errno));\n      return NULL;\n    }\n# else\n  path = xmalloc (L_tmpnam + 1);\n  if (tmpnam (path) == NULL)\n    {\n      OS (error, NILF,\n        _(\"cannot generate temp name: %s\"), strerror (errno));\n      return NULL;\n    }\n# endif\n\n  return path;\n}\n#endif\n\n/* Generate a temporary file and return an fd for it.  If name is NULL then\n   the temp file is anonymous and will be deleted when the process exits.  If\n   name is not null then *name will point to an allocated buffer, or set to\n   NULL on failure.  */\nint\nget_tmpfd (char **name)\n{\n  int fd = -1;\n  char *tmpnm;\n  mode_t mask;\n\n  if (name)\n    *name = NULL;\n  else\n    {\n      /* If there's an os-specific way to get an anonymous temp file use it.  */\n      fd = os_anontmp ();\n      if (fd >= 0)\n        return fd;\n    }\n\n  /* Preserve the current umask, and set a restrictive one for temp files.\n     Only really needed for mkstemp() but won't hurt for the open method.  */\n  mask = umask (0077);\n\n#if defined(HAVE_MKSTEMP)\n  tmpnm = get_tmptemplate ();\n\n  /* It's safest to use mkstemp(), if we can.  */\n  EINTRLOOP (fd, mkstemp (tmpnm));\n#else\n  tmpnm = get_tmppath ();\n  if (!tmpnm)\n    return -1;\n\n  /* Can't use mkstemp(), but try to guard against a race condition.  */\n  EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));\n#endif\n  if (fd < 0)\n    {\n      OSS (error, NILF,\n           _(\"cannot create temporary file %s: %s\"), tmpnm, strerror (errno));\n      free (tmpnm);\n      return -1;\n    }\n\n  if (name)\n    *name = tmpnm;\n  else\n    {\n      int r;\n      EINTRLOOP (r, unlink (tmpnm));\n      if (r < 0)\n        OSS (error, NILF,\n             _(\"cannot unlink temporary file %s: %s\"), tmpnm, strerror (errno));\n      free (tmpnm);\n    }\n\n  umask (mask);\n\n  return fd;\n}\n\n/* Return a FILE* for a temporary file, opened in the safest way possible.\n   Set name to point to an allocated buffer containing the name of the file,\n   or NULL on failure.  Note, name cannot be NULL!  */\nFILE *\nget_tmpfile (char **name)\n{\n  /* Be consistent with tmpfile, which opens as if by \"wb+\".  */\n  const char *tmpfile_mode = \"wb+\";\n  FILE *file;\n\n#if defined(HAVE_FDOPEN)\n  int fd;\n  assert (name);\n  fd = get_tmpfd (name);\n  if (fd < 0)\n    return NULL;\n  assert (*name);\n\n  ENULLLOOP (file, fdopen (fd, tmpfile_mode));\n  if (file == NULL)\n    OSS (error, NILF,\n         _(\"fdopen: temporary file %s: %s\"), *name, strerror (errno));\n#else\n  /* Preserve the current umask, and set a restrictive one for temp files.  */\n  mode_t mask = umask (0077);\n\n  assert (name);\n  *name = get_tmppath ();\n  if (!*name)\n    return NULL;\n\n  /* Although this fopen is insecure, it is executed only on non-fdopen\n     platforms, which should be a rarity nowadays.  */\n\n  ENULLLOOP (file, fopen (*name, tmpfile_mode));\n  if (file == NULL)\n    {\n      OSS (error, NILF,\n           _(\"fopen: temporary file %s: %s\"), *name, strerror (errno));\n      free (*name);\n      *name = NULL;\n    }\n\n  umask (mask);\n#endif\n\n  return file;\n}\n\f\n\n#if HAVE_TTYNAME && MK_OS_OS2\n/* OS/2 kLIBC has a declaration for ttyname(), so configure finds it.\n   But, it is not implemented!  Roll our own.  */\nchar *ttyname (int fd)\n{\n  ULONG type;\n  ULONG attr;\n  ULONG rc;\n\n  rc = DosQueryHType (fd, &type, &attr);\n  if (rc)\n    {\n      errno = EBADF;\n      return NULL;\n    }\n\n  if (type == HANDTYPE_DEVICE)\n    {\n      if (attr & 3)     /* 1 = KBD$, 2 = SCREEN$ */\n        return (char *) \"/dev/con\";\n\n      if (attr & 4)     /* 4 = NUL */\n        return (char *) \"/dev/nul\";\n\n      if (attr & 8)     /* 8 = CLOCK$ */\n        return (char *) \"/dev/clock$\";\n    }\n\n  errno = ENOTTY;\n  return NULL;\n}\n#endif\n\f\n\n#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI\n/* If we don't have strcasecmp() (from POSIX), or anything that can substitute\n   for it, define our own version.  */\n\nint\nstrcasecmp (const char *s1, const char *s2)\n{\n  while (1)\n    {\n      int c1 = (unsigned char) *(s1++);\n      int c2 = (unsigned char) *(s2++);\n\n      if (isalpha (c1))\n        c1 = tolower (c1);\n      if (isalpha (c2))\n        c2 = tolower (c2);\n\n      if (c1 != '\\0' && c1 == c2)\n        continue;\n\n      return (c1 - c2);\n    }\n}\n#endif\n\n#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI\n/* If we don't have strncasecmp() (from POSIX), or anything that can\n   substitute for it, define our own version.  */\n\nint\nstrncasecmp (const char *s1, const char *s2, size_t n)\n{\n  while (n-- > 0)\n    {\n      int c1 = (unsigned char) *(s1++);\n      int c2 = (unsigned char) *(s2++);\n\n      if (isalpha (c1))\n        c1 = tolower (c1);\n      if (isalpha (c2))\n        c2 = tolower (c2);\n\n      if (c1 != '\\0' && c1 == c2)\n        continue;\n\n      return (c1 - c2);\n    }\n\n  return 0;\n}\n#endif\n\f\n\n#ifdef NEED_GET_PATH_MAX\nunsigned int\nget_path_max (void)\n{\n  static unsigned int value;\n\n  if (value == 0)\n    {\n      long x = pathconf (\"/\", _PC_PATH_MAX);\n      if (x > 0)\n        value = (unsigned int) x;\n      else\n        value = PATH_MAX;\n    }\n\n  return value;\n}\n#endif\n\n#if !HAVE_MEMPCPY\nvoid *\nmempcpy (void *dest, const void *src, size_t n)\n{\n  return (char *) memcpy (dest, src, n) + n;\n}\n#endif\n\n#if !HAVE_STPCPY\nchar *\nstpcpy (char *dest, const char *src)\n{\n  char *d = dest;\n  const char *s = src;\n\n  do\n    *d++ = *s;\n  while (*s++ != '\\0');\n\n  return d - 1;\n}\n#endif\n\n#if !HAVE_STRTOLL\n# undef UNSIGNED\n# undef USE_NUMBER_GROUPING\n# undef USE_WIDE_CHAR\n# define QUAD 1\n# include <strtol.c>\n#endif\n\n#if !HAVE_STRERROR\nchar *\nstrerror (int errnum)\n{\n  static char msg[256];\n\n#define SETMSG(_e, _m) case _e: strcpy(msg, _m); break\n\n  switch (errnum)\n    {\n#ifdef EPERM\n    SETMSG (EPERM  , \"Operation not permitted\");\n#endif\n#ifdef ENOENT\n    SETMSG (ENOENT , \"No such file or directory\");\n#endif\n#ifdef ESRCH\n    SETMSG (ESRCH  , \"No such process\");\n#endif\n#ifdef EINTR\n    SETMSG (EINTR  , \"Interrupted system call\");\n#endif\n#ifdef EIO\n    SETMSG (EIO    , \"I/O error\");\n#endif\n#ifdef ENXIO\n    SETMSG (ENXIO  , \"No such device or address\");\n#endif\n#ifdef E2BIG\n    SETMSG (E2BIG  , \"Argument list too long\");\n#endif\n#ifdef ENOEXEC\n    SETMSG (ENOEXEC, \"Exec format error\");\n#endif\n#ifdef EBADF\n    SETMSG (EBADF  , \"Bad file number\");\n#endif\n#ifdef ECHILD\n    SETMSG (ECHILD , \"No child processes\");\n#endif\n#ifdef EAGAIN\n    SETMSG (EAGAIN , \"Try again\");\n#endif\n#ifdef ENOMEM\n    SETMSG (ENOMEM , \"Out of memory\");\n#endif\n#ifdef EACCES\n    SETMSG (EACCES , \"Permission denied\");\n#endif\n#ifdef EFAULT\n    SETMSG (EFAULT , \"Bad address\");\n#endif\n#ifdef ENOTBLK\n    SETMSG (ENOTBLK, \"Block device required\");\n#endif\n#ifdef EBUSY\n    SETMSG (EBUSY  , \"Device or resource busy\");\n#endif\n#ifdef EEXIST\n    SETMSG (EEXIST , \"File exists\");\n#endif\n#ifdef EXDEV\n    SETMSG (EXDEV  , \"Cross-device link\");\n#endif\n#ifdef ENODEV\n    SETMSG (ENODEV , \"No such device\");\n#endif\n#ifdef ENOTDIR\n    SETMSG (ENOTDIR, \"Not a directory\");\n#endif\n#ifdef EISDIR\n    SETMSG (EISDIR , \"Is a directory\");\n#endif\n#ifdef EINVAL\n    SETMSG (EINVAL , \"Invalid argument\");\n#endif\n#ifdef ENFILE\n    SETMSG (ENFILE , \"File table overflow\");\n#endif\n#ifdef EMFILE\n    SETMSG (EMFILE , \"Too many open files\");\n#endif\n#ifdef ENOTTY\n    SETMSG (ENOTTY , \"Not a typewriter\");\n#endif\n#ifdef ETXTBSY\n    SETMSG (ETXTBSY, \"Text file busy\");\n#endif\n#ifdef EFBIG\n    SETMSG (EFBIG  , \"File too large\");\n#endif\n#ifdef ENOSPC\n    SETMSG (ENOSPC , \"No space left on device\");\n#endif\n#ifdef ESPIPE\n    SETMSG (ESPIPE , \"Illegal seek\");\n#endif\n#ifdef EROFS\n    SETMSG (EROFS  , \"Read-only file system\");\n#endif\n#ifdef EMLINK\n    SETMSG (EMLINK , \"Too many links\");\n#endif\n#ifdef EPIPE\n    SETMSG (EPIPE  , \"Broken pipe\");\n#endif\n#ifdef EDOM\n    SETMSG (EDOM   , \"Math argument out of domain of func\");\n#endif\n#ifdef ERANGE\n    SETMSG (ERANGE , \"Math result not representable\");\n#endif\n    default: sprintf (msg, \"Unknown error %d\", errnum); break;\n    }\n\n  return msg;\n}\n#endif\n"
  },
  {
    "path": "src/mkconfig.h.in",
    "content": "/* Autoconf values for use on non-POSIX systems.\nCopyright (C) 2022-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* Name of package */\n#define PACKAGE \"@PACKAGE@\"\n\n/* Define to the address where bug reports for this package should be sent. */\n#define PACKAGE_BUGREPORT \"@PACKAGE_BUGREPORT@\"\n\n/* Define to the full name of this package. */\n#define PACKAGE_NAME \"@PACKAGE_NAME@\"\n\n/* Define to the full name and version of this package. */\n#define PACKAGE_STRING \"@PACKAGE_NAME@ @PACKAGE_VERSION@\"\n\n/* Define to the one symbol short name of this package. */\n#define PACKAGE_TARNAME \"@PACKAGE_TARNAME@\"\n\n/* Define to the home page for this package. */\n#define PACKAGE_URL \"@PACKAGE_URL@\"\n\n/* Define to the version of this package. */\n#define PACKAGE_VERSION \"@PACKAGE_VERSION@\"\n"
  },
  {
    "path": "src/mkcustom.h",
    "content": "/* Miscellaneous global declarations and portability cruft for GNU Make.\nCopyright (C) 2023-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/*\n  This file is included at the end of config.h\n\n   That means it's included _everywhere_ as the first thing,\n   INCLUDING content imported from gnulib.  BE AWARE!!\n*/\n\n#undef  HAVE_CONFIG_H\n#define HAVE_CONFIG_H 1\n\n/* Specify we want GNU source code.  This must be defined before any\n   system headers are included.  */\n\n#define _GNU_SOURCE 1\n\n/* AIX requires this to be the first thing in the file.  */\n#if HAVE_ALLOCA_H\n# include <alloca.h>\n#else\n# ifdef _AIX\n #pragma alloca\n# else\n#  if !defined(__GNUC__) && !MK_OS_W32\n#   ifndef alloca /* predefined by HP cc +Olibcalls */\nchar *alloca ();\n#   endif\n#  endif\n# endif\n#endif\n\n/* Declare function prototypes for src/misc.c functions if needed.  */\n\n#include <stddef.h>\n\n#if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI\nint strcasecmp (const char *s1, const char *s2);\n#endif\n\n#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI\nint strncasecmp (const char *s1, const char *s2, size_t n);\n#endif\n\n#if !HAVE_MEMPCPY\nvoid *mempcpy (void *dest, const void *src, size_t n);\n#endif\n\n#if !HAVE_STPCPY\nchar *stpcpy (char *dest, const char *src);\n#endif\n"
  },
  {
    "path": "src/os.h",
    "content": "/* Declarations for operating system interfaces for GNU Make.\nCopyright (C) 2016-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#define IO_UNKNOWN              0x0001\n#define IO_COMBINED_OUTERR      0x0002\n#define IO_STDIN_OK             0x0004\n#define IO_STDOUT_OK            0x0008\n#define IO_STDERR_OK            0x0010\n\n#if MK_OS_VMS || MK_OS_DOS\n# define check_io_state()       (IO_STDIN_OK|IO_STDOUT_OK|IO_STDERR_OK)\n# define fd_inherit(_i)         (0)\n# define fd_noinherit(_i)       (0)\n# define fd_set_append(_i)      (-1)\n# define fd_reset_append(_i,_f) (void)(0)\n# define os_anontmp()           (-1)\n#else\n\n/* Determine the state of stdin/stdout/stderr.  */\nunsigned int check_io_state (void);\n\n/* Set a file descriptor to close/not close in a subprocess.  */\nvoid fd_inherit (int fd);\nvoid fd_noinherit (int fd);\n\n/* If the file descriptor is for a file put it into append mode.\n   Return the original flags for the file descriptor, or -1 if not found.  */\nint fd_set_append (int fd);\n\n/* Reset the append mode to the flags returned by fd_set_append().  */\nvoid fd_reset_append (int fd, int flags);\n\n/* Return a file descriptor for a new anonymous temp file, or -1.  */\nint os_anontmp (void);\n#endif\n\n/* This section provides OS-specific functions to support the jobserver.  */\n\n#ifdef MAKE_JOBSERVER\n\n/* Returns 1 if the jobserver is enabled, else 0.  */\nunsigned int jobserver_enabled (void);\n\n/* Called in the parent make to set up the jobserver initially.  */\nunsigned int jobserver_setup (int job_slots, const char *style);\n\n/* Called in a child instance to connect to the jobserver.\n   Return 1 if we got a valid auth, else 0.  */\nunsigned int jobserver_parse_auth (const char* auth);\n\n/* Returns an allocated buffer used to pass to child instances.  */\nchar *jobserver_get_auth (void);\n\n/* Returns a pointer to a static string used to indicate that the child\n   cannot access the jobserver, or NULL if it always can.  */\nconst char *jobserver_get_invalid_auth (void);\n\n/* Clear this instance's jobserver configuration.\n   This method might be invoked from a signal handler.  */\nvoid jobserver_clear (void);\n\n/* Recover all the jobserver tokens and return the number we got.\n   Will also run jobserver_clear() as a side-effect.  */\nunsigned int jobserver_acquire_all (void);\n\n/* Release a jobserver token.  If it fails and is_fatal is 1, fatal.  */\nvoid jobserver_release (int is_fatal);\n\n/* Notify the jobserver that a child exited.  */\nvoid jobserver_signal (void);\n\n/* Get ready to start a non-recursive child.  */\nvoid jobserver_pre_child (int);\n\n/* Complete starting a non-recursive child.  */\nvoid jobserver_post_child (int);\n\n/* Set up to acquire a new token.  */\nvoid jobserver_pre_acquire (void);\n\n/* Wait until we can acquire a jobserver token.\n   TIMEOUT is 1 if we have other jobs waiting for the load to go down;\n   in this case we won't wait forever, so we can check the load.\n   Returns 1 if we got a token, or 0 if we stopped waiting due to a child\n   exiting or a timeout.    */\nunsigned int jobserver_acquire (int timeout);\n\n#else\n\n#define jobserver_enabled()             (0)\n#define jobserver_setup(_slots, _style) (0)\n#define jobserver_parse_auth(_auth)     (0)\n#define jobserver_get_auth()            (NULL)\n#define jobserver_get_invalid_auth()    (NULL)\n#define jobserver_clear()               (void)(0)\n#define jobserver_release(_fatal)       (void)(0)\n#define jobserver_acquire_all()         (0)\n#define jobserver_signal()              (void)(0)\n#define jobserver_pre_child(_r)         (void)(0)\n#define jobserver_post_child(_r)        (void)(0)\n#define jobserver_pre_acquire()         (void)(0)\n#define jobserver_acquire(_tmout)       (0)\n\n#endif  /* MAKE_JOBSERVER */\n\n#ifndef NO_OUTPUT_SYNC\n\n/* Returns 1 if output sync is enabled, else 0.  */\nunsigned int osync_enabled (void);\n\n/* Called in the parent make to set up output sync initially.  */\nvoid osync_setup (void);\n\n/* Returns an allocated buffer containing output sync info to pass to child\n   instances, or NULL if not needed.  */\nchar *osync_get_mutex (void);\n\n/* Called in a child instance to obtain info on the output sync mutex.\n   Return 1 if we got a valid mutex, else 0.  */\nunsigned int osync_parse_mutex (const char *mutex);\n\n/* Clean up this instance's output sync facilities.\n   This method might be invoked from a signal handler.  */\nvoid osync_clear (void);\n\n/* Acquire the output sync lock.  This will wait until available.\n   Returns 0 if there was an error getting the semaphore.  */\nunsigned int osync_acquire (void);\n\n/* Release the output sync lock.  */\nvoid osync_release (void);\n\n#else\n\n#define osync_enabled()       (0)\n#define osync_setup()         (void)(0)\n#define osync_get_mutex()     (0)\n#define osync_parse_mutex(_s) (0)\n#define osync_clear()         (void)(0)\n#define osync_acquire()       (1)\n#define osync_release()       (void)(0)\n\n#endif  /* NO_OUTPUT_SYNC */\n\n/* Create a \"bad\" file descriptor for stdin when parallel jobs are run.  */\n#if MK_OS_VMS || MK_OS_W32 || MK_OS_DOS\n# define get_bad_stdin() (-1)\n#else\nint get_bad_stdin (void);\n#endif\n\n#if MK_OS_W32\n#include <windows.h> /* Needed for HANDLE */\nHANDLE get_handle_for_fd (int);\n#endif\n"
  },
  {
    "path": "src/output.c",
    "content": "/* Output to stdout / stderr for GNU Make\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"os.h\"\n#include \"output.h\"\n\n/* GNU Make no longer supports pre-ANSI89 environments.  */\n\n#include <assert.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\n\n#ifdef HAVE_FCNTL_H\n# include <fcntl.h>\n#else\n# include <sys/file.h>\n#endif\n\n#if MK_OS_W32\n# include <windows.h>\n# include <io.h>\n# include \"sub_proc.h\"\n#endif\n\nstruct output *output_context = NULL;\nunsigned int stdio_traced = 0;\n\n#define OUTPUT_NONE (-1)\n\n#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)\n\n/* Write a string to the current STDOUT or STDERR.  */\nstatic void\n_outputs (struct output *out, int is_err, const char *msg)\n{\n  FILE *f;\n\n  if (out && out->syncout)\n    {\n      int fd = is_err ? out->err : out->out;\n      if (fd != OUTPUT_NONE)\n        {\n          size_t len = strlen (msg);\n          int r;\n          EINTRLOOP (r, lseek (fd, 0, SEEK_END));\n          writebuf (fd, msg, len);\n          return;\n        }\n    }\n\n  f = is_err ? stderr : stdout;\n  fputs (msg, f);\n  fflush (f);\n}\n\f\n/* Write a message indicating that we've just entered or\n   left (according to ENTERING) the current directory.  */\n\nstatic int\nlog_working_directory (int entering)\n{\n  static char *buf = NULL;\n  static size_t len = 0;\n  size_t need;\n  const char *fmt;\n  char *p;\n\n  /* Get enough space for the longest possible output.  */\n  need = strlen (program) + INTSTR_LENGTH + 2 + 1;\n  if (starting_directory)\n    need += strlen (starting_directory);\n\n  /* Use entire sentences to give the translators a fighting chance.  */\n  if (makelevel == 0)\n    if (starting_directory == 0)\n      if (entering)\n        fmt = _(\"%s: Entering an unknown directory\\n\");\n      else\n        fmt = _(\"%s: Leaving an unknown directory\\n\");\n    else\n      if (entering)\n        fmt = _(\"%s: Entering directory '%s'\\n\");\n      else\n        fmt = _(\"%s: Leaving directory '%s'\\n\");\n  else\n    if (starting_directory == 0)\n      if (entering)\n        fmt = _(\"%s[%u]: Entering an unknown directory\\n\");\n      else\n        fmt = _(\"%s[%u]: Leaving an unknown directory\\n\");\n    else\n      if (entering)\n        fmt = _(\"%s[%u]: Entering directory '%s'\\n\");\n      else\n        fmt = _(\"%s[%u]: Leaving directory '%s'\\n\");\n\n  need += strlen (fmt);\n\n  if (need > len)\n    {\n      buf = xrealloc (buf, need);\n      len = need;\n    }\n\n  p = buf;\n  if (print_data_base_flag)\n    {\n      *(p++) = '#';\n      *(p++) = ' ';\n    }\n\n  if (makelevel == 0)\n    if (starting_directory == 0)\n      sprintf (p, fmt , program);\n    else\n      sprintf (p, fmt, program, starting_directory);\n  else if (starting_directory == 0)\n    sprintf (p, fmt, program, makelevel);\n  else\n    sprintf (p, fmt, program, makelevel, starting_directory);\n\n  _outputs (NULL, 0, buf);\n\n  return 1;\n}\n\f\n\n#ifndef NO_OUTPUT_SYNC\n\n/* Support routine for output_sync() */\nstatic void\npump_from_tmp (int from, FILE *to)\n{\n  static char buffer[8192];\n\n#if MK_OS_W32\n  int prev_mode;\n\n  /* \"from\" is opened by open_tmpfd, which does it in binary mode, so\n     we need the mode of \"to\" to match that.  */\n  prev_mode = _setmode (fileno (to), _O_BINARY);\n#endif\n\n  if (lseek (from, 0, SEEK_SET) == -1)\n    perror (\"lseek()\");\n\n  while (1)\n    {\n      int len;\n      EINTRLOOP (len, read (from, buffer, sizeof (buffer)));\n      if (len < 0)\n        perror (\"read()\");\n      if (len <= 0)\n        break;\n      if (fwrite (buffer, len, 1, to) < 1)\n        {\n          perror (\"fwrite()\");\n          break;\n        }\n      fflush (to);\n    }\n\n#if MK_OS_W32\n  /* Switch \"to\" back to its original mode, so that log messages by\n     Make have the same EOL format as without --output-sync.  */\n  _setmode (fileno (to), prev_mode);\n#endif\n}\n\n/* Returns a file descriptor to a temporary file, that will be automatically\n   deleted on exit.  */\nint\noutput_tmpfd (void)\n{\n  int fd = get_tmpfd (NULL);\n  fd_set_append (fd);\n  return fd;\n}\n\n/* Adds file descriptors to the child structure to support output_sync; one\n   for stdout and one for stderr as long as they are open.  If stdout and\n   stderr share a device they can share a temp file too.\n   Will reset output_sync on error.  */\nstatic void\nsetup_tmpfile (struct output *out)\n{\n  static unsigned int in_setup = 0;\n  unsigned int io_state;\n\n  /* If something fails during setup we might recurse back into this function\n     while writing errors.  Make sure we don't do so infinitely.  */\n  if (in_setup)\n    return;\n  in_setup = 1;\n\n  io_state = check_io_state ();\n\n  if (NONE_SET (io_state, IO_STDOUT_OK|IO_STDERR_OK))\n    {\n      /* This is probably useless since stdout/stderr aren't working. */\n      perror_with_name (\"output-sync suppressed: \", \"stderr\");\n      goto error;\n    }\n\n  if (ANY_SET (io_state, IO_STDOUT_OK))\n    {\n      int fd = output_tmpfd ();\n      if (fd < 0)\n        goto error;\n      fd_noinherit (fd);\n      out->out = fd;\n    }\n\n  if (ANY_SET (io_state, IO_STDERR_OK))\n    {\n      if (out->out != OUTPUT_NONE && ANY_SET (io_state, IO_COMBINED_OUTERR))\n        out->err = out->out;\n      else\n        {\n          int fd = output_tmpfd ();\n          if (fd < 0)\n            goto error;\n          fd_noinherit (fd);\n          out->err = fd;\n        }\n    }\n\n  in_setup = 0;\n  return;\n\n  /* If we failed to create a temp file, disable output sync going forward.  */\n error:\n  O (error, NILF,\n     _(\"cannot open output-sync lock file: suppressing output-sync\"));\n\n  output_close (out);\n  output_sync = OUTPUT_SYNC_NONE;\n  osync_clear ();\n  in_setup = 0;\n}\n\n/* Synchronize the output of jobs in -j mode to keep the results of\n   each job together. This is done by holding the results in temp files,\n   one for stdout and potentially another for stderr, and only releasing\n   them to \"real\" stdout/stderr when a semaphore can be obtained. */\n\nvoid\noutput_dump (struct output *out)\n{\n#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)\n\n  int outfd_not_empty = FD_NOT_EMPTY (out->out);\n  int errfd_not_empty = FD_NOT_EMPTY (out->err);\n\n  if (outfd_not_empty || errfd_not_empty)\n    {\n      int traced = 0;\n\n      /* Try to acquire the semaphore.  If it fails, dump the output\n         unsynchronized; still better than silently discarding it.\n         We want to keep this lock for as little time as possible.  */\n      if (!osync_acquire ())\n        {\n          O (error, NILF,\n             _(\"warning: cannot acquire output lock: disabling output sync\"));\n          osync_clear ();\n        }\n\n      /* Log the working directory for this dump.  */\n\n      if (output_sync != OUTPUT_SYNC_RECURSE && should_print_dir ())\n        traced = log_working_directory (1);\n\n      if (outfd_not_empty)\n        pump_from_tmp (out->out, stdout);\n      if (errfd_not_empty && out->err != out->out)\n        pump_from_tmp (out->err, stderr);\n\n      if (traced)\n        log_working_directory (0);\n\n      /* Exit the critical section.  */\n      osync_release ();\n\n      /* Truncate and reset the output, in case we use it again.  */\n      if (out->out != OUTPUT_NONE)\n        {\n          int e;\n          lseek (out->out, 0, SEEK_SET);\n          EINTRLOOP (e, ftruncate (out->out, 0));\n        }\n      if (out->err != OUTPUT_NONE && out->err != out->out)\n        {\n          int e;\n          lseek (out->err, 0, SEEK_SET);\n          EINTRLOOP (e, ftruncate (out->err, 0));\n        }\n    }\n}\n#endif /* NO_OUTPUT_SYNC */\n\f\n\nstatic int stdout_flags = -1;\nstatic int stderr_flags = -1;\n\nvoid\noutput_init (struct output *out)\n{\n  if (out)\n    {\n      out->out = out->err = OUTPUT_NONE;\n      out->syncout = !!output_sync;\n      return;\n    }\n\n  /* Force stdout/stderr into append mode (if they are files) to ensure\n     parallel jobs won't lose output due to overlapping writes.  */\n  stdout_flags = fd_set_append (fileno (stdout));\n  stderr_flags = fd_set_append (fileno (stderr));\n}\n\nvoid\noutput_close (struct output *out)\n{\n  if (! out)\n    {\n      if (stdio_traced)\n        log_working_directory (0);\n      fd_reset_append(fileno (stdout), stdout_flags);\n      fd_reset_append(fileno (stderr), stderr_flags);\n      return;\n    }\n\n#ifndef NO_OUTPUT_SYNC\n  output_dump (out);\n#endif\n\n  if (out->out >= 0)\n    close (out->out);\n  if (out->err >= 0 && out->err != out->out)\n    close (out->err);\n\n  output_init (out);\n}\n\n/* We're about to generate output: be sure it's set up.  */\nvoid\noutput_start (void)\n{\n#ifndef NO_OUTPUT_SYNC\n  /* If we're syncing output make sure the temporary file is set up.  */\n  if (output_context && output_context->syncout)\n    if (! OUTPUT_ISSET(output_context))\n      setup_tmpfile (output_context);\n#endif\n\n  /* If we're not syncing this output per-line or per-target, make sure we emit\n     the \"Entering...\" message where appropriate.  */\n  if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)\n    if (! stdio_traced && should_print_dir ())\n      stdio_traced = log_working_directory (1);\n}\n\nvoid\noutputs (int is_err, const char *msg)\n{\n  if (! msg || *msg == '\\0')\n    return;\n\n  output_start ();\n\n  _outputs (output_context, is_err, msg);\n}\n\f\n\nstatic struct fmtstring\n  {\n    char *buffer;\n    size_t size;\n  } fmtbuf = { NULL, 0 };\n\nstatic char *\nget_buffer (size_t need)\n{\n  /* Make sure we have room.  NEED includes space for \\0.  */\n  if (need > fmtbuf.size)\n    {\n      fmtbuf.size += need * 2;\n      fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);\n    }\n\n  fmtbuf.buffer[need-1] = '\\0';\n\n  return fmtbuf.buffer;\n}\n\n/* Print a message on stdout.  */\n\nvoid\nmessage (int prefix, size_t len, const char *fmt, ...)\n{\n  va_list args;\n  char *start;\n  char *p;\n\n  len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;\n  start = p = get_buffer (len);\n\n  if (prefix)\n    {\n      if (makelevel == 0)\n        sprintf (p, \"%s: \", program);\n      else\n        sprintf (p, \"%s[%u]: \", program, makelevel);\n      p += strlen (p);\n    }\n\n  va_start (args, fmt);\n  vsprintf (p, fmt, args);\n  va_end (args);\n\n  strcat (p, \"\\n\");\n\n  assert (start[len-1] == '\\0');\n  outputs (0, start);\n}\n\n/* Print an error message.  */\n\nvoid\nerror (const floc *flocp, size_t len, const char *fmt, ...)\n{\n  va_list args;\n  char *start;\n  char *p;\n\n  len += (strlen (fmt) + strlen (program)\n          + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)\n          + INTSTR_LENGTH + 4 + 1 + 1);\n  start = p = get_buffer (len);\n\n  if (flocp && flocp->filenm)\n    sprintf (p, \"%s:%lu: \", flocp->filenm, flocp->lineno + flocp->offset);\n  else if (makelevel == 0)\n    sprintf (p, \"%s: \", program);\n  else\n    sprintf (p, \"%s[%u]: \", program, makelevel);\n  p += strlen (p);\n\n  va_start (args, fmt);\n  vsprintf (p, fmt, args);\n  va_end (args);\n\n  strcat (p, \"\\n\");\n\n  assert (start[len-1] == '\\0');\n  outputs (1, start);\n}\n\n/* Print an error message and exit.  */\n\nvoid\nfatal (const floc *flocp, size_t len, const char *fmt, ...)\n{\n  const char *stop = _(\".  Stop.\\n\");\n  va_list args;\n  char *start;\n  char *p;\n\n  len += (strlen (fmt) + strlen (program)\n          + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)\n          + INTSTR_LENGTH + 8 + strlen (stop) + 1);\n  start = p = get_buffer (len);\n\n  if (flocp && flocp->filenm)\n    sprintf (p, \"%s:%lu: *** \", flocp->filenm, flocp->lineno + flocp->offset);\n  else if (makelevel == 0)\n    sprintf (p, \"%s: *** \", program);\n  else\n    sprintf (p, \"%s[%u]: *** \", program, makelevel);\n  p += strlen (p);\n\n  va_start (args, fmt);\n  vsprintf (p, fmt, args);\n  va_end (args);\n\n  strcat (p, stop);\n\n  assert (start[len-1] == '\\0');\n  outputs (1, start);\n\n  die (MAKE_FAILURE);\n}\n\n/* Format a message and return a pointer to an internal buffer.  */\n\nchar *\nformat (const char *prefix, size_t len, const char *fmt, ...)\n{\n  va_list args;\n  size_t plen = prefix ? strlen (prefix) : 0;\n  char *start;\n  char *p;\n\n  len += strlen (fmt) + plen + 1;\n  start = p = get_buffer (len);\n\n  if (plen)\n    p = mempcpy (p, prefix, plen);\n\n  va_start (args, fmt);\n  vsprintf (p, fmt, args);\n  va_end (args);\n\n  return start;\n}\n\n/* Print an error message from errno.  */\n\nvoid\nperror_with_name (const char *str, const char *name)\n{\n  const char *err = strerror (errno);\n  OSSS (error, NILF, _(\"%s%s: %s\"), str, name, err);\n}\n\n/* Print an error message from errno and exit.  */\n\nvoid\npfatal_with_name (const char *name)\n{\n  const char *err = strerror (errno);\n  OSS (fatal, NILF, _(\"%s: %s\"), name, err);\n\n  /* NOTREACHED */\n}\n\n/* Print a message about out of memory (not using more heap) and exit.\n   Our goal here is to be sure we don't try to allocate more memory, which\n   means we don't want to use string translations or normal cleanup.  */\n\nvoid\nout_of_memory ()\n{\n  writebuf (FD_STDOUT, program, strlen (program));\n  writebuf (FD_STDOUT, STRING_SIZE_TUPLE (\": *** virtual memory exhausted\\n\"));\n  exit (MAKE_FAILURE);\n}\n"
  },
  {
    "path": "src/output.h",
    "content": "/* Output to stdout / stderr for GNU Make\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\nstruct output\n  {\n    int out;\n    int err;\n    unsigned int syncout:1;     /* True if we want to synchronize output.  */\n };\n\nextern struct output *output_context;\nextern unsigned int stdio_traced;\n\n#define FD_STDIN  (fileno (stdin))\n#define FD_STDOUT (fileno (stdout))\n#define FD_STDERR (fileno (stderr))\n\n#define OUTPUT_SET(_new)    do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0)\n#define OUTPUT_UNSET()      do{ output_context = NULL; }while(0)\n\n#define OUTPUT_TRACED()     do{ stdio_traced = 1; }while(0)\n#define OUTPUT_IS_TRACED()  (!!stdio_traced)\n\n/* Write a buffer directly to the given file descriptor.\n   This handles errors etc.  */\nint output_write (int fd, const void *buffer, size_t len);\n\n/* Initialize and close a child output structure: if NULL do this program's\n   output (this should only be done once).  */\nvoid output_init (struct output *out);\nvoid output_close (struct output *out);\n\n/* In situations where output may be about to be displayed but we're not\n   sure if we've set it up yet, call this.  */\nvoid output_start (void);\n\n/* Show a message on stdout or stderr.  Will start the output if needed.  */\nvoid outputs (int is_err, const char *msg);\n\n#if defined(NO_OUTPUT_SYNC)\n# define output_dump(_o) (void)(0)\n#else\n/* Dump any child output content to stdout, and reset it.  */\nvoid output_dump (struct output *out);\n#endif\n"
  },
  {
    "path": "src/posixos.c",
    "content": "/* POSIX-based operating system interface for GNU Make.\nCopyright (C) 2016-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <stdio.h>\n\n#ifdef HAVE_FCNTL_H\n# include <fcntl.h>\n# define FD_OK(_f) (fcntl ((_f), F_GETFD) != -1)\n#elif defined(HAVE_SYS_FILE_H)\n# include <sys/file.h>\n#endif\n#if MK_OS_ZOS\n/* FIXME: HAVE_PSELECT path hangs on z/OS */\n#undef HAVE_PSELECT\n#endif\n\n#if !defined(FD_OK)\n# define FD_OK(_f) 1\n#endif\n\n#if defined(HAVE_PSELECT) && defined(HAVE_SYS_SELECT_H)\n# include <sys/select.h>\n#endif\n\n#include \"debug.h\"\n#include \"job.h\"\n#include \"os.h\"\n\n#define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))\n\nunsigned int\ncheck_io_state ()\n{\n  static unsigned int state = IO_UNKNOWN;\n\n  /* We only need to compute this once per process.  */\n  if (state != IO_UNKNOWN)\n    return state;\n\n  if (STREAM_OK (stdin))\n    state |= IO_STDIN_OK;\n  if (STREAM_OK (stdout))\n    state |= IO_STDOUT_OK;\n  if (STREAM_OK (stderr))\n    state |= IO_STDERR_OK;\n\n  if (ALL_SET (state, IO_STDOUT_OK|IO_STDERR_OK))\n    {\n      struct stat stbuf_o, stbuf_e;\n\n      if (fstat (fileno (stdout), &stbuf_o) == 0\n          && fstat (fileno (stderr), &stbuf_e) == 0\n          && stbuf_o.st_dev == stbuf_e.st_dev\n          && stbuf_o.st_ino == stbuf_e.st_ino)\n        state |= IO_COMBINED_OUTERR;\n    }\n\n  return state;\n}\n\n#if defined(MAKE_JOBSERVER)\n\n#define FIFO_PREFIX    \"fifo:\"\n\n/* This section provides OS-specific functions to support the jobserver.  */\n\n/* True if this is the root make instance.  */\nstatic unsigned char job_root = 0;\n\n/* These track the state of the jobserver pipe.  Passed to child instances.  */\nstatic int job_fds[2] = { -1, -1 };\n\n/* Used to signal read() that a SIGCHLD happened.  Always CLOEXEC.\n   If we use pselect() this will never be created and always -1.\n */\nstatic int job_rfd = -1;\n\n/* Token written to the pipe (could be any character...)  */\nstatic char token = '+';\n\n/* The type of jobserver we're using.  */\nenum js_type\n  {\n    js_none = 0,        /* No jobserver.  */\n    js_pipe,            /* Use a simple pipe as the jobserver.  */\n    js_fifo             /* Use a named pipe as the jobserver.  */\n  };\n\nstatic enum js_type js_type = js_none;\n\n/* The name of the named pipe (if used).  */\nstatic char *fifo_name = NULL;\n\nstatic int\nmake_job_rfd ()\n{\n#ifdef HAVE_PSELECT\n  /* Pretend we succeeded.  */\n  return 0;\n#else\n  EINTRLOOP (job_rfd, dup (job_fds[0]));\n  if (job_rfd >= 0)\n    fd_noinherit (job_rfd);\n\n  return job_rfd;\n#endif\n}\n\nstatic void\nset_blocking (int fd, int blocking)\n{\n  /* If we're not using pselect() don't change the blocking.  */\n#ifdef HAVE_PSELECT\n  int flags;\n  EINTRLOOP (flags, fcntl (fd, F_GETFL));\n  if (flags >= 0)\n    {\n      int r;\n      flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);\n      EINTRLOOP (r, fcntl (fd, F_SETFL, flags));\n      if (r < 0)\n        pfatal_with_name (\"fcntl(O_NONBLOCK)\");\n    }\n#else\n  (void) fd;\n  (void) blocking;\n#endif\n}\n\nunsigned int\njobserver_setup (int slots, const char *style)\n{\n  int r;\n\n#if JOBSERVER_USE_FIFO\n  if (!style || strcmp (style, \"fifo\") == 0)\n    {\n  /* Unfortunately glibc warns about uses of mktemp even though we aren't\n     using it in dangerous way here.  So avoid this by generating our own\n     temporary file name.  The template in misc.c uses 6 X's so be sure this\n     name cannot conflict with that.  */\n# define  FNAME_PREFIX \"GmFIFO\"\n      const char *tmpdir = get_tmpdir ();\n\n      fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX)\n                           + INTSTR_LENGTH + 2);\n      sprintf (fifo_name, \"%s/\" FNAME_PREFIX \"%03\" MK_PRI64_PREFIX \"d\",\n               tmpdir, (long long)make_pid ());\n\n      EINTRLOOP (r, mkfifo (fifo_name, 0600));\n      if (r < 0)\n        {\n          perror_with_name(\"jobserver mkfifo: \", fifo_name);\n          free (fifo_name);\n          fifo_name = NULL;\n        }\n      else\n        {\n          /* We have to open the read side in non-blocking mode, else it will\n             hang until the write side is open.  */\n          EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY|O_NONBLOCK));\n          if (job_fds[0] < 0)\n            OSS (fatal, NILF, _(\"cannot open jobserver %s: %s\"),\n                 fifo_name, strerror (errno));\n\n          EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));\n          if (job_fds[0] < 0)\n            OSS (fatal, NILF, _(\"cannot open jobserver %s: %s\"),\n                 fifo_name, strerror (errno));\n\n          js_type = js_fifo;\n        }\n    }\n#endif\n\n  if (js_type == js_none)\n    {\n      if (style && strcmp (style, \"pipe\") != 0)\n        OS (fatal, NILF, _(\"unknown jobserver auth style '%s'\"), style);\n\n      EINTRLOOP (r, pipe (job_fds));\n      if (r < 0)\n        pfatal_with_name (_(\"creating jobs pipe\"));\n\n      js_type = js_pipe;\n    }\n\n  /* By default we don't send the job pipe FDs to our children.\n     See jobserver_pre_child() and jobserver_post_child().  */\n  fd_noinherit (job_fds[0]);\n  fd_noinherit (job_fds[1]);\n\n  if (make_job_rfd () < 0)\n    pfatal_with_name (_(\"duping jobs pipe\"));\n\n  while (slots--)\n    {\n      EINTRLOOP (r, write (job_fds[1], &token, 1));\n      if (r != 1)\n        pfatal_with_name (_(\"init jobserver pipe\"));\n    }\n\n  /* When using pselect() we want the read to be non-blocking.  */\n  set_blocking (job_fds[0], 0);\n\n  job_root = 1;\n\n  return 1;\n}\n\nunsigned int\njobserver_parse_auth (const char *auth)\n{\n  int rfd, wfd;\n\n  /* Given the command-line parameter, parse it.  */\n\n  /* First see if we're using a named pipe.  */\n  if (strncmp (auth, FIFO_PREFIX, CSTRLEN (FIFO_PREFIX)) == 0)\n    {\n      fifo_name = xstrdup (auth + CSTRLEN (FIFO_PREFIX));\n\n      EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY));\n      if (job_fds[0] < 0)\n        {\n          OSS (error, NILF,\n               _(\"cannot open jobserver %s: %s\"), fifo_name, strerror (errno));\n          return 0;\n        }\n\n      EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));\n      if (job_fds[1] < 0)\n        {\n          OSS (error, NILF,\n               _(\"cannot open jobserver %s: %s\"), fifo_name, strerror (errno));\n          return 0;\n        }\n      js_type = js_fifo;\n    }\n  /* If not, it must be a simple pipe.  */\n  else if (sscanf (auth, \"%d,%d\", &rfd, &wfd) == 2)\n    {\n      /* The parent overrode our FDs because we aren't a recursive make.  */\n      if (rfd == -2 || wfd == -2)\n        return 0;\n\n      /* Make sure our pipeline is valid.  */\n      if (!FD_OK (rfd) || !FD_OK (wfd))\n        return 0;\n\n      job_fds[0] = rfd;\n      job_fds[1] = wfd;\n\n      js_type = js_pipe;\n    }\n  /* Who knows what it is?  */\n  else\n    {\n      OS (error, NILF, _(\"invalid --jobserver-auth string '%s'\"), auth);\n      return 0;\n    }\n\n  /* Create a duplicate pipe, if needed, that will be closed in the SIGCHLD\n     handler.  If this fails with EBADF, the parent closed the pipe on us as\n     it didn't think we were a submake.  If so, warn and default to -j1.  */\n\n  if (make_job_rfd () < 0)\n    {\n      if (errno != EBADF)\n        pfatal_with_name (\"jobserver readfd\");\n\n      jobserver_clear ();\n\n      return 0;\n    }\n\n  /* When using pselect() we want the read to be non-blocking.  */\n  set_blocking (job_fds[0], 0);\n\n  /* By default we don't send the job pipe FDs to our children.\n     See jobserver_pre_child() and jobserver_post_child().  */\n  fd_noinherit (job_fds[0]);\n  fd_noinherit (job_fds[1]);\n\n  return 1;\n}\n\nchar *\njobserver_get_auth ()\n{\n  char *auth;\n\n  if (js_type == js_fifo) {\n    auth = xmalloc (strlen (fifo_name) + CSTRLEN (FIFO_PREFIX) + 1);\n    sprintf (auth, FIFO_PREFIX \"%s\", fifo_name);\n  } else {\n    auth = xmalloc ((INTSTR_LENGTH * 2) + 2);\n    sprintf (auth, \"%d,%d\", job_fds[0], job_fds[1]);\n  }\n\n  return auth;\n}\n\nconst char *\njobserver_get_invalid_auth ()\n{\n  /* If we're using a named pipe we don't need to invalidate the jobserver.  */\n  if (js_type == js_fifo) {\n    return NULL;\n  }\n\n  /* It's not really great that we are assuming the command line option\n     here but other alternatives are also gross.  */\n  return \" --\" JOBSERVER_AUTH_OPT \"=-2,-2\";\n}\n\nunsigned int\njobserver_enabled ()\n{\n  return js_type != js_none;\n}\n\nvoid\njobserver_clear ()\n{\n  if (job_fds[0] >= 0)\n    close (job_fds[0]);\n  if (job_fds[1] >= 0)\n    close (job_fds[1]);\n  if (job_rfd >= 0)\n    close (job_rfd);\n\n  job_fds[0] = job_fds[1] = job_rfd = -1;\n\n  if (fifo_name)\n    {\n      if (job_root)\n        {\n          int r;\n          EINTRLOOP (r, unlink (fifo_name));\n        }\n\n      if (!handling_fatal_signal)\n        {\n          free (fifo_name);\n          fifo_name = NULL;\n        }\n    }\n\n  js_type = js_none;\n}\n\nvoid\njobserver_release (int is_fatal)\n{\n  int r;\n  EINTRLOOP (r, write (job_fds[1], &token, 1));\n  if (r != 1)\n    {\n      if (is_fatal)\n        pfatal_with_name (_(\"write jobserver\"));\n      perror_with_name (\"write\", \"\");\n    }\n}\n\nunsigned int\njobserver_acquire_all ()\n{\n  int r;\n  unsigned int tokens = 0;\n\n  /* Use blocking reads to wait for all outstanding jobs.  */\n  set_blocking (job_fds[0], 1);\n\n  /* Close the write side, so the read() won't hang forever.  */\n  close (job_fds[1]);\n  job_fds[1] = -1;\n\n  while (1)\n    {\n      char intake;\n      EINTRLOOP (r, read (job_fds[0], &intake, 1));\n      if (r != 1)\n        break;\n      ++tokens;\n    }\n\n  DB (DB_JOBS, (\"Acquired all %u jobserver tokens.\\n\", tokens));\n\n  jobserver_clear ();\n\n  return tokens;\n}\n\n/* Prepare the jobserver to start a child process.  */\nvoid\njobserver_pre_child (int recursive)\n{\n  if (recursive && js_type == js_pipe)\n    {\n      fd_inherit (job_fds[0]);\n      fd_inherit (job_fds[1]);\n    }\n}\n\n/* Reconfigure the jobserver after starting a child process.  */\nvoid\njobserver_post_child (int recursive)\n{\n  if (recursive && js_type == js_pipe)\n    {\n      fd_noinherit (job_fds[0]);\n      fd_noinherit (job_fds[1]);\n    }\n}\n\nvoid\njobserver_signal ()\n{\n  if (job_rfd >= 0)\n    {\n      close (job_rfd);\n      job_rfd = -1;\n    }\n}\n\nvoid\njobserver_pre_acquire ()\n{\n  /* Make sure we have a dup'd FD.  */\n  if (job_rfd < 0 && job_fds[0] >= 0 && make_job_rfd () < 0)\n    pfatal_with_name (_(\"duping jobs pipe\"));\n}\n\n#ifdef HAVE_PSELECT\n\n/* Use pselect() to atomically wait for both a signal and a file descriptor.\n   It also provides a timeout facility so we don't need to use SIGALRM.\n\n   This method relies on the fact that SIGCHLD will be blocked everywhere,\n   and only unblocked (atomically) within the pselect() call, so we can\n   never miss a SIGCHLD.\n */\nunsigned int\njobserver_acquire (int timeout)\n{\n  struct timespec spec;\n  struct timespec *specp = NULL;\n  sigset_t empty;\n\n  sigemptyset (&empty);\n\n  if (timeout)\n    {\n      /* Alarm after one second (is this too granular?)  */\n      spec.tv_sec = 1;\n      spec.tv_nsec = 0;\n      specp = &spec;\n    }\n\n  while (1)\n    {\n      fd_set readfds;\n      int r;\n      char intake;\n\n      FD_ZERO (&readfds);\n      FD_SET (job_fds[0], &readfds);\n\n      r = pselect (job_fds[0]+1, &readfds, NULL, NULL, specp, &empty);\n      if (r < 0)\n        switch (errno)\n          {\n          case EINTR:\n            /* SIGCHLD will show up as an EINTR.  */\n            return 0;\n\n          case EBADF:\n            /* Someone closed the jobs pipe.\n               That shouldn't happen but if it does we're done.  */\n            O (fatal, NILF, _(\"job server shut down\"));\n\n          default:\n            pfatal_with_name (_(\"pselect jobs pipe\"));\n          }\n\n      if (r == 0)\n        /* Timeout.  */\n        return 0;\n\n      /* The read FD is ready: read it!  This is non-blocking.  */\n      EINTRLOOP (r, read (job_fds[0], &intake, 1));\n\n      if (r < 0)\n        {\n          /* Someone sniped our token!  Try again.  */\n          if (errno == EAGAIN)\n            continue;\n\n          pfatal_with_name (_(\"read jobs pipe\"));\n        }\n\n      /* read() should never return 0: only the parent make can reap all the\n         tokens and close the write side...??  */\n      return r > 0;\n    }\n}\n\n#else\n\n/* This method uses a \"traditional\" UNIX model for waiting on both a signal\n   and a file descriptor.  However, it's complex and since we have a SIGCHLD\n   handler installed we need to check ALL system calls for EINTR: painful!\n\n   Read a token.  As long as there's no token available we'll block.  We\n   enable interruptible system calls before the read(2) so that if we get a\n   SIGCHLD while we're waiting, we'll return with EINTR and we can process the\n   death(s) and return tokens to the free pool.\n\n   Once we return from the read, we immediately reinstate restartable system\n   calls.  This allows us to not worry about checking for EINTR on all the\n   other system calls in the program.\n\n   There is one other twist: there is a span between the time reap_children()\n   does its last check for dead children and the time the read(2) call is\n   entered, below, where if a child dies we won't notice.  This is extremely\n   serious as it could cause us to deadlock, given the right set of events.\n\n   To avoid this, we do the following: before we reap_children(), we dup(2)\n   the read FD on the jobserver pipe.  The read(2) call below uses that new\n   FD.  In the signal handler, we close that FD.  That way, if a child dies\n   during the section mentioned above, the read(2) will be invoked with an\n   invalid FD and will return immediately with EBADF.  */\n\nstatic void\njob_noop (int sig UNUSED)\n{\n}\n\n/* Set the child handler action flags to FLAGS.  */\nstatic void\nset_child_handler_action_flags (int set_handler, int set_alarm)\n{\n  struct sigaction sa;\n\n#if MK_OS_OS2\n  /* The child handler must be turned off here.  */\n  signal (SIGCHLD, SIG_DFL);\n#endif\n\n  memset (&sa, '\\0', sizeof sa);\n  sa.sa_handler = child_handler;\n  sa.sa_flags = set_handler ? 0 : SA_RESTART;\n\n#if defined SIGCHLD\n  if (sigaction (SIGCHLD, &sa, NULL) < 0)\n    pfatal_with_name (\"sigaction: SIGCHLD\");\n#endif\n\n#if defined SIGCLD && SIGCLD != SIGCHLD\n  if (sigaction (SIGCLD, &sa, NULL) < 0)\n    pfatal_with_name (\"sigaction: SIGCLD\");\n#endif\n\n#if defined SIGALRM\n  if (set_alarm)\n    {\n      /* If we're about to enter the read(), set an alarm to wake up in a\n         second so we can check if the load has dropped and we can start more\n         work.  On the way out, turn off the alarm and set SIG_DFL.  */\n      if (set_handler)\n        {\n          sa.sa_handler = job_noop;\n          sa.sa_flags = 0;\n          if (sigaction (SIGALRM, &sa, NULL) < 0)\n            pfatal_with_name (\"sigaction: SIGALRM\");\n          alarm (1);\n        }\n      else\n        {\n          alarm (0);\n          sa.sa_handler = SIG_DFL;\n          sa.sa_flags = 0;\n          if (sigaction (SIGALRM, &sa, NULL) < 0)\n            pfatal_with_name (\"sigaction: SIGALRM\");\n        }\n    }\n#endif\n}\n\nunsigned int\njobserver_acquire (int timeout)\n{\n  char intake;\n  int got_token;\n  int saved_errno;\n\n  /* Set interruptible system calls, and read() for a job token.  */\n  set_child_handler_action_flags (1, timeout);\n\n  EINTRLOOP (got_token, read (job_rfd, &intake, 1));\n  saved_errno = errno;\n\n  set_child_handler_action_flags (0, timeout);\n\n  if (got_token == 1)\n    return 1;\n\n  /* If the error _wasn't_ expected (EINTR or EBADF), fatal.  Otherwise,\n     go back and reap_children(), and try again.  */\n  errno = saved_errno;\n\n  if (errno != EINTR && errno != EBADF && errno != EAGAIN)\n    pfatal_with_name (_(\"read jobs pipe\"));\n\n  if (errno == EBADF)\n    DB (DB_JOBS, (\"Read returned EBADF.\\n\"));\n\n  return 0;\n}\n\n#endif /* HAVE_PSELECT */\n\n#endif /* MAKE_JOBSERVER */\n\n#if !defined(NO_OUTPUT_SYNC)\n\n#define MUTEX_PREFIX    \"fnm:\"\n\nstatic int osync_handle = -1;\n\nstatic char *osync_tmpfile = NULL;\n\nstatic unsigned int sync_root = 0;\n\nunsigned int\nosync_enabled ()\n{\n  return osync_handle >= 0;\n}\n\nvoid\nosync_setup ()\n{\n  osync_handle = get_tmpfd (&osync_tmpfile);\n  fd_noinherit (osync_handle);\n  sync_root = 1;\n}\n\nchar *\nosync_get_mutex ()\n{\n  char *mutex = NULL;\n\n  if (osync_enabled ())\n    {\n      /* Prepare the mutex handle string for our children.  */\n      mutex = xmalloc (strlen (osync_tmpfile) + CSTRLEN (MUTEX_PREFIX) + 1);\n      sprintf (mutex, MUTEX_PREFIX \"%s\", osync_tmpfile);\n    }\n\n  return mutex;\n}\n\nunsigned int\nosync_parse_mutex (const char *mutex)\n{\n  if (strncmp (mutex, MUTEX_PREFIX, CSTRLEN (MUTEX_PREFIX)) != 0)\n    {\n      OS (error, NILF, _(\"invalid --sync-mutex string '%s'\"), mutex);\n      return 0;\n    }\n\n  free (osync_tmpfile);\n  osync_tmpfile = xstrdup (mutex + CSTRLEN (MUTEX_PREFIX));\n\n  EINTRLOOP (osync_handle, open (osync_tmpfile, O_WRONLY));\n  if (osync_handle < 0)\n    OSS (fatal, NILF, _(\"cannot open output sync mutex %s: %s\"),\n         osync_tmpfile, strerror (errno));\n\n  fd_noinherit (osync_handle);\n\n  return 1;\n}\n\nvoid\nosync_clear ()\n{\n  if (osync_handle >= 0)\n    {\n      close (osync_handle);\n      osync_handle = -1;\n    }\n\n  if (sync_root && osync_tmpfile)\n    {\n      int r;\n\n      EINTRLOOP (r, unlink (osync_tmpfile));\n      free (osync_tmpfile);\n      osync_tmpfile = NULL;\n    }\n}\n\nunsigned int\nosync_acquire ()\n{\n  if (osync_enabled())\n    {\n      struct flock fl;\n\n      fl.l_type = F_WRLCK;\n      fl.l_whence = SEEK_SET;\n      fl.l_start = 0;\n      fl.l_len = 1;\n      /* We don't want to keep waiting on EINTR.  */\n      if (fcntl (osync_handle, F_SETLKW, &fl) == -1)\n        {\n          perror (\"fcntl()\");\n          return 0;\n        }\n    }\n\n  return 1;\n}\n\nvoid\nosync_release ()\n{\n  if (osync_enabled())\n    {\n      struct flock fl;\n\n      fl.l_type = F_UNLCK;\n      fl.l_whence = SEEK_SET;\n      fl.l_start = 0;\n      fl.l_len = 1;\n      /* We don't want to keep waiting on EINTR.  */\n      if (fcntl (osync_handle, F_SETLKW, &fl) == -1)\n        perror (\"fcntl()\");\n    }\n}\n\n#endif\n\n/* Create a \"bad\" file descriptor for stdin when parallel jobs are run.  */\nint\nget_bad_stdin ()\n{\n  static int bad_stdin = -1;\n\n  /* Set up a bad standard input that reads from a broken pipe.  */\n\n  if (bad_stdin == -1)\n    {\n      /* Make a file descriptor that is the read end of a broken pipe.\n         This will be used for some children's standard inputs.  */\n      int pd[2];\n      if (pipe (pd) == 0)\n        {\n          /* Close the write side.  */\n          close (pd[1]);\n          /* Save the read side.  */\n          bad_stdin = pd[0];\n\n          /* Set the descriptor to close on exec, so it does not litter any\n             child's descriptor table.  When it is dup2'd onto descriptor 0,\n             that descriptor will not close on exec.  */\n          fd_noinherit (bad_stdin);\n        }\n    }\n\n  return bad_stdin;\n}\n\n/* Set file descriptors to be inherited / not inherited by subprocesses.  */\n\n#if !defined(F_SETFD) || !defined(F_GETFD)\nvoid fd_inherit (int fd) {}\nvoid fd_noinherit (int fd) {}\n\n#else\n\n# ifndef FD_CLOEXEC\n#  define FD_CLOEXEC 1\n# endif\n\nvoid\nfd_inherit (int fd)\n{\n  int flags;\n  EINTRLOOP (flags, fcntl (fd, F_GETFD));\n  if (flags >= 0)\n    {\n      int r;\n      flags &= ~FD_CLOEXEC;\n      EINTRLOOP (r, fcntl (fd, F_SETFD, flags));\n    }\n}\n\nvoid\nfd_noinherit (int fd)\n{\n    int flags;\n    EINTRLOOP (flags, fcntl(fd, F_GETFD));\n    if (flags >= 0)\n      {\n        int r;\n        flags |= FD_CLOEXEC;\n        EINTRLOOP (r, fcntl(fd, F_SETFD, flags));\n      }\n}\n#endif\n\n/* Set a file descriptor referring to a regular file to be in O_APPEND mode.\n   If it fails, just ignore it.  */\n\nint\nfd_set_append (int fd)\n{\n  int flags = -1;\n#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)\n  struct stat stbuf;\n  if (fstat (fd, &stbuf) == 0 && S_ISREG (stbuf.st_mode))\n    {\n      flags = fcntl (fd, F_GETFL, 0);\n      if (flags >= 0)\n        {\n          int r;\n          EINTRLOOP(r, fcntl (fd, F_SETFL, flags | O_APPEND));\n        }\n    }\n#endif\n  return flags;\n}\n\n/* Reset a file descriptor referring to a regular file to be in O_APPEND mode.\n   If it fails, just ignore it.  */\n\nvoid\nfd_reset_append (int fd, int flags)\n{\n#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)\n  if (flags >= 0)\n    {\n      int r;\n      EINTRLOOP(r, fcntl (fd, F_SETFL, flags));\n    }\n#endif\n}\n\n/* Return a file descriptor for a new anonymous temp file, or -1.  */\nint\nos_anontmp ()\n{\n  const char *tdir = get_tmpdir ();\n  int fd = -1;\n\n#ifdef O_TMPFILE\n  static unsigned int tmpfile_works = 1;\n\n  if (tmpfile_works)\n    {\n      EINTRLOOP (fd, open (tdir, O_RDWR | O_TMPFILE | O_EXCL, 0600));\n      if (fd >= 0)\n        return fd;\n\n      DB (DB_BASIC, (_(\"Cannot open '%s' with O_TMPFILE: %s.\\n\"),\n                     tdir, strerror (errno)));\n      tmpfile_works = 0;\n    }\n#endif\n\n#if HAVE_DUP\n  /* If we can dup and we are creating temp files in the default location then\n     try tmpfile() + dup() + fclose() to avoid ever having a named file.  */\n  if (streq (tdir, DEFAULT_TMPDIR))\n    {\n      mode_t mask = umask (0077);\n      FILE *tfile;\n      ENULLLOOP (tfile, tmpfile ());\n      if (!tfile)\n        {\n          OS (error, NILF, \"tmpfile: %s\", strerror (errno));\n          return -1;\n        }\n      umask (mask);\n\n      EINTRLOOP (fd, dup (fileno (tfile)));\n      if (fd < 0)\n        OS (error, NILF, \"dup: %s\", strerror (errno));\n      fclose (tfile);\n    }\n#endif\n\n  return fd;\n}\n"
  },
  {
    "path": "src/read.c",
    "content": "/* Reading and parsing of makefiles for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#if MK_OS_W32\n# include <windows.h>\n# include \"sub_proc.h\"\n#elif MK_OS_VMS\nstruct passwd *getpwnam (char *name);\n#else\n# include <pwd.h>\n#endif\n\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"os.h\"\n#include \"commands.h\"\n#include \"variable.h\"\n#include \"rule.h\"\n#include \"debug.h\"\n#include \"hash.h\"\n#include \"warning.h\"\n\n/* A 'struct ebuffer' controls the origin of the makefile we are currently\n   eval'ing.\n*/\n\nstruct ebuffer\n  {\n    char *buffer;       /* Start of the current line in the buffer.  */\n    char *bufnext;      /* Start of the next line in the buffer.  */\n    char *bufstart;     /* Start of the entire buffer.  */\n    size_t size;        /* Malloc'd size of buffer. */\n    FILE *fp;           /* File, or NULL if this is an internal buffer.  */\n    floc floc;          /* Info on the file in fp (if any).  */\n  };\n\n/* Track the modifiers we can have on variable assignments */\n\nstruct vmodifiers\n  {\n    unsigned int assign_v:1;\n    unsigned int define_v:1;\n    unsigned int undefine_v:1;\n    unsigned int override_v:1;\n    unsigned int private_v:1;\n    enum variable_export export_v ENUM_BITFIELD (2);\n  };\n\n/* Types of \"words\" that can be read in a makefile.  */\nenum make_word_type\n  {\n     w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon,\n     w_ampcolon, w_ampdcolon\n  };\n\n\n/* A 'struct conditionals' contains the information describing\n   all the active conditionals in a makefile.\n\n   The global variable 'conditionals' contains the conditionals\n   information for the current makefile.  It is initialized from\n   the static structure 'toplevel_conditionals' and is later changed\n   to new structures for included makefiles.  */\n\nstruct conditionals\n  {\n    unsigned int if_cmds;       /* Depth of conditional nesting.  */\n    unsigned int allocated;     /* Elts allocated in following arrays.  */\n    char *ignoring;             /* Are we ignoring or interpreting?\n                                   0=interpreting, 1=not yet interpreted,\n                                   2=already interpreted */\n    char *seen_else;            /* Have we already seen an 'else'?  */\n  };\n\nstatic struct conditionals toplevel_conditionals;\nstatic struct conditionals *conditionals = &toplevel_conditionals;\n\n\n/* Default directories to search for include files in  */\n\nstatic const char *default_include_directories[] =\n  {\n#if MK_OS_W32 && !defined(INCLUDEDIR)\n/* This completely up to the user when they install MSVC or other packages.\n   This is defined as a placeholder.  */\n# define INCLUDEDIR \".\"\n#endif\n#if defined(INCLUDEDIR)\n    INCLUDEDIR,\n#endif\n    \"/usr/gnu/include\",\n    \"/usr/local/include\",\n    \"/usr/include\",\n    NULL\n  };\n\n/* List of directories to search for include files in  */\n\nstatic const char **include_directories;\n\n/* Maximum length of an element of the above.  */\n\nstatic size_t max_incl_len;\n\n/* The filename and pointer to line number of the\n   makefile currently being read in.  */\n\nconst floc *reading_file = 0;\n\n/* The chain of files read by read_all_makefiles.  */\n\nstatic struct goaldep *read_files = 0;\n\nstatic struct goaldep *eval_makefile (const char *filename, unsigned short flags);\nstatic void eval (struct ebuffer *buffer, int flags);\n\nstatic long readline (struct ebuffer *ebuf);\nstatic void do_undefine (char *name, enum variable_origin origin,\n                         struct ebuffer *ebuf);\nstatic struct variable *do_define (char *name, enum variable_origin origin,\n                                   struct ebuffer *ebuf);\nstatic int conditional_line (char *line, size_t len, const floc *flocp);\nstatic void check_specials (struct nameseq *filep, int set_default);\nstatic void check_special_file (struct file *filep, const floc *flocp);\nstatic void record_files (struct nameseq *filenames, int are_also_makes,\n                          const char *pattern,\n                          const char *pattern_percent, char *depstr,\n                          unsigned int cmds_started, char *commands,\n                          size_t commands_idx, int two_colon,\n                          char prefix, const floc *flocp);\nstatic void record_target_var (struct nameseq *filenames, char *defn,\n                               enum variable_origin origin,\n                               struct vmodifiers *vmod,\n                               const floc *flocp);\nstatic enum make_word_type get_next_mword (char *buffer,\n                                           char **startp, size_t *length);\nstatic void remove_comments (char *line);\nstatic char *find_map_unquote (char *string, int map);\nstatic char *find_char_unquote (char *string, int stop);\nstatic char *unescape_char (char *string, int c);\n\n\n/* Compare a word, both length and contents.\n   P must point to the word to be tested, and WLEN must be the length.  */\n#define word1eq(s)  (wlen == CSTRLEN (s) && memcmp (s, p, CSTRLEN (s)) == 0)\n\n\f\n/* Read in all the makefiles and return a chain of targets to rebuild.  */\n\nstruct goaldep *\nread_all_makefiles (const char **makefiles)\n{\n  unsigned int num_makefiles = 0;\n\n  /* Create *_LIST variables, to hold the makefiles, targets, and variables\n     we will be reading. */\n\n  define_variable_cname (\"MAKEFILE_LIST\", \"\", o_file, 0);\n\n  DB (DB_BASIC, (_(\"Reading makefiles...\\n\")));\n\n  /* If there's a non-null variable MAKEFILES, its value is a list of\n     files to read first thing.  But don't let it prevent reading the\n     default makefiles and don't let the default goal come from there.  */\n\n  {\n    char *value;\n    char *name, *p;\n    size_t length;\n\n    value = allocated_expand_variable (STRING_SIZE_TUPLE (\"MAKEFILES\"));\n\n    /* Set NAME to the start of next token and LENGTH to its length.\n       MAKEFILES is updated for finding remaining tokens.  */\n    p = value;\n\n    while ((name = find_next_token ((const char **)&p, &length)) != 0)\n      {\n        if (*p != '\\0')\n          *p++ = '\\0';\n        eval_makefile (strcache_add (name), RM_NO_DEFAULT_GOAL|RM_INCLUDED|RM_DONTCARE);\n      }\n\n    free (value);\n  }\n\n  /* Read makefiles specified with -f switches.  */\n\n  if (makefiles != 0)\n    while (*makefiles != 0)\n      {\n        struct goaldep *d = eval_makefile (*makefiles, 0);\n\n        if (errno)\n          perror_with_name (\"\", *makefiles);\n\n        /* Reuse the storage allocated for the read_file.  */\n        *makefiles = dep_name (d);\n        ++num_makefiles;\n        ++makefiles;\n      }\n\n  /* If there were no -f switches, try the default names.  */\n\n  if (num_makefiles == 0)\n    {\n      static const char *default_makefiles[] =\n#if MK_OS_VMS\n        /* all lower case since readdir() (the vms version) 'lowercasifies' */\n        /* TODO: Above is not always true, this needs more work */\n        { \"makefile.vms\", \"gnumakefile\", \"makefile\", 0 };\n#else\n#if MK_OS_W32\n        { \"GNUmakefile\", \"makefile\", \"Makefile\", \"makefile.mak\", 0 };\n#else /* !MK_OS_VMS && !MK_OS_W32 */\n        { \"GNUmakefile\", \"makefile\", \"Makefile\", 0 };\n#endif /* !MK_OS_VMS && !MK_OS_W32 */\n#endif /* MK_OS_VMS */\n      const char **p = default_makefiles;\n      while (*p != 0 && !file_exists_p (*p))\n        ++p;\n\n      if (*p != 0)\n        {\n          eval_makefile (*p, 0);\n          if (errno)\n            perror_with_name (\"\", *p);\n        }\n      else\n        {\n          /* No default makefile was found.  Add the default makefiles to the\n             'read_files' chain so they will be updated if possible.  */\n          for (p = default_makefiles; *p != 0; ++p)\n            {\n              struct goaldep *d = alloc_goaldep ();\n              d->file = enter_file (strcache_add (*p));\n              /* Tell update_goal_chain to bail out as soon as this file is\n                 made, and main not to die if we can't make this file.  */\n              d->flags = RM_DONTCARE;\n              d->next = read_files;\n              read_files = d;\n            }\n        }\n    }\n\n  return read_files;\n}\n\f\n/* Install a new conditional and return the previous one.  */\n\nstatic struct conditionals *\ninstall_conditionals (struct conditionals *new)\n{\n  struct conditionals *save = conditionals;\n\n  memset (new, '\\0', sizeof (*new));\n  conditionals = new;\n\n  return save;\n}\n\n/* Free the current conditionals and reinstate a saved one.  */\n\nstatic void\nrestore_conditionals (struct conditionals *saved)\n{\n  /* Free any space allocated by conditional_line.  */\n  free (conditionals->ignoring);\n  free (conditionals->seen_else);\n\n  /* Restore state.  */\n  conditionals = saved;\n}\n\f\nstatic struct goaldep *\neval_makefile (const char *filename, unsigned short flags)\n{\n  struct goaldep *deps;\n  struct ebuffer ebuf;\n  const floc *curfile;\n  char *expanded = 0;\n\n  /* Create a new goaldep entry.  */\n  deps = alloc_goaldep ();\n  deps->next = read_files;\n  read_files = deps;\n\n  ebuf.floc.filenm = filename; /* Use the original file name.  */\n  ebuf.floc.lineno = 1;\n  ebuf.floc.offset = 0;\n\n  if (ISDB (DB_VERBOSE))\n    {\n      printf (_(\"Reading makefile '%s'\"), filename);\n      if (flags & RM_NO_DEFAULT_GOAL)\n        printf (_(\" (no default goal)\"));\n      if (flags & RM_INCLUDED)\n        printf (_(\" (search path)\"));\n      if (flags & RM_DONTCARE)\n        printf (_(\" (don't care)\"));\n      if (flags & RM_NO_TILDE)\n        printf (_(\" (no ~ expansion)\"));\n      puts (\"...\");\n    }\n\n  /* First, get a stream to read.  */\n\n  /* Expand ~ in FILENAME unless it came from 'include',\n     in which case it was already done.  */\n  if (!(flags & RM_NO_TILDE) && filename[0] == '~')\n    {\n      expanded = tilde_expand (filename);\n      if (expanded != 0)\n        filename = expanded;\n    }\n\n  errno = 0;\n  ENULLLOOP (ebuf.fp, fopen (filename, \"r\"));\n  deps->error = errno;\n\n  /* Check for unrecoverable errors: out of mem or FILE slots.  */\n  switch (deps->error)\n    {\n#ifdef EMFILE\n    case EMFILE:\n#endif\n#ifdef ENFILE\n    case ENFILE:\n#endif\n    case ENOMEM:\n      {\n        const char *err = strerror (deps->error);\n        OS (fatal, reading_file, \"%s\", err);\n      }\n    }\n\n  /* If the makefile wasn't found and it's either a makefile from the\n     'MAKEFILES' variable or an included makefile, search the included\n     makefile search path for this makefile.  */\n  if (ebuf.fp == NULL && deps->error == ENOENT && include_directories\n      && ANY_SET (flags, RM_INCLUDED)\n      && !HAS_DRIVESPEC (filename) && !ISDIRSEP (*filename))\n    {\n      const char **dir;\n      for (dir = include_directories; *dir != NULL; ++dir)\n        {\n          const char *included = concat (3, *dir, \"/\", filename);\n\n          ENULLLOOP(ebuf.fp, fopen (included, \"r\"));\n          if (ebuf.fp)\n            {\n              filename = included;\n              break;\n            }\n          if (errno != ENOENT)\n            {\n              filename = included;\n              deps->error = errno;\n              break;\n            }\n        }\n    }\n\n  /* Enter the final name for this makefile as a goaldep.  */\n  filename = strcache_add (filename);\n  deps->file = lookup_file (filename);\n  if (deps->file == 0)\n    deps->file = enter_file (filename);\n  filename = deps->file->name;\n  deps->flags = flags;\n  deps->file->is_explicit = 1;\n\n  free (expanded);\n\n  if (ebuf.fp == 0)\n    {\n      /* The makefile can't be read at all, give up entirely.\n         If we did some searching errno has the error from the last attempt,\n         rather from FILENAME itself: recover the more accurate one.  */\n      errno = deps->error;\n      deps->file->last_mtime = NONEXISTENT_MTIME;\n      return deps;\n    }\n\n  /* Success; clear errno.  */\n  deps->error = 0;\n\n  /* If we tried and failed to read the included file before but this\n     time we succeeded, reset the last mtime.  */\n  if (deps->file->last_mtime == NONEXISTENT_MTIME)\n    deps->file->last_mtime = 0;\n\n  /* Avoid leaking the makefile to children.  */\n  fd_noinherit (fileno (ebuf.fp));\n\n  /* Add this makefile to the list. */\n  do_variable_definition (&ebuf.floc, \"MAKEFILE_LIST\", filename, o_file,\n                          f_append_value, 0, s_global);\n\n  /* Evaluate the makefile */\n\n  ebuf.size = 200;\n  ebuf.buffer = ebuf.bufnext = ebuf.bufstart = xmalloc (ebuf.size);\n\n  curfile = reading_file;\n  reading_file = &ebuf.floc;\n\n  eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL));\n\n  reading_file = curfile;\n\n  fclose (ebuf.fp);\n\n  free (ebuf.bufstart);\n  free_alloca ();\n\n  errno = 0;\n  return deps;\n}\n\nvoid\neval_buffer (char *buffer, const floc *flocp)\n{\n  struct ebuffer ebuf;\n  struct conditionals *saved;\n  struct conditionals new;\n  const floc *curfile;\n\n  /* Evaluate the buffer */\n\n  ebuf.size = strlen (buffer);\n  ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer;\n  ebuf.fp = NULL;\n\n  if (flocp)\n    ebuf.floc = *flocp;\n  else if (reading_file)\n    ebuf.floc = *reading_file;\n  else\n    {\n      ebuf.floc.filenm = NULL;\n      ebuf.floc.lineno = 1;\n      ebuf.floc.offset = 0;\n    }\n\n  curfile = reading_file;\n  reading_file = &ebuf.floc;\n\n  saved = install_conditionals (&new);\n\n  eval (&ebuf, 1);\n\n  restore_conditionals (saved);\n\n  reading_file = curfile;\n\n  free_alloca ();\n}\n\f\n/* Check LINE to see if it's a variable assignment or undefine.\n\n   It might use one of the modifiers \"export\", \"override\", \"private\", or it\n   might be one of the conditional tokens like \"ifdef\", \"include\", etc.\n\n   If it's not a variable assignment or undefine, VMOD.V_ASSIGN is 0.\n   Returns LINE.\n\n   Returns a pointer to the first non-modifier character, and sets VMOD\n   based on the modifiers found if any, plus V_ASSIGN is 1.\n */\nstatic char *\nparse_var_assignment (const char *line, int targvar, struct vmodifiers *vmod)\n{\n  const char *p;\n  memset (vmod, '\\0', sizeof (*vmod));\n\n  /* Find the start of the next token.  If there isn't one we're done.  */\n  NEXT_TOKEN (line);\n  if (*line == '\\0')\n    return (char *) line;\n\n  p = line;\n  while (1)\n    {\n      size_t wlen;\n      const char *p2;\n      struct variable v;\n\n      p2 = parse_variable_definition (p, &v);\n\n      /* If this is a variable assignment, we're done.  */\n      if (p2)\n        break;\n\n      /* It's not a variable; see if it's a modifier.  */\n      p2 = end_of_token (p);\n      wlen = p2 - p;\n\n      if (word1eq (\"export\"))\n        vmod->export_v = v_export;\n      else if (word1eq (\"unexport\"))\n        vmod->export_v = v_noexport;\n      else if (word1eq (\"override\"))\n        vmod->override_v = 1;\n      else if (word1eq (\"private\"))\n        vmod->private_v = 1;\n      else if (!targvar && word1eq (\"define\"))\n        {\n          /* We can't have modifiers after 'define' */\n          vmod->define_v = 1;\n          p = next_token (p2);\n          break;\n        }\n      else if (!targvar && word1eq (\"undefine\"))\n        {\n          /* We can't have modifiers after 'undefine' */\n          vmod->undefine_v = 1;\n          p = next_token (p2);\n          break;\n        }\n      else\n        /* Not a variable or modifier: this is not a variable assignment.  */\n        return (char *) line;\n\n      /* It was a modifier.  Try the next word.  */\n      p = next_token (p2);\n      if (*p == '\\0')\n        return (char *) line;\n    }\n\n  /* Found a variable assignment or undefine.  */\n  vmod->assign_v = 1;\n  return (char *)p;\n}\n\f\n\n/* Read file FILENAME as a makefile and add its contents to the data base.\n\n   SET_DEFAULT is true if we are allowed to set the default goal.  */\n\nstatic void\neval (struct ebuffer *ebuf, int set_default)\n{\n  char *collapsed = 0;\n  size_t collapsed_length = 0;\n  size_t commands_len = 200;\n  char *commands;\n  size_t commands_idx = 0;\n  unsigned int cmds_started, tgts_started;\n  int ignoring = 0, in_ignored_define = 0;\n  int no_targets = 0;           /* Set when reading a rule without targets.  */\n  int also_make_targets = 0;    /* Set when reading grouped targets. */\n  struct nameseq *filenames = 0;\n  char *depstr = 0;\n  long nlines = 0;\n  int two_colon = 0;\n  char prefix = cmd_prefix;\n  const char *pattern = 0;\n  const char *pattern_percent;\n  floc *fstart;\n  floc fi;\n\n#define record_waiting_files()                                                \\\n  do                                                                          \\\n    {                                                                         \\\n      if (filenames != 0)                                                     \\\n        {                                                                     \\\n          fi.lineno = tgts_started;                                           \\\n          fi.offset = 0;                                                      \\\n          record_files (filenames, also_make_targets, pattern,                \\\n                        pattern_percent, depstr,                              \\\n                        cmds_started, commands, commands_idx, two_colon,      \\\n                        prefix, &fi);                                         \\\n          filenames = 0;                                                      \\\n        }                                                                     \\\n      commands_idx = 0;                                                       \\\n      no_targets = 0;                                                         \\\n      pattern = 0;                                                            \\\n      also_make_targets = 0;                                                  \\\n    } while (0)\n\n  pattern_percent = 0;\n  cmds_started = tgts_started = 1;\n\n  fstart = &ebuf->floc;\n  fi.filenm = ebuf->floc.filenm;\n\n  /* Loop over lines in the file.\n     The strategy is to accumulate target names in FILENAMES, dependencies\n     in DEPS and commands in COMMANDS.  These are used to define a rule\n     when the start of the next rule (or eof) is encountered.\n\n     When you see a \"continue\" in the loop below, that means we are moving on\n     to the next line.  If you see record_waiting_files(), then the statement\n     we are parsing also finishes the previous rule.  */\n\n  commands = xmalloc (200);\n\n  while (1)\n    {\n      size_t linelen;\n      char *line;\n      size_t wlen;\n      char *p;\n      char *p2;\n      unsigned int is_rule;\n      struct vmodifiers vmod;\n\n      /* At the top of this loop, we are starting a brand new line.  */\n      /* Grab the next line to be evaluated */\n      ebuf->floc.lineno += nlines;\n      nlines = readline (ebuf);\n\n      /* If there is nothing left to eval, we're done.  */\n      if (nlines < 0)\n        break;\n\n      line = ebuf->buffer;\n\n      /* If this is the first line, check for a UTF-8 BOM and skip it.  */\n      if (ebuf->floc.lineno == 1)\n        {\n          unsigned char *ul = (unsigned char *) line;\n          if (ul[0] == 0xEF && ul[1] == 0xBB && ul[2] == 0xBF)\n            {\n              line += 3;\n              if (ISDB(DB_BASIC))\n                {\n                  if (ebuf->floc.filenm)\n                    printf (_(\"Skipping UTF-8 BOM in makefile '%s'\\n\"),\n                            ebuf->floc.filenm);\n                  else\n                    printf (_(\"Skipping UTF-8 BOM in makefile buffer\\n\"));\n                }\n            }\n        }\n      /* If this line is empty, skip it.  */\n      if (line[0] == '\\0')\n        continue;\n\n      linelen = strlen (line);\n\n      /* Check for a shell command line first.\n         If it is not one, we can stop treating cmd_prefix specially.  */\n      if (line[0] == cmd_prefix)\n        {\n          if (no_targets)\n            /* Ignore the commands in a rule with no targets.  */\n            continue;\n\n          if (ignoring)\n            /* Yep, this is a shell command, and we don't care.  */\n            continue;\n\n          /* If there is no preceding rule line, don't treat this line\n             as a command, even though it begins with a recipe prefix.\n             SunOS 4 make appears to behave this way.  */\n\n          if (filenames != 0)\n            {\n              if (commands_idx == 0)\n                cmds_started = ebuf->floc.lineno;\n\n              /* Append this command line to the line being accumulated.\n                 Skip the initial command prefix character.  */\n              if (linelen + commands_idx > commands_len)\n                {\n                  commands_len = (linelen + commands_idx) * 2;\n                  commands = xrealloc (commands, commands_len);\n                }\n              memcpy (&commands[commands_idx], line + 1, linelen - 1);\n              commands_idx += linelen - 1;\n              commands[commands_idx++] = '\\n';\n              continue;\n            }\n        }\n\n      /* This line is not a shell command line.  Don't worry about whitespace.\n         Get more space if we need it; we don't need to preserve the current\n         contents of the buffer.  */\n\n      if (collapsed_length < linelen+1)\n        {\n          collapsed_length = linelen+1;\n          free (collapsed);\n          /* Don't need xrealloc: we don't need to preserve the content.  */\n          collapsed = xmalloc (collapsed_length);\n        }\n      strcpy (collapsed, line);\n      /* Collapse continuation lines.  */\n      collapse_continuations (collapsed);\n      remove_comments (collapsed);\n\n      /* Get rid if starting space (including formfeed, vtab, etc.)  */\n      p = collapsed;\n      NEXT_TOKEN (p);\n\n      /* See if this is a variable assignment.  We need to do this early, to\n         allow variables with names like 'ifdef', 'export', 'private', etc.  */\n      p = parse_var_assignment (p, 0, &vmod);\n      if (vmod.assign_v)\n        {\n          struct variable *v;\n          enum variable_origin origin = vmod.override_v ? o_override : o_file;\n\n          /* If we're ignoring then we're done now.  */\n          if (ignoring)\n            {\n              if (vmod.define_v)\n                in_ignored_define = 1;\n              continue;\n            }\n\n          /* Variable assignment ends the previous rule.  */\n          record_waiting_files ();\n\n          if (vmod.undefine_v)\n            {\n              do_undefine (p, origin, ebuf);\n              continue;\n            }\n          if (vmod.define_v)\n            v = do_define (p, origin, ebuf);\n          else\n            v = try_variable_definition (fstart, p, origin, s_global);\n\n          assert (v != NULL);\n\n          if (vmod.export_v != v_default)\n            v->export = vmod.export_v;\n          if (vmod.private_v)\n            v->private_var = 1;\n\n          /* This line has been dealt with.  */\n          continue;\n        }\n\n      /* If this line is completely empty, ignore it.  */\n      if (*p == '\\0')\n        continue;\n\n      p2 = end_of_token (p);\n      wlen = p2 - p;\n      NEXT_TOKEN (p2);\n\n      is_rule = *p2 == ':' || ((*p2 == '&' || *p2 == '|') && p2[1] == ':');\n\n      /* If we're in an ignored define, skip this line (but maybe get out).  */\n      if (in_ignored_define)\n        {\n          /* See if this is an endef line (plus optional comment).  */\n          if (word1eq (\"endef\") && STOP_SET (*p2, MAP_COMMENT|MAP_NUL))\n            in_ignored_define = 0;\n\n          continue;\n        }\n\n      /* Check for conditional state changes.  */\n      {\n        int i = conditional_line (p, wlen, fstart);\n        if (i != -2)\n          {\n            if (i == -1)\n              O (fatal, fstart, _(\"invalid syntax in conditional\"));\n\n            ignoring = i;\n            continue;\n          }\n      }\n\n      /* Nothing to see here... move along.  */\n      if (ignoring)\n        continue;\n\n      /* Manage the \"export\" keyword used outside of variable assignment\n         as well as \"unexport\".  */\n      if (word1eq (\"export\") || word1eq (\"unexport\"))\n        {\n          int exporting = *p == 'u' ? 0 : 1;\n\n          /* Export/unexport ends the previous rule.  */\n          record_waiting_files ();\n\n          /* (un)export by itself causes everything to be (un)exported. */\n          if (*p2 == '\\0')\n            export_all_variables = exporting;\n          else\n            {\n              size_t l;\n              const char *cp;\n              char *ap;\n\n              /* Expand the line so we can use indirect and constructed\n                 variable names in an (un)export command.  */\n              cp = ap = allocated_expand_string (p2);\n\n              for (p = find_next_token (&cp, &l); p != 0;\n                   p = find_next_token (&cp, &l))\n                {\n                  struct variable *v = lookup_variable (p, l);\n                  if (v == 0)\n                    v = define_variable_global (p, l, \"\", o_file, 0, fstart);\n                  v->export = exporting ? v_export : v_noexport;\n                }\n\n              free (ap);\n            }\n          continue;\n        }\n\n      /* Handle the special syntax for vpath.  */\n      if (word1eq (\"vpath\"))\n        {\n          const char *cp;\n          char *vpat;\n          size_t l;\n\n          /* vpath ends the previous rule.  */\n          record_waiting_files ();\n\n          cp = expand_string (p2);\n          p = find_next_token (&cp, &l);\n          if (p != 0)\n            {\n              vpat = xstrndup (p, l);\n              p = find_next_token (&cp, &l);\n              /* No searchpath means remove all previous\n                 selective VPATH's with the same pattern.  */\n            }\n          else\n            /* No pattern means remove all previous selective VPATH's.  */\n            vpat = 0;\n          construct_vpath_list (vpat, p);\n          free (vpat);\n\n          continue;\n        }\n\n      /* Handle include and variants.  */\n      if (word1eq (\"include\") || word1eq (\"-include\") || word1eq (\"sinclude\"))\n        {\n          /* We have found an 'include' line specifying a nested\n             makefile to be read at this point.  */\n          struct conditionals *save;\n          struct conditionals new_conditionals;\n          struct nameseq *files;\n          /* \"-include\" (vs \"include\") says no error if the file does not\n             exist.  \"sinclude\" is an alias for this from SGI.  */\n          int noerror = (p[0] != 'i');\n\n          /* Include ends the previous rule.  */\n          record_waiting_files ();\n\n          p = allocated_expand_string (p2);\n\n          /* If no filenames, it's a no-op.  */\n          if (*p == '\\0')\n            {\n              free (p);\n              continue;\n            }\n\n          /* Parse the list of file names.  Don't expand archive references!  */\n          p2 = p;\n          files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL,\n                                  PARSEFS_NOAR);\n          free (p);\n\n          /* Save the state of conditionals and start\n             the included makefile with a clean slate.  */\n          save = install_conditionals (&new_conditionals);\n\n          /* Record the rules that are waiting so they will determine\n             the default goal before those in the included makefile.  */\n          record_waiting_files ();\n\n          /* Read each included makefile.  */\n          while (files != 0)\n            {\n              struct nameseq *next = files->next;\n              unsigned short flags = (RM_INCLUDED | RM_NO_TILDE\n                                      | (noerror ? RM_DONTCARE : 0)\n                                      | (set_default ? 0 : RM_NO_DEFAULT_GOAL));\n\n              struct goaldep *d = eval_makefile (files->name, flags);\n              d->floc = *fstart;\n\n              free_ns (files);\n              files = next;\n            }\n\n          /* Restore conditional state.  */\n          restore_conditionals (save);\n\n          continue;\n        }\n\n      /* Handle the load operations.  Allow targets named \"load\".  */\n      if ((word1eq (\"load\") || word1eq (\"-load\")) && !is_rule)\n        {\n          /* A 'load' line specifies a dynamic object to load.  */\n          struct nameseq *files;\n          int noerror = (p[0] == '-');\n\n          /* Load ends the previous rule.  */\n          record_waiting_files ();\n\n          p = allocated_expand_string (p2);\n\n          /* If no filenames, it's a no-op.  */\n          if (*p == '\\0')\n            {\n              free (p);\n              continue;\n            }\n\n          /* Parse the list of file names.\n             Don't expand archive references or strip \"./\"  */\n          p2 = p;\n          files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL,\n                                  PARSEFS_NOAR);\n          free (p);\n\n          /* Load each file.  */\n          while (files != 0)\n            {\n              struct nameseq *next = files->next;\n              const char *name = files->name;\n              struct goaldep *deps;\n              struct file *f;\n              int r;\n\n              {\n                struct file file = {0};\n                file.name = name;\n                /* Load the file.  0 means failure.  */\n                r = load_file (&ebuf->floc, &file, noerror);\n                if (! r && ! noerror)\n                  OS (fatal, &ebuf->floc, _(\"%s: failed to load\"), name);\n                name = file.name;\n              }\n\n              f = lookup_file (name);\n              if (!f)\n                f = enter_file (name);\n              f->loaded = 1;\n              f->unloaded = 0;\n\n              free_ns (files);\n              files = next;\n\n              /* Return of -1 means don't ever try to rebuild.  */\n              if (r == -1)\n                continue;\n\n              /* Otherwise add it to the list to be rebuilt.  */\n              deps = alloc_goaldep ();\n              deps->next = read_files;\n              deps->floc = ebuf->floc;\n              read_files = deps;\n              deps->file = f;\n            }\n\n          continue;\n        }\n\n      /* This line starts with a tab but was not caught above because there\n         was no preceding target, and the line might have been usable as a\n         variable definition.  But now we know it is definitely lossage.  */\n      if (line[0] == cmd_prefix)\n        O (fatal, fstart, _(\"recipe commences before first target\"));\n\n      /* This line describes some target files.  This is complicated by\n         the existence of target-specific variables, because we can't\n         expand the entire line until we know if we have one or not.  So\n         we expand the line word by word until we find the first ':',\n         then check to see if it's a target-specific variable.\n\n         In this algorithm, 'lb_next' will point to the beginning of the\n         unexpanded parts of the input buffer, while 'p2' points to the\n         parts of the expanded buffer we haven't searched yet. */\n\n      {\n        enum make_word_type wtype;\n        char *cmdleft, *semip = 0, *lb_next;\n        size_t plen = 0;\n        char *colonp;\n        const char *end, *beg; /* Helpers for whitespace stripping. */\n\n        /* Record the previous rule.  */\n\n        record_waiting_files ();\n        tgts_started = fstart->lineno;\n\n        /* Search the line for an unquoted ; that is not after an\n           unquoted #.  */\n        cmdleft = find_map_unquote (line, MAP_SEMI|MAP_COMMENT|MAP_VARIABLE);\n        if (cmdleft != 0 && *cmdleft == '#')\n          {\n            /* We found a comment before a semicolon.  */\n            *cmdleft = '\\0';\n            cmdleft = 0;\n          }\n        else if (cmdleft != 0)\n          {\n            /* Found one.  Cut the line short there before expanding it.  */\n            semip = cmdleft++;\n            *semip = '\\0';\n          }\n\n        collapse_continuations (line);\n\n        /* We can't expand the entire line, since if it's a per-target\n           variable we don't want to expand it.  So, walk from the\n           beginning, expanding as we go, and looking for \"interesting\"\n           chars.  The first word is always expandable.  */\n        wtype = get_next_mword (line, &lb_next, &wlen);\n        switch (wtype)\n          {\n          case w_eol:\n            if (cmdleft != 0)\n              O (fatal, fstart, _(\"missing rule before recipe\"));\n            /* This line contained something but turned out to be nothing\n               but whitespace (a comment?).  */\n            continue;\n\n          case w_colon:\n          case w_dcolon:\n          case w_ampcolon:\n          case w_ampdcolon:\n            /* We accept and ignore rules without targets for\n               compatibility with SunOS 4 make.  */\n            no_targets = 1;\n            continue;\n\n          default:\n            break;\n          }\n\n        p2 = expand_string_buf (NULL, lb_next, wlen);\n\n        while (1)\n          {\n            lb_next += wlen;\n            if (cmdleft == 0)\n              {\n                /* Look for a semicolon in the expanded line.  */\n                cmdleft = find_char_unquote (p2, ';');\n\n                if (cmdleft != 0)\n                  {\n                    size_t p2_off = p2 - variable_buffer;\n                    size_t cmd_off = cmdleft - variable_buffer;\n                    char *pend = p2 + strlen (p2);\n\n                    /* Append any remnants of lb, then cut the line short\n                       at the semicolon.  */\n                    *cmdleft = '\\0';\n\n                    /* One school of thought says that you shouldn't expand\n                       here, but merely copy, since now you're beyond a \";\"\n                       and into a command script.  However, the old parser\n                       expanded the whole line, so we continue that for\n                       backwards-compatibility.  Also, it wouldn't be\n                       entirely consistent, since we do an unconditional\n                       expand below once we know we don't have a\n                       target-specific variable. */\n                    expand_string_buf (pend, lb_next, SIZE_MAX);\n                    lb_next += strlen (lb_next);\n                    p2 = variable_buffer + p2_off;\n                    cmdleft = variable_buffer + cmd_off + 1;\n                  }\n              }\n\n            colonp = find_char_unquote (p2, ':');\n\n#ifdef HAVE_DOS_PATHS\n            if (colonp > p2)\n              /* The drive spec brain-damage strikes again...\n                 Note that the only separators of targets in this context are\n                 whitespace and a left paren.  If others are possible, add them\n                 to the string in the call to strchr.  */\n              while (colonp && ISDIRSEP (colonp[1]) &&\n                     isalpha ((unsigned char) colonp[-1]) &&\n                     (colonp == p2 + 1 || strchr (\" \\t(\", colonp[-2]) != 0))\n                colonp = find_char_unquote (colonp + 1, ':');\n#endif\n\n            if (colonp)\n              {\n                /* If the previous character is '&', back up before '&:' */\n                if (colonp > p2 && colonp[-1] == '&')\n                  --colonp;\n\n                break;\n              }\n\n            wtype = get_next_mword (lb_next, &lb_next, &wlen);\n            if (wtype == w_eol)\n              break;\n\n            p2 += strlen (p2);\n            *(p2++) = ' ';\n            p2 = expand_string_buf (p2, lb_next, wlen);\n            /* We don't need to worry about cmdleft here, because if it was\n               found in the variable_buffer the entire buffer has already\n               been expanded... we'll never get here.  */\n          }\n\n        p2 = next_token (variable_buffer);\n\n        /* If we're at EOL we didn't find a separator so we don't know what\n           kind of line this is.  */\n        if (wtype == w_eol)\n          {\n            /* Ignore an empty line.  */\n            if (*p2 == '\\0')\n              continue;\n\n            /* Check for spaces instead of TAB.  */\n            if (cmd_prefix == '\\t' && strneq (line, \"        \", 8))\n              O (fatal, fstart, _(\"missing separator (did you mean TAB instead of 8 spaces?)\"));\n\n            /* Check for conditionals without whitespace afterward.\n               We don't check ifdef/ifndef because there's no real way to miss\n               whitespace there.  */\n            p2 = next_token (line);\n            if (strneq (p2, \"if\", 2) &&\n                ((strneq (&p2[2], \"neq\", 3) && !STOP_SET (p2[5], MAP_BLANK))\n                 || (strneq (&p2[2], \"eq\", 2) && !STOP_SET (p2[4], MAP_BLANK))))\n              O (fatal, fstart, _(\"missing separator (ifeq/ifneq must be followed by whitespace)\"));\n\n            /* No idea...  */\n            O (fatal, fstart, _(\"missing separator\"));\n          }\n\n        {\n          char save = *colonp;\n\n          /* If we have &:, it specifies that the targets are understood to be\n             updated/created together by a single invocation of the recipe. */\n          if (save == '&')\n            also_make_targets = 1;\n\n          /* Make the colon the end-of-string so we know where to stop\n             looking for targets.  Start there again once we're done.  */\n          *colonp = '\\0';\n          filenames = PARSE_SIMPLE_SEQ (&p2, struct nameseq);\n          *colonp = save;\n          p2 = colonp + (save == '&');\n        }\n\n        if (!filenames)\n          {\n            /* We accept and ignore rules without targets for\n               compatibility with SunOS 4 make.  */\n            no_targets = 1;\n            continue;\n          }\n        /* This should never be possible; we handled it above.  */\n        assert (*p2 != '\\0');\n        ++p2;\n\n        /* Is this a one-colon or two-colon entry?  */\n        two_colon = *p2 == ':';\n        if (two_colon)\n          p2++;\n\n        /* Test to see if it's a target-specific variable.  Copy the rest\n           of the buffer over, possibly temporarily (we'll expand it later\n           if it's not a target-specific variable).  PLEN saves the length\n           of the unparsed section of p2, for later.  */\n        if (*lb_next != '\\0')\n          {\n            size_t l = p2 - variable_buffer;\n            plen = strlen (p2);\n            variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1);\n            p2 = variable_buffer + l;\n          }\n\n        p2 = parse_var_assignment (p2, 1, &vmod);\n        if (vmod.assign_v)\n          {\n            /* If there was a semicolon found, add it back, plus anything\n               after it.  */\n            if (semip)\n              {\n                size_t l = p2 - variable_buffer;\n                *semip = ';';\n                collapse_continuations (semip);\n                variable_buffer_output (p2 + strlen (p2),\n                                        semip, strlen (semip)+1);\n                p2 = variable_buffer + l;\n              }\n            record_target_var (filenames, p2,\n                               vmod.override_v ? o_override : o_file,\n                               &vmod, fstart);\n            filenames = 0;\n            continue;\n          }\n\n        /* This is a normal target, _not_ a target-specific variable.\n           Unquote any = in the dependency list.  */\n        find_char_unquote (lb_next, '=');\n\n        /* Remember the command prefix for this target.  */\n        prefix = cmd_prefix;\n\n        /* We have some targets, so don't ignore the following commands.  */\n        no_targets = 0;\n\n        /* Expand the dependencies, etc.  */\n        if (*lb_next != '\\0')\n          {\n            size_t l = p2 - variable_buffer;\n            expand_string_buf (p2 + plen, lb_next, SIZE_MAX);\n            p2 = variable_buffer + l;\n\n            /* Look for a semicolon in the expanded line.  */\n            if (cmdleft == 0)\n              {\n                cmdleft = find_char_unquote (p2, ';');\n                if (cmdleft != 0)\n                  *(cmdleft++) = '\\0';\n              }\n          }\n\n        /* Is this a static pattern rule: 'target: %targ: %dep; ...'?  */\n        p = strchr (p2, ':');\n        while (p != 0 && p[-1] == '\\\\')\n          {\n            char *q = &p[-1];\n            int backslash = 0;\n            while (*q-- == '\\\\')\n              backslash = !backslash;\n            if (backslash)\n              p = strchr (p + 1, ':');\n            else\n              break;\n          }\n#ifdef HAVE_DOS_PATHS\n        {\n          int check_again;\n          do {\n            check_again = 0;\n            /* For DOS-style paths, skip a \"C:\\...\" or a \"C:/...\" */\n            if (p != 0 && ISDIRSEP (p[1]) && isalpha ((unsigned char)p[-1]) &&\n                (p == p2 + 1 || strchr (\" \\t:(\", p[-2]) != 0)) {\n              p = strchr (p + 1, ':');\n              check_again = 1;\n            }\n          } while (check_again);\n        }\n#endif\n        if (p != 0)\n          {\n            struct nameseq *target;\n            target = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_COLON, NULL,\n                                     PARSEFS_NOGLOB);\n            ++p2;\n            if (target == 0)\n              O (fatal, fstart, _(\"missing target pattern\"));\n            else if (target->next != 0)\n              O (fatal, fstart, _(\"multiple target patterns\"));\n            pattern_percent = find_percent_cached (&target->name);\n            pattern = target->name;\n            if (pattern_percent == 0)\n              O (fatal, fstart, _(\"target pattern contains no '%%'\"));\n            free_ns (target);\n          }\n        else\n          pattern = 0;\n\n        /* Strip leading and trailing whitespaces. */\n        beg = p2;\n        end = beg + strlen (beg) - 1;\n        strip_whitespace (&beg, &end);\n\n        /* Put all the prerequisites here; they'll be parsed later.  */\n        if (beg <= end && *beg != '\\0')\n          depstr = xstrndup (beg, end - beg + 1);\n        else\n          depstr = 0;\n\n        commands_idx = 0;\n        if (cmdleft != 0)\n          {\n            /* Semicolon means rest of line is a command.  */\n            size_t l = strlen (cmdleft);\n\n            cmds_started = fstart->lineno;\n\n            /* Add this command line to the buffer.  */\n            if (l + 2 > commands_len)\n              {\n                commands_len = (l + 2) * 2;\n                commands = xrealloc (commands, commands_len);\n              }\n            memcpy (commands, cmdleft, l);\n            commands_idx += l;\n            commands[commands_idx++] = '\\n';\n          }\n\n        check_specials (filenames, set_default);\n      }\n    }\n\n#undef word1eq\n\n  if (conditionals->if_cmds)\n    O (fatal, fstart, _(\"missing 'endif'\"));\n\n  /* At eof, record the last rule.  */\n  record_waiting_files ();\n\n  free (collapsed);\n  free (commands);\n}\n\f\n\n/* Remove comments from LINE.\n   This will also remove backslashes that escape things.\n   It ignores comment characters that appear inside variable references.  */\n\nstatic void\nremove_comments (char *line)\n{\n  char *comment;\n\n  comment = find_map_unquote (line, MAP_COMMENT|MAP_VARIABLE);\n\n  if (comment != 0)\n    /* Cut off the line at the #.  */\n    *comment = '\\0';\n}\n\n/* Execute a 'undefine' directive.\n   The undefine line has already been read, and NAME is the name of\n   the variable to be undefined. */\n\nstatic void\ndo_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf)\n{\n  char *p, *var;\n\n  /* Expand the variable name and find the beginning (NAME) and end.  */\n  var = allocated_expand_string (name);\n  name = next_token (var);\n  if (*name == '\\0')\n    O (fatal, &ebuf->floc, _(\"empty variable name\"));\n  p = name + strlen (name) - 1;\n  while (p > name && ISBLANK (*p))\n    --p;\n  p[1] = '\\0';\n\n  undefine_variable_global (&ebuf->floc, name, p - name + 1, origin);\n  free (var);\n}\n\n/* Execute a 'define' directive.\n   The first line has already been read, and NAME is the name of\n   the variable to be defined.  The following lines remain to be read.  */\n\nstatic struct variable *\ndo_define (char *name, enum variable_origin origin, struct ebuffer *ebuf)\n{\n  struct variable *v;\n  struct variable var;\n  floc defstart;\n  int nlevels = 1;\n  size_t length = 100;\n  char *definition = xmalloc (length);\n  size_t idx = 0;\n  char *p, *n;\n\n  defstart = ebuf->floc;\n\n  p = parse_variable_definition (name, &var);\n  if (p == NULL)\n    {\n      /* No assignment token, so assume recursive.  */\n      var.flavor = f_recursive;\n      var.conditional = 0;\n    }\n  else\n    {\n      if (var.value[0] != '\\0')\n        O (error, &defstart, _(\"extraneous text after 'define' directive\"));\n\n      /* Chop the string before the assignment token to get the name.  */\n      var.name[var.length] = '\\0';\n    }\n\n  /* Expand the variable name and find the beginning (NAME) and end.  */\n  n = allocated_expand_string (name);\n  name = next_token (n);\n  if (name[0] == '\\0')\n    O (fatal, &defstart, _(\"empty variable name\"));\n  p = name + strlen (name) - 1;\n  while (p > name && ISBLANK (*p))\n    --p;\n  p[1] = '\\0';\n\n  /* Now read the value of the variable.  */\n  while (1)\n    {\n      size_t len;\n      char *line;\n      long nlines = readline (ebuf);\n\n      /* If there is nothing left to be eval'd, there's no 'endef'!!  */\n      if (nlines < 0)\n        O (fatal, &defstart, _(\"missing 'endef', unterminated 'define'\"));\n\n      ebuf->floc.lineno += nlines;\n      line = ebuf->buffer;\n\n      collapse_continuations (line);\n\n      /* If the line doesn't begin with a tab, test to see if it introduces\n         another define, or ends one.  Stop if we find an 'endef' */\n      if (line[0] != cmd_prefix)\n        {\n          p = next_token (line);\n          len = strlen (p);\n\n          /* If this is another 'define', increment the level count.  */\n          if ((len == 6 || (len > 6 && ISBLANK (p[6])))\n              && strneq (p, \"define\", 6))\n            ++nlevels;\n\n          /* If this is an 'endef', decrement the count.  If it's now 0,\n             we've found the last one.  */\n          else if ((len == 5 || (len > 5 && ISBLANK (p[5])))\n                   && strneq (p, \"endef\", 5))\n            {\n              p += 5;\n              remove_comments (p);\n              if (*(next_token (p)) != '\\0')\n                O (error, &ebuf->floc,\n                   _(\"extraneous text after 'endef' directive\"));\n\n              if (--nlevels == 0)\n                break;\n            }\n        }\n\n      /* Add this line to the variable definition.  */\n      len = strlen (line);\n      if (idx + len + 1 > length)\n        {\n          length = (idx + len) * 2;\n          definition = xrealloc (definition, length + 1);\n        }\n\n      memcpy (&definition[idx], line, len);\n      idx += len;\n      /* Separate lines with a newline.  */\n      definition[idx++] = '\\n';\n    }\n\n  /* We've got what we need; define the variable.  */\n  if (idx == 0)\n    definition[0] = '\\0';\n  else\n    definition[idx - 1] = '\\0';\n\n  v = do_variable_definition (&defstart, name, definition, origin, var.flavor,\n                              var.conditional, s_global);\n  free (definition);\n  free (n);\n  return (v);\n}\n\f\n/* Interpret conditional commands \"ifdef\", \"ifndef\", \"ifeq\",\n   \"ifneq\", \"else\" and \"endif\".\n   LINE is the input line, with the command as its first word.\n\n   FILENAME and LINENO are the filename and line number in the\n   current makefile.  They are used for error messages.\n\n   Value is -2 if the line is not a conditional at all,\n   -1 if the line is an invalid conditional,\n   0 if following text should be interpreted,\n   1 if following text should be ignored.  */\n\nstatic int\nconditional_line (char *line, size_t len, const floc *flocp)\n{\n  const char *cmdname;\n  enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq, c_else, c_endif } cmdtype;\n  unsigned int i;\n  unsigned int o;\n\n  /* Compare a word, both length and contents. */\n#define word1eq(s)      (len == CSTRLEN (s) && strneq (s, line, CSTRLEN (s)))\n#define chkword(s, t)   if (word1eq (s)) { cmdtype = (t); cmdname = (s); }\n\n  /* Make sure this line is a conditional.  */\n  chkword (\"ifdef\", c_ifdef)\n  else chkword (\"ifndef\", c_ifndef)\n  else chkword (\"ifeq\", c_ifeq)\n  else chkword (\"ifneq\", c_ifneq)\n  else chkword (\"else\", c_else)\n  else chkword (\"endif\", c_endif)\n  else\n    return -2;\n\n  /* Found one: skip past it and any whitespace after it.  */\n  line += len;\n  NEXT_TOKEN (line);\n\n#define EXTRATEXT() OS (error, flocp, _(\"extraneous text after '%s' directive\"), cmdname)\n#define EXTRACMD()  OS (fatal, flocp, _(\"extraneous '%s'\"), cmdname)\n\n  /* An 'endif' cannot contain extra text, and reduces the if-depth by 1  */\n  if (cmdtype == c_endif)\n    {\n      if (*line != '\\0')\n        EXTRATEXT ();\n\n      if (!conditionals->if_cmds)\n        EXTRACMD ();\n\n      --conditionals->if_cmds;\n\n      goto DONE;\n    }\n\n  /* An 'else' statement can either be simple, or it can have another\n     conditional after it.  */\n  if (cmdtype == c_else)\n    {\n      const char *p;\n\n      if (!conditionals->if_cmds)\n        EXTRACMD ();\n\n      o = conditionals->if_cmds - 1;\n\n      if (conditionals->seen_else[o])\n        O (fatal, flocp, _(\"only one 'else' per conditional\"));\n\n      /* Change the state of ignorance.  */\n      switch (conditionals->ignoring[o])\n        {\n          case 0:\n            /* We've just been interpreting.  Never do it again.  */\n            conditionals->ignoring[o] = 2;\n            break;\n          case 1:\n            /* We've never interpreted yet.  Maybe this time!  */\n            conditionals->ignoring[o] = 0;\n            break;\n        }\n\n      /* It's a simple 'else'.  */\n      if (*line == '\\0')\n        {\n          conditionals->seen_else[o] = 1;\n          goto DONE;\n        }\n\n      /* The 'else' has extra text.  That text must be another conditional\n         and cannot be an 'else' or 'endif'.  */\n\n      /* Find the length of the next word.  */\n      for (p = line+1; ! STOP_SET (*p, MAP_SPACE|MAP_NUL); ++p)\n        ;\n      len = p - line;\n\n      /* If it's 'else' or 'endif' or an illegal conditional, fail.  */\n      if (word1eq (\"else\") || word1eq (\"endif\")\n          || conditional_line (line, len, flocp) < 0)\n        EXTRATEXT ();\n      else\n        {\n          /* conditional_line() created a new level of conditional.\n             Raise it back to this level.  */\n          if (conditionals->ignoring[o] < 2)\n            conditionals->ignoring[o] = conditionals->ignoring[o+1];\n          --conditionals->if_cmds;\n        }\n\n      goto DONE;\n    }\n\n  if (conditionals->allocated == 0)\n    {\n      conditionals->allocated = 5;\n      conditionals->ignoring = xmalloc (conditionals->allocated);\n      conditionals->seen_else = xmalloc (conditionals->allocated);\n    }\n\n  o = conditionals->if_cmds++;\n  if (conditionals->if_cmds > conditionals->allocated)\n    {\n      conditionals->allocated += 5;\n      conditionals->ignoring = xrealloc (conditionals->ignoring,\n                                         conditionals->allocated);\n      conditionals->seen_else = xrealloc (conditionals->seen_else,\n                                          conditionals->allocated);\n    }\n\n  /* Record that we have seen an 'if...' but no 'else' so far.  */\n  conditionals->seen_else[o] = 0;\n\n  /* Search through the stack to see if we're already ignoring.  */\n  for (i = 0; i < o; ++i)\n    if (conditionals->ignoring[i])\n      {\n        /* We are already ignoring, so just push a level to match the next\n           \"else\" or \"endif\", and keep ignoring.  We don't want to expand\n           variables in the condition.  */\n        conditionals->ignoring[o] = 1;\n        return 1;\n      }\n\n  if (cmdtype == c_ifdef || cmdtype == c_ifndef)\n    {\n      size_t l;\n      char *var;\n      struct variable *v;\n      char *p;\n\n      /* Expand the thing we're looking up, so we can use indirect and\n         constructed variable names.  */\n      var = allocated_expand_string (line);\n\n      /* Make sure there's only one variable name to test.  */\n      p = end_of_token (var);\n      l = p - var;\n      NEXT_TOKEN (p);\n      if (*p != '\\0')\n        return -1;\n\n      var[l] = '\\0';\n      v = lookup_variable (var, l);\n\n      conditionals->ignoring[o] =\n        ((v != 0 && *v->value != '\\0') == (cmdtype == c_ifndef));\n\n      free (var);\n    }\n  else\n    {\n      /* \"ifeq\" or \"ifneq\".  */\n      char *s1, *s2;\n      size_t l;\n      char termin = *line == '(' ? ',' : *line;\n\n      if (termin != ',' && termin != '\"' && termin != '\\'')\n        return -1;\n\n      s1 = ++line;\n      /* Find the end of the first string.  */\n      while (*line != '\\0' && *line != termin)\n        if (*line == '$')\n          line = skip_reference (line+1);\n        else\n          ++line;\n\n      if (*line == '\\0')\n        return -1;\n\n      if (termin == ',')\n        {\n          /* Strip blanks before the comma.  */\n          char *p = line++;\n          while (ISBLANK (p[-1]))\n            --p;\n          *p = '\\0';\n        }\n      else\n        *line++ = '\\0';\n\n      s2 = expand_string (s1);\n      /* We must allocate a new copy of the expanded string because\n         expand_string re-uses the same buffer.  */\n      l = strlen (s2);\n      s1 = alloca (l + 1);\n      memcpy (s1, s2, l + 1);\n\n      if (termin != ',')\n        /* Find the start of the second string.  */\n        NEXT_TOKEN (line);\n\n      termin = termin == ',' ? ')' : *line;\n      if (termin != ')' && termin != '\"' && termin != '\\'')\n        return -1;\n\n      /* Find the end of the second string.  */\n      if (termin == ')')\n        {\n          int count = 0;\n          s2 = next_token (line);\n          for (line = s2; *line != '\\0'; ++line)\n            {\n              if (*line == '(')\n                ++count;\n              else if (*line == ')')\n                {\n                  if (count <= 0)\n                    break;\n                  else\n                    --count;\n                }\n            }\n        }\n      else\n        {\n          ++line;\n          s2 = line;\n          while (*line != '\\0' && *line != termin)\n            ++line;\n        }\n\n      if (*line == '\\0')\n        return -1;\n\n      *(line++) = '\\0';\n      NEXT_TOKEN (line);\n      if (*line != '\\0')\n        EXTRATEXT ();\n\n      s2 = expand_string (s2);\n      conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq));\n    }\n\n DONE:\n  /* Search through the stack to see if we're ignoring.  */\n  for (i = 0; i < conditionals->if_cmds; ++i)\n    if (conditionals->ignoring[i])\n      return 1;\n  return 0;\n}\n\f\n\n/* Record target-specific variable values for files FILENAMES.\n   TWO_COLON is nonzero if a double colon was used.\n\n   The links of FILENAMES are freed, and so are any names in it\n   that are not incorporated into other data structures.\n\n   If the target is a pattern, add the variable to the pattern-specific\n   variable value list.  */\n\nstatic void\nrecord_target_var (struct nameseq *filenames, char *defn,\n                   enum variable_origin origin, struct vmodifiers *vmod,\n                   const floc *flocp)\n{\n  struct nameseq *nextf;\n  struct variable_set_list *global;\n\n  global = current_variable_set_list;\n\n  /* If the variable is an append version, store that but treat it as a\n     normal recursive variable.  */\n\n  for (; filenames != 0; filenames = nextf)\n    {\n      struct variable *v;\n      const char *name = filenames->name;\n      const char *percent;\n      struct pattern_var *p;\n\n      nextf = filenames->next;\n      free_ns (filenames);\n\n      /* If it's a pattern target, then add it to the pattern-specific\n         variable list.  */\n      percent = find_percent_cached (&name);\n      if (percent)\n        {\n          /* Get a reference for this pattern-specific variable struct.  */\n          p = create_pattern_var (name, percent);\n          p->variable.fileinfo = *flocp;\n          /* I don't think this can fail since we already determined it was a\n             variable definition.  */\n          v = assign_variable_definition (&p->variable, defn);\n          assert (v != 0);\n\n          v->origin = origin;\n          if (v->flavor == f_simple)\n            v->value = allocated_expand_string (v->value);\n          else\n            v->value = xstrdup (v->value);\n        }\n      else\n        {\n          struct file *f;\n\n          /* Get a file reference for this file, and initialize it.\n             We don't want to just call enter_file() because that allocates a\n             new entry if the file is a double-colon, which we don't want in\n             this situation.  */\n          f = lookup_file (name);\n          if (!f)\n            f = enter_file (strcache_add (name));\n          else if (f->double_colon)\n            f = f->double_colon;\n\n          initialize_file_variables (f, 1);\n\n          current_variable_set_list = f->variables;\n          v = try_variable_definition (flocp, defn, origin, s_target);\n          if (!v)\n            O (fatal, flocp, _(\"malformed target-specific variable definition\"));\n          current_variable_set_list = global;\n        }\n\n      /* Set up the variable to be *-specific.  */\n      v->per_target = 1;\n      v->private_var = vmod->private_v;\n      if (vmod->export_v != v_default)\n        v->export = vmod->export_v;\n\n      /* If it's not an override, check to see if there was a command-line\n         setting.  If so, reset the value.  */\n      if (v->origin != o_override)\n        {\n          struct variable *gv;\n          size_t len = strlen (v->name);\n\n          gv = lookup_variable (v->name, len);\n          if (gv && v != gv\n              && (gv->origin == o_env_override || gv->origin == o_command))\n            {\n              free (v->value);\n              v->value = xstrdup (gv->value);\n              v->origin = gv->origin;\n              v->recursive = gv->recursive;\n              v->append = 0;\n            }\n        }\n    }\n}\n\f\n\n/* Check for special targets.  We used to do this in record_files() but that's\n   too late: by the time we get there we'll have already parsed the next line\n   and it have been mis-parsed because these special targets haven't been\n   considered yet.  */\n\nstatic void\ncheck_specials (struct nameseq *files, int set_default)\n{\n  struct nameseq *t;\n\n  for (t = files; t != NULL; t = t->next)\n    {\n      const char* nm = t->name;\n\n      if (!posix_pedantic && streq (nm, \".POSIX\"))\n        {\n          posix_pedantic = 1;\n          define_variable_cname (\".SHELLFLAGS\", \"-ec\", o_default, 0);\n          /* These default values are based on IEEE Std 1003.1-2008.\n             It requires '-O 1' for [CF]FLAGS, but GCC doesn't allow\n             space between -O and the number so omit it here.  */\n          define_variable_cname (\"CC\", \"c99\", o_default, 0);\n          define_variable_cname (\"CFLAGS\", \"-O1\", o_default, 0);\n          define_variable_cname (\"FC\", \"fort77\", o_default, 0);\n          define_variable_cname (\"FFLAGS\", \"-O1\", o_default, 0);\n          define_variable_cname (\"SCCSGETFLAGS\", \"-s\", o_default, 0);\n          define_variable_cname (\"ARFLAGS\", \"-rv\", o_default, 0);\n          continue;\n        }\n\n      if (!second_expansion && streq (nm, \".SECONDEXPANSION\"))\n        {\n          second_expansion = 1;\n          continue;\n        }\n\n#if !MK_OS_DOS && !MK_OS_OS2\n      if (!one_shell && streq (nm, \".ONESHELL\"))\n        {\n          one_shell = 1;\n          continue;\n        }\n#endif\n\n      /* Determine if this target should be made default.  */\n\n      if (set_default && default_goal_var->value[0] == '\\0')\n        {\n          struct dep *d;\n          int reject = 0;\n\n          /* We have nothing to do if this is an implicit rule. */\n          if (strchr (nm, '%') != 0)\n            break;\n\n          /* See if this target's name does not start with a '.',\n             unless it contains a slash.  */\n          if (*nm == '.' && strchr (nm, '/') == 0\n#ifdef HAVE_DOS_PATHS\n              && strchr (nm, '\\\\') == 0\n#endif\n              )\n            continue;\n\n          /* If this file is a suffix, it can't be the default goal file.  */\n          for (d = suffix_file->deps; d != 0; d = d->next)\n            {\n              struct dep *d2;\n              if (*dep_name (d) != '.' && streq (nm, dep_name (d)))\n                {\n                  reject = 1;\n                  break;\n                }\n              for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)\n                {\n                  size_t l = strlen (dep_name (d2));\n                  if (!strneq (nm, dep_name (d2), l))\n                    continue;\n                  if (streq (nm + l, dep_name (d)))\n                    {\n                      reject = 1;\n                      break;\n                    }\n                }\n\n              if (reject)\n                break;\n            }\n\n          if (!reject)\n            define_variable_global (\".DEFAULT_GOAL\", 13, t->name,\n                                    o_file, 0, NILF);\n        }\n    }\n}\n\n/* Check for special targets.  We used to do this in record_files() but that's\n   too late: by the time we get there we'll have already parsed the next line\n   and it have been mis-parsed because these special targets haven't been\n   considered yet.  */\n\nstatic void\ncheck_special_file (struct file *file, const floc *flocp)\n{\n  if (streq (file->name, \".WAIT\"))\n    {\n      static unsigned int wpre = 0, wcmd = 0;\n\n      if (!wpre && file->deps)\n        {\n          O (error, flocp, _(\".WAIT should not have prerequisites\"));\n          wpre = 1;\n        }\n\n      if (!wcmd && file->cmds)\n        {\n          O (error, flocp, _(\".WAIT should not have commands\"));\n          wcmd = 1;\n        }\n\n      return;\n    }\n}\n\f\n/* Record a description line for files FILENAMES,\n   with dependencies DEPS, commands to execute described\n   by COMMANDS and COMMANDS_IDX, coming from FILENAME:COMMANDS_STARTED.\n   TWO_COLON is nonzero if a double colon was used.\n   If not nil, PATTERN is the '%' pattern to make this\n   a static pattern rule, and PATTERN_PERCENT is a pointer\n   to the '%' within it.\n\n   The links of FILENAMES are freed, and so are any names in it\n   that are not incorporated into other data structures.  */\n\nstatic void\nrecord_files (struct nameseq *filenames, int are_also_makes,\n              const char *pattern,\n              const char *pattern_percent, char *depstr,\n              unsigned int cmds_started, char *commands,\n              size_t commands_idx, int two_colon,\n              char prefix, const floc *flocp)\n{\n  struct commands *cmds;\n  struct dep *deps;\n  struct dep *also_make = NULL;\n  const char *implicit_percent;\n  const char *name;\n\n  /* If we've already snapped deps, that means we're in an eval being\n     resolved after the makefiles have been read in.  We can't add more rules\n     at this time, since they won't get snapped and we'll get core dumps.\n     See Savannah bug # 12124.  */\n  if (snapped_deps)\n    O (fatal, flocp, _(\"prerequisites cannot be defined in recipes\"));\n\n  /* Determine if this is a pattern rule or not.  */\n  name = filenames->name;\n  implicit_percent = find_percent_cached (&name);\n\n  /* If there's a recipe, set up a struct for it.  */\n  if (commands_idx > 0)\n    {\n      cmds = xmalloc (sizeof (struct commands));\n      cmds->fileinfo.filenm = flocp->filenm;\n      cmds->fileinfo.lineno = cmds_started;\n      cmds->fileinfo.offset = 0;\n      cmds->commands = xstrndup (commands, commands_idx);\n      cmds->command_lines = 0;\n      cmds->recipe_prefix = prefix;\n    }\n  else if (are_also_makes)\n    O (fatal, flocp, _(\"grouped targets must provide a recipe\"));\n  else\n     cmds = NULL;\n\n  /* If there's a prereq string then parse it--unless it's eligible for 2nd\n     expansion: if so, snap_deps() will do it.  */\n  if (depstr == 0)\n    deps = 0;\n  else\n    {\n      depstr = unescape_char (depstr, ':');\n      if (second_expansion && strchr (depstr, '$'))\n        {\n          deps = alloc_dep ();\n          deps->name = depstr;\n          deps->need_2nd_expansion = 1;\n          deps->staticpattern = pattern != 0;\n        }\n      else\n        {\n          deps = split_prereqs (depstr);\n          free (depstr);\n\n          /* We'll enter static pattern prereqs later when we have the stem.\n             We don't want to enter pattern rules at all so that we don't\n             think that they ought to exist (make manual \"Implicit Rule Search\n             Algorithm\", item 5c).  */\n          if (! pattern && ! implicit_percent)\n            deps = enter_prereqs (deps, NULL);\n        }\n    }\n\n  /* For implicit rules, _all_ the targets must have a pattern.  That means we\n     can test the first one to see if we're working with an implicit rule; if\n     so we handle it specially. */\n\n  if (implicit_percent)\n    {\n      struct nameseq *nextf;\n      const char **targets, **target_pats;\n      unsigned short c;\n\n      if (pattern != 0)\n        O (fatal, flocp, _(\"mixed implicit and static pattern rules\"));\n\n      /* Count the targets to create an array of target names.\n         We already have the first one.  */\n      nextf = filenames->next;\n      free_ns (filenames);\n      filenames = nextf;\n\n      for (c = 1; nextf; ++c, nextf = nextf->next)\n        ;\n      targets = xmalloc (c * sizeof (const char *));\n      target_pats = xmalloc (c * sizeof (const char *));\n\n      targets[0] = name;\n      target_pats[0] = implicit_percent;\n\n      c = 1;\n      while (filenames)\n        {\n          name = filenames->name;\n          implicit_percent = find_percent_cached (&name);\n\n          if (implicit_percent == 0)\n            O (fatal, flocp, _(\"mixed implicit and normal rules\"));\n\n          targets[c] = name;\n          target_pats[c] = implicit_percent;\n          ++c;\n\n          nextf = filenames->next;\n          free_ns (filenames);\n          filenames = nextf;\n        }\n\n      create_pattern_rule (targets, target_pats, c, two_colon, deps, cmds, 1);\n\n      return;\n    }\n\n  /* Walk through each target and create it in the database.\n     We already set up the first target, above.  */\n  while (1)\n    {\n      struct nameseq *nextf = filenames->next;\n      struct file *f;\n      struct dep *this = 0;\n\n      free_ns (filenames);\n\n      /* If this is a static pattern rule:\n         'targets: target%pattern: prereq%pattern; recipe',\n         make sure the pattern matches this target name.  */\n      if (pattern && !pattern_matches (pattern, pattern_percent, name))\n        OS (error, flocp,\n            _(\"target '%s' doesn't match the target pattern\"), name);\n      else if (deps)\n        /* If there are multiple targets, copy the chain DEPS for all but the\n           last one.  It is not safe for the same deps to go in more than one\n           place in the database.  */\n        this = nextf != 0 ? copy_dep_chain (deps) : deps;\n\n      /* Find or create an entry in the file database for this target.  */\n      if (!two_colon)\n        {\n          /* Single-colon.  Combine this rule with the file's existing record,\n             if any.  */\n          f = enter_file (strcache_add (name));\n          if (f->double_colon)\n            OS (fatal, flocp,\n                _(\"target file '%s' has both : and :: entries\"), f->name);\n\n          /* If CMDS == F->CMDS, this target was listed in this rule\n             more than once.  Just give a warning since this is harmless.  */\n          if (cmds != 0 && cmds == f->cmds)\n            OS (error, flocp,\n                _(\"target '%s' given more than once in the same rule\"),\n                f->name);\n\n          /* Check for two single-colon entries both with commands.\n             Check is_target so that we don't lose on files such as .c.o\n             whose commands were preinitialized.  */\n          else if (cmds != 0 && f->cmds != 0 && f->is_target)\n            {\n              size_t l = strlen (f->name);\n              error (&cmds->fileinfo, l,\n                     _(\"warning: overriding recipe for target '%s'\"),\n                     f->name);\n              error (&f->cmds->fileinfo, l,\n                     _(\"warning: ignoring old recipe for target '%s'\"),\n                     f->name);\n            }\n\n          /* Defining .DEFAULT with no deps or cmds clears it.  */\n          if (f == default_file && this == 0 && cmds == 0)\n            f->cmds = 0;\n          if (cmds != 0)\n            f->cmds = cmds;\n\n          /* Defining .SUFFIXES with no dependencies clears out the list of\n             suffixes.  */\n          if (f == suffix_file && this == 0)\n            {\n              free_dep_chain (f->deps);\n              f->deps = 0;\n            }\n          /* This file is explicitly mentioned as a target.  There is no need\n             to set is_explicit in the case of double colon below, because an\n             implicit double colon rule only applies when the prerequisite\n             exists. A prerequisite which exists is not intermediate anyway. */\n          f->is_explicit = 1;\n        }\n      else\n        {\n          /* Double-colon.  Make a new record even if there already is one.  */\n          f = lookup_file (name);\n\n          /* Check for both : and :: rules.  Check is_target so we don't lose\n             on default suffix rules or makefiles.  */\n          if (f != 0 && f->is_target && !f->double_colon)\n            OS (fatal, flocp,\n                _(\"target file '%s' has both : and :: entries\"), f->name);\n\n          f = enter_file (strcache_add (name));\n          /* If there was an existing entry and it was a double-colon entry,\n             enter_file will have returned a new one, making it the prev\n             pointer of the old one, and setting its double_colon pointer to\n             the first one.  */\n          if (f->double_colon == 0)\n            /* This is the first entry for this name, so we must set its\n               double_colon pointer to itself.  */\n            f->double_colon = f;\n\n          f->cmds = cmds;\n        }\n\n      if (are_also_makes)\n        {\n          struct dep *also = alloc_dep();\n          also->name = f->name;\n          also->file = f;\n          also->next = also_make;\n          also_make = also;\n        }\n\n      f->is_target = 1;\n\n      /* If this is a static pattern rule, set the stem to the part of its\n         name that matched the '%' in the pattern, so you can use $* in the\n         commands.  If we didn't do it before, enter the prereqs now.  */\n      if (pattern)\n        {\n          static const char *percent = \"%\";\n          char *o = patsubst_expand_pat (variable_buffer, name, pattern,\n                                         percent, pattern_percent+1, percent+1);\n          f->stem = strcache_add_len (variable_buffer, o - variable_buffer);\n          if (this)\n            {\n              if (! this->need_2nd_expansion)\n                this = enter_prereqs (this, f->stem);\n              else\n                this->stem = f->stem;\n            }\n        }\n\n      /* Add the dependencies to this file entry.  */\n      if (this != 0)\n        {\n          /* Add the file's old deps and the new ones in THIS together.  */\n          if (f->deps == 0)\n            f->deps = this;\n          else if (cmds != 0)\n            {\n              struct dep *d = this;\n\n              /* If this rule has commands, put these deps first.  */\n              while (d->next != 0)\n                d = d->next;\n\n              d->next = f->deps;\n              f->deps = this;\n            }\n          else\n            {\n              struct dep *d = f->deps;\n\n              /* A rule without commands: put its prereqs at the end.  */\n              while (d->next != 0)\n                d = d->next;\n\n              d->next = this;\n            }\n        }\n\n      name = f->name;\n\n      check_special_file (f, flocp);\n\n      /* All done!  Set up for the next one.  */\n      if (nextf == 0)\n        break;\n\n      filenames = nextf;\n\n      /* Reduce escaped percents.  If there are any unescaped it's an error  */\n      name = filenames->name;\n      if (find_percent_cached (&name))\n        O (error, flocp,\n           _(\"*** mixed implicit and normal rules: deprecated syntax\"));\n    }\n\n  /* If there are also-makes, then populate a copy of the also-make list into\n     each one.  Omit the file from its also-make list.  */\n  {\n    struct dep *i;\n\n    for (i = also_make; i != NULL; i = i->next)\n      {\n        struct file *f = i->file;\n        struct dep *dp;\n\n        if (f->also_make)\n          {\n            OS (error, &cmds->fileinfo,\n                _(\"warning: overriding group membership for target '%s'\"),\n                f->name);\n            free_dep_chain (f->also_make);\n            f->also_make = NULL;\n          }\n\n        for (dp = also_make; dp != NULL; dp = dp->next)\n          if (dp->file != f)\n            {\n              struct dep *cpy = copy_dep (dp);\n              cpy->next = f->also_make;\n              f->also_make = cpy;\n            }\n      }\n\n    free_dep_chain (also_make);\n  }\n}\n\f\n/* Search STRING for an unquoted STOPMAP.\n   Backslashes quote elements from STOPMAP and backslash.\n   Quoting backslashes are removed from STRING by compacting it into itself.\n   Returns a pointer to the first unquoted STOPCHAR if there is one, or nil if\n   there are none.\n\n   If MAP_VARIABLE is set, then the complete contents of variable references\n   are skipped, even if the contain STOPMAP characters.  */\n\nstatic char *\nfind_map_unquote (char *string, int stopmap)\n{\n  size_t string_len = 0;\n  char *p = string;\n\n  /* Always stop on NUL.  */\n  stopmap |= MAP_NUL;\n\n  while (1)\n    {\n      while (! STOP_SET (*p, stopmap))\n        ++p;\n\n      if (*p == '\\0')\n        break;\n\n      /* If we stopped due to a variable reference, skip over its contents.  */\n      if (*p == '$')\n        {\n          p = skip_reference (p+1);\n          continue;\n        }\n\n      if (p > string && p[-1] == '\\\\')\n        {\n          /* Search for more backslashes.  */\n          int i = -2;\n          while (&p[i] >= string && p[i] == '\\\\')\n            --i;\n          ++i;\n          /* Only compute the length if really needed.  */\n          if (string_len == 0)\n            string_len = strlen (string);\n          /* The number of backslashes is now -I.\n             Copy P over itself to swallow half of them.  */\n          {\n            /* Avoid arithmetic conversion of negative values to unsigned.  */\n            int hi = -(i/2);\n            memmove (&p[i], &p[i/2], (string_len - (p - string)) + hi + 1);\n            p += i/2;\n          }\n          if (i % 2 == 0)\n            /* All the backslashes quoted each other; the STOPCHAR was\n               unquoted.  */\n            return p;\n\n          /* The STOPCHAR was quoted by a backslash.  Look for another.  */\n        }\n      else\n        /* No backslash in sight.  */\n        return p;\n    }\n\n  /* Never hit a STOPCHAR or blank (with BLANK nonzero).  */\n  return 0;\n}\n\nstatic char *\nfind_char_unquote (char *string, int stop)\n{\n  size_t string_len = 0;\n  char *p = string;\n\n  while (1)\n    {\n      p = strchr(p, stop);\n\n      if (!p)\n        return NULL;\n\n      if (p > string && p[-1] == '\\\\')\n        {\n          /* Search for more backslashes.  */\n          int i = -2;\n          while (&p[i] >= string && p[i] == '\\\\')\n            --i;\n          ++i;\n          /* Only compute the length if really needed.  */\n          if (string_len == 0)\n            string_len = strlen (string);\n          /* The number of backslashes is now -I.\n             Copy P over itself to swallow half of them.  */\n          {\n            /* Avoid arithmetic conversion of negative values to unsigned.  */\n            int hi = -(i/2);\n            memmove (&p[i], &p[i/2], (string_len - (p - string)) + hi + 1);\n            p += i/2;\n          }\n          if (i % 2 == 0)\n            /* All the backslashes quoted each other; the STOPCHAR was\n               unquoted.  */\n            return p;\n\n          /* The STOPCHAR was quoted by a backslash.  Look for another.  */\n        }\n      else\n        /* No backslash in sight.  */\n        return p;\n    }\n}\n\n/* Unescape a character in a string.  The string is compressed onto itself.  */\n\nstatic char *\nunescape_char (char *string, int c)\n{\n  char *p = string;\n  char *s = string;\n\n  while (*s != '\\0')\n    {\n      if (*s == '\\\\')\n        {\n          char *e = s;\n          size_t l;\n\n          /* We found a backslash.  See if it's escaping our character.  */\n          while (*e == '\\\\')\n            ++e;\n          l = e - s;\n\n          if (*e != c || l%2 == 0)\n            {\n              /* It's not; just take it all without unescaping.  */\n              memmove (p, s, l);\n              p += l;\n\n              /* If we hit the end of the string, we're done.  */\n              if (*e == '\\0')\n                break;\n            }\n          else if (l > 1)\n            {\n              /* It is, and there's >1 backslash.  Take half of them.  */\n              l /= 2;\n              memmove (p, s, l);\n              p += l;\n            }\n\n          s = e;\n        }\n\n      *(p++) = *(s++);\n    }\n\n  *p = '\\0';\n  return string;\n}\n\n/* Search PATTERN for an unquoted % and handle quoting.  */\n\nchar *\nfind_percent (char *pattern)\n{\n  return find_char_unquote (pattern, '%');\n}\n\n/* Return a pointer to the first unescaped %, or NULL if there isn't one.\n   Compress any escape chars up to the first unescaped %, but not afterward.\n   This version is used with strings in the string cache: if there's a need to\n   modify the string to handle escape chars a new version will be added to the\n   string cache and *STRING will be set to that.  */\n\nconst char *\nfind_percent_cached (const char **string)\n{\n  const char *p = strchr (*string, '%');\n  char *new, *np;\n  size_t slen;\n\n  /* If there is no % or there is but it's not escaped, reuse this string.  */\n  if (!p || p == *string || p[-1] != '\\\\')\n    return p;\n\n  /* We must create a new cached string with backslashes compressed.  */\n  slen = strlen (*string);\n  new = alloca (slen + 1);\n  memcpy (new, *string, slen + 1);\n  np = new + (p - *string);\n\n  do\n    {\n      /* Remember where the percent is.  */\n      char *pp = np;\n      int i = -2;\n\n      /* This % is preceded by a backslash; search for more backslashes.  */\n      while (&np[i] >= new && np[i] == '\\\\')\n        --i;\n      ++i;\n\n      /* The number of backslashes is -I.  Copy the string over itself to\n         swallow half of them.  */\n      {\n        /* Avoid arithmetic conversion of negative values to unsigned.  */\n        int hi = -(i/2);\n        memmove (&pp[i], &pp[i/2], (slen - (pp - new)) + hi + 1);\n      }\n\n      /* Update SLEN and set NP to point after the %.  */\n      slen += i/2 + i%2;\n      np += i/2;\n\n      /* If all backslashes quoted each other then % was unquoted.  */\n      if (i % 2 == 0)\n        break;\n\n      np = strchr (np, '%');\n    }\n  while (np && np[-1] == '\\\\');\n\n  /* Add the new string to the strcache.  */\n  *string = strcache_add (new);\n\n  /* If we didn't find a %, return NULL.  Otherwise return a ptr to it.  */\n  return np ? *string + (np - new) : NULL;\n}\n\f\n/* Find the next line of text in an eval buffer, combining continuation lines\n   into one line.\n   Return the number of actual lines read (> 1 if continuation lines).\n   Returns -1 if there's nothing left in the buffer.\n\n   After this function, ebuf->buffer points to the first character of the\n   line we just found.\n */\n\n/* Read a line of text from a STRING.\n   Since we aren't really reading from a file, don't bother with linenumbers.\n */\n\nstatic long\nreadstring (struct ebuffer *ebuf)\n{\n  char *eol;\n\n  /* If there is nothing left in this buffer, return 0.  */\n  if (ebuf->bufnext >= ebuf->bufstart + ebuf->size)\n    return -1;\n\n  /* Set up a new starting point for the buffer, and find the end of the\n     next logical line (taking into account backslash/newline pairs).  */\n\n  eol = ebuf->buffer = ebuf->bufnext;\n\n  while (1)\n    {\n      int backslash = 0;\n      const char *bol = eol;\n      const char *p;\n\n      /* Find the next newline.  At EOS, stop.  */\n      p = eol = strchr (eol , '\\n');\n      if (!eol)\n        {\n          ebuf->bufnext = ebuf->bufstart + ebuf->size + 1;\n          return 0;\n        }\n\n      /* Found a newline; if it's escaped continue; else we're done.  */\n      while (p > bol && *(--p) == '\\\\')\n        backslash = !backslash;\n      if (!backslash)\n        break;\n      ++eol;\n    }\n\n  /* Overwrite the newline char.  */\n  *eol = '\\0';\n  ebuf->bufnext = eol+1;\n\n  return 0;\n}\n\nstatic long\nreadline (struct ebuffer *ebuf)\n{\n  char *p;\n  char *end;\n  char *start;\n  long nlines = 0;\n\n  /* The behaviors between string and stream buffers are different enough to\n     warrant different functions.  Do the Right Thing.  */\n\n  if (!ebuf->fp)\n    return readstring (ebuf);\n\n  /* When reading from a file, we always start over at the beginning of the\n     buffer for each new line.  */\n\n  p = start = ebuf->bufstart;\n  end = p + ebuf->size;\n  *p = '\\0';\n\n  while (fgets (p, (int) (end - p), ebuf->fp) != 0)\n    {\n      char *p2;\n      size_t len;\n      int backslash;\n\n      len = strlen (p);\n      if (len == 0)\n        {\n          /* This only happens when the first thing on the line is a '\\0'.\n             It is a pretty hopeless case, but (wonder of wonders) Athena\n             lossage strikes again!  (xmkmf puts NULs in its makefiles.)\n             There is nothing really to be done; we synthesize a newline so\n             the following line doesn't appear to be part of this line.  */\n          O (error, &ebuf->floc,\n             _(\"warning: NUL character seen; rest of line ignored\"));\n          p[0] = '\\n';\n          len = 1;\n        }\n\n      /* Jump past the text we just read.  */\n      p += len;\n\n      /* If the last char isn't a newline, the whole line didn't fit into the\n         buffer.  Get some more buffer and try again.  */\n      if (p[-1] != '\\n')\n        goto more_buffer;\n\n      /* We got a newline, so add one to the count of lines.  */\n      ++nlines;\n\n#if !MK_OS_W32 && !MK_OS_DOS && !MK_OS_OS2\n      /* Check to see if the line was really ended with CRLF; if so ignore\n         the CR.  */\n      if ((p - start) > 1 && p[-2] == '\\r')\n        {\n          --p;\n          memmove (p-1, p, strlen (p) + 1);\n        }\n#endif\n\n      backslash = 0;\n      for (p2 = p - 2; p2 >= start; --p2)\n        {\n          if (*p2 != '\\\\')\n            break;\n          backslash = !backslash;\n        }\n\n      if (!backslash)\n        {\n          p[-1] = '\\0';\n          break;\n        }\n\n      /* It was a backslash/newline combo.  If we have more space, read\n         another line.  */\n      if (end - p >= 80)\n        continue;\n\n      /* We need more space at the end of our buffer, so realloc it.\n         Make sure to preserve the current offset of p.  */\n    more_buffer:\n      {\n        size_t off = p - start;\n        ebuf->size *= 2;\n        start = ebuf->buffer = ebuf->bufstart = xrealloc (start, ebuf->size);\n        p = start + off;\n        end = start + ebuf->size;\n        *p = '\\0';\n      }\n    }\n\n  if (ferror (ebuf->fp))\n    pfatal_with_name (ebuf->floc.filenm);\n\n  /* If we found some lines, return how many.\n     If we didn't, but we did find _something_, that indicates we read the last\n     line of a file with no final newline; return 1.\n     If we read nothing, we're at EOF; return -1.  */\n\n  return nlines ? nlines : p == ebuf->bufstart ? -1 : 1;\n}\n\f\n/* Parse the next \"makefile word\" from the input buffer, and return info\n   about it.  This function won't be called in any context where we might need\n   to parse a variable assignment so we don't need to check that.\n\n   A \"makefile word\" is one of:\n\n     w_bogus        Should never happen\n     w_eol          End of input\n     w_static       A static word; cannot be expanded\n     w_variable     A word containing one or more variables/functions\n     w_colon        A colon\n     w_dcolon       A double-colon\n     w_ampcolon     An ampersand-colon (&:) token\n     w_ampdcolon    An ampersand-double-colon (&::) token\n     w_semicolon    A semicolon\n\n   Note that this function is only used when reading certain parts of the\n   makefile.  Don't use it where special rules hold sway (RHS of a variable,\n   in a recipe, etc.)  */\n\nstatic enum make_word_type\nget_next_mword (char *buffer, char **startp, size_t *length)\n{\n  enum make_word_type wtype;\n  char *p = buffer, *beg;\n  char c;\n\n  /* Skip any leading whitespace.  */\n  while (ISSPACE (*p))\n    ++p;\n\n  beg = p;\n  c = *(p++);\n\n  /* Look at the start of the word to see if it's simple.  */\n  switch (c)\n    {\n    case '\\0':\n      wtype = w_eol;\n      goto done;\n\n    case ';':\n      wtype = w_semicolon;\n      goto done;\n\n    case ':':\n      wtype = w_colon;\n      if (*p == ':')\n        {\n          ++p;\n          wtype = w_dcolon;\n        }\n      goto done;\n\n    case '&':\n      if (*p == ':')\n        {\n          ++p;\n          if (*p != ':')\n            wtype = w_ampcolon; /* &: */\n          else\n            {\n              ++p;\n              wtype = w_ampdcolon; /* &:: */\n            }\n          goto done;\n        }\n      break;\n\n    default:\n      break;\n    }\n\n  /* This is some non-operator word.  A word consists of the longest string of\n     characters that doesn't contain whitespace, one of [:#], or &:.  */\n\n  /* We start out assuming a static word; if we see a variable we'll\n     adjust our assumptions then.  */\n  wtype = w_static;\n\n  while (1)\n    {\n      /* Each time through the loop, \"c\" has the current character\n         and \"p\" points to the next character.  */\n      if (END_OF_TOKEN (c))\n        goto done_word;\n\n      switch (c)\n        {\n        case ':':\n#ifdef HAVE_DOS_PATHS\n          /* A word CAN include a colon in its drive spec.  The drive\n             spec is allowed either at the beginning of a word, or as part\n             of the archive member name, like in \"libfoo.a(d:/foo/bar.o)\".  */\n          if ((p - beg == 2 || (p - beg > 2 && p[-3] == '('))\n              && isalpha ((unsigned char)p[-2]))\n            break;\n#endif\n          goto done_word;\n\n        case '$':\n          c = *(p++);\n          if (c == '$')\n            break;\n          if (c == '\\0')\n            goto done_word;\n\n          /* This is a variable reference: note that then skip it.  */\n          wtype = w_variable;\n          p = skip_reference (p-1);\n          break;\n\n        case '\\\\':\n          switch (*p)\n            {\n            case ':':\n            case ';':\n            case '=':\n            case '\\\\':\n              ++p;\n              break;\n            }\n          break;\n\n        case '&':\n          if (*p == ':')\n            goto done_word;\n          break;\n\n        default:\n          break;\n        }\n\n      c = *(p++);\n    }\n done_word:\n  --p;\n\n done:\n  if (startp)\n    *startp = beg;\n  if (length)\n    *length = p - beg;\n\n  return wtype;\n}\n\f\n/* Construct the list of include directories\n   from the arguments and the default list.  */\n\nvoid\nconstruct_include_path (const char **arg_dirs)\n{\n#ifdef VAXC             /* just don't ask ... */\n  stat_t stbuf;\n#else\n  struct stat stbuf;\n#endif\n  const char **dirs;\n  const char **cpp;\n  size_t idx;\n  int disable = 0;\n\n  /* Compute the number of pointers we need in the table.  */\n  idx = ARRAYLEN (default_include_directories);\n  if (arg_dirs)\n    for (cpp = arg_dirs; *cpp != 0; ++cpp)\n      ++idx;\n\n#if MK_OS_DOS\n  /* Add one for $DJDIR.  */\n  ++idx;\n#endif\n\n  dirs = xmalloc (idx * sizeof (const char *));\n\n  idx = 0;\n  max_incl_len = 0;\n\n  /* First consider any dirs specified with -I switches.\n     Ignore any that don't exist.  Restart if we find \"-\".\n     Remember the maximum string length.  */\n\n  if (arg_dirs)\n    while (*arg_dirs != 0)\n      {\n        const char *dir = *(arg_dirs++);\n        char *expanded = 0;\n        int e;\n\n        if (dir[0] == '-' && dir[1] == '\\0')\n          {\n            disable = 1;\n            idx = 0;\n            max_incl_len = 0;\n            continue;\n          }\n\n        if (dir[0] == '~')\n          {\n            expanded = tilde_expand (dir);\n            if (expanded != 0)\n              dir = expanded;\n          }\n\n        EINTRLOOP (e, stat (dir, &stbuf));\n        if (e == 0 && S_ISDIR (stbuf.st_mode))\n          {\n            size_t len = strlen (dir);\n            /* If dir name is written with trailing slashes, discard them.  */\n            while (len > 1 && dir[len - 1] == '/')\n              --len;\n            if (len > max_incl_len)\n              max_incl_len = len;\n            dirs[idx++] = strcache_add_len (dir, len);\n          }\n\n        free (expanded);\n      }\n\n  /* Now add the standard default dirs at the end.  */\n  if (!disable)\n    {\n#if MK_OS_DOS\n      /* The environment variable $DJDIR holds the root of the DJGPP directory\n         tree; add ${DJDIR}/include.  */\n      struct variable *djdir = lookup_variable (\"DJDIR\", 5);\n\n      if (djdir)\n        {\n          size_t len = strlen (djdir->value) + 8;\n          char *defdir = alloca (len + 1);\n\n          strcat (strcpy (defdir, djdir->value), \"/include\");\n          dirs[idx++] = strcache_add (defdir);\n\n          if (len > max_incl_len)\n            max_incl_len = len;\n        }\n#endif\n      for (cpp = default_include_directories; *cpp != 0; ++cpp)\n        {\n          int e;\n\n          EINTRLOOP (e, stat (*cpp, &stbuf));\n          if (e == 0 && S_ISDIR (stbuf.st_mode))\n            {\n              size_t len = strlen (*cpp);\n              /* If dir name is written with trailing slashes, discard them.  */\n              while (len > 1 && (*cpp)[len - 1] == '/')\n                --len;\n              if (len > max_incl_len)\n                max_incl_len = len;\n              dirs[idx++] = strcache_add_len (*cpp, len);\n            }\n        }\n    }\n\n  dirs[idx] = 0;\n\n  /* Now add each dir to the .INCLUDE_DIRS variable.  */\n\n  do_variable_definition (NILF, \".INCLUDE_DIRS\", \"\", o_default, f_simple, 0,\n                          s_global);\n  for (cpp = dirs; *cpp != 0; ++cpp)\n    do_variable_definition (NILF, \".INCLUDE_DIRS\", *cpp, o_default, f_append,\n                            0, s_global);\n\n  free ((void *) include_directories);\n  include_directories = dirs;\n}\n\f\n/* Expand ~ or ~USER at the beginning of NAME.\n   Return a newly malloc'd string or 0.  */\n\nchar *\ntilde_expand (const char *name)\n{\n#if !MK_OS_VMS\n  if (name[1] == '/' || name[1] == '\\0')\n    {\n      char *home_dir;\n      int is_variable;\n\n      {\n        /* Turn off undefined variables warning while we expand HOME.  */\n        enum warning_action save = warn_get (wt_undefined_var);\n        warn_set (wt_undefined_var, w_ignore);\n\n        home_dir = allocated_expand_variable (STRING_SIZE_TUPLE (\"HOME\"));\n\n        warn_set (wt_undefined_var, save);\n      }\n\n      is_variable = home_dir[0] != '\\0';\n      if (!is_variable)\n        {\n          free (home_dir);\n          home_dir = getenv (\"HOME\");\n        }\n# if !MK_OS_W32\n      if (home_dir == 0 || home_dir[0] == '\\0')\n        {\n          char *logname = getlogin ();\n          home_dir = 0;\n          if (logname != 0)\n            {\n              struct passwd *p = getpwnam (logname);\n              if (p != 0)\n                home_dir = p->pw_dir;\n            }\n        }\n# endif /* !MK_OS_W32 */\n      if (home_dir != 0)\n        {\n          char *new = xstrdup (concat (2, home_dir, name + 1));\n          if (is_variable)\n            free (home_dir);\n          return new;\n        }\n    }\n# if !MK_OS_W32\n  else\n    {\n      struct passwd *pwent;\n      char *userend = strchr (name + 1, '/');\n      if (userend != 0)\n        *userend = '\\0';\n      pwent = getpwnam (name + 1);\n      if (pwent != 0)\n        {\n          if (userend == 0)\n            return xstrdup (pwent->pw_dir);\n\n          *userend = '/';\n          return xstrdup (concat (3, pwent->pw_dir, \"/\", userend + 1));\n        }\n      else if (userend != 0)\n        *userend = '/';\n    }\n# endif /* !MK_OS_W32 */\n#endif /* !MK_OS_VMS */\n  return 0;\n}\n\f\n/* Parse a string into a sequence of filenames represented as a chain of\n   struct nameseq's and return that chain.  Optionally expand the strings via\n   glob().\n\n   The string is passed as STRINGP, the address of a string pointer.\n   The string pointer is updated to point at the first character\n   not parsed, which either is a null char or equals STOPMAP.\n\n   SIZE is how large (in bytes) each element in the new chain should be.\n   This is useful if we want them actually to be other structures\n   that have room for additional info.\n\n   STOPMAP is a map of characters that tell us to stop parsing.\n\n   PREFIX, if non-null, is added to the beginning of each filename.\n\n   FLAGS allows one or more of the following bitflags to be set:\n        PARSEFS_NOSTRIP - Do no strip './'s off the beginning\n        PARSEFS_NOAR    - Do not check filenames for archive references\n        PARSEFS_NOGLOB  - Do not expand globbing characters\n        PARSEFS_EXISTS  - Only return globbed files that actually exist\n                          (cannot also set NOGLOB)\n        PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees)\n        PARSEFS_ONEWORD - Don't break the sequence on whitespace\n        PARSEFS_WAIT    - Assume struct dep and handle .WAIT\n  */\n\nvoid *\nparse_file_seq (char **stringp, size_t size, int stopmap,\n                const char *prefix, int flags)\n{\n  /* tmp points to tmpbuf after the prefix, if any.\n     tp is the end of the buffer. */\n  static char *tmpbuf = NULL;\n\n  int cachep = NONE_SET (flags, PARSEFS_NOCACHE);\n\n  struct nameseq *new = 0;\n  struct nameseq **newp = &new;\n#define NEWELT(_n)  do { \\\n                        struct nameseq *_ns = xcalloc (size);       \\\n                        const char *__n = (_n);                     \\\n                        _ns->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \\\n                        if (found_wait) {                           \\\n                          ((struct dep*)_ns)->wait_here = 1;        \\\n                          found_wait = 0;                           \\\n                        }                                           \\\n                        *newp = _ns;                                \\\n                        newp = &_ns->next;                          \\\n                    } while(0)\n\n  char *p;\n  glob_t gl;\n  char *tp;\n  int findmap = stopmap|MAP_VMSCOMMA|MAP_NUL;\n  int found_wait = 0;\n\n  if (NONE_SET (flags, PARSEFS_ONEWORD))\n    findmap |= MAP_BLANK;\n\n  /* Always stop on NUL.  */\n  stopmap |= MAP_NUL;\n\n  if (size < sizeof (struct nameseq))\n    size = sizeof (struct nameseq);\n\n  if (NONE_SET (flags, PARSEFS_NOGLOB))\n    dir_setup_glob (&gl);\n\n  /* Get enough temporary space to construct the largest possible target.  */\n  {\n    static size_t tmpbuf_len = 0;\n    size_t l = strlen (*stringp) + 1;\n    if (l > tmpbuf_len)\n      {\n        tmpbuf = xrealloc (tmpbuf, l);\n        tmpbuf_len = l;\n      }\n  }\n  tp = tmpbuf;\n\n  /* Parse STRING.  P will always point to the end of the parsed content.  */\n  p = *stringp;\n  while (1)\n    {\n      const char *name;\n      const char **nlist = 0;\n      char *tildep = 0;\n      int globme = 1;\n#ifndef NO_ARCHIVES\n      char *arname = 0;\n      char *memname = 0;\n#endif\n      char *s;\n      size_t nlen;\n      int tot, i;\n\n      /* Skip whitespace; at the end of the string or STOPCHAR we're done.  */\n      NEXT_TOKEN (p);\n      if (STOP_SET (*p, stopmap))\n        break;\n\n      /* There are names left, so find the end of the next name.\n         Throughout this iteration S points to the start.  */\n      s = p;\n      p = find_map_unquote (p, findmap);\n\n#if MK_OS_VMS\n        /* convert comma separated list to space separated */\n      if (p && *p == ',')\n        *p =' ';\n#endif\n#ifdef HAVE_DOS_PATHS\n      /* If we stopped due to a drive specifier, skip it.\n         Tokens separated by spaces are treated as separate paths since make\n         doesn't allow path names with spaces.  */\n      if (p && p == s+1 && p[0] == ':'\n          && isalpha ((unsigned char)s[0]) && ISDIRSEP (p[1]))\n        p = find_map_unquote (p+1, findmap);\n#endif\n\n      if (!p)\n        p = s + strlen (s);\n\n      if (ANY_SET (flags, PARSEFS_WAIT) && p - s == CSTRLEN (\".WAIT\")\n          && memcmp (s, \".WAIT\", CSTRLEN (\".WAIT\")) == 0)\n        {\n          /* Note that we found a .WAIT for the next dep but skip it.  */\n          found_wait = 1;\n          continue;\n        }\n\n      /* Strip leading \"this directory\" references.  */\n      if (NONE_SET (flags, PARSEFS_NOSTRIP))\n        {\n#if MK_OS_VMS\n          /* Skip leading '[]'s. should only be one set or bug somewhere else */\n          if (p - s > 2 && s[0] == '[' && s[1] == ']')\n            s += 2;\n          /* Skip leading '<>'s. should only be one set or bug somewhere else */\n          if (p - s > 2 && s[0] == '<' && s[1] == '>')\n            s += 2;\n#endif\n          /* Skip leading './'s.  */\n          while (p - s > 2 && s[0] == '.' && s[1] == '/')\n            {\n              /* Skip \"./\" and all following slashes.  */\n              s += 2;\n              while (*s == '/')\n                ++s;\n            }\n        }\n\n      /* Extract the filename just found, and skip it.\n         Set NAME to the string, and NLEN to its length.  */\n\n      if (s == p)\n        {\n        /* The name was stripped to empty (\"./\"). */\n          tp[0] = '.';\n          tp[1] = '/';\n          tp[2] = '\\0';\n          nlen = 2;\n        }\n      else\n        {\n#if MK_OS_VMS\n/* VMS filenames can have a ':' in them but they have to be '\\'ed but we need\n *  to remove this '\\' before we can use the filename.\n * xstrdup called because S may be read-only string constant.\n */\n          char *n = tp;\n          while (s < p)\n            {\n              if (s[0] == '\\\\' && s[1] == ':')\n                ++s;\n              *(n++) = *(s++);\n            }\n          n[0] = '\\0';\n          nlen = strlen (tp);\n#else\n          nlen = p - s;\n          memcpy (tp, s, nlen);\n          tp[nlen] = '\\0';\n#endif\n        }\n\n      /* At this point, TP points to the element and NLEN is its length.  */\n\n#ifndef NO_ARCHIVES\n      /* If this is the start of an archive group that isn't complete, set up\n         to add the archive prefix for future files.  A file list like:\n         \"libf.a(x.o y.o z.o)\" needs to be expanded as:\n         \"libf.a(x.o) libf.a(y.o) libf.a(z.o)\"\n\n         TP == TMP means we're not already in an archive group.  Ignore\n         something starting with '(', as that cannot actually be an\n         archive-member reference (and treating it as such results in an empty\n         file name, which causes much lossage).  Also if it ends in \")\" then\n         it's a complete reference so we don't need to treat it specially.\n\n         Finally, note that archive groups must end with ')' as the last\n         character, so ensure there's some word ending like that before\n         considering this an archive group.  */\n      if (NONE_SET (flags, PARSEFS_NOAR)\n          && tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')')\n        {\n          char *n = strchr (tp, '(');\n          if (n)\n            {\n              /* This looks like the first element in an open archive group.\n                 A valid group MUST have ')' as the last character.  */\n              const char *e = p;\n              do\n                {\n                  const char *o = e;\n                  NEXT_TOKEN (e);\n                  /* Find the end of this word.  We don't want to unquote and\n                     we don't care about quoting since we're looking for the\n                     last char in the word. */\n                  while (! STOP_SET (*e, findmap))\n                    ++e;\n                  /* If we didn't move, we're done now.  */\n                  if (e == o)\n                    break;\n                  if (e[-1] == ')')\n                    {\n                      /* Found the end, so this is the first element in an\n                         open archive group.  It looks like \"lib(mem\".\n                         Reset TP past the open paren.  */\n                      nlen -= (n + 1) - tp;\n                      tp = n + 1;\n\n                      /* We can stop looking now.  */\n                      break;\n                    }\n                }\n              while (*e != '\\0');\n\n              /* If we have just \"lib(\", part of something like \"lib( a b)\",\n                 go to the next item.  */\n              if (! nlen)\n                continue;\n            }\n        }\n\n      /* If we are inside an archive group, make sure it has an end.  */\n      if (tp > tmpbuf)\n        {\n          if (tp[nlen-1] == ')')\n            {\n              /* This is the natural end; reset TP.  */\n              tp = tmpbuf;\n\n              /* This is just \")\", something like \"lib(a b )\": skip it.  */\n              if (nlen == 1)\n                continue;\n            }\n          else\n            {\n              /* Not the end, so add a \"fake\" end.  */\n              tp[nlen++] = ')';\n              tp[nlen] = '\\0';\n            }\n        }\n#endif\n\n      /* If we're not globbing we're done: add it to the end of the chain.\n         Go to the next item in the string.  */\n      if (ANY_SET (flags, PARSEFS_NOGLOB))\n        {\n          NEWELT (concat (2, prefix, tmpbuf));\n          continue;\n        }\n\n      /* If we get here we know we're doing glob expansion.\n         TP is a string in tmpbuf.  NLEN is no longer used.\n         We may need to do more work: after this NAME will be set.  */\n      name = tmpbuf;\n\n      /* Expand tilde if applicable.  */\n      if (tmpbuf[0] == '~')\n        {\n          tildep = tilde_expand (tmpbuf);\n          if (tildep != 0)\n            name = tildep;\n        }\n\n#ifndef NO_ARCHIVES\n      /* If NAME is an archive member reference replace it with the archive\n         file name, and save the member name in MEMNAME.  We will glob on the\n         archive name and then reattach MEMNAME later.  */\n      if (NONE_SET (flags, PARSEFS_NOAR) && ar_name (name))\n        {\n          ar_parse_name (name, &arname, &memname);\n          name = arname;\n        }\n#endif /* !NO_ARCHIVES */\n\n      /* glob() is expensive: don't call it unless we need to.  */\n      if (NONE_SET (flags, PARSEFS_EXISTS) && strpbrk (name, \"?*[\") == NULL)\n        {\n          globme = 0;\n          tot = 1;\n          nlist = &name;\n        }\n      else\n        switch (glob (name, GLOB_ALTDIRFUNC, NULL, &gl))\n          {\n          case GLOB_NOSPACE:\n            out_of_memory ();\n\n          case 0:\n            /* Success.  */\n            tot = gl.gl_pathc;\n            nlist = (const char **)gl.gl_pathv;\n            break;\n\n          case GLOB_NOMATCH:\n            /* If we want only existing items, skip this one.  */\n            if (ANY_SET (flags, PARSEFS_EXISTS))\n              {\n                tot = 0;\n                break;\n              }\n            /* FALLTHROUGH */\n\n          default:\n            /* By default keep this name.  */\n            tot = 1;\n            nlist = &name;\n            break;\n          }\n\n      /* For each matched element, add it to the list.  */\n      for (i = 0; i < tot; ++i)\n#ifndef NO_ARCHIVES\n        if (memname != 0)\n          {\n            /* Try to glob on MEMNAME within the archive.  */\n            struct nameseq *found = ar_glob (nlist[i], memname, size);\n            if (! found)\n              /* No matches.  Use MEMNAME as-is.  */\n              NEWELT (concat (5, prefix, nlist[i], \"(\", memname, \")\"));\n            else\n              {\n                /* We got a chain of items.  Attach them.  */\n                if (*newp)\n                  (*newp)->next = found;\n                else\n                  *newp = found;\n\n                /* Find and set the new end.  Massage names if necessary.  */\n                while (1)\n                  {\n                    if (! cachep)\n                      found->name = xstrdup (concat (2, prefix, name));\n                    else if (prefix)\n                      found->name = strcache_add (concat (2, prefix, name));\n\n                    if (found->next == 0)\n                      break;\n\n                    found = found->next;\n                  }\n                newp = &found->next;\n              }\n          }\n        else\n#endif /* !NO_ARCHIVES */\n          NEWELT (concat (2, prefix, nlist[i]));\n\n      if (globme)\n        globfree (&gl);\n\n#ifndef NO_ARCHIVES\n      free (arname);\n#endif\n\n      free (tildep);\n    }\n\n  *stringp = p;\n  return new;\n}\n"
  },
  {
    "path": "src/remake.c",
    "content": "/* Basic dependency engine for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"dep.h\"\n#include \"variable.h\"\n#include \"warning.h\"\n#include \"debug.h\"\n\n#include <assert.h>\n\n#ifdef HAVE_FCNTL_H\n#include <fcntl.h>\n#else\n#include <sys/file.h>\n#endif\n\n#if MK_OS_VMS\n#include <starlet.h>\n#endif\n#if MK_OS_W32\n#include <windows.h>\n#include <io.h>\n#include <sys/stat.h>\n#if defined(_MSC_VER) && _MSC_VER > 1200\n/* VC7 or later supports _stat64 to access 64-bit file size. */\n#define STAT _stat64\n#else\n#define STAT stat\n#endif\n#endif\n\n\n/* The test for circular dependencies is based on the 'updating' bit in\n   'struct file'.  However, double colon targets have separate 'struct\n   file's; make sure we always use the base of the double colon chain. */\n\n#define start_updating(_f)  (((_f)->double_colon ? (_f)->double_colon : (_f))\\\n                             ->updating = 1)\n#define finish_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\\\n                             ->updating = 0)\n#define is_updating(_f)     (((_f)->double_colon ? (_f)->double_colon : (_f))\\\n                             ->updating)\n\n\n/* Incremented when a command is started (under -n, when one would be).  */\nunsigned int commands_started = 0;\n\n/* Set to the goal dependency.  Mostly needed for remaking makefiles.  */\nstatic struct goaldep *goal_list;\nstatic struct dep *goal_dep;\n\n/* Current value for pruning the scan of the goal chain.\n   All files start with considered == 0.  */\nstatic unsigned int considered = 0;\n\n/* During processing we might drop some dependencies, which can't be freed\n   immediately because they are still in use.  Remember them: this is mainly\n   to satisfy leak detectors.  */\nstatic struct dep **dropped_list = NULL;\nstatic size_t dropped_list_len = 0;\n#define DROPPED_LIST_INCR 5\n\nstatic enum update_status update_file (struct file *file, unsigned int depth);\nstatic enum update_status update_file_1 (struct file *file, unsigned int depth);\nstatic enum update_status check_dep (struct file *file, unsigned int depth,\n                                     FILE_TIMESTAMP this_mtime, int *must_make);\nstatic enum update_status touch_file (struct file *file);\nstatic void remake_file (struct file *file);\nstatic FILE_TIMESTAMP name_mtime (const char *name);\nstatic const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr);\n\n\f\nstatic void\ncheck_also_make (const struct file *file)\n{\n  struct dep *ad;\n  FILE_TIMESTAMP mtime = file->last_mtime;\n\n  if (mtime == UNKNOWN_MTIME)\n    mtime = name_mtime (file->name);\n\n  /* If we updated the file, check its also-make files.  */\n\n  if (is_ordinary_mtime (mtime) && mtime > file->mtime_before_update)\n    for (ad = file->also_make; ad; ad = ad->next)\n      if (ad->file->last_mtime == NONEXISTENT_MTIME)\n        OS (error, file->cmds ? &file->cmds->fileinfo : NILF,\n            _(\"warning: pattern recipe did not update peer target '%s'\"),\n            ad->file->name);\n}\n\n/* Remake all the goals in the 'struct dep' chain GOALS.  Return update_status\n   representing the totality of the status of the goals.\n\n   If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q,\n   and -n should be disabled for them unless they were also command-line\n   targets, and we should only make one goal at a time and return as soon as\n   one goal whose 'changed' member is nonzero is successfully made.  */\n\nenum update_status\nupdate_goal_chain (struct goaldep *goaldeps)\n{\n  unsigned long last_cmd_count = 0;\n  int t = touch_flag, q = question_flag, n = just_print_flag;\n  enum update_status status = us_none;\n  const unsigned int depth = rebuilding_makefiles ? 1 : 0;\n\n  /* Duplicate the chain so we can remove things from it.  */\n  struct dep *goals_orig = copy_dep_chain ((struct dep *)goaldeps);\n  struct dep *goals = goals_orig;\n\n  goal_list = rebuilding_makefiles ? goaldeps : NULL;\n\n#define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \\\n                     : file_mtime (file))\n\n  /* Start a fresh batch of consideration.  */\n  ++considered;\n\n  /* Update all the goals until they are all finished.  */\n\n  while (goals != 0)\n    {\n      struct dep *gu, *g, *lastgoal;\n      int running = 0, wait = 0;\n\n      /* Start jobs that are waiting for the load to go down.  */\n\n      start_waiting_jobs ();\n\n      /* Check for exited children.  If no children have finished since the\n         last time we looked, then block until one exits.  If some have\n         exited don't block, so we can possibly do more work.  */\n\n      reap_children (last_cmd_count == command_count, 0);\n      last_cmd_count = command_count;\n\n      lastgoal = 0;\n      gu = goals;\n      while (gu != 0)\n        {\n          /* Iterate over all double-colon entries for this file.  */\n          struct file *file, *dchead;\n          int stop = 0, all_updated = 1;\n\n          g = gu->shuf ? gu->shuf : gu;\n\n          goal_dep = g;\n          dchead = g->file->double_colon ? g->file->double_colon : g->file;\n          for (file = dchead; file != NULL; file = file->prev)\n            {\n              unsigned int ocommands_started;\n              enum update_status fail;\n\n              file->dontcare = ANY_SET (g->flags, RM_DONTCARE);\n\n              check_renamed (file);\n              if (rebuilding_makefiles)\n                {\n                  if (file->cmd_target)\n                    {\n                      touch_flag = t;\n                      question_flag = q;\n                      just_print_flag = n;\n                    }\n                  else\n                    touch_flag = question_flag = just_print_flag = 0;\n                }\n\n              /* Save the old value of 'commands_started' so we can compare\n                 later.  It will be incremented when any commands are\n                 actually run.  */\n              ocommands_started = commands_started;\n\n              stop = 0;\n\n              /* In the case of double colon rules, only the recipe of the 1st\n                 rule should be blocked by .WAIT. The recipes of all subsequent\n                 rules for the same file will execute sequentially in order\n                 after the 1st.  */\n              wait = file == dchead && g->wait_here && running;\n              if (wait)\n                {\n                  DBF (DB_VERBOSE, _(\".WAIT is blocking '%s'.\\n\"));\n                  break;\n                }\n\n              fail = update_file (file, depth);\n              check_renamed (file);\n              running |= (file->command_state == cs_running\n                          || file->command_state == cs_deps_running);\n\n\n              /* Set the goal's 'changed' flag if any commands were started\n                 by calling update_file above.  We check this flag below to\n                 decide when to give an \"up to date\" diagnostic.  */\n              if (commands_started > ocommands_started)\n                g->changed = 1;\n\n              if ((fail || file->updated) && status < us_question)\n                {\n                  /* We updated this goal.  Update STATUS and decide whether\n                     to stop.  */\n                  if (file->update_status)\n                    {\n                      /* Updating failed, or -q triggered.  The STATUS value\n                         tells our caller which.  */\n                      status = file->update_status;\n                      /* If -q just triggered, stop immediately.  It doesn't\n                         matter how much more we run, since we already know\n                         the answer to return.  */\n                      stop = (question_flag && !keep_going_flag\n                              && !rebuilding_makefiles);\n                    }\n                  else\n                    {\n                      FILE_TIMESTAMP mtime = MTIME (file);\n                      check_renamed (file);\n\n                      if (file->updated && mtime != file->mtime_before_update)\n                        {\n                          /* Updating was done.  If this is a makefile and\n                             just_print_flag or question_flag is set (meaning\n                             -n or -q was given and this file was specified\n                             as a command-line target), don't change STATUS.\n                             If STATUS is changed, we will get re-exec'd, and\n                             enter an infinite loop.  */\n                          if (!rebuilding_makefiles\n                              || (!just_print_flag && !question_flag))\n                            status = us_success;\n                          if (rebuilding_makefiles && file->dontcare)\n                            /* This is a default makefile; stop remaking.  */\n                            stop = 1;\n                        }\n                    }\n                }\n\n              /* Keep track if any double-colon entry is not finished.\n                 When they are all finished, the goal is finished.  */\n              all_updated &= file->updated;\n\n              file->dontcare = 0;\n\n              if (stop)\n                break;\n            }\n\n          /* Reset FILE since it is null at the end of the loop.  */\n          file = g->file;\n\n          if (wait)\n            break;\n\n          if (stop || all_updated)\n            {\n              /* If we have found nothing whatever to do for the goal,\n                 print a message saying nothing needs doing.  */\n\n              if (!rebuilding_makefiles\n                  /* If the update_status is success, we updated successfully\n                     or not at all.  G->changed will have been set above if\n                     any commands were actually started for this goal.  */\n                  && file->update_status == us_success && !g->changed\n                  /* Never give a message under -s or -q.  */\n                  && !run_silent && !question_flag)\n                OS (message, 1, ((file->phony || file->cmds == 0)\n                                 ? _(\"Nothing to be done for '%s'.\")\n                                 : _(\"'%s' is up to date.\")),\n                    file->name);\n\n              /* This goal is finished.  Remove it from the chain.  */\n              if (lastgoal == 0)\n                goals = gu->next;\n              else\n                lastgoal->next = gu->next;\n\n              if (stop)\n                break;\n            }\n          else\n            lastgoal = gu;\n\n          gu = gu->next;\n        }\n\n      /* If we reached the end of the dependency graph update CONSIDERED\n         for the next pass.  In the case of waiting, increment CONSIDERED to\n         prevent the same file from getting pruned over and over again.  */\n      if (gu == 0 || wait)\n        ++considered;\n    }\n\n  free_dep_chain (goals_orig);\n\n  if (rebuilding_makefiles)\n    {\n      touch_flag = t;\n      question_flag = q;\n      just_print_flag = n;\n    }\n\n  return status;\n}\n\f\n/* If we're rebuilding an included makefile that failed, and we care\n   about errors, show an error message the first time.  */\n\nvoid\nshow_goal_error (void)\n{\n  struct goaldep *goal;\n\n  if ((goal_dep->flags & (RM_INCLUDED|RM_DONTCARE)) != RM_INCLUDED)\n    return;\n\n  for (goal = goal_list; goal; goal = goal->next)\n    if (goal_dep->file == goal->file)\n      {\n        if (goal->error)\n          {\n            OSS (error, &goal->floc, \"%s: %s\",\n                 goal->file->name, strerror (goal->error));\n            goal->error = 0;\n          }\n        return;\n      }\n}\n\f\n/* If FILE is not up to date, execute the commands for it.\n   Return 0 if successful, non-0 if unsuccessful;\n   but with some flag settings, just call 'exit' if unsuccessful.\n\n   DEPTH is the depth in recursions of this function.\n   We increment it during the consideration of our dependencies,\n   then decrement it again after finding out whether this file\n   is out of date.\n\n   If there are multiple double-colon entries for FILE,\n   each is considered in turn.  */\n\nstatic enum update_status\nupdate_file (struct file *file, unsigned int depth)\n{\n  enum update_status status = us_success;\n  struct file *f;\n\n  f = file->double_colon ? file->double_colon : file;\n\n  /* Prune the dependency graph: if we've already been here on _this_\n     pass through the dependency graph, we don't have to go any further.\n     We won't reap_children until we start the next pass, so no state\n     change is possible below here until then.  */\n  if (f->considered == considered)\n    {\n      /* Check for the case where a target has been tried and failed but\n         the diagnostics haven't been issued. If we need the diagnostics\n         then we will have to continue.\n         In the case of double colon rules, this file cannot be pruned if\n         this recipe finished (file->command_state == cs_finished) and there\n         are more double colon rules for this file. Instead the recipe of the\n         next double colon rule of this file should be run.  */\n      if (!(f->updated && f->update_status > us_none\n            && !f->dontcare && f->no_diag)\n            && !(file->double_colon && file->command_state == cs_finished &&\n                 f->prev))\n        {\n          DBF (DB_VERBOSE, _(\"Pruning file '%s'.\\n\"));\n          return f->command_state == cs_finished ? f->update_status : us_success;\n        }\n    }\n\n  /* This loop runs until we start commands for a double colon rule, or until\n     the chain is exhausted. */\n  for (; f != 0; f = f->prev)\n    {\n      enum update_status new;\n\n      f->considered = considered;\n\n      new = update_file_1 (f, depth);\n      check_renamed (f);\n\n      /* Clean up any alloca() used during the update.  */\n      free_alloca ();\n\n      /* If we got an error, don't bother with double_colon etc.  */\n      if (new && !keep_going_flag)\n        return new;\n\n      if (f->command_state == cs_running\n          || f->command_state == cs_deps_running)\n        /* Don't run other :: rules for this target until\n           this rule is finished.  Multiple recipes running in parallel and\n           updating the same target will corrupt the target.  */\n        return us_success;\n\n      if (new > status)\n        status = new;\n    }\n\n  return status;\n}\n\f\n/* Show a message stating the target failed to build.  */\n\nstatic void\ncomplain (struct file *file)\n{\n  /* If this file has no_diag set then it means we tried to update it\n     before in the dontcare mode and failed. The target that actually\n     failed is not necessarily this file but could be one of its direct\n     or indirect dependencies. So traverse this file's dependencies and\n     find the one that actually caused the failure. */\n\n  struct dep *d;\n\n  for (d = file->deps; d != 0; d = d->next)\n    {\n      if (d->file->updated && d->file->update_status > us_none && file->no_diag)\n        {\n          complain (d->file);\n          break;\n        }\n    }\n\n  if (d == 0)\n    {\n      show_goal_error ();\n\n      /* Didn't find any dependencies to complain about. */\n      if (file->parent)\n        {\n          size_t l = strlen (file->name) + strlen (file->parent->name) + 4;\n          const char *m = _(\"%sNo rule to make target '%s', needed by '%s'%s\");\n\n          if (!keep_going_flag)\n            fatal (NILF, l, m, \"\", file->name, file->parent->name, \"\");\n\n          error (NILF, l, m, \"*** \", file->name, file->parent->name, \".\");\n        }\n      else\n        {\n          size_t l = strlen (file->name) + 4;\n          const char *m = _(\"%sNo rule to make target '%s'%s\");\n\n          if (!keep_going_flag)\n            fatal (NILF, l, m, \"\", file->name, \"\");\n\n          error (NILF, l, m, \"*** \", file->name, \".\");\n        }\n\n      file->no_diag = 0;\n    }\n}\n\n/* Consider a single 'struct file' and update it as appropriate.\n   Return an update_status value; use us_success if we aren't sure yet.  */\n\nstatic enum update_status\nupdate_file_1 (struct file *file, unsigned int depth)\n{\n  enum update_status dep_status = us_success;\n  FILE_TIMESTAMP this_mtime;\n  int noexist, must_make, deps_changed;\n  struct file *ofile;\n  struct dep *du, *d, *ad;\n  struct dep amake;\n  int running = 0;\n\n  DBF (DB_VERBOSE, _(\"Considering target file '%s'.\\n\"));\n\n  if (file->updated)\n    {\n      if (file->update_status > us_none)\n        {\n          DBF (DB_VERBOSE,\n               _(\"Recently tried and failed to update file '%s'.\\n\"));\n\n          /* If the file we tried to make is marked no_diag then no message\n             was printed about it when it failed during the makefile rebuild.\n             If we're trying to build it again in the normal rebuild, print a\n             message now.  */\n          if (file->no_diag && !file->dontcare)\n              complain (file);\n\n          return file->update_status;\n        }\n\n      DBF (DB_VERBOSE, _(\"File '%s' was considered already.\\n\"));\n      return us_success;\n    }\n\n  switch (file->command_state)\n    {\n    case cs_not_started:\n    case cs_deps_running:\n      break;\n    case cs_running:\n      DBF (DB_VERBOSE, _(\"Still updating file '%s'.\\n\"));\n      return us_success;\n    case cs_finished:\n      DBF (DB_VERBOSE, _(\"Finished updating file '%s'.\\n\"));\n      return file->update_status;\n    default:\n      abort ();\n    }\n\n  /* Determine whether the diagnostics will be issued should this update\n     fail. */\n  file->no_diag = file->dontcare;\n\n  /* Notice recursive update of the same file.  */\n  start_updating (file);\n\n  /* We might change file if we find a different one via vpath;\n     remember this one to turn off updating.  */\n  ofile = file;\n\n  /* Increase the depth for reporting how we build the file.  */\n  ++depth;\n\n  /* Looking at the file's modtime beforehand allows the possibility\n     that its name may be changed by a VPATH search, and thus it may\n     not need an implicit rule.  If this were not done, the file\n     might get implicit commands that apply to its initial name, only\n     to have that name replaced with another found by VPATH search.  */\n\n  this_mtime = file_mtime (file);\n  check_renamed (file);\n  noexist = this_mtime == NONEXISTENT_MTIME;\n  if (noexist)\n    {\n      if (file->phony)\n        DBF (DB_BASIC, _(\"Target '%s' is phony.\\n\"));\n      else\n        DBF (DB_BASIC, _(\"File '%s' does not exist.\\n\"));\n    }\n  else if (is_ordinary_mtime (this_mtime) && file->low_resolution_time)\n    {\n      /* Avoid spurious rebuilds due to low resolution time stamps.  */\n      int ns = FILE_TIMESTAMP_NS (this_mtime);\n      if (ns != 0)\n        OS (error, NILF,\n            _(\"*** warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp\"),\n            file->name);\n      this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;\n    }\n\n  /* If any also_make target doesn't exist, we must remake this one too.\n     If they do exist choose the oldest mtime so they will rebuild.  */\n\n  for (ad = file->also_make; ad && !noexist; ad = ad->next)\n    {\n      struct file *adfile = ad->file;\n      FILE_TIMESTAMP fmtime = file_mtime (adfile);\n\n      noexist = fmtime == NONEXISTENT_MTIME;\n      if (noexist)\n        {\n          check_renamed (adfile);\n          if (adfile->phony)\n            DBS (DB_BASIC,\n                 (_(\"Grouped target peer '%s' of file '%s' is phony.\\n\"),\n                  adfile->name, file->name));\n          else\n            DBS (DB_BASIC,\n                 (_(\"Grouped target peer '%s' of file '%s' does not exist.\\n\"),\n                  adfile->name, file->name));\n        }\n      else if (fmtime < this_mtime)\n        this_mtime = fmtime;\n    }\n\n  must_make = noexist;\n\n  /* If file was specified as a target with no commands, come up with some\n     default commands.  This may also add more also_make files.  */\n\n  if (!file->phony && file->cmds == 0 && !file->tried_implicit)\n    {\n      try_implicit_rule (file, depth);\n      file->tried_implicit = 1;\n    }\n  if (file->cmds == 0 && !file->is_target\n      && default_file != 0 && default_file->cmds != 0)\n    {\n      DBF (DB_IMPLICIT, _(\"Using default recipe for '%s'.\\n\"));\n      file->cmds = default_file->cmds;\n    }\n\n  /* Update all non-intermediate files we depend on, if necessary, and see\n     whether any of them is more recent than this file.  We need to walk our\n     deps, AND the deps of any also_make targets to ensure everything happens\n     in the correct order.  */\n\n  amake.file = file;\n  amake.next = file->also_make;\n  ad = &amake;\n  while (ad)\n    {\n      struct dep *lastd = 0;\n\n      /* Perform second expansion and enter each dependency name as a file.\n         We only need to do this if second_expansion has been defined; if it\n         hasn't then all deps were expanded as the makefile was read in.  */\n      if (second_expansion)\n        expand_deps (ad->file);\n\n      /* Find the deps we're scanning */\n      du = ad->file->deps;\n      ad = ad->next;\n\n      while (du)\n        {\n          enum update_status new;\n          FILE_TIMESTAMP mtime;\n          int maybe_make;\n          int dontcare = 0;\n\n          d = du->shuf ? du->shuf : du;\n\n          if (d->wait_here && running)\n            break;\n\n          check_renamed (d->file);\n\n          mtime = file_mtime (d->file);\n          check_renamed (d->file);\n\n          if (is_updating (d->file))\n            {\n              /* Avoid macro warning, bacause its output differs from that of\n                 older makes. */\n              if (warn_error (wt_circular_dep))\n                OSS (fatal, NILF, _(\"circular %s <- %s dependency detected\"),\n                     file->name, d->file->name);\n              if (warn_check (wt_circular_dep))\n                OSS (error, NILF, _(\"circular %s <- %s dependency dropped\"),\n                     file->name, d->file->name);\n\n              if (lastd == 0)\n                file->deps = du->next;\n              else\n                lastd->next = du->next;\n\n              du = du->next;\n\n              /* We cannot free D here because our the caller will still have\n                 a reference to it when we were called recursively via\n                 check_dep below.  */\n              if (dropped_list_len % DROPPED_LIST_INCR == 0)\n                dropped_list = xrealloc (dropped_list,\n                                         sizeof (struct dep *) * (dropped_list_len + DROPPED_LIST_INCR));\n              dropped_list[dropped_list_len++] = d;\n\n              continue;\n            }\n\n          d->file->parent = file;\n          maybe_make = must_make;\n\n          /* Inherit dontcare flag from our parent. */\n          if (rebuilding_makefiles)\n            {\n              dontcare = d->file->dontcare;\n              d->file->dontcare = file->dontcare;\n            }\n\n          new = check_dep (d->file, depth, this_mtime, &maybe_make);\n          if (new > dep_status)\n            dep_status = new;\n\n          /* Restore original dontcare flag. */\n          if (rebuilding_makefiles)\n            d->file->dontcare = dontcare;\n\n          if (! d->ignore_mtime)\n            must_make = maybe_make;\n\n          check_renamed (d->file);\n\n          {\n            struct file *f = d->file;\n            if (f->double_colon)\n              f = f->double_colon;\n            do\n              {\n                running |= (f->command_state == cs_running\n                            || f->command_state == cs_deps_running);\n                f = f->prev;\n              }\n            while (f != 0);\n          }\n\n          if (dep_status && !keep_going_flag)\n            break;\n\n          if (!running)\n            /* The prereq is considered changed if the timestamp has changed\n               while it was built, OR it doesn't exist.  */\n            d->changed = ((file_mtime (d->file) != mtime)\n                          || (mtime == NONEXISTENT_MTIME));\n\n          lastd = du;\n          du = du->next;\n        }\n    }\n\n  /* Now we know whether this target needs updating.\n     If it does, update all the intermediate files we depend on.  */\n\n  if (must_make || always_make_flag)\n    {\n      for (du = file->deps; du != 0; du = du->next)\n        {\n          d = du->shuf ? du->shuf : du;\n\n          if (d->wait_here && running)\n            break;\n\n          if (d->file->intermediate)\n            {\n              enum update_status new;\n              int dontcare = 0;\n\n              FILE_TIMESTAMP mtime = file_mtime (d->file);\n              check_renamed (d->file);\n              d->file->parent = file;\n\n              /* Inherit dontcare flag from our parent. */\n              if (rebuilding_makefiles)\n                {\n                  dontcare = d->file->dontcare;\n                  d->file->dontcare = file->dontcare;\n                }\n\n              /* We may have already considered this file, when we didn't know\n                 we'd need to update it.  Force update_file() to consider it and\n                 not prune it.  */\n              d->file->considered = 0;\n\n              new = update_file (d->file, depth);\n              if (new > dep_status)\n                dep_status = new;\n\n              /* Restore original dontcare flag. */\n              if (rebuilding_makefiles)\n                d->file->dontcare = dontcare;\n\n              check_renamed (d->file);\n\n              {\n                struct file *f = d->file;\n                if (f->double_colon)\n                  f = f->double_colon;\n                do\n                  {\n                    running |= (f->command_state == cs_running\n                                || f->command_state == cs_deps_running);\n                    f = f->prev;\n                  }\n                while (f != 0);\n              }\n\n              if (dep_status && !keep_going_flag)\n                break;\n\n              if (!running)\n                d->changed = ((file->phony && file->cmds != 0)\n                              || file_mtime (d->file) != mtime);\n            }\n        }\n    }\n\n  finish_updating (file);\n  finish_updating (ofile);\n\n  /* We've decided what we need to do to build the file.  */\n  --depth;\n\n  if (running)\n    {\n      set_command_state (file, cs_deps_running);\n      DBF (DB_VERBOSE, _(\"The prerequisites of '%s' are being made.\\n\"));\n      return us_success;\n    }\n\n  DBF (DB_VERBOSE, _(\"Finished prerequisites of target file '%s'.\\n\"));\n\n  /* If any dependency failed, give up now.  */\n\n  if (dep_status)\n    {\n      /* I'm not sure if we can't just assign dep_status...  */\n      file->update_status = dep_status == us_none ? us_failed : dep_status;\n      notice_finished_file (file);\n\n      DBF (DB_VERBOSE, _(\"Giving up on target file '%s'.\\n\"));\n\n      if (depth == 0 && keep_going_flag\n          && !just_print_flag && !question_flag)\n        OS (error, NILF,\n            _(\"Target '%s' not remade because of errors.\"), file->name);\n\n      return dep_status;\n    }\n\n  if (file->command_state == cs_deps_running)\n    /* The commands for some deps were running on the last iteration, but\n       they have finished now.  Reset the command_state to not_started to\n       simplify later bookkeeping.  It is important that we do this only\n       when the prior state was cs_deps_running, because that prior state\n       was definitely propagated to FILE's also_make's by set_command_state\n       (called above), but in another state an also_make may have\n       independently changed to finished state, and we would confuse that\n       file's bookkeeping (updated, but not_started is bogus state).  */\n    set_command_state (file, cs_not_started);\n\n  /* Now record which prerequisites are more\n     recent than this file, so we can define $?.  */\n\n  deps_changed = 0;\n  for (d = file->deps; d != 0; d = d->next)\n    {\n      FILE_TIMESTAMP d_mtime = file_mtime (d->file);\n      check_renamed (d->file);\n\n      if (! d->ignore_mtime)\n        {\n#if 1\n          /* %%% In version 4, remove this code completely to\n           implement not remaking deps if their deps are newer\n           than their parents.  */\n          if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate)\n            /* We must remake if this dep does not\n               exist and is not intermediate.  */\n            must_make = 1;\n#endif\n\n          /* Set DEPS_CHANGED if this dep actually changed.  */\n          deps_changed |= d->changed;\n        }\n\n      /* Set D->changed if either this dep actually changed,\n         or its dependent, FILE, is older or does not exist.  */\n      d->changed |= noexist || d_mtime > this_mtime;\n\n      if (!noexist && ISDB (DB_BASIC|DB_VERBOSE))\n        {\n          const char *fmt = 0;\n\n          if (d->ignore_mtime)\n            {\n              if (ISDB (DB_VERBOSE))\n                fmt = _(\"Prerequisite '%s' is order-only for target '%s'.\\n\");\n            }\n          else if (d_mtime == NONEXISTENT_MTIME)\n            {\n              if (ISDB (DB_BASIC))\n                {\n                  if (d->file->phony)\n                    fmt = _(\"Prerequisite '%s' of target '%s' is phony.\\n\");\n                  else\n                    fmt = _(\"Prerequisite '%s' of target '%s' does not exist.\\n\");\n                }\n            }\n          else if (d->changed)\n            {\n              if (ISDB (DB_BASIC))\n                fmt = _(\"Prerequisite '%s' is newer than target '%s'.\\n\");\n            }\n          else if (ISDB (DB_VERBOSE))\n            fmt = _(\"Prerequisite '%s' is older than target '%s'.\\n\");\n\n          if (fmt)\n            {\n              print_spaces (depth+1);\n              printf (fmt, dep_name (d), file->name);\n              fflush (stdout);\n            }\n        }\n    }\n\n  if (file->double_colon && file->deps == 0)\n    {\n      must_make = 1;\n      DBF (DB_BASIC,\n           _(\"Target '%s' is double-colon and has no prerequisites.\\n\"));\n    }\n  else if (!noexist && file->is_target && !deps_changed && file->cmds == 0\n           && !always_make_flag)\n    {\n      must_make = 0;\n      DBF (DB_VERBOSE,\n           _(\"No recipe for '%s' and no prerequisites actually changed.\\n\"));\n    }\n  else if (!must_make && file->cmds != 0 && always_make_flag)\n    {\n      must_make = 1;\n      DBF (DB_VERBOSE, _(\"Making '%s' due to always-make flag.\\n\"));\n    }\n\n  if (!must_make)\n    {\n      if (ISDB (DB_VERBOSE))\n        {\n          print_spaces (depth);\n          printf (_(\"No need to remake target '%s'\"), file->name);\n          if (!streq (file->name, file->hname))\n              printf (_(\"; using VPATH name '%s'\"), file->hname);\n          puts (\".\");\n          fflush (stdout);\n        }\n\n      /* Since make has not created this file, make should not remove it,\n         even if the file is intermediate. */\n      if (!file->notintermediate && no_intermediates == 0)\n        file->secondary = 1;\n\n      notice_finished_file (file);\n\n      /* Since we don't need to remake the file, convert it to use the\n         VPATH filename if we found one.  hfile will be either the\n         local name if no VPATH or the VPATH name if one was found.  */\n\n      while (file)\n        {\n          file->name = file->hname;\n          file = file->prev;\n        }\n\n      return us_success;\n    }\n\n  DBF (DB_BASIC, _(\"Must remake target '%s'.\\n\"));\n\n  /* It needs to be remade.  If it's VPATH and not reset via GPATH, toss the\n     VPATH.  */\n  if (!streq (file->name, file->hname))\n    {\n      DB (DB_BASIC, (_(\"  Ignoring VPATH name '%s'.\\n\"), file->hname));\n      file->ignore_vpath = 1;\n    }\n\n  /* Now, take appropriate actions to remake the file.  */\n  remake_file (file);\n\n  if (file->command_state != cs_finished)\n    {\n      DBF (DB_VERBOSE, _(\"Recipe of '%s' is being run.\\n\"));\n      return us_success;\n    }\n\n  switch (file->update_status)\n    {\n    case us_failed:\n      DBF (DB_BASIC, _(\"Failed to remake target file '%s'.\\n\"));\n      break;\n    case us_success:\n      DBF (DB_BASIC, _(\"Successfully remade target file '%s'.\\n\"));\n      break;\n    case us_question:\n      DBF (DB_BASIC, _(\"Target file '%s' needs to be remade under -q.\\n\"));\n      break;\n    case us_none:\n      break;\n    }\n\n  file->updated = 1;\n  return file->update_status;\n}\n\f\n/* Set FILE's 'updated' flag and re-check its mtime and the mtime's of all\n   files listed in its 'also_make' member.  Under -t, this function also\n   touches FILE.\n\n   On return, FILE->update_status will no longer be us_none if it was.  */\n\nvoid\nnotice_finished_file (struct file *file)\n{\n  struct dep *d;\n  int ran = file->command_state == cs_running;\n  int touched = 0;\n\n  file->command_state = cs_finished;\n  file->updated = 1;\n\n  if (touch_flag\n      /* The update status will be:\n           us_success   if 0 or more commands (+ or ${MAKE}) were run and won;\n           us_none      if this target was not remade;\n           >us_none     if some commands were run and lost.\n         We touch the target if it has commands which either were not run\n         or won when they ran (i.e. status is 0).  */\n      && file->update_status == us_success)\n    {\n      if (file->cmds != 0 && file->cmds->any_recurse)\n        {\n          /* If all the command lines were recursive,\n             we don't want to do the touching.  */\n          unsigned int i;\n          for (i = 0; i < file->cmds->ncommand_lines; ++i)\n            if (NONE_SET (file->cmds->lines_flags[i], COMMANDS_RECURSE))\n              goto have_nonrecursing;\n        }\n      else\n        {\n        have_nonrecursing:\n          if (file->phony)\n            file->update_status = us_success;\n          /* According to POSIX, -t doesn't affect targets with no cmds.  */\n          else if (file->cmds != 0)\n            {\n              /* Should set file's modification date and do nothing else.  */\n              file->update_status = touch_file (file);\n\n              /* Pretend we ran a real touch command, to suppress the\n                 \"'foo' is up to date\" message.  */\n              commands_started++;\n\n              /* Request for the timestamp to be updated (and distributed\n                 to the double-colon entries). Simply setting ran=1 would\n                 almost have done the trick, but messes up with the also_make\n                 updating logic below.  */\n              touched = 1;\n            }\n        }\n    }\n\n  if (file->mtime_before_update == UNKNOWN_MTIME)\n    file->mtime_before_update = file->last_mtime;\n\n  if ((ran && !file->phony) || touched)\n    {\n      int i = 0;\n\n      /* If -n, -t, or -q and all the commands are recursive, we ran them so\n         really check the target's mtime again.  Otherwise, assume the target\n         would have been updated. */\n\n      if ((question_flag || just_print_flag || touch_flag) && file->cmds)\n        {\n          for (i = file->cmds->ncommand_lines; i > 0; --i)\n            if (NONE_SET (file->cmds->lines_flags[i-1], COMMANDS_RECURSE))\n              break;\n        }\n\n      /* If there were no commands at all, it's always new. */\n\n      else if (file->is_target && file->cmds == 0)\n        i = 1;\n\n      file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME;\n    }\n\n  if (file->double_colon)\n    {\n      /* If this is a double colon rule and it is the last one to be\n         updated, propagate the change of modification time to all the\n         double-colon entries for this file.\n\n         We do it on the last update because it is important to handle\n         individual entries as separate rules with separate timestamps\n         while they are treated as targets and then as one rule with the\n         unified timestamp when they are considered as a prerequisite\n         of some target.  */\n\n      struct file *f;\n      FILE_TIMESTAMP max_mtime = file->last_mtime;\n\n      /* Check that all rules were updated and at the same time find\n         the max timestamp.  We assume UNKNOWN_MTIME is newer then\n         any other value.  */\n      for (f = file->double_colon; f != 0 && f->updated; f = f->prev)\n        if (max_mtime != UNKNOWN_MTIME\n            && (f->last_mtime == UNKNOWN_MTIME || f->last_mtime > max_mtime))\n          max_mtime = f->last_mtime;\n\n      if (f == 0)\n        for (f = file->double_colon; f != 0; f = f->prev)\n          f->last_mtime = max_mtime;\n    }\n\n  if (ran && file->update_status != us_none)\n    {\n      /* We actually tried to update FILE, which has\n         updated its also_make's as well (if it worked).\n         If it didn't work, it wouldn't work again for them.\n         So mark them as updated with the same status.  */\n      for (d = file->also_make; d != 0; d = d->next)\n        {\n          d->file->command_state = cs_finished;\n          d->file->updated = 1;\n          d->file->update_status = file->update_status;\n\n          if (ran && !d->file->phony)\n            {\n              /* Fetch the new modification time.\n                 We do this instead of just invalidating the cached time\n                 so that a vpath_search can happen.  Otherwise, it would\n                 never be done because the target is already updated.  */\n              f_mtime (d->file, 0);\n\n              if (just_print_flag)\n                /* Nothing got updated, but pretend it did.  */\n                d->file->last_mtime = NEW_MTIME;\n            }\n        }\n\n      /* If the target was created by an implicit rule, and it was updated,\n         warn about any of its also_make targets that don't exist.  */\n      if (file->tried_implicit && file->also_make)\n        check_also_make (file);\n    }\n  else if (file->update_status == us_none)\n    /* Nothing was done for FILE, but it needed nothing done.\n       So mark it now as \"succeeded\".  */\n    file->update_status = us_success;\n}\n\f\n/* Check whether another file (whose mtime is THIS_MTIME) needs updating on\n   account of a dependency which is file FILE.  If it does, store 1 in\n   *MUST_MAKE_PTR.  In the process, update any non-intermediate files that\n   FILE depends on (including FILE itself).  Return nonzero if any updating\n   failed.  */\n\nstatic enum update_status\ncheck_dep (struct file *file, unsigned int depth,\n           FILE_TIMESTAMP this_mtime, int *must_make_ptr)\n{\n  struct file *ofile;\n  struct dep *d;\n  enum update_status dep_status = us_success;\n\n  start_updating (file);\n\n  /* We might change file if we find a different one via vpath;\n     remember this one to turn off updating.  */\n  ofile = file;\n\n  if (file->phony || !file->intermediate)\n    {\n      /* If this is a non-intermediate file, update it and record whether it\n         is newer than THIS_MTIME.  */\n      FILE_TIMESTAMP mtime;\n      dep_status = update_file (file, depth);\n      check_renamed (file);\n      mtime = file_mtime (file);\n      check_renamed (file);\n      if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)\n        *must_make_ptr = 1;\n    }\n  else\n    {\n      /* FILE is an intermediate file.  */\n      FILE_TIMESTAMP mtime;\n\n      if (!file->phony && file->cmds == 0 && !file->tried_implicit)\n        {\n          try_implicit_rule (file, depth);\n          file->tried_implicit = 1;\n        }\n      if (file->cmds == 0 && !file->is_target\n          && default_file != 0 && default_file->cmds != 0)\n        {\n          DBF (DB_IMPLICIT, _(\"Using default commands for '%s'.\\n\"));\n          file->cmds = default_file->cmds;\n        }\n\n      check_renamed (file);\n      mtime = file_mtime (file);\n      check_renamed (file);\n      if (mtime != NONEXISTENT_MTIME && mtime > this_mtime)\n        /* If the intermediate file actually exists and is newer, then we\n           should remake from it.  */\n        *must_make_ptr = 1;\n      else\n        {\n          /* Otherwise, update all non-intermediate files we depend on, if\n             necessary, and see whether any of them is more recent than the\n             file on whose behalf we are checking.  */\n          struct dep *ld;\n          int deps_running = 0;\n\n          /* If this target is not running, set it's state so that we check it\n             fresh.  It could be it was checked as part of an order-only\n             prerequisite and so wasn't rebuilt then, but should be now.  */\n          if (file->command_state != cs_running)\n            {\n              /* If the target was waiting for a dependency it has to be\n                 reconsidered, as that dependency might have finished.  */\n              if (file->command_state == cs_deps_running)\n                file->considered = 0;\n\n              set_command_state (file, cs_not_started);\n            }\n\n          ld = 0;\n          /* Perform second expansion and enter each dependency name as a file.\n             We only need to do this if second_expansion has been defined; if it\n             hasn't then all deps were expanded as the makefile was read in.  */\n          if (second_expansion)\n            expand_deps (file);\n\n          d = file->deps;\n          while (d != 0)\n            {\n              enum update_status new;\n              int maybe_make;\n\n              if (is_updating (d->file))\n                {\n                  OSS (error, NILF, _(\"circular %s <- %s dependency dropped\"),\n                       file->name, d->file->name);\n                  if (ld == 0)\n                    {\n                      file->deps = d->next;\n                      free_dep (d);\n                      d = file->deps;\n                    }\n                  else\n                    {\n                      ld->next = d->next;\n                      free_dep (d);\n                      d = ld->next;\n                    }\n                  continue;\n                }\n\n              d->file->parent = file;\n              maybe_make = *must_make_ptr;\n              new = check_dep (d->file, depth+1, this_mtime, &maybe_make);\n              if (new > dep_status)\n                dep_status = new;\n\n              if (! d->ignore_mtime)\n                *must_make_ptr = maybe_make;\n              check_renamed (d->file);\n              if (dep_status && !keep_going_flag)\n                break;\n\n              if (d->file->command_state == cs_running\n                  || d->file->command_state == cs_deps_running)\n                deps_running = 1;\n\n              ld = d;\n              d = d->next;\n            }\n\n          if (deps_running)\n            /* Record that some of FILE's deps are still being made.\n               This tells the upper levels to wait on processing it until the\n               commands are finished.  */\n            set_command_state (file, cs_deps_running);\n        }\n    }\n\n  finish_updating (file);\n  finish_updating (ofile);\n\n  return dep_status;\n}\n\f\n/* Touch FILE.  Return us_success if successful, us_failed if not.  */\n\n#define TOUCH_ERROR(call) do{ perror_with_name ((call), file->name);    \\\n                              return us_failed; }while(0)\n\nstatic enum update_status\ntouch_file (struct file *file)\n{\n  if (!run_silent)\n    OS (message, 0, \"touch %s\", file->name);\n\n  /* Print-only (-n) takes precedence over touch (-t).  */\n  if (just_print_flag)\n    return us_success;\n\n#ifndef NO_ARCHIVES\n  if (ar_name (file->name))\n    return ar_touch (file->name) ? us_failed : us_success;\n  else\n#endif\n    {\n      int fd;\n\n      EINTRLOOP (fd, open (file->name, O_RDWR | O_CREAT, 0666));\n      if (fd < 0)\n        TOUCH_ERROR (\"touch: open: \");\n      else\n        {\n          struct stat statbuf;\n          char buf = 'x';\n          int e;\n\n          EINTRLOOP (e, fstat (fd, &statbuf));\n          if (e < 0)\n            TOUCH_ERROR (\"touch: fstat: \");\n          /* Rewrite character 0 same as it already is.  */\n          EINTRLOOP (e, read (fd, &buf, 1));\n          if (e < 0)\n            TOUCH_ERROR (\"touch: read: \");\n          {\n            off_t o;\n            EINTRLOOP (o, lseek (fd, 0L, 0));\n            if (o < 0L)\n              TOUCH_ERROR (\"touch: lseek: \");\n          }\n          EINTRLOOP (e, write (fd, &buf, 1));\n          if (e < 0)\n            TOUCH_ERROR (\"touch: write: \");\n\n          /* If file length was 0, we just changed it, so change it back.  */\n          if (statbuf.st_size == 0)\n            {\n              (void) close (fd);\n              EINTRLOOP (fd, open (file->name, O_RDWR | O_TRUNC, 0666));\n              if (fd < 0)\n                TOUCH_ERROR (\"touch: open: \");\n            }\n          (void) close (fd);\n        }\n    }\n\n  return us_success;\n}\n\f\n/* Having checked and updated the dependencies of FILE,\n   do whatever is appropriate to remake FILE itself.\n   Return the status from executing FILE's commands.  */\n\nstatic void\nremake_file (struct file *file)\n{\n  if (file->cmds == 0)\n    {\n      if (file->phony)\n        /* Phony target.  Pretend it succeeded.  */\n        file->update_status = us_success;\n      else if (file->is_target)\n        /* This is a nonexistent target file we cannot make.\n           Pretend it was successfully remade.  */\n        file->update_status = us_success;\n      else\n        {\n          /* This is a dependency file we cannot remake.  Fail.  */\n          if (!rebuilding_makefiles || !file->dontcare)\n            complain (file);\n          file->update_status = us_failed;\n        }\n    }\n  else\n    {\n      chop_commands (file->cmds);\n\n      /* The normal case: start some commands.  */\n      if (!touch_flag || file->cmds->any_recurse)\n        {\n          execute_file_commands (file);\n          return;\n        }\n\n      /* This tells notice_finished_file it is ok to touch the file.  */\n      file->update_status = us_success;\n    }\n\n  /* This does the touching under -t.  */\n  notice_finished_file (file);\n}\n\f\n/* Return the mtime of a file, given a 'struct file'.\n   Caches the time in the struct file to avoid excess stat calls.\n\n   If the file is not found, and SEARCH is nonzero, VPATH searching and\n   replacement is done.  If that fails, a library (-lLIBNAME) is tried and\n   the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into\n   FILE.  */\n\nFILE_TIMESTAMP\nf_mtime (struct file *file, int search)\n{\n  FILE_TIMESTAMP mtime;\n  unsigned int propagate_timestamp;\n\n  /* File's mtime is not known; must get it from the system.  */\n\n#ifndef NO_ARCHIVES\n  if (ar_name (file->name))\n    {\n      /* This file is an archive-member reference.  */\n      FILE_TIMESTAMP memmtime;\n      char *arname, *memname;\n      struct file *arfile;\n      time_t member_date;\n\n      /* Find the archive's name.  */\n      ar_parse_name (file->name, &arname, &memname);\n\n      /* Find the mtime of the member file (it might not exist).  */\n      memmtime = name_mtime (memname);\n\n      /* Find the modification time of the archive itself.\n         Also allow for its name to be changed via VPATH search.  */\n      arfile = lookup_file (arname);\n      if (arfile == 0)\n        arfile = enter_file (strcache_add (arname));\n      mtime = f_mtime (arfile, search);\n      check_renamed (arfile);\n      if (search && strcmp (arfile->hname, arname))\n        {\n          /* The archive's name has changed.\n             Change the archive-member reference accordingly.  */\n\n          char *name;\n          size_t arlen, memlen;\n\n          arlen = strlen (arfile->hname);\n          memlen = strlen (memname);\n\n          name = alloca (arlen + 1 + memlen + 2);\n          memcpy (name, arfile->hname, arlen);\n          name[arlen] = '(';\n          memcpy (name + arlen + 1, memname, memlen);\n          name[arlen + 1 + memlen] = ')';\n          name[arlen + 1 + memlen + 1] = '\\0';\n\n          /* If the archive was found with GPATH, make the change permanent;\n             otherwise defer it until later.  */\n          if (arfile->name == arfile->hname)\n            rename_file (file, strcache_add (name));\n          else\n            rehash_file (file, strcache_add (name));\n          check_renamed (file);\n        }\n\n      free (arname);\n\n      file->low_resolution_time = 1;\n\n      if (mtime == NONEXISTENT_MTIME)\n        /* The archive doesn't exist, so its members don't exist either.  */\n        return NONEXISTENT_MTIME;\n\n      member_date = ar_member_date (file->hname);\n\n      if (member_date == (time_t) -1\n          || (memmtime != NONEXISTENT_MTIME\n              && (time_t) FILE_TIMESTAMP_S (memmtime) > member_date))\n        /* If the member file exists and is newer than the member in the\n           archive, pretend it's nonexistent.  This means the member file was\n           updated but not added to the archive yet.  */\n        mtime = NONEXISTENT_MTIME;\n      else\n        mtime = file_timestamp_cons (file->hname, member_date, 0);\n    }\n  else\n#endif\n    {\n      mtime = name_mtime (file->name);\n\n      if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)\n        {\n          /* If name_mtime failed, search VPATH.  */\n          const char *name = vpath_search (file->name, &mtime, NULL, NULL);\n          if (name\n              /* Last resort, is it a library (-lxxx)?  */\n              || (file->name[0] == '-' && file->name[1] == 'l'\n                  && (name = library_search (file->name, &mtime)) != 0))\n            {\n              size_t name_len;\n\n              if (mtime != UNKNOWN_MTIME)\n                /* vpath_search and library_search store UNKNOWN_MTIME\n                   if they didn't need to do a stat call for their work.  */\n                file->last_mtime = mtime;\n\n              /* If we found it in VPATH, see if it's in GPATH too; if so,\n                 change the name right now; if not, defer until after the\n                 dependencies are updated. */\n#if !MK_OS_VMS\n              name_len = strlen (name) - strlen (file->name) - 1;\n#else\n              name_len = strlen (name) - strlen (file->name);\n              if (name[name_len - 1] == '/')\n                  name_len--;\n#endif\n              if (gpath_search (name, name_len))\n                {\n                  rename_file (file, name);\n                  check_renamed (file);\n                  return file_mtime (file);\n                }\n\n              rehash_file (file, name);\n              check_renamed (file);\n              /* If the result of a vpath search is -o or -W, preserve it.\n                 Otherwise, find the mtime of the resulting file.  */\n              if (mtime != OLD_MTIME && mtime != NEW_MTIME)\n                mtime = name_mtime (name);\n            }\n        }\n    }\n\n  /* Files can have bogus timestamps that nothing newly made will be\n     \"newer\" than.  Updating their dependents could just result in loops.\n     So notify the user of the anomaly with a warning.\n\n     We only need to do this once, for now. */\n\n  if (!clock_skew_detected\n      && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME\n      && !file->updated)\n    {\n      static FILE_TIMESTAMP adjusted_now;\n\n      FILE_TIMESTAMP adjusted_mtime = mtime;\n\n#if MK_OS_W32 || MK_OS_DOS\n      /* Experimentation has shown that FAT filesystems can set file times\n         up to 3 seconds into the future!  Play it safe.  */\n\n#define FAT_ADJ_OFFSET  (FILE_TIMESTAMP) 3\n\n      FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;\n      if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)\n        adjusted_mtime -= adjustment;\n#endif\n\n      /* If the file's time appears to be in the future, update our\n         concept of the present and try once more.  */\n      if (adjusted_now < adjusted_mtime)\n        {\n          int resolution;\n          FILE_TIMESTAMP now = file_timestamp_now (&resolution);\n          adjusted_now = now + (resolution - 1);\n          if (adjusted_now < adjusted_mtime)\n            {\n              double from_now =\n                (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)\n                 + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))\n                    / 1e9));\n              char from_now_string[100];\n\n              if (from_now >= 100.0 && from_now < (double) ULONG_MAX)\n                sprintf (from_now_string, \"%lu\", (unsigned long) from_now);\n              else\n                sprintf (from_now_string, \"%.2g\", from_now);\n              OSS (error, NILF,\n                   _(\"warning: file '%s' has modification time %s s in the future\"),\n                   file->name, from_now_string);\n              clock_skew_detected = 1;\n            }\n        }\n    }\n\n  /* Store the mtime into all the entries for this file for which it is safe\n     to do so: avoid propagating timestamps to double-colon rules that haven't\n     been examined so they're run or not based on the pre-update timestamp.  */\n  if (file->double_colon)\n    file = file->double_colon;\n\n  propagate_timestamp = file->updated;\n  do\n    {\n      /* If this file is not implicit but it is intermediate then it was\n         made so by the .INTERMEDIATE target.  If this file has never\n         been built by us but was found now, it existed before make\n         started.  So, turn off the intermediate bit so make doesn't\n         delete it, since it didn't create it.  */\n      if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started\n          && !file->tried_implicit && file->intermediate)\n        file->intermediate = 0;\n\n      if (file->updated == propagate_timestamp)\n        file->last_mtime = mtime;\n      file = file->prev;\n    }\n  while (file != 0);\n\n  return mtime;\n}\n\n\n/* Return the mtime of the file or archive-member reference NAME.  */\n\n/* First, we check with stat().  If the file does not exist, then we return\n   NONEXISTENT_MTIME.  If it does, and the symlink check flag is set, then\n   examine each indirection of the symlink and find the newest mtime.\n   This causes one duplicate stat() when -L is being used, but the code is\n   much cleaner.  */\n\nstatic FILE_TIMESTAMP\nname_mtime (const char *name)\n{\n  FILE_TIMESTAMP mtime;\n#if MK_OS_W32\n  struct STAT st;\n#else\n  struct stat st;\n#endif\n  int e;\n\n#if MK_OS_W32\n  {\n    char tem[MAX_PATH+1], *tstart, *tend;\n    const char *p = name + strlen (name);\n\n    /* Remove any trailing slashes and \".\"/\"..\".  MS-Windows stat\n       fails on valid directories if NAME ends in a slash, and we need\n       to emulate the Posix behavior where stat on \"foo/\" or \"foo/.\"\n       succeeds ONLY if \"foo\" is a directory. */\n    if (p > name)\n      {\n        memcpy (tem, name, p - name + 1);\n        tstart = tem;\n        if (tstart[1] == ':')\n          tstart += 2;\n        tend = tem + (p - name - 1);\n        if (*tend == '.' && tend > tstart)\n          tend--;\n        if (*tend == '.' && tend > tstart)\n          tend--;\n        for ( ; tend > tstart && ISDIRSEP (*tend); tend--)\n          *tend = '\\0';\n      }\n    else\n      {\n        tem[0] = '\\0';\n        tend = &tem[0];\n      }\n\n#if MK_OS_W32\n    e = STAT (tem, &st);\n#else\n    e = stat (tem, &st);\n#endif\n    if (e == 0 && !_S_ISDIR (st.st_mode) && tend < tem + (p - name - 1))\n      {\n        errno = ENOTDIR;\n        e = -1;\n      }\n  }\n#else\n  EINTRLOOP (e, stat (name, &st));\n#endif\n  if (e == 0)\n    mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st);\n  else if (errno == ENOENT || errno == ENOTDIR)\n    mtime = NONEXISTENT_MTIME;\n  else\n    {\n      perror_with_name (\"stat: \", name);\n      return NONEXISTENT_MTIME;\n    }\n\n  /* If we get here we either found it, or it doesn't exist.\n     If it doesn't exist see if we can use a symlink mtime instead.  */\n\n#ifdef MAKE_SYMLINKS\n#ifndef S_ISLNK\n# define S_ISLNK(_m)     (((_m)&S_IFMT)==S_IFLNK)\n#endif\n  if (check_symlink_flag && strlen (name) <= GET_PATH_MAX)\n    {\n      PATH_VAR (lpath);\n\n      /* Check each symbolic link segment (if any).  Find the latest mtime\n         amongst all of them (and the target file of course).\n         Note that we have already successfully dereferenced all the links\n         above.  So, if we run into any error trying to lstat(), or\n         readlink(), or whatever, something bizarre-o happened.  Just give up\n         and use whatever mtime we've already computed at that point.  */\n      strcpy (lpath, name);\n      while (1)\n        {\n          FILE_TIMESTAMP ltime;\n          PATH_VAR (lbuf);\n          long llen;\n          char *p;\n\n          EINTRLOOP (e, lstat (lpath, &st));\n          if (e)\n            {\n              /* Just take what we have so far.  */\n              if (errno != ENOENT && errno != ENOTDIR)\n                perror_with_name (\"lstat: \", lpath);\n              break;\n            }\n\n          /* If this is not a symlink, we're done (we started with the real\n             file's mtime so we don't need to test it again).  */\n          if (!S_ISLNK (st.st_mode))\n            break;\n\n          /* If this mtime is newer than what we had, keep the new one.  */\n          ltime = FILE_TIMESTAMP_STAT_MODTIME (lpath, st);\n          if (ltime > mtime)\n            mtime = ltime;\n\n          /* Set up to check the file pointed to by this link.  */\n          EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX - 1));\n          if (llen < 0)\n            {\n              /* Eh?  Just take what we have.  */\n              perror_with_name (\"readlink: \", lpath);\n              break;\n            }\n          lbuf[llen] = '\\0';\n\n          /* If the target is fully-qualified or the source is just a\n             filename, then the new path is the target.  Otherwise it's the\n             source directory plus the target.  */\n          if (lbuf[0] == '/' || (p = strrchr (lpath, '/')) == NULL)\n            strcpy (lpath, lbuf);\n          else if ((p - lpath) + llen + 2 > GET_PATH_MAX)\n            /* Eh?  Path too long!  Again, just go with what we have.  */\n            break;\n          else\n            /* Create the next step in the symlink chain.  */\n            strcpy (p+1, lbuf);\n        }\n    }\n#endif\n\n  return mtime;\n}\n\n\n/* Search for a library file specified as -lLIBNAME, searching for a\n   suitable library file in the system library directories and the VPATH\n   directories.  */\n\nstatic const char *\nlibrary_search (const char *lib, FILE_TIMESTAMP *mtime_ptr)\n{\n  static const char *dirs[] =\n    {\n      \"/lib\",\n      \"/usr/lib\",\n#if MK_OS_W32 && !defined(LIBDIR)\n/*\n * This is completely up to the user at product install time. Just define\n * a placeholder.\n */\n#define LIBDIR \".\"\n#endif\n      LIBDIR,                   /* Defined by configuration.  */\n      0\n    };\n\n  const char *file = 0;\n  char *libpatterns;\n  FILE_TIMESTAMP mtime;\n\n  /* Loop variables for the libpatterns value.  */\n  char *p;\n  const char *p2;\n  size_t len;\n  size_t liblen;\n\n  /* Information about the earliest (in the vpath sequence) match.  */\n  unsigned int best_vpath = 0, best_path = 0;\n\n  const char **dp;\n\n  libpatterns = allocated_expand_variable (STRING_SIZE_TUPLE (\".LIBPATTERNS\"));\n\n  /* Skip the '-l'.  */\n  lib += 2;\n  liblen = strlen (lib);\n\n  /* Loop through all the patterns in .LIBPATTERNS, and search on each one.\n     To implement the linker-compatible behavior we have to search through\n     all entries in .LIBPATTERNS and choose the \"earliest\" one.  */\n  p2 = libpatterns;\n  while ((p = find_next_token (&p2, &len)) != 0)\n    {\n      static char *buf = NULL;\n      static size_t buflen = 0;\n      static size_t libdir_maxlen = 0;\n      static unsigned int std_dirs = 0;\n      char *libbuf;\n\n      /* Expand the pattern using LIB as a replacement.  */\n      {\n        char c = p[len];\n        char *p3, *p4;\n\n        p[len] = '\\0';\n        p3 = find_percent (p);\n        if (!p3)\n          {\n            /* Give a warning if there is no pattern.  */\n            OS (error, NILF,\n                _(\".LIBPATTERNS element '%s' is not a pattern\"), p);\n            p[len] = c;\n            continue;\n          }\n        p4 = variable_buffer_output (variable_buffer, p, p3-p);\n        p4 = variable_buffer_output (p4, lib, liblen);\n        p4 = variable_buffer_output (p4, p3+1, len - (p3-p));\n        p[len] = c;\n\n        libbuf = variable_buffer;\n      }\n\n      /* Look first for 'libNAME.a' in the current directory.  */\n      mtime = name_mtime (libbuf);\n      if (mtime != NONEXISTENT_MTIME)\n        {\n          if (mtime_ptr != 0)\n            *mtime_ptr = mtime;\n          file = strcache_add (libbuf);\n          /* This by definition will have the best index, so stop now.  */\n          break;\n        }\n\n      /* Now try VPATH search on that.  */\n\n      {\n        unsigned int vpath_index, path_index;\n        const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL,\n                                      &vpath_index, &path_index);\n        if (f)\n          {\n            /* If we have a better match, record it.  */\n            if (file == 0 ||\n                vpath_index < best_vpath ||\n                (vpath_index == best_vpath && path_index < best_path))\n              {\n                file = f;\n                best_vpath = vpath_index;\n                best_path = path_index;\n\n                if (mtime_ptr != 0)\n                  *mtime_ptr = mtime;\n              }\n          }\n      }\n\n      /* Now try the standard set of directories.  */\n\n      if (!buflen)\n        {\n          for (dp = dirs; *dp != 0; ++dp)\n            {\n              size_t l = strlen (*dp);\n              if (l > libdir_maxlen)\n                libdir_maxlen = l;\n              std_dirs++;\n            }\n          buflen = strlen (libbuf);\n          buf = xmalloc (libdir_maxlen + buflen + 2);\n        }\n      else if (buflen < strlen (libbuf))\n        {\n          buflen = strlen (libbuf);\n          buf = xrealloc (buf, libdir_maxlen + buflen + 2);\n        }\n\n      {\n        /* Use the last std_dirs index for standard directories. This\n           was it will always be greater than the VPATH index.  */\n        unsigned int vpath_index = ~((unsigned int)0) - std_dirs;\n\n        for (dp = dirs; *dp != 0; ++dp)\n          {\n            sprintf (buf, \"%s/%s\", *dp, libbuf);\n            mtime = name_mtime (buf);\n            if (mtime != NONEXISTENT_MTIME)\n              {\n                if (file == 0 || vpath_index < best_vpath)\n                  {\n                    file = strcache_add (buf);\n                    best_vpath = vpath_index;\n\n                    if (mtime_ptr != 0)\n                      *mtime_ptr = mtime;\n                  }\n              }\n\n            vpath_index++;\n          }\n      }\n\n    }\n\n  free (libpatterns);\n  return file;\n}\n"
  },
  {
    "path": "src/remote-cstms.c",
    "content": "/* GNU Make remote job exportation interface to the Customs daemon.\n   THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT.\n   Please do not send bug reports or questions about it to\n   the Make maintainers.\n\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include \"filedef.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"debug.h\"\n\n#if HAVE_SYS_TIME_H\n# include <sys/time.h>\n#endif\n#include <netdb.h>\n\n#include \"customs.h\"\n\nchar *remote_description = \"Customs\";\n\n/* File name of the Customs 'export' client command.\n   A full path name can be used to avoid some path-searching overhead.  */\n#define EXPORT_COMMAND  \"/usr/local/bin/export\"\n\n/* ExportPermit gotten by start_remote_job_p, and used by start_remote_job.  */\nstatic ExportPermit permit;\n\n/* Normalized path name of the current directory.  */\nstatic char *normalized_cwd;\n\n/* Call once at startup even if no commands are run.  */\n\nvoid\nremote_setup (void)\n{\n}\n\n/* Called before exit.  */\n\nvoid\nremote_cleanup (void)\n{\n}\n\f\n/* Return nonzero if the next job should be done remotely.  */\n\nint\nstart_remote_job_p (int first_p)\n{\n  static int inited = 0;\n  int status;\n  int njobs;\n\n  if (!inited)\n    {\n      /* Allow the user to turn off job exportation (useful while he is\n         debugging Customs, for example).  */\n      if (getenv (\"GNU_MAKE_NO_CUSTOMS\") != 0)\n        {\n          inited = -1;\n          return 0;\n        }\n\n      if (ISDB (DB_JOBS))\n        Rpc_Debug (1);\n\n      /* Ping the daemon once to see if it is there.  */\n      inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;\n\n      if (starting_directory == 0)\n        /* main couldn't figure it out.  */\n        inited = -1;\n      else\n        {\n          /* Normalize the current directory path name to something\n             that should work on all machines exported to.  */\n\n          normalized_cwd = xmalloc (GET_PATH_MAX);\n          strcpy (normalized_cwd, starting_directory);\n          if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0)\n            /* Path normalization failure means using Customs\n               won't work, but it's not really an error.  */\n            inited = -1;\n        }\n    }\n\n  if (inited < 0)\n    return 0;\n\n  njobs = job_slots_used;\n  if (!first_p)\n    njobs -= 1;         /* correction for being called from reap_children() */\n\n  /* the first job should run locally, or, if the -l flag is given, we use\n     that as clue as to how many local jobs should be scheduled locally */\n  if (max_load_average < 0 && njobs == 0 || njobs < max_load_average)\n     return 0;\n\n  status = Customs_Host (EXPORT_SAME, &permit);\n  if (status != RPC_SUCCESS)\n    {\n      DB (DB_JOBS, (_(\"Customs won't export: %s\\n\"),\n                    Rpc_ErrorMessage (status)));\n      return 0;\n    }\n\n  return !CUSTOMS_FAIL (&permit.addr);\n}\n\f\n/* Start a remote job running the command in ARGV, with environment from\n   ENVP.  It gets standard input from STDIN_FD.  On failure, return\n   nonzero.  On success, return zero, and set *USED_STDIN to nonzero if it\n   will actually use STDIN_FD, zero if not, set *ID_PTR to a unique\n   identification, and set *IS_REMOTE to nonzero if the job is remote, zero\n   if it is local (meaning *ID_PTR is a process ID).  */\n\nint\nstart_remote_job (char **argv, char **envp, int stdin_fd,\n                  int *is_remote, pid_t *id_ptr, int *used_stdin)\n{\n  char waybill[MAX_DATA_SIZE], msg[128];\n  struct hostent *host;\n  struct timeval timeout;\n  struct sockaddr_in sin;\n  int len;\n  int retsock, retport, sock;\n  Rpc_Stat status;\n  pid_t pid;\n\n  /* Create the return socket.  */\n  retsock = Rpc_UdpCreate (True, 0);\n  if (retsock < 0)\n    {\n      O (error, NILF, \"exporting: Couldn't create return socket.\");\n      return 1;\n    }\n\n  /* Get the return socket's port number.  */\n  len = sizeof (sin);\n  if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0)\n    {\n      (void) close (retsock);\n      perror_with_name (\"exporting: \", \"getsockname\");\n      return 1;\n    }\n  retport = sin.sin_port;\n\n  /* Create the TCP socket for talking to the remote child.  */\n  sock = Rpc_TcpCreate (False, 0);\n\n  /* Create a WayBill to give to the server.  */\n  len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv,\n                             envp, retport, waybill);\n\n  /* Modify the waybill for the child's uid/gid.  */\n  {\n    WayBill *wb = (WayBill *) waybill;\n    wb->ruid = wb->euid;\n    wb->rgid = wb->egid;\n  }\n\n  /* Send the request to the server, timing out in 20 seconds.  */\n  timeout.tv_usec = 0;\n  timeout.tv_sec = 20;\n  sin.sin_family = AF_INET;\n  sin.sin_port = htons (Customs_Port ());\n  sin.sin_addr = permit.addr;\n  status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT,\n                     len, (Rpc_Opaque) waybill,\n                     sizeof (msg), (Rpc_Opaque) msg,\n                     1, &timeout);\n\n  host = gethostbyaddr ((char *)&permit.addr, sizeof(permit.addr), AF_INET);\n\n  {\n    const char *hnm = host ? host->h_name : inet_ntoa (permit.addr);\n    size_t hlen = strlen (hnm);\n\n    if (status != RPC_SUCCESS)\n      {\n        const char *err = Rpc_ErrorMessage (status);\n        (void) close (retsock);\n        (void) close (sock);\n        error (NILF, hlen + strlen (err),\n               \"exporting to %s: %s\", hnm, err);\n        return 1;\n      }\n    else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\\0')\n      {\n        (void) close (retsock);\n        (void) close (sock);\n        error (NILF, hlen + strlen (msg), \"exporting to %s: %s\", hnm, msg);\n        return 1;\n      }\n    else\n      {\n        error (NILF, hlen + INTSTR_LENGTH,\n               \"*** exported to %s (id %u)\", hnm, permit.id);\n      }\n\n    fflush (stdout);\n    fflush (stderr);\n  }\n\n  pid = vfork ();\n  if (pid < 0)\n    {\n      /* The fork failed!  */\n      perror_with_name (\"fork\", \"\");\n      return 1;\n    }\n  else if (pid == 0)\n    {\n      /* Child side.  Run 'export' to handle the connection.  */\n      static char sock_buf[INTSTR_LENGTH], retsock_buf[INTSTR_LENGTH];\n      static char id_buf[INTSTR_LENGTH];\n      static char *new_argv[6] =\n        { EXPORT_COMMAND, \"-id\", sock_buf, retsock_buf, id_buf, 0 };\n\n      /* Set up the arguments.  */\n      (void) sprintf (sock_buf, \"%d\", sock);\n      (void) sprintf (retsock_buf, \"%d\", retsock);\n      (void) sprintf (id_buf, \"%x\", permit.id);\n\n      /* Get the right stdin.  */\n      if (stdin_fd != 0)\n        (void) dup2 (stdin_fd, 0);\n\n      /* Unblock signals in the child.  */\n      unblock_all_sigs ();\n\n      /* Run the command.  */\n      exec_command (new_argv, envp);\n    }\n\n  /* Parent side.  Return the 'export' process's ID.  */\n  (void) close (retsock);\n  (void) close (sock);\n  *is_remote = 0;\n  *id_ptr = pid;\n  *used_stdin = 1;\n  return 0;\n}\n\f\n/* Get the status of a dead remote child.  Block waiting for one to die\n   if BLOCK is nonzero.  Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR\n   to the termination signal or zero if it exited normally, and *COREDUMP_PTR\n   nonzero if it dumped core.  Return the ID of the child that died,\n   0 if we would have to block and !BLOCK, or < 0 if there were none.  */\n\nint\nremote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr,\n               int block)\n{\n  return -1;\n}\n\n/* Block asynchronous notification of remote child death.\n   If this notification is done by raising the child termination\n   signal, do not block that signal.  */\nvoid\nblock_remote_children (void)\n{\n  return;\n}\n\n/* Restore asynchronous notification of remote child death.\n   If this is done by raising the child termination signal,\n   do not unblock that signal.  */\nvoid\nunblock_remote_children (void)\n{\n  return;\n}\n\n/* Send signal SIG to child ID.  Return 0 if successful, -1 if not.  */\nint\nremote_kill (pid_t id, int sig)\n{\n  return -1;\n}\n"
  },
  {
    "path": "src/remote-stub.c",
    "content": "/* Template for the remote job exportation interface to GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"job.h\"\n#include \"commands.h\"\n\n\nchar *remote_description = 0;\n\n/* Call once at startup even if no commands are run.  */\n\nvoid\nremote_setup (void)\n{\n}\n\n/* Called before exit.  */\n\nvoid\nremote_cleanup (void)\n{\n}\n\f\n/* Return nonzero if the next job should be done remotely.  */\n\nint\nstart_remote_job_p (int first_p UNUSED)\n{\n  return 0;\n}\n\f\n/* Start a remote job running the command in ARGV,\n   with environment from ENVP.  It gets standard input from STDIN_FD.  On\n   failure, return nonzero.  On success, return zero, and set *USED_STDIN\n   to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to\n   a unique identification, and set *IS_REMOTE to zero if the job is local,\n   nonzero if it is remote (meaning *ID_PTR is a process ID).  */\n\nint\nstart_remote_job (char **argv UNUSED, char **envp UNUSED, int stdin_fd UNUSED,\n                  int *is_remote UNUSED, pid_t *id_ptr UNUSED,\n                  int *used_stdin UNUSED)\n{\n  return -1;\n}\n\f\n/* Get the status of a dead remote child.  Block waiting for one to die\n   if BLOCK is nonzero.  Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR\n   to the termination signal or zero if it exited normally, and *COREDUMP_PTR\n   nonzero if it dumped core.  Return the ID of the child that died,\n   0 if we would have to block and !BLOCK, or < 0 if there were none.  */\n\nint\nremote_status (int *exit_code_ptr UNUSED, int *signal_ptr UNUSED,\n               int *coredump_ptr UNUSED, int block UNUSED)\n{\n  errno = ECHILD;\n  return -1;\n}\n\n/* Block asynchronous notification of remote child death.\n   If this notification is done by raising the child termination\n   signal, do not block that signal.  */\nvoid\nblock_remote_children (void)\n{\n  return;\n}\n\n/* Restore asynchronous notification of remote child death.\n   If this is done by raising the child termination signal,\n   do not unblock that signal.  */\nvoid\nunblock_remote_children (void)\n{\n  return;\n}\n\n/* Send signal SIG to child ID.  Return 0 if successful, -1 if not.  */\nint\nremote_kill (pid_t id UNUSED, int sig UNUSED)\n{\n  return -1;\n}\n"
  },
  {
    "path": "src/rule.c",
    "content": "/* Pattern and suffix rule internals for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#include \"filedef.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"variable.h\"\n#include \"rule.h\"\n\nstatic void freerule (struct rule *rule, struct rule *lastrule);\n\f\n/* Chain of all pattern rules.  */\n\nstruct rule *pattern_rules;\n\n/* Pointer to last rule in the chain, so we can add onto the end.  */\n\nstruct rule *last_pattern_rule;\n\n/* Number of rules in the chain.  */\n\nunsigned int num_pattern_rules;\n\n/* Maximum number of target patterns of any pattern rule.  */\n\nunsigned int max_pattern_targets;\n\n/* Maximum number of dependencies of any pattern rule.  */\n\nunsigned int max_pattern_deps;\n\n/* Maximum length of the name of a dependencies of any pattern rule.  */\n\nsize_t max_pattern_dep_length;\n\n/* Pointer to structure for the file .SUFFIXES\n   whose dependencies are the suffixes to be searched.  */\n\nstruct file *suffix_file;\n\n/* Return the rule definition: space separated rule targets, followed by\n   either a colon or two colons in the case of a terminal rule, followed by\n   space separated rule prerequisites, followed by a pipe, followed by\n   order-only prerequisites, if present.  */\n\nconst char *\nget_rule_defn (struct rule *r)\n{\n  if (r->_defn == NULL)\n    {\n      size_t len = 8; /* Reserve for \":: \", \" | \", and nul.  */\n      unsigned int k;\n      char *p;\n      const char *sep = \"\";\n      const struct dep *dep, *ood = 0;\n\n      for (k = 0; k < r->num; ++k)\n        len += r->lens[k] + 1;\n\n      for (dep = r->deps; dep; dep = dep->next)\n        len += strlen (dep_name (dep)) + (dep->wait_here ? CSTRLEN (\" .WAIT\") : 0) + 1;\n\n      p = r->_defn = xmalloc (len);\n      for (k = 0; k < r->num; ++k, sep = \" \")\n        p = mempcpy (mempcpy (p, sep, strlen (sep)), r->targets[k], r->lens[k]);\n      *p++ = ':';\n      if (r->terminal)\n        *p++ = ':';\n\n      /* Copy all normal dependencies; note any order-only deps.  */\n      for (dep = r->deps; dep; dep = dep->next)\n        if (dep->ignore_mtime == 0)\n          {\n            if (dep->wait_here)\n              p = mempcpy (p, \" .WAIT\", CSTRLEN (\" .WAIT\"));\n            p = mempcpy (mempcpy (p, \" \", 1), dep_name (dep),\n                         strlen (dep_name (dep)));\n          }\n        else if (ood == 0)\n          ood = dep;\n\n      /* Copy order-only deps, if we have any.  */\n      for (sep = \" | \"; ood; ood = ood->next, sep = \" \")\n        if (ood->ignore_mtime)\n          {\n            p = mempcpy (p, sep, strlen (sep));\n            if (ood->wait_here)\n              p = mempcpy (p, \".WAIT \", CSTRLEN (\".WAIT \"));\n            p = mempcpy (p, dep_name (ood), strlen (dep_name (ood)));\n          }\n      *p = '\\0';\n    }\n\n  return r->_defn;\n}\n\n\f\n/* Compute the maximum dependency length and maximum number of dependencies of\n   all implicit rules.  Also sets the subdir flag for a rule when appropriate,\n   possibly removing the rule completely when appropriate.\n\n   Add any global EXTRA_PREREQS here as well.  */\n\nvoid\nsnap_implicit_rules (void)\n{\n  char *name = NULL;\n  size_t namelen = 0;\n  struct rule *rule;\n  struct dep *dep;\n  struct dep *prereqs = expand_extra_prereqs (lookup_variable (STRING_SIZE_TUPLE(\".EXTRA_PREREQS\")));\n  unsigned int pre_deps = 0;\n\n  max_pattern_dep_length = 0;\n\n  for (dep = prereqs; dep; dep = dep->next)\n    {\n      const char *d = dep_name (dep);\n      size_t l = strlen (d);\n\n      if (second_expansion)\n        {\n          if (!dep->name)\n            dep->name = xstrdup (dep->file->name);\n          dep->need_2nd_expansion = 1;\n        }\n      if (dep->need_2nd_expansion)\n        /* When pattern_search allocates a buffer, allow 5 bytes per each % to\n           substitute each % with $(*F) while avoiding realloc.  */\n        while ((d = strchr (d, '%')) != 0)\n          {\n            l += 4;\n            ++d;\n          }\n\n      if (l > max_pattern_dep_length)\n        max_pattern_dep_length = l;\n      ++pre_deps;\n    }\n\n  num_pattern_rules = max_pattern_targets = max_pattern_deps = 0;\n\n  for (rule = pattern_rules; rule; rule = rule->next)\n    {\n      unsigned int ndeps = pre_deps;\n      struct dep *lastdep = NULL;\n\n      ++num_pattern_rules;\n\n      if (rule->num > max_pattern_targets)\n        max_pattern_targets = rule->num;\n\n      for (dep = rule->deps; dep != 0; dep = dep->next)\n        {\n          const char *dname = dep_name (dep);\n          size_t len = strlen (dname);\n\n#if MK_OS_VMS\n          const char *p = strrchr (dname, ']');\n          const char *p2;\n          if (p == 0)\n            p = strrchr (dname, ':');\n          p2 = p ? strchr (p, '%') : 0;\n#else\n          const char *p = strrchr (dname, '/');\n          const char *p2 = p ? strchr (p, '%') : 0;\n#endif\n          ndeps++;\n\n          if (len > max_pattern_dep_length)\n            max_pattern_dep_length = len;\n\n          if (!dep->next)\n            lastdep = dep;\n\n          if (p2)\n            {\n              /* There is a slash before the % in the dep name.\n                 Extract the directory name.  */\n              if (p == dname)\n                ++p;\n              if ((size_t) (p - dname) > namelen)\n                {\n                  namelen = p - dname;\n                  name = xrealloc (name, namelen + 1);\n                }\n              memcpy (name, dname, p - dname);\n              name[p - dname] = '\\0';\n\n              /* In the deps of an implicit rule the 'changed' flag\n                 actually indicates that the dependency is in a\n                 nonexistent subdirectory.  */\n\n              dep->changed = !dir_file_exists_p (name, \"\");\n            }\n          else\n            /* This dependency does not reside in a subdirectory.  */\n            dep->changed = 0;\n        }\n\n      if (prereqs)\n        {\n          if (lastdep)\n            lastdep->next = copy_dep_chain (prereqs);\n          else\n            rule->deps = copy_dep_chain (prereqs);\n        }\n\n      if (ndeps > max_pattern_deps)\n        max_pattern_deps = ndeps;\n    }\n\n  free (name);\n  free_dep_chain (prereqs);\n}\n\f\n/* Create a pattern rule from a suffix rule.\n   TARGET is the target suffix; SOURCE is the source suffix.\n   CMDS are the commands.\n   If TARGET is nil, it means the target pattern should be '(%.o)'.\n   If SOURCE is nil, it means there should be no deps.  */\n\nstatic void\nconvert_suffix_rule (const char *target, const char *source,\n                     struct commands *cmds)\n{\n  const char **names, **percents;\n  struct dep *deps;\n\n  names = xmalloc (sizeof (const char *));\n  percents = xmalloc (sizeof (const char *));\n\n  if (target == 0)\n    {\n      /* Special case: TARGET being nil means we are defining a '.X.a' suffix\n         rule; the target pattern is always '(%.o)'.  */\n#if MK_OS_VMS\n      *names = strcache_add_len (\"(%.obj)\", 7);\n#else\n      *names = strcache_add_len (\"(%.o)\", 5);\n#endif\n      *percents = *names + 1;\n    }\n  else\n    {\n      /* Construct the target name.  */\n      size_t len = strlen (target);\n      char *p = alloca (1 + len + 1);\n      p[0] = '%';\n      memcpy (p + 1, target, len + 1);\n      *names = strcache_add_len (p, len + 1);\n      *percents = *names;\n    }\n\n  if (source == 0)\n    deps = 0;\n  else\n    {\n      /* Construct the dependency name.  */\n      size_t len = strlen (source);\n      char *p = alloca (1 + len + 1);\n      p[0] = '%';\n      memcpy (p + 1, source, len + 1);\n      deps = alloc_dep ();\n      deps->name = strcache_add_len (p, len + 1);\n    }\n\n  create_pattern_rule (names, percents, 1, 0, deps, cmds, 0);\n}\n\n/* Convert old-style suffix rules to pattern rules.\n   All rules for the suffixes on the .SUFFIXES list are converted and added to\n   the chain of pattern rules.  */\n\nvoid\nconvert_to_pattern (void)\n{\n  struct dep *d, *d2;\n  char *rulename;\n\n  /* We will compute every potential suffix rule (.x.y) from the list of\n     suffixes in the .SUFFIXES target's dependencies and see if it exists.\n     First find the longest of the suffixes.  */\n\n  size_t maxsuffix = 0;\n  for (d = suffix_file->deps; d != 0; d = d->next)\n    {\n      size_t l = strlen (dep_name (d));\n      if (l > maxsuffix)\n        maxsuffix = l;\n    }\n\n  /* Space to construct the suffix rule target name.  */\n  rulename = alloca ((maxsuffix * 2) + 1);\n\n  for (d = suffix_file->deps; d != 0; d = d->next)\n    {\n      struct file *f;\n      size_t slen;\n\n      /* Make a rule that is just the suffix, with no deps or commands.\n         This rule exists solely to disqualify match-anything rules.  */\n      convert_suffix_rule (dep_name (d), 0, 0);\n\n      if (d->file->cmds != 0)\n        /* Record a pattern for this suffix's null-suffix rule.  */\n        convert_suffix_rule (\"\", dep_name (d), d->file->cmds);\n\n      slen = strlen (dep_name (d));\n      memcpy (rulename, dep_name (d), slen + 1);\n\n      f = lookup_file (rulename);\n      if (f && f->cmds)\n        {\n          if (!f->deps)\n            f->suffix = 1;\n          else if (!posix_pedantic)\n            {\n              O (error, &f->cmds->fileinfo,\n                 _(\"warning: ignoring prerequisites on suffix rule definition\"));\n              f->suffix = 1;\n            }\n        }\n\n      /* Add every other suffix to this one and see if it exists as a\n         two-suffix rule.  */\n      for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next)\n        {\n          size_t s2len;\n\n          s2len = strlen (dep_name (d2));\n\n          /* Can't build something from itself.  */\n          if (slen == s2len && streq (dep_name (d), dep_name (d2)))\n            continue;\n\n          memcpy (rulename + slen, dep_name (d2), s2len + 1);\n          f = lookup_file (rulename);\n\n          /* No target, or no commands: it can't be a suffix rule.  */\n          if (f == 0 || f->cmds == 0)\n            continue;\n\n          /* POSIX says that suffix rules can't have prerequisites.\n             In POSIX mode, don't make this a suffix rule.  Previous versions\n             of GNU Make did treat this as a suffix rule and ignored the\n             prerequisites, which is bad.  In the future we'll do the same as\n             POSIX, but for now preserve the old behavior and warn about it.  */\n          if (f->deps != 0)\n            {\n              if (posix_pedantic)\n                continue;\n              O (error, &f->cmds->fileinfo,\n                 _(\"warning: ignoring prerequisites on suffix rule definition\"));\n            }\n\n          f->suffix = 1;\n\n          if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a')\n            /* A suffix rule '.X.a:' generates the pattern rule '(%.o): %.X'.\n               It also generates a normal '%.a: %.X' rule below.  */\n            convert_suffix_rule (NULL, /* Indicates '(%.o)'.  */\n                                 dep_name (d),\n                                 f->cmds);\n\n          /* The suffix rule '.X.Y:' is converted\n             to the pattern rule '%.Y: %.X'.  */\n          convert_suffix_rule (dep_name (d2), dep_name (d), f->cmds);\n        }\n    }\n}\n\n\n/* Install the pattern rule RULE (whose fields have been filled in) at the end\n   of the list (so that any rules previously defined will take precedence).\n   If this rule duplicates a previous one (identical target and dependencies),\n   the old one is replaced if OVERRIDE is nonzero, otherwise this new one is\n   thrown out.  When an old rule is replaced, the new one is put at the end of\n   the list.  Return nonzero if RULE is used; zero if not.  */\n\nstatic int\nnew_pattern_rule (struct rule *rule, int override)\n{\n  struct rule *r, *lastrule;\n  unsigned int i, j;\n\n  rule->in_use = 0;\n  rule->terminal = 0;\n\n  rule->next = 0;\n\n  /* Search for an identical rule.  */\n  lastrule = 0;\n  for (r = pattern_rules; r != 0; lastrule = r, r = r->next)\n    for (i = 0; i < rule->num; ++i)\n      {\n        for (j = 0; j < r->num; ++j)\n          if (!streq (rule->targets[i], r->targets[j]))\n            break;\n        /* If all the targets matched...  */\n        if (j == r->num)\n          {\n            struct dep *d, *d2;\n            for (d = rule->deps, d2 = r->deps;\n                 d != 0 && d2 != 0; d = d->next, d2 = d2->next)\n              if (!streq (dep_name (d), dep_name (d2)))\n                break;\n            if (d == 0 && d2 == 0)\n              {\n                /* All the dependencies matched.  */\n                if (override)\n                  {\n                    /* Remove the old rule.  */\n                    freerule (r, lastrule);\n                    /* Install the new one.  */\n                    if (pattern_rules == 0)\n                      pattern_rules = rule;\n                    else\n                      last_pattern_rule->next = rule;\n                    last_pattern_rule = rule;\n\n                    /* We got one.  Stop looking.  */\n                    goto matched;\n                  }\n                else\n                  {\n                    /* The old rule stays intact.  Destroy the new one.  */\n                    freerule (rule, (struct rule *) 0);\n                    return 0;\n                  }\n              }\n          }\n      }\n\n matched:;\n\n  if (r == 0)\n    {\n      /* There was no rule to replace.  */\n      if (pattern_rules == 0)\n        pattern_rules = rule;\n      else\n        last_pattern_rule->next = rule;\n      last_pattern_rule = rule;\n    }\n\n  return 1;\n}\n\n\n/* Install an implicit pattern rule based on the three text strings\n   in the structure P points to.  These strings come from one of\n   the arrays of default implicit pattern rules.\n   TERMINAL specifies what the 'terminal' field of the rule should be.  */\n\nvoid\ninstall_pattern_rule (struct pspec *p, int terminal)\n{\n  struct rule *r;\n  const char *ptr;\n\n  r = xmalloc (sizeof (struct rule));\n\n  r->num = 1;\n  r->targets = xmalloc (sizeof (const char *));\n  r->suffixes = xmalloc (sizeof (const char *));\n  r->lens = xmalloc (sizeof (unsigned int));\n  r->_defn = NULL;\n\n  r->lens[0] = (unsigned int) strlen (p->target);\n  r->targets[0] = p->target;\n  r->suffixes[0] = find_percent_cached (&r->targets[0]);\n  assert (r->suffixes[0] != NULL);\n  ++r->suffixes[0];\n\n  ptr = p->dep;\n  r->deps = PARSE_SIMPLE_SEQ ((char **)&ptr, struct dep);\n\n  if (new_pattern_rule (r, 0))\n    {\n      r->terminal = terminal ? 1 : 0;\n      r->cmds = xmalloc (sizeof (struct commands));\n      r->cmds->fileinfo.filenm = 0;\n      r->cmds->fileinfo.lineno = 0;\n      r->cmds->fileinfo.offset = 0;\n      /* These will all be string literals, but we malloc space for them\n         anyway because somebody might want to free them later.  */\n      r->cmds->commands = xstrdup (p->commands);\n      r->cmds->command_lines = 0;\n      r->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;\n    }\n}\n\n\n/* Free all the storage used in RULE and take it out of the\n   pattern_rules chain.  LASTRULE is the rule whose next pointer\n   points to RULE.  */\n\nstatic void\nfreerule (struct rule *rule, struct rule *lastrule)\n{\n  struct rule *next = rule->next;\n\n  free_dep_chain (rule->deps);\n\n  /* MSVC erroneously warns without a cast here.  */\n  free ((void *)rule->targets);\n  free ((void *)rule->suffixes);\n  free (rule->lens);\n  free ((void *) rule->_defn);\n\n  /* We can't free the storage for the commands because there\n     are ways that they could be in more than one place:\n       * If the commands came from a suffix rule, they could also be in\n       the 'struct file's for other suffix rules or plain targets given\n       on the same makefile line.\n       * If two suffixes that together make a two-suffix rule were each\n       given twice in the .SUFFIXES list, and in the proper order, two\n       identical pattern rules would be created and the second one would\n       be discarded here, but both would contain the same 'struct commands'\n       pointer from the 'struct file' for the suffix rule.  */\n\n  free (rule);\n\n  if (pattern_rules == rule)\n    if (lastrule != 0)\n      abort ();\n    else\n      pattern_rules = next;\n  else if (lastrule != 0)\n    lastrule->next = next;\n  if (last_pattern_rule == rule)\n    last_pattern_rule = lastrule;\n}\n\f\n/* Create a new pattern rule with the targets in the nil-terminated array\n   TARGETS.  TARGET_PERCENTS is an array of pointers to the % in each element\n   of TARGETS.  N is the number of items in the array (not counting the nil\n   element).  The new rule has dependencies DEPS and commands from COMMANDS.\n   It is a terminal rule if TERMINAL is nonzero.  This rule overrides\n   identical rules with different commands if OVERRIDE is nonzero.\n\n   The storage for TARGETS and its elements and TARGET_PERCENTS is used and\n   must not be freed until the rule is destroyed.  */\n\nvoid\ncreate_pattern_rule (const char **targets, const char **target_percents,\n                     unsigned short n, int terminal, struct dep *deps,\n                     struct commands *commands, int override)\n{\n  unsigned int i;\n  struct rule *r = xmalloc (sizeof (struct rule));\n\n  r->num = n;\n  r->cmds = commands;\n  r->deps = deps;\n  r->targets = targets;\n  r->suffixes = target_percents;\n  r->lens = xmalloc (n * sizeof (unsigned int));\n  r->_defn = NULL;\n\n  for (i = 0; i < n; ++i)\n    {\n      r->lens[i] = (unsigned int) strlen (targets[i]);\n      assert (r->suffixes[i] != NULL);\n      ++r->suffixes[i];\n    }\n\n  if (new_pattern_rule (r, override))\n    r->terminal = terminal ? 1 : 0;\n}\n\f\n/* Print the data base of rules.  */\n\nstatic void                     /* Useful to call from gdb.  */\nprint_rule (struct rule *r)\n{\n  fputs (get_rule_defn (r), stdout);\n  putchar ('\\n');\n\n  if (r->cmds != 0)\n    print_commands (r->cmds);\n}\n\nvoid\nprint_rule_data_base (void)\n{\n  unsigned int rules, terminal;\n  struct rule *r;\n\n  puts (_(\"\\n# Implicit Rules\"));\n\n  rules = terminal = 0;\n  for (r = pattern_rules; r != 0; r = r->next)\n    {\n      ++rules;\n\n      putchar ('\\n');\n      print_rule (r);\n\n      if (r->terminal)\n        ++terminal;\n    }\n\n  if (rules == 0)\n    puts (_(\"\\n# No implicit rules.\"));\n  else\n    {\n      printf (_(\"\\n# %u implicit rules, %u (%.1f%%) terminal.\"),\n              rules, terminal, (double) terminal / (double) rules * 100.0);\n    }\n\n  if (num_pattern_rules != rules)\n    {\n      /* This can happen if a fatal error was detected while reading the\n         makefiles and thus count_implicit_rule_limits wasn't called yet.  */\n      if (num_pattern_rules != 0)\n        ONN (fatal, NILF, \"INTERNAL: num_pattern_rules is wrong!  %u != %u\",\n             num_pattern_rules, rules);\n    }\n}\n"
  },
  {
    "path": "src/rule.h",
    "content": "/* Definitions for using pattern rules in GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Structure used for pattern (implicit) rules.  */\n\nstruct rule\n  {\n    struct rule *next;\n    const char **targets;       /* Targets of the rule.  */\n    unsigned int *lens;         /* Lengths of each target.  */\n    const char **suffixes;      /* Suffixes (after '%') of each target.  */\n    struct dep *deps;           /* Dependencies of the rule.  */\n    struct commands *cmds;      /* Commands to execute.  */\n    char *_defn;                /* Definition of the rule. */\n    unsigned short num;         /* Number of targets.  */\n    char terminal;              /* If terminal (double-colon).  */\n    char in_use;                /* If in use by a parent pattern_search.  */\n  };\n\n/* For calling install_pattern_rule.  */\nstruct pspec\n  {\n    const char *target, *dep, *commands;\n  };\n\n\nextern struct rule *pattern_rules;\nextern struct rule *last_pattern_rule;\nextern unsigned int num_pattern_rules;\n\nextern unsigned int max_pattern_deps;\nextern unsigned int max_pattern_targets;\nextern size_t max_pattern_dep_length;\n\nextern struct file *suffix_file;\n\n\nvoid snap_implicit_rules (void);\nvoid convert_to_pattern (void);\nvoid install_pattern_rule (struct pspec *p, int terminal);\nvoid create_pattern_rule (const char **targets, const char **target_percents,\n                          unsigned short num, int terminal, struct dep *deps,\n                          struct commands *commands, int override);\nconst char *get_rule_defn (struct rule *rule);\nvoid print_rule_data_base (void);\n"
  },
  {
    "path": "src/shuffle.c",
    "content": "/* Provide prerequisite shuffle support.\nCopyright (C) 2022-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include \"shuffle.h\"\n\n#include \"filedef.h\"\n#include \"dep.h\"\n\n/* Supported shuffle modes.  */\nstatic void random_shuffle_array (void ** a, size_t len);\nstatic void reverse_shuffle_array (void ** a, size_t len);\nstatic void identity_shuffle_array (void ** a, size_t len);\n\n/* The way goals and rules are shuffled during update.  */\nenum shuffle_mode\n  {\n    /* No shuffle data is populated or used.  */\n    sm_none,\n    /* Random within dependency list.  */\n    sm_random,\n    /* Inverse order.  */\n    sm_reverse,\n    /* identity order. Differs from SM_NONE by explicitly populating\n       the traversal order.  */\n    sm_identity,\n  };\n\n/* Shuffle configuration.  */\nstatic struct\n  {\n    enum shuffle_mode mode;\n    unsigned int seed;\n    void (*shuffler) (void **a, size_t len);\n    char strval[INTSTR_LENGTH + 1];\n  } config = { sm_none, 0, NULL, \"\" };\n\n/* Return string value of --shuffle= option passed.\n   If none was passed or --shuffle=none was used function\n   returns NULL.  */\nconst char *\nshuffle_get_mode ()\n{\n  return config.strval[0] == '\\0' ? NULL : config.strval;\n}\n\nvoid\nshuffle_set_mode (const char *cmdarg)\n{\n  /* Parse supported '--shuffle' mode.  */\n  if (strcasecmp (cmdarg, \"reverse\") == 0)\n    {\n      config.mode = sm_reverse;\n      config.shuffler = reverse_shuffle_array;\n      strcpy (config.strval, \"reverse\");\n    }\n  else if (strcasecmp (cmdarg, \"identity\") == 0)\n    {\n      config.mode = sm_identity;\n      config.shuffler = identity_shuffle_array;\n      strcpy (config.strval, \"identity\");\n    }\n  else if (strcasecmp (cmdarg, \"none\") == 0)\n    {\n      config.mode = sm_none;\n      config.shuffler = NULL;\n      config.strval[0] = '\\0';\n    }\n  else\n    {\n      if (strcasecmp (cmdarg, \"random\") == 0)\n        config.seed = make_rand ();\n      else\n        {\n          /* Assume explicit seed.  */\n          const char *err;\n          config.seed = make_toui (cmdarg, &err);\n          if (err)\n            OSS (fatal, NILF, _(\"invalid shuffle mode: %s: '%s'\"), err, cmdarg);\n        }\n\n      config.mode = sm_random;\n      config.shuffler = random_shuffle_array;\n      sprintf (config.strval, \"%u\", config.seed);\n    }\n}\n\n/* Shuffle array elements using RAND().  */\nstatic void\nrandom_shuffle_array (void **a, size_t len)\n{\n  size_t i;\n  for (i = 0; i < len; i++)\n    {\n      void *t;\n\n      /* Pick random element and swap. */\n      unsigned int j = make_rand () % len;\n      if (i == j)\n        continue;\n\n      /* Swap. */\n      t = a[i];\n      a[i] = a[j];\n      a[j] = t;\n    }\n}\n\n/* Shuffle array elements using reverse order.  */\nstatic void\nreverse_shuffle_array (void **a, size_t len)\n{\n  size_t i;\n  for (i = 0; i < len / 2; i++)\n    {\n      void *t;\n\n      /* Pick mirror and swap. */\n      size_t j = len - 1 - i;\n\n      /* Swap. */\n      t = a[i];\n      a[i] = a[j];\n      a[j] = t;\n    }\n}\n\n/* Shuffle array elements using identity order.  */\nstatic void\nidentity_shuffle_array (void **a UNUSED, size_t len UNUSED)\n{\n  /* No-op!  */\n}\n\n/* Shuffle list of dependencies by populating '->shuf'\n   field in each 'struct dep'.  */\nstatic void\nshuffle_deps (struct dep *deps)\n{\n  size_t ndeps = 0;\n  struct dep *dep;\n  void **da;\n  void **dp;\n\n  for (dep = deps; dep; dep = dep->next)\n    {\n      /* Do not reshuffle prerequisites if any .WAIT is present.  */\n      if (dep->wait_here)\n        return;\n\n      ndeps++;\n    }\n\n  if (ndeps == 0)\n    return;\n\n  /* Allocate array of all deps, store, shuffle, write back.  */\n  da = xmalloc (sizeof (struct dep *) * ndeps);\n\n  /* Store locally.  */\n  for (dep = deps, dp = da; dep; dep = dep->next, dp++)\n    *dp = dep;\n\n  /* Shuffle.  */\n  config.shuffler (da, ndeps);\n\n  /* Write back.  */\n  for (dep = deps, dp = da; dep; dep = dep->next, dp++)\n    dep->shuf = *dp;\n\n  free (da);\n}\n\n/* Shuffle 'deps' of each 'file' recursively.  */\nstatic void\nshuffle_file_deps_recursive (struct file *f)\n{\n  struct dep *dep;\n\n  /* Implicit rules do not always provide any depends.  */\n  if (!f)\n    return;\n\n  /* Avoid repeated shuffles and loops.  */\n  if (f->was_shuffled)\n    return;\n  f->was_shuffled = 1;\n\n  shuffle_deps (f->deps);\n\n  /* Shuffle dependencies. */\n  for (dep = f->deps; dep; dep = dep->next)\n    shuffle_file_deps_recursive (dep->file);\n}\n\n/* Shuffle goal dependencies first, then shuffle dependency list\n   of each file reachable from goaldep recursively.  Used by\n   --shuffle flag to introduce artificial non-determinism in build\n   order.  .*/\n\nvoid\nshuffle_deps_recursive (struct dep *deps)\n{\n  struct dep *dep;\n\n  /* Exit early if shuffling was not requested.  */\n  if (config.mode == sm_none)\n    return;\n\n  /* Do not reshuffle prerequisites if .NOTPARALLEL was specified.  */\n  if (not_parallel)\n    return;\n\n  /* Set specific seed at the top level of recursion.  */\n  if (config.mode == sm_random)\n    make_seed (config.seed);\n\n  shuffle_deps (deps);\n\n  /* Shuffle dependencies. */\n  for (dep = deps; dep; dep = dep->next)\n    shuffle_file_deps_recursive (dep->file);\n}\n"
  },
  {
    "path": "src/shuffle.h",
    "content": "/* Declarations for target shuffling support.\nCopyright (C) 2022, 2024-2022 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\nstruct dep;\nstruct goaldep;\n\nvoid shuffle_set_mode (const char *cmdarg);\nconst char *shuffle_get_mode (void);\nvoid shuffle_deps_recursive (struct dep* g);\n\n#define shuffle_goaldeps_recursive(_g) do{              \\\n        shuffle_deps_recursive ((struct dep *)_g);      \\\n    } while(0)\n"
  },
  {
    "path": "src/signame.c",
    "content": "/* Convert between signal names and numbers.\nCopyright (C) 1990-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n/* If the system provides strsignal, we don't need it. */\n\n#if !HAVE_STRSIGNAL\n\n/* If the system provides sys_siglist, we'll use that.\n   Otherwise create our own.\n */\n\n#if !HAVE_DECL_SYS_SIGLIST\n\n/* Some systems do not define NSIG in <signal.h>.  */\n#ifndef NSIG\n#ifdef  _NSIG\n#define NSIG    _NSIG\n#else\n#define NSIG    32\n#endif\n#endif\n\n/* There is too much variation in Sys V signal numbers and names, so\n   we must initialize them at runtime.  */\n\nstatic const char *undoc;\n\nstatic const char *sys_siglist[NSIG];\n\n/* Table of abbreviations for signals.  Note:  A given number can\n   appear more than once with different abbreviations.  */\n#define SIG_TABLE_SIZE  (NSIG*2)\n\ntypedef struct\n  {\n    int number;\n    const char *abbrev;\n  } num_abbrev;\n\nstatic num_abbrev sig_table[SIG_TABLE_SIZE];\n\n/* Number of elements of sig_table used.  */\nstatic int sig_table_nelts = 0;\n\n/* Enter signal number NUMBER into the tables with ABBREV and NAME.  */\n\nstatic void\ninit_sig (int number, const char *abbrev, const char *name)\n{\n  /* If this value is ever greater than NSIG it seems like it'd be a bug in\n     the system headers, but... better safe than sorry.  We know, for\n     example, that this isn't always true on VMS.  */\n\n  if (number >= 0 && number < NSIG)\n    sys_siglist[number] = name;\n\n  if (sig_table_nelts < SIG_TABLE_SIZE)\n    {\n      sig_table[sig_table_nelts].number = number;\n      sig_table[sig_table_nelts++].abbrev = abbrev;\n    }\n}\n\nstatic int\nsigname_init (void)\n{\n  int i;\n\n  undoc = xstrdup (_(\"unknown signal\"));\n\n  /* Initialize signal names.  */\n  for (i = 0; i < NSIG; i++)\n    sys_siglist[i] = undoc;\n\n  /* Initialize signal names.  */\n#if defined (SIGHUP)\n  init_sig (SIGHUP, \"HUP\", _(\"Hangup\"));\n#endif\n#if defined (SIGINT)\n  init_sig (SIGINT, \"INT\", _(\"Interrupt\"));\n#endif\n#if defined (SIGQUIT)\n  init_sig (SIGQUIT, \"QUIT\", _(\"Quit\"));\n#endif\n#if defined (SIGILL)\n  init_sig (SIGILL, \"ILL\", _(\"Illegal Instruction\"));\n#endif\n#if defined (SIGTRAP)\n  init_sig (SIGTRAP, \"TRAP\", _(\"Trace/breakpoint trap\"));\n#endif\n  /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because\n     SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't.  */\n#if defined (SIGABRT)\n  init_sig (SIGABRT, \"ABRT\", _(\"Aborted\"));\n#endif\n#if defined (SIGIOT)\n  init_sig (SIGIOT, \"IOT\", _(\"IOT trap\"));\n#endif\n#if defined (SIGEMT)\n  init_sig (SIGEMT, \"EMT\", _(\"EMT trap\"));\n#endif\n#if defined (SIGFPE)\n  init_sig (SIGFPE, \"FPE\", _(\"Floating point exception\"));\n#endif\n#if defined (SIGKILL)\n  init_sig (SIGKILL, \"KILL\", _(\"Killed\"));\n#endif\n#if defined (SIGBUS)\n  init_sig (SIGBUS, \"BUS\", _(\"Bus error\"));\n#endif\n#if defined (SIGSEGV)\n  init_sig (SIGSEGV, \"SEGV\", _(\"Segmentation fault\"));\n#endif\n#if defined (SIGSYS)\n  init_sig (SIGSYS, \"SYS\", _(\"Bad system call\"));\n#endif\n#if defined (SIGPIPE)\n  init_sig (SIGPIPE, \"PIPE\", _(\"Broken pipe\"));\n#endif\n#if defined (SIGALRM)\n  init_sig (SIGALRM, \"ALRM\", _(\"Alarm clock\"));\n#endif\n#if defined (SIGTERM)\n  init_sig (SIGTERM, \"TERM\", _(\"Terminated\"));\n#endif\n#if defined (SIGUSR1)\n  init_sig (SIGUSR1, \"USR1\", _(\"User defined signal 1\"));\n#endif\n#if defined (SIGUSR2)\n  init_sig (SIGUSR2, \"USR2\", _(\"User defined signal 2\"));\n#endif\n  /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that\n     is what is in POSIX.1.  */\n#if defined (SIGCHLD)\n  init_sig (SIGCHLD, \"CHLD\", _(\"Child exited\"));\n#endif\n#if defined (SIGCLD)\n  init_sig (SIGCLD, \"CLD\", _(\"Child exited\"));\n#endif\n#if defined (SIGPWR)\n  init_sig (SIGPWR, \"PWR\", _(\"Power failure\"));\n#endif\n#if defined (SIGTSTP)\n  init_sig (SIGTSTP, \"TSTP\", _(\"Stopped\"));\n#endif\n#if defined (SIGTTIN)\n  init_sig (SIGTTIN, \"TTIN\", _(\"Stopped (tty input)\"));\n#endif\n#if defined (SIGTTOU)\n  init_sig (SIGTTOU, \"TTOU\", _(\"Stopped (tty output)\"));\n#endif\n#if defined (SIGSTOP)\n  init_sig (SIGSTOP, \"STOP\", _(\"Stopped (signal)\"));\n#endif\n#if defined (SIGXCPU)\n  init_sig (SIGXCPU, \"XCPU\", _(\"CPU time limit exceeded\"));\n#endif\n#if defined (SIGXFSZ)\n  init_sig (SIGXFSZ, \"XFSZ\", _(\"File size limit exceeded\"));\n#endif\n#if defined (SIGVTALRM)\n  init_sig (SIGVTALRM, \"VTALRM\", _(\"Virtual timer expired\"));\n#endif\n#if defined (SIGPROF)\n  init_sig (SIGPROF, \"PROF\", _(\"Profiling timer expired\"));\n#endif\n#if defined (SIGWINCH)\n  /* \"Window size changed\" might be more accurate, but even if that\n     is all that it means now, perhaps in the future it will be\n     extended to cover other kinds of window changes.  */\n  init_sig (SIGWINCH, \"WINCH\", _(\"Window changed\"));\n#endif\n#if defined (SIGCONT)\n  init_sig (SIGCONT, \"CONT\", _(\"Continued\"));\n#endif\n#if defined (SIGURG)\n  init_sig (SIGURG, \"URG\", _(\"Urgent I/O condition\"));\n#endif\n#if defined (SIGIO)\n  /* \"I/O pending\" has also been suggested.  A disadvantage is that signal\n     only happens when the process has asked for it, not every time I/O is\n     pending.  Another disadvantage is the confusion from giving it a\n     different name than under Unix.  */\n  init_sig (SIGIO, \"IO\", _(\"I/O possible\"));\n#endif\n#if defined (SIGWIND)\n  init_sig (SIGWIND, \"WIND\", _(\"SIGWIND\"));\n#endif\n#if defined (SIGPHONE)\n  init_sig (SIGPHONE, \"PHONE\", _(\"SIGPHONE\"));\n#endif\n#if defined (SIGPOLL)\n  init_sig (SIGPOLL, \"POLL\", _(\"I/O possible\"));\n#endif\n#if defined (SIGLOST)\n  init_sig (SIGLOST, \"LOST\", _(\"Resource lost\"));\n#endif\n#if defined (SIGDANGER)\n  init_sig (SIGDANGER, \"DANGER\", _(\"Danger signal\"));\n#endif\n#if defined (SIGINFO)\n  init_sig (SIGINFO, \"INFO\", _(\"Information request\"));\n#endif\n#if defined (SIGNOFP)\n  init_sig (SIGNOFP, \"NOFP\", _(\"Floating point co-processor not available\"));\n#endif\n\n  return 1;\n}\n\n#endif  /* HAVE_DECL_SYS_SIGLIST */\n\n\nchar *\nstrsignal (int sig)\n{\n  static char buf[] = \"Signal 12345678901234567890\";\n\n#if ! HAVE_DECL_SYS_SIGLIST\n# if HAVE_DECL__SYS_SIGLIST\n#  define sys_siglist _sys_siglist\n# elif HAVE_DECL___SYS_SIGLIST\n#  define sys_siglist __sys_siglist\n# else\n  static int sig_initted = 0;\n\n  if (!sig_initted)\n    sig_initted = signame_init ();\n# endif\n#endif\n\n  if (sig > 0 && sig < NSIG)\n    return (char *) sys_siglist[sig];\n\n  sprintf (buf, \"Signal %d\", sig);\n  return buf;\n}\n\n#endif  /* HAVE_STRSIGNAL */\n"
  },
  {
    "path": "src/strcache.c",
    "content": "/* Constant string caching for GNU Make.\nCopyright (C) 2006-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <stddef.h>\n#include <assert.h>\n\n#include \"hash.h\"\n\n/* A string cached here will never be freed, so we don't need to worry about\n   reference counting.  We just store the string, and then remember it in a\n   hash so it can be looked up again. */\n\ntypedef unsigned short int sc_buflen_t;\n\nstruct strcache {\n  struct strcache *next;    /* The next block of strings.  Must be first!  */\n  sc_buflen_t end;          /* Offset to the beginning of free space.  */\n  sc_buflen_t bytesfree;    /* Free space left in this buffer.  */\n  sc_buflen_t count;        /* # of strings in this buffer (for stats).  */\n  char buffer[1];           /* The buffer comes after this.  */\n};\n\n/* The size (in bytes) of each cache buffer.\n   Try to pick something that will map well into the heap.\n   This must be able to be represented by a short int (<=65535).  */\n#define CACHE_BUFFER_BASE       (8192)\n#define CACHE_BUFFER_ALLOC(_s)  ((_s) - (2 * sizeof (size_t)))\n#define CACHE_BUFFER_OFFSET     (offsetof (struct strcache, buffer))\n#define CACHE_BUFFER_SIZE(_s)   (CACHE_BUFFER_ALLOC(_s) - CACHE_BUFFER_OFFSET)\n#define BUFSIZE                 CACHE_BUFFER_SIZE (CACHE_BUFFER_BASE)\n\nstatic struct strcache *strcache = NULL;\nstatic struct strcache *fullcache = NULL;\n\nstatic unsigned long total_buffers = 0;\nstatic unsigned long total_strings = 0;\nstatic unsigned long total_size = 0;\n\n/* Add a new buffer to the cache.  Add it at the front to reduce search time.\n   This can also increase the overhead, since it's less likely that older\n   buffers will be filled in.  However, GNU Make has so many smaller strings\n   that this doesn't seem to be much of an issue in practice.\n */\nstatic struct strcache *\nnew_cache (struct strcache **head, sc_buflen_t buflen)\n{\n  struct strcache *new = xmalloc (buflen + CACHE_BUFFER_OFFSET);\n  new->end = 0;\n  new->count = 0;\n  new->bytesfree = buflen;\n\n  new->next = *head;\n  *head = new;\n\n  ++total_buffers;\n  return new;\n}\n\nstatic const char *\ncopy_string (struct strcache *sp, const char *str, sc_buflen_t len)\n{\n  /* Add the string to this cache.  */\n  char *res = &sp->buffer[sp->end];\n\n  memmove (res, str, len);\n  res[len++] = '\\0';\n  sp->end += len;\n  sp->bytesfree -= len;\n  ++sp->count;\n\n  return res;\n}\n\nstatic const char *\nadd_string (const char *str, sc_buflen_t len)\n{\n  const char *res;\n  struct strcache *sp;\n  struct strcache **spp = &strcache;\n  /* We need space for the nul char.  */\n  sc_buflen_t sz = len + 1;\n\n  ++total_strings;\n  total_size += sz;\n\n  /* If the string we want is too large to fit into a single buffer, then\n     no existing cache is large enough.  Add it directly to the fullcache.  */\n  if (sz > BUFSIZE)\n    {\n      sp = new_cache (&fullcache, sz);\n      return copy_string (sp, str, len);\n    }\n\n  /* Find the first cache with enough free space.  */\n  for (; *spp != NULL; spp = &(*spp)->next)\n    if ((*spp)->bytesfree > sz)\n      break;\n  sp = *spp;\n\n  /* If nothing is big enough, make a new cache at the front.  */\n  if (sp == NULL)\n    {\n      sp = new_cache (&strcache, BUFSIZE);\n      spp = &strcache;\n    }\n\n  /* Add the string to this cache.  */\n  res = copy_string (sp, str, len);\n\n  /* If the amount free in this cache is less than the average string size,\n     consider it full and move it to the full list.  */\n  if (total_strings > 20 && sp->bytesfree < (total_size / total_strings) + 1)\n    {\n      *spp = sp->next;\n      sp->next = fullcache;\n      fullcache = sp;\n    }\n\n  return res;\n}\n\n/* For strings too large for the strcache, we just save them in a list.  */\nstruct hugestring {\n  struct hugestring *next;  /* The next string.  */\n  char buffer[1];           /* The string.  */\n};\n\nstatic struct hugestring *hugestrings = NULL;\n\nstatic const char *\nadd_hugestring (const char *str, size_t len)\n{\n  struct hugestring *new = xmalloc (sizeof (struct hugestring) + len);\n  memcpy (new->buffer, str, len);\n  new->buffer[len] = '\\0';\n\n  new->next = hugestrings;\n  hugestrings = new;\n\n  return new->buffer;\n}\n\n/* Hash table of strings in the cache.  */\n\nstatic unsigned long\nstr_hash_1 (const void *key)\n{\n  return_ISTRING_HASH_1 ((const char *) key);\n}\n\nstatic unsigned long\nstr_hash_2 (const void *key)\n{\n  return_ISTRING_HASH_2 ((const char *) key);\n}\n\nstatic int\nstr_hash_cmp (const void *x, const void *y)\n{\n  return_ISTRING_COMPARE ((const char *) x, (const char *) y);\n}\n\nstatic struct hash_table strings;\nstatic unsigned long total_adds = 0;\n\nstatic const char *\nadd_hash (const char *str, size_t len)\n{\n  char *const *slot;\n  const char *key;\n\n  /* If it's too large for the string cache, just copy it.\n     We don't bother trying to match these.  */\n  if (len > USHRT_MAX - 1)\n    return add_hugestring (str, len);\n\n  /* Look up the string in the hash.  If it's there, return it.  */\n  slot = (char *const *) hash_find_slot (&strings, str);\n  key = *slot;\n\n  /* Count the total number of add operations we performed.  */\n  ++total_adds;\n\n  if (!HASH_VACANT (key))\n    return key;\n\n  /* Not there yet so add it to a buffer, then into the hash table.  */\n  key = add_string (str, (sc_buflen_t)len);\n  hash_insert_at (&strings, key, slot);\n  return key;\n}\n\n/* Returns true if the string is in the cache; false if not.  */\nint\nstrcache_iscached (const char *str)\n{\n  struct strcache *sp;\n\n  for (sp = strcache; sp != 0; sp = sp->next)\n    if (str >= sp->buffer && str < sp->buffer + sp->end)\n      return 1;\n  for (sp = fullcache; sp != 0; sp = sp->next)\n    if (str >= sp->buffer && str < sp->buffer + sp->end)\n      return 1;\n\n  {\n    struct hugestring *hp;\n    for (hp = hugestrings; hp != 0; hp = hp->next)\n      if (str == hp->buffer)\n        return 1;\n  }\n\n  return 0;\n}\n\n/* If the string is already in the cache, return a pointer to the cached\n   version.  If not, add it then return a pointer to the cached version.\n   Note we do NOT take control of the string passed in.  */\nconst char *\nstrcache_add (const char *str)\n{\n  return add_hash (str, strlen (str));\n}\n\nconst char *\nstrcache_add_len (const char *str, size_t len)\n{\n  /* If we're not given a nul-terminated string we have to create one, because\n     the hashing functions expect it.  */\n  if (str[len] != '\\0')\n    {\n      char *key = alloca (len + 1);\n      memcpy (key, str, len);\n      key[len] = '\\0';\n      str = key;\n    }\n\n  return add_hash (str, len);\n}\n\nvoid\nstrcache_init (void)\n{\n  hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp);\n}\n\n\n/* Generate some stats output.  */\n\nvoid\nstrcache_print_stats (const char *prefix)\n{\n  const struct strcache *sp;\n  unsigned long numbuffs = 0, fullbuffs = 0;\n  unsigned long totfree = 0, maxfree = 0, minfree = BUFSIZE;\n\n  if (! strcache)\n    {\n      printf (_(\"\\n%s No strcache buffers\\n\"), prefix);\n      return;\n    }\n\n  /* Count the first buffer separately since it's not full.  */\n  for (sp = strcache->next; sp != NULL; sp = sp->next)\n    {\n      sc_buflen_t bf = sp->bytesfree;\n\n      totfree += bf;\n      maxfree = (bf > maxfree ? bf : maxfree);\n      minfree = (bf < minfree ? bf : minfree);\n\n      ++numbuffs;\n    }\n  for (sp = fullcache; sp != NULL; sp = sp->next)\n    {\n      sc_buflen_t bf = sp->bytesfree;\n\n      totfree += bf;\n      maxfree = (bf > maxfree ? bf : maxfree);\n      minfree = (bf < minfree ? bf : minfree);\n\n      ++numbuffs;\n      ++fullbuffs;\n    }\n\n  /* Make sure we didn't lose any buffers.  */\n  assert (total_buffers == numbuffs + 1);\n\n  printf (_(\"\\n%s strcache buffers: %lu (%lu) / strings = %lu / storage = %lu B / avg = %lu B\\n\"),\n          prefix, numbuffs + 1, fullbuffs, total_strings, total_size,\n          (total_size / total_strings));\n\n  printf (_(\"%s current buf: size = %hu B / used = %hu B / count = %hu / avg = %u B\\n\"),\n          prefix, (sc_buflen_t)BUFSIZE, strcache->end, strcache->count,\n          (unsigned int) (strcache->end / strcache->count));\n\n  if (numbuffs)\n    {\n      /* Show information about non-current buffers.  */\n      unsigned long sz = total_size - strcache->end;\n      unsigned long cnt = total_strings - strcache->count;\n      sc_buflen_t avgfree = (sc_buflen_t) (totfree / numbuffs);\n\n      printf (_(\"%s other used: total = %lu B / count = %lu / avg = %lu B\\n\"),\n              prefix, sz, cnt, sz / cnt);\n\n      printf (_(\"%s other free: total = %lu B / max = %lu B / min = %lu B / avg = %hu B\\n\"),\n              prefix, totfree, maxfree, minfree, avgfree);\n    }\n\n  printf (_(\"\\n%s strcache performance: lookups = %lu / hit rate = %lu%%\\n\"),\n          prefix, total_adds, (long unsigned)(100.0 * (total_adds - total_strings) / total_adds));\n  fputs (_(\"# hash-table stats:\\n# \"), stdout);\n  hash_print_stats (&strings, stdout);\n}\n"
  },
  {
    "path": "src/variable.c",
    "content": "/* Internals of variables for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n\n#include \"filedef.h\"\n#include \"debug.h\"\n#include \"dep.h\"\n#include \"job.h\"\n#include \"commands.h\"\n#include \"variable.h\"\n#include \"os.h\"\n#include \"rule.h\"\n#if MK_OS_W32\n#include \"pathstuff.h\"\n#endif\n#include \"hash.h\"\n#include \"warning.h\"\n\n/* Incremented every time we enter target_environment().  */\nunsigned long long env_recursion = 0;\n\n/* Incremented every time we add or remove a global variable.  */\nstatic unsigned long variable_changenum = 0;\n\n/* Chain of all pattern-specific variables.  */\n\nstatic struct pattern_var *pattern_vars = NULL;\n\n/* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/\n\nstatic struct pattern_var *last_pattern_vars[256];\n\n/* Create a new pattern-specific variable struct. The new variable is\n   inserted into the PATTERN_VARS list in the shortest patterns first\n   order to support the shortest stem matching (the variables are\n   matched in the reverse order so the ones with the longest pattern\n   will be considered first). Variables with the same pattern length\n   are inserted in the definition order. */\n\nstruct pattern_var *\ncreate_pattern_var (const char *target, const char *suffix)\n{\n  size_t len = strlen (target);\n  struct pattern_var *p = xcalloc (sizeof (struct pattern_var));\n\n  if (pattern_vars != 0)\n    {\n      if (len < 256 && last_pattern_vars[len] != 0)\n        {\n          p->next = last_pattern_vars[len]->next;\n          last_pattern_vars[len]->next = p;\n        }\n      else\n        {\n          /* Find the position where we can insert this variable. */\n          struct pattern_var **v;\n\n          for (v = &pattern_vars; ; v = &(*v)->next)\n            {\n              /* Insert at the end of the pack so that patterns with the\n                 same length appear in the order they were defined .*/\n\n              if (*v == 0 || (*v)->len > len)\n                {\n                  p->next = *v;\n                  *v = p;\n                  break;\n                }\n            }\n        }\n    }\n  else\n    {\n      pattern_vars = p;\n      p->next = 0;\n    }\n\n  p->target = target;\n  p->len = len;\n  p->suffix = suffix + 1;\n\n  if (len < 256)\n    last_pattern_vars[len] = p;\n\n  return p;\n}\n\n/* Look up a target in the pattern-specific variable list.  */\n\nstatic struct pattern_var *\nlookup_pattern_var (struct pattern_var *start, const char *target,\n                    size_t targlen)\n{\n  struct pattern_var *p;\n\n  for (p = start ? start->next : pattern_vars; p != 0; p = p->next)\n    {\n      const char *stem;\n      size_t stemlen;\n\n      if (p->len > targlen)\n        /* It can't possibly match.  */\n        continue;\n\n      /* From the lengths of the filename and the pattern parts,\n         find the stem: the part of the filename that matches the %.  */\n      stem = target + (p->suffix - p->target - 1);\n      stemlen = targlen - p->len + 1;\n\n      /* Compare the text in the pattern before the stem, if any.  */\n      if (stem > target && !strneq (p->target, target, stem - target))\n        continue;\n\n      /* Compare the text in the pattern after the stem, if any.\n         We could test simply using streq, but this way we compare the\n         first two characters immediately.  This saves time in the very\n         common case where the first character matches because it is a\n         period.  */\n      if (*p->suffix == stem[stemlen]\n          && (*p->suffix == '\\0' || streq (&p->suffix[1], &stem[stemlen+1])))\n        break;\n    }\n\n  return p;\n}\n\f\n/* Hash table of all global variable definitions.  */\n\nstatic unsigned long\nvariable_hash_1 (const void *keyv)\n{\n  struct variable const *key = (struct variable const *) keyv;\n  return_STRING_N_HASH_1 (key->name, key->length);\n}\n\nstatic unsigned long\nvariable_hash_2 (const void *keyv)\n{\n  struct variable const *key = (struct variable const *) keyv;\n  return_STRING_N_HASH_2 (key->name, key->length);\n}\n\nstatic int\nvariable_hash_cmp (const void *xv, const void *yv)\n{\n  struct variable const *x = (struct variable const *) xv;\n  struct variable const *y = (struct variable const *) yv;\n  int result = x->length - y->length;\n  if (result)\n    return result;\n  return_STRING_N_COMPARE (x->name, y->name, x->length);\n}\n\n#ifndef VARIABLE_BUCKETS\n#define VARIABLE_BUCKETS                523\n#endif\n#ifndef PERFILE_VARIABLE_BUCKETS\n#define PERFILE_VARIABLE_BUCKETS        23\n#endif\n#ifndef SMALL_SCOPE_VARIABLE_BUCKETS\n#define SMALL_SCOPE_VARIABLE_BUCKETS    13\n#endif\n\nstatic struct variable_set global_variable_set;\nstatic struct variable_set_list global_setlist\n  = { 0, &global_variable_set, 0 };\nstruct variable_set_list *current_variable_set_list = &global_setlist;\n\f\n/* Implement variables.  */\n\nstatic void\ncheck_valid_name (const floc* flocp, const char *name, size_t length)\n{\n  const char *cp, *end;\n\n  if (!warn_check (wt_invalid_var))\n    return;\n\n  for (cp = name, end = name + length; cp < end; ++cp)\n    if (ISSPACE (*cp))\n      break;\n  if (cp == end)\n    return;\n\n  warning (wt_invalid_var, flocp,\n           ONS (format, 0, _(\"invalid variable name '%.*s'\"), (int)length, name));\n}\n\nvoid\ninit_hash_global_variable_set (void)\n{\n  hash_init (&global_variable_set.table, VARIABLE_BUCKETS,\n             variable_hash_1, variable_hash_2, variable_hash_cmp);\n}\n\n/* Define variable named NAME with value VALUE in SET.  VALUE is copied.\n   LENGTH is the length of NAME, which does not need to be null-terminated.\n   ORIGIN specifies the origin of the variable (makefile, command line\n   or environment).\n   If RECURSIVE is nonzero a flag is set in the variable saying\n   that it should be recursively re-expanded.  */\n\nstruct variable *\ndefine_variable_in_set (const char *name, size_t length,\n                        const char *value, enum variable_origin origin,\n                        int recursive, struct variable_set *set,\n                        const floc *flocp)\n{\n  struct variable *v;\n  struct variable **var_slot;\n  struct variable var_key;\n\n  check_valid_name (flocp, name, length);\n\n  if (set == NULL)\n    set = &global_variable_set;\n\n  var_key.name = (char *) name;\n  var_key.length = (unsigned int) length;\n  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);\n  v = *var_slot;\n\n#if MK_OS_VMS\n  /* VMS does not populate envp[] with DCL symbols and logical names which\n     historically are mapped to environment variables.\n     If the variable is not yet defined, then we need to check if getenv()\n     can find it.  Do not do this for origin == o_env to avoid infinite\n     recursion */\n  if (HASH_VACANT (v) && (origin != o_env))\n    {\n      struct variable * vms_variable;\n      char * vname = alloca (length + 1);\n      char * vvalue;\n\n      strncpy (vname, name, length);\n      vvalue = getenv(vname);\n\n      /* Values starting with '$' are probably foreign commands.\n         We want to treat them as Shell aliases and not look them up here */\n      if ((vvalue != NULL) && (vvalue[0] != '$'))\n        {\n          vms_variable =  lookup_variable(name, length);\n          /* Refresh the slot */\n          var_slot = (struct variable **) hash_find_slot (&set->table,\n                                                          &var_key);\n          v = *var_slot;\n        }\n    }\n#endif\n\n  if (env_overrides && origin == o_env)\n    origin = o_env_override;\n\n  if (! HASH_VACANT (v))\n    {\n      if (env_overrides && v->origin == o_env)\n        /* V came from in the environment.  Since it was defined\n           before the switches were parsed, it wasn't affected by -e.  */\n        v->origin = o_env_override;\n\n      /* A variable of this name is already defined.\n         If the old definition is from a stronger source\n         than this one, don't redefine it.  */\n      if ((int) origin >= (int) v->origin)\n        {\n          free (v->value);\n          v->value = xstrdup (value);\n          if (flocp != 0)\n            v->fileinfo = *flocp;\n          else\n            v->fileinfo.filenm = 0;\n          v->origin = origin;\n          v->recursive = recursive;\n        }\n      return v;\n    }\n\n  /* Create a new variable definition and add it to the hash table.  */\n\n  v = xcalloc (sizeof (struct variable));\n  v->name = xstrndup (name, length);\n  v->length = (unsigned int) length;\n  hash_insert_at (&set->table, v, var_slot);\n  if (set == &global_variable_set)\n    ++variable_changenum;\n\n  v->value = xstrdup (value);\n  if (flocp != 0)\n    v->fileinfo = *flocp;\n  v->origin = origin;\n  v->recursive = recursive;\n\n  v->export = v_default;\n  v->exportable = 1;\n  /* Check the nul-terminated variable name.  */\n  name = v->name;\n  if (*name != '_' && (*name < 'A' || *name > 'Z')\n      && (*name < 'a' || *name > 'z'))\n    v->exportable = 0;\n  else\n    {\n      for (++name; *name != '\\0'; ++name)\n        if (*name != '_' && (*name < 'a' || *name > 'z')\n            && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name))\n          break;\n\n      if (*name != '\\0')\n        v->exportable = 0;\n    }\n\n  return v;\n}\n\f\n\n/* Undefine variable named NAME in SET. LENGTH is the length of NAME, which\n   does not need to be null-terminated. ORIGIN specifies the origin of the\n   variable (makefile, command line or environment). */\n\nstatic void\nfree_variable_name_and_value (const void *item)\n{\n  struct variable *v = (struct variable *) item;\n  free (v->name);\n  free (v->value);\n}\n\nvoid\nfree_variable_set (struct variable_set_list *list)\n{\n  hash_map (&list->set->table, free_variable_name_and_value);\n  hash_free (&list->set->table, 1);\n  free (list->set);\n  free (list);\n}\n\nvoid\nundefine_variable_in_set (const floc *flocp, const char *name, size_t length,\n                          enum variable_origin origin,\n                          struct variable_set *set)\n{\n  struct variable *v;\n  struct variable **var_slot;\n  struct variable var_key;\n\n  check_valid_name (flocp, name, length);\n\n  if (set == NULL)\n    set = &global_variable_set;\n\n  var_key.name = (char *) name;\n  var_key.length = (unsigned int) length;\n  var_slot = (struct variable **) hash_find_slot (&set->table, &var_key);\n\n  if (env_overrides && origin == o_env)\n    origin = o_env_override;\n\n  v = *var_slot;\n  if (! HASH_VACANT (v))\n    {\n      if (env_overrides && v->origin == o_env)\n        /* V came from in the environment.  Since it was defined\n           before the switches were parsed, it wasn't affected by -e.  */\n        v->origin = o_env_override;\n\n      /* Undefine only if this undefinition is from an equal or stronger\n         source than the variable definition.  */\n      if ((int) origin >= (int) v->origin)\n        {\n          hash_delete_at (&set->table, var_slot);\n          free_variable_name_and_value (v);\n          free (v);\n          if (set == &global_variable_set)\n            ++variable_changenum;\n        }\n    }\n}\n\n/* If the variable passed in is \"special\", handle its special nature.\n   Currently there are two such variables, both used for introspection:\n   .VARIABLES expands to a list of all the variables defined in this instance\n   of make.\n   .TARGETS expands to a list of all the targets defined in this\n   instance of make.\n   Returns the variable reference passed in.  */\n\n#define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500)\n\nstatic struct variable *\nlookup_special_var (struct variable *var)\n{\n  static unsigned long last_changenum = 0;\n\n  /* This one actually turns out to be very hard, due to the way the parser\n     records targets.  The way it works is that target information is collected\n     internally until make knows the target is completely specified.  Only when\n     it sees that some new construct (a new target or variable) is defined does\n     make know that the previous one is done.  In short, this means that if\n     you do this:\n\n       all:\n\n       TARGS := $(.TARGETS)\n\n     then $(TARGS) won't contain \"all\", because it's not until after the\n     variable is created that the previous target is completed.\n\n     Changing this would be a major pain.  I think a less complex way to do it\n     would be to pre-define the target files as soon as the first line is\n     parsed, then come back and do the rest of the definition as now.  That\n     would allow $(.TARGETS) to be correct without a major change to the way\n     the parser works.\n\n  if (streq (var->name, \".TARGETS\"))\n    var->value = build_target_list (var->value);\n  else\n  */\n\n  if (variable_changenum != last_changenum && streq (var->name, \".VARIABLES\"))\n    {\n      size_t max = EXPANSION_INCREMENT (strlen (var->value));\n      size_t len;\n      char *p;\n      struct variable **vp = (struct variable **) global_variable_set.table.ht_vec;\n      struct variable **end = &vp[global_variable_set.table.ht_size];\n\n      /* Make sure we have at least MAX bytes in the allocated buffer.  */\n      var->value = xrealloc (var->value, max);\n\n      /* Walk through the hash of variables, constructing a list of names.  */\n      p = var->value;\n      len = 0;\n      for (; vp < end; ++vp)\n        if (!HASH_VACANT (*vp))\n          {\n            struct variable *v = *vp;\n            int l = v->length;\n\n            len += l + 1;\n            if (len > max)\n              {\n                size_t off = p - var->value;\n\n                max += EXPANSION_INCREMENT (l + 1);\n                var->value = xrealloc (var->value, max);\n                p = &var->value[off];\n              }\n\n            p = mempcpy (p, v->name, l);\n            *(p++) = ' ';\n          }\n      *(p-1) = '\\0';\n\n      /* Remember the current variable change number.  */\n      last_changenum = variable_changenum;\n    }\n\n  return var;\n}\n\n\f\n/* Check the variable name for validity.  */\nstatic void\ncheck_variable_reference (const char *name, size_t length)\n{\n  const char *cp, *end;\n\n  if (!warn_check (wt_invalid_ref))\n    return;\n\n  for (cp = name, end = name + length; cp < end; ++cp)\n    if (ISSPACE (*cp))\n      break;\n  if (cp == end)\n    return;\n\n  warning (wt_invalid_ref, *expanding_var,\n           ONS (format, 0, _(\"invalid variable reference '%.*s'\"), (int)length, name));\n}\n\n/* Lookup a variable whose name is a string starting at NAME\n   and with LENGTH chars.  NAME need not be null-terminated.\n   Returns address of the 'struct variable' containing all info\n   on the variable, or nil if no such variable is defined.  */\n\nstruct variable *\nlookup_variable (const char *name, size_t length)\n{\n  const struct variable_set_list *setlist;\n  struct variable var_key;\n  int is_parent = 0;\n\n  check_variable_reference (name, length);\n\n  var_key.name = (char *) name;\n  var_key.length = (unsigned int) length;\n\n  for (setlist = current_variable_set_list;\n       setlist != 0; setlist = setlist->next)\n    {\n      const struct variable_set *set = setlist->set;\n      struct variable *v;\n\n      v = hash_find_item ((struct hash_table *) &set->table, &var_key);\n      if (v && (!is_parent || !v->private_var))\n        return v->special ? lookup_special_var (v) : v;\n\n      is_parent |= setlist->next_is_parent;\n    }\n\n#if MK_OS_VMS\n  /* VMS doesn't populate envp[] with DCL symbols and logical names, which\n     historically are mapped to environment variables and returned by\n     getenv().  */\n  {\n    char *vname = alloca (length + 1);\n    char *value;\n    strncpy (vname, name, length);\n    vname[length] = 0;\n    value = getenv (vname);\n    if (value != 0)\n      {\n        char *sptr;\n        int scnt;\n\n        sptr = value;\n        scnt = 0;\n\n        while ((sptr = strchr (sptr, '$')))\n          {\n            scnt++;\n            sptr++;\n          }\n\n        if (scnt > 0)\n          {\n            char *nvalue;\n            char *nptr;\n\n            nvalue = alloca (strlen (value) + scnt + 1);\n            sptr = value;\n            nptr = nvalue;\n\n            while (*sptr)\n              {\n                if (*sptr == '$')\n                  {\n                    *nptr++ = '$';\n                    *nptr++ = '$';\n                  }\n                else\n                  *nptr++ = *sptr;\n                sptr++;\n              }\n\n            *nptr = '\\0';\n            return define_variable (vname, length, nvalue, o_env, 1);\n\n          }\n\n        return define_variable (vname, length, value, o_env, 1);\n      }\n  }\n#endif /* MK_OS_VMS */\n\n  return 0;\n}\n/* Lookup a variable whose name is a string starting at NAME\n   and with LENGTH chars.  NAME need not be null-terminated.\n   Returns address of the 'struct variable' containing all info\n   on the variable, or nil if no such variable is defined.  */\n\nstruct variable *\nlookup_variable_for_file (const char *name, size_t length, struct file *file)\n{\n  struct variable *var;\n  struct variable_set_list *savev;\n\n  if (file == NULL)\n    return lookup_variable (name, length);\n\n  install_file_context (file, &savev, NULL);\n\n  var = lookup_variable (name, length);\n\n  restore_file_context (savev, NULL);\n\n  return var;\n}\n\f\n/* Lookup a variable whose name is a string starting at NAME\n   and with LENGTH chars in set SET.  NAME need not be null-terminated.\n   Returns address of the 'struct variable' containing all info\n   on the variable, or nil if no such variable is defined.  */\n\nstruct variable *\nlookup_variable_in_set (const char *name, size_t length,\n                        const struct variable_set *set)\n{\n  struct variable var_key;\n\n  check_variable_reference (name, length);\n\n  var_key.name = (char *) name;\n  var_key.length = (unsigned int) length;\n\n  return hash_find_item ((struct hash_table *) &set->table, &var_key);\n}\n\f\n/* Initialize FILE's variable set list.  If FILE already has a variable set\n   list, the topmost variable set is left intact, but the the rest of the\n   chain is replaced with FILE->parent's setlist.  If FILE is a double-colon\n   rule, then we will use the \"root\" double-colon target's variable set as the\n   parent of FILE's variable set.\n\n   If we're READING a makefile, don't do the pattern variable search now,\n   since the pattern variable might not have been defined yet.  */\n\nvoid\ninitialize_file_variables (struct file *file, int reading)\n{\n  struct variable_set_list *l = file->variables;\n\n  if (l == 0)\n    {\n      l = (struct variable_set_list *)\n        xmalloc (sizeof (struct variable_set_list));\n      l->set = xmalloc (sizeof (struct variable_set));\n      hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS,\n                 variable_hash_1, variable_hash_2, variable_hash_cmp);\n      file->variables = l;\n    }\n\n  /* If this is a double-colon, then our \"parent\" is the \"root\" target for\n     this double-colon rule.  Since that rule has the same name, parent,\n     etc. we can just use its variables as the \"next\" for ours.  */\n\n  if (file->double_colon && file->double_colon != file)\n    {\n      initialize_file_variables (file->double_colon, reading);\n      l->next = file->double_colon->variables;\n      l->next_is_parent = 0;\n      return;\n    }\n\n  if (file->parent == 0)\n    l->next = &global_setlist;\n  else\n    {\n      initialize_file_variables (file->parent, reading);\n      l->next = file->parent->variables;\n    }\n  l->next_is_parent = 1;\n\n  /* If we're not reading makefiles and we haven't looked yet, see if\n     we can find pattern variables for this target.  */\n\n  if (!reading && !file->pat_searched)\n    {\n      struct pattern_var *p;\n      const size_t targlen = strlen (file->name);\n\n      p = lookup_pattern_var (0, file->name, targlen);\n      if (p != 0)\n        {\n          struct variable_set_list *global = current_variable_set_list;\n\n          /* We found at least one.  Set up a new variable set to accumulate\n             all the pattern variables that match this target.  */\n\n          file->pat_variables = create_new_variable_set ();\n          current_variable_set_list = file->pat_variables;\n\n          do\n            {\n              /* We found one, so insert it into the set.  */\n\n              struct variable *v;\n\n              if (p->variable.flavor == f_simple)\n                {\n                  v = define_variable_loc (\n                    p->variable.name, strlen (p->variable.name),\n                    p->variable.value, p->variable.origin,\n                    0, &p->variable.fileinfo);\n\n                  v->flavor = f_simple;\n                }\n              else\n                v = do_variable_definition (\n                  &p->variable.fileinfo, p->variable.name, p->variable.value,\n                  p->variable.origin, p->variable.flavor,\n                  p->variable.conditional, s_pattern);\n\n              /* Also mark it as a per-target and copy export status. */\n              v->per_target = p->variable.per_target;\n              v->export = p->variable.export;\n              v->private_var = p->variable.private_var;\n            }\n          while ((p = lookup_pattern_var (p, file->name, targlen)) != 0);\n\n          current_variable_set_list = global;\n        }\n      file->pat_searched = 1;\n    }\n\n  /* If we have a pattern variable match, set it up.  */\n\n  if (file->pat_variables != 0)\n    {\n      file->pat_variables->next = l->next;\n      file->pat_variables->next_is_parent = l->next_is_parent;\n      l->next = file->pat_variables;\n      l->next_is_parent = 0;\n    }\n}\n\f\n/* Pop the top set off the current variable set list,\n   and free all its storage.  */\n\nstruct variable_set_list *\ncreate_new_variable_set (void)\n{\n  struct variable_set_list *setlist;\n  struct variable_set *set;\n\n  set = xmalloc (sizeof (struct variable_set));\n  hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS,\n             variable_hash_1, variable_hash_2, variable_hash_cmp);\n\n  setlist = (struct variable_set_list *)\n    xmalloc (sizeof (struct variable_set_list));\n  setlist->set = set;\n  setlist->next = current_variable_set_list;\n  setlist->next_is_parent = 0;\n\n  return setlist;\n}\n\n/* Create a new variable set and push it on the current setlist.\n   If we're pushing a global scope (that is, the current scope is the global\n   scope) then we need to \"push\" it the other way: file variable sets point\n   directly to the global_setlist so we need to replace that with the new one.\n */\n\nstruct variable_set_list *\npush_new_variable_scope (void)\n{\n  current_variable_set_list = create_new_variable_set ();\n  if (current_variable_set_list->next == &global_setlist)\n    {\n      /* It was the global, so instead of new -> &global we want to replace\n         &global with the new one and have &global -> new, with current still\n         pointing to &global  */\n      struct variable_set *set = current_variable_set_list->set;\n      current_variable_set_list->set = global_setlist.set;\n      global_setlist.set = set;\n      current_variable_set_list->next = global_setlist.next;\n      global_setlist.next = current_variable_set_list;\n      current_variable_set_list = &global_setlist;\n    }\n  return current_variable_set_list;\n}\n\nvoid\npop_variable_scope (void)\n{\n  struct variable_set_list *setlist;\n  struct variable_set *set;\n\n  /* Can't call this if there's no scope to pop!  */\n  assert (current_variable_set_list->next != NULL);\n\n  if (current_variable_set_list != &global_setlist)\n    {\n      /* We're not pointing to the global setlist, so pop this one.  */\n      setlist = current_variable_set_list;\n      set = setlist->set;\n      current_variable_set_list = setlist->next;\n    }\n  else\n    {\n      /* This set is the one in the global_setlist, but there is another global\n         set beyond that.  We want to copy that set to global_setlist, then\n         delete what used to be in global_setlist.  */\n      setlist = global_setlist.next;\n      set = global_setlist.set;\n      global_setlist.set = setlist->set;\n      global_setlist.next = setlist->next;\n      global_setlist.next_is_parent = setlist->next_is_parent;\n    }\n\n  /* Free the one we no longer need.  */\n  free (setlist);\n  hash_map (&set->table, free_variable_name_and_value);\n  hash_free (&set->table, 1);\n  free (set);\n}\n\n/* Install a new global context for FILE so that errors/warnings are shown\n   in that context.  Sets OLDLIST to the previous list, and if not NULL sets\n   OLDFLOC to reading_file and changes reading_file to the current FILE.\n   Use restore_file_context() to undo this.  */\n\nvoid\ninstall_file_context (struct file *file, struct variable_set_list **oldlist, const floc **oldfloc)\n{\n  *oldlist = current_variable_set_list;\n  current_variable_set_list = file->variables;\n\n  if (oldfloc)\n    {\n      *oldfloc = reading_file;\n      if (file->cmds && file->cmds->fileinfo.filenm)\n        reading_file = &file->cmds->fileinfo;\n      else\n        reading_file = NULL;\n    }\n}\n\n/* Restore a saved global context from OLDLIST.  If OLDFLOC is not NULL,\n   set reading_file back to that value.  */\n\nvoid\nrestore_file_context (struct variable_set_list *oldlist, const floc *oldfloc)\n{\n  current_variable_set_list = oldlist;\n  if (oldfloc)\n    reading_file = oldfloc;\n}\n\n\f\n/* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET.  */\n\nstatic void\nmerge_variable_sets (struct variable_set *to_set,\n                     struct variable_set *from_set)\n{\n  struct variable **from_var_slot = (struct variable **) from_set->table.ht_vec;\n  struct variable **from_var_end = from_var_slot + from_set->table.ht_size;\n\n  int inc = to_set == &global_variable_set ? 1 : 0;\n\n  for ( ; from_var_slot < from_var_end; from_var_slot++)\n    if (! HASH_VACANT (*from_var_slot))\n      {\n        struct variable *from_var = *from_var_slot;\n        struct variable **to_var_slot\n          = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot);\n        if (HASH_VACANT (*to_var_slot))\n          {\n            hash_insert_at (&to_set->table, from_var, to_var_slot);\n            variable_changenum += inc;\n          }\n        else\n          {\n            /* GKM FIXME: delete in from_set->table */\n            free (from_var->value);\n            free (from_var);\n          }\n      }\n}\n\n/* Merge SETLIST1 into SETLIST0, freeing unused storage in SETLIST1.  */\n\nvoid\nmerge_variable_set_lists (struct variable_set_list **setlist0,\n                          struct variable_set_list *setlist1)\n{\n  struct variable_set_list *to = *setlist0;\n  struct variable_set_list *last0 = 0;\n\n  /* If there's nothing to merge, stop now.  */\n  if (!setlist1 || setlist1 == &global_setlist)\n    return;\n\n  if (to)\n    {\n      /* These loops rely on the fact that all setlists terminate with the\n         global setlist (before NULL).  If not, arguably we SHOULD die.  */\n\n      /* Make sure that setlist1 is not already a subset of setlist0.  */\n      while (to != &global_setlist)\n        {\n          if (to == setlist1)\n            return;\n          to = to->next;\n        }\n\n      to = *setlist0;\n      while (setlist1 != &global_setlist && to != &global_setlist)\n        {\n          struct variable_set_list *from = setlist1;\n          setlist1 = setlist1->next;\n\n          merge_variable_sets (to->set, from->set);\n\n          last0 = to;\n          to = to->next;\n        }\n    }\n\n  if (setlist1 != &global_setlist)\n    {\n      if (last0 == 0)\n        *setlist0 = setlist1;\n      else\n        last0->next = setlist1;\n    }\n}\n\f\n/* Define the automatic variables, and record the addresses\n   of their structures so we can change their values quickly.  */\n\nvoid\ndefine_automatic_variables (void)\n{\n  struct variable *v;\n  char buf[200];\n\n  sprintf (buf, \"%u\", makelevel);\n  define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0);\n\n  sprintf (buf, \"%s%s%s\",\n           version_string,\n           (remote_description == 0 || remote_description[0] == '\\0')\n           ? \"\" : \"-\",\n           (remote_description == 0 || remote_description[0] == '\\0')\n           ? \"\" : remote_description);\n  define_variable_cname (\"MAKE_VERSION\", buf, o_default, 0);\n  define_variable_cname (\"MAKE_HOST\", make_host, o_default, 0);\n\n#if MK_OS_DOS\n  /* Allow to specify a special shell just for Make,\n     and use $COMSPEC as the default $SHELL when appropriate.  */\n  {\n    static char shell_str[] = \"SHELL\";\n    const int shlen = sizeof (shell_str) - 1;\n    struct variable *mshp = lookup_variable (\"MAKESHELL\", 9);\n    struct variable *comp = lookup_variable (\"COMSPEC\", 7);\n\n    /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect.  */\n    if (mshp)\n      (void) define_variable (shell_str, shlen,\n                              mshp->value, o_env_override, 0);\n    else if (comp)\n      {\n        /* $(COMSPEC) shouldn't override $(SHELL).  */\n        struct variable *shp = lookup_variable (shell_str, shlen);\n\n        if (!shp)\n          (void) define_variable (shell_str, shlen, comp->value, o_env, 0);\n      }\n  }\n#elif MK_OS_OS2\n  {\n    static char shell_str[] = \"SHELL\";\n    const int shlen = sizeof (shell_str) - 1;\n    struct variable *shell = lookup_variable (shell_str, shlen);\n    struct variable *replace = lookup_variable (\"MAKESHELL\", 9);\n\n    /* if $MAKESHELL is defined in the environment assume o_env_override */\n    if (replace && *replace->value && replace->origin == o_env)\n      replace->origin = o_env_override;\n\n    /* if $MAKESHELL is not defined use $SHELL but only if the variable\n       did not come from the environment */\n    if (!replace || !*replace->value)\n      if (shell && *shell->value && (shell->origin == o_env\n          || shell->origin == o_env_override))\n        {\n          /* overwrite whatever we got from the environment */\n          free (shell->value);\n          shell->value = xstrdup (default_shell);\n          shell->origin = o_default;\n        }\n\n    /* Some people do not like cmd to be used as the default\n       if $SHELL is not defined in the Makefile.\n       With -DNO_CMD_DEFAULT you can turn off this behaviour */\n# ifndef NO_CMD_DEFAULT\n    /* otherwise use $COMSPEC */\n    if (!replace || !*replace->value)\n      replace = lookup_variable (\"COMSPEC\", 7);\n\n    /* otherwise use $OS2_SHELL */\n    if (!replace || !*replace->value)\n      replace = lookup_variable (\"OS2_SHELL\", 9);\n# else\n#   warning NO_CMD_DEFAULT: GNU Make will not use CMD.EXE as default shell\n# endif\n\n    if (replace && *replace->value)\n      /* overwrite $SHELL */\n      (void) define_variable (shell_str, shlen, replace->value,\n                              replace->origin, 0);\n    else\n      /* provide a definition if there is none */\n      (void) define_variable (shell_str, shlen, default_shell,\n                              o_default, 0);\n  }\n\n#endif\n\n  /* This won't override any definition, but it will provide one if there\n     isn't one there.  */\n  v = define_variable_cname (\"SHELL\", default_shell, o_default, 0);\n#if MK_OS_DOS\n  v->export = v_export;  /*  Export always SHELL.  */\n#endif\n\n  /* On MSDOS we do use SHELL from environment, since it isn't a standard\n     environment variable on MSDOS, so whoever sets it, does that on purpose.\n     On OS/2 we do not use SHELL from environment but we have already handled\n     that problem above. */\n#if !MK_OS_DOS && !MK_OS_OS2\n  /* Don't let SHELL come from the environment.  */\n  if (*v->value == '\\0' || v->origin == o_env || v->origin == o_env_override)\n    {\n      free (v->value);\n      v->origin = o_file;\n      v->value = xstrdup (default_shell);\n    }\n#endif\n\n  /* Make sure MAKEFILES gets exported if it is set.  */\n  v = define_variable_cname (\"MAKEFILES\", \"\", o_default, 0);\n  v->export = v_ifset;\n\n  /* Define the magic D and F variables in terms of\n     the automatic variables they are variations of.  */\n\n#if MK_OS_DOS || MK_OS_W32\n  /* For consistency, remove the trailing backslash as well as slash.  */\n  define_variable_cname (\"@D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $@)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"%D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $%)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"*D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $*)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"<D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $<)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"?D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $?)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"^D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $^)))\",\n                         o_automatic, 1);\n  define_variable_cname (\"+D\", \"$(patsubst %/,%,$(patsubst %\\\\,%,$(dir $+)))\",\n                         o_automatic, 1);\n#else  /* not MK_OS_DOS, not MK_OS_W32 */\n  define_variable_cname (\"@D\", \"$(patsubst %/,%,$(dir $@))\", o_automatic, 1);\n  define_variable_cname (\"%D\", \"$(patsubst %/,%,$(dir $%))\", o_automatic, 1);\n  define_variable_cname (\"*D\", \"$(patsubst %/,%,$(dir $*))\", o_automatic, 1);\n  define_variable_cname (\"<D\", \"$(patsubst %/,%,$(dir $<))\", o_automatic, 1);\n  define_variable_cname (\"?D\", \"$(patsubst %/,%,$(dir $?))\", o_automatic, 1);\n  define_variable_cname (\"^D\", \"$(patsubst %/,%,$(dir $^))\", o_automatic, 1);\n  define_variable_cname (\"+D\", \"$(patsubst %/,%,$(dir $+))\", o_automatic, 1);\n#endif\n  define_variable_cname (\"@F\", \"$(notdir $@)\", o_automatic, 1);\n  define_variable_cname (\"%F\", \"$(notdir $%)\", o_automatic, 1);\n  define_variable_cname (\"*F\", \"$(notdir $*)\", o_automatic, 1);\n  define_variable_cname (\"<F\", \"$(notdir $<)\", o_automatic, 1);\n  define_variable_cname (\"?F\", \"$(notdir $?)\", o_automatic, 1);\n  define_variable_cname (\"^F\", \"$(notdir $^)\", o_automatic, 1);\n  define_variable_cname (\"+F\", \"$(notdir $+)\", o_automatic, 1);\n}\n\f\n\nstatic int\nshould_export (const struct variable *v)\n{\n  switch (v->export)\n    {\n    case v_export:\n      break;\n\n    case v_noexport:\n      return 0;\n\n    case v_ifset:\n      if (v->origin == o_default)\n        return 0;\n      break;\n\n    case v_default:\n      if (v->origin == o_default || v->origin == o_automatic)\n        /* Only export default variables by explicit request.  */\n        return 0;\n\n      /* The variable doesn't have a name that can be exported.  */\n      if (! v->exportable)\n        return 0;\n\n      if (! export_all_variables\n          && v->origin != o_command\n          && v->origin != o_env && v->origin != o_env_override)\n        return 0;\n      break;\n    }\n\n  return 1;\n}\n\n/* Create a new environment for FILE's commands.\n   If FILE is nil, this is for the 'shell' function.\n   The child's MAKELEVEL variable is incremented.\n   If recursive is true then we're running a recursive make, else not.  */\n\nchar **\ntarget_environment (struct file *file, int recursive)\n{\n  struct variable_set_list *set_list;\n  struct variable_set_list *s;\n  struct hash_table table;\n  struct variable **v_slot;\n  struct variable **v_end;\n  char **result_0;\n  char **result;\n  const char *invalid = NULL;\n  /* If we got no value from the environment then never add the default.  */\n  int added_SHELL = shell_var.value == 0;\n  int found_makelevel = 0;\n  int found_mflags = 0;\n  int found_makeflags = 0;\n\n  /* If file is NULL we're creating the target environment for $(shell ...)\n     Remember this so we can just ignore recursion.  */\n  if (!file)\n    ++env_recursion;\n\n  /* We need to update makeflags if (a) we're not recurive, (b) jobserver_auth\n     is enabled, and (c) we need to add invalidation.  */\n  if (!recursive && jobserver_auth)\n    invalid = jobserver_get_invalid_auth ();\n\n  if (file)\n    set_list = file->variables;\n  else\n    set_list = current_variable_set_list;\n\n  hash_init (&table, VARIABLE_BUCKETS,\n             variable_hash_1, variable_hash_2, variable_hash_cmp);\n\n  /* Run through all the variable sets in the list, accumulating variables\n     in TABLE.  We go from most specific to least, so the first variable we\n     encounter is the keeper.  */\n  for (s = set_list; s != 0; s = s->next)\n    {\n      struct variable_set *set = s->set;\n      const int islocal = s == set_list;\n      const int isglobal = set == &global_variable_set;\n\n      v_slot = (struct variable **) set->table.ht_vec;\n      v_end = v_slot + set->table.ht_size;\n      for ( ; v_slot < v_end; v_slot++)\n        if (! HASH_VACANT (*v_slot))\n          {\n            struct variable **evslot;\n            struct variable *v = *v_slot;\n\n            if (!islocal && v->private_var)\n              continue;\n\n            evslot = (struct variable **) hash_find_slot (&table, v);\n\n            if (HASH_VACANT (*evslot))\n              {\n                /* We'll always add target-specific variables, since we may\n                   discover that they should be exported later: we'll check\n                   again below.  For global variables only add them if they're\n                   exportable.  */\n                if (!isglobal || should_export (v))\n                  hash_insert_at (&table, v, evslot);\n              }\n            else if ((*evslot)->export == v_default)\n              /* We already have a variable but we don't know its status.  */\n              (*evslot)->export = v->export;\n          }\n    }\n\n  result = result_0 = xmalloc ((table.ht_fill + 3) * sizeof (char *));\n\n  v_slot = (struct variable **) table.ht_vec;\n  v_end = v_slot + table.ht_size;\n  for ( ; v_slot < v_end; v_slot++)\n    if (! HASH_VACANT (*v_slot))\n      {\n        struct variable *v = *v_slot;\n        char *value = v->value;\n        char *cp = NULL;\n\n        /* This might be here because it was a target-specific variable that\n           we didn't know the status of when we added it.  */\n        if (! should_export (v))\n          continue;\n\n        /* If V is recursively expanded and didn't come from the environment,\n           expand its value.  If it came from the environment, it should\n           go back into the environment unchanged... except MAKEFLAGS.  */\n        if (v->recursive && ((v->origin != o_env && v->origin != o_env_override)\n                             || streq (v->name, MAKEFLAGS_NAME)))\n          value = cp = recursively_expand_for_file (v, file);\n\n        /* If this is the SHELL variable remember we already added it.  */\n        if (!added_SHELL && streq (v->name, \"SHELL\"))\n          {\n            added_SHELL = 1;\n            goto setit;\n          }\n\n        /* If this is MAKELEVEL, update it.  */\n        if (!found_makelevel && streq (v->name, MAKELEVEL_NAME))\n          {\n            char val[INTSTR_LENGTH + 1];\n            sprintf (val, \"%u\", makelevel + 1);\n            free (cp);\n            value = cp = xstrdup (val);\n            found_makelevel = 1;\n            goto setit;\n          }\n\n        /* If we need to reset jobserver, check for MAKEFLAGS / MFLAGS.  */\n        if (invalid)\n          {\n            if (!found_makeflags && streq (v->name, MAKEFLAGS_NAME))\n              {\n                char *mf;\n                char *vars;\n                found_makeflags = 1;\n\n                if (!strstr (value, \" --\" JOBSERVER_AUTH_OPT \"=\"))\n                  goto setit;\n\n                /* The invalid option must come before variable overrides.  */\n                vars = strstr (value, \" -- \");\n                if (!vars)\n                  mf = xstrdup (concat (2, value, invalid));\n                else\n                  {\n                    size_t lf = vars - value;\n                    size_t li = strlen (invalid);\n                    mf = xmalloc (strlen (value) + li + 1);\n                    strcpy (mempcpy (mempcpy (mf, value, lf), invalid, li),\n                            vars);\n                  }\n                free (cp);\n                value = cp = mf;\n                if (found_mflags)\n                  invalid = NULL;\n                goto setit;\n              }\n\n            if (!found_mflags && streq (v->name, \"MFLAGS\"))\n              {\n                const char *mf;\n                found_mflags = 1;\n\n                if (!strstr (value, \" --\" JOBSERVER_AUTH_OPT \"=\"))\n                  goto setit;\n\n                if (v->origin != o_env)\n                  goto setit;\n                mf = concat (2, value, invalid);\n                free (cp);\n                value = cp = xstrdup (mf);\n                if (found_makeflags)\n                  invalid = NULL;\n                goto setit;\n              }\n          }\n\n#if MK_OS_W32\n        if (streq (v->name, \"Path\") || streq (v->name, \"PATH\"))\n          {\n            if (!cp)\n              cp = xstrdup (value);\n            value = convert_Path_to_windows32 (cp, ';');\n            goto setit;\n          }\n#endif\n\n      setit:\n        *result++ = xstrdup (concat (3, v->name, \"=\", value));\n        free (cp);\n      }\n\n  if (!added_SHELL)\n    *result++ = xstrdup (concat (3, shell_var.name, \"=\", shell_var.value));\n\n  if (!found_makelevel)\n    {\n      char val[MAKELEVEL_LENGTH + 1 + INTSTR_LENGTH + 1];\n      sprintf (val, \"%s=%u\", MAKELEVEL_NAME, makelevel + 1);\n      *result++ = xstrdup (val);\n    }\n\n  *result = NULL;\n\n  hash_free (&table, 0);\n\n  if (!file)\n    --env_recursion;\n\n  return result_0;\n}\n\f\nstatic struct variable *\nset_special_var (struct variable *var, enum variable_origin origin)\n{\n  if (streq (var->name, MAKEFLAGS_NAME))\n    reset_makeflags (origin);\n\n  else if (streq (var->name, RECIPEPREFIX_NAME))\n    /* The user is resetting the command introduction prefix.  This has to\n       happen immediately, so that subsequent rules are interpreted\n       properly.  */\n    cmd_prefix = var->value[0]=='\\0' ? RECIPEPREFIX_DEFAULT : var->value[0];\n\n  else if (streq (var->name, WARNINGS_NAME))\n    {\n      /* It's weird but for .WARNINGS to make sense we need to expand them\n         when they are set, even if it's a recursive variable.  */\n      char *actions = allocated_expand_variable (STRING_SIZE_TUPLE (WARNINGS_NAME));\n      decode_warn_actions (actions, &var->fileinfo);\n      free (actions);\n    }\n\n  return var;\n}\n\f\n/* Given a string, shell-execute it and return a malloc'ed string of the\n * result. This removes only ONE newline (if any) at the end, for maximum\n * compatibility with the *BSD makes.  If it fails, returns NULL. */\n\nstatic char *\nshell_result (const char *p)\n{\n  char *buf;\n  size_t len;\n  char *args[2];\n\n  install_variable_buffer (&buf, &len);\n\n  args[0] = (char *) p;\n  args[1] = NULL;\n  func_shell_base (variable_buffer, args, 0);\n\n  return swap_variable_buffer (buf, len);\n}\n\f\n/* Given a variable, a value, and a flavor, define the variable.\n   See the try_variable_definition() function for details on the parameters. */\n\nstruct variable *\ndo_variable_definition (const floc *flocp, const char *varname, const char *value,\n                        enum variable_origin origin, enum variable_flavor flavor,\n                        int conditional, enum variable_scope scope)\n{\n  const char *newval;\n  char *alloc_value = NULL;\n  struct variable *v;\n  int append = 0;\n\n  /* Conditional variable definition: only set if the var is not defined. */\n  if (conditional)\n    {\n      v = lookup_variable (varname, strlen (varname));\n      if (v)\n        return v;\n    }\n\n  /* Calculate the variable's new value in VALUE.  */\n\n  switch (flavor)\n    {\n    case f_simple:\n      /* A simple variable definition \"var := value\".  Expand the value.\n         We have to allocate memory since otherwise it'll clobber the\n         variable buffer, and we may still need that if we're looking at a\n         target-specific variable.  */\n      newval = alloc_value = allocated_expand_string (value);\n      break;\n    case f_expand:\n      {\n        /* A POSIX \"var :::= value\" assignment.  Expand the value, then it\n           becomes a recursive variable.  After expansion convert all '$'\n           tokens to '$$' to resolve to '$' when recursively expanded.  */\n        char *t = allocated_expand_string (value);\n        char *np = alloc_value = xmalloc (strlen (t) * 2 + 1);\n        char *op = t;\n        while (op[0] != '\\0')\n          {\n            if (op[0] == '$')\n              *(np++) = '$';\n            *(np++) = *(op++);\n          }\n        *np = '\\0';\n        free (t);\n        newval = alloc_value;\n        break;\n      }\n    case f_shell:\n      {\n        /* A shell definition \"var != value\".  Expand value, pass it to\n           the shell, and store the result in recursively-expanded var. */\n        char *q = allocated_expand_string (value);\n        alloc_value = shell_result (q);\n        free (q);\n        flavor = f_recursive;\n        newval = alloc_value;\n        break;\n      }\n    case f_recursive:\n      /* A recursive variable definition \"var = value\".\n         The value is used verbatim.  */\n      newval = value;\n      break;\n    case f_append:\n    case f_append_value:\n      {\n        int override = 0;\n        if (scope == s_global)\n          v = lookup_variable (varname, strlen (varname));\n        else\n          {\n            /* When appending in a target/pattern variable context, we want to\n               append only with other variables in the context of this\n               target/pattern.  */\n            append = 1;\n            v = lookup_variable_in_set (varname, strlen (varname),\n                                        current_variable_set_list->set);\n            if (v)\n              {\n                /* Don't append from the global set if a previous non-appending\n                   target/pattern-specific variable definition exists. */\n                if (!v->append)\n                  append = 0;\n\n                if (scope == s_pattern &&\n                    (v->origin == o_env_override || v->origin == o_command))\n                  {\n                    /* This is the case of multiple target/pattern specific\n                       definitions/appends, e.g.\n                         al%: hello := first\n                         al%: hello += second\n                       in the presence of a command line definition or an\n                       env override.  Do not merge x->value and value here.\n                       For pattern-specific variables the values are merged in\n                       recursively_expand_for_file.  */\n                    override = 1;\n                    append = 1;\n                  }\n              }\n          }\n\n        if (!v)\n          {\n            /* There was no old value: make this a recursive definition.  */\n            newval = value;\n            flavor = f_recursive;\n          }\n        else if (override)\n          {\n            /* Command line definition / env override takes precedence over\n               a pattern/target-specific append.  */\n            newval = value;\n            /* Set flavor to f_recursive to recursively expand this variable\n               at build time in recursively_expand_for_file.  */\n            flavor = f_recursive;\n          }\n        else\n          {\n            /* Paste the old and new values together in VALUE.  */\n\n            size_t oldlen, vallen, alloclen;\n            const char *val;\n            char *cp;\n            char *tp = NULL;\n\n            val = value;\n            if (v->recursive)\n              /* The previous definition of the variable was recursive.\n                 The new value is the unexpanded old and new values.  */\n              flavor = f_recursive;\n            else if (flavor != f_append_value)\n              /* The previous definition of the variable was simple.\n                 The new value comes from the old value, which was expanded\n                 when it was set; and from the expanded new value.  Allocate\n                 memory for the expansion as we may still need the rest of the\n                 buffer if we're looking at a target-specific variable.  */\n              val = tp = allocated_expand_string (val);\n\n            /* If the new value is empty, nothing to do.  */\n            vallen = strlen (val);\n            if (!vallen)\n              {\n                alloc_value = tp;\n                goto done;\n              }\n\n            oldlen = strlen (v->value);\n            alloclen = oldlen + 1 + vallen + 1;\n            cp = alloc_value = xmalloc (alloclen);\n\n            if (oldlen)\n              {\n                char *s;\n                if (streq (varname, MAKEFLAGS_NAME)\n                    && (s = strstr (v->value, \" -- \")) != NULL)\n                  /* We found a separator in MAKEFLAGS.  Ignore variable\n                     assignments: set_special_var() will reconstruct things.  */\n                  cp = mempcpy (cp, v->value, s - v->value);\n                else\n                  cp = mempcpy (cp, v->value, oldlen);\n                *(cp++) = ' ';\n              }\n\n            memcpy (cp, val, vallen + 1);\n            free (tp);\n            newval = alloc_value;\n          }\n      }\n      break;\n    case f_bogus:\n    default:\n      /* Should not be possible.  */\n      abort ();\n    }\n\n  assert (newval);\n\n#if MK_OS_DOS\n  /* Many Unix Makefiles include a line saying \"SHELL=/bin/sh\", but\n     non-Unix systems don't conform to this default configuration (in\n     fact, most of them don't even have '/bin').  On the other hand,\n     $SHELL in the environment, if set, points to the real pathname of\n     the shell.\n     Therefore, we generally won't let lines like \"SHELL=/bin/sh\" from\n     the Makefile override $SHELL from the environment.  But first, we\n     look for the basename of the shell in the directory where SHELL=\n     points, and along the $PATH; if it is found in any of these places,\n     we define $SHELL to be the actual pathname of the shell.  Thus, if\n     you have bash.exe installed as d:/unix/bash.exe, and d:/unix is on\n     your $PATH, then SHELL=/usr/local/bin/bash will have the effect of\n     defining SHELL to be \"d:/unix/bash.exe\".  */\n  if ((origin == o_file || origin == o_override)\n      && strcmp (varname, \"SHELL\") == 0)\n    {\n      PATH_VAR (shellpath);\n      extern char * __dosexec_find_on_path (const char *, char *[], char *);\n\n      /* See if we can find \"/bin/sh.exe\", \"/bin/sh.com\", etc.  */\n      if (__dosexec_find_on_path (p, NULL, shellpath))\n        {\n          char *tp;\n\n          for (tp = shellpath; *tp; tp++)\n            if (*tp == '\\\\')\n              *tp = '/';\n\n          v = define_variable_loc (varname, strlen (varname),\n                                   shellpath, origin, flavor == f_recursive,\n                                   flocp);\n        }\n      else\n        {\n          const char *shellbase, *bslash;\n          struct variable *pathv = lookup_variable (\"PATH\", 4);\n          char *path_string;\n          char *fake_env[2];\n          size_t pathlen = 0;\n\n          shellbase = strrchr (newval, '/');\n          bslash = strrchr (newval, '\\\\');\n          if (!shellbase || bslash > shellbase)\n            shellbase = bslash;\n          if (!shellbase && newval[1] == ':')\n            shellbase = newval + 1;\n          if (shellbase)\n            shellbase++;\n          else\n            shellbase = newval;\n\n          /* Search for the basename of the shell (with standard\n             executable extensions) along the $PATH.  */\n          if (pathv)\n            pathlen = strlen (pathv->value);\n          path_string = xmalloc (5 + pathlen + 2 + 1);\n          /* On MSDOS, current directory is considered as part of $PATH.  */\n          sprintf (path_string, \"PATH=.;%s\", pathv ? pathv->value : \"\");\n          fake_env[0] = path_string;\n          fake_env[1] = 0;\n          if (__dosexec_find_on_path (shellbase, fake_env, shellpath))\n            {\n              char *tp;\n\n              for (tp = shellpath; *tp; tp++)\n                if (*tp == '\\\\')\n                  *tp = '/';\n\n              v = define_variable_loc (varname, strlen (varname),\n                                       shellpath, origin,\n                                       flavor == f_recursive, flocp);\n            }\n          else\n            v = lookup_variable (varname, strlen (varname));\n\n          free (path_string);\n        }\n    }\n  else\n#endif /* MK_OS_DOS */\n#if MK_OS_W32\n  if ((origin == o_file || origin == o_override || origin == o_command)\n      && streq (varname, \"SHELL\"))\n    {\n      extern const char *default_shell;\n\n      /* Call shell locator function. If it returns TRUE, then\n         set no_default_sh_exe to indicate sh was found and\n         set new value for SHELL variable.  */\n\n      if (find_and_set_default_shell (newval))\n        {\n          v = define_variable_in_set (varname, strlen (varname), default_shell,\n                                      origin, flavor == f_recursive,\n                                      (scope == s_global ? NULL\n                                       : current_variable_set_list->set),\n                                      flocp);\n          no_default_sh_exe = 0;\n        }\n      else\n        {\n          char *tp = alloc_value;\n\n          alloc_value = allocated_expand_string (newval);\n\n          if (find_and_set_default_shell (alloc_value))\n            {\n              v = define_variable_in_set (varname, strlen (varname), newval,\n                                          origin, flavor == f_recursive,\n                                          (scope == s_global ? NULL\n                                           : current_variable_set_list->set),\n                                          flocp);\n              no_default_sh_exe = 0;\n            }\n          else\n            v = lookup_variable (varname, strlen (varname));\n\n          free (tp);\n        }\n    }\n  else\n    v = NULL;\n\n  /* If not $SHELL, or if $SHELL points to a program we didn't find,\n     just process this variable \"as usual\".  */\n  if (!v)\n#endif\n\n  /* If we are defining variables inside an $(eval ...), we might have a\n     different variable context pushed, not the global context (maybe we're\n     inside a $(call ...) or something.  Since this function is only ever\n     invoked in places where we want to define globally visible variables,\n     make sure we define this variable in the global set.  */\n\n  v = define_variable_in_set (varname, strlen (varname), newval, origin,\n                              flavor == f_recursive || flavor == f_expand,\n                              (scope == s_global\n                               ? NULL : current_variable_set_list->set),\n                              flocp);\n  v->append = append;\n  v->conditional = conditional;\n\n done:\n  free (alloc_value);\n  return v->special ? set_special_var (v, origin) : v;\n}\n\f\n/* Parse P (a null-terminated string) as a variable definition.\n\n   If it is not a variable definition, return NULL and the contents of *VAR\n   are undefined, except NAME points to the first non-space character or EOS.\n\n   If it is a variable definition, return a pointer to the char after the\n   assignment token and set the following fields (only) of *VAR:\n    name        : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!)\n    length      : length of the variable name\n    value       : value of the variable (nul-terminated)\n    flavor      : flavor of the variable\n    conditional : whether it's a conditional assignment\n   Other values in *VAR are unchanged.\n  */\n\nchar *\nparse_variable_definition (const char *str, struct variable *var)\n{\n  const char *p = str;\n  const char *end = NULL;\n\n  NEXT_TOKEN (p);\n  var->name = (char *)p;\n  var->length = 0;\n  var->conditional = 0;\n\n  /* Walk through STR until we find a valid assignment operator.  Each time\n     through this loop P points to the next character to consider.  */\n  while (1)\n    {\n      const char *start;\n      int c = *p++;\n\n      /* If we find a comment or EOS, it's not a variable definition.  */\n      if (STOP_SET (c, MAP_COMMENT|MAP_NUL))\n        return NULL;\n\n      if (ISBLANK (c))\n        {\n          /* Variable names can't contain spaces so if this is the second set\n             of spaces we know it's not a variable assignment.  */\n          if (end)\n            return NULL;\n          end = p - 1;\n          NEXT_TOKEN (p);\n          continue;\n        }\n\n      /* This is the start of a token.  */\n      start = p - 1;\n\n      /* If we see a ? then it could be a conditional assignment. */\n      if (c == '?')\n        {\n          var->conditional = 1;\n          c = *p++;\n        }\n\n      /* If we found = we're done!  */\n      if (c == '=')\n        {\n          if (!end)\n            end = start;\n          var->flavor = f_recursive; /* = */\n          break;\n        }\n\n      if (c == ':')\n        {\n          if (!end)\n            end = start;\n\n          /* We need to distinguish :=, ::=, and :::=, versus : outside of an\n             assignment (which means this is not a variable definition).  */\n          c = *p++;\n          if (c == '=')\n            {\n              var->flavor = f_simple; /* := */\n              break;\n            }\n          if (c == ':')\n            {\n              c = *p++;\n              if (c == '=')\n                {\n                  var->flavor = f_simple; /* ::= */\n                  break;\n                }\n              if (c == ':' && *p++ == '=')\n                {\n                  var->flavor = f_expand; /* :::= */\n                  break;\n                }\n            }\n          return NULL;\n        }\n\n      /* See if it's one of the other two-byte operators.  */\n      if (*p == '=')\n        {\n          switch (c)\n            {\n            case '+':\n              var->flavor = f_append; /* += */\n              break;\n            case '!':\n              var->flavor = f_shell; /* != */\n              break;\n            default:\n              goto other;\n            }\n\n          if (!end)\n            end = start;\n          ++p;\n          break;\n        }\n\n    other:\n      /* We found a char which is not part of an assignment operator.\n         If we've seen whitespace, then we know this is not a variable\n         assignment since variable names cannot contain whitespace.  */\n      if (end)\n        return NULL;\n\n      if (c == '$')\n        p = skip_reference (p);\n\n      var->conditional = 0;\n    }\n\n  /* We found a valid variable assignment: END points to the char after the\n     end of the variable name and P points to the char after the =.  */\n  var->length = (unsigned int) (end - var->name);\n  var->value = next_token (p);\n\n  return (char *)p;\n}\n\f\n/* Try to interpret LINE (a null-terminated string) as a variable definition.\n\n   If LINE was recognized as a variable definition, a pointer to its 'struct\n   variable' is returned.  If LINE is not a variable definition, NULL is\n   returned.  */\n\nstruct variable *\nassign_variable_definition (struct variable *v, const char *line)\n{\n  char *name;\n\n  if (!parse_variable_definition (line, v))\n    return NULL;\n\n  /* Expand the name, so \"$(foo)bar = baz\" works.  */\n  name = alloca (v->length + 1);\n  memcpy (name, v->name, v->length);\n  name[v->length] = '\\0';\n  v->name = allocated_expand_string (name);\n\n  if (v->name[0] == '\\0')\n    O (fatal, &v->fileinfo, _(\"empty variable name\"));\n\n  return v;\n}\n\f\n/* Try to interpret LINE (a null-terminated string) as a variable definition.\n\n   ORIGIN may be o_file, o_override, o_env, o_env_override,\n   or o_command specifying that the variable definition comes\n   from a makefile, an override directive, the environment with\n   or without the -e switch, or the command line.\n\n   See the comments for assign_variable_definition().\n\n   If LINE was recognized as a variable definition, a pointer to its 'struct\n   variable' is returned.  If LINE is not a variable definition, NULL is\n   returned.  */\n\nstruct variable *\ntry_variable_definition (const floc *flocp, const char *line,\n                         enum variable_origin origin, enum variable_scope scope)\n{\n  struct variable v;\n  struct variable *vp;\n\n  if (flocp != 0)\n    v.fileinfo = *flocp;\n  else\n    v.fileinfo.filenm = 0;\n\n  if (!assign_variable_definition (&v, line))\n    return 0;\n\n  vp = do_variable_definition (flocp, v.name, v.value, origin, v.flavor,\n                               v.conditional, scope);\n\n  free (v.name);\n\n  return vp;\n}\n\n/* These variables are internal to make, and so considered \"defined\" for the\n   purposes of warn_undefined even if they are not really defined.  */\n\nstruct defined_vars\n  {\n    const char *name;\n    size_t len;\n  };\n\nstatic const struct defined_vars defined_vars[] = {\n  { STRING_SIZE_TUPLE (\"MAKECMDGOALS\") },\n  { STRING_SIZE_TUPLE (\"MAKE_RESTARTS\") },\n  { STRING_SIZE_TUPLE (\"MAKE_TERMOUT\") },\n  { STRING_SIZE_TUPLE (\"MAKE_TERMERR\") },\n  { STRING_SIZE_TUPLE (\"MAKEOVERRIDES\") },\n  { STRING_SIZE_TUPLE (\".DEFAULT\") },\n  { STRING_SIZE_TUPLE (\"-*-command-variables-*-\") },\n  { STRING_SIZE_TUPLE (\"-*-eval-flags-*-\") },\n  { STRING_SIZE_TUPLE (\"VPATH\") },\n  { STRING_SIZE_TUPLE (\"GPATH\") },\n  { STRING_SIZE_TUPLE (WARNINGS_NAME) },\n  { STRING_SIZE_TUPLE (GNUMAKEFLAGS_NAME) },\n  { NULL, 0 }\n};\n\nvoid\nwarn_undefined (const char *name, size_t len)\n{\n  if (warn_check (wt_undefined_var))\n    {\n      const struct defined_vars *dp;\n      for (dp = defined_vars; dp->name != NULL; ++dp)\n        if (dp->len == len && memcmp (dp->name, name, len) == 0)\n          return;\n\n      warning (wt_undefined_var, reading_file,\n               ONS (format, 0, _(\"reference to undefined variable '%.*s'\"),\n                    (int)len, name));\n    }\n}\n\nstatic void\nset_env_override (const void *item, void *arg UNUSED)\n{\n  struct variable *v = (struct variable *)item;\n  enum variable_origin old = env_overrides ? o_env : o_env_override;\n  enum variable_origin new = env_overrides ? o_env_override : o_env;\n\n  if (v->origin == old)\n    v->origin = new;\n}\n\nvoid\nreset_env_override ()\n{\n  hash_map_arg (&global_variable_set.table, set_env_override, NULL);\n}\n\f\n/* Print information for variable V, prefixing it with PREFIX.  */\n\nstatic void\nprint_variable (const void *item, void *arg)\n{\n  const struct variable *v = item;\n  const char *prefix = arg;\n  const char *origin;\n\n  switch (v->origin)\n    {\n    case o_automatic:\n      origin = _(\"automatic\");\n      break;\n    case o_default:\n      origin = _(\"default\");\n      break;\n    case o_env:\n      origin = _(\"environment\");\n      break;\n    case o_file:\n      origin = _(\"makefile\");\n      break;\n    case o_env_override:\n      origin = _(\"environment under -e\");\n      break;\n    case o_command:\n      origin = _(\"command line\");\n      break;\n    case o_override:\n      origin = _(\"'override' directive\");\n      break;\n    case o_invalid:\n      abort ();\n    }\n  fputs (\"# \", stdout);\n  fputs (origin, stdout);\n  if (v->private_var)\n    fputs (\" private\", stdout);\n  if (v->fileinfo.filenm)\n    printf (_(\" (from '%s', line %lu)\"),\n            v->fileinfo.filenm, v->fileinfo.lineno + v->fileinfo.offset);\n  putchar ('\\n');\n  fputs (prefix, stdout);\n\n  /* Is this a 'define'?  */\n  if (v->recursive && strchr (v->value, '\\n') != 0)\n    printf (\"define %s\\n%s\\nendef\\n\", v->name, v->value);\n  else\n    {\n      char *p;\n\n      printf (\"%s %s= \", v->name, v->recursive ? v->append ? \"+\" : \"\" : \":\");\n\n      /* Check if the value is just whitespace.  */\n      p = next_token (v->value);\n      if (p != v->value && *p == '\\0')\n        /* All whitespace.  */\n        printf (\"$(subst ,,%s)\", v->value);\n      else if (v->recursive)\n        fputs (v->value, stdout);\n      else\n        /* Double up dollar signs.  */\n        for (p = v->value; *p != '\\0'; ++p)\n          {\n            if (*p == '$')\n              putchar ('$');\n            putchar (*p);\n          }\n      putchar ('\\n');\n    }\n}\n\nstatic void\nprint_auto_variable (const void *item, void *arg)\n{\n  const struct variable *v = item;\n\n  if (v->origin == o_automatic)\n    print_variable (item, arg);\n}\n\nstatic void\nprint_noauto_variable (const void *item, void *arg)\n{\n  const struct variable *v = item;\n\n  if (v->origin != o_automatic)\n    print_variable (item, arg);\n}\n\n/* Print all the variables in SET.  PREFIX is printed before\n   the actual variable definitions (everything else is comments).  */\n\nstatic void\nprint_variable_set (struct variable_set *set, const char *prefix, int pauto)\n{\n  hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable),\n                (void *)prefix);\n\n  fputs (_(\"# variable set hash-table stats:\\n\"), stdout);\n  fputs (\"# \", stdout);\n  hash_print_stats (&set->table, stdout);\n  putc ('\\n', stdout);\n}\n\n/* Print the data base of variables.  */\n\nvoid\nprint_variable_data_base (void)\n{\n  puts (_(\"\\n# Variables\\n\"));\n\n  print_variable_set (&global_variable_set, \"\", 0);\n\n  puts (_(\"\\n# Pattern-specific Variable Values\"));\n\n  {\n    struct pattern_var *p;\n    unsigned int rules = 0;\n\n    for (p = pattern_vars; p != 0; p = p->next)\n      {\n        ++rules;\n        printf (\"\\n%s :\\n\", p->target);\n        print_variable (&p->variable, (void *)\"# \");\n      }\n\n    if (rules == 0)\n      puts (_(\"\\n# No pattern-specific variable values.\"));\n    else\n      printf (_(\"\\n# %u pattern-specific variable values\"), rules);\n  }\n}\n\n\n/* Print all the local variables of FILE.  */\n\nvoid\nprint_file_variables (const struct file *file)\n{\n  if (file->variables != 0)\n    print_variable_set (file->variables->set, \"# \", 1);\n}\n\nvoid\nprint_target_variables (const struct file *file)\n{\n  if (file->variables != 0)\n    {\n      size_t l = strlen (file->name);\n      char *t = alloca (l + 3);\n\n      memcpy (t, file->name, l);\n      t[l] = ':';\n      t[l+1] = ' ';\n      t[l+2] = '\\0';\n\n      hash_map_arg (&file->variables->set->table, print_noauto_variable, t);\n    }\n}\n\n#if MK_OS_W32\nvoid\nsync_Path_environment ()\n{\n  static char *environ_path = NULL;\n  char *oldpath = environ_path;\n  char *path = allocated_expand_string (\"PATH=$(PATH)\");\n\n  if (!path)\n    return;\n\n  /* Convert the value of PATH into something Windows32 world can grok.\n    Note: convert_Path_to_windows32 must see only the value of PATH,\n    and see it from its first character, to do its tricky job.  */\n  convert_Path_to_windows32 (path + CSTRLEN (\"PATH=\"), ';');\n\n  environ_path = path;\n  putenv (environ_path);\n  free (oldpath);\n}\n#endif\n"
  },
  {
    "path": "src/variable.h",
    "content": "/* Definitions for using variables in GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"hash.h\"\n\nstruct file;\n\n/* Codes in a variable definition saying where the definition came from.\n   Increasing numeric values signify less-overridable definitions.  */\nenum variable_origin\n  {\n    o_default,          /* Variable from the default set.  */\n    o_env,              /* Variable from environment.  */\n    o_file,             /* Variable given in a makefile.  */\n    o_env_override,     /* Variable from environment, if -e.  */\n    o_command,          /* Variable given by user.  */\n    o_override,         /* Variable from an 'override' directive.  */\n    o_automatic,        /* Automatic variable -- cannot be set.  */\n    o_invalid           /* Core dump time.  */\n  };\n\nenum variable_flavor\n  {\n    f_bogus,            /* Bogus (error) */\n    f_simple,           /* Simple definition (:= or ::=) */\n    f_recursive,        /* Recursive definition (=) */\n    f_expand,           /* POSIX :::= assignment */\n    f_append,           /* Appending definition (+=) */\n    f_shell,            /* Shell assignment (!=) */\n    f_append_value      /* Append unexpanded value */\n  };\n\nenum variable_export\n{\n    v_default = 0,      /* Decide in target_environment.  */\n    v_export,           /* Export this variable.  */\n    v_noexport,         /* Don't export this variable.  */\n    v_ifset             /* Export it if it has a non-default value.  */\n};\n\nenum variable_scope\n{\n    s_global = 0,       /* Global variable.  */\n    s_target,           /* Target-specific variable.  */\n    s_pattern           /* Pattern-specific variable.  */\n};\n\n/* Structure that represents one variable definition.\n   Each bucket of the hash table is a chain of these,\n   chained through 'next'.  */\n\n#define EXP_COUNT_BITS  15      /* This gets all the bitfields into 32 bits */\n#define EXP_COUNT_MAX   ((1<<EXP_COUNT_BITS)-1)\n\nstruct variable\n  {\n    char *name;                 /* Variable name.  */\n    char *value;                /* Variable value.  */\n    floc fileinfo;              /* Where the variable was defined.  */\n    unsigned int length;        /* strlen (name) */\n    unsigned int recursive:1;   /* Gets recursively re-evaluated.  */\n    unsigned int append:1;      /* Nonzero if an appending target-specific\n                                   variable.  */\n    unsigned int conditional:1; /* Nonzero if set with a ?=. */\n    unsigned int per_target:1;  /* Nonzero if a target-specific variable.  */\n    unsigned int special:1;     /* Nonzero if this is a special variable.  */\n    unsigned int exportable:1;  /* Nonzero if the variable _could_ be\n                                   exported.  */\n    unsigned int expanding:1;   /* Nonzero if currently being expanded.  */\n    unsigned int private_var:1; /* Nonzero avoids inheritance of this\n                                   target-specific variable.  */\n    unsigned int exp_count:EXP_COUNT_BITS;\n                                /* If >1, allow this many self-referential\n                                   expansions.  */\n    enum variable_flavor\n      flavor ENUM_BITFIELD (3); /* Variable flavor.  */\n    enum variable_origin\n      origin ENUM_BITFIELD (3); /* Variable origin.  */\n    enum variable_export\n      export ENUM_BITFIELD (2); /* Export control. */\n  };\n\n/* Structure that represents a variable set.  */\n\nstruct variable_set\n  {\n    struct hash_table table;    /* Hash table of variables.  */\n  };\n\n/* Structure that represents a list of variable sets.  */\n\nstruct variable_set_list\n  {\n    struct variable_set_list *next;     /* Link in the chain.  */\n    struct variable_set *set;           /* Variable set.  */\n    int next_is_parent;                 /* True if next is a parent target.  */\n  };\n\n/* Structure used for pattern-specific variables.  */\n\nstruct pattern_var\n  {\n    struct pattern_var *next;\n    const char *suffix;\n    const char *target;\n    size_t len;\n    struct variable variable;\n  };\n\nextern unsigned long long env_recursion;\nextern char *variable_buffer;\nextern struct variable_set_list *current_variable_set_list;\nextern struct variable *default_goal_var;\nextern struct variable shell_var;\n\n/* expand.c */\nchar *initialize_variable_output (void);\nchar *variable_buffer_output (char *ptr, const char *string, size_t length);\nvoid install_variable_buffer (char **bufp, size_t *lenp);\nvoid restore_variable_buffer (char *buf, size_t len);\nchar *swap_variable_buffer (char *buf, size_t len);\n\nchar *expand_string_buf (char *buf, const char *string, size_t length);\n#define expand_string(s) expand_string_buf (NULL, (s), SIZE_MAX)\nchar *expand_string_for_file (const char *string, struct file *file);\nchar *allocated_expand_string_for_file (const char *line, struct file *file);\n#define allocated_expand_string(s) allocated_expand_string_for_file ((s), NULL)\nchar *expand_argument (const char *str, const char *end);\nchar *recursively_expand_for_file (struct variable *v, struct file *file);\n#define recursively_expand(v) recursively_expand_for_file ((v), NULL)\n\nchar *expand_variable_output (char *ptr, const char *name, size_t length);\nchar *expand_variable_buf (char *buf, const char *name, size_t length);\n#define expand_variable(n,l) expand_variable_buf (NULL, (n), (l));\nchar *allocated_expand_variable (const char *name, size_t length);\nchar *allocated_expand_variable_for_file (const char *name, size_t length, struct file *file);\n\n/* function.c */\nint handle_function (char **op, const char **stringp);\nint pattern_matches (const char *pattern, const char *percent, const char *str);\nchar *subst_expand (char *o, const char *text, const char *subst,\n                    const char *replace, size_t slen, size_t rlen,\n                    int by_word);\nchar *patsubst_expand_pat (char *o, const char *text, const char *pattern,\n                           const char *replace, const char *pattern_percent,\n                           const char *replace_percent);\nchar *patsubst_expand (char *o, const char *text, char *pattern, char *replace);\nchar *func_shell_base (char *o, char **argv, int trim_newlines);\nvoid shell_completed (int exit_code, int exit_sig);\n\n/* variable.c */\nstruct variable_set_list *create_new_variable_set (void);\nvoid free_variable_set (struct variable_set_list *);\nstruct variable_set_list *push_new_variable_scope (void);\nvoid pop_variable_scope (void);\nvoid install_file_context (struct file *file, struct variable_set_list **oldlist, const floc **oldfloc);\nvoid restore_file_context (struct variable_set_list *oldlist, const floc *oldfloc);\nvoid define_automatic_variables (void);\nvoid initialize_file_variables (struct file *file, int reading);\nvoid print_file_variables (const struct file *file);\nvoid print_target_variables (const struct file *file);\nvoid merge_variable_set_lists (struct variable_set_list **to_list,\n                               struct variable_set_list *from_list);\nstruct variable *do_variable_definition (const floc *flocp,\n                                         const char *name, const char *value,\n                                         enum variable_origin origin,\n                                         enum variable_flavor flavor,\n                                         int conditional,\n                                         enum variable_scope scope);\nchar *parse_variable_definition (const char *line,\n                                 struct variable *v);\nstruct variable *assign_variable_definition (struct variable *v, const char *line);\nstruct variable *try_variable_definition (const floc *flocp, const char *line,\n                                          enum variable_origin origin,\n                                          enum variable_scope scope);\nvoid init_hash_global_variable_set (void);\nvoid hash_init_function_table (void);\nvoid define_new_function(const floc *flocp, const char *name,\n                         unsigned int min, unsigned int max, unsigned int flags,\n                         gmk_func_ptr func);\n\nstruct variable *lookup_variable (const char *name, size_t length);\nstruct variable *lookup_variable_for_file (const char *name, size_t length,\n                                           struct file *file);\nstruct variable *lookup_variable_in_set (const char *name, size_t length,\n                                         const struct variable_set *set);\n\nstruct variable *define_variable_in_set (const char *name, size_t length,\n                                         const char *value,\n                                         enum variable_origin origin,\n                                         int recursive,\n                                         struct variable_set *set,\n                                         const floc *flocp);\nvoid warn_undefined (const char* name, size_t length);\nvoid reset_env_override (void);\n\n/* Define a variable in the current variable set.  */\n\n#define define_variable(n,l,v,o,r) \\\n          define_variable_in_set((n),(l),(v),(o),(r),\\\n                                 current_variable_set_list->set,NILF)\n\n/* Define a variable with a constant name in the current variable set.  */\n\n#define define_variable_cname(n,v,o,r) \\\n          define_variable_in_set((n),(sizeof (n) - 1),(v),(o),(r),\\\n                                 current_variable_set_list->set,NILF)\n\n/* Define a variable with a location in the current variable set.  */\n\n#define define_variable_loc(n,l,v,o,r,f) \\\n          define_variable_in_set((n),(l),(v),(o),(r),\\\n                                 current_variable_set_list->set,(f))\n\n/* Define a variable with a location in the global variable set.  */\n\n#define define_variable_global(n,l,v,o,r,f) \\\n          define_variable_in_set((n),(l),(v),(o),(r),NULL,(f))\n\n/* Define a variable in FILE's variable set.  */\n\n#define define_variable_for_file(n,l,v,o,r,f) \\\n          define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF)\n\nvoid undefine_variable_in_set (const floc *flocp,\n                               const char *name, size_t length,\n                               enum variable_origin origin,\n                               struct variable_set *set);\n\n/* Remove variable from the current variable set. */\n\n#define undefine_variable_global(f,n,l,o) \\\n          undefine_variable_in_set((f),(n),(l),(o),NULL)\n\nchar **target_environment (struct file *file, int recursive);\n\nstruct pattern_var *create_pattern_var (const char *target,\n                                        const char *suffix);\n"
  },
  {
    "path": "src/version.c",
    "content": "/* Record version and build host architecture for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* We use <config.h> instead of \"config.h\" so that a compilation\n   using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h\n   (which it would do because makeint.h was found in $srcdir).  */\n#include <config.h>\n\n#ifndef MAKE_HOST\n# define MAKE_HOST \"unknown\"\n#endif\n\nconst char *version_string = PACKAGE_VERSION;\nconst char *make_host = MAKE_HOST;\n\f\n/*\n  Local variables:\n  version-control: never\n  End:\n */\n"
  },
  {
    "path": "src/vms_exit.c",
    "content": "/* vms_exit.c\n *\n * Wrapper for the VMS exit() command to translate UNIX codes to be\n * encoded for POSIX, but also have VMS severity levels.\n * The posix_exit() variant only sets a severity level for status code 1.\n *\n * Author: John E. Malmberg\n */\n\n/* Copyright (C) 2014-2024 Free Software Foundation, Inc.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Per copyright assignment agreement with the Free Software Foundation\n   this software may be available under under other license agreements\n   and copyrights. */\n\n#include <makeint.h>\n\n#include <stsdef.h>\nvoid\ndecc$exit (int status);\n#ifndef C_FACILITY_NO\n# define C_FACILITY_NO 0x350000\n#endif\n\n/* Lowest legal non-success VMS exit code is 8 */\n/* GNU Make only defines codes 0, 1, 2 */\n/* So assume any exit code > 8 is a VMS exit code */\n\n#ifndef MAX_EXPECTED_EXIT_CODE\n# define MAX_EXPECTED_EXIT_CODE 7\n#endif\n\n/* Build a Posix Exit with VMS severity */\nvoid\nvms_exit (int status)\n{\n  int vms_status;\n  /* Fake the __posix_exit with severity added */\n  /* Undocumented correct way to do this. */\n  vms_status = 0;\n\n  /* The default DECC definition is not compatible with doing a POSIX_EXIT */\n  /* So fix it. */\n  if (status == EXIT_FAILURE)\n    status = MAKE_FAILURE;\n\n  /* Trivial case exit success */\n  if (status == 0)\n    decc$exit (STS$K_SUCCESS);\n\n  /* Is this a VMS status then just take it */\n  if (status > MAX_EXPECTED_EXIT_CODE)\n    {\n      /* Make sure that the message inhibit is set since message has */\n      /* already been displayed. */\n      vms_status = status | STS$M_INHIB_MSG;\n      decc$exit (vms_status);\n    }\n\n  /* Unix status codes are limited to 1 byte, so anything larger */\n  /* is a probably a VMS exit code and needs to be passed through */\n  /* A lower value can be set for a macro. */\n  /* Status 0 is always passed through as it is converted to SS$_NORMAL */\n  /* Always set the message inhibit bit */\n  vms_status = C_FACILITY_NO | 0xA000 | STS$M_INHIB_MSG;\n  vms_status |= (status << 3);\n\n  /* STS$K_ERROR is for status that stops makefile that a simple */\n  /* Rerun of the makefile will not fix. */\n\n  if (status == MAKE_FAILURE)\n    vms_status |= STS$K_ERROR;\n  else if (status == MAKE_TROUBLE)\n    {\n      /* Make trouble is for when make was told to do nothing and */\n      /* found that a target was not up to date.  Since a second */\n      /* of make will produce the same condition, this is of */\n      /* Error severity */\n      vms_status |= STS$K_ERROR;\n    }\n  decc$exit (vms_status);\n}\n"
  },
  {
    "path": "src/vms_export_symbol.c",
    "content": "/* File: vms_export_symbol.c\n *\n * Some programs need special environment variables deported as DCL\n * DCL symbols.\n */\n\n/* Copyright (C) 2014-2024 Free Software Foundation, Inc.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Per copyright assignment agreement with the Free Software Foundation\n   this software may be available under under other license agreements\n   and copyrights. */\n\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <errno.h>\n\n#include <descrip.h>\n#include <stsdef.h>\n#include <ssdef.h>\n#include <unixlib.h>\n#include <libclidef.h>\n\n#pragma member_alignment save\n#pragma nomember_alignment longword\nstruct item_list_3\n{\n  unsigned short len;\n  unsigned short code;\n  void * bufadr;\n  unsigned short * retlen;\n};\n\n\n#pragma member_alignment\n\nint\nLIB$GET_SYMBOL (const struct dsc$descriptor_s * symbol,\n                struct dsc$descriptor_s * value,\n                unsigned short * value_len,\n                const unsigned long * table);\n\nint\nLIB$SET_SYMBOL (const struct dsc$descriptor_s * symbol,\n                const struct dsc$descriptor_s * value,\n                const unsigned long * table);\n\nint\nLIB$DELETE_SYMBOL (const struct dsc$descriptor_s * symbol,\n                   const unsigned long * table);\n\n#define MAX_DCL_SYMBOL_LEN (255)\n#if __CRTL_VER >= 70302000 && !defined(__VAX)\n# define MAX_DCL_SYMBOL_VALUE (8192)\n#else\n# define MAX_DCL_SYMBOL_VALUE (1024)\n#endif\n\nstruct dcl_symbol\n{\n  struct dcl_symbol * link;\n  struct dsc$descriptor_s name_desc;\n  struct dsc$descriptor_s value_desc;\n  char name[MAX_DCL_SYMBOL_LEN + 1];    /* + 1 byte for null terminator */\n  char value[MAX_DCL_SYMBOL_VALUE +1];  /* + 1 byte for null terminator */\n  char pad[3]; /* Pad structure to longword alignment */\n};\n\nstatic struct dcl_symbol * vms_dcl_symbol_head = NULL;\n\n/* Restore symbol state to original condition. */\nstatic unsigned long\nclear_dcl_symbol (struct dcl_symbol * symbol)\n{\n\n  const unsigned long symtbl = LIB$K_CLI_LOCAL_SYM;\n  int status;\n\n  if (symbol->value_desc.dsc$w_length == (unsigned short)-1)\n    status = LIB$DELETE_SYMBOL (&symbol->name_desc, &symtbl);\n  else\n    status = LIB$SET_SYMBOL (&symbol->name_desc,\n                             &symbol->value_desc, &symtbl);\n  return status;\n}\n\n\n/* Restore all exported symbols to their original conditions */\nstatic void\nclear_exported_symbols (void)\n{\n\n  struct dcl_symbol * symbol;\n\n  symbol = vms_dcl_symbol_head;\n\n  /* Walk the list of symbols.  This is done during exit,\n   * so no need to free memory.\n   */\n  while (symbol != NULL)\n  {\n    clear_dcl_symbol (symbol);\n    symbol = symbol->link;\n  }\n\n}\n\n\n/* Restore the symbol back to the original value\n * symbol name is either a plain name or of the form \"symbol=name\" where\n * the name portion is ignored.\n */\nvoid\nvms_restore_symbol (const char * string)\n{\n\n  struct dcl_symbol * symbol;\n  char name[MAX_DCL_SYMBOL_LEN + 1];\n  int status;\n  char * value;\n  int name_len;\n\n  symbol = vms_dcl_symbol_head;\n\n  /* Isolate the name from the value */\n  value = strchr (string, '=');\n  if (value != NULL)\n    {\n      /* Copy the name from the string */\n      name_len = (value - string);\n    }\n  else\n    name_len = strlen (string);\n\n  if (name_len > MAX_DCL_SYMBOL_LEN)\n    name_len = MAX_DCL_SYMBOL_LEN;\n\n  strncpy (name, string, name_len);\n  name[name_len] = 0;\n\n  /* Walk the list of symbols.  The saved symbol is not freed\n   * symbols are likely to be overwritten multiple times, so this\n   * saves time in saving them each time.\n   */\n  while (symbol != NULL)\n    {\n      int result;\n      result = strcmp (symbol->name, name);\n      if (result == 0)\n        {\n          clear_dcl_symbol (symbol);\n          break;\n        }\n      symbol = symbol->link;\n    }\n}\n\nint\nvms_export_dcl_symbol (const char * name, const char * value)\n{\n\n  struct dcl_symbol * symbol;\n  struct dcl_symbol * next;\n  struct dcl_symbol * link;\n  int found;\n  const unsigned long symtbl = LIB$K_CLI_LOCAL_SYM;\n  struct dsc$descriptor_s value_desc;\n  int string_len;\n  int status;\n  char new_value[MAX_DCL_SYMBOL_VALUE + 1];\n  char * dollarp;\n\n  next = vms_dcl_symbol_head;\n  link = vms_dcl_symbol_head;\n\n  /* Is symbol already exported? */\n  found = 0;\n  while ((found == 0) && (link != NULL))\n    {\n      int x;\n      found = !strncasecmp (link->name, name, MAX_DCL_SYMBOL_LEN);\n      if (found)\n        symbol = link;\n      next = link;\n      link = link->link;\n    }\n\n  /* New symbol, set it up */\n  if (found == 0)\n    {\n      symbol = malloc (sizeof (struct dcl_symbol));\n      if (symbol == NULL)\n        return SS$_INSFMEM;\n\n      /* Construct the symbol descriptor, used for both saving\n       * the old symbol and creating the new symbol.\n       */\n      symbol->name_desc.dsc$w_length = strlen (name);\n      if (symbol->name_desc.dsc$w_length > MAX_DCL_SYMBOL_LEN)\n        symbol->name_desc.dsc$w_length = MAX_DCL_SYMBOL_LEN;\n\n      strncpy (symbol->name, name, symbol->name_desc.dsc$w_length);\n      symbol->name[symbol->name_desc.dsc$w_length] = 0;\n      symbol->name_desc.dsc$a_pointer = symbol->name;\n      symbol->name_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n      symbol->name_desc.dsc$b_class = DSC$K_CLASS_S;\n\n      /* construct the value descriptor, used only for saving\n       * the old symbol.\n       */\n      symbol->value_desc.dsc$a_pointer = symbol->value;\n      symbol->value_desc.dsc$w_length = MAX_DCL_SYMBOL_VALUE;\n      symbol->value_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n      symbol->value_desc.dsc$b_class = DSC$K_CLASS_S;\n    }\n\n  if (found == 0)\n    {\n      unsigned long old_symtbl;\n      unsigned short value_len;\n\n      /* Look up the symbol */\n      status = LIB$GET_SYMBOL (&symbol->name_desc, &symbol->value_desc,\n                               &value_len, &old_symtbl);\n      if (!$VMS_STATUS_SUCCESS (status))\n        value_len = (unsigned short)-1;\n      else if (old_symtbl != symtbl)\n        value_len = (unsigned short)-1;\n\n      symbol->value_desc.dsc$w_length = value_len;\n\n      /* Store it away */\n      if (value_len != (unsigned short) -1)\n        symbol->value[value_len] = 0;\n\n      /* Make sure atexit scheduled */\n      if (vms_dcl_symbol_head == NULL)\n        {\n          vms_dcl_symbol_head = symbol;\n          atexit (clear_exported_symbols);\n        }\n      else\n        {\n          /* Extend the chain */\n          next->link = symbol;\n        }\n    }\n\n  /* Create or replace a symbol */\n  value_desc.dsc$a_pointer = new_value;\n  string_len = strlen (value);\n  if (string_len > MAX_DCL_SYMBOL_VALUE)\n    string_len = MAX_DCL_SYMBOL_VALUE;\n\n  strncpy (new_value, value, string_len);\n  new_value[string_len] = 0;\n\n  /* Special handling for GNU Make.  GNU Make doubles the dollar signs\n   * in environment variables read in from getenv().  Make exports symbols\n   * with the dollar signs already doubled.  So all $$ must be converted\n   * back to $.\n   * If the first $ is not doubled, then do not convert at all.\n   */\n  dollarp = strchr (new_value, '$');\n  while (dollarp && dollarp[1] == '$')\n    {\n      int left;\n      dollarp++;\n      left = string_len - (dollarp - new_value - 1);\n      string_len--;\n      if (left > 0)\n        {\n          memmove (dollarp, &dollarp[1], left);\n          dollarp = strchr (&dollarp[1], '$');\n        }\n      else\n        {\n          /* Ended with $$, simple case */\n          dollarp[1] = 0;\n          break;\n        }\n    }\n  value_desc.dsc$w_length = string_len;\n  value_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n  value_desc.dsc$b_class = DSC$K_CLASS_S;\n  status = LIB$SET_SYMBOL (&symbol->name_desc, &value_desc, &symtbl);\n  return status;\n}\n\n/* export a DCL symbol using a string in the same syntax as putenv */\nint\nvms_putenv_symbol (const char * string)\n{\n\n  char name[MAX_DCL_SYMBOL_LEN + 1];\n  int status;\n  char * value;\n  int name_len;\n\n  /* Isolate the name from the value */\n  value = strchr (string, '=');\n  if (value == NULL)\n    {\n      errno = EINVAL;\n      return -1;\n    }\n\n  /* Copy the name from the string */\n  name_len = (value - string);\n  if (name_len > MAX_DCL_SYMBOL_LEN)\n    name_len = MAX_DCL_SYMBOL_LEN;\n\n  strncpy (name, string, name_len);\n  name[name_len] = 0;\n\n  /* Skip past the \"=\" */\n  value++;\n\n  /* Export the symbol */\n  status = vms_export_dcl_symbol (name, value);\n\n  /* Convert the error to Unix format */\n  if (!$VMS_STATUS_SUCCESS (status))\n    {\n      errno = EVMSERR;\n      vaxc$errno = status;\n      return -1;\n    }\n  return 0;\n}\n\n#if __CRTL_VER >= 70301000\n# define transpath_parm transpath\n#else\nstatic char transpath[MAX_DCL_SYMBOL_VALUE];\n#endif\n\n/* Helper callback routine for converting Unix paths to VMS */\nstatic int\nto_vms_action (char * vms_spec, int flag, char * transpath_parm)\n{\n  strncpy (transpath, vms_spec, MAX_DCL_SYMBOL_VALUE - 1);\n  transpath[MAX_DCL_SYMBOL_VALUE - 1] = 0;\n  return 0;\n}\n\n#ifdef __DECC\n# pragma message save\n  /* Undocumented extra parameter use triggers a ptrmismatch warning */\n# pragma message disable ptrmismatch\n#endif\n\n/* Create a foreign command only visible to children */\nint\ncreate_foreign_command (const char * command, const char * image)\n{\n  char vms_command[MAX_DCL_SYMBOL_VALUE + 1];\n  int status;\n\n  vms_command[0] = '$';\n  vms_command[1] = 0;\n  if (image[0] == '/')\n    {\n#if __CRTL_VER >= 70301000\n      /* Current decc$to_vms is reentrant */\n      decc$to_vms (image, to_vms_action, 0, 1, &vms_command[1]);\n#else\n      /* Older decc$to_vms is not reentrant */\n      decc$to_vms (image, to_vms_action, 0, 1);\n      strncpy (&vms_command[1], transpath, MAX_DCL_SYMBOL_VALUE - 1);\n      vms_command[MAX_DCL_SYMBOL_VALUE] = 0;\n#endif\n    }\n  else\n    {\n      strncpy (&vms_command[1], image, MAX_DCL_SYMBOL_VALUE - 1);\n      vms_command[MAX_DCL_SYMBOL_VALUE] = 0;\n    }\n  status = vms_export_dcl_symbol (command, vms_command);\n\n  return status;\n}\n#ifdef __DECC\n# pragma message restore\n#endif\n\n\n#ifdef DEBUG\n\nint\nmain(int argc, char ** argv, char **env)\n{\n\n  char value[MAX_DCL_SYMBOL_VALUE +1];\n  int status = 0;\n  int putenv_status;\n  int vms_status;\n  struct dsc$descriptor_s name_desc;\n  struct dsc$descriptor_s value_desc;\n  const unsigned long symtbl = LIB$K_CLI_LOCAL_SYM;\n  unsigned short value_len;\n  unsigned long old_symtbl;\n  int result;\n  const char * vms_command = \"vms_export_symbol\";\n  const char * vms_image = \"test_image.exe\";\n  const char * vms_symbol1 = \"test_symbol1\";\n  const char * value1 = \"test_value1\";\n  const char * vms_symbol2 = \"test_symbol2\";\n  const char * putenv_string = \"test_symbol2=value2\";\n  const char * value2 = \"value2\";\n\n  /* Test creating a foreign command */\n  vms_status = create_foreign_command (vms_command, vms_image);\n  if (!$VMS_STATUS_SUCCESS (vms_status))\n    {\n      printf(\"Create foreign command failed: %d\\n\", vms_status);\n      status = 1;\n    }\n\n  name_desc.dsc$a_pointer = (char *)vms_command;\n  name_desc.dsc$w_length = strlen (vms_command);\n  name_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n  name_desc.dsc$b_class = DSC$K_CLASS_S;\n\n  value_desc.dsc$a_pointer = value;\n  value_desc.dsc$w_length = MAX_DCL_SYMBOL_VALUE;\n  value_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n  value_desc.dsc$b_class = DSC$K_CLASS_S;\n\n  vms_status = LIB$GET_SYMBOL (&name_desc, &value_desc,\n                               &value_len, &old_symtbl);\n  if (!$VMS_STATUS_SUCCESS (vms_status))\n    {\n      printf (\"lib$get_symbol for command failed: %d\\n\", vms_status);\n      status = 1;\n    }\n\n  value[value_len] = 0;\n  result = strncasecmp (&value[1], vms_image, value_len - 1);\n  if (result != 0)\n    {\n      printf (\"create_foreign_command failed!  expected '%s', got '%s'\\n\",\n              vms_image, &value[1]);\n      status = 1;\n    }\n\n  /* Test exporting a symbol */\n  vms_status = vms_export_dcl_symbol (vms_symbol1, value1);\n  if (!$VMS_STATUS_SUCCESS (vms_status))\n    {\n      printf (\"vms_export_dcl_symbol for command failed: %d\\n\", vms_status);\n      status = 1;\n    }\n\n  name_desc.dsc$a_pointer = (char *)vms_symbol1;\n  name_desc.dsc$w_length = strlen (vms_symbol1);\n  vms_status = LIB$GET_SYMBOL(&name_desc, &value_desc,\n                              &value_len, &old_symtbl);\n  if (!$VMS_STATUS_SUCCESS(vms_status))\n    {\n      printf (\"lib$get_symbol for command failed: %d\\n\", vms_status);\n      status = 1;\n    }\n\n  value[value_len] = 0;\n  result = strncmp (value, value1, value_len);\n  if (result != 0)\n    {\n      printf (\"vms_export_dcl_symbol failed!  expected '%s', got '%s'\\n\",\n              value1, value);\n      status = 1;\n    }\n\n  /* Test putenv for DCL symbols */\n  putenv_status = vms_putenv_symbol (putenv_string);\n  if (putenv_status != 0)\n    {\n      perror (\"vms_putenv_symbol\");\n      status = 1;\n    }\n\n  name_desc.dsc$a_pointer = (char *)vms_symbol2;\n  name_desc.dsc$w_length = strlen(vms_symbol2);\n  vms_status = LIB$GET_SYMBOL (&name_desc, &value_desc,\n                               &value_len, &old_symtbl);\n  if (!$VMS_STATUS_SUCCESS (vms_status))\n    {\n      printf (\"lib$get_symbol for command failed: %d\\n\", vms_status);\n      status = 1;\n    }\n\n  value[value_len] = 0;\n  result = strncmp (value, value2, value_len);\n  if (result != 0)\n  {\n    printf (\"vms_putenv_symbol failed!  expected '%s', got '%s'\\n\",\n            value2, value);\n    status = 1;\n  }\n\n  vms_restore_symbol (putenv_string);\n  vms_status = LIB$GET_SYMBOL (&name_desc, &value_desc,\n                               &value_len, &old_symtbl);\n  if ($VMS_STATUS_SUCCESS (vms_status))\n    {\n      printf (\"lib$get_symbol for command succeeded, should have failed\\n\");\n      status = 1;\n    }\n\n  exit (status);\n}\n\n#endif\n"
  },
  {
    "path": "src/vms_progname.c",
    "content": "/* File: vms_progname.c\n *\n * This module provides a fixup of the program name.\n *\n * This module is designed to be a plug in replacement for the\n * progname module used by many GNU utilities with a few enhancements\n * needed for GNU Make.\n *\n * It does not support the HAVE_DECL_PROGRAM_INVOCATION_* macros at this\n * time.\n *\n * Make sure that the program_name string is set as close as possible to\n *    what the original command was given.\n *\n * When run from DCL, The argv[0] element is initialized with an absolute\n * path name.  The decc$ feature logical names can control the format\n * of this pathname.  In some cases it causes the UNIX format name to be\n * formatted incorrectly.\n *\n * This DCL provided name is usually incompatible with what is expected to\n * be provided by Unix programs and needs to be replaced.\n *\n * When run from an exec() call, the argv[0] element is initialized by the\n * program.  This name is compatible with what is expected to be provided\n * by Unix programs and should be passed through unchanged.\n *\n * The DCL provided name can be detected because it always contains the\n * device name.\n *\n * DCL examples:\n *    devname:[dir]program.exe;1         Normal VMS - remove path and .EXE;n\n *    devname:[dir]facility$program.exe;1   Facility also needs removal.\n *    /devname/dir/program.exe\n *    /DISK$VOLUME/dir/program.exe.1     Bug version should not be there.\n *    /DISK$VOLUME/dir/program.          Bug Period should not be there.\n *\n */\n\n/* Copyright (C) 2014-2024 Free Software Foundation, Inc.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n/* Per copyright assignment agreement with the Free Software Foundation\n   this software may be available under under other license agreements\n   and copyrights. */\n\n\n#ifdef HAVE_CONFIG_H\n# include \"config.h\"\n#endif\n\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdlib.h>\n\n#include <descrip.h>\n#include <dvidef.h>\n#include <efndef.h>\n#include <fscndef.h>\n#include <stsdef.h>\n\n#ifdef USE_PROGNAME_H\n# include \"progname.h\"\n#endif\n\n#pragma member_alignment save\n#pragma nomember_alignment longword\nstruct item_list_3\n{\n  unsigned short len;\n  unsigned short code;\n  void * bufadr;\n  unsigned short * retlen;\n};\n\nstruct filescan_itmlst_2\n{\n  unsigned short length;\n  unsigned short itmcode;\n  char * component;\n};\n\n#pragma member_alignment\n\nint\nSYS$GETDVIW (unsigned long efn,\n             unsigned short chan,\n             const struct dsc$descriptor_s * devnam,\n             const struct item_list_3 * itmlst,\n             void * iosb,\n             void (* astadr)(unsigned long),\n             unsigned long astprm,\n             void * nullarg);\n\nint\nSYS$FILESCAN (const struct dsc$descriptor_s * srcstr,\n              struct filescan_itmlst_2 * valuelist,\n              unsigned long * fldflags,\n              struct dsc$descriptor_s *auxout,\n              unsigned short * retlen);\n\n/* String containing name the program is called with.\n   To be initialized by main().  */\n\nconst char *program_name = NULL;\n\nstatic int internal_need_vms_symbol = 0;\n\nstatic char vms_new_nam[256];\n\nint\nneed_vms_symbol (void)\n{\n  return internal_need_vms_symbol;\n}\n\n\nvoid\nset_program_name (const char *argv0)\n{\n  int status;\n  int result;\n\n#ifdef DEBUG\n  printf (\"original argv0 = %s\\n\", argv0);\n#endif\n\n  /* Posix requires non-NULL argv[0] */\n  if (argv0 == NULL)\n    {\n      fputs (\"A NULL argv[0] was passed through an exec system call.\\n\",\n             stderr);\n      abort ();\n    }\n\n  program_name = argv0;\n  result = 0;\n  internal_need_vms_symbol = 0;\n\n  /* If the path name starts with a /, then it is an absolute path         */\n  /* that may have been generated by the CRTL instead of the command name  */\n  /* If it is the device name between the slashes, then this was likely    */\n  /* from the run command and needs to be fixed up.                        */\n  /* If the DECC$POSIX_COMPLIANT_PATHNAMES is set to 2, then it is the     */\n  /* DISK$VOLUME that will be present, and it will still need to be fixed. */\n  if (argv0[0] == '/')\n    {\n      char * nextslash;\n      int length;\n      struct item_list_3 itemlist[3];\n      unsigned short dvi_iosb[4];\n      char alldevnam[64];\n      unsigned short alldevnam_len;\n      struct dsc$descriptor_s devname_dsc;\n      char diskvolnam[256];\n      unsigned short diskvolnam_len;\n\n      internal_need_vms_symbol = 1;\n\n       /* Get some information about the disk */\n      /*--------------------------------------*/\n      itemlist[0].len = (sizeof alldevnam) - 1;\n      itemlist[0].code = DVI$_ALLDEVNAM;\n      itemlist[0].bufadr = alldevnam;\n      itemlist[0].retlen = &alldevnam_len;\n      itemlist[1].len = (sizeof diskvolnam) - 1 - 5;\n      itemlist[1].code = DVI$_VOLNAM;\n      itemlist[1].bufadr = &diskvolnam[5];\n      itemlist[1].retlen = &diskvolnam_len;\n      itemlist[2].len = 0;\n      itemlist[2].code = 0;\n\n      /* Add the prefix for the volume name. */\n      /* SYS$GETDVI will append the volume name to this */\n      strcpy (diskvolnam, \"DISK$\");\n\n      nextslash = strchr (&argv0[1], '/');\n      if (nextslash != NULL)\n        {\n          length = nextslash - argv0 - 1;\n\n          /* Cast needed for HP C compiler diagnostic */\n          devname_dsc.dsc$a_pointer = (char *)&argv0[1];\n          devname_dsc.dsc$w_length = length;\n          devname_dsc.dsc$b_dtype = DSC$K_DTYPE_T;\n          devname_dsc.dsc$b_class = DSC$K_CLASS_S;\n\n          status = SYS$GETDVIW (EFN$C_ENF, 0, &devname_dsc, itemlist,\n                                dvi_iosb, NULL, 0, 0);\n          if (!$VMS_STATUS_SUCCESS (status))\n            {\n              /* If the sys$getdviw fails, then this path was passed by */\n              /* An exec() program and not from DCL, so do nothing */\n              /* An example is \"/tmp/program\" where tmp: does not exist */\n#ifdef DEBUG\n              printf (\"sys$getdviw failed with status %d\\n\", status);\n#endif\n              result = 0;\n             }\n           else if (!$VMS_STATUS_SUCCESS (dvi_iosb[0]))\n             {\n#ifdef DEBUG\n                printf (\"sys$getdviw failed with iosb %d\\n\", dvi_iosb[0]);\n#endif\n                result = 0;\n              }\n            else\n              {\n                char * devnam;\n                int devnam_len;\n                char argv_dev[64];\n\n                /* Null terminate the returned alldevnam */\n                alldevnam[alldevnam_len] = 0;\n                devnam = alldevnam;\n                devnam_len = alldevnam_len;\n\n                /* Need to skip past any leading underscore */\n                if (devnam[0] == '_')\n                  {\n                    devnam++;\n                    devnam_len--;\n                  }\n\n                /* And remove the trailing colon */\n                if (devnam[devnam_len - 1] == ':')\n                  {\n                    devnam_len--;\n                    devnam[devnam_len] = 0;\n                  }\n\n                /* Null terminate the returned volnam */\n                diskvolnam_len += 5;\n                diskvolnam[diskvolnam_len] = 0;\n\n                /* Check first for normal CRTL behavior */\n                if (devnam_len == length)\n                  {\n                    strncpy (vms_new_nam, &argv0[1], length);\n                    vms_new_nam[length] = 0;\n                    result = (strcasecmp (devnam, vms_new_nam) == 0);\n                  }\n\n                /* If we have not got a match, check for POSIX Compliant */\n                /* behavior.  To be more accurate, we could also check */\n                /* to see if that feature is active. */\n                if ((result == 0) && (diskvolnam_len == length))\n                  {\n                    strncpy (vms_new_nam, &argv0[1], length);\n                    vms_new_nam[length] = 0;\n                    result = (strcasecmp (diskvolnam, vms_new_nam) == 0);\n                  }\n              }\n        }\n      }\n    else\n      {\n        /* The path did not start with a slash, so it could be VMS format */\n        /* If it is vms format, it has a volume/device in it as it must   */\n        /* be an absolute path */\n        struct dsc$descriptor_s path_desc;\n        int status;\n        unsigned long field_flags;\n        struct filescan_itmlst_2 item_list[5];\n        char * volume;\n        char * name;\n        int name_len;\n        char * ext;\n\n        path_desc.dsc$a_pointer = (char *)argv0; /* cast ok */\n        path_desc.dsc$w_length = strlen (argv0);\n        path_desc.dsc$b_dtype = DSC$K_DTYPE_T;\n        path_desc.dsc$b_class = DSC$K_CLASS_S;\n\n        /* Don't actually need to initialize anything buf itmcode */\n        /* I just do not like uninitialized input values */\n\n        /* Sanity check, this must be the same length as input */\n        item_list[0].itmcode = FSCN$_FILESPEC;\n        item_list[0].length = 0;\n        item_list[0].component = NULL;\n\n        /* If the device is present, then it if a VMS spec */\n        item_list[1].itmcode = FSCN$_DEVICE;\n        item_list[1].length = 0;\n        item_list[1].component = NULL;\n\n        /* we need the program name and type */\n        item_list[2].itmcode = FSCN$_NAME;\n        item_list[2].length = 0;\n        item_list[2].component = NULL;\n\n        item_list[3].itmcode = FSCN$_TYPE;\n        item_list[3].length = 0;\n        item_list[3].component = NULL;\n\n        /* End the list */\n        item_list[4].itmcode = 0;\n        item_list[4].length = 0;\n        item_list[4].component = NULL;\n\n        status = SYS$FILESCAN ((const struct dsc$descriptor_s *)&path_desc,\n                               item_list, &field_flags, NULL, NULL);\n\n\n        if ($VMS_STATUS_SUCCESS (status) &&\n           (item_list[0].length == path_desc.dsc$w_length) &&\n           (item_list[1].length != 0))\n          {\n\n            char * dollar;\n            int keep_ext;\n            int i;\n\n            /* We need the filescan to be successful, */\n            /* same length as input, and a volume to be present */\n            internal_need_vms_symbol = 1;\n\n            /* We will assume that we only get to this path on a version */\n            /* of VMS that does not support the EFS character set */\n\n            /* There may be a xxx$ prefix on the image name.  Linux */\n            /* programs do not handle that well, so strip the prefix */\n            name = item_list[2].component;\n            name_len = item_list[2].length;\n            dollar = strrchr (name, '$');\n            if (dollar != NULL)\n              {\n                dollar++;\n                name_len = name_len - (dollar - name);\n                name = dollar;\n              }\n\n            strncpy (vms_new_nam, name, name_len);\n            vms_new_nam[name_len] = 0;\n\n            /* Commit to using the new name */\n            program_name = vms_new_nam;\n\n            /* We only keep the extension if it is not \".exe\" */\n            keep_ext = 0;\n            ext = item_list[3].component;\n\n            if (item_list[3].length != 1)\n              {\n                keep_ext = 1;\n                if (item_list[3].length == 4)\n                  {\n                    if ((ext[1] == 'e' || ext[1] == 'E') &&\n                        (ext[2] == 'x' || ext[2] == 'X') &&\n                        (ext[3] == 'e' || ext[3] == 'E'))\n                      keep_ext = 0;\n                  }\n              }\n\n            if (keep_ext == 1)\n              strncpy (&vms_new_nam[name_len], ext, item_list[3].length);\n          }\n      }\n\n    if (result)\n      {\n        char * lastslash;\n        char * dollar;\n        char * dotexe;\n        char * lastdot;\n        char * extension;\n\n        /* This means it is probably the name from a DCL command */\n        /* Find the last slash which separates the file from the */\n        /* path. */\n        lastslash = strrchr (argv0, '/');\n\n        if (lastslash != NULL) {\n            int i;\n\n            lastslash++;\n\n            /* There may be a xxx$ prefix on the image name.  Linux */\n            /* programs do not handle that well, so strip the prefix */\n            dollar = strrchr (lastslash, '$');\n\n            if (dollar != NULL) {\n                dollar++;\n                lastslash = dollar;\n            }\n\n            strcpy (vms_new_nam, lastslash);\n\n            /* In UNIX mode + EFS character set, there should not be a */\n            /* version present, as it is not possible when parsing to  */\n            /* tell if it is a version or part of the UNIX filename as */\n            /* UNIX programs use numeric extensions for many reasons.  */\n\n            lastdot = strrchr (vms_new_nam, '.');\n            if (lastdot != NULL) {\n                int i;\n\n                i = 1;\n                while (isdigit ((unsigned char) lastdot[i])) {\n                    i++;\n                }\n                if (lastdot[i] == 0) {\n                    *lastdot = 0;\n                }\n            }\n\n            /* Find the .exe on the name (case insensitive) and toss it */\n            dotexe = strrchr (vms_new_nam, '.');\n            if (dotexe != NULL) {\n                if ((dotexe[1] == 'e' || dotexe[1] == 'E') &&\n                    (dotexe[2] == 'x' || dotexe[2] == 'X') &&\n                    (dotexe[3] == 'e' || dotexe[3] == 'E') &&\n                    (dotexe[4] == 0)) {\n\n                    *dotexe = 0;\n                } else {\n                     /* Also need to handle a null extension because of a */\n                     /* CRTL bug. */\n                     if (dotexe[1] == 0) {\n                         *dotexe = 0;\n                    }\n                }\n            }\n\n            /* Commit to new name */\n            program_name = vms_new_nam;\n\n        } else {\n            /* There is no way that the code should ever get here */\n            /* As we already verified that the '/' was present */\n            fprintf (stderr, \"Sanity failure somewhere we lost a '/'\\n\");\n        }\n    }\n}\n\n#ifdef DEBUG\n\nint\nmain (int argc, char ** argv, char **env)\n{\n\n  char command[1024];\n\n  set_program_name (argv[0]);\n\n  printf (\"modified argv[0] = %s\\n\", program_name);\n\n  return 0;\n}\n#endif\n"
  },
  {
    "path": "src/vmsdir.h",
    "content": "/* dirent.h for vms\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef VMSDIR_H\n#define VMSDIR_H\n\n#include <rms.h>\n\n#define\tMAXNAMLEN\t255\n\n#ifndef __DECC\n#if !defined (__GNUC__) && !defined (__ALPHA)\ntypedef unsigned long u_long;\ntypedef unsigned short u_short;\n#endif\n#endif\n\nstruct direct\n{\n  off_t d_off;\n  u_long d_fileno;\n  u_short d_reclen;\n  u_short d_namlen;\n  char d_name[MAXNAMLEN + 1];\n};\n\n#undef DIRSIZ\n#define DIRSIZ(dp)\t\t\\\n  (((sizeof (struct direct)\t\\\n     - (MAXNAMLEN+1)\t\t\\\n     + ((dp)->d_namlen+1))\t\\\n    + 3) & ~3)\n\n#define d_ino\td_fileno\t\t/* compatibility */\n\n\n/*\n * Definitions for library routines operating on directories.\n */\n\ntypedef struct DIR\n{\n  struct direct dir;\n  char d_result[MAXNAMLEN + 1];\n#if defined (__ALPHA) || defined (__DECC)\n  struct FAB fab;\n#else\n  struct fabdef fab;\n#endif\n} DIR;\n\n#ifndef NULL\n#define NULL 0\n#endif\n\n#define rewinddir(dirp)\tseekdir((dirp), (long)0)\n\nDIR *opendir ();\nstruct direct *readdir (DIR *dfd);\nint closedir (DIR *dfd);\nconst char *vmsify (const char *name, int type);\n\n#endif /* VMSDIR_H */\n"
  },
  {
    "path": "src/vmsfunctions.c",
    "content": "/* VMS functions\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"debug.h\"\n#include \"job.h\"\n\n#include <ctype.h>\n#include <string.h>\n\n#ifdef __DECC\n#include <starlet.h>\n#endif\n\n#include <rms.h>\n#include \"vmsdir.h\"\n\n#ifdef HAVE_VMSDIR_H\n\nDIR *\nopendir (char *dspec)\n{\n  struct DIR *dir  = xcalloc (sizeof (struct DIR));\n  struct NAM *dnam = xmalloc (sizeof (struct NAM));\n  struct FAB *dfab = &dir->fab;\n  char *searchspec = xmalloc (MAXNAMLEN + 1);\n\n  *dfab = cc$rms_fab;\n  *dnam = cc$rms_nam;\n  sprintf (searchspec, \"%s*.*;\", dspec);\n\n  dfab->fab$l_fna = searchspec;\n  dfab->fab$b_fns = strlen (searchspec);\n  dfab->fab$l_nam = dnam;\n\n  *dnam = cc$rms_nam;\n  dnam->nam$l_esa = searchspec;\n  dnam->nam$b_ess = MAXNAMLEN;\n\n  if (! (sys$parse (dfab) & 1))\n    {\n      free (dir);\n      free (dnam);\n      free (searchspec);\n      return (NULL);\n    }\n\n  return dir;\n}\n\n#define uppercasify(str) \\\n  do \\\n    { \\\n      char *tmp; \\\n      for (tmp = (str); *tmp != '\\0'; tmp++) \\\n        if (islower ((unsigned char)*tmp)) \\\n          *tmp = toupper ((unsigned char)*tmp); \\\n    } \\\n  while (0)\n\nstruct direct *\nreaddir (DIR *dir)\n{\n  struct FAB *dfab = &dir->fab;\n  struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);\n  struct direct *dentry = &dir->dir;\n  int i;\n\n  memset (dentry, 0, sizeof *dentry);\n\n  dnam->nam$l_rsa = dir->d_result;\n  dnam->nam$b_rss = MAXNAMLEN;\n\n  DB (DB_VERBOSE, (\".\"));\n\n  if (!((i = sys$search (dfab)) & 1))\n    {\n      DB (DB_VERBOSE, (_(\"sys$search() failed with %d\\n\"), i));\n      return (NULL);\n    }\n\n  dentry->d_off = 0;\n  if (dnam->nam$w_fid == 0)\n    dentry->d_fileno = 1;\n  else\n    dentry->d_fileno = dnam->nam$w_fid[0] + (dnam->nam$w_fid[1] << 16);\n\n  dentry->d_reclen = sizeof (struct direct);\n  dentry->d_namlen = dnam->nam$b_name + dnam->nam$b_type;\n  strncpy (dentry->d_name, dnam->nam$l_name, dentry->d_namlen);\n  dentry->d_name[dentry->d_namlen] = '\\0';\n\n#ifdef HAVE_CASE_INSENSITIVE_FS\n  uppercasify (dentry->d_name);\n#endif\n\n  return (dentry);\n}\n\nint\nclosedir (DIR *dir)\n{\n  if (dir != NULL)\n    {\n      struct FAB *dfab = &dir->fab;\n      struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);\n      if (dnam != NULL)\n        free (dnam->nam$l_esa);\n      free (dnam);\n      free (dir);\n    }\n\n  return 0;\n}\n#endif /* compiled for OpenVMS prior to V7.x */\n\n/* Argv0 will be a full vms file specification, like\n   node$dka100:[utils.gnumake]make.exe;47\n   prefix it with \"mcr \" to make it a vms command, executable for DCL. */\nconst char *\nvms_command(const char* argv0)\n{\n  size_t l = strlen(argv0) + 1;\n  char* s = xmalloc(l + 4);\n  memcpy(s, \"mcr \", 4);\n  memcpy(s+4, argv0, l);\n  return s;\n}\n\n/* Argv0 aka argv[0] will be a full vms file specification, like\n   node$dka100:[utils.gnumake]make.exe;47, set up by the CRTL.\n   The vms progname should be ^^^^, the file name without\n   file type .exe and ;version.\n   Use sys$parse to get the name part of the file specification. That is\n   in the above example, pick up \"make\" and return a copy of that string.\n   If something goes wrong in sys$parse (unlikely, this is a VMS/CRTL supplied\n   file specification) or if there is an empty name part (not easy to produce,\n   but it is possible) just return \"make\".\n   Some notes ...\n   NAM[L]$M_SYNCHK requests a syntax check, only.\n   NAM is for ODS2 names (shorter parts, output usually converted to UPPERCASE).\n   NAML is for ODS2/ODS5 names (longer parts, output unchanged).\n   NAM$M_NO_SHORT_UPCASE may not be available for older versions of VMS.\n   NAML is not available on older versions of VMS (NAML$C_BID not defined).\n   argv[0] on older versions of VMS (no extended parse style and no\n   CRTL feature DECC$ARGV_PARSE_STYLE) is always in lowercase. */\nconst char *\nvms_progname(const char* argv0)\n{\n  int status;\n  static struct FAB fab;\n  char *progname;\n  const char *fallback = \"make\";\n\n#ifdef NAML$C_BID\n  static char esa[NAML$C_MAXRSS];\n  static struct NAML naml;\n#else\n  static char esa[NAM$C_MAXRSS];\n  static struct NAM nam;\n#endif\n\n  fab = cc$rms_fab;\n  fab.fab$l_fna = (char*)argv0;\n  fab.fab$b_fns = strlen(argv0);\n\n#ifdef NAML$C_BID\n  fab.fab$l_naml = &naml;\n  naml = cc$rms_naml;\n  naml.naml$l_long_expand = esa;\n  naml.naml$l_long_expand_alloc = NAML$C_MAXRSS;\n  naml.naml$b_nop = NAML$M_SYNCHK;\n  naml.naml$l_input_flags = NAML$M_NO_SHORT_OUTPUT;\n#else\n  fab.fab$l_nam = &nam;\n  nam = cc$rms_nam;\n  nam.nam$l_esa = esa;\n  nam.nam$b_ess = NAM$C_MAXRSS;\n# ifdef NAM$M_NO_SHORT_UPCASE\n  nam.nam$b_nop = NAM$M_SYNCHK | NAM$M_NO_SHORT_UPCASE;\n# else\n  nam.nam$b_nop = NAM$M_SYNCHK;\n# endif\n#endif\n\n  status = sys$parse(&fab);\n  if (!(status & 1))\n    return fallback;\n\n#ifdef NAML$C_BID\n  if (naml.naml$l_long_name_size == 0)\n    return fallback;\n  progname = xmalloc(naml.naml$l_long_name_size + 1);\n  memcpy(progname, naml.naml$l_long_name, naml.naml$l_long_name_size);\n  progname[naml.naml$l_long_name_size] = '\\0';\n#else\n  if (nam.nam$b_name == 0)\n    return fallback;\n  progname = xmalloc(nam.nam$b_name + 1);\n# ifdef NAM$M_NO_SHORT_UPCASE\n  memcpy(progname, nam.nam$l_name, nam.nam$b_name);\n# else\n    {\n      int i;\n      for (i = 0; i < nam.nam$b_name; i++)\n        progname[i] = tolower(nam.nam$l_name[i]);\n    }\n# endif\n  progname[nam.nam$b_name] = '\\0';\n#endif\n\n  return progname;\n}\n"
  },
  {
    "path": "src/vmsify.c",
    "content": "/* vmsify.c -- Module for vms <-> unix file name conversion\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* Written by Klaus Kmpf (kkaempf@progis.de)\n   of proGIS Software, Aachen, Germany */\n\n\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n\n#include \"makeint.h\"\n\n#if MK_OS_VMS\n#include <unixlib.h>\n#include <stdlib.h>\n#include <jpidef.h>\n#include <descrip.h>\n#include <uaidef.h>\n#include <ssdef.h>\n#include <starlet.h>\n#include <lib$routines.h>\n/* Initialize a string descriptor (struct dsc$descriptor_s) for an\n   arbitrary string.   ADDR is a pointer to the first character\n   of the string, and LEN is the length of the string. */\n\n#define INIT_DSC_S(dsc, addr, len) do { \\\n  (dsc).dsc$b_dtype = DSC$K_DTYPE_T;    \\\n  (dsc).dsc$b_class = DSC$K_CLASS_S;    \\\n  (dsc).dsc$w_length = (len);           \\\n  (dsc).dsc$a_pointer = (addr);         \\\n} while (0)\n\n/* Initialize a string descriptor (struct dsc$descriptor_s) for a\n   NUL-terminated string.  S is a pointer to the string; the length\n   is determined by calling strlen(). */\n\n#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))\n#endif\n\n/*\n  copy 'from' to 'to' up to but not including 'upto'\n  return 0 if eos on from\n  return 1 if upto found\n\n  return 'to' at last char + 1\n  return 'from' at match + 1 or eos if no match\n\n  if as_dir == 1, change all '.' to '_'\n  else change all '.' but the last to '_'\n*/\n\nstatic int\ncopyto (char **to, const char **from, char upto, int as_dir)\n{\n  const char *s;\n\n  s = strrchr (*from, '.');\n\n  while (**from)\n    {\n      if (**from == upto)\n\t{\n\t  do\n\t    {\n\t      (*from)++;\n\t    }\n\t  while (**from == upto);\n\t  return 1;\n\t}\n      if (**from == '.')\n\t{\n\t  if ((as_dir == 1)\n\t      || (*from != s))\n\t    **to = '_';\n\t  else\n\t    **to = '.';\n\t}\n      else\n\t{\n#ifdef HAVE_CASE_INSENSITIVE_FS\n\t  if (isupper ((unsigned char)**from))\n\t    **to = tolower ((unsigned char)**from);\n\t  else\n#endif\n\t    **to = **from;\n\t}\n      (*to)++;\n      (*from)++;\n    }\n\n  return 0;\n}\n\n\n/*\n  get translation of logical name\n\n*/\n\nstatic char *\ntrnlog (const char *name)\n{\n  int stat;\n  static char reslt[1024];\n  $DESCRIPTOR (reslt_dsc, reslt);\n  short resltlen;\n  struct dsc$descriptor_s name_dsc;\n  char *s;\n\n  /*\n   * the string isn't changed, but there is no string descriptor with\n   * \"const char *dsc$a_pointer\"\n   */\n  INIT_DSC_CSTRING (name_dsc, (char *)name);\n\n  stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);\n\n  if ((stat&1) == 0)\n    {\n      return \"\";\n    }\n  if (stat == SS$_NOTRAN)\n    {\n      return \"\";\n    }\n  reslt[resltlen] = '\\0';\n\n  s = xmalloc (resltlen+1);\n  strcpy (s, reslt);\n  return s;\n}\n\nstatic char *\nshowall (char *s)\n{\n  static char t[512];\n  char *pt;\n\n  pt = t;\n  if (strchr (s, '\\\\') == 0)\n    return s;\n  while (*s)\n    {\n      if (*s == '\\\\')\n\t{\n\t  *pt++ = *s;\n\t}\n      *pt++ = *s++;\n    }\n  return pt;\n}\n\n\nenum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };\n\n/*\n  convert unix style name to vms style\n  type = 0 -> name is a full name (directory and filename part)\n  type = 1 -> name is a directory\n  type = 2 -> name is a filename without directory\n\n  The following conversions are applied\n\t\t\t(0)\t\t(1)\t\t\t(2)\n\tinput\t\tfull name\tdir name\t\tfile name\n\n1\t./\t\t<cwd>\t\t[]\t\t\t<current directory>.dir\n2\t../\t\t<home of cwd>\t<home of cwd>\t\t<home of cwd>.dir\n\n3\t//\t\t<dev of cwd>:\t<dev of cwd>:[000000]\t<dev of cwd>:000000.dir\n4\t//a\t\ta:\t\ta:\t\t\ta:\n5\t//a/\t\ta:\t\ta:\t\t\ta:000000.dir\n\n9\t/\t\t[000000]\t[000000]\t\t000000.dir\n10\t/a\t\t[000000]a\t[a]\t\t\t[000000]a\n11\t/a/\t\t[a]\t\t[a]\t\t\t[000000]a.dir\n12\t/a/b\t\t[a]b\t\t[a.b]\t\t\t[a]b\n13\t/a/b/\t\t[a.b]\t\t[a.b]\t\t\t[a]b.dir\n14\t/a/b/c\t\t[a.b]c\t\t[a.b.c]\t\t\t[a.b]c\n15\t/a/b/c/\t\t[a.b.c]\t\t[a.b.c]\t\t\t[a.b]c.dir\n\n16\ta\t\ta\t\t[.a]\t\t\ta\n17\ta/\t\t[.a]\t\t[.a]\t\t\ta.dir\n18\ta/b\t\t[.a]b\t\t[.a.b]\t\t\t[.a]b\n19\ta/b/\t\t[.a.b]\t\t[.a.b]\t\t\t[.a]b.dir\n20\ta/b/c\t\t[.a.b]c\t\t[.a.b.c]\t\t[.a.b]c\n21\ta/b/c/\t\t[.a.b.c]\t[.a.b.c]\t\t[.a.b]c.dir\n\n22\ta.b.c\t\ta_b.c\t\t[.a_b_c]\t\ta_b_c.dir\n\n23\t[x][y]z\t\t[x.y]z\t\t[x.y]z\t\t\t[x.y]z\n24\t[x][.y]z\t[x.y]z\t\t[x.y]z\t\t\t[x.y]z\n\n25  filenames with '$'  are left unchanged if they contain no '/'\n25  filenames with ':' are left unchanged\n26  filenames with a single pair of '[' ']' are left unchanged\n\n  The input string is not written to.  The result is also const because\n  it's a static buffer; we don't want to change it.\n*/\n\nconst char *\nvmsify (const char *name, int type)\n{\n/* max 255 device\n   max 39 directory\n   max 39 filename\n   max 39 filetype\n   max 5 version\n*/\n/* todo: VMSMAXPATHLEN is defined for ODS2 names: it needs to be adjusted. */\n#define VMSMAXPATHLEN 512\n\n  enum namestate nstate;\n  static char vmsname[VMSMAXPATHLEN+1];\n  const char *fptr;\n  const char *t;\n  char *vptr;\n  int as_dir;\n  int count;\n  const char *s;\n  const char *s1;\n  const char *s2;\n\n  if (name == 0)\n    return 0;\n  fptr = name;\n  vptr = vmsname;\n  nstate = N_START;\n\n  /* case 25a */\n  t = strpbrk (name, \"$:\");\n\n  if (t != 0)\n    {\n//      const char *s1;\n//      const char *s2;\n\n      if (type == 1)\n        {\n          s1 = strchr (t+1, '[');\n          s2 = strchr (t+1, ']');\n        }\n\n      if (*t == '$')\n        {\n          if (strchr (name, '/') == 0)\n            {\n              strcpy (vmsname, name);\n              if ((type == 1) && (s1 != 0) && (s2 == 0))\n                strcat (vmsname, \"]\");\n              return vmsname;\n            }\n        }\n      else\n        {\n          strcpy (vmsname, name);\n          if ((type == 1) && (s1 != 0) && (s2 == 0))\n            strcat (vmsname, \"]\");\n          return vmsname;\n        }\n    }\n\n  /* case 26 */\n  t = strchr (name, '[');\n\n  if (t != 0)\n    {\n//      const char *s;\n//      const char *s1 = strchr (t+1, '[');\n      s1 = strchr (t+1, '[');\n      if (s1 == 0)\n\t{\n          strcpy (vmsname, name);\n\t  if ((type == 1) && (strchr (t+1, ']') == 0))\n            strcat (vmsname, \"]\");\n          return vmsname;\n\t}\n      s1--;\n      if (*s1 != ']')\n\t{\n          strcpy (vmsname, name);\n\t  return vmsname;\t\t/* not ][, keep unchanged */\n\t}\n\n      /* we have ][ */\n\n      s = name;\n\n      /* s  -> starting char\n\t s1 -> ending ']'  */\n      do\n\t{\n\t  strncpy (vptr, s, s1-s);\t/* copy up to but not including ']' */\n\t  vptr += s1-s;\n\t  if (*s1 == 0)\n\t    break;\n\t  s = s1 + 1;\t\t\t/* s -> char behind ']' */\n\t  if (*s != '[')\t\t/* was '][' ? */\n\t    break;\t\t\t/* no, last ] found, exit */\n\t  s++;\n\t  if (*s != '.')\n\t    *vptr++ = '.';\n\t  s1 = strchr (s, ']');\n\t  if (s1 == 0)\t\t\t/* no closing ] */\n\t    s1 = s + strlen (s);\n\t}\n      while (1);\n\n      *vptr++ = ']';\n\n      fptr = s;\n\n    }\n  else\t\t/* no [ in name */\n    {\n      int state = 0;\n      int rooted = 1;\t/* flag if logical is rooted, else insert [000000] */\n\n      do\n\t{\n      switch (state)\n\t{\n\t  case 0:\t\t\t\t/* start of loop */\n\t    if (*fptr == '/')\n\t      {\n\t\tfptr++;\n\t\tstate = 1;\n\t      }\n\t    else if (*fptr == '.')\n\t      {\n\t\tfptr++;\n\t\tstate = 10;\n\t      }\n\t    else\n\t      state = 2;\n\t    break;\n\n\t  case 1:\t\t\t\t/* '/' at start */\n\t    if (*fptr == '/')\n\t      {\n\t\tfptr++;\n\t\tstate = 3;\n\t      }\n\t    else\n\t      state = 4;\n\t    break;\n\n\t  case 2:\t\t\t\t/* no '/' at start */\n            {\n            const char *s = strchr (fptr, '/');\n\t    if (s == 0)\t\t\t/* no '/' (16) */\n\t      {\n\t\tif (type == 1)\n\t\t  {\n\t\t    strcpy (vptr, \"[.\");\n\t\t    vptr += 2;\n\t\t  }\n\t\tcopyto (&vptr, &fptr, 0, (type==1));\n\t\tif (type == 1)\n\t\t  *vptr++ = ']';\n\t\tstate = -1;\n\t      }\n\t    else\t\t\t/* found '/' (17..21) */\n\t      {\n\t\tif ((type == 2)\n\t\t    && (*(s+1) == 0))\t/* 17(2) */\n\t\t  {\n\t\t    copyto (&vptr, &fptr, '/', 1);\n\t\t    state = 7;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    strcpy (vptr, \"[.\");\n\t\t    vptr += 2;\n\t\t    copyto (&vptr, &fptr, '/', 1);\n\t\t    nstate = N_OPEN;\n\t\t    state = 9;\n\t\t  }\n\t      }\n\t    break;\n            }\n\n\t  case 3:\t\t\t\t/* '//' at start */\n            {\n//            const char *s;\n//            const char *s1;\n            char *vp;\n\t    while (*fptr == '/')\t/* collapse all '/' */\n\t      fptr++;\n\t    if (*fptr == 0)\t\t/* just // */\n\t      {\n\t\tchar cwdbuf[VMSMAXPATHLEN+1];\n\n\t\ts1 = getcwd(cwdbuf, VMSMAXPATHLEN);\n\t\tif (s1 == 0)\n\t\t  {\n                    vmsname[0] = '\\0';\n\t\t    return vmsname;\t/* FIXME, err getcwd */\n\t\t  }\n\t\ts = strchr (s1, ':');\n\t\tif (s == 0)\n\t\t  {\n                    vmsname[0] = '\\0';\n\t\t    return vmsname;\t/* FIXME, err no device */\n\t\t  }\n\t\tstrncpy (vptr, s1, s-s1+1);\n\t\tvptr += s-s1+1;\n\t\tstate = -1;\n\t\tbreak;\n\t      }\n\n\t    s = vptr;\n\n\t    if (copyto (&vptr, &fptr, '/', 1) == 0)\t/* copy device part */\n\t      {\n\t\t*vptr++ = ':';\n\t\tstate = -1;\n\t\tbreak;\n\t      }\n\t    *vptr = ':';\n\t    nstate = N_DEVICE;\n\t    if (*fptr == 0)\t/* just '//a/' */\n\t      {\n\t\tstrcpy (vptr+1, \"[000000]\");\n\t\tvptr += 9;\n\t\tstate = -1;\n\t\tbreak;\n\t      }\n\t    *vptr = 0;\n\t\t\t\t/* check logical for [000000] insertion */\n\t    vp = trnlog (s);\n\t    if (*vp != '\\0')\n\t      {\t\t\t/* found translation */\n\t\tfor (;;)\t/* loop over all nested logicals */\n\t\t  {\n\t\t    char *vp2 = vp + strlen (vp) - 1;\n\t\t    if (*vp2 == ':')\t/* translation ends in ':' */\n\t\t      {\n\t\t\tvp2 = trnlog (vp);\n\t\t\tfree (vp);\n\t\t\tif (*vp2 == 0)\n\t\t\t  {\n\t\t\t    rooted = 0;\n\t\t\t    break;\n\t\t\t  }\n\t\t\tvp = vp2;\n\t\t\tcontinue;\t/* next iteration */\n\t\t      }\n\t\t    if (*vp2 == ']')\t/* translation ends in ']' */\n\t\t      {\n\t\t\tif (*(vp2-1) == '.')\t/* ends in '.]' */\n\t\t\t  {\n\t\t\t    if (strncmp (fptr, \"000000\", 6) != 0)\n\t\t\t      rooted = 0;\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    strcpy (vmsname, s1);\n\t\t\t    vp = strchr (vmsname, ']');\n\t\t\t    *vp = '.';\n\t\t\t    nstate = N_DOT;\n\t\t\t    vptr = vp;\n\t\t\t  }\n\t\t      }\n\t\t    break;\n\t\t  }\n\t\tfree (vp);\n\t      }\n\t    else\n\t      rooted = 0;\n\n\t    if (*vptr == 0)\n\t      {\n\t\tnstate = N_DEVICE;\n\t        *vptr++ = ':';\n\t      }\n\t    else\n\t      vptr++;\n\n\t    if (rooted == 0)\n\t      {\n\t\tnstate = N_DOT;\n\t        strcpy (vptr, \"[000000.\");\n\t\tvptr += 8;\n\t\tvp = vptr-1;\n\t      }\n\t    else\n\t      vp = 0;\n\n            /* vp-> '.' after 000000 or NULL */\n\n\t    s = strchr (fptr, '/');\n\t    if (s == 0)\n\t      {\t\t\t\t/* no next '/' */\n\t\tif (*(vptr-1) == '.')\n\t\t  *(vptr-1) = ']';\n\t\telse if (rooted == 0)\n\t\t  *vptr++ = ']';\n\t\tcopyto (&vptr, &fptr, 0, (type == 1));\n\t\tstate = -1;\n\t\tbreak;\n\t      }\n\t    else\n\t      {\n\t\twhile (*(s+1) == '/')\t/* skip multiple '/' */\n\t\t  s++;\n\t      }\n\n\t    if ((rooted != 0)\n\t        && (*(vptr-1) != '.'))\n\t      {\n\t\t*vptr++ = '[';\n\t\tnstate = N_DOT;\n\t      }\n\t    else\n\t      if ((nstate == N_DOT)\n\t\t && (vp != 0)\n\t\t && (*(s+1) == 0))\n\t\t{\n\t\t  if (type == 2)\n\t\t    {\n\t\t      *vp = ']';\n\t\t      nstate = N_CLOSED;\n\t\t    }\n\t\t}\n\t    state = 9;\n\t    break;\n            }\n\t  case 4:\t\t\t\t/* single '/' at start (9..15) */\n\t    if (*fptr == 0)\n\t      state = 5;\n\t    else\n\t      state = 6;\n\t    break;\n\n\t  case 5:\t\t\t\t/* just '/' at start (9) */\n\t    if (type != 2)\n\t      {\n\t        *vptr++ = '[';\n\t\tnstate = N_OPEN;\n\t      }\n\t    strcpy (vptr, \"000000\");\n\t    vptr += 6;\n\t    if (type == 2)\n\t      state = 7;\n\t    else\n\t      state = 8;\n\t    break;\n\n\t  case 6:\t\t/* chars following '/' at start 10..15 */\n            {\n            const char *s;\n\t    *vptr++ = '[';\n\t    nstate = N_OPEN;\n\t    s = strchr (fptr, '/');\n\t    if (s == 0)\t\t\t/* 10 */\n\t      {\n\t\tif (type != 1)\n\t\t  {\n\t\t    strcpy (vptr, \"000000]\");\n\t\t    vptr += 7;\n\t\t  }\n\t\tcopyto (&vptr, &fptr, 0, (type == 1));\n\t\tif (type == 1)\n\t\t  {\n\t\t    *vptr++ = ']';\n\t\t  }\n\t\tstate = -1;\n\t      }\n\t    else\t\t\t/* 11..15 */\n\t      {\n\t\tif ( (type == 2)\n\t\t   && (*(s+1) == 0))\t/* 11(2) */\n\t\t  {\n\t\t    strcpy (vptr, \"000000]\");\n\t\t    nstate = N_CLOSED;\n\t\t    vptr += 7;\n\t\t  }\n\t\tcopyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));\n\t\tstate = 9;\n\t      }\n\t    break;\n            }\n\n\t  case 7:\t\t\t\t/* add '.dir' and exit */\n\t    if ((nstate == N_OPEN)\n\t\t|| (nstate == N_DOT))\n\t      {\n\t\tchar *vp = vptr-1;\n\t\twhile (vp > vmsname)\n\t\t  {\n\t\t    if (*vp == ']')\n\t\t      {\n\t\t\tbreak;\n\t\t      }\n\t\t    if (*vp == '.')\n\t\t      {\n\t\t\t*vp = ']';\n\t\t\tbreak;\n\t\t      }\n\t\t    vp--;\n\t\t  }\n\t      }\n\t    strcpy (vptr, \".dir\");\n\t    vptr += 4;\n\t    state = -1;\n\t    break;\n\n\t  case 8:\t\t\t\t/* add ']' and exit */\n\t    *vptr++ = ']';\n\t    state = -1;\n\t    break;\n\n\t  case 9:\t\t\t/* 17..21, fptr -> 1st '/' + 1 */\n            {\n            const char *s;\n\t    if (*fptr == 0)\n\t      {\n\t\tif (type == 2)\n\t\t  {\n\t\t    state = 7;\n\t\t  }\n\t\telse\n\t\t  state = 8;\n\t\tbreak;\n\t      }\n\t    s = strchr (fptr, '/');\n\t    if (s == 0)\n\t      {\n\t\tif (type != 1)\n\t\t  {\n\t\t    if (nstate == N_OPEN)\n\t\t      {\n\t\t\t*vptr++ = ']';\n\t\t\tnstate = N_CLOSED;\n\t\t      }\n\t\t    as_dir = 0;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    if (nstate == N_OPEN)\n\t\t      {\n\t\t\t*vptr++ = '.';\n\t\t\tnstate = N_DOT;\n\t\t      }\n\t\t    as_dir = 1;\n\t\t  }\n\t      }\n\t    else\n\t      {\n\t\twhile (*(s+1) == '/')\n\t\t  s++;\n\t\tif ( (type == 2)\n\t\t    && (*(s+1) == 0))\t\t/* 19(2), 21(2)*/\n\t\t  {\n\t\t    if (nstate != N_CLOSED)\n\t\t      {\n\t\t\t*vptr++ = ']';\n\t\t\tnstate = N_CLOSED;\n\t\t      }\n\t\t    as_dir = 1;\n\t\t  }\n\t\telse\n\t\t  {\n\t\t    if (nstate == N_OPEN)\n\t\t      {\n\t\t\t*vptr++ = '.';\n\t\t\tnstate = N_DOT;\n\t\t      }\n\t\t    as_dir = 1;\n\t\t  }\n\t      }\n\t    if ( (*fptr == '.')\t\t\t/* check for '..' or '../' */\n\t\t&& (*(fptr+1) == '.')\n\t\t&& ((*(fptr+2) == '/')\n\t\t    || (*(fptr+2) == 0)) )\n\t      {\n                char *vp;\n\t\tfptr += 2;\n\t\tif (*fptr == '/')\n\t\t  {\n\t\t    do\n\t\t      {\n\t\t\tfptr++;\n\t\t      }\n\t\t    while (*fptr == '/');\n\t\t  }\n\t\telse if (*fptr == 0)\n\t\t  type = 1;\n\t\tvptr--;\t\t\t\t/* vptr -> '.' or ']' */\n\t\tvp = vptr;\n\t\tfor (;;)\n\t\t  {\n\t\t    vp--;\n\t\t    if (*vp == '.')\t\t/* one back */\n\t\t      {\n\t\t\tvptr = vp;\n\t\t\tnstate = N_OPEN;\n\t\t\tbreak;\n\t\t      }\n\t\t    if (*vp == '[')\t\t/* top level reached */\n\t\t      {\n\t\t\tif (*fptr == 0)\n\t\t\t  {\n\t\t\t    strcpy (vp, \"[000000]\");\n\t\t\t    vptr = vp + 8;\n\t\t\t    nstate = N_CLOSED;\n\t\t\t    s = 0;\n\t\t\t    break;\n\t\t\t  }\n\t\t\telse\n\t\t\t  {\n\t\t\t    vptr = vp+1;\n\t\t\t    nstate = N_OPEN;\n\t\t\t    break;\n\t\t\t  }\n\t\t      }\n\t\t  }\n\t      }\n\t    else\n\t      {\n\t\tcopyto (&vptr, &fptr, '/', as_dir);\n\t\tif (nstate == N_DOT)\n\t\t  nstate = N_OPEN;\n\t      }\n\t    if (s == 0)\n\t      {\t\t\t\t\t/* 18,20 */\n\t\tif (type == 1)\n\t\t  *vptr++ = ']';\n\t\tstate = -1;\n\t      }\n\t    else\n\t      {\n\t\tif (*(s+1) == 0)\n\t\t  {\n\t\t    if (type == 2)\t\t/* 19,21 */\n\t\t      {\n\t\t        state = 7;\n\t\t      }\n\t\t    else\n\t\t      {\n\t\t\t*vptr++ = ']';\n\t\t\tstate = -1;\n\t\t      }\n\t\t  }\n\t      }\n\t    break;\n            }\n\n\t  case 10:\t\t\t\t/* 1,2 first is '.' */\n\t    if (*fptr == '.')\n\t      {\n\t\tfptr++;\n\t\tstate = 11;\n\t      }\n\t    else\n\t      state = 12;\n\t    break;\n\n\t  case 11:\t\t\t\t/* 2, '..' at start */\n\t    count = 1;\n\t    if (*fptr != 0)\n\t      {\n\t\tif (*fptr != '/')\t\t/* got ..xxx */\n\t\t  {\n                    strcpy (vmsname, name);\n\t\t    return vmsname;\n\t\t  }\n\t\tdo\t\t\t\t/* got ../ */\n\t\t  {\n\t\t    fptr++;\n\t\t    while (*fptr == '/') fptr++;\n\t\t    if (*fptr != '.')\n\t\t      break;\n\t\t    if (*(fptr+1) != '.')\n\t\t      break;\n\t\t    fptr += 2;\n\t\t    if ((*fptr == 0)\n\t\t\t|| (*fptr == '/'))\n\t\t      count++;\n\t\t  }\n\t\twhile (*fptr == '/');\n\t      }\n\t    {\t\t\t\t\t/* got '..' or '../' */\n              char *vp;\n\t      char cwdbuf[VMSMAXPATHLEN+1];\n\n\t      vp = getcwd(cwdbuf, VMSMAXPATHLEN);\n\t      if (vp == 0)\n\t\t{\n                  vmsname[0] = '\\0';\n\t\t  return vmsname;    /* FIXME, err getcwd */\n\t\t}\n\t      strcpy (vptr, vp);\n\t      vp = strchr (vptr, ']');\n\t      if (vp != 0)\n\t\t{\n\t\t  nstate = N_OPEN;\n\t\t  while (vp > vptr)\n\t\t    {\n\t\t      vp--;\n\t\t      if (*vp == '[')\n\t\t\t{\n\t\t\t  vp++;\n\t\t\t  strcpy (vp, \"000000]\");\n\t\t\t  state = -1;\n\t\t\t  break;\n\t\t\t}\n\t\t      else if (*vp == '.')\n\t\t\t{\n\t\t\t  if (--count == 0)\n\t\t\t    {\n\t\t\t      if (*fptr == 0)\t/* had '..' or '../' */\n\t\t\t\t{\n\t\t\t\t  *vp++ = ']';\n\t\t\t\t  state = -1;\n\t\t\t\t}\n\t\t\t      else\t\t\t/* had '../xxx' */\n\t\t\t\t{\n\t\t\t\t  state = 9;\n\t\t\t\t}\n\t\t\t      *vp = '\\0';\n\t\t\t      break;\n\t\t\t    }\n\t\t\t}\n\t\t    }\n\t\t}\n\t      vptr += strlen (vptr);\n\t    }\n\t    break;\n\n\t  case 12:\t\t\t\t/* 1, '.' at start */\n\t    if (*fptr != 0)\n\t      {\n\t\tif (*fptr != '/')\n\t\t  {\n                    strcpy (vmsname, name);\n\t\t    return vmsname;\n\t\t  }\n\t\twhile (*fptr == '/')\n\t\t  fptr++;\n\t      }\n\n\t    {\n              char *vp;\n\t      char cwdbuf[VMSMAXPATHLEN+1];\n\n\t      vp = getcwd(cwdbuf, VMSMAXPATHLEN);\n\t      if (vp == 0)\n\t\t{\n                  vmsname[0] = '\\0';\n\t\t  return vmsname;    /*FIXME, err getcwd */\n\t\t}\n\t      strcpy (vptr, vp);\n            }\n            if (*fptr == 0)\n              {\n                state = -1;\n                break;\n              }\n            else\n              {\n                char *vp = strchr (vptr, ']');\n                if (vp == 0)\n                  {\n                    state = -1;\n                    break;\n                  }\n                *vp = '\\0';\n                nstate = N_OPEN;\n                vptr += strlen (vptr);\n                state = 9;\n              }\n\t    break;\n\t}\n\n\t}\n      while (state > 0);\n\n\n    }\n\n\n  /* directory conversion done\n     fptr -> filename part of input string\n     vptr -> free space in vmsname\n  */\n\n  *vptr++ = 0;\n\n  return vmsname;\n}\n\n\n\n/*\n  convert from vms-style to unix-style\n\n  dev:[dir1.dir2]\t//dev/dir1/dir2/\n*/\n\nconst char *\nunixify (const char *name)\n{\n  static char piece[512];\n  const char *s;\n  char *p;\n\n  if (strchr (name, '/') != 0)\t\t/* already in unix style */\n    {\n      strcpy (piece, name);\n      return piece;\n    }\n\n  p = piece;\n  *p = 0;\n\n  /* device part */\n\n  s = strchr (name, ':');\n\n  if (s != 0)\n    {\n      int l = s - name;\n      *p++ = '/';\n      *p++ = '/';\n      strncpy (p, name, l);\n      p += l;\n    }\n\n  /* directory part */\n\n  *p++ = '/';\n  s = strchr (name, '[');\n\n  if (s != 0)\n    {\n      s++;\n      switch (*s)\n        {\n\t  case ']':\t\t/* [] */\n\t    strcat (p, \"./\");\n\t    break;\n\t  case '-':\t\t/* [- */\n\t    strcat (p, \"../\");\n\t    break;\n\t  case '.':\n\t    strcat (p, \"./\");\t/* [. */\n\t    break;\n\t  default:\n\t    s--;\n\t    break;\n        }\n      s++;\n      while (*s)\n        {\n\t  if (*s == '.')\n\t    *p++ = '/';\n\t  else\n\t    *p++ = *s;\n\t  s++;\n\t  if (*s == ']')\n\t    {\n\t      s++;\n\t      break;\n\t    }\n        }\n      if (*s != 0)\t\t/* more after ']' ?? */\n        {\n\t  if (*(p-1) != '/')\n\t    *p++ = '/';\n\t  strcpy (p, s);\t\t/* copy it anyway */\n        }\n    }\n\n  else\t\t/* no '[' anywhere */\n\n    {\n      *p++ = 0;\n    }\n\n  /* force end with '/' */\n\n  if (*(p-1) != '/')\n    *p++ = '/';\n  *p = 0;\n\n  return piece;\n}\n\n/* EOF */\n"
  },
  {
    "path": "src/vmsjobs.c",
    "content": "/* --------------- Moved here from job.c ---------------\n   This file must be #included in job.c, as it accesses static functions.\n\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include <string.h>\n#include <descrip.h>\n#include <clidef.h>\n\n/* TODO - VMS specific header file conditionally included in makeint.h */\n\n#include <stsdef.h>\n#include <ssdef.h>\nvoid\ndecc$exit (int status);\n\n/* Lowest legal non-success VMS exit code is 8 */\n/* GNU Make only defines codes 0, 1, 2 */\n/* So assume any exit code > 8 is a VMS exit code */\n\n#ifndef MAX_EXPECTED_EXIT_CODE\n# define MAX_EXPECTED_EXIT_CODE 7\n#endif\n\n\n#if __CRTL_VER >= 70302000 && !defined(__VAX)\n# define MAX_DCL_LINE_LENGTH 4095\n# define MAX_DCL_CMD_LINE_LENGTH 8192\n#else\n# define MAX_DCL_LINE_LENGTH 255\n# define MAX_DCL_CMD_LINE_LENGTH 1024\n#endif\n#define MAX_DCL_TOKEN_LENGTH 255\n#define MAX_DCL_TOKENS 127\n\nenum auto_pipe { nopipe, add_pipe, dcl_pipe };\n\nchar *vmsify (char *name, int type);\n\nstatic int vms_jobsefnmask = 0;\n\n/* returns whether path is assumed to be a unix like shell. */\nint\n_is_unixy_shell (const char *path)\n{\n  return vms_gnv_shell;\n}\n\n#define VMS_GETMSG_MAX 256\nstatic char vms_strsignal_text[VMS_GETMSG_MAX + 2];\n\nchar *\nvms_strsignal (int status)\n{\n  if (status <= MAX_EXPECTED_EXIT_CODE)\n    sprintf (vms_strsignal_text, \"lib$spawn returned %x\", status);\n  else\n    {\n      int vms_status;\n      unsigned short * msg_len;\n      unsigned char out[4];\n      vms_status = SYS$GETMSG (status, &msg_len,\n                               vms_strsignal_text, 7, *out);\n    }\n\n  return vms_strsignal_text;\n}\n\n\n/* Wait for nchildren children to terminate */\nstatic void\nvmsWaitForChildren (int *status)\n{\n  while (1)\n    {\n      if (!vms_jobsefnmask)\n        {\n          *status = 0;\n          return;\n        }\n\n      *status = sys$wflor (32, vms_jobsefnmask);\n    }\n  return;\n}\n\nstatic int ctrlYPressed= 0;\n/* This is called at main or AST level. It is at AST level for DONTWAITFORCHILD\n   and at main level otherwise. In any case it is called when a child process\n   terminated. At AST level it won't get interrupted by anything except a\n   inner mode level AST.\n*/\nstatic int\nvmsHandleChildTerm (struct childbase *cbase)\n{\n  struct child *child = (struct child*)cbase;\n  struct child *lastc, *c;\n  int child_failed;\n  int exit_code;\n\n  /* The child efn is 0 when a built-in or null command is executed\n     successfully with out actually creating a child.\n  */\n  if (child->efn > 0)\n  {\n    vms_jobsefnmask &= ~(1 << (child->efn - 32));\n\n    lib$free_ef (&child->efn);\n  }\n  if (child->comname)\n    {\n      if (!ISDB (DB_JOBS) && !ctrlYPressed)\n        unlink (child->comname);\n      free (child->comname);\n    }\n\n  (void) sigblock (fatal_signal_mask);\n\n  /* First check to see if this is a POSIX exit status and handle */\n  if ((child->cstatus & VMS_POSIX_EXIT_MASK) == VMS_POSIX_EXIT_MASK)\n    {\n      exit_code = (child->cstatus >> 3) & 255;\n      if (exit_code != MAKE_SUCCESS)\n        child_failed = 1;\n    }\n  else\n    {\n      child_failed = !$VMS_STATUS_SUCCESS (child->cstatus);\n      if (child_failed)\n        exit_code = child->cstatus;\n    }\n\n  /* Search for a child matching the deceased one.  */\n  lastc = 0;\n#if defined(RECURSIVEJOBS)\n  /* I've had problems with recursive stuff and process handling */\n  for (c = children; c != 0 && c != child; lastc = c, c = c->next)\n    ;\n#else\n  c = child;\n#endif\n\n  if ($VMS_STATUS_SUCCESS (child->vms_launch_status))\n    {\n      /* Convert VMS success status to 0 for UNIX code to be happy */\n      child->vms_launch_status = 0;\n    }\n\n  /* Set the state flag to say the commands have finished.  */\n  c->file->command_state = cs_finished;\n  notice_finished_file (c->file);\n\n  (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));\n\n  return 1;\n}\n\n/* VMS:\n   Spawn a process executing the command in ARGV and return its pid. */\n\n/* local helpers to make ctrl+c and ctrl+y working, see below */\n#include <iodef.h>\n#include <libclidef.h>\n#include <ssdef.h>\n\nstatic int ctrlMask= LIB$M_CLI_CTRLY;\nstatic int oldCtrlMask;\nstatic int setupYAstTried= 0;\nstatic unsigned short int chan= 0;\n\nstatic void\nreEnableAst(void)\n{\n  lib$enable_ctrl (&oldCtrlMask,0);\n}\n\nstatic int\nastYHandler (void)\n{\n  struct child *c;\n  for (c = children; c != 0; c = c->next)\n    if (c->pid > 0)\n      sys$delprc (&c->pid, 0, 0);\n  ctrlYPressed= 1;\n  kill (getpid(),SIGQUIT);\n  return SS$_NORMAL;\n}\n\nstatic void\ntryToSetupYAst(void)\n{\n  $DESCRIPTOR(inputDsc,\"SYS$COMMAND\");\n  int     status;\n  struct {\n    short int       status, count;\n    int     dvi;\n  } iosb;\n  unsigned short int loc_chan;\n\n  setupYAstTried++;\n\n  if (chan)\n    loc_chan= chan;\n  else\n    {\n      status= sys$assign(&inputDsc,&loc_chan,0,0);\n      if (!(status&SS$_NORMAL))\n        {\n          lib$signal(status);\n          return;\n        }\n    }\n  status= sys$qiow (0, loc_chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0,\n                    astYHandler,0,0,0,0,0);\n  if (status==SS$_NORMAL)\n    status= iosb.status;\n  if (status!=SS$_NORMAL)\n    {\n      if (!chan)\n        sys$dassgn(loc_chan);\n      if (status!=SS$_ILLIOFUNC && status!=SS$_NOPRIV)\n        lib$signal(status);\n      return;\n    }\n\n  /* called from AST handler ? */\n  if (setupYAstTried>1)\n    return;\n  if (atexit(reEnableAst))\n    fprintf (stderr,\n             _(\"-warning, you may have to re-enable CTRL-Y handling from DCL.\\n\"));\n  status= lib$disable_ctrl (&ctrlMask, &oldCtrlMask);\n  if (!(status&SS$_NORMAL))\n    {\n      lib$signal(status);\n      return;\n    }\n  if (!chan)\n    chan = loc_chan;\n}\n\n/* Check if a token is too long */\n#define INC_TOKEN_LEN_OR_RETURN(x) {token->length++; \\\n  if (token->length >= MAX_DCL_TOKEN_LENGTH) \\\n    { token->cmd_errno = ERANGE; return x; }}\n\n#define INC_TOKEN_LEN_OR_BREAK {token->length++; \\\n  if (token->length >= MAX_DCL_TOKEN_LENGTH) \\\n    { token->cmd_errno = ERANGE; break; }}\n\n#define ADD_TOKEN_LEN_OR_RETURN(add_len, x) {token->length += add_len; \\\n  if (token->length >= MAX_DCL_TOKEN_LENGTH) \\\n    { token->cmd_errno = ERANGE; return x; }}\n\n/* Check if we are out of space for more tokens */\n#define V_NEXT_TOKEN { if (cmd_tkn_index < MAX_DCL_TOKENS) \\\n  cmd_tokens[++cmd_tkn_index] = NULL; \\\n  else { token.cmd_errno = E2BIG; break; } \\\n  token.length = 0;}\n\n\n#define UPDATE_TOKEN {cmd_tokens[cmd_tkn_index] = strdup(token.text); \\\n  V_NEXT_TOKEN;}\n\n#define EOS_ERROR(x) { if (*x == 0) { token->cmd_errno = ERANGE; break; }}\n\nstruct token_info\n  {\n    char *text;       /* Parsed text */\n    int length;       /* Length of parsed text */\n    char *src;        /* Pointer to source text */\n    int cmd_errno;    /* Error status of parse */\n    int use_cmd_file; /* Force use of a command file */\n  };\n\n\n/* Extract a Posix single quoted string from input line */\nstatic char *\nposix_parse_sq (struct token_info *token)\n{\n  /* A Posix quoted string with no expansion unless in a string\n     Unix simulation means no lexical functions present.\n  */\n  char * q;\n  char * p;\n  q = token->text;\n  p = token->src;\n\n  *q++ = '\"';\n  p++;\n  INC_TOKEN_LEN_OR_RETURN (p);\n\n  while (*p != '\\'' && (token->length < MAX_DCL_TOKEN_LENGTH))\n    {\n      EOS_ERROR (p);\n      if (*p == '\"')\n        {\n          /* Embedded double quotes need to be doubled */\n          *q++ = '\"';\n          INC_TOKEN_LEN_OR_BREAK;\n          *q = '\"';\n        }\n      else\n        *q = *p;\n\n      q++;\n      p++;\n      INC_TOKEN_LEN_OR_BREAK;\n    }\n  *q++ = '\"';\n  p++;\n  INC_TOKEN_LEN_OR_RETURN (p);\n  *q = 0;\n  return p;\n}\n\n/* Extract a Posix double quoted string from input line */\nstatic char *\nposix_parse_dq (struct token_info *token)\n{\n  /* Unix mode:  Any embedded \\\" becomes doubled.\n                 \\t is tab, \\\\, \\$ leading character stripped.\n                 $ character replaced with \\' unless escaped.\n  */\n  char * q;\n  char * p;\n  q = token->text;\n  p = token->src;\n  *q++ = *p++;\n  INC_TOKEN_LEN_OR_RETURN (p);\n  while (*p != 0)\n    {\n      if (*p == '\\\\')\n        {\n          switch(p[1])\n            {\n            case 't':     /* Convert tabs */\n              *q = '\\t';\n              p++;\n              break;\n            case '\\\\':     /* Just remove leading backslash */\n            case '$':\n              p++;\n              *q = *p;\n              break;\n            case '\"':\n              p++;\n              *q = *p;\n              *q++ = '\"';\n              INC_TOKEN_LEN_OR_BREAK;\n            default:      /* Pass through unchanged */\n              *q++ = *p++;\n              INC_TOKEN_LEN_OR_BREAK;\n            }\n          INC_TOKEN_LEN_OR_BREAK;\n        }\n      else if (*p == '$' && isalpha ((unsigned char) p[1]))\n        {\n          /* A symbol we should be able to substitute */\n          *q++ = '\\'';\n          INC_TOKEN_LEN_OR_BREAK;\n          *q = '\\'';\n          INC_TOKEN_LEN_OR_BREAK;\n          token->use_cmd_file = 1;\n        }\n      else\n        {\n          *q = *p;\n          INC_TOKEN_LEN_OR_BREAK;\n          if (*p == '\"')\n            {\n              p++;\n              q++;\n              break;\n            }\n        }\n      p++;\n      q++;\n    }\n  *q = 0;\n  return p;\n}\n\n/* Extract a VMS quoted string or substitution string from input line */\nstatic char *\nvms_parse_quotes (struct token_info *token)\n{\n  /* VMS mode, the \\' means that a symbol substitution is starting\n     so while you might think you can just copy until the next\n     \\'.  Unfortunately the substitution can be a lexical function\n     which can contain embedded strings and lexical functions.\n     Messy, so both types need to be handled together.\n  */\n  char * q;\n  char * p;\n  q = token->text;\n  p = token->src;\n  int parse_level[MAX_DCL_TOKENS + 1];\n  int nest = 0;\n\n  parse_level[0] = *p;\n  if (parse_level[0] == '\\'')\n    token->use_cmd_file = 1;\n\n  *q++ = *p++;\n  INC_TOKEN_LEN_OR_RETURN (p);\n\n\n  /* Copy everything until after the next single quote at nest == 0 */\n  while (token->length < MAX_DCL_TOKEN_LENGTH)\n    {\n      EOS_ERROR (p);\n      *q = *p;\n      INC_TOKEN_LEN_OR_BREAK;\n      if ((*p == parse_level[nest]) && (p[1] != '\"'))\n        {\n          if (nest == 0)\n            {\n              *q++ = *p++;\n              break;\n            }\n          nest--;\n        }\n      else\n        {\n          switch(*p)\n            {\n            case '\\\\':\n              /* Handle continuation on to next line */\n              if (p[1] != '\\n')\n                break;\n              p++;\n              p++;\n              *q = *p;\n              break;\n            case '(':\n              /* Parenthesis only in single quote level */\n              if (parse_level[nest] == '\\'')\n                {\n                  nest++;\n                  parse_level[nest] == ')';\n                }\n              break;\n            case '\"':\n              /* Double quotes only in parenthesis */\n              if (parse_level[nest] == ')')\n                {\n                  nest++;\n                  parse_level[nest] == '\"';\n                }\n              break;\n            case '\\'':\n              /* Symbol substitution only in double quotes */\n              if ((p[1] == '\\'') && (parse_level[nest] == '\"'))\n                {\n                  nest++;\n                  parse_level[nest] == '\\'';\n                  *p++ = *q++;\n                  token->use_cmd_file = 1;\n                  INC_TOKEN_LEN_OR_BREAK;\n                  break;\n                }\n              *q = *p;\n            }\n        }\n      p++;\n      q++;\n      /* Pass through doubled double quotes */\n      if ((*p == '\"') && (p[1] == '\"') && (parse_level[nest] == '\"'))\n      {\n        *p++ = *q++;\n        INC_TOKEN_LEN_OR_BREAK;\n        *p++ = *q++;\n        INC_TOKEN_LEN_OR_BREAK;\n      }\n    }\n  *q = 0;\n  return p;\n}\n\n/* Extract a $ string from the input line */\nstatic char *\nposix_parse_dollar (struct token_info *token)\n{\n  /* $foo becomes 'foo' */\n  char * q;\n  char * p;\n  q = token->text;\n  p = token->src;\n  token->use_cmd_file = 1;\n\n  p++;\n  *q++ = '\\'';\n  INC_TOKEN_LEN_OR_RETURN (p);\n\n  while ((isalnum ((unsigned char) *p)) || (*p == '_'))\n    {\n      *q++ = *p++;\n      INC_TOKEN_LEN_OR_BREAK;\n    }\n  *q++ = '\\'';\n  while (1)\n    {\n      INC_TOKEN_LEN_OR_BREAK;\n      break;\n    }\n  *q = 0;\n  return p;\n}\n\nconst char *vms_filechars = \"0123456789abcdefghijklmnopqrstuvwxyz\" \\\n   \"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]<>:/_-.$\";\n\n/* Simple text copy */\nstatic char *\nparse_text (struct token_info *token, int assignment_hack)\n{\n  char * q;\n  char * p;\n  int str_len;\n  q = token->text;\n  p = token->src;\n\n  /* If assignment hack, then this text needs to be double quoted. */\n  if (vms_unix_simulation && (assignment_hack == 2))\n    {\n      *q++ = '\"';\n      INC_TOKEN_LEN_OR_RETURN (p);\n    }\n\n  *q++ = *p++;\n  INC_TOKEN_LEN_OR_RETURN (p);\n\n  while (*p != 0)\n    {\n      str_len = strspn (p, vms_filechars);\n      if (str_len == 0)\n        {\n          /* Pass through backslash escapes in Unix simulation\n             probably will not work anyway.\n             All any character after a ^ otherwise to support EFS.\n          */\n          if (vms_unix_simulation && (p[0] == '\\\\') && (p[1] != 0))\n            str_len = 2;\n          else if ((p[0] == '^') && (p[1] != 0))\n            str_len = 2;\n          else if (!vms_unix_simulation && (p[0] == ';'))\n            str_len = 1;\n\n          if (str_len == 0)\n            {\n              /* If assignment hack, then this needs to be double quoted. */\n              if (vms_unix_simulation && (assignment_hack == 2))\n              {\n                *q++ = '\"';\n                INC_TOKEN_LEN_OR_RETURN (p);\n              }\n              *q = 0;\n              return p;\n            }\n        }\n      if (str_len > 0)\n        {\n          ADD_TOKEN_LEN_OR_RETURN (str_len, p);\n          strncpy (q, p, str_len);\n          p += str_len;\n          q += str_len;\n          *q = 0;\n        }\n    }\n  /* If assignment hack, then this text needs to be double quoted. */\n  if (vms_unix_simulation && (assignment_hack == 2))\n    {\n      *q++ = '\"';\n      INC_TOKEN_LEN_OR_RETURN (p);\n    }\n  return p;\n}\n\n/* single character copy */\nstatic char *\nparse_char (struct token_info *token, int count)\n{\n  char * q;\n  char * p;\n  q = token->text;\n  p = token->src;\n\n  while (count > 0)\n    {\n      *q++ = *p++;\n      INC_TOKEN_LEN_OR_RETURN (p);\n      count--;\n    }\n  *q = 0;\n  return p;\n}\n\n/* Build a command string from the collected tokens\n   and process built-ins now\n*/\nstatic struct dsc$descriptor_s *\nbuild_vms_cmd (char **cmd_tokens,\n               enum auto_pipe use_pipe_cmd,\n               int append_token)\n{\n  struct dsc$descriptor_s *cmd_dsc;\n  int cmd_tkn_index;\n  char * cmd;\n  int cmd_len;\n  int semicolon_seen;\n\n  cmd_tkn_index = 0;\n  cmd_dsc = xmalloc (sizeof (struct dsc$descriptor_s));\n\n  /* Empty command? */\n  if (cmd_tokens[0] == NULL)\n    {\n      cmd_dsc->dsc$a_pointer = NULL;\n      cmd_dsc->dsc$w_length = 0;\n      return cmd_dsc;\n    }\n\n  /* Max DCL command + 1 extra token and trailing space */\n  cmd = xmalloc (MAX_DCL_CMD_LINE_LENGTH + 256);\n\n  cmd[0] = '$';\n  cmd[1] = 0;\n  cmd_len = 1;\n\n  /* Handle real or auto-pipe */\n  if (use_pipe_cmd == add_pipe)\n    {\n      /* We need to auto convert to a pipe command */\n      strcat (cmd, \"pipe \");\n      cmd_len += 5;\n    }\n\n  semicolon_seen = 0;\n  while (cmd_tokens[cmd_tkn_index] != NULL)\n    {\n\n      /* Check for buffer overflow */\n      if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n        {\n          errno = E2BIG;\n          break;\n        }\n\n      /* Eliminate double ';' */\n      if (semicolon_seen && (cmd_tokens[cmd_tkn_index][0] == ';'))\n        {\n          semicolon_seen = 0;\n          free (cmd_tokens[cmd_tkn_index++]);\n          if (cmd_tokens[cmd_tkn_index] == NULL)\n            break;\n        }\n\n      /* Special handling for CD built-in */\n      if (strncmp (cmd_tokens[cmd_tkn_index], \"builtin_cd\", 11) == 0)\n        {\n          int result;\n          semicolon_seen = 0;\n          free (cmd_tokens[cmd_tkn_index]);\n          cmd_tkn_index++;\n          if (cmd_tokens[cmd_tkn_index] == NULL)\n            break;\n          DB(DB_JOBS, (_(\"BUILTIN CD %s\\n\"), cmd_tokens[cmd_tkn_index]));\n\n          /* TODO: chdir fails with some valid syntaxes */\n          result = chdir (cmd_tokens[cmd_tkn_index]);\n          if (result != 0)\n            {\n              /* TODO: Handle failure better */\n              free (cmd);\n              while (cmd_tokens[cmd_tkn_index] == NULL)\n                free (cmd_tokens[cmd_tkn_index++]);\n              cmd_dsc->dsc$w_length = -1;\n              cmd_dsc->dsc$a_pointer = NULL;\n              return cmd_dsc;\n            }\n        }\n      else if (strncmp (cmd_tokens[cmd_tkn_index], \"exit\", 5) == 0)\n        {\n          /* Copy the exit command */\n          semicolon_seen = 0;\n          strcpy (&cmd[cmd_len], cmd_tokens[cmd_tkn_index]);\n          cmd_len += strlen (cmd_tokens[cmd_tkn_index]);\n          free (cmd_tokens[cmd_tkn_index++]);\n          if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n            {\n              errno = E2BIG;\n              break;\n            }\n\n          /* Optional whitespace */\n          if (isspace ((unsigned char) cmd_tokens[cmd_tkn_index][0]))\n            {\n              strcpy (&cmd[cmd_len], cmd_tokens[cmd_tkn_index]);\n              cmd_len += strlen (cmd_tokens[cmd_tkn_index]);\n              free (cmd_tokens[cmd_tkn_index++]);\n              if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n              {\n                errno = E2BIG;\n                break;\n              }\n            }\n\n          /* There should be a status, but it is optional */\n          if (cmd_tokens[cmd_tkn_index][0] == ';')\n            continue;\n\n          /* If Unix simulation, add '((' */\n          if (vms_unix_simulation)\n            {\n              strcpy (&cmd[cmd_len], \"((\");\n              cmd_len += 2;\n              if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n                {\n                  errno = E2BIG;\n                  break;\n                }\n            }\n\n          /* Add the parameter */\n          strcpy (&cmd[cmd_len], cmd_tokens[cmd_tkn_index]);\n          cmd_len += strlen (cmd_tokens[cmd_tkn_index]);\n          free (cmd_tokens[cmd_tkn_index++]);\n          if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n            {\n              errno = E2BIG;\n              break;\n            }\n\n          /* Add \" * 8) .and. %x7f8) .or. %x1035a002\" */\n          if (vms_unix_simulation)\n            {\n              const char *end_str = \" * 8) .and. %x7f8) .or. %x1035a002\";\n              strcpy (&cmd[cmd_len], end_str);\n              cmd_len += strlen (end_str);\n              if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n                {\n                  errno = E2BIG;\n                  break;\n                }\n            }\n          continue;\n        }\n\n      /* auto pipe needs spaces before semicolon */\n      if (use_pipe_cmd == add_pipe)\n        if (cmd_tokens[cmd_tkn_index][0] == ';')\n          {\n            cmd[cmd_len++] = ' ';\n            semicolon_seen = 1;\n            if (cmd_len > MAX_DCL_CMD_LINE_LENGTH)\n              {\n                errno = E2BIG;\n                break;\n              }\n          }\n        else\n          {\n            char ch;\n            ch = cmd_tokens[cmd_tkn_index][0];\n            if (!(ch == ' ' || ch == '\\t'))\n              semicolon_seen = 0;\n          }\n\n      strcpy (&cmd[cmd_len], cmd_tokens[cmd_tkn_index]);\n      cmd_len += strlen (cmd_tokens[cmd_tkn_index]);\n\n      free (cmd_tokens[cmd_tkn_index++]);\n\n      /* Skip the append tokens if they exist */\n      if (cmd_tkn_index == append_token)\n        {\n          free (cmd_tokens[cmd_tkn_index++]);\n          if (isspace ((unsigned char) cmd_tokens[cmd_tkn_index][0]))\n            free (cmd_tokens[cmd_tkn_index++]);\n          free (cmd_tokens[cmd_tkn_index++]);\n        }\n    }\n\n  cmd[cmd_len] = 0;\n  cmd_dsc->dsc$w_length = cmd_len;\n  cmd_dsc->dsc$a_pointer = cmd;\n  cmd_dsc->dsc$b_dtype = DSC$K_DTYPE_T;\n  cmd_dsc->dsc$b_class = DSC$K_CLASS_S;\n\n  return cmd_dsc;\n}\n\npid_t\nchild_execute_job (struct childbase *child, int good_stdin UNUSED, char *argv)\n{\n  int i;\n\n  static struct dsc$descriptor_s *cmd_dsc;\n  static struct dsc$descriptor_s pnamedsc;\n  int spflags = CLI$M_NOWAIT;\n  int status;\n  int comnamelen;\n  char procname[100];\n\n  char *p;\n  char *cmd_tokens[(MAX_DCL_TOKENS * 2) + 1]; /* whitespace does not count */\n  char token_str[MAX_DCL_TOKEN_LENGTH + 1];\n  struct token_info token;\n  int cmd_tkn_index;\n  int paren_level = 0;\n  enum auto_pipe use_pipe_cmd = nopipe;\n  int append_token = -1;\n  char *append_file = NULL;\n  int unix_echo_cmd = 0;  /* Special handle Unix echo command */\n  int assignment_hack = 0; /* Handle x=y command as piped command */\n\n  /* Parse IO redirection.  */\n\n  child->comname = NULL;\n\n  DB (DB_JOBS, (\"child_execute_job (%s)\\n\", argv));\n\n  while (isspace ((unsigned char)*argv))\n    argv++;\n\n  if (*argv == 0)\n    {\n      /* Only a built-in or a null command - Still need to run term AST */\n      child->cstatus = VMS_POSIX_EXIT_MASK;\n      child->vms_launch_status = SS$_NORMAL;\n      child->efn = 0;\n      vmsHandleChildTerm (child);\n      /* TODO what is this \"magic number\" */\n      return 270163; /* Special built-in */\n    }\n\n  sprintf (procname, \"GMAKE_%05x\", getpid () & 0xfffff);\n  pnamedsc.dsc$w_length = strlen (procname);\n  pnamedsc.dsc$a_pointer = procname;\n  pnamedsc.dsc$b_dtype = DSC$K_DTYPE_T;\n  pnamedsc.dsc$b_class = DSC$K_CLASS_S;\n\n  /* Old */\n  /* Handle comments and redirection.\n     For ONESHELL, the redirection must be on the first line. Any other\n     redirection token is handled by DCL, that is, the pipe command with\n     redirection can be used, but it should not be used on the first line\n     for ONESHELL. */\n\n  /* VMS parser notes:\n     1. A token is any of DCL verbs, qualifiers, parameters, or punctuation.\n     2. Only MAX_DCL_TOKENS per line in both one line or command file mode.\n     3. Each token limited to MAC_DCL_TOKEN_LENGTH\n     4. If the line to DCL is greater than MAX_DCL_LINE_LENGTH then a\n        command file must be used.\n     5. Currently a command file must be used symbol substitution is to\n        be performed.\n     6. Currently limiting command files to 2 * MAX_DCL_TOKENS.\n\n     Build both a command file token list and command line token list\n     until it is determined that the command line limits are exceeded.\n  */\n\n  cmd_tkn_index = 0;\n  cmd_tokens[cmd_tkn_index] = NULL;\n  p = argv;\n\n  token.text = token_str;\n  token.length = 0;\n  token.cmd_errno = 0;\n  token.use_cmd_file = 0;\n\n  while (*p != 0)\n    {\n      /* We can not build this command so give up */\n      if (token.cmd_errno != 0)\n        break;\n\n      token.src = p;\n\n      switch (*p)\n        {\n        case '\\'':\n          if (vms_unix_simulation || unix_echo_cmd)\n            {\n              p = posix_parse_sq (&token);\n              UPDATE_TOKEN;\n              break;\n            }\n\n          /* VMS mode, the \\' means that a symbol substitution is starting\n             so while you might think you can just copy until the next\n             \\'.  Unfortunately the substitution can be a lexical function\n             which can contain embedded strings and lexical functions.\n             Messy.\n          */\n          p = vms_parse_quotes (&token);\n          UPDATE_TOKEN;\n          break;\n        case '\"':\n          if (vms_unix_simulation)\n            {\n              p = posix_parse_dq (&token);\n              UPDATE_TOKEN;\n              break;\n            }\n\n          /* VMS quoted string, can contain lexical functions with\n             quoted strings and nested lexical functions.\n          */\n          p = vms_parse_quotes (&token);\n          UPDATE_TOKEN;\n          break;\n\n        case '$':\n          if (vms_unix_simulation)\n            {\n              p = posix_parse_dollar (&token);\n              UPDATE_TOKEN;\n              break;\n            }\n\n          /* Otherwise nothing special */\n          p = parse_text (&token, 0);\n          UPDATE_TOKEN;\n          break;\n        case '\\\\':\n          if (p[1] == '\\n')\n            {\n              /* Line continuation, remove it */\n              p += 2;\n              break;\n            }\n\n          /* Ordinary character otherwise */\n          if (assignment_hack != 0)\n            assignment_hack++;\n          if (assignment_hack > 2)\n            {\n              assignment_hack = 0;          /* Reset */\n              if (use_pipe_cmd == nopipe)   /* force pipe use */\n                use_pipe_cmd = add_pipe;\n              token_str[0] = ';';              /* add ; token */\n              token_str[1] = 0;\n              UPDATE_TOKEN;\n            }\n          p = parse_text (&token, assignment_hack);\n          UPDATE_TOKEN;\n          break;\n        case '!':\n        case '#':\n          /* Unix '#' is VMS '!' which comments out the rest of the line.\n             Historically the rest of the line has been skipped.\n             Not quite the right thing to do, as the f$verify lexical\n             function works in comments.  But this helps keep the line\n             lengths short.\n          */\n          unix_echo_cmd = 0;\n          while (*p != '\\n' && *p != 0)\n            p++;\n          break;\n        case '(':\n          /* Subshell, equation, or lexical function argument start */\n          p = parse_char (&token, 1);\n          UPDATE_TOKEN;\n          paren_level++;\n          break;\n        case ')':\n          /* Close out a paren level */\n          p = parse_char (&token, 1);\n          UPDATE_TOKEN;\n          paren_level--;\n          /* TODO: Should we diagnose if paren_level goes negative? */\n          break;\n        case '&':\n          if (isalpha ((unsigned char) p[1]) && !vms_unix_simulation)\n            {\n              /* VMS symbol substitution */\n              p = parse_text (&token, 0);\n              token.use_cmd_file = 1;\n              UPDATE_TOKEN;\n              break;\n            }\n          if (use_pipe_cmd == nopipe)\n            use_pipe_cmd = add_pipe;\n          if (p[1] != '&')\n            p = parse_char (&token, 1);\n          else\n            p = parse_char (&token, 2);\n          UPDATE_TOKEN;\n          break;\n        case '|':\n          if (use_pipe_cmd == nopipe)\n            use_pipe_cmd = add_pipe;\n          if (p[1] != '|')\n            p = parse_char (&token, 1);\n          else\n            p = parse_char (&token, 2);\n          UPDATE_TOKEN;\n          break;\n        case ';':\n          /* Separator - convert to a pipe command. */\n          unix_echo_cmd = 0;\n        case '<':\n          if (use_pipe_cmd == nopipe)\n            use_pipe_cmd = add_pipe;\n          p = parse_char (&token, 1);\n          UPDATE_TOKEN;\n          break;\n        case '>':\n          if (use_pipe_cmd == nopipe)\n            use_pipe_cmd = add_pipe;\n          if (p[1] == '>')\n            {\n              /* Parsing would have been simple until support for the >>\n                 append redirect was added.\n                 Implementation needs:\n                 * if not exist output file create empty\n                 * open/append gnv$make_temp??? output_file\n                 * define/user sys$output gnv$make_temp???\n                 ** And all this done before the command previously tokenized.\n                 * command previously tokenized\n                 * close gnv$make_temp???\n              */\n              p = parse_char (&token, 2);\n              append_token = cmd_tkn_index;\n              token.use_cmd_file = 1;\n            }\n          else\n            p = parse_char (&token, 1);\n          UPDATE_TOKEN;\n          break;\n        case '/':\n          /* Unix path or VMS option start, read until non-path symbol */\n          if (assignment_hack != 0)\n            assignment_hack++;\n          if (assignment_hack > 2)\n            {\n              assignment_hack = 0;          /* Reset */\n              if (use_pipe_cmd == nopipe)   /* force pipe use */\n                use_pipe_cmd = add_pipe;\n              token_str[0] = ';';              /* add ; token */\n              token_str[1] = 0;\n              UPDATE_TOKEN;\n            }\n          p = parse_text (&token, assignment_hack);\n          UPDATE_TOKEN;\n          break;\n        case ':':\n          if ((p[1] == 0) || isspace ((unsigned char) p[1]))\n            {\n              /* Unix Null command - treat as comment until next command */\n              unix_echo_cmd = 0;\n              p++;\n              while (*p != 0)\n                {\n                  if (*p == ';')\n                    {\n                      /* Remove Null command from pipeline */\n                      p++;\n                      break;\n                    }\n                  p++;\n                }\n              break;\n            }\n\n          /* String assignment */\n          /* := :== or : */\n          if (p[1] != '=')\n            p = parse_char (&token, 1);\n          else if (p[2] != '=')\n            p = parse_char (&token, 2);\n          else\n            p = parse_char (&token, 3);\n          UPDATE_TOKEN;\n          break;\n        case '=':\n          /* = or == */\n          /* If this is not an echo statement, this could be a shell\n             assignment.  VMS requires the target to be quoted if it\n             is not a macro substitution */\n          if (!unix_echo_cmd && vms_unix_simulation && (assignment_hack == 0))\n            assignment_hack = 1;\n          if (p[1] != '=')\n            p = parse_char (&token, 1);\n          else\n            p = parse_char (&token, 2);\n          UPDATE_TOKEN;\n          break;\n        case '+':\n        case '-':\n        case '*':\n          p = parse_char (&token, 1);\n          UPDATE_TOKEN;\n          break;\n        case '.':\n          /* .xxx. operation, VMS does not require the trailing . */\n          p = parse_text (&token, 0);\n          UPDATE_TOKEN;\n          break;\n        default:\n          /* Skip repetitive whitespace */\n          if (isspace ((unsigned char) *p))\n            {\n              p = parse_char (&token, 1);\n\n              /* Force to a space or a tab */\n              if ((token_str[0] != ' ') ||\n                  (token_str[0] != '\\t'))\n                token_str[0] = ' ';\n              UPDATE_TOKEN;\n\n              while (isspace ((unsigned char) *p))\n                p++;\n              if (assignment_hack != 0)\n                assignment_hack++;\n              break;\n            }\n\n          if (assignment_hack != 0)\n            assignment_hack++;\n          if (assignment_hack > 2)\n            {\n              assignment_hack = 0;          /* Reset */\n              if (use_pipe_cmd == nopipe)   /* force pipe use */\n                use_pipe_cmd = add_pipe;\n              token_str[0] = ';';              /* add ; token */\n              token_str[1] = 0;\n              UPDATE_TOKEN;\n            }\n          p = parse_text (&token, assignment_hack);\n          if (strncasecmp (token.text, \"echo\", 4) == 0)\n            unix_echo_cmd = 1;\n          else if (strncasecmp (token.text, \"pipe\", 4) == 0)\n            use_pipe_cmd = dcl_pipe;\n          UPDATE_TOKEN;\n          break;\n        }\n    }\n\n  /* End up here with a list of tokens to build a command line.\n     Deal with errors detected during parsing.\n   */\n  if (token.cmd_errno != 0)\n    {\n      while (cmd_tokens[cmd_tkn_index] == NULL)\n        free (cmd_tokens[cmd_tkn_index++]);\n      child->cstatus = VMS_POSIX_EXIT_MASK | (MAKE_TROUBLE << 3);\n      child->vms_launch_status = SS$_ABORT;\n      child->efn = 0;\n      errno = token.cmd_errno;\n      return -1;\n    }\n\n  /* Save any redirection to append file */\n  if (append_token != -1)\n    {\n      int file_token;\n      char * lastdot;\n      char * lastdir;\n      char * raw_append_file;\n      file_token = append_token;\n      file_token++;\n      if (isspace ((unsigned char) cmd_tokens[file_token][0]))\n        file_token++;\n      raw_append_file = vmsify (cmd_tokens[file_token], 0);\n      /* VMS DCL needs a trailing dot if null file extension */\n      lastdot = strrchr(raw_append_file, '.');\n      lastdir = strrchr(raw_append_file, ']');\n      if (lastdir == NULL)\n        lastdir = strrchr(raw_append_file, '>');\n      if (lastdir == NULL)\n        lastdir = strrchr(raw_append_file, ':');\n      if ((lastdot == NULL) || (lastdot > lastdir))\n        {\n          append_file = xmalloc (strlen (raw_append_file) + 1);\n          strcpy (append_file, raw_append_file);\n          strcat (append_file, \".\");\n        }\n      else\n        append_file = strdup(raw_append_file);\n    }\n\n  cmd_dsc = build_vms_cmd (cmd_tokens, use_pipe_cmd, append_token);\n  if (cmd_dsc->dsc$a_pointer == NULL)\n    {\n      if (cmd_dsc->dsc$w_length < 0)\n        {\n          free (cmd_dsc);\n          child->cstatus = VMS_POSIX_EXIT_MASK | (MAKE_TROUBLE << 3);\n          child->vms_launch_status = SS$_ABORT;\n          child->efn = 0;\n          return -1;\n        }\n\n      /* Only a built-in or a null command - Still need to run term AST */\n      free (cmd_dsc);\n      child->cstatus = VMS_POSIX_EXIT_MASK;\n      child->vms_launch_status = SS$_NORMAL;\n      child->efn = 0;\n      vmsHandleChildTerm (child);\n      /* TODO what is this \"magic number\" */\n      return 270163; /* Special built-in */\n    }\n\n  if (cmd_dsc->dsc$w_length > MAX_DCL_LINE_LENGTH)\n    token.use_cmd_file = 1;\n\n  DB(DB_JOBS, (_(\"DCL: %s\\n\"), cmd_dsc->dsc$a_pointer));\n\n  /* Enforce the creation of a command file if \"vms_always_use_cmd_file\" is\n     non-zero.\n     Further, this way DCL reads the input stream and therefore does\n     'forced' symbol substitution, which it doesn't do for one-liners when\n     they are 'lib$spawn'ed.\n\n     Otherwise the behavior is:\n\n     Create a *.com file if either the command is too long for\n     lib$spawn, or if a redirect appending to a file is desired, or\n     symbol substitution.\n  */\n\n  if (vms_always_use_cmd_file || token.use_cmd_file)\n    {\n      FILE *outfile;\n      int cmd_len;\n\n      outfile = get_tmpfile (&child->comname);\n\n      comnamelen = strlen (child->comname);\n\n      /* The whole DCL \"script\" is executed as one action, and it behaves as\n         any DCL \"script\", that is errors stop it but warnings do not. Usually\n         the command on the last line, defines the exit code.  However, with\n         redirections there is a prolog and possibly an epilog to implement\n         the redirection.  Both are part of the script which is actually\n         executed. So if the redirection encounters an error in the prolog,\n         the user actions will not run; if in the epilog, the user actions\n         ran, but output is not captured. In both error cases, the error of\n         redirection is passed back and not the exit code of the actions. The\n         user should be able to enable DCL \"script\" verification with \"set\n         verify\". However, the prolog and epilog commands are not shown. Also,\n         if output redirection is used, the verification output is redirected\n         into that file as well. */\n      fprintf (outfile, \"$ gnv$$make_verify = \\\"''f$verify(0)'\\\"\\n\");\n      fprintf (outfile, \"$ gnv$$make_pid = f$getjpi(\\\"\\\",\\\"pid\\\")\\n\");\n      fprintf (outfile, \"$ on error then $ goto gnv$$make_error\\n\");\n\n      /* Handle append redirection */\n      if (append_file != NULL)\n        {\n          /* If file does not exist, create it */\n          fprintf (outfile,\n                   \"$ gnv$$make_al = \\\"gnv$$make_append''gnv$$make_pid'\\\"\\n\");\n          fprintf (outfile,\n                   \"$ if f$search(\\\"%s\\\") .eqs. \\\"\\\" then create %s\\n\",\n                   append_file, append_file);\n\n          fprintf (outfile,\n                   \"$ open/append 'gnv$$make_al' %s\\n\", append_file);\n\n          /* define sys$output to that file */\n          fprintf (outfile,\n                   \"$ define/user sys$output 'gnv$$make_al'\\n\");\n          DB (DB_JOBS, (_(\"Append output to %s\\n\"), append_file));\n          free(append_file);\n        }\n\n      fprintf (outfile, \"$ gnv$$make_verify = f$verify(gnv$$make_verify)\\n\");\n\n      /* TODO:\n         Only for ONESHELL there will be several commands separated by\n         '\\n'. But there can always be multiple continuation lines.\n      */\n\n      fprintf (outfile, \"%s\\n\", cmd_dsc->dsc$a_pointer);\n      fprintf (outfile, \"$ gnv$$make_status_2 = $status\\n\");\n      fprintf (outfile, \"$ goto gnv$$make_exit\\n\");\n\n      /* Exit and clean up */\n      fprintf (outfile, \"$ gnv$$make_error: ! 'f$verify(0)\\n\");\n      fprintf (outfile, \"$ gnv$$make_status_2 = $status\\n\");\n\n      if (append_token != -1)\n        {\n          fprintf (outfile, \"$ deassign sys$output\\n\");\n          fprintf (outfile, \"$ close 'gnv$$make_al'\\n\");\n\n          DB (DB_JOBS,\n              (_(\"Append %.*s and cleanup\\n\"), comnamelen-3, child->comname));\n        }\n      fprintf (outfile, \"$ gnv$$make_exit: ! 'f$verify(0)\\n\");\n      fprintf (outfile,\n             \"$ exit 'gnv$$make_status_2' + (0*f$verify(gnv$$make_verify))\\n\");\n\n      fclose (outfile);\n\n      free (cmd_dsc->dsc$a_pointer);\n      cmd_dsc->dsc$a_pointer = xmalloc (256 + 4);\n      sprintf (cmd_dsc->dsc$a_pointer, \"$ @%s\", child->comname);\n      cmd_dsc->dsc$w_length = strlen (cmd_dsc->dsc$a_pointer);\n\n      DB (DB_JOBS, (_(\"Executing %s instead\\n\"), child->comname));\n    }\n\n  child->efn = 0;\n  while (child->efn < 32 || child->efn > 63)\n    {\n      status = LIB$GET_EF ((unsigned long *)&child->efn);\n      if (!$VMS_STATUS_SUCCESS (status))\n        {\n          if (child->comname)\n            {\n              if (!ISDB (DB_JOBS))\n                unlink (child->comname);\n              free (child->comname);\n            }\n          return -1;\n        }\n    }\n\n  SYS$CLREF (child->efn);\n\n  vms_jobsefnmask |= (1 << (child->efn - 32));\n\n  /* Export the child environment into DCL symbols */\n  if (child->environment != 0)\n    {\n      char **ep = child->environment;\n      while (*ep != 0)\n        {\n          vms_putenv_symbol (*ep);\n          *ep++;\n        }\n    }\n\n  /*\n    LIB$SPAWN  [command-string]\n    [,input-file]\n    [,output-file]\n    [,flags]\n    [,process-name]\n    [,process-id] [,completion-status-address] [,byte-integer-event-flag-num]\n    [,AST-address] [,varying-AST-argument]\n    [,prompt-string] [,cli] [,table]\n  */\n\n#ifndef DONTWAITFORCHILD\n  /*\n   * Code to make ctrl+c and ctrl+y working.\n   * The problem starts with the synchronous case where after lib$spawn is\n   * called any input will go to the child. But with input re-directed,\n   * both control characters won't make it to any of the programs, neither\n   * the spawning nor to the spawned one. Hence the caller needs to spawn\n   * with CLI$M_NOWAIT to NOT give up the input focus. A sys$waitfr\n   * has to follow to simulate the wanted synchronous behaviour.\n   * The next problem is ctrl+y which isn't caught by the crtl and\n   * therefore isn't converted to SIGQUIT (for a signal handler which is\n   * already established). The only way to catch ctrl+y, is an AST\n   * assigned to the input channel. But ctrl+y handling of DCL needs to be\n   * disabled, otherwise it will handle it. Not to mention the previous\n   * ctrl+y handling of DCL needs to be re-established before make exits.\n   * One more: At the time of LIB$SPAWN signals are blocked. SIGQUIT will\n   * make it to the signal handler after the child \"normally\" terminates.\n   * This isn't enough. It seems reasonable for simple command lines like\n   * a 'cc foobar.c' spawned in a subprocess but it is unacceptable for\n   * spawning make. Therefore we need to abort the process in the AST.\n   *\n   * Prior to the spawn it is checked if an AST is already set up for\n   * ctrl+y, if not one is set up for a channel to SYS$COMMAND. In general\n   * this will work except if make is run in a batch environment, but there\n   * nobody can press ctrl+y. During the setup the DCL handling of ctrl+y\n   * is disabled and an exit handler is established to re-enable it.\n   * If the user interrupts with ctrl+y, the assigned AST will fire, force\n   * an abort to the subprocess and signal SIGQUIT, which will be caught by\n   * the already established handler and will bring us back to common code.\n   * After the spawn (now /nowait) a sys$waitfr simulates the /wait and\n   * enables the ctrl+y be delivered to this code. And the ctrl+c too,\n   * which the crtl converts to SIGINT and which is caught by the common\n   * signal handler. Because signals were blocked before entering this code\n   * sys$waitfr will always complete and the SIGQUIT will be processed after\n   * it (after termination of the current block, somewhere in common code).\n   * And SIGINT too will be delayed. That is ctrl+c can only abort when the\n   * current command completes. Anyway it's better than nothing :-)\n   */\n\n  if (!setupYAstTried)\n    tryToSetupYAst();\n  child->vms_launch_status = lib$spawn (cmd_dsc,               /* cmd-string */\n                     NULL, /* input-file */\n                     NULL, /* output-file */\n                     &spflags,                                 /* flags */\n                     &pnamedsc,                                /* proc name */\n                     &child->pid, &child->cstatus, &child->efn,\n                     0, 0,\n                     0, 0, 0);\n\n  status = child->vms_launch_status;\n  if ($VMS_STATUS_SUCCESS (status))\n    {\n      status = sys$waitfr (child->efn);\n      vmsHandleChildTerm (child);\n    }\n#else\n  child->vms_launch_status = lib$spawn (cmd_dsc,\n                      NULL,\n                      NULL,\n                      &spflags,\n                      &pnamedsc,\n                      &child->pid, &child->cstatus, &child->efn,\n                      vmsHandleChildTerm, child,\n                      0, 0, 0);\n   status = child->vms_launch_status;\n#endif\n\n  /* Free the pointer if not a command file */\n  if (!vms_always_use_cmd_file && !token.use_cmd_file)\n    free (cmd_dsc->dsc$a_pointer);\n  free (cmd_dsc);\n\n  if (!$VMS_STATUS_SUCCESS (status))\n    {\n      switch (status)\n        {\n        case SS$_EXQUOTA:\n          errno = EPROCLIM;\n          break;\n        default:\n          errno = EFAIL;\n        }\n    }\n\n  /* Restore the VMS symbols that were changed */\n  if (child->environment != 0)\n    {\n      char **ep = child->environment;\n      while (*ep != 0)\n        {\n          vms_restore_symbol (*ep);\n          *ep++;\n        }\n    }\n\n  /* TODO what is this \"magic number\" */\n  return (status & 1) ? 270163 : -1 ;\n}\n"
  },
  {
    "path": "src/vpath.c",
    "content": "/* Implementation of pattern-matching file search paths for GNU Make.\nCopyright (C) 1988-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"filedef.h\"\n#include \"variable.h\"\n#if MK_OS_W32\n#include \"pathstuff.h\"\n#endif\n\n\n/* Structure used to represent a selective VPATH searchpath.  */\n\nstruct vpath\n  {\n    struct vpath *next;      /* Pointer to next struct in the linked list.  */\n    const char *pattern;     /* The pattern to match.  */\n    const char *percent;     /* Pointer into 'pattern' where the '%' is.  */\n    size_t patlen;           /* Length of the pattern.  */\n    const char **searchpath; /* Null-terminated list of directories.  */\n    size_t maxlen;           /* Maximum length of any entry in the list.  */\n  };\n\n/* Linked-list of all selective VPATHs.  */\n\nstatic struct vpath *vpaths;\n\n/* Structure for the general VPATH given in the variable.  */\n\nstatic struct vpath *general_vpath;\n\n/* Structure for GPATH given in the variable.  */\n\nstatic struct vpath *gpaths;\n\f\n\n/* Reverse the chain of selective VPATH lists so they will be searched in the\n   order given in the makefiles and construct the list from the VPATH\n   variable.  */\n\nvoid\nbuild_vpath_lists (void)\n{\n  struct vpath *new = 0;\n  struct vpath *old, *nexto;\n  char *p;\n\n  /* Reverse the chain.  */\n  for (old = vpaths; old != 0; old = nexto)\n    {\n      nexto = old->next;\n      old->next = new;\n      new = old;\n    }\n\n  vpaths = new;\n\n  /* If there is a VPATH variable with a nonnull expanded value, construct the\n     general VPATH list from it.  */\n\n  p = expand_variable (\"VPATH\", 5);\n  NEXT_TOKEN (p);\n\n  if (*p != '\\0')\n    {\n      /* Save the list of vpaths.  */\n      struct vpath *save_vpaths = vpaths;\n      char gp[] = \"%\";\n\n      /* Empty 'vpaths' so the new one will have no next, and 'vpaths'\n         will still be nil if P contains no existing directories.  */\n      vpaths = 0;\n\n      /* Parse P.  */\n      construct_vpath_list (gp, p);\n\n      /* Store the created path as the general path,\n         and restore the old list of vpaths.  */\n      general_vpath = vpaths;\n      vpaths = save_vpaths;\n    }\n\n  /* If there is a GPATH variable with a nonnull expanded value, construct the\n     GPATH list from it.  */\n\n  p = expand_variable (\"GPATH\", 5);\n  NEXT_TOKEN (p);\n\n  if (*p != '\\0')\n    {\n      /* Save the list of vpaths.  */\n      struct vpath *save_vpaths = vpaths;\n      char gp[] = \"%\";\n\n      /* Empty 'vpaths' so the new one will have no next, and 'vpaths'\n         will still be nil if P contains no existing directories.  */\n      vpaths = 0;\n\n      /* Parse P.  */\n      construct_vpath_list (gp, p);\n\n      /* Store the created path as the GPATH,\n         and restore the old list of vpaths.  */\n      gpaths = vpaths;\n      vpaths = save_vpaths;\n    }\n}\n\f\n/* Construct the VPATH listing for the PATTERN and DIRPATH given.\n\n   This function is called to generate selective VPATH lists and also for\n   the general VPATH list (which is in fact just a selective VPATH that\n   is applied to everything).  The returned pointer is either put in the\n   linked list of all selective VPATH lists or in the GENERAL_VPATH\n   variable.\n\n   If DIRPATH is nil, remove all previous listings with the same\n   pattern.  If PATTERN is nil, remove all VPATH listings.  Existing\n   and readable directories that are not \".\" given in the DIRPATH\n   separated by the path element separator (defined in makeint.h) are\n   loaded into the directory hash table if they are not there already\n   and put in the VPATH searchpath for the given pattern with trailing\n   slashes stripped off if present (and if the directory is not the\n   root, \"/\").  The length of the longest entry in the list is put in\n   the structure as well.  The new entry will be at the head of the\n   VPATHS chain.  */\n\nvoid\nconstruct_vpath_list (char *pattern, char *dirpath)\n{\n  unsigned int elem;\n  char *p;\n  const char **vpath;\n  size_t maxvpath;\n  unsigned int maxelem;\n  const char *percent = NULL;\n\n  if (pattern != 0)\n    percent = find_percent (pattern);\n\n  if (dirpath == 0)\n    {\n      /* Remove matching listings.  */\n      struct vpath *path, *lastpath;\n\n      lastpath = 0;\n      path = vpaths;\n      while (path != 0)\n        {\n          struct vpath *next = path->next;\n\n          if (pattern == 0\n              || (((percent == 0 && path->percent == 0)\n                   || (percent - pattern == path->percent - path->pattern))\n                  && streq (pattern, path->pattern)))\n            {\n              /* Remove it from the linked list.  */\n              if (lastpath == 0)\n                vpaths = path->next;\n              else\n                lastpath->next = next;\n\n              /* Free its unused storage.  */\n              /* MSVC erroneously warns without a cast here.  */\n              free ((void *)path->searchpath);\n              free (path);\n            }\n          else\n            lastpath = path;\n\n          path = next;\n        }\n\n      return;\n    }\n\n#if MK_OS_W32\n    convert_vpath_to_windows32 (dirpath, ';');\n#endif\n\n  /* Skip over any initial separators and blanks.  */\n  while (STOP_SET (*dirpath, MAP_BLANK|MAP_PATHSEP))\n    ++dirpath;\n\n  /* Figure out the maximum number of VPATH entries and put it in\n     MAXELEM.  We start with 2, one before the first separator and one\n     nil (the list terminator) and increment our estimated number for\n     each separator or blank we find.  */\n  maxelem = 2;\n  p = dirpath;\n  while (*p != '\\0')\n    if (STOP_SET (*p++, MAP_BLANK|MAP_PATHSEP))\n      ++maxelem;\n\n  vpath = xmalloc (maxelem * sizeof (const char *));\n  maxvpath = 0;\n\n  elem = 0;\n  p = dirpath;\n  while (*p != '\\0')\n    {\n      char *v;\n      size_t len;\n\n      /* Find the end of this entry.  */\n      v = p;\n      while (*p != '\\0'\n#if defined(HAVE_DOS_PATHS) && (PATH_SEPARATOR_CHAR == ':')\n             /* Platforms whose PATH_SEPARATOR_CHAR is ':' and which\n                also define HAVE_DOS_PATHS would like us to recognize\n                colons after the drive letter in the likes of\n                \"D:/foo/bar:C:/xyzzy\".  */\n             && (*p != PATH_SEPARATOR_CHAR || (p == v + 1 && ISDIRSEP (p[1])))\n#else\n             && *p != PATH_SEPARATOR_CHAR\n#endif\n             && !ISBLANK (*p))\n        ++p;\n\n      len = p - v;\n      /* Make sure there's no trailing slash,\n         but still allow \"/\" as a directory.  */\n#if MK_OS_DOS || MK_OS_OS2 || defined(HAVE_DOS_PATHS)\n      /* We need also to leave alone a trailing slash in \"d:/\".  */\n      if (len > 3 || (len > 1 && v[1] != ':'))\n#endif\n      if (len > 1 && p[-1] == '/')\n        --len;\n\n      /* Put the directory on the vpath list.  */\n      if (len > 1 || *v != '.')\n        {\n          vpath[elem++] = dir_name (strcache_add_len (v, len));\n          if (len > maxvpath)\n            maxvpath = len;\n        }\n\n      /* Skip over separators and blanks between entries.  */\n      while (STOP_SET (*p, MAP_BLANK|MAP_PATHSEP))\n        ++p;\n    }\n\n  if (elem > 0)\n    {\n      struct vpath *path;\n      /* ELEM is now incremented one element past the last\n         entry, to where the nil-pointer terminator goes.\n         Usually this is maxelem - 1.  If not, shrink down.  */\n      if (elem < (maxelem - 1))\n        vpath = xrealloc ((void *)vpath, (elem+1) * sizeof (const char *));\n\n      /* Put the nil-pointer terminator on the end of the VPATH list.  */\n      vpath[elem] = NULL;\n\n      /* Construct the vpath structure and put it into the linked list.  */\n      path = xmalloc (sizeof (struct vpath));\n      path->searchpath = vpath;\n      path->maxlen = maxvpath;\n      path->next = vpaths;\n      vpaths = path;\n\n      /* Set up the members.  */\n      path->pattern = strcache_add (pattern);\n      path->patlen = strlen (pattern);\n      path->percent = percent ? path->pattern + (percent - pattern) : 0;\n    }\n  else\n    /* There were no entries, so free whatever space we allocated.  */\n    /* MSVC erroneously warns without a cast here.  */\n    free ((void *)vpath);\n}\n\f\n/* Search the GPATH list for a pathname string that matches the one passed\n   in.  If it is found, return 1.  Otherwise we return 0.  */\n\nint\ngpath_search (const char *file, size_t len)\n{\n  if (gpaths && (len <= gpaths->maxlen))\n    {\n      const char **gp;\n      for (gp = gpaths->searchpath; *gp != NULL; ++gp)\n        if (strneq (*gp, file, len) && (*gp)[len] == '\\0')\n          return 1;\n    }\n\n  return 0;\n}\n\f\n\n/* Search the given VPATH list for a directory where the name pointed to by\n   FILE exists.  If it is found, we return a cached name of the existing file\n   and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no\n   stat call was done). Also set the matching directory index in PATH_INDEX\n   if it is not NULL. Otherwise we return NULL.  */\n\nstatic const char *\nselective_vpath_search (struct vpath *path, const char *file,\n                        FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index)\n{\n  int not_target;\n  char *name;\n  const char *n;\n  const char *filename;\n  const char **vpath = path->searchpath;\n  size_t maxvpath = path->maxlen;\n  unsigned int i;\n  size_t flen, name_dplen;\n  int exists = 0;\n\n  /* Find out if *FILE is a target.\n     If and only if it is NOT a target, we will accept prospective\n     files that don't exist but are mentioned in a makefile.  */\n  {\n    struct file *f = lookup_file (file);\n    not_target = f == 0 || !f->is_target;\n  }\n\n  flen = strlen (file);\n\n  /* Split *FILE into a directory prefix and a name-within-directory.\n     NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to\n     the name-within-directory and FLEN is its length.  */\n\n  n = strrchr (file, '/');\n#ifdef HAVE_DOS_PATHS\n  /* We need the rightmost slash or backslash.  */\n  {\n    const char *bslash = strrchr (file, '\\\\');\n    if (!n || bslash > n)\n      n = bslash;\n  }\n#endif\n  name_dplen = n != 0 ? n - file : 0;\n  filename = name_dplen > 0 ? n + 1 : file;\n  if (name_dplen > 0)\n    flen -= name_dplen + 1;\n\n  /* Get enough space for the biggest VPATH entry, a slash, the directory\n     prefix that came with FILE, another slash (although this one may not\n     always be necessary), the filename, and a null terminator.  */\n  name = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1);\n\n  /* Try each VPATH entry.  */\n  for (i = 0; vpath[i] != 0; ++i)\n    {\n      int exists_in_cache = 0;\n      char *p = name;\n      size_t vlen = strlen (vpath[i]);\n\n      /* Put the next VPATH entry into NAME at P and increment P past it.  */\n      p = mempcpy (p, vpath[i], vlen);\n\n      /* Add the directory prefix already in *FILE.  */\n      if (name_dplen > 0)\n        {\n#if !MK_OS_VMS\n          *p++ = '/';\n#else\n          /* VMS: if this is not in VMS format, treat as Unix format */\n          if ((*p != ':') && (*p != ']') && (*p != '>'))\n            *p++ = '/';\n#endif\n          p = mempcpy (p, file, name_dplen);\n        }\n\n#ifdef HAVE_DOS_PATHS\n      /* Cause the next if to treat backslash and slash alike.  */\n      if (p != name && p[-1] == '\\\\' )\n        p[-1] = '/';\n#endif\n      /* Now add the name-within-directory at the end of NAME.  */\n#if !MK_OS_VMS\n      if (p != name && p[-1] != '/')\n        {\n          *p = '/';\n          memcpy (p + 1, filename, flen + 1);\n        }\n      else\n#else\n      /* VMS use a slash if no directory terminator present */\n      if (p != name && p[-1] != '/' && p[-1] != ':' &&\n          p[-1] != '>' && p[-1] != ']')\n        {\n          *p = '/';\n          memcpy (p + 1, filename, flen + 1);\n        }\n      else\n#endif\n        memcpy (p, filename, flen + 1);\n\n      /* Check if the file is mentioned in a makefile.  If *FILE is not\n         a target, that is enough for us to decide this file exists.\n         If *FILE is a target, then the file must be mentioned in the\n         makefile also as a target to be chosen.\n\n         The restriction that *FILE must not be a target for a\n         makefile-mentioned file to be chosen was added by an\n         inadequately commented change in July 1990; I am not sure off\n         hand what problem it fixes.\n\n         In December 1993 I loosened this restriction to allow a file\n         to be chosen if it is mentioned as a target in a makefile.  This\n         seem logical.\n\n         Special handling for -W / -o: make sure we preserve the special\n         values here.  Actually this whole thing is a little bogus: I think\n         we should ditch the name/hname thing and look into the renamed\n         capability that already exists for files: that is, have a new struct\n         file* entry for the VPATH-found file, and set the renamed field if\n         we use it.\n      */\n      {\n        struct file *f = lookup_file (name);\n        if (f != 0)\n          {\n            exists = not_target || f->is_target;\n            if (exists && mtime_ptr\n                && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME))\n              {\n                *mtime_ptr = f->last_mtime;\n                mtime_ptr = 0;\n              }\n          }\n      }\n\n      if (!exists)\n        {\n          /* That file wasn't mentioned in the makefile.\n             See if it actually exists.  */\n\n#if MK_OS_VMS\n          /* For VMS syntax just use the original vpath */\n          if (*p != '/')\n            exists_in_cache = exists = dir_file_exists_p (vpath[i], filename);\n          else\n#endif\n            {\n              /* Clobber a null into the name at the last slash.\n                 Now NAME is the name of the directory to look in.  */\n              *p = '\\0';\n              /* We know the directory is in the hash table now because either\n                 construct_vpath_list or the code just above put it there.\n                 Does the file we seek exist in it?  */\n              exists_in_cache = exists = dir_file_exists_p (name, filename);\n            }\n        }\n\n      if (exists)\n        {\n          /* The file is in the directory cache.\n             Now check that it actually exists in the filesystem.\n             The cache may be out of date.  When vpath thinks a file\n             exists, but stat fails for it, confusion results in the\n             higher levels.  */\n\n          struct stat st;\n\n#if !MK_OS_VMS\n          /* Put the slash back in NAME.  */\n          *p = '/';\n#else\n          /* If the slash was removed, put it back */\n          if (*p == 0)\n            *p = '/';\n#endif\n\n          if (exists_in_cache)  /* Makefile-mentioned file need not exist.  */\n            {\n              int e;\n\n              EINTRLOOP (e, stat (name, &st)); /* Does it really exist?  */\n              if (e != 0)\n                {\n                  exists = 0;\n                  continue;\n                }\n\n              /* Store the modtime into *MTIME_PTR for the caller.  */\n              if (mtime_ptr != 0)\n                {\n                  *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st);\n                  mtime_ptr = 0;\n                }\n            }\n\n          /* We have found a file.\n             If we get here and mtime_ptr hasn't been set, record\n             UNKNOWN_MTIME to indicate this.  */\n          if (mtime_ptr != 0)\n            *mtime_ptr = UNKNOWN_MTIME;\n\n          /* Store the name we found and return it.  */\n\n          if (path_index)\n            *path_index = i;\n\n          return strcache_add_len (name, (p + 1 - name) + flen);\n        }\n    }\n\n  return 0;\n}\n\n\n/* Search the VPATH list whose pattern matches FILE for a directory where FILE\n   exists.  If it is found, return the cached name of an existing file, and\n   set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no\n   stat call was done). Also set the matching directory index in VPATH_INDEX\n   and PATH_INDEX if they are not NULL.  Otherwise we return 0.  */\n\nconst char *\nvpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr,\n              unsigned int* vpath_index, unsigned int* path_index)\n{\n  struct vpath *v;\n\n  /* If there are no VPATH entries or FILENAME starts at the root,\n     there is nothing we can do.  */\n\n  if (file[0] == '/'\n#ifdef HAVE_DOS_PATHS\n      || file[0] == '\\\\' || file[1] == ':'\n#endif\n      || (vpaths == 0 && general_vpath == 0))\n    return 0;\n\n  if (vpath_index)\n    {\n      *vpath_index = 0;\n      *path_index = 0;\n    }\n\n  for (v = vpaths; v != 0; v = v->next)\n    {\n      if (pattern_matches (v->pattern, v->percent, file))\n        {\n          const char *p = selective_vpath_search (\n            v, file, mtime_ptr, path_index);\n          if (p)\n            return p;\n        }\n\n      if (vpath_index)\n        ++*vpath_index;\n    }\n\n\n  if (general_vpath != 0)\n    {\n      const char *p = selective_vpath_search (\n        general_vpath, file, mtime_ptr, path_index);\n      if (p)\n        return p;\n    }\n\n  return 0;\n}\n\n\n\n\f\n/* Print the data base of VPATH search paths.  */\n\nvoid\nprint_vpath_data_base (void)\n{\n  unsigned int nvpaths;\n  struct vpath *v;\n\n  puts (_(\"\\n# VPATH Search Paths\\n\"));\n\n  nvpaths = 0;\n  for (v = vpaths; v != 0; v = v->next)\n    {\n      unsigned int i;\n\n      ++nvpaths;\n\n      printf (\"vpath %s \", v->pattern);\n\n      for (i = 0; v->searchpath[i] != 0; ++i)\n        printf (\"%s%c\", v->searchpath[i],\n                v->searchpath[i + 1] == 0 ? '\\n' : PATH_SEPARATOR_CHAR);\n    }\n\n  if (vpaths == 0)\n    puts (_(\"# No 'vpath' search paths.\"));\n  else\n    printf (_(\"\\n# %u 'vpath' search paths.\\n\"), nvpaths);\n\n  if (general_vpath == 0)\n    puts (_(\"\\n# No general ('VPATH' variable) search path.\"));\n  else\n    {\n      const char **path = general_vpath->searchpath;\n      unsigned int i;\n\n      fputs (_(\"\\n# General ('VPATH' variable) search path:\\n# \"), stdout);\n\n      for (i = 0; path[i] != 0; ++i)\n        printf (\"%s%c\", path[i],\n                path[i + 1] == 0 ? '\\n' : PATH_SEPARATOR_CHAR);\n    }\n}\n"
  },
  {
    "path": "src/w32/compat/dirent.c",
    "content": "/* Directory entry code for Window platforms.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n\n#include <config.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <errno.h>\n#include <string.h>\n#include <stdlib.h>\n#include \"dirent.h\"\n\n#ifndef __MINGW32__\nDIR*\nopendir(const char* pDirName)\n{\n        struct stat sb;\n        DIR*    pDir;\n        char*   pEndDirName;\n        size_t  nBufferLen;\n\n        /* sanity checks */\n        if (!pDirName) {\n                errno = EINVAL;\n                return NULL;\n        }\n        if (stat(pDirName, &sb) != 0) {\n                errno = ENOENT;\n                return NULL;\n        }\n        if ((sb.st_mode & S_IFMT) != S_IFDIR) {\n                errno = ENOTDIR;\n                return NULL;\n        }\n\n        /* allocate a DIR structure to return */\n        pDir = (DIR *) malloc(sizeof (DIR));\n\n        if (!pDir)\n                return NULL;\n\n        /* input directory name length */\n        nBufferLen = strlen(pDirName);\n\n        /* copy input directory name to DIR buffer */\n        strcpy(pDir->dir_pDirectoryName, pDirName);\n\n        /* point to end of the copied directory name */\n        pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];\n\n        /* if directory name did not end in '/' or '\\', add '/' */\n        if ((*pEndDirName != '/') && (*pEndDirName != '\\\\')) {\n                pEndDirName++;\n                *pEndDirName = '/';\n        }\n\n        /* now append the wildcard character to the buffer */\n        pEndDirName++;\n        *pEndDirName = '*';\n        pEndDirName++;\n        *pEndDirName = '\\0';\n\n        /* other values defaulted */\n        pDir->dir_nNumFiles = 0;\n        pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;\n        pDir->dir_ulCookie = __DIRENT_COOKIE;\n\n        return pDir;\n}\n\nvoid\nclosedir(DIR *pDir)\n{\n        /* got a valid pointer? */\n        if (!pDir) {\n                errno = EINVAL;\n                return;\n        }\n\n        /* sanity check that this is a DIR pointer */\n        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\n                errno = EINVAL;\n                return;\n        }\n\n        /* close the Windows32 directory handle */\n        if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)\n                FindClose(pDir->dir_hDirHandle);\n\n        free(pDir);\n\n        return;\n}\n\nstruct dirent *\nreaddir(DIR* pDir)\n{\n        WIN32_FIND_DATA wfdFindData;\n\n        if (!pDir) {\n                errno = EINVAL;\n                return NULL;\n        }\n\n        /* sanity check that this is a DIR pointer */\n        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\n                errno = EINVAL;\n                return NULL;\n        }\n\n        if (pDir->dir_nNumFiles == 0) {\n                pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);\n                if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)\n                        return NULL;\n        } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))\n                        return NULL;\n\n        /* bump count for next call to readdir() */\n        pDir->dir_nNumFiles++;\n\n        /* fill in struct dirent values */\n        pDir->dir_sdReturn.d_ino = (ino_t)-1;\n        strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);\n\n        if (wfdFindData.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)\n          pDir->dir_sdReturn.d_type = DT_CHR;\n        else if (wfdFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\n          pDir->dir_sdReturn.d_type = DT_DIR;\n        else\n          pDir->dir_sdReturn.d_type = DT_REG;\n\n        return &pDir->dir_sdReturn;\n}\n\nvoid\nrewinddir(DIR* pDir)\n{\n        if (!pDir) {\n                errno = EINVAL;\n                return;\n        }\n\n        /* sanity check that this is a DIR pointer */\n        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {\n                errno = EINVAL;\n                return;\n        }\n\n        /* close the Windows32 directory handle */\n        if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)\n                if (!FindClose(pDir->dir_hDirHandle))\n                        errno = EBADF;\n\n        /* reset members which control readdir() */\n        pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;\n        pDir->dir_nNumFiles = 0;\n\n        return;\n}\n\nvoid\nseekdir(DIR* pDir, long nPosition)\n{\n        if (!pDir)\n                return;\n\n        /* sanity check that this is a DIR pointer */\n        if (pDir->dir_ulCookie != __DIRENT_COOKIE)\n                return;\n\n        /* go back to beginning of directory */\n        rewinddir(pDir);\n\n        /* loop until we have found position we care about */\n        for (--nPosition; nPosition && readdir(pDir); nPosition--);\n\n        /* flag invalid nPosition value */\n        if (nPosition)\n                errno = EINVAL;\n\n        return;\n}\n#endif  /* !__MINGW32__ */\n"
  },
  {
    "path": "src/w32/compat/posixfcn.c",
    "content": "/* Replacements for Posix functions and Posix functionality for MS-Windows.\n\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <string.h>\n#include <io.h>\n#include <stdarg.h>\n#include <errno.h>\n#include <windows.h>\n#include \"os.h\"\n\n#include \"dlfcn.h\"\n\n#include \"job.h\"\n\n#if MAKE_LOAD\n\n/* Support for dynamic loading of objects.  */\n\nstatic DWORD last_err;\n\nvoid *\ndlopen (const char *file, int mode)\n{\n  char dllfn[MAX_PATH], *p;\n  HANDLE dllhandle;\n\n  if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0)\n    {\n      errno = EINVAL;\n      last_err = ERROR_INVALID_PARAMETER;\n      return NULL;\n    }\n\n  if (!file)\n    dllhandle = GetModuleHandle (NULL);\n  else\n    {\n      /* MSDN says to be sure to use backslashes in the DLL file name.  */\n      strcpy (dllfn, file);\n      for (p = dllfn; *p; p++)\n        if (*p == '/')\n          *p = '\\\\';\n\n      dllhandle = LoadLibrary (dllfn);\n    }\n  if (!dllhandle)\n    last_err = GetLastError ();\n\n  return dllhandle;\n}\n\nchar *\ndlerror (void)\n{\n  static char errbuf[1024];\n  DWORD ret;\n\n  if (!last_err)\n    return NULL;\n\n  ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM\n                       | FORMAT_MESSAGE_IGNORE_INSERTS,\n                       NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);\n  while (ret > 0 && (errbuf[ret - 1] == '\\n' || errbuf[ret - 1] == '\\r'))\n    --ret;\n\n  errbuf[ret] = '\\0';\n  if (!ret)\n    sprintf (errbuf, \"Error code %lu\", last_err);\n\n  last_err = 0;\n  return errbuf;\n}\n\nvoid *\ndlsym (void *handle, const char *name)\n{\n  FARPROC addr = NULL;\n\n  if (!handle || handle == INVALID_HANDLE_VALUE)\n    {\n      last_err = ERROR_INVALID_PARAMETER;\n      return NULL;\n    }\n\n  addr = GetProcAddress (handle, name);\n  if (!addr)\n    last_err = GetLastError ();\n\n  return (void *)addr;\n}\n\nint\ndlclose (void *handle)\n{\n  if (!handle || handle == INVALID_HANDLE_VALUE)\n    return -1;\n  if (!FreeLibrary (handle))\n    return -1;\n\n  return 0;\n}\n\n\n#endif  /* MAKE_LOAD */\n\n\n/* MS runtime's isatty returns non-zero for any character device,\n   including the null device, which is not what we want.  */\nint\nisatty (int fd)\n{\n  HANDLE fh = get_handle_for_fd (fd);\n  DWORD con_mode;\n\n  if (fh == INVALID_HANDLE_VALUE)\n    {\n      errno = EBADF;\n      return 0;\n    }\n  if (GetConsoleMode (fh, &con_mode))\n    return 1;\n\n  errno = ENOTTY;\n  return 0;\n}\n\nchar *\nttyname (int fd UNUSED)\n{\n  /* This \"knows\" that Make only asks about stdout and stderr.  A more\n     sophisticated implementation should test whether FD is open for\n     input or output.  We can do that by looking at the mode returned\n     by GetConsoleMode.  */\n  static char name[] = \"CONOUT$\";\n  return name;\n}\n"
  },
  {
    "path": "src/w32/include/dirent.h",
    "content": "/* Windows version of dirent.h\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _DIRENT_H\n#define _DIRENT_H\n\n#ifdef __MINGW32__\n# include <windows.h>\n# include_next <dirent.h>\n#else\n\n#include <stdlib.h>\n#include <windows.h>\n#include <limits.h>\n#include <sys/types.h>\n\n#ifndef NAME_MAX\n#define NAME_MAX 255\n#endif\n\n#define __DIRENT_COOKIE 0xfefeabab\n\n/* File types for `d_type'.\n   Windows only supports DT_CHR, DT_DIR, and DT_REG.  */\nenum\n  {\n    DT_UNKNOWN = 0,\n# define DT_UNKNOWN     DT_UNKNOWN\n    DT_FIFO = 1,\n# define DT_FIFO        DT_FIFO\n    DT_CHR = 2,\n# define DT_CHR         DT_CHR\n    DT_DIR = 4,\n# define DT_DIR         DT_DIR\n    DT_BLK = 6,\n# define DT_BLK         DT_BLK\n    DT_REG = 8,\n# define DT_REG         DT_REG\n    DT_LNK = 10,\n# define DT_LNK         DT_LNK\n    DT_SOCK = 12,\n# define DT_SOCK        DT_SOCK\n    DT_WHT = 14\n# define DT_WHT         DT_WHT\n  };\n\n\nstruct dirent\n  {\n    ino_t d_ino;             /* unused - no equivalent on Windows32.  */\n    unsigned char d_type;\n    char d_name[NAME_MAX+1]; /* must come last due to dir.c assumptions.  */\n  };\n\ntypedef struct dir_struct\n  {\n    ULONG   dir_ulCookie;\n    HANDLE  dir_hDirHandle;\n    DWORD   dir_nNumFiles;\n    char    dir_pDirectoryName[NAME_MAX+1];\n    struct dirent dir_sdReturn;\n  } DIR;\n\nDIR *opendir(const char *);\nstruct dirent *readdir(DIR *);\nvoid rewinddir(DIR *);\nvoid closedir(DIR *);\nvoid seekdir(DIR *, long);\n\n#endif  /* !__MINGW32__ */\n#endif\n"
  },
  {
    "path": "src/w32/include/dlfcn.h",
    "content": "/* dlfcn.h replacement for MS-Windows build.\nCopyright (C) 2013-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef DLFCN_H\n#define DLFCN_H\n\n#define RTLD_LAZY   1\n#define RTLD_NOW    2\n#define RTLD_GLOBAL 4\n\nextern void *dlopen (const char *, int);\nextern void *dlsym (void *, const char *);\nextern char *dlerror (void);\nextern int   dlclose (void *);\n\n#endif  /* DLFCN_H */\n"
  },
  {
    "path": "src/w32/include/pathstuff.h",
    "content": "/* Definitions for Windows path manipulation.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _PATHSTUFF_H\n#define _PATHSTUFF_H\n\nchar *convert_Path_to_windows32(char *Path, char to_delim);\nchar *convert_vpath_to_windows32(char *Path, char to_delim);\nchar *w32ify(const char *file, int resolve);\nchar *getcwd_fs(char *buf, int len);\n\n#endif\n"
  },
  {
    "path": "src/w32/include/sub_proc.h",
    "content": "/* Definitions for Windows process invocation.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef SUB_PROC_H\n#define SUB_PROC_H\n\n/*\n * Component Name:\n *\n * $Date$\n *\n * $Source$\n *\n * $Id$\n */\n\n#define EXTERN_DECL(entry, args) extern entry args\n#define VOID_DECL void\n\nEXTERN_DECL(HANDLE process_init, (VOID_DECL));\nEXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,\n                                     HANDLE stderrh));\nEXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,\n                                 char *exec_path, char *as_user));\nEXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,\n                                   int stdin_data_len));\nEXTERN_DECL(long process_file_io, (HANDLE proc));\nEXTERN_DECL(void process_cleanup, (HANDLE proc));\nEXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus));\nEXTERN_DECL(void process_register, (HANDLE proc));\nEXTERN_DECL(HANDLE process_easy, (char** argv, char** env,\n                                  int outfd, int errfd));\nEXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));\nEXTERN_DECL(BOOL process_table_full, (VOID_DECL));\nEXTERN_DECL(int process_table_usable_size, (VOID_DECL));\nEXTERN_DECL(int process_table_actual_size, (VOID_DECL));\nEXTERN_DECL(DWORD process_set_handles, (HANDLE *handles));\nEXTERN_DECL(DWORD process_wait_for_multiple_objects, (DWORD, const HANDLE*, BOOL, DWORD));\n\n/* support routines */\nEXTERN_DECL(long process_errno, (HANDLE proc));\nEXTERN_DECL(long process_last_err, (HANDLE proc));\nEXTERN_DECL(long process_exit_code, (HANDLE proc));\nEXTERN_DECL(long process_signal, (HANDLE proc));\nEXTERN_DECL(char * process_outbuf, (HANDLE proc));\nEXTERN_DECL(char * process_errbuf, (HANDLE proc));\nEXTERN_DECL(int process_outcnt, (HANDLE proc));\nEXTERN_DECL(int process_errcnt, (HANDLE proc));\nEXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));\n\n#endif\n"
  },
  {
    "path": "src/w32/include/w32err.h",
    "content": "/* Definitions for Windows error handling.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _W32ERR_H_\n#define _W32ERR_H_\n\n#ifndef EXTERN_DECL\n#define EXTERN_DECL(entry, args) entry args\n#endif\n\nEXTERN_DECL(const char * map_windows32_error_to_string, (DWORD error));\n\n#endif /* !_W32ERR_H */\n"
  },
  {
    "path": "src/w32/pathstuff.c",
    "content": "/* Path conversion for Windows pathnames.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include <string.h>\n#include <stdlib.h>\n#include \"pathstuff.h\"\n\n/*\n * Convert delimiter separated vpath to Canonical format.\n */\nchar *\nconvert_vpath_to_windows32(char *Path, char to_delim)\n{\n    char *etok;            /* token separator for old Path */\n\n        /*\n         * Convert all spaces to delimiters. Note that pathnames which\n         * contain blanks get trounced here. Use 8.3 format as a workaround.\n         */\n        for (etok = Path; etok && *etok; etok++)\n                if (ISBLANK ((unsigned char) *etok))\n                        *etok = to_delim;\n\n        return (convert_Path_to_windows32(Path, to_delim));\n}\n\n/*\n * Convert delimiter separated path to Canonical format.\n */\nchar *\nconvert_Path_to_windows32(char *Path, char to_delim)\n{\n    char *etok;            /* token separator for old Path */\n    char *p;            /* points to element of old Path */\n\n    /* is this a multi-element Path ? */\n    /* FIXME: Perhaps use \":;\\\"\" in strpbrk to convert all quotes to\n       delimiters as well, as a way to handle quoted directories in\n       PATH?  */\n    for (p = Path, etok = strpbrk(p, \":;\");\n         etok;\n         etok = strpbrk(p, \":;\"))\n        if ((etok - p) == 1) {\n            if (*(etok - 1) == ';' ||\n                *(etok - 1) == ':') {\n                etok[-1] = to_delim;\n                etok[0] = to_delim;\n                p = ++etok;\n                continue;    /* ignore empty bucket */\n            } else if (!isalpha ((unsigned char) *p)) {\n                /* found one to count, handle things like '.' */\n                *etok = to_delim;\n                p = ++etok;\n            } else if ((*etok == ':') && ((etok = strpbrk(etok+1, \":;\")) != NULL)) {\n                /* found one to count, handle drive letter */\n                *etok = to_delim;\n                p = ++etok;\n            } else\n                /* all finished, force abort */\n                p += strlen(p);\n        } else if (*p == '\"') { /* a quoted directory */\n            for (p++; *p && *p != '\"'; p++) /* skip quoted part */\n                ;\n            etok = strpbrk(p, \":;\");        /* find next delimiter */\n            if (etok) {\n                *etok = to_delim;\n                p = ++etok;\n            } else\n                p += strlen(p);\n        } else {\n            /* found another one, no drive letter */\n            *etok = to_delim;\n            p = ++etok;\n        }\n\n    return Path;\n}\n\n/*\n * Convert to forward slashes. Resolve to full pathname optionally\n */\nchar *\nw32ify(const char *filename, int resolve)\n{\n    static char w32_path[FILENAME_MAX];\n    char *p;\n\n    if (resolve)\n      {\n        char *fp = _fullpath (NULL, filename, sizeof (w32_path));\n        strncpy (w32_path, fp, sizeof (w32_path) - 1);\n        free (fp);\n      }\n    else\n      strncpy(w32_path, filename, sizeof (w32_path) - 1);\n\n    for (p = w32_path; p && *p; p++)\n      if (*p == '\\\\')\n        *p = '/';\n\n    return w32_path;\n}\n\nchar *\ngetcwd_fs(char* buf, int len)\n{\n        char *p = getcwd(buf, len);\n\n        if (p) {\n                char *q = w32ify(buf, 0);\n                strncpy(buf, q, len);\n        }\n\n        return p;\n}\n\n#ifdef unused\n/*\n * Convert delimiter separated pathnames (e.g. PATH) or single file pathname\n * (e.g. c:/foo, c:\\bar) to NutC format. If we are handed a string that\n * _NutPathToNutc() fails to convert, just return the path we were handed\n * and assume the caller will know what to do with it (It was probably\n * a mistake to try and convert it anyway due to some of the bizarre things\n * that might look like pathnames in makefiles).\n */\nchar *\nconvert_path_to_nutc(char *path)\n{\n    int  count;            /* count of path elements */\n    char *nutc_path;     /* new NutC path */\n    int  nutc_path_len;    /* length of buffer to allocate for new path */\n    char *pathp;        /* pointer to nutc_path used to build it */\n    char *etok;            /* token separator for old path */\n    char *p;            /* points to element of old path */\n    char sep;            /* what flavor of separator used in old path */\n    char *rval;\n\n    /* is this a multi-element path ? */\n    for (p = path, etok = strpbrk(p, \":;\"), count = 0;\n         etok;\n         etok = strpbrk(p, \":;\"))\n        if ((etok - p) == 1) {\n            if (*(etok - 1) == ';' ||\n                *(etok - 1) == ':') {\n                p = ++etok;\n                continue;    /* ignore empty bucket */\n            } else if (etok = strpbrk(etok+1, \":;\"))\n                /* found one to count, handle drive letter */\n                p = ++etok, count++;\n            else\n                /* all finished, force abort */\n                p += strlen(p);\n        } else\n            /* found another one, no drive letter */\n            p = ++etok, count++;\n\n    if (count) {\n        count++;    /* x1;x2;x3 <- need to count x3 */\n\n        /*\n         * Hazard a guess on how big the buffer needs to be.\n         * We have to convert things like c:/foo to /c=/foo.\n         */\n        nutc_path_len = strlen(path) + (count*2) + 1;\n        nutc_path = xmalloc(nutc_path_len);\n        pathp = nutc_path;\n        *pathp = '\\0';\n\n        /*\n         * Loop through PATH and convert one element of the path at at\n         * a time. Single file pathnames will fail this and fall\n         * to the logic below loop.\n         */\n        for (p = path, etok = strpbrk(p, \":;\");\n             etok;\n             etok = strpbrk(p, \":;\")) {\n\n            /* don't trip up on device specifiers or empty path slots */\n            if ((etok - p) == 1)\n                if (*(etok - 1) == ';' ||\n                    *(etok - 1) == ':') {\n                    p = ++etok;\n                    continue;\n                } else if ((etok = strpbrk(etok+1, \":;\")) == NULL)\n                    break;    /* thing found was a Windows32 pathname */\n\n            /* save separator */\n            sep = *etok;\n\n            /* terminate the current path element -- temporarily */\n            *etok = '\\0';\n\n#ifdef __NUTC__\n            /* convert to NutC format */\n            if (_NutPathToNutc(p, pathp, 0) == FALSE) {\n                free(nutc_path);\n                rval = savestring(path, strlen(path));\n                return rval;\n            }\n#else\n            *pathp++ = '/';\n            *pathp++ = p[0];\n            *pathp++ = '=';\n            *pathp++ = '/';\n            strcpy(pathp, &p[2]);\n#endif\n\n            pathp += strlen(pathp);\n            *pathp++ = ':';     /* use Unix style path separator for new path */\n            *pathp   = '\\0'; /* make sure we are null terminaed */\n\n            /* restore path separator */\n            *etok = sep;\n\n            /* point p to first char of next path element */\n            p = ++etok;\n\n        }\n    } else {\n        nutc_path_len = strlen(path) + 3;\n        nutc_path = xmalloc(nutc_path_len);\n        pathp = nutc_path;\n        *pathp = '\\0';\n        p = path;\n    }\n\n    /*\n      * OK, here we handle the last element in PATH (e.g. c of a;b;c)\n     * or the path was a single filename and will be converted\n     * here. Note, testing p here assures that we don't trip up\n     * on paths like a;b; which have trailing delimiter followed by\n     * nothing.\n     */\n    if (*p != '\\0') {\n#ifdef __NUTC__\n        if (_NutPathToNutc(p, pathp, 0) == FALSE) {\n            free(nutc_path);\n            rval = savestring(path, strlen(path));\n            return rval;\n        }\n#else\n        *pathp++ = '/';\n        *pathp++ = p[0];\n        *pathp++ = '=';\n        *pathp++ = '/';\n        strcpy(pathp, &p[2]);\n#endif\n    } else\n        *(pathp-1) = '\\0'; /* we're already done, don't leave trailing : */\n\n    rval = savestring(nutc_path, strlen(nutc_path));\n    free(nutc_path);\n    return rval;\n}\n\n#endif\n"
  },
  {
    "path": "src/w32/subproc/misc.c",
    "content": "/* Process handling for Windows\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include <config.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n#include <windows.h>\n#include \"proc.h\"\n\n\n/*\n * Description:  Convert a NULL string terminated UNIX environment block to\n *              an environment block suitable for a windows32 system call\n *\n * Returns:  TRUE= success, FALSE=fail\n *\n * Notes/Dependencies:  the environment block is sorted in case-insensitive\n *      order, is double-null terminated, and is a char *, not a char **\n */\nint _cdecl compare(const void *a1, const void *a2)\n{\n        return _stricoll(*((char**)a1),*((char**)a2));\n}\nbool_t\narr2envblk(char **arr, char **envblk_out, size_t *envsize_needed)\n{\n        char **tmp;\n        size_t size_needed;\n        int arrcnt;\n        char *ptr;\n\n        arrcnt = 0;\n        while (arr[arrcnt]) {\n                arrcnt++;\n        }\n\n        tmp = (char**) calloc(arrcnt + 1, sizeof(char *));\n        if (!tmp) {\n                return FALSE;\n        }\n\n        arrcnt = 0;\n        size_needed = *envsize_needed = 0;\n        while (arr[arrcnt]) {\n                tmp[arrcnt] = arr[arrcnt];\n                size_needed += strlen(arr[arrcnt]) + 1;\n                arrcnt++;\n        }\n        size_needed++;\n        *envsize_needed = size_needed;\n\n        qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);\n\n        ptr = *envblk_out = calloc(size_needed, 1);\n        if (!ptr) {\n                free(tmp);\n                return FALSE;\n        }\n\n        arrcnt = 0;\n        while (tmp[arrcnt]) {\n                strcpy(ptr, tmp[arrcnt]);\n                ptr += strlen(tmp[arrcnt]) + 1;\n                arrcnt++;\n        }\n\n        free(tmp);\n        return TRUE;\n}\n"
  },
  {
    "path": "src/w32/subproc/proc.h",
    "content": "/* Definitions for Windows\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#ifndef _PROC_H\n#define _PROC_H\n\ntypedef int bool_t;\n\n#define E_SCALL         101\n#define E_IO            102\n#define E_NO_MEM        103\n#define E_FORK          104\n\nextern bool_t arr2envblk(char **arr, char **envblk_out, size_t *envsize_needed);\n\n#endif\n"
  },
  {
    "path": "src/w32/subproc/sub_proc.c",
    "content": "/* Process handling for Windows.\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <assert.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <io.h>         /* for _get_osfhandle */\n#ifdef _MSC_VER\n# include <stddef.h>    /* for intptr_t */\n#else\n# include <stdint.h>\n#endif\n#include <string.h>\n#include <process.h>  /* for msvc _beginthreadex, _endthreadex */\n#include <signal.h>\n#include <windows.h>\n\n#include \"filedef.h\"\n#include \"variable.h\"\n#include \"sub_proc.h\"\n#include \"proc.h\"\n#include \"w32err.h\"\n#include \"debug.h\"\n#include \"os.h\"\n\n#define GMAKE_MAXIMUM_WAIT_OBJECTS (MAXIMUM_WAIT_OBJECTS * MAXIMUM_WAIT_OBJECTS)\n\n/* We need to move these special-case return codes out-of-band */\n#define GMAKE_WAIT_TIMEOUT      0xFFFF0102L\n#define GMAKE_WAIT_ABANDONED_0  0x00080000L\n\nstatic char *make_command_line(char *shell_name, char *exec_path, char **argv);\n\ntypedef struct sub_process_t {\n        intptr_t sv_stdin[2];\n        intptr_t sv_stdout[2];\n        intptr_t sv_stderr[2];\n        int using_pipes;\n        char *inp;\n        DWORD incnt;\n        char * volatile outp;\n        volatile DWORD outcnt;\n        char * volatile errp;\n        volatile DWORD errcnt;\n        pid_t pid;\n        int exit_code;\n        int signal;\n        long last_err;\n        long lerrno;\n} sub_process;\n\n/* keep track of children so we can implement a waitpid-like routine */\nstatic sub_process *proc_array[GMAKE_MAXIMUM_WAIT_OBJECTS];\nstatic unsigned int proc_index = 0;\nstatic unsigned int fake_exits_pending = 0;\n\n/*\n * Address the scalability limit intrisic to WaitForMultipleOjects by\n * calling WaitForMultipleObjects on 64 element chunks of the input\n * array with 0 timeout.  Exit with an appropriately conditioned result\n * or repeat again every 10 ms if no handle has signaled and the\n * requested timeout was not zero.\n */\nDWORD process_wait_for_multiple_objects(\n  DWORD nCount,\n  const HANDLE *lpHandles,\n  BOOL bWaitAll,\n  DWORD dwMilliseconds\n)\n{\n  assert(nCount <= GMAKE_MAXIMUM_WAIT_OBJECTS);\n\n  if (nCount <= MAXIMUM_WAIT_OBJECTS) {\n    DWORD retVal =  WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);\n    return (retVal == WAIT_TIMEOUT) ? GMAKE_WAIT_TIMEOUT : retVal;\n  } else {\n    for (;;) {\n      DWORD objectCount = nCount;\n      int blockCount  = 0;\n      DWORD retVal = 0;\n\n      assert(bWaitAll == FALSE); /* This logic only works for this use case */\n      assert(dwMilliseconds == 0 || dwMilliseconds == INFINITE); /* No support for timeouts */\n\n      for (; objectCount > 0; blockCount++) {\n        DWORD n = objectCount <= MAXIMUM_WAIT_OBJECTS ? objectCount : MAXIMUM_WAIT_OBJECTS;\n        objectCount -= n;\n        retVal = WaitForMultipleObjects(n, &lpHandles[blockCount * MAXIMUM_WAIT_OBJECTS],\n                                            FALSE, 0);\n        switch (retVal) {\n          case WAIT_TIMEOUT:\n            retVal = GMAKE_WAIT_TIMEOUT;\n            continue;\n            break;\n          case WAIT_FAILED:\n            fprintf(stderr,\"WaitForMultipleOjbects failed waiting with error %lu\\n\", GetLastError());\n            break;\n          default:\n            if (retVal >= WAIT_ABANDONED_0) {\n              assert(retVal < WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS);\n              retVal += blockCount * MAXIMUM_WAIT_OBJECTS - WAIT_ABANDONED_0 + GMAKE_WAIT_ABANDONED_0;\n            } else {\n              assert(retVal < WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS);\n              retVal += blockCount * MAXIMUM_WAIT_OBJECTS;\n            }\n            break;\n        }\n\n        return retVal;\n\n      }\n\n      if (dwMilliseconds == 0) return retVal;\n\n      Sleep(10);  /* Sleep for 10 ms */\n    }\n  }\n}\n\n/*\n * Fill a HANDLE list with handles to wait for.\n */\nDWORD\nprocess_set_handles(HANDLE *handles)\n{\n    DWORD count = 0;\n    unsigned int i;\n\n    /* Build array of handles to wait for */\n    for (i = 0; i < proc_index; i++) {\n        /* Don't wait on child processes that have already finished */\n        if (fake_exits_pending && proc_array[i]->exit_code)\n            continue;\n\n        handles[count++] = (HANDLE) proc_array[i]->pid;\n    }\n\n    return count;\n}\n\n/*\n * When a process has been waited for, adjust the wait state\n * array so that we don't wait for it again\n */\nstatic void\nprocess_adjust_wait_state(sub_process* pproc)\n{\n        unsigned int i;\n\n        if (!proc_index)\n                return;\n\n        for (i = 0; i < proc_index; i++)\n                if (proc_array[i]->pid == pproc->pid)\n                        break;\n\n        if (i < proc_index) {\n                proc_index--;\n                if (i != proc_index)\n                        memmove(&proc_array[i], &proc_array[i+1],\n                                (proc_index-i) * sizeof(sub_process*));\n                proc_array[proc_index] = NULL;\n        }\n}\n\n/*\n * Waits for any of the registered child processes to finish.\n */\nstatic sub_process *\nprocess_wait_for_any_private(int block, DWORD* pdwWaitStatus)\n{\n        HANDLE handles[GMAKE_MAXIMUM_WAIT_OBJECTS];\n        DWORD retval, which;\n        unsigned int i;\n\n        if (!proc_index)\n                return NULL;\n\n        /* build array of handles to wait for */\n        for (i = 0; i < proc_index; i++) {\n                handles[i] = (HANDLE) proc_array[i]->pid;\n\n                if (fake_exits_pending && proc_array[i]->exit_code)\n                        break;\n        }\n\n        /* wait for someone to exit */\n        if (!fake_exits_pending) {\n                retval = process_wait_for_multiple_objects(proc_index, handles, FALSE, (block ? INFINITE : 0));\n                which = retval - WAIT_OBJECT_0;\n        } else {\n                fake_exits_pending--;\n                retval = !WAIT_FAILED;\n                which = i;\n        }\n\n        /* If the pointer is not NULL, set the wait status result variable. */\n        if (pdwWaitStatus)\n                *pdwWaitStatus = (retval == GMAKE_WAIT_TIMEOUT) ? WAIT_TIMEOUT : retval;\n\n        /* return pointer to process */\n        if ((retval == GMAKE_WAIT_TIMEOUT) || (retval == WAIT_FAILED)) {\n                return NULL;\n        }\n        else {\n                sub_process* pproc = proc_array[which];\n                process_adjust_wait_state(pproc);\n                return pproc;\n        }\n}\n\n/*\n * Terminate a process.\n */\nBOOL\nprocess_kill(HANDLE proc, int signal)\n{\n        sub_process* pproc = (sub_process*) proc;\n        pproc->signal = signal;\n        return (TerminateProcess((HANDLE) pproc->pid, signal));\n}\n\n/*\n * Returns true when we have no more available slots in our process table.\n */\nBOOL\nprocess_table_full()\n{\n  extern int shell_function_pid;\n\n  /* Reserve slots for jobserver_semaphore if we have one and the shell function if not active */\n  return(proc_index >= GMAKE_MAXIMUM_WAIT_OBJECTS - jobserver_enabled() - (shell_function_pid == 0));\n}\n\n/*\n * Returns the maximum number of job slots we can support when using the jobserver.\n */\nint\nprocess_table_usable_size()\n{\n  /* Reserve slots for jobserver_semaphore and shell function */\n  return(GMAKE_MAXIMUM_WAIT_OBJECTS - 2);\n}\n\n/*\n * Returns the actual size of the process table.\n */\nint\nprocess_table_actual_size()\n{\n  return(GMAKE_MAXIMUM_WAIT_OBJECTS);\n}\n\n/*\n * Use this function to register processes you wish to wait for by\n * calling process_file_io(NULL) or process_wait_any(). This must be done\n * because it is possible for callers of this library to reuse the same\n * handle for multiple processes launches :-(\n */\nvoid\nprocess_register(HANDLE proc)\n{\n  assert(proc_index < GMAKE_MAXIMUM_WAIT_OBJECTS);\n  proc_array[proc_index++] = (sub_process *) proc;\n}\n\n/*\n * Public function which works kind of like waitpid(). Wait for any\n * of the children to die and return results. To call this function,\n * you must do 1 of things:\n *\n *      x = process_easy(...);\n *\n * or\n *\n *      x = process_init_fd();\n *      process_register(x);\n *\n * or\n *\n *      x = process_init();\n *      process_register(x);\n *\n * You must NOT then call process_pipe_io() because this function is\n * not capable of handling automatic notification of any child\n * death.\n */\n\nHANDLE\nprocess_wait_for_any(int block, DWORD* pdwWaitStatus)\n{\n        sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus);\n\n        if (!pproc)\n                return NULL;\n        else {\n                /*\n                 * Ouch! can't tell caller if this fails directly. Caller\n                 * will have to use process_last_err()\n                 */\n                (void) process_file_io(pproc);\n                return ((HANDLE) pproc);\n        }\n}\n\nlong\nprocess_signal(HANDLE proc)\n{\n        if (proc == INVALID_HANDLE_VALUE) return 0;\n        return (((sub_process *)proc)->signal);\n}\n\nlong\nprocess_last_err(HANDLE proc)\n{\n        if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;\n        return (((sub_process *)proc)->last_err);\n}\n\nlong\nprocess_exit_code(HANDLE proc)\n{\n        if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;\n        return (((sub_process *)proc)->exit_code);\n}\n\n/*\n2006-02:\nAll the following functions are currently unused.\nAll of them would crash gmake if called with argument INVALID_HANDLE_VALUE.\nHence whoever wants to use one of this functions must invent and implement\na reasonable error handling for this function.\n\nchar *\nprocess_outbuf(HANDLE proc)\n{\n        return (((sub_process *)proc)->outp);\n}\n\nchar *\nprocess_errbuf(HANDLE proc)\n{\n        return (((sub_process *)proc)->errp);\n}\n\nint\nprocess_outcnt(HANDLE proc)\n{\n        return (((sub_process *)proc)->outcnt);\n}\n\nint\nprocess_errcnt(HANDLE proc)\n{\n        return (((sub_process *)proc)->errcnt);\n}\n\nvoid\nprocess_pipes(HANDLE proc, int pipes[3])\n{\n        pipes[0] = ((sub_process *)proc)->sv_stdin[0];\n        pipes[1] = ((sub_process *)proc)->sv_stdout[0];\n        pipes[2] = ((sub_process *)proc)->sv_stderr[0];\n        return;\n}\n*/\n\n        HANDLE\nprocess_init()\n{\n        sub_process *pproc;\n        /*\n         * open file descriptors for attaching stdin/stdout/sterr\n         */\n        HANDLE stdin_pipes[2];\n        HANDLE stdout_pipes[2];\n        HANDLE stderr_pipes[2];\n        SECURITY_ATTRIBUTES inherit;\n        BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];\n\n        pproc = malloc(sizeof(*pproc));\n        memset(pproc, 0, sizeof(*pproc));\n\n        /* We can't use NULL for lpSecurityDescriptor because that\n           uses the default security descriptor of the calling process.\n           Instead we use a security descriptor with no DACL.  This\n           allows nonrestricted access to the associated objects. */\n\n        if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),\n                                          SECURITY_DESCRIPTOR_REVISION)) {\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n                return((HANDLE)pproc);\n        }\n\n        inherit.nLength = sizeof(inherit);\n        inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);\n        inherit.bInheritHandle = TRUE;\n\n        /* By convention, parent gets pipe[0], and child gets pipe[1].\n           This means the READ side of stdin pipe goes into pipe[1] and the\n           WRITE side of the stdout and stderr pipes go into pipe[1].  */\n        if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||\n        CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||\n        CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {\n\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n                return((HANDLE)pproc);\n        }\n\n        /* Mark the parent sides of the pipes as non-inheritable.  */\n        if (SetHandleInformation(stdin_pipes[0],\n                                HANDLE_FLAG_INHERIT, 0) == FALSE ||\n                SetHandleInformation(stdout_pipes[0],\n                                HANDLE_FLAG_INHERIT, 0) == FALSE ||\n                SetHandleInformation(stderr_pipes[0],\n                                HANDLE_FLAG_INHERIT, 0) == FALSE) {\n\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n                return((HANDLE)pproc);\n        }\n        pproc->sv_stdin[0]  = (intptr_t) stdin_pipes[0];\n        pproc->sv_stdin[1]  = (intptr_t) stdin_pipes[1];\n        pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];\n        pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];\n        pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];\n        pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];\n\n        pproc->using_pipes = 1;\n\n        pproc->lerrno = 0;\n\n        return((HANDLE)pproc);\n}\n\n\n        HANDLE\nprocess_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)\n{\n        sub_process *pproc;\n\n        pproc = malloc(sizeof(*pproc));\n        if (pproc) {\n                memset(pproc, 0, sizeof(*pproc));\n\n                /*\n                 * Just pass the provided file handles to the 'child\n                 * side' of the pipe, bypassing pipes altogether.\n                 */\n                pproc->sv_stdin[1]  = (intptr_t) stdinh;\n                pproc->sv_stdout[1] = (intptr_t) stdouth;\n                pproc->sv_stderr[1] = (intptr_t) stderrh;\n\n                pproc->last_err = pproc->lerrno = 0;\n        }\n\n        return((HANDLE)pproc);\n}\n\n\nstatic HANDLE\nfind_file(const char *exec_path, const char *path_var,\n          char *full_fname, DWORD full_len)\n{\n        HANDLE exec_handle;\n        char *fname;\n        char *ext;\n        DWORD req_len;\n        int i;\n        static const char *extensions[] =\n          /* Should .com come before no-extension case?  */\n          { \".exe\", \".cmd\", \".bat\", \"\", \".com\", NULL };\n\n        fname = xmalloc(strlen(exec_path) + 5);\n        strcpy(fname, exec_path);\n        ext = fname + strlen(fname);\n\n        for (i = 0; extensions[i]; i++) {\n                strcpy(ext, extensions[i]);\n                if (((req_len = SearchPath (path_var, fname, NULL, full_len,\n                                            full_fname, NULL)) > 0\n                     /* For compatibility with previous code, which\n                        used OpenFile, and with Windows operation in\n                        general, also look in various default\n                        locations, such as Windows directory and\n                        Windows System directory.  Warning: this also\n                        searches PATH in the Make's environment, which\n                        might not be what the Makefile wants, but it\n                        seems to be OK as a fallback, after the\n                        previous SearchPath failed to find on child's\n                        PATH.  */\n                     || (req_len = SearchPath (NULL, fname, NULL, full_len,\n                                               full_fname, NULL)) > 0)\n                    && req_len <= full_len\n                    && (exec_handle =\n                                CreateFile(full_fname,\n                                           GENERIC_READ,\n                                           FILE_SHARE_READ | FILE_SHARE_WRITE,\n                                           NULL,\n                                           OPEN_EXISTING,\n                                           FILE_ATTRIBUTE_NORMAL,\n                                           NULL)) != INVALID_HANDLE_VALUE) {\n                        free(fname);\n                        return(exec_handle);\n                }\n        }\n\n        free(fname);\n        return INVALID_HANDLE_VALUE;\n}\n\n/*\n * Return non-zero of FNAME specifies a batch file and its name\n * includes embedded whitespace.\n */\n\nstatic int\nbatch_file_with_spaces(const char *fname)\n{\n        size_t fnlen = strlen(fname);\n\n        return (fnlen > 4\n                && (_strnicmp(fname + fnlen - 4, \".bat\", 4) == 0\n                    || _strnicmp(fname + fnlen - 4, \".cmd\", 4) == 0)\n                /* The set of characters in the 2nd arg to strpbrk\n                   should be the same one used by make_command_line\n                   below to decide whether an argv[] element needs\n                   quoting.  */\n                && strpbrk(fname, \" \\t\") != NULL);\n}\n\n\n/*\n * Description:   Create the child process to be helped\n *\n * Returns: success <=> 0\n *\n * Notes/Dependencies:\n */\nlong\nprocess_begin(\n        HANDLE proc,\n        char **argv,\n        char **envp,\n        char *exec_path,\n        char *as_user)\n{\n        sub_process *pproc = (sub_process *)proc;\n        char *shell_name = 0;\n        int file_not_found=0;\n        HANDLE exec_handle;\n        char exec_fname[MAX_PATH+1];\n        const char *path_var = NULL;\n        char **ep;\n        char buf[MAX_PATH+1];\n        DWORD bytes_returned;\n        DWORD flags;\n        char *command_line;\n        STARTUPINFO startInfo;\n        PROCESS_INFORMATION procInfo;\n        char *envblk=NULL;\n        size_t envsize_needed = 0;\n        int pass_null_exec_path = 0;\n\n        /*\n         *  Shell script detection...  if the exec_path starts with #! then\n         *  we want to exec shell-script-name exec-path, not just exec-path\n         *  NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl.  We do not\n         *  hard-code the path to the shell or perl or whatever:  Instead, we\n         *  assume it's in the path somewhere (generally, the NT tools\n         *  bin directory)\n         */\n\n        /* Use the Makefile's value of PATH to look for the program to\n           execute, because it could be different from Make's PATH\n           (e.g., if the target sets its own value.  */\n        if (envp)\n                for (ep = envp; *ep; ep++) {\n                        if (strncmp (*ep, \"PATH=\", 5) == 0\n                            || strncmp (*ep, \"Path=\", 5) == 0) {\n                                path_var = *ep + 5;\n                                break;\n                        }\n                }\n        exec_handle = find_file(exec_path, path_var,\n                                exec_fname, sizeof(exec_fname));\n\n        /*\n         * If we couldn't open the file, just assume that Windows will be\n         * somehow able to find and execute it.  If the first character\n         * of the command is '/', assume they set SHELL to a Unixy shell\n         * that have some magic mounts known only to it, and run the whole\n         * command via $SHELL -c \"COMMAND\" instead.\n         */\n        if (exec_handle == INVALID_HANDLE_VALUE) {\n                if (exec_path[0] == '/') {\n                        char *new_argv0;\n                        char **argvi = argv;\n                        size_t arglen = 0;\n                        char *exp = expand_variable (\"SHELL\", 5);\n\n                        memcpy (buf, exp, strlen(exp) + 1);\n                        shell_name = &buf[0];\n                        strcpy(exec_fname, \"-c\");\n                        /* Construct a single command string in argv[0].  */\n                        while (*argvi) {\n                                arglen += strlen(*argvi) + 1;\n                                argvi++;\n                        }\n                        new_argv0 = xmalloc(arglen + 1);\n                        new_argv0[0] = '\\0';\n                        for (argvi = argv; *argvi; argvi++) {\n                                strcat(new_argv0, *argvi);\n                                strcat(new_argv0, \" \");\n                        }\n                        /* Remove the extra blank at the end.  */\n                        new_argv0[arglen-1] = '\\0';\n                        free(argv[0]);\n                        argv[0] = new_argv0;\n                        argv[1] = NULL;\n                }\n                else\n                        file_not_found++;\n        }\n        else {\n                /* Attempt to read the first line of the file */\n                if (ReadFile( exec_handle,\n                                buf, sizeof(buf) - 1, /* leave room for trailing NULL */\n                                &bytes_returned, 0) == FALSE || bytes_returned < 2) {\n\n                        pproc->last_err = GetLastError();\n                        pproc->lerrno = E_IO;\n                        CloseHandle(exec_handle);\n                        return(-1);\n                }\n                if (buf[0] == '#' && buf[1] == '!') {\n                        /*\n                         *  This is a shell script...  Change the command line from\n                         *      exec_path args to shell_name exec_path args\n                         */\n                        char *p;\n\n                        /*  Make sure buf is NULL terminated */\n                        buf[bytes_returned] = 0;\n                        /*\n                         * Depending on the file system type, etc. the first line\n                         * of the shell script may end with newline or newline-carriage-return\n                         * Whatever it ends with, cut it off.\n                         */\n                        p= strchr(buf, '\\n');\n                        if (p)\n                                *p = 0;\n                        p = strchr(buf, '\\r');\n                        if (p)\n                                *p = 0;\n\n                        /*\n                         *  Find base name of shell\n                         */\n                        shell_name = strrchr( buf, '/');\n                        if (shell_name) {\n                                shell_name++;\n                        } else {\n                                shell_name = &buf[2];/* skipping \"#!\" */\n                        }\n\n                }\n                CloseHandle(exec_handle);\n        }\n\n        flags = 0;\n\n        if (file_not_found)\n                command_line = make_command_line( shell_name, exec_path, argv);\n        else {\n                /* If exec_fname includes whitespace, CreateProcess\n                   behaves erratically and unreliably, and often fails\n                   if argv[0] also includes whitespace (and thus will\n                   be quoted by make_command_line below).  So in that\n                   case, we don't pass exec_fname as the 1st arg to\n                   CreateProcess, but instead replace argv[0] with\n                   exec_fname (to keep its leading directories and\n                   extension as found by find_file), and pass NULL to\n                   CreateProcess as its 1st arg.  This works around\n                   the bugs in CreateProcess, which are probably\n                   caused by its passing the command to cmd.exe with\n                   some incorrect quoting.  */\n                if (!shell_name\n                    && batch_file_with_spaces(exec_fname)\n                    && _stricmp(exec_path, argv[0]) == 0) {\n                        char *new_argv, *p;\n                        char **argvi;\n                        size_t arglen;\n                        int i;\n                        pass_null_exec_path = 1;\n                        /* Rewrite argv[] replacing argv[0] with exec_fname.  */\n                        for (argvi = argv + 1, arglen = strlen(exec_fname) + 1;\n                             *argvi;\n                             argvi++) {\n                                arglen += strlen(*argvi) + 1;\n                        }\n                        new_argv = xmalloc(arglen);\n                        p = strcpy(new_argv, exec_fname) + strlen(exec_fname) + 1;\n                        for (argvi = argv + 1, i = 1; *argvi; argvi++, i++) {\n                                strcpy(p, *argvi);\n                                argv[i] = p;\n                                p += strlen(*argvi) + 1;\n                        }\n                        argv[i] = NULL;\n                        free (argv[0]);\n                        argv[0] = new_argv;\n                }\n                command_line = make_command_line( shell_name, exec_fname, argv);\n        }\n\n        if ( command_line == NULL ) {\n                pproc->last_err = 0;\n                pproc->lerrno = E_NO_MEM;\n                return(-1);\n        }\n\n        if (envp) {\n                if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) {\n                        pproc->lerrno = E_NO_MEM;\n                        free( command_line );\n                        if ((pproc->last_err == ERROR_INVALID_PARAMETER\n                             || pproc->last_err == ERROR_MORE_DATA)\n                            && envsize_needed > 32*1024) {\n                                fprintf (stderr, \"CreateProcess failed, probably because environment is too large (%Iu bytes).\\n\",\n                                         envsize_needed);\n                        }\n                        pproc->last_err = 0;\n                        return(-1);\n                }\n        }\n\n        if (shell_name || file_not_found || pass_null_exec_path) {\n                exec_path = 0;  /* Search for the program in %Path% */\n        } else {\n                exec_path = exec_fname;\n        }\n\n        /*\n         *  Set up inherited stdin, stdout, stderr for child\n         */\n        memset(&startInfo, '\\0', sizeof(startInfo));\n        GetStartupInfo(&startInfo);\n        startInfo.dwFlags = STARTF_USESTDHANDLES;\n        startInfo.lpReserved = 0;\n        startInfo.cbReserved2 = 0;\n        startInfo.lpReserved2 = 0;\n        startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];\n        startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];\n        startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];\n\n        if (as_user) {\n                free(envblk);\n                return -1;\n        } else {\n                DB (DB_JOBS, (\"CreateProcess(%s,%s,...)\\n\",\n                        exec_path ? exec_path : \"NULL\",\n                        command_line ? command_line : \"NULL\"));\n                if (CreateProcess(\n                        exec_path,\n                        command_line,\n                        NULL,\n                        0, /* default security attributes for thread */\n                        TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */\n                        flags,\n                        envblk,\n                        0, /* default starting directory */\n                        &startInfo,\n                        &procInfo) == FALSE) {\n\n                        pproc->last_err = GetLastError();\n                        pproc->lerrno = E_FORK;\n                        fprintf(stderr, \"process_begin: CreateProcess(%s, %s, ...) failed.\\n\",\n                                exec_path ? exec_path : \"NULL\", command_line);\n                        free(envblk);\n                        free( command_line );\n                        return(-1);\n                }\n        }\n\n        pproc->pid = (pid_t)procInfo.hProcess;\n        /* Close the thread handle -- we'll just watch the process */\n        CloseHandle(procInfo.hThread);\n\n        /* Close the halves of the pipes we don't need */\n        if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE)\n          CloseHandle((HANDLE)pproc->sv_stdin[1]);\n        if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE)\n          CloseHandle((HANDLE)pproc->sv_stdout[1]);\n        if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE)\n          CloseHandle((HANDLE)pproc->sv_stderr[1]);\n        pproc->sv_stdin[1] = 0;\n        pproc->sv_stdout[1] = 0;\n        pproc->sv_stderr[1] = 0;\n\n        free( command_line );\n        free(envblk);\n        pproc->lerrno=0;\n        return 0;\n}\n\n\n\n#if 0   /* unused */\nstatic DWORD\nproc_stdin_thread(sub_process *pproc)\n{\n        DWORD in_done;\n        for (;;) {\n                if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,\n                                         &in_done, NULL) == FALSE)\n                        _endthreadex(0);\n                /* This if should never be true for anonymous pipes, but gives\n                   us a chance to change I/O mechanisms later.  */\n                if (in_done < pproc->incnt) {\n                        pproc->incnt -= in_done;\n                        pproc->inp += in_done;\n                } else {\n                        _endthreadex(0);\n                }\n        }\n        return 0; /* for compiler warnings only.. not reached.  */\n}\n\nstatic DWORD\nproc_stdout_thread(sub_process *pproc)\n{\n        DWORD bufsize = 1024;\n        char c;\n        DWORD nread;\n        pproc->outp = malloc(bufsize);\n        if (pproc->outp == NULL)\n                _endthreadex(0);\n        pproc->outcnt = 0;\n\n        for (;;) {\n                if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)\n                                        == FALSE) {\n/*                      map_windows32_error_to_string(GetLastError());*/\n                        _endthreadex(0);\n                }\n                if (nread == 0)\n                        _endthreadex(0);\n                if (pproc->outcnt + nread > bufsize) {\n                        bufsize += nread + 512;\n                        pproc->outp = realloc(pproc->outp, bufsize);\n                        if (pproc->outp == NULL) {\n                                pproc->outcnt = 0;\n                                _endthreadex(0);\n                        }\n                }\n                pproc->outp[pproc->outcnt++] = c;\n        }\n        return 0;\n}\n\nstatic DWORD\nproc_stderr_thread(sub_process *pproc)\n{\n        DWORD bufsize = 1024;\n        char c;\n        DWORD nread;\n        pproc->errp = malloc(bufsize);\n        if (pproc->errp == NULL)\n                _endthreadex(0);\n        pproc->errcnt = 0;\n\n        for (;;) {\n                if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {\n/*                      map_windows32_error_to_string(GetLastError());*/\n                        _endthreadex(0);\n                }\n                if (nread == 0)\n                        _endthreadex(0);\n                if (pproc->errcnt + nread > bufsize) {\n                        bufsize += nread + 512;\n                        pproc->errp = realloc(pproc->errp, bufsize);\n                        if (pproc->errp == NULL) {\n                                pproc->errcnt = 0;\n                                _endthreadex(0);\n                        }\n                }\n                pproc->errp[pproc->errcnt++] = c;\n        }\n        return 0;\n}\n\n\n/*\n * Purpose: collects output from child process and returns results\n *\n * Description:\n *\n * Returns:\n *\n * Notes/Dependencies:\n */\n        long\nprocess_pipe_io(\n        HANDLE proc,\n        char *stdin_data,\n        int stdin_data_len)\n{\n        sub_process *pproc = (sub_process *)proc;\n        bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;\n        HANDLE childhand = (HANDLE) pproc->pid;\n        HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;\n        unsigned int dwStdin, dwStdout, dwStderr;\n        HANDLE wait_list[4];\n        DWORD wait_count;\n        DWORD wait_return;\n        HANDLE ready_hand;\n        bool_t child_dead = FALSE;\n        BOOL GetExitCodeResult;\n\n        /*\n         *  Create stdin thread, if needed\n         */\n        pproc->inp = stdin_data;\n        pproc->incnt = stdin_data_len;\n        if (!pproc->inp) {\n                stdin_eof = TRUE;\n                CloseHandle((HANDLE)pproc->sv_stdin[0]);\n                pproc->sv_stdin[0] = 0;\n        } else {\n                tStdin = (HANDLE) _beginthreadex( 0, 1024,\n                        (unsigned (__stdcall *) (void *))proc_stdin_thread,\n                                                  pproc, 0, &dwStdin);\n                if (tStdin == 0) {\n                        pproc->last_err = GetLastError();\n                        pproc->lerrno = E_SCALL;\n                        goto done;\n                }\n        }\n\n        /*\n         *   Assume child will produce stdout and stderr\n         */\n        tStdout = (HANDLE) _beginthreadex( 0, 1024,\n                (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,\n                &dwStdout);\n        tStderr = (HANDLE) _beginthreadex( 0, 1024,\n                (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,\n                &dwStderr);\n\n        if (tStdout == 0 || tStderr == 0) {\n\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n                goto done;\n        }\n\n\n        /*\n         *  Wait for all I/O to finish and for the child process to exit\n         */\n\n        while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {\n                wait_count = 0;\n                if (!stdin_eof) {\n                        wait_list[wait_count++] = tStdin;\n                }\n                if (!stdout_eof) {\n                        wait_list[wait_count++] = tStdout;\n                }\n                if (!stderr_eof) {\n                        wait_list[wait_count++] = tStderr;\n                }\n                if (!child_dead) {\n                        wait_list[wait_count++] = childhand;\n                }\n\n                wait_return = WaitForMultipleObjects(wait_count, wait_list,\n                         FALSE, /* don't wait for all: one ready will do */\n                         child_dead? 1000 :INFINITE); /* after the child dies, subthreads have\n                                one second to collect all remaining output */\n\n                if (wait_return == WAIT_FAILED) {\n/*                      map_windows32_error_to_string(GetLastError());*/\n                        pproc->last_err = GetLastError();\n                        pproc->lerrno = E_SCALL;\n                        goto done;\n                }\n\n                ready_hand = wait_list[wait_return - WAIT_OBJECT_0];\n\n                if (ready_hand == tStdin) {\n                        CloseHandle((HANDLE)pproc->sv_stdin[0]);\n                        pproc->sv_stdin[0] = 0;\n                        CloseHandle(tStdin);\n                        tStdin = 0;\n                        stdin_eof = TRUE;\n\n                } else if (ready_hand == tStdout) {\n\n                        CloseHandle((HANDLE)pproc->sv_stdout[0]);\n                        pproc->sv_stdout[0] = 0;\n                        CloseHandle(tStdout);\n                        tStdout = 0;\n                        stdout_eof = TRUE;\n\n                } else if (ready_hand == tStderr) {\n\n                        CloseHandle((HANDLE)pproc->sv_stderr[0]);\n                        pproc->sv_stderr[0] = 0;\n                        CloseHandle(tStderr);\n                        tStderr = 0;\n                        stderr_eof = TRUE;\n\n                } else if (ready_hand == childhand) {\n\n                        DWORD ierr;\n                        GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);\n                        if (ierr == CONTROL_C_EXIT) {\n                                pproc->signal = SIGINT;\n                        } else {\n                                pproc->exit_code = ierr;\n                        }\n                        if (GetExitCodeResult == FALSE) {\n                                pproc->last_err = GetLastError();\n                                pproc->lerrno = E_SCALL;\n                                goto done;\n                        }\n                        child_dead = TRUE;\n\n                } else {\n\n                        /* ?? Got back a handle we didn't query ?? */\n                        pproc->last_err = 0;\n                        pproc->lerrno = E_FAIL;\n                        goto done;\n                }\n        }\n\n done:\n        if (tStdin != 0)\n                CloseHandle(tStdin);\n        if (tStdout != 0)\n                CloseHandle(tStdout);\n        if (tStderr != 0)\n                CloseHandle(tStderr);\n\n        if (pproc->lerrno)\n                return(-1);\n        else\n                return(0);\n\n}\n#endif  /* unused */\n\n/*\n * Purpose: collects output from child process and returns results\n *\n * Description:\n *\n * Returns:\n *\n * Notes/Dependencies:\n */\n        long\nprocess_file_io(\n        HANDLE proc)\n{\n        sub_process *pproc;\n        HANDLE childhand;\n        DWORD wait_return;\n        BOOL GetExitCodeResult;\n        DWORD ierr;\n\n        if (proc == NULL)\n                pproc = process_wait_for_any_private(1, 0);\n        else\n                pproc = (sub_process *)proc;\n\n        /* some sort of internal error */\n        if (!pproc)\n                return -1;\n\n        childhand = (HANDLE) pproc->pid;\n\n        /*\n         * This function is poorly named, and could also be used just to wait\n         * for child death if you're doing your own pipe I/O.  If that is\n         * the case, close the pipe handles here.\n         */\n        if (pproc->sv_stdin[0]) {\n                CloseHandle((HANDLE)pproc->sv_stdin[0]);\n                pproc->sv_stdin[0] = 0;\n        }\n        if (pproc->sv_stdout[0]) {\n                CloseHandle((HANDLE)pproc->sv_stdout[0]);\n                pproc->sv_stdout[0] = 0;\n        }\n        if (pproc->sv_stderr[0]) {\n                CloseHandle((HANDLE)pproc->sv_stderr[0]);\n                pproc->sv_stderr[0] = 0;\n        }\n\n        /*\n         *  Wait for the child process to exit\n         */\n\n        wait_return = WaitForSingleObject(childhand, INFINITE);\n\n        if (wait_return != WAIT_OBJECT_0) {\n/*              map_windows32_error_to_string(GetLastError());*/\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n                goto done2;\n        }\n\n        GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);\n        if (ierr == CONTROL_C_EXIT) {\n                pproc->signal = SIGINT;\n        } else {\n                pproc->exit_code = ierr;\n        }\n        if (GetExitCodeResult == FALSE) {\n                pproc->last_err = GetLastError();\n                pproc->lerrno = E_SCALL;\n        }\n\ndone2:\n        if (pproc->lerrno)\n                return(-1);\n        else\n                return(0);\n\n}\n\n/*\n * Description:  Clean up any leftover handles, etc.  It is up to the\n * caller to manage and free the input, output, and stderr buffers.\n */\n        void\nprocess_cleanup(\n        HANDLE proc)\n{\n        sub_process *pproc = (sub_process *)proc;\n        int i;\n\n        if (pproc->using_pipes) {\n                for (i= 0; i <= 1; i++) {\n                        if ((HANDLE)pproc->sv_stdin[i]\n                            && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE)\n                                CloseHandle((HANDLE)pproc->sv_stdin[i]);\n                        if ((HANDLE)pproc->sv_stdout[i]\n                            && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE)\n                                CloseHandle((HANDLE)pproc->sv_stdout[i]);\n                        if ((HANDLE)pproc->sv_stderr[i]\n                            && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE)\n                                CloseHandle((HANDLE)pproc->sv_stderr[i]);\n                }\n        }\n        if ((HANDLE)pproc->pid)\n                CloseHandle((HANDLE)pproc->pid);\n\n        free(pproc);\n}\n\n\n/*\n * Description:\n *       Create a command line buffer to pass to CreateProcess\n *\n * Returns:  the buffer or NULL for failure\n *      Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...\n *      Otherwise:   argv[0] argv[1] argv[2] ...\n *\n * Notes/Dependencies:\n *   CreateProcess does not take an argv, so this command creates a\n *   command line for the executable.\n */\n\nstatic char *\nmake_command_line( char *shell_name, char *full_exec_path, char **argv)\n{\n        int    argc = 0;\n        char** argvi;\n        int*   enclose_in_quotes = NULL;\n        int*   enclose_in_quotes_i;\n        size_t bytes_required = 0;\n        char*  command_line;\n        char*  command_line_i;\n        int have_sh = 0; /* HAVE_CYGWIN_SHELL */\n        int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */\n\n#ifdef HAVE_CYGWIN_SHELL\n        cygwin_mode = 1;\n#endif\n\n        if (shell_name && full_exec_path) {\n                have_sh = cygwin_mode && strstr(full_exec_path, \"sh.exe\");\n                bytes_required\n                  = strlen(shell_name) + 1 + strlen(full_exec_path);\n                /*\n                 * Skip argv[0] if any, when shell_name is given.\n                 * The special case of \"-c\" in full_exec_path means\n                 * argv[0] is not the shell name, but the command string\n                 * to pass to the shell.\n                 */\n                if (*argv && strcmp(full_exec_path, \"-c\")) argv++;\n                /*\n                 * Add one for the intervening space.\n                 */\n                if (*argv) bytes_required++;\n        }\n\n        argvi = argv;\n        while (*(argvi++)) argc++;\n\n        if (argc) {\n                enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));\n\n                if (!enclose_in_quotes) {\n                        return NULL;\n                }\n        }\n\n        /* We have to make one pass through each argv[i] to see if we need\n         * to enclose it in \", so we might as well figure out how much\n         * memory we'll need on the same pass.\n         */\n\n        argvi = argv;\n        enclose_in_quotes_i = enclose_in_quotes;\n        while(*argvi) {\n                char* p = *argvi;\n                unsigned int backslash_count = 0;\n\n                /*\n                 * We have to enclose empty arguments in \".\n                 */\n                if (!(*p)) *enclose_in_quotes_i = 1;\n\n                while(*p) {\n                        switch (*p) {\n                        case '\\\"':\n                                /*\n                                 * We have to insert a backslash for each \"\n                                 * and each \\ that precedes the \".\n                                 */\n                                bytes_required += (backslash_count + 1);\n                                backslash_count = 0;\n                                break;\n\n#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)\n                        case '\\\\':\n                                backslash_count++;\n                                break;\n#endif\n        /*\n         * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress\n         * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so\n         * that argv in always equals argv out. This was removed.  Say you have\n         * such a program named glob.exe.  You enter\n         * glob '*'\n         * at the sh command prompt.  Obviously the intent is to make glob do the\n         * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',\n         * then the command line that glob would see would be\n         * glob \"*\"\n         * and the _setargv in SETARGV.OBJ would _not_ expand the *.\n         */\n                        case ' ':\n                        case '\\t':\n                                *enclose_in_quotes_i = 1;\n                                /* fall through */\n\n                        default:\n                                backslash_count = 0;\n                                break;\n                        }\n\n                        /*\n                         * Add one for each character in argv[i].\n                         */\n                        bytes_required++;\n\n                        p++;\n                }\n\n                if (*enclose_in_quotes_i) {\n                        /*\n                         * Add one for each enclosing \",\n                         * and one for each \\ that precedes the\n                         * closing \".\n                         */\n                        bytes_required += (backslash_count + 2);\n                }\n\n                /*\n                 * Add one for the intervening space.\n                 */\n                if (*(++argvi)) bytes_required++;\n                enclose_in_quotes_i++;\n        }\n\n        /*\n         * Add one for the terminating NULL.\n         */\n        bytes_required++;\n\n        command_line = (char*) malloc(bytes_required);\n\n        if (!command_line) {\n                free(enclose_in_quotes);\n                return NULL;\n        }\n\n        command_line_i = command_line;\n\n        if (shell_name && full_exec_path) {\n                while(*shell_name) {\n                        *(command_line_i++) = *(shell_name++);\n                }\n\n                *(command_line_i++) = ' ';\n\n                while(*full_exec_path) {\n                        *(command_line_i++) = *(full_exec_path++);\n                }\n\n                if (*argv) {\n                        *(command_line_i++) = ' ';\n                }\n        }\n\n        argvi = argv;\n        enclose_in_quotes_i = enclose_in_quotes;\n\n        while(*argvi) {\n                char* p = *argvi;\n                unsigned int backslash_count = 0;\n\n                if (*enclose_in_quotes_i) {\n                        *(command_line_i++) = '\\\"';\n                }\n\n                while(*p) {\n                        if (*p == '\\\"') {\n                                if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */\n                                        /* instead of a \\\", cygwin likes \"\" */\n                                        *(command_line_i++) = '\\\"';\n                                } else {\n\n                                /*\n                                 * We have to insert a backslash for the \"\n                                 * and each \\ that precedes the \".\n                                 */\n                                backslash_count++;\n\n                                while(backslash_count) {\n                                        *(command_line_i++) = '\\\\';\n                                        backslash_count--;\n                                };\n                                }\n#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)\n                        } else if (*p == '\\\\') {\n                                backslash_count++;\n                        } else {\n                                backslash_count = 0;\n#endif\n                        }\n\n                        /*\n                         * Copy the character.\n                         */\n                        *(command_line_i++) = *(p++);\n                }\n\n                if (*enclose_in_quotes_i) {\n#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)\n                        /*\n                         * Add one \\ for each \\ that precedes the\n                         * closing \".\n                         */\n                        while(backslash_count--) {\n                                *(command_line_i++) = '\\\\';\n                        };\n#endif\n                        *(command_line_i++) = '\\\"';\n                }\n\n                /*\n                 * Append an intervening space.\n                 */\n                if (*(++argvi)) {\n                        *(command_line_i++) = ' ';\n                }\n\n                enclose_in_quotes_i++;\n        }\n\n        /*\n         * Append the terminating NULL.\n         */\n        *command_line_i = '\\0';\n\n        free(enclose_in_quotes);\n        return command_line;\n}\n\n/*\n * Description: Given an argv and optional envp, launch the process\n *              using the default stdin, stdout, and stderr handles.\n *              Also, register process so that process_wait_for_any_private()\n *              can be used via process_file_io(NULL) or\n *              process_wait_for_any().\n *\n * Returns:\n *\n * Notes/Dependencies:\n */\nHANDLE\nprocess_easy(\n        char **argv,\n        char **envp,\n        int outfd,\n        int errfd)\n{\n  HANDLE hIn = INVALID_HANDLE_VALUE;\n  HANDLE hOut = INVALID_HANDLE_VALUE;\n  HANDLE hErr = INVALID_HANDLE_VALUE;\n  HANDLE hProcess, tmpIn, tmpOut, tmpErr;\n  DWORD e;\n\n  if (process_table_full()) {\n        DB (DB_JOBS, (\"process_easy: All process slots used up\\n\"));\n        return INVALID_HANDLE_VALUE;\n  }\n  /* Standard handles returned by GetStdHandle can be NULL or\n     INVALID_HANDLE_VALUE if the parent process closed them.  If that\n     happens, we open the null device and pass its handle to\n     CreateProcess as the corresponding handle to inherit.  */\n  tmpIn = GetStdHandle(STD_INPUT_HANDLE);\n  if (DuplicateHandle(GetCurrentProcess(),\n                      tmpIn,\n                      GetCurrentProcess(),\n                      &hIn,\n                      0,\n                      TRUE,\n                      DUPLICATE_SAME_ACCESS) == FALSE) {\n    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {\n      tmpIn = CreateFile(\"NUL\", GENERIC_READ,\n                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n      if (tmpIn != INVALID_HANDLE_VALUE\n          && DuplicateHandle(GetCurrentProcess(),\n                             tmpIn,\n                             GetCurrentProcess(),\n                             &hIn,\n                             0,\n                             TRUE,\n                             DUPLICATE_SAME_ACCESS) == FALSE)\n        CloseHandle(tmpIn);\n    }\n    if (hIn == INVALID_HANDLE_VALUE) {\n      fprintf(stderr, \"process_easy: DuplicateHandle(In) failed (e=%lu)\\n\", e);\n      return INVALID_HANDLE_VALUE;\n    }\n  }\n  if (outfd >= 0)\n    tmpOut = get_handle_for_fd (outfd);\n  else\n    tmpOut = GetStdHandle (STD_OUTPUT_HANDLE);\n  if (DuplicateHandle(GetCurrentProcess(),\n                      tmpOut,\n                      GetCurrentProcess(),\n                      &hOut,\n                      0,\n                      TRUE,\n                      DUPLICATE_SAME_ACCESS) == FALSE) {\n    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {\n      tmpOut = CreateFile(\"NUL\", GENERIC_WRITE,\n                          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n      if (tmpOut != INVALID_HANDLE_VALUE\n          && DuplicateHandle(GetCurrentProcess(),\n                             tmpOut,\n                             GetCurrentProcess(),\n                             &hOut,\n                             0,\n                             TRUE,\n                             DUPLICATE_SAME_ACCESS) == FALSE)\n        CloseHandle(tmpOut);\n    }\n    if (hOut == INVALID_HANDLE_VALUE) {\n      fprintf(stderr, \"process_easy: DuplicateHandle(Out) failed (e=%lu)\\n\", e);\n      return INVALID_HANDLE_VALUE;\n    }\n  }\n  if (errfd >= 0)\n    tmpErr = get_handle_for_fd (errfd);\n  else\n    tmpErr = GetStdHandle(STD_ERROR_HANDLE);\n  if (DuplicateHandle(GetCurrentProcess(),\n                      tmpErr,\n                      GetCurrentProcess(),\n                      &hErr,\n                      0,\n                      TRUE,\n                      DUPLICATE_SAME_ACCESS) == FALSE) {\n    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {\n      tmpErr = CreateFile(\"NUL\", GENERIC_WRITE,\n                          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n      if (tmpErr != INVALID_HANDLE_VALUE\n          && DuplicateHandle(GetCurrentProcess(),\n                             tmpErr,\n                             GetCurrentProcess(),\n                             &hErr,\n                             0,\n                             TRUE,\n                             DUPLICATE_SAME_ACCESS) == FALSE)\n        CloseHandle(tmpErr);\n    }\n    if (hErr == INVALID_HANDLE_VALUE) {\n      fprintf(stderr, \"process_easy: DuplicateHandle(Err) failed (e=%lu)\\n\", e);\n      return INVALID_HANDLE_VALUE;\n    }\n  }\n\n  hProcess = process_init_fd(hIn, hOut, hErr);\n\n  if (process_begin(hProcess, argv, envp, argv[0], NULL)) {\n    fake_exits_pending++;\n    /* process_begin() failed: make a note of that.  */\n    if (!((sub_process*) hProcess)->last_err)\n      ((sub_process*) hProcess)->last_err = -1;\n    ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);\n\n    /* close up unused handles */\n    if (hIn != INVALID_HANDLE_VALUE)\n      CloseHandle(hIn);\n    if (hOut != INVALID_HANDLE_VALUE)\n      CloseHandle(hOut);\n    if (hErr != INVALID_HANDLE_VALUE)\n      CloseHandle(hErr);\n  }\n\n  process_register(hProcess);\n\n  return hProcess;\n}\n"
  },
  {
    "path": "src/w32/subproc/w32err.c",
    "content": "/* Error handling for Windows\nCopyright (C) 1996-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include <stdlib.h>\n#include <windows.h>\n#include \"makeint.h\"\n#include \"w32err.h\"\n\n/*\n * Description: the windows32 version of perror()\n *\n * Returns:  a pointer to a static error\n *\n * Notes/Dependencies:  I got this from\n *      comp.os.ms-windows.programmer.win32\n */\nconst char *\nmap_windows32_error_to_string (DWORD ercode) {\n/*\n * We used to have an MSVC-specific '__declspec (thread)' qualifier\n * here, with the following comment:\n *\n * __declspec (thread) necessary if you will use multiple threads on MSVC\n *\n * However, Make was never multithreaded on Windows (except when\n * Ctrl-C is hit, in which case the main thread is stopped\n * immediately, so it doesn't matter in this context).  The functions\n * on sub_proc.c that started and stopped additional threads were\n * never used, and are now #ifdef'ed away.  Until we need more than\n * one thread, we have no problems with the following buffer being\n * static.  (If and when we do need it to be in thread-local storage,\n * the corresponding GCC qualifier is '__thread'.)\n */\n  static char szMessageBuffer[128];\n  DWORD ret;\n\n  /* Fill message buffer with a default message in\n   * case FormatMessage fails\n   */\n  wsprintf (szMessageBuffer, \"Error %ld\", ercode);\n\n  /*\n   *  Special code for winsock error handling.\n   */\n  if (ercode > WSABASEERR) {\n    OS (fatal, NILF, \"%s\", szMessageBuffer);\n  }\n\n  /*\n   *  Default system message handling\n   */\n  ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\n                      NULL,\n                      ercode,\n                      LANG_NEUTRAL,\n                      szMessageBuffer,\n                      sizeof(szMessageBuffer),\n                      NULL);\n\n  if (ret)\n    {\n      char *cp;\n      for (cp = szMessageBuffer + ret - 1; cp >= szMessageBuffer; --cp)\n        {\n          if (*cp != '\\r' && *cp != '\\n')\n            break;\n          *cp = '\\0';\n        }\n    }\n\n  return szMessageBuffer;\n}\n"
  },
  {
    "path": "src/w32/utf8.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n  <application>\n    <windowsSettings>\n      <activeCodePage xmlns=\"http://schemas.microsoft.com/SMI/2019/WindowsSettings\">UTF-8</activeCodePage>\n    </windowsSettings>\n  </application>\n</assembly>\n"
  },
  {
    "path": "src/w32/utf8.rc",
    "content": "#include <winuser.h>\n\nCREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST \"utf8.manifest\"\n"
  },
  {
    "path": "src/w32/w32os.c",
    "content": "/* Windows32-based operating system interface for GNU Make.\nCopyright (C) 2016-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#include <windows.h>\n#include <process.h>\n#include <io.h>\n#if _WIN32_WINNT > 0x0601\n#include <synchapi.h>\n#endif\n#include \"pathstuff.h\"\n#include \"sub_proc.h\"\n#include \"w32err.h\"\n#include \"os.h\"\n#include \"debug.h\"\n\nunsigned int\ncheck_io_state ()\n{\n  static unsigned int state = IO_UNKNOWN;\n  HANDLE outfd, errfd;\n\n  /* We only need to compute this once per process.  */\n  if (state != IO_UNKNOWN)\n    return state;\n\n  /* Could have used GetHandleInformation, but that isn't supported\n     on Windows 9X.  */\n  outfd = get_handle_for_fd (fileno (stdout));\n  errfd = get_handle_for_fd (fileno (stderr));\n\n  if (get_handle_for_fd (fileno (stdin)) != INVALID_HANDLE_VALUE)\n    state |= IO_STDIN_OK;\n  if (outfd != INVALID_HANDLE_VALUE)\n    state |= IO_STDOUT_OK;\n  if (errfd != INVALID_HANDLE_VALUE)\n    state |= IO_STDERR_OK;\n\n  if (ALL_SET (state, IO_STDOUT_OK|IO_STDERR_OK))\n    {\n      unsigned int combined = 0;\n\n      if (outfd == errfd)\n        combined = IO_COMBINED_OUTERR;\n      else\n        {\n          DWORD outtype = GetFileType (outfd), errtype = GetFileType (errfd);\n\n          if (outtype == errtype\n              && outtype != FILE_TYPE_UNKNOWN && errtype != FILE_TYPE_UNKNOWN)\n            {\n              if (outtype == FILE_TYPE_CHAR)\n                {\n                  /* For character devices, check if they both refer to a\n                     console.  This loses if both handles refer to the\n                     null device (FIXME!), but in that case we don't care\n                     in the context of Make.  */\n                  DWORD outmode, errmode;\n\n                  /* Each process on Windows can have at most 1 console,\n                     so if both handles are for the console device, they\n                     are the same.  We also compare the console mode to\n                     distinguish between stdin and stdout/stderr.  */\n                  if (GetConsoleMode (outfd, &outmode)\n                      && GetConsoleMode (errfd, &errmode)\n                      && outmode == errmode)\n                    combined = IO_COMBINED_OUTERR;\n                }\n              else\n                {\n                  /* For disk files and pipes, compare their unique\n                     attributes.  */\n                  BY_HANDLE_FILE_INFORMATION outfi, errfi;\n\n                  /* Pipes get zero in the volume serial number, but do\n                     appear to have meaningful information in file index\n                     attributes.  We test file attributes as well, for a\n                     good measure.  */\n                  if (GetFileInformationByHandle (outfd, &outfi)\n                      && GetFileInformationByHandle (errfd, &errfi)\n                      && outfi.dwVolumeSerialNumber == errfi.dwVolumeSerialNumber\n                      && outfi.nFileIndexLow == errfi.nFileIndexLow\n                      && outfi.nFileIndexHigh == errfi.nFileIndexHigh\n                      && outfi.dwFileAttributes == errfi.dwFileAttributes)\n                    combined = IO_COMBINED_OUTERR;\n                }\n            }\n        }\n      state |= combined;\n    }\n\n  return state;\n}\n\n/* A replacement for tmpfile, since the MSVCRT implementation creates\n   the file in the root directory of the current drive, which might\n   not be writable by our user, and also it returns a FILE* and we want a file\n   descriptor.  Mostly borrowed from create_batch_file, see job.c.  */\nint\nos_anontmp ()\n{\n  char temp_path[MAX_PATH+1];\n  unsigned path_size = GetTempPath (sizeof (temp_path), temp_path);\n  int using_cwd = 0;\n\n  /* These variables are static so we won't try to reuse a name that was\n     generated a little while ago, because that file might not be on disk yet,\n     since we use FILE_ATTRIBUTE_TEMPORARY below, which tells the OS it\n     doesn't need to flush the cache to disk.  If the file is not yet on disk,\n     we might think the name is available, while it really isn't.  This\n     happens in parallel builds.  */\n  static unsigned uniq = 0;\n  static int second_loop = 0;\n\n  const char base[] = \"GmTMPF\";\n  const unsigned sizemax = sizeof (base) - 1 + 4 + 10 + 10;\n  unsigned pid = GetCurrentProcessId ();\n\n  if (path_size == 0)\n    {\n      path_size = GetCurrentDirectory (sizeof (temp_path), temp_path);\n      using_cwd = 1;\n    }\n\n  ++uniq;\n  if (uniq >= 0x10000 && !second_loop)\n    {\n      /* If we already had 64K batch files in this\n         process, make a second loop through the numbers,\n         looking for free slots, i.e. files that were\n         deleted in the meantime.  */\n      second_loop = 1;\n      uniq = 1;\n    }\n\n  while (path_size > 0 && path_size + sizemax < sizeof (temp_path)\n         && (uniq < 0x10000 || !second_loop))\n    {\n      HANDLE h;\n\n      sprintf (temp_path + path_size,\n               \"%s%s%u-%x.tmp\",\n               temp_path[path_size - 1] == '\\\\' ? \"\" : \"\\\\\",\n               base, pid, uniq);\n      h = CreateFile (temp_path,  /* file name */\n                      GENERIC_READ | GENERIC_WRITE | DELETE, /* desired access */\n                      FILE_SHARE_READ | FILE_SHARE_WRITE,    /* share mode */\n                      NULL,                                  /* default security attributes */\n                      CREATE_NEW,                            /* creation disposition */\n                      FILE_ATTRIBUTE_NORMAL |                /* flags and attributes */\n                      FILE_ATTRIBUTE_TEMPORARY |\n                      FILE_FLAG_DELETE_ON_CLOSE,\n                      NULL);                                 /* no template file */\n\n      if (h != INVALID_HANDLE_VALUE)\n        return _open_osfhandle ((intptr_t)h, 0);\n\n      {\n        const DWORD er = GetLastError ();\n\n        if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)\n          {\n            ++uniq;\n            if (uniq == 0x10000 && !second_loop)\n              {\n                second_loop = 1;\n                uniq = 1;\n              }\n          }\n        /* The temporary path is not guaranteed to exist, or might not be\n           writable by user.  Use the current directory as fallback.  */\n        else if (!using_cwd)\n          {\n            path_size = GetCurrentDirectory (sizeof (temp_path), temp_path);\n            using_cwd = 1;\n          }\n        else\n          {\n            errno = EACCES;\n            return -1;\n          }\n      }\n    }\n\n  if (uniq >= 0x10000)\n    errno = EEXIST;\n  return -1;\n}\n\n#if defined(MAKE_JOBSERVER)\n\n/* This section provides OS-specific functions to support the jobserver.  */\n\nstatic char jobserver_semaphore_name[MAX_PATH + 1];\nstatic HANDLE jobserver_semaphore = NULL;\n\nunsigned int\njobserver_setup (int slots, const char *style)\n{\n  /* sub_proc.c is limited in the number of objects it can wait for. */\n\n  if (style && strcmp (style, \"sem\") != 0)\n    OS (fatal, NILF, _(\"unknown jobserver auth style '%s'\"), style);\n\n  if (slots > process_table_usable_size())\n    {\n      slots = process_table_usable_size();\n      DB (DB_JOBS, (_(\"jobserver slots limited to %d\\n\"), slots));\n    }\n\n  sprintf (jobserver_semaphore_name, \"gmake_semaphore_%d\", _getpid ());\n\n  jobserver_semaphore = CreateSemaphore (\n      NULL,                           /* Use default security descriptor */\n      slots,                          /* Initial count */\n      slots,                          /* Maximum count */\n      jobserver_semaphore_name);      /* Semaphore name */\n\n  if (jobserver_semaphore == NULL)\n    {\n      DWORD err = GetLastError ();\n      const char *estr = map_windows32_error_to_string (err);\n      ONS (fatal, NILF,\n           _(\"creating jobserver semaphore: (Error %lu: %s)\"), err, estr);\n    }\n\n  return 1;\n}\n\nunsigned int\njobserver_parse_auth (const char *auth)\n{\n  jobserver_semaphore = OpenSemaphore (\n      SEMAPHORE_ALL_ACCESS,   /* Semaphore access setting */\n      FALSE,                  /* Child processes DON'T inherit */\n      auth);                  /* Semaphore name */\n\n  if (jobserver_semaphore == NULL)\n    {\n      DWORD err = GetLastError ();\n      const char *estr = map_windows32_error_to_string (err);\n      error (NILF, strlen (auth) + INTSTR_LENGTH + strlen (estr),\n             _(\"unable to open jobserver semaphore '%s': (Error %lu: %s)\"),\n             auth, err, estr);\n      return 0;\n    }\n\n  DB (DB_JOBS, (_(\"Jobserver client (semaphore %s)\\n\"), auth));\n\n  return 1;\n}\n\nchar *\njobserver_get_auth ()\n{\n  return xstrdup (jobserver_semaphore_name);\n}\n\nconst char *\njobserver_get_invalid_auth ()\n{\n  /* Because we're using a semaphore we don't need to invalidate.  */\n  return NULL;\n}\n\nunsigned int\njobserver_enabled ()\n{\n  return jobserver_semaphore != NULL;\n}\n\n/* Close jobserver semaphore */\nvoid\njobserver_clear ()\n{\n  if (jobserver_semaphore != NULL)\n    {\n      CloseHandle (jobserver_semaphore);\n      jobserver_semaphore = NULL;\n    }\n}\n\nvoid\njobserver_release (int is_fatal)\n{\n  if (! ReleaseSemaphore (\n          jobserver_semaphore,    /* handle to semaphore */\n          1,                      /* increase count by one */\n          NULL))                  /* not interested in previous count */\n    {\n      if (is_fatal)\n        {\n          DWORD err = GetLastError ();\n          const char *estr = map_windows32_error_to_string (err);\n          ONS (fatal, NILF,\n               _(\"release jobserver semaphore: (Error %lu: %s)\"), err, estr);\n        }\n      perror_with_name (\"release_jobserver_semaphore\", \"\");\n    }\n}\n\nunsigned int\njobserver_acquire_all ()\n{\n  unsigned int tokens = 0;\n  while (1)\n    {\n      DWORD dwEvent = WaitForSingleObject (\n          jobserver_semaphore,    /* Handle to semaphore */\n          0);                     /* DON'T wait on semaphore */\n\n      if (dwEvent != WAIT_OBJECT_0)\n        return tokens;\n\n      ++tokens;\n    }\n}\n\nvoid\njobserver_signal ()\n{\n}\n\nvoid jobserver_pre_child (int recursive UNUSED)\n{\n}\n\nvoid jobserver_post_child (int recursive UNUSED)\n{\n}\n\nvoid\njobserver_pre_acquire ()\n{\n}\n\n/* Returns 1 if we got a token, or 0 if a child has completed.\n   The Windows implementation doesn't support load detection.  */\nunsigned int\njobserver_acquire (int timeout UNUSED)\n{\n    HANDLE *handles;\n    DWORD dwHandleCount;\n    DWORD dwEvent;\n\n    handles = xmalloc(process_table_actual_size() * sizeof(HANDLE));\n\n    /* Add jobserver semaphore to first slot. */\n    handles[0] = jobserver_semaphore;\n\n    /* Build array of handles to wait for.  */\n    dwHandleCount = 1 + process_set_handles (&handles[1]);\n\n    dwEvent = process_wait_for_multiple_objects (\n        dwHandleCount,  /* number of objects in array */\n        handles,        /* array of objects */\n        FALSE,          /* wait for any object */\n        INFINITE);      /* wait until object is signalled */\n\n    free(handles);\n\n    if (dwEvent == WAIT_FAILED)\n      {\n        DWORD err = GetLastError ();\n        const char *estr = map_windows32_error_to_string (err);\n        ONS (fatal, NILF,\n             _(\"semaphore or child process wait: (Error %lu: %s)\"),\n             err, estr);\n      }\n\n    /* WAIT_OBJECT_0 indicates that the semaphore was signalled.  */\n    return dwEvent == WAIT_OBJECT_0;\n}\n\n#endif /* MAKE_JOBSERVER */\n\n#if !defined(NO_OUTPUT_SYNC)\n\n#define MUTEX_PREFIX    \"fnm:\"\n\n/* Since we're using this with CreateMutex, NULL is invalid.  */\nstatic HANDLE osync_handle = NULL;\n\nunsigned int\nosync_enabled ()\n{\n  return osync_handle != NULL;\n}\n\nvoid\nosync_setup ()\n{\n  SECURITY_ATTRIBUTES secattr;\n\n  /* We are the top-level make, and we want the handle to be inherited\n     by our child processes.  */\n  secattr.nLength = sizeof (secattr);\n  secattr.lpSecurityDescriptor = NULL; /* use default security descriptor */\n  secattr.bInheritHandle = TRUE;\n\n  osync_handle = CreateMutex (&secattr, FALSE, NULL);\n  if (!osync_handle)\n    {\n      DWORD err = GetLastError ();\n      fprintf (stderr, \"CreateMutex: error %lu\\n\", err);\n      errno = ENOLCK;\n    }\n}\n\nchar *\nosync_get_mutex ()\n{\n  char *mutex = NULL;\n\n  if (osync_enabled ())\n    {\n      /* Prepare the mutex handle string for our children.\n         2 hex digits per byte + 2 characters for \"0x\" + null.  */\n      mutex = xmalloc ((2 * sizeof (osync_handle)) + 2 + 1);\n      sprintf (mutex, \"0x%Ix\", (unsigned long long)(DWORD_PTR)osync_handle);\n    }\n\n  return mutex;\n}\n\nunsigned int\nosync_parse_mutex (const char *mutex)\n{\n  char *endp;\n  unsigned long long i;\n\n  errno = 0;\n  i = strtoull (mutex, &endp, 16);\n  if (errno != 0)\n    OSS (fatal, NILF, _(\"cannot parse output sync mutex %s: %s\"),\n         mutex, strerror (errno));\n  if (endp[0] != '\\0')\n    OS (fatal, NILF, _(\"invalid output sync mutex: %s\"), mutex);\n\n  osync_handle = (HANDLE) (DWORD_PTR) i;\n\n  return 1;\n}\n\nvoid\nosync_clear ()\n{\n  if (osync_handle)\n    {\n      CloseHandle (osync_handle);\n      osync_handle = NULL;\n    }\n}\n\nunsigned int\nosync_acquire ()\n{\n  if (osync_enabled())\n    {\n      DWORD result = WaitForSingleObject (osync_handle, INFINITE);\n      if (result == WAIT_FAILED || result == WAIT_TIMEOUT)\n        return 0;\n    }\n\n  return 1;\n}\n\nvoid\nosync_release ()\n{\n  if (osync_enabled())\n    /* FIXME: Perhaps we should call ReleaseMutex repatedly until it errors\n       out, to make sure the mutext is released even if we somehow managed to\n       to take ownership multiple times?  */\n    ReleaseMutex (osync_handle);\n}\n\n#endif /* NO_OUTPUT_SYNC */\n\nvoid\nfd_inherit(int fd)\n{\n  HANDLE fh = get_handle_for_fd (fd);\n\n  if (fh && fh != INVALID_HANDLE_VALUE)\n        SetHandleInformation (fh, HANDLE_FLAG_INHERIT, 1);\n}\n\nvoid\nfd_noinherit(int fd)\n{\n  HANDLE fh = get_handle_for_fd (fd);\n\n  if (fh && fh != INVALID_HANDLE_VALUE)\n        SetHandleInformation (fh, HANDLE_FLAG_INHERIT, 0);\n}\n\nint\nfd_set_append (int fd UNUSED)\n{\n  return -1;\n}\n\nvoid\nfd_reset_append (int fd UNUSED, int flags UNUSED)\n{}\n\nHANDLE\nget_handle_for_fd (int fd)\n{\n  /* This funcion call is needed to get around the \"bad-function-cast\"-warning\n     emitted by GCC when casting and assigning in the same statement.  */\n  intptr_t fh = _get_osfhandle (fd);\n  return (HANDLE) fh;\n}\n"
  },
  {
    "path": "src/warning.c",
    "content": "/* Control warning output in GNU Make.\nCopyright (C) 2023-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n#include \"makeint.h\"\n#include \"warning.h\"\n#include \"variable.h\"\n\n/* Current action for each warning.  */\nenum warning_action warnings[wt_max];\n\n/* The default behavior of warnings.  */\nstatic struct warning_data warn_default;\n\n/* Warning settings from the .WARNING variable.  */\nstatic struct warning_data warn_variable;\n\n/* Warning settings from the command line.  */\nstatic struct warning_data warn_flag;\n\nstatic const char *w_action_map[w_error+1] = {NULL, \"ignore\", \"warn\", \"error\"};\nstatic const char *w_name_map[wt_max] = {\n                                          \"circular-dep\",\n                                          \"invalid-ref\",\n                                          \"invalid-var\",\n                                          \"undefined-var\"\n                                        };\n\n#define encode_warn_action(_b,_s) \\\n    variable_buffer_output (_b, w_action_map[_s], strlen (w_action_map[_s]))\n#define encode_warn_name(_b,_t)   \\\n    variable_buffer_output (_b, w_name_map[_t], strlen (w_name_map[_t]))\n\nstatic void set_warnings ()\n{\n  /* Called whenever any warnings could change; resets the current actions.  */\n  for (enum warning_type wt = 0; wt < wt_max; ++wt)\n    warnings[wt] =\n        warn_flag.actions[wt]     != w_unset ? warn_flag.actions[wt]\n      : warn_flag.global          != w_unset ? warn_flag.global\n      : warn_variable.actions[wt] != w_unset ? warn_variable.actions[wt]\n      : warn_variable.global      != w_unset ? warn_variable.global\n      : warn_default.actions[wt];\n}\n\nvoid\nwarn_init ()\n{\n  memset (&warn_default, '\\0', sizeof (warn_default));\n  memset (&warn_variable, '\\0', sizeof (warn_variable));\n  memset (&warn_flag, '\\0', sizeof (warn_flag));\n\n  /* All warnings must have a default.  */\n  warn_default.global = w_warn;\n  warn_default.actions[wt_circular_dep] = w_warn;\n  warn_default.actions[wt_invalid_ref] = w_warn;\n  warn_default.actions[wt_invalid_var] = w_warn;\n  warn_default.actions[wt_undefined_var] = w_ignore;\n\n  set_warnings ();\n}\n\nstatic void\ninit_data (struct warning_data *data)\n{\n  data->global = w_unset;\n  for (enum warning_type wt = 0; wt < wt_max; ++wt)\n    data->actions[wt] = w_unset;\n}\n\nstatic enum warning_action\ndecode_warn_action (const char *action, size_t length)\n{\n  for (enum warning_action st = w_ignore; st <= w_error; ++st)\n    {\n      size_t len = strlen (w_action_map[st]);\n      if (length == len && strncasecmp (action, w_action_map[st], length) == 0)\n        return st;\n    }\n\n  return w_unset;\n}\n\nstatic enum warning_type\ndecode_warn_name (const char *name, size_t length)\n{\n  for (enum warning_type wt = 0; wt < wt_max; ++wt)\n    {\n      size_t len = strlen (w_name_map[wt]);\n      if (length == len && strncasecmp (name, w_name_map[wt], length) == 0)\n        return wt;\n    }\n\n  return wt_max;\n}\n\nvoid\ndecode_warn_actions (const char *value, const floc *flocp)\n{\n  struct warning_data *data = &warn_flag;\n\n  NEXT_TOKEN (value);\n\n  if (flocp)\n    {\n      data = &warn_variable;\n      /* When a variable is set to empty, reset everything.  */\n      if (*value == '\\0')\n        init_data (data);\n    }\n\n  while (*value != '\\0')\n    {\n      enum warning_action action;\n\n      /* Find the end of the next warning definition.  */\n      const char *ep = value;\n      while (! STOP_SET (*ep, MAP_BLANK|MAP_COMMA|MAP_NUL))\n        ++ep;\n\n      /* If the value is just an action set it globally.  */\n      action = decode_warn_action (value, ep - value);\n      if (action != w_unset)\n        data->global = action;\n      else\n        {\n          enum warning_type type;\n          const char *cp = memchr (value, ':', ep - value);\n          int wl, al;\n\n          if (!cp)\n            cp = ep;\n          wl = (int)(cp - value);\n          type = decode_warn_name (value, wl);\n          if (cp == ep)\n            action = w_warn;\n          else\n            {\n              /* There's a warning action: decode it.  */\n              ++cp;\n              al = (int)(ep - cp);\n              action = decode_warn_action (cp, al);\n            }\n\n          if (type == wt_max)\n            {\n              if (!flocp)\n                ONS (fatal, NILF, _(\"unknown warning '%.*s'\"), wl, value);\n              ONS (error, flocp,\n                   _(\"unknown warning '%.*s': ignored\"), wl, value);\n            }\n          else if (action == w_unset)\n            {\n              if (!flocp)\n                ONS (fatal, NILF,\n                     _(\"unknown warning action '%.*s'\"), al, cp);\n              ONS (error, flocp,\n                   _(\"unknown warning action '%.*s': ignored\"), al, cp);\n            }\n          else\n            data->actions[type] = action;\n        }\n\n      value = ep;\n      while (STOP_SET (*value, MAP_BLANK|MAP_COMMA))\n        ++value;\n    }\n\n  set_warnings ();\n}\n\nchar *\nencode_warn_flag (char *fp)\n{\n  enum warning_type wt;\n  char sp = '=';\n\n  /* See if any warning options are set.  */\n  for (wt = 0; wt < wt_max; ++wt)\n    if (warn_flag.actions[wt] != w_unset)\n      break;\n  if (wt == wt_max && warn_flag.global == w_unset)\n    return fp;\n\n  /* Something is set so construct a --warn option.  */\n  fp = variable_buffer_output (fp, STRING_SIZE_TUPLE (\" --warn\"));\n\n  /* If only a global action set to warn, we're done.  */\n  if (wt == wt_max && warn_flag.global == w_warn)\n    return fp;\n\n  /* If a global action is set, add it.  */\n  if (warn_flag.global > w_unset)\n    {\n      fp = variable_buffer_output (fp, &sp, 1);\n      sp = ',';\n      fp = encode_warn_action (fp, warn_flag.global);\n    }\n\n  /* Add any specific actions.  */\n  if (wt != wt_max)\n    for (wt = 0; wt < wt_max; ++wt)\n      {\n        enum warning_action act = warn_flag.actions[wt];\n        if (act > w_unset)\n          {\n            fp = variable_buffer_output (fp, &sp, 1);\n            sp = ',';\n            fp = encode_warn_name (fp, wt);\n            if (act != w_warn)\n              fp = encode_warn_action (variable_buffer_output (fp, \":\", 1), act);\n          }\n      }\n\n  return fp;\n}\n\nvoid\nwarn_get_vardata (struct warning_data *data)\n{\n  memcpy (data, &warn_variable, sizeof (warn_variable));\n}\n\nvoid\nwarn_set_vardata (const struct warning_data *data)\n{\n  memcpy (&warn_variable, data, sizeof (warn_variable));\n  set_warnings ();\n}\n"
  },
  {
    "path": "src/warning.h",
    "content": "/* Control warning output in GNU Make.\nCopyright (C) 2023-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* Types of warnings we can show.\n   These can be rearranged but the first value must be 0.  */\nenum warning_type\n  {\n    wt_circular_dep = 0, /* A target depends on itself.  */\n    wt_invalid_ref,      /* Reference an invalid variable name.  */\n    wt_invalid_var,      /* Assign to an invalid variable name.  */\n    wt_undefined_var,    /* Reference an undefined variable name.  */\n    wt_max\n  };\n\n/* Action taken for a given warning.  Unset must be 0.  */\nenum warning_action\n  {\n    w_unset = 0,\n    w_ignore,\n    w_warn,\n    w_error\n  };\n\nstruct warning_data\n  {\n    enum warning_action global;          /* Global setting.  */\n    enum warning_action actions[wt_max]; /* Action for each warning type.  */\n  };\n\n/* Actions taken for each warning.  */\nextern enum warning_action warnings[wt_max];\n\n/* Get the current action for a given warning.  */\n#define warn_get(_w)     (warnings[_w])\n\n/* Set the current actin for a given warning.  Can't use w_unset here.\n   This should only be used for temporary resetting of warnings.  */\n#define warn_set(_w,_f)  do{ warnings[_w] = (_f); }while(0)\n\n/* True if we should check for the warning in the first place.  */\n#define warn_check(_w)   (warn_get (_w) > w_ignore)\n\n/* Check if the warning is ignored.  */\n#define warn_ignored(_w) (warn_get (_w) == w_ignore)\n\n/* Check if the warning is in \"warn\" mode.  */\n#define warn_warned(_w)  (warn_get (_w) == w_warn)\n\n/* Check if the warning is in \"error\" mode.  */\n#define warn_error(_w)   (warn_get (_w) == w_error)\n\nvoid warn_init (void);\nvoid decode_warn_actions (const char *value, const floc *flocp);\nchar *encode_warn_flag (char *fp);\n\nvoid warn_get_vardata (struct warning_data *data);\nvoid warn_set_vardata (const struct warning_data *data);\n\n#define warning(_t,_f,_m)                                   \\\n    do{                                                     \\\n        if (warn_check (_t))                                \\\n          {                                                 \\\n            char *_a = xstrdup (_m);                        \\\n            if (warn_error (_t))                            \\\n              fatal (_f, strlen (_a), \"%s\", _a);            \\\n            error (_f, strlen (_a), _(\"warning: %s\"), _a);  \\\n            free (_a);                                      \\\n          }                                                 \\\n    }while(0)\n"
  },
  {
    "path": "tests/.gitignore",
    "content": ".test-result\nconfig-flags.pm\nwork\n"
  },
  {
    "path": "tests/ChangeLog.1",
    "content": "2013-10-09  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/patspecific_vars: Typo fixes.\n\n2013-10-05  Paul Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (run_all_tests): Rewrite to be more clear.\n\t* scripts/features/jobserver: Avoid using $ENV{HOME} as it doesn't\n\texist everywhere.\n\t* scripts/features/default_names: End with 1;\n\n\t* scripts/features/loadapi: Use new calling signatures.  Verify\n\tthe NOEXPAND flag works.  Test with all valid function name\n\tcharacters.\n\n2013-09-29  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/SHELL: Solaris /bin/sh can't handle options in\n\tmultiple words; skip that test.\n\t* scripts/targets/ONESHELL: Ditto.\n\n\t* scripts/variables/GNUMAKEFLAGS: Verify that GNUMAKEFLAGS is\n\tcleared and options are not duplicated.\n\n2013-09-23  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/options/print-directory: Rename dash-w to\n\tprint-directory to avoid conflicts with dash-W on case-insensitive\n\tfilesystems.\n\n2013-09-22  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/se_implicit: Verify that order-only tokens\n\tinside second expansion are parsed correctly.\n\tTest for Savannah bug #31155.\n\n\t* run_make_tests.pl (set_more_defaults): If we can't find\n\tgnumake.h based on the make program we might be running from a\n\tremote build directory.  Parse the Makefile for the right path.\n\n\tFix some test issues on Solaris.\n\n\t* scripts/features/archives: Determine what output ar gives when\n\tadding and replacing objects and compare with that.\n\t* scripts/features/escape: Solaris /bin/sh doesn't properly handle\n\tbackslashes inside single quotes, so don't rely on it.\n\t* scripts/features/output-sync: false(1) gives different exit\n\tcodes on different systems; use \"exit 1\" instead.\n\t* scripts/features/parallelism: Increase the timeout for slower systems.\n\n2013-09-21  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/archives: Some versions of ar (MacOSX) generate\n\tdifferent output when creating archives.  Run it and verify the\n\treal output.\n\t* scripts/features/default_names: MacOSX is, like Windows,\n\tcase-preserving / case-insensitive.  Redo the test to avoid\n\tchecking for \"UNIX\".\n\t* test_driver.pl (attach_default_output): Don't dup stdout into\n\tstderr.  Reported by Denis Excoffier <bug-tar@Denis-Excoffier.org>\n\n\t* scripts/features/se_explicit: Fix a test that behaves\n\tdifferently with/without archive capability enabled.\n\t* scripts/features/output-sync: Don't test output-sync if it's not\n\tenabled.  We also skip it if parallelism is not enabled, although\n\tstrictly speaking some of the output-sync tests are valid even\n\twithout parallelism.\n\t* scripts/features/jobserver: Move some tests that require the\n\tjobserver from features/parallelism to a separate suite.  Only run\n\tthis if jobserver mode is enabled.\n\n\t* scripts/features/output-sync: Test shell functions writing to\n\tstderr in recipes: ensure it's captured via output-sync.  Test\n\toutput generated while reading makefiles and make sure it's\n\tcaptured via output-sync.  Make sure that fatal errors dump the\n\toutput so it's not lost.\n\n\t* scripts/options/dash-w: Add a test for -w flag.\n\n2013-09-15  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/misc/fopen-fail: Check for failure on infinite recursion.\n\t* run_make_tests.pl (run_make_test): Allow the answer string to be\n\tundef, which means that we shouldn't compare it at all.  Only the\n\texit code matters in this case.\n\t* test_driver.pl (compare_output): Ditto.\n\tTest for Savannah bug #27374.\n\n\t* scripts/features/parallelism: Test broken jobserver on recursion.\n\tTest for Savannah bug #39934.\n\n\t* scripts/options/eval: Verify --eval during restart.\n\tTest for Savannah bug #39203.\n\n2013-09-14  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync: Verify -Orecurse properly.\n\n2013-09-12  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync: Modify for output sync behavior.\n\t* scripts/variables/MAKE_RESTARTS: Ditto.\n\t* scripts/variables/MAKEFLAGS: Remove mode for --trace.\n\t* scripts/variables/GNUMAKEFLAGS: Ditto.\n\n2013-07-22  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/rule_glob: Add tests for wildcards in rules.\n\tTest for Savannah bug #39310.\n\n2013-07-09  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/se_implicit: Add a test for SE rules depending\n\ton other SE rules to be built.\n\n2013-05-26  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/archives: Test for Savannah bug #38442.\n\n\t* scripts/misc/bs-nl: Test for Savannah bug #39035.\n\tAdd a test for Savannah bug #38945.\n\n2013-05-22  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-n: Fix results after MAKEFLAGS fixes.\n\t* scripts/variables/MAKEFLAGS: Ditto.\n\t* scripts/variables/GNUMAKEFLAGS: Ditto.\n\n2013-05-14  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/loadapi: Add plugin_is_GPL_compatible symbol.\n\t* scripts/features/load: Ditto.\n\n2013-05-13  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync (output_sync_set): Update for new\n\t--trace behavior.\n\n2013-05-05  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync (output_sync_set): Remove\n\textraneous enter/leave lines, which are no longer printed.\n\tAdd tests for syncing command line printing.\n\t(output_sync_set): Rename options: \"job\"->\"line\"; \"make\"->\"recurse\"\n\n2013-05-04  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/loadapi: Use the new alloc functions.\n\n\t* scripts/features/output-sync (output_sync_set): New test for\n\tordered recursive output for -Ojob / -Otarget.\n\n2013-05-03  Eli Zaretskii  <eliz@gnu.org>\n\n\t* scripts/features/load: Fix signatures of testload_gmk_setup and\n\texplicit_setup, to bring them in line with the documentation.\n\n2013-04-28  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync (output_sync_set): Add tests for\n\tthe per-job syntax mode.\n\t(output_sync_set): Test improved error message location.\n\n2013-04-15  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync (output_sync_set): New arg syntax.\n\n2013-04-14  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/output-sync: Rewrite to be more reliable.\n\n\t* test_driver.pl (_run_command): Don't set SIGALRM until after we\n\tstart the child.  Print errors to the top-level output, which will\n\tbe stderr.\n\t(attach_default_output): Use a list of file handles as the stack.\n\t(detach_default_output): Ditto.\n\n\t* scripts/features/output-sync: Add a test for output-sync.\n\n2013-02-25  Paul Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (valid_option): Support the -srcdir flag.\n\t(set_more_defaults): Set up $srcdir if it's not set yet.\n\n\t* scripts/functions/guile: Verify gmk-eval doesn't expand twice.\n\t* scripts/features/load: Rework to test just the load capability.\n\t* scripts/features/loadapi: New set of tests for the load API.\n\n2013-01-19  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/load: Test loaded files with and without \"./\"\n\tprefix.  Add tests for automatically rebuilding loaded files if\n\tthey are out of date or non-existent.\n\n2013-01-13  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/archives: Add a check targets that have parens,\n\tbut are not archives.  See Savannah bug #37878.\n\n\t* scripts/options/dash-n: Verify -n is preserved after recursive /\n\tre-exec.  See Savannah bug #38051.\n\n2013-01-12  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Change rule so it doesn't depend\n\ton invocation order, etc.\n\n2012-10-29  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/load: New test suite for the \"load\" directive.\n\n2012-09-09  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/file: Get errors in the C locale, not the\n\tcurrent locale.  Fixes Savannah bug #35764.\n\n\t* scripts/features/escape: Check that backslashes before\n\tnon-special characters are not removed.\n\n\t* scripts/features/utf8: New test for UTF-8 support.\n\tSee Savannah bug #36529.\n\n\t* scripts/targets/POSIX: Add tests for default macro values as\n\tspecified by IEEE Std 1003.1-2008.  See Savannah bug #37069.\n\n2012-03-04  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/se_explicit: Test $(x:%=%) format in secondary\n\texpansion prerequisite lists.  See Savannah bug #16545.\n\n\t* scripts/features/escape: Test escaped \":\" in prerequisite lists.\n\tSee Savannah bug #12126.\n\n\t* scripts/variables/private: Test appending private variables in\n\tpattern-specific target rules.  See Savannah bug #35468.\n\n2012-03-03  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/SHELL: Ensure .SHELLFLAGS works with options\n\tseparated by whitespace.\n\n\t* scripts/targets/ONESHELL: Try .ONESHELL in combination with\n\twhitespace-separated options in .SHELLFLAGS.  See Savannah bug #35397.\n\n\t* scripts/functions/filter-out: Add filter tests and test escape\n\toperations.  See Savannah bug #35410.\n\n\t* guile.supp: Suppress valgrind errors from Guile\n\t* run_make_tests.pl: Use the Guile suppression file.\n\n\t* scripts/misc/bs-nl: Check for POSIX and non-POSIX\n\tbackslash/newline handling.  Addresses Savannah bug #16670.\n\n2012-01-29  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/flavors: Add tests for ::=\n\t* scripts/variables/define: Ditto\n\n\t* scripts/functions/file: Test the new $(file ...) function.\n\n2012-01-12  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/guile: New regression tests for Guile support.\n\n2011-12-10  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/targets/SECONDARY: Add prereq statements to ensure rules\n\tare printed in the right order for test #9\n\n2011-11-14  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/double_colon: Check double-colon with escaped\n\tfilenames.  See Savannah bug #33399.\n\n2011-09-18  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: On re-exec make sure we preserve\n\tthe value of MAKEFLAGS when necessary.  See Savannah bug #33873.\n\n\t* scripts/features/vpath3: Verify handling of -lfoo libraries\n\tfound via vpath vs. the standard directory search.\n\tSee Savannah bug #32511.\n\n2011-09-12  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/call: Verify that using export in a $(call ...)\n\tcontext creates a global variable.  See Savannah bug #32498.\n\n2011-09-02  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-n: Verify that in \"-n -t\", the -n takes\n\tpriority.  Patch from Michael Witten <mfwitten@gmail.com>.\n\n2011-08-29  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/varnesting: Test resetting of variables while\n\texpanding them.  See Savannah patch #7534\n\n2011-06-12  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/archives: Check archives with whitespace at the\n\tbeginning, end, and extra in the middle.\n\tAnother test for Savannah bug #30612.\n\n2011-05-07  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/private: Ensure we skip private variables when\n\tappending.  Test for Savannah bug #32872.\n\n\t* scripts/functions/wildcard: Verify wildcard used to test for\n\tfile existence/non-existence.\n\n2011-05-02  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/sort: Add a test for Savannah bug #33125.\n\n2011-04-17  David A. Wheeler  <dwheeler@dwheeler.com>\n\n\t* scripts/features/shell_assignment: Regression for \"!=\" feature\n\n2010-11-06  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Fix known-good output for BS/NL changes.\n\t* scripts/functions/call: Ditto.\n\t* scripts/variables/special: Ditto.\n\n\t* scripts/misc/bs-nl: New test suite for backslash/newline testing.\n\n2010-08-29  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/errors: Add new error message to output text.\n\t* scripts/variables/SHELL: Ditto.\n\t* scripts/targets/POSIX: Ditto.\n\t* scripts/options/dash-k: Ditto.\n\t* scripts/features/vpathplus: Ditto.\n\t* scripts/features/patternrules: Ditto.\n\t* scripts/features/parallelism: Ditto.\n\n2010-08-13  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/archives: New regression tests for archive\n\tsupport.  Test for fix to Savannah bug #30612.\n\n\t* run_make_tests.pl (set_more_defaults): Set a %FEATURES hash to\n\tthe features available in $(.FEATURES).\n\n2010-08-10  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/reinvoke: Ensure command line variable settings\n\tare preserved across make re-exec.  Tests Savannah bug #30723.\n\n2010-07-28  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/targets/POSIX: Compatibility issues with Solaris (and\n\tTru64?); \"false\" returns different exit codes, and set -x shows\n\toutput with extra whitespace.  Run the commands by hand first to\n\tfind out what the real shell would do, then compare what make does.\n\t* scripts/variables/SHELL: Ditto.\n\n2010-07-12  Paul Smith  <psmith@gnu.org>\n\n\t* test_driver.pl: Add a new $perl_name containing the path to Perl.\n\t* run_make_tests.pl (run_make_test): Replace the special string\n\t#PERL# in a makefile etc. with the path the Perl executable so\n\tmakefiles can use it.\n\n\t* scripts/targets/ONESHELL: Add a new set of regression tests for\n\tthe .ONESHELL feature.\n\n2010-07-06  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/SHELL: Test the new .SHELLFLAGS variable.\n\n\t* scripts/targets/POSIX: New file.  Test the .POSIX special target.\n\tVerify that enabling .POSIX changes the shell flags to set -e.\n\n2010-07-01  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/recursion: Add a space to separate command-line\n\targs.  Fixes Savannah bug #29968.\n\n2009-11-12  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* scripts/features/vpath3: Test for the new library search\n\tbehavior.\n\n2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* scripts/features/se_explicit: Enable the test for now fixed\n\tSavannah bug 25780.\n\n2009-10-06  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* scripts/variables/undefine: Tests for the new undefine feature.\n\n2009-10-03  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Test for open Savannah bug #26846.\n\n\t* scripts/variables/MAKE: Rewrite for new run_make_test() format.\n\n\t* scripts/variables/MAKEFLAGS: Created.\n\tAdd test for Savannah bug #2216 (still open).\n\n\t* scripts/features/include: Test for Savannah bug #102 (still open).\n\n2009-09-30  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* scripts/features/include: Add diagnostics issuing tests for\n\tcases where targets have been updated and failed with the\n\tdontcare flag. Savannah bugs #15110, #25493, #12686, #17740.\n\n2009-09-28  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/shell: Add regression test for Savannah bug\n\t#20513 (still open).\n\n\t* scripts/features/se_explicit: Add regression tests for Savannah\n\tbug #25780 (still open).\n\n\t* run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)?\n\tthat runs tests we know will fail.  This allows us to add\n\tregression tests to the test suite for bugs that haven't been\n\tfixed yet.\n\n2009-09-28  Boris Kolpackov  <boris@codesynthesis.com>\n\n\t* scripts/features/patspecific_vars: Add a test for the shortest\n\tstem first order.\n\n\t* scripts/features/patternrules: Add a test for the shortest stem\n\tfirst order.\n\n2009-09-24  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/se_implicit: Add a test for order-only\n\tsecondary expansion prerequisites.\n\n2009-09-23  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/patternrules: Test that we can remove pattern\n\trules, both single and multiple prerequisites.  Savannah bug #18622.\n\n\t* scripts/features/echoing: Rework for run_make_test().\n\n2009-06-14  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/vpath: Verify we don't get bogus circular\n\tdependency warnings if we choose a different file via vpath during\n\tupdate.  Savannah bug #13529.\n\n2009-06-13  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/MAKEFILES: Verify that MAKEFILES included\n\tfiles (and files included by them) don't set the default goal.\n\tSavannah bug #13401.\n\n\t* scripts/functions/wildcard: Test that wildcards with\n\tnon-existent glob matchers return empty.\n\n2009-06-09  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-B: Test the $? works correctly with -B.\n\tSavannah bug #17825.\n\n\t* scripts/features/patternrules: Test that dependencies of\n\t\"also_make\" targets are created properly.  Savannah bug #19108.\n\n\t* test_driver.pl (compare_output): Create a \"run\" file for failed\n\ttests containing the command that was run.\n\t(get_runfile): New function.\n\n\t* run_make_tests.pl (valid_option): Enhanced support for valgrind:\n\tallow memcheck and massif tools.\n\n\t* scripts/features/patternrules: Have to comment out a line in the\n\tfirst test due to backing out a change that broke the implicit\n\trule search algorithm.  Savannah bug #17752.\n\t* scripts/misc/general4: Remove a test that is redundant with\n\tpatternrules.\n\n\t* scripts/features/parallelism: Add a test for re-exec with\n\tjobserver master override.  Savannah bug #18124.\n\n2009-06-08  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Add a test for continued target\n\tvars after a semicolon.  Savannah bug #17521.\n\n2009-06-07  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/se_explicit: Make sure we catch defining\n\tprereqs during snap_deps().  Savannah bug #24622.\n\n\t* scripts/variables/automatic: Check prereq ordering when the\n\ttarget with the recipe has no prereqs.  Savannah bug #21198.\n\n\t* scripts/variables/LIBPATTERNS: Add a new set of test for\n\t$(.LIBPATTERNS) (previously untested!)\n\n2009-06-04  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/SHELL: The export target-specific SHELL test\n\thas an incorrect known-good-value.\n\n\t* scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.)\n\n\t* scripts/features/se_explicit: Add tests for Savannah bug #24588.\n\n2009-05-31  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697.\n\n\t* scripts/features/targetvars: Add tests of overrides for Savannah\n\tbug #26207.\n\t* scripts/features/patspecific_vars: Ditto.\n\n\t* scripts/features/patternrules: Add a test for Savannah bug #26593.\n\n2009-05-30  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/flavors: Update with new variable flavor tests.\n\t* scripts/variables/define: Create a new set of tests for\n\tdefine/endef and move those aspects of the flavors suite here.\n\n2009-05-25  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Ditto.\n\n\t* scripts/features/export: Test new variable parsing abilities.\n\n2009-02-23  Ramon Garcia  <ramon.garcia.f@gmail.com>\n\n\t* scripts/variables/private: Create a new suite of tests for 'private'.\n\n2007-11-04  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/functions/eval: Update error message for command -> recipe.\n\n\t* test_driver.pl (compare_output): Allow the answer to be a regex,\n\tif surrounded by '/'.\n\t* scripts/misc/close_stdout: Use a regex for the answer, since\n\tsometimes the error will have a description and sometimes it won't.\n\n2007-09-10  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/special: Add tests for .RECIPEPREFIX variable.\n\n2007-08-15  Paul Smith  <psmith@gnu.org>\n\n\tThese test cases were contributed by\n\tIcarus Sparry <savannah@icarus.freeuk.com> and J. David Bryan for\n\tSavannah bugs #3330 and #15919.\n\n\t* scripts/targets/SECONDARY: Add tests for Savannah bugs 3330 and\n\t15919.\n\n\t* scripts/features/parallelism: Add tests for wrong answer/hang\n\tcombining INTERMEDIATE, order-only prereqs, and parallelism.\n\tSee Savannah bugs 3330 and 15919.\n\n2007-07-13  Paul Smith  <psmith@gnu.org>\n\n\tInstall a timeout so tests can never loop infinitely.\n\tOriginal idea and patch for a single-test version provided by\n\tIcarus Sparry <savannah@icarus.freeuk.com>\n\n\t* test_driver.pl (_run_command): New function: this is called by\n\tother functions to actually run a command.  Before we run it,\n\tinstall a SIGALRM handler and set up a timer to go off in the\n\tfuture (default is 5s; this can be overridden by individual tests).\n\t(run_command): Call it.\n\t(run_command_with_output): Call it.\n\n\t* run_make_tests.pl (run_make_with_options): Override the default\n\ttimeout if the caller requests it.\n\t(run_make_test): Pass any timeout override to run_make_with_options.\n\n\t* scripts/features/parallelism: Increase the timeout for long tests.\n\t* scripts/options/dash-l: Ditto.\n\n2006-10-01  Paul Smith  <psmith@paulandlesley.org>\n\n\t* run_make_tests.pl (set_more_defaults): Remove setting of LANG in\n\tENV here.  This doesn't always work.\n\t* test_driver.pl (toplevel): Set LC_ALL to 'C' in the make\n\tenvironment.  Fixes Savannah bug #16698.\n\n2006-09-30  Paul Smith  <psmith@paulandlesley.org>\n\n\t* scripts/variables/automatic: Add back the test for bug #8154.\n\n2006-04-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/realpath: Don't run tests with multiple\n\tinitial slashes on Windows: those paths mean something different.\n\n2006-03-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Test that the jobserver is\n\tproperly managed when we have to re-exec the master instance of\n\tmake.\n\n2006-03-17  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/statipattrules: Add tests for bug #16053.\n\n2006-03-09  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/features/escape: Use \"pre:\" not \"p:\" to avoid conflicts\n\twith DOS drive letters.  Fixes Savannah bug #15947.\n\n\t* test_driver.pl (run_each_test): Set the status properly even\n\twhen a test fails to execute.  Fixes Savannah bug #15942.\n\n\t* scripts/functions/foreach: Use a different environment variable\n\tother than PATH to avoid differences with Windows platforms.\n\tFixes Savannah bug #15938.\n\n2006-03-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (set_more_defaults): Add CYGWIN_NT as a port\n\ttype W32.  Fixed Savannah bug #15937.\n\n\t* scripts/features/default_names: Don't call error() when the test\n\tfails.  Fixes Savannah bug #15941.\n\n2006-02-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Test a complex construction which\n\tguarantees that we have to merge variable lists of different\n\tsizes.  Tests for Savannah bug #15757.\n\n2006-02-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/error: Make sure filename/lineno information\n\tis related to where the error is expanded, not where it's set.\n\t* scripts/functions/warning: Ditto.\n\t* scripts/functions/foreach: Check for different error conditions.\n\t* scripts/functions/word: Ditto.\n\t* scripts/variables/negative: Test some variable reference failure\n\tconditions.\n\t* scripts/options/warn-undefined-variables: Test the\n\t--warn-undefined-variables flag.\n\n2006-02-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (set_more_defaults): Update valgrind support\n\tfor newer versions.\n\t* test_driver.pl (toplevel): Skip all hidden files/directories (ones\n\tbeginning with \".\").\n\n\t* scripts/functions/andor: Tests for $(and ...) and $(or ...)\n\tfunctions.\n\n2006-02-08  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/parallelism: Add a test for bug #15641.\n\n2006-02-06  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-W: Add a test for bug #15341.\n\n2006-01-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/automatic: Add a test for bug #8154.\n\n\t* README: Update to reflect the current state of the test suite.\n\n2005-12-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism, scripts/functions/wildcard,\n\tscripts/targets/FORCE, scripts/targets/PHONY,\n\tscripts/targets/SILENT: Use the default setting for\n\t$delete_command.  Fixes bug #15085.\n\n\t* run_make_tests.pl (get_this_pwd) [VMS]: Use -no_ask with delete_file.\n\n2005-12-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/misc/general4: Test implicit rules with '$' in the\n\tprereq list & prereq patterns.\n\t* scripts/features/se_implicit: Add in .SECONDEXPANSION settings.\n\n2005-12-09  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/patternrules: Add a test for bug #13022.\n\n2005-12-07  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/double_colon: Add a test for bug #14334.\n\n2005-11-17  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/functions/flavor: Add a test for the flavor function.\n\n2005-11-14  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/variables/INCLUDE_DIRS: Add a test for the .INCLUDE_DIRS\n\tspecial variable.\n\n2005-10-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/misc/general4: Test '$$' in prerequisites list.\n\t* scripts/features/statipattrules: Rewrite to use run_make_test().\n\tAdd various static pattern info.\n\t* scripts/features/se_statpat: Enable .SECONDEXPANSION target.\n\t* scripts/features/se_explicit: Add tests for handling '$$' in\n\tprerequisite lists with and without setting .SECONDEXPANSION.\n\t* scripts/features/order_only: Convert to run_make_test().\n\t* run_make_tests.pl (set_more_defaults): If we can't get the value\n\tof $(MAKE) from make, then fatal immediately.\n\n2005-08-31  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (get_this_pwd): Require the POSIX module (in\n\tan eval to trap errors) and if it exists, use POSIX::getcwd to\n\tfind the working directory.  If it doesn't exist, go back to the\n\tprevious methods.  This tries to be more accurate on Windows\n\tsystems.\n\n2005-08-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/abspath: Add some text to the error messages\n\tto get a better idea of what's wrong.  Make warnings instead of\n\terrors.\n\n\t* scripts/features/patspecific_vars: Don't use \"test\", which is\n\tUNIX specific.  Print the values and let the test script match\n\tthem.\n\n2005-08-25  Paul Smith  <psmith@gnu.org>\n\n\t* scripts/variables/SHELL: Use a /./ prefix instead of //: the\n\tformer works better with non-UNIX environments.  Fixes Savannah\n\tbug #14129.\n\n2005-08-13  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/functions/wildcard: Wrap calls to $(wildcard) with\n\t$(sort) so that the resulting order is no longer filesystem-\n\tdependent.\n\n2005-08-10  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/statipattrules: Add a test for Savannah bug #13881.\n\n2005-08-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Add a test for a bug reported by\n\tMichael Matz (matz@suse.de) in which make exits without waiting\n\tfor all its children in some situations during parallel builds.\n\n2005-07-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl: Reset the environment to a clean value every\n\ttime before we invoke make.  I'm suspicious that the environment\n\tisn't handled the same way in Windows as it is in UNIX, and some\n\tvariables are leaking out beyond the tests they are intended for.\n\tCreate an %extraENV hash tests can set to add more env. vars.\n\t* tests/scripts/features/export: Change to use %extraENV.\n\t* tests/scripts/functions/eval: Ditto.\n\t* tests/scripts/functions/origin: Ditto.\n\t* tests/scripts/options/dash-e: Ditto.\n\t* tests/scripts/variables/SHELL: Ditto.\n\n2005-06-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-W: Use 'echo >>' instead of touch to update\n\tfiles.\n\t* scripts/features/reinvoke: Rewrite to be safer on systems with\n\tsubsecond timestamps.\n\t* scripts/features/patternrules: False exits with different error\n\tcodes on different systems (for example, Linux => 1, Solaris => 255).\n\n\t* scripts/options/dash-W: Set the timestamp to foo.x in the future,\n\tto be sure it will be considered updated when it's remade.\n\n2005-06-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/shell: New test suite for the shell function.\n\n2005-06-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/include: Test include/-include/sinclude with no\n\targuments.  Tests fix for Savannah bug #1761.\n\n\t* scripts/misc/general3: Implement comprehensive testing of\n\tbackslash-newline behavior in command scripts: various types of\n\tquoting, fast path / slow path, etc.\n\tTests fix for Savannah bug #1332.\n\n\t* scripts/options/symlinks: Test symlinks to non-existent files.\n\tTests fix for Savannah bug #13280.\n\n\t* scripts/misc/general3: Test semicolons in variable references.\n\tTests fix for Savannah bug #1454.\n\n\t* scripts/variables/MAKE_RESTARTS: New file: test the\n\tMAKE_RESTARTS variable.\n\t* scripts/options/dash-B: Test re-exec doesn't loop infinitely.\n\tTests fix for Savannah bug #7566.\n\t* scripts/options/dash-W: New file: test the -W flag, including\n\tre-exec infinite looping.\n\n2005-06-12  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/misc/close_stdout: Add a test for Savannah bug #1328.\n\tThis test only works on systems that have /dev/full (e.g., Linux).\n\n2005-06-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/foreach: Add a test for Savannah bug #11913.\n\n2005-05-31  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/include: Add a test for Savannah bug #13216.\n\t* scripts/features/patternrules: Add a test for Savannah bug #13218.\n\n2005-05-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/conditionals: Add tests for the new if... else\n\tif... endif syntax.\n\n2005-05-03  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to\n\tDEFAULT_GOAL.\n\n2005-05-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Add a test for exporting recursive\n\tvariables containing $(shell) calls.  Rewrite this script to use\n\trun_make_test() everywhere.\n\n2005-04-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/targets/SECONDARY: Add a test for Savannah bug #12331.\n\n2005-03-15  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/variables/automatic: Add a test for Savannah bug #12320.\n\n2005-03-10  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/patternrules: Add a test for Savannah bug #12267.\n\n2005-03-09  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/variables/DEFAULT_TARGET: Add a test for Savannah\n\tbug #12266.\n\n2005-03-04  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/patternrules: Add a test for Savannah bug #12202.\n\n2005-03-03  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/se_implicit: Add a test for stem\n\ttermination bug. Add a test for stem triple-expansion bug.\n\n\t* scripts/features/se_statpat: Add a test for stem\n\ttriple-expansion bug.\n\n\t* scripts/features/statipattrules: Change test #4 to reflect\n\tnew way empty prerequisite list is handled.\n\n\n2005-03-01  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/statipattrules: Add a test for\n\tSavannah bug #12180.\n\n2005-02-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-q: Add a test for Savannah bug # 7144.\n\n\t* scripts/options/symlinks: New file to test checking of symlink\n\ttimestamps.  Can't use filename dash-L because it conflicts with\n\tdash-l on case-insensitive filesystems.\n\n\t* scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST:\n\tRename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3\n\tunique filenames.\n\n2005-02-28  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET\n\tspecial variable.\n\n2005-02-27  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/se_explicit: Test the second expansion in\n\texplicit rules.\n\t* scripts/features/se_implicit: Test the second expansion in\n\timplicit rules.\n\t* scripts/features/se_statpat: Test the second expansion in\n\tstatic pattern rules.\n\t* scripts/variables/automatic: Fix to work with the second\n\texpansion.\n\n\t* scripts/misc/general4: Add a test for bug #12091.\n\n2005-02-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/eval: Check that eval of targets within\n\tcommand scripts fails.  See Savannah bug # 12124.\n\n2005-02-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (compare_output): If a basic comparison of the\n\tlog and answer doesn't match, try harder: change all backslashes\n\tto slashes and all CRLF to LF.  This helps on DOS/Windows systems.\n\n2005-02-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/recursion: Test command line variable settings:\n\tonly one instance of a given variable should be provided.\n\n2004-11-30  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* tests/scripts/functions/abspath: New file: test `abspath'\n\tbuilt-in function.\n\n\t* tests/scripts/functions/realpath: New file: test `realpath'\n\tbuilt-in function.\n\n2004-11-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;\n\tthis doesn't really test anything useful in UNIX but...\n\n\t* scripts/variables/SHELL: New file: test proper handling of SHELL\n\taccording to POSIX rules.  Fixes bug #1276.\n\n2004-10-21  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/functions/word: Test $(firstword ) and $(lastword ).\n\n2004-10-05  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/patspecific_vars: Test simple/recursive\n\tvariable expansion.\n\n2004-09-28  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/include: Test dontcare flag inheritance\n\twhen rebuilding makefiles.\n\n2004-09-27  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* scripts/features/patspecific_vars: Test exported variables.\n\n2004-09-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (run_make_test): Don't add newlines to the\n\tmakestring or answer if they are completely empty.\n\n\t* scripts/features/patternrules: Rename from implicit_prereq_eval.\n\n\t* scripts/test_template: Rework the template.\n\n2004-09-21  Boris Kolpackov  <boris@kolpackov.net>\n\n\t* run_make_tests.pl: Change `#!/usr/local/bin/perl' to be\n\t`#!/usr/bin/env perl'.\n\n\t* scripts/features/implicit_prereq_eval: Test implicit rule\n\tprerequisite evaluation code.\n\n2004-09-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (run_make_test): Enhance to allow the make\n\tstring to be undef: in that case it reuses the previous make\n\tstring.  Allows multiple tests on the same makefile.\n\n\t* scripts/variables/flavors: Add some tests for prefix characters\n\tinteracting with define/endef variables.\n\n2004-09-20  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/substitution: Rewrite to use run_make_test()\n\tinterface, and add test for substitution failures reported by\n\tMarkus Mauhart <qwe123@chello.at>.\n\n2004-03-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (run_each_test, toplevel, compare_output): Change\n\tto track both the testing categories _AND_ the number of\n\tindividual tests, and report both sets of numbers.\n\n2004-02-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/origin: Set our own environment variable\n\trather than relying on $HOME.\n\n2004-01-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/conditionals: Test arguments to ifn?def which\n\tcontain whitespace (such as a function that is evaluated).  Bug\n\t#7257.\n\n2004-01-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/order_only: Test order-only prerequisites in\n\tpattern rules (patch #2349).\n\n2003-11-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/if: Test if on conditionals with trailing\n\twhitespace--bug #5798.\n\n\t* scripts/functions/eval: Test eval in a non-file context--bug #6195.\n\n2003-04-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/patspecific_vars: Test multiple patterns\n\tmatching the same target--Bug #1405.\n\n2003-04-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (set_more_defaults): A new $port_type of\n\t'OS/2' for (surprise!) OS/2.  Also choose a wait time of 2 seconds\n\tfor OS/2.\n\n2003-03-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/targets/SECONDARY: Test the \"global\" .SECONDARY (with\n\tnot prerequisites)--Bug #2515.\n\n2003-01-30  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Test very long target-specific\n\tvariable definition lines (longer than the default make buffer\n\tlength).  Tests patch # 1022.\n\n\t* scripts/functions/eval: Test very recursive $(eval ...) calls\n\twith simple variable expansion (bug #2238).\n\n\t* scripts/functions/word: Test error handling for word and\n\twordlist functions (bug #2407).\n\n2003-01-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/call: Test recursive argument masking (bug\n\t#1744).\n\n2002-10-25  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/eval: Test using $(eval ...) inside\n\tconditionals (Bug #1516).\n\n2002-10-14  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-t: Add a test for handling -t on targets\n\twith no commands (Bug #1418).\n\n2002-10-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Add a test for exporting\n\ttarget-specific vars (Bug #1391).\n\n2002-10-05  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/automatic: Add tests for $$(@), $${@}, $${@D},\n\tand $${@F}.\n\n2002-09-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/escape: Test handling of escaped comment\n\tcharacters in targets and prerequisites.\n\n2002-09-18  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/export: Test export/unexport of multiple\n\tvariables in a single command.\n\n2002-09-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Tests for Bug #940: test\n\ttarget-specific and pattern-specific variables in conjunction with\n\tdouble-colon targets.\n\n2002-09-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (compare_output): Match the new format for time\n\tskew error messages.\n\n\t* scripts/features/export: Created.  Add tests for export/unexport\n\tcapabilities, including exporting/unexporting expanded variables.\n\n\t* scripts/features/conditionals: Add a test for expanded variables\n\tin ifdef conditionals.\n\n2002-09-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/reinvoke: Change touch/sleep combos to utouch\n\tinvocations.\n\t* scripts/features/vpathgpath: Ditto.\n\t* scripts/features/vpathplus: Ditto.\n\t* scripts/options/dash-n: Ditto.\n\t* scripts/targets/INTERMEDIATE: Ditto.\n\t* scripts/targets/SECONDARY: Ditto.\n\n\t* scripts/options/dash-t: Added a test for the -t bug fixed by\n\tHenning Makholm.  This test was also contributed by Henning.\n\n\t* scripts/misc/general4: Add a test suite for obscure algorithmic\n\tfeatures of make.  First test: make sure creation subdirectories\n\tas prerequisites of targets works properly.\n\n\t* scripts/misc/version: Remove this bogus test.\n\n2002-08-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/misc/general3: Add a test for makefiles that don't end\n\tin newlines.\n\n\t* scripts/variables/special: Create tests for the special\n\tvariables (.VARIABLES and .TARGETS).  Comment out .TARGETS test\n\tfor now as it's not yet supported.\n\n2002-08-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-B: Add a test for the new -B option.\n\n2002-07-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (valid_option): Add support for Valgrind.  Use\n\t-valgrind option to the test suite.\n\t(set_more_defaults): Set up the file descriptor to capture\n\tValgrind output.  We have to unset its close-on-exec flag; we\n\thardcode the value for F_SETFD (2) rather than load it; hopefully\n\tthis will help us avoid breaking the Windows/DOS test suite.\n\n2002-07-10  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/automatic: Add some tests for $$@, $$(@D), and\n\t$$(@F).\n\n\t* test_driver.pl (utouch): Create a new function that creates a\n\tfile with a specific timestamp offset.  Use of this function will\n\tlet us avoid lots of annoying sleep() invocations in the tests\n\tjust to get proper timestamping, which will make the tests run a\n\tlot faster.  So far it's only used in the automatic test suite.\n\n2002-07-09  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/automatic: Create a test for automatic variables.\n\n2002-07-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/order_only: Test new order-only prerequisites.\n\n2002-07-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/eval: Test new function.\n\t* scripts/functions/value: Test new function.\n\t* scripts/variables/MAKEFILE_LIST: Test new variable.\n\n2002-04-28  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/call: New test: transitive closure\n\timplementation using $(call ...) to test variable recursion.\n\n2002-04-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (compare_dir_tree): Ignore CVS and RCS\n\tdirectories in the script directories.\n\n2001-05-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/flavors: Test define/endef scripts where only\n\tone of the command lines is quiet.\n\n2000-06-22  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-q: New file; test the -q option.  Includes\n\ta test for PR/1780.\n\n2000-06-21  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Added a test for PR/1709: allowing\n\tsemicolons in target-specific variable values.\n\n2000-06-19  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/addsuffix: Test for an empty final argument.\n\tActually this bug might have happened for any function, but this\n\tone was handy.\n\n2000-06-17  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* scripts/options/general: If parallel jobs are not supported,\n\texpect a warning message from Make.\n\n2000-06-15  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* scripts/options/general: Don't try -jN with N != 1 if parallel\n\tjobs are not supported.\n\n2000-05-24  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/general: Test general option processing (PR/1716).\n\n2000-04-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/strip: Test empty value to strip (PR/1689).\n\n2000-04-08  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* scripts/features/reinvoke: Sleep before updating the target\n\tfiles in the first test, to ensure its time stamp really gets\n\tnewer; otherwise Make might re-exec more than once.\n\n2000-04-07  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* scripts/features/double_colon: Don't run the parallel tests if\n\tparallel jobs aren't supported.\n\n2000-04-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/word: wordlist doesn't swap arguments anymore.\n\n2000-03-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/statipattrules: Test that static pattern rules\n\twhose prerequisite patterns resolve to empty strings throw an\n\terror (instead of dumping core).  Fixes PR/1670.\n\n\t* scripts/features/reinvoke: Make more robust by touching \"b\"\n\tfirst, to ensure it's not newer than \"a\".\n\tReported by Marco Franzen <Marco.Franzen@Thyron.com>.\n\t* scripts/options/dash-n: Ditto.\n\n\t* scripts/functions/call: Whoops.  The fix to PR/1527 caused\n\trecursive invocations of $(call ...) to break.  I can't come up\n\twith any way to get both working at the same time, so I backed out\n\tthe fix to 1527 and added a test case for recursive calls.  This\n\talso tests the fix for PR/1610.\n\n\t* scripts/features/double_colon: Test that circular dependencies\n\tin double-colon rule sets are detected correctly (PR/1671).\n\n2000-03-26  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/targets/INTERMEDIATE: Test that make doesn't remove\n\t.INTERMEDIATE files when given on the command line (PR/1669).\n\n2000-03-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-k: Add a test for error detection by\n\tmultiple targets depending on the same prerequisite with -k.\n\tFor PR/1634.\n\n2000-02-07  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/escape: Add a test for backslash-escaped spaces\n\tin a target name (PR/1586).\n\n2000-02-04  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/patspecific_vars: Add a test for pattern-specific\n\ttarget variables inherited from the parent target (PR/1407).\n\n2000-02-02  Paul D. Smith  <psmith@gnu.org>\n\n\t* run_make_tests.pl (set_more_defaults): Hard-code the LANG to C\n\tto make sure sorting order, etc. is predictable.\n\tReported by Andreas Jaeger <aj@suse.de>.\n\n\t* run_make_tests.pl (set_more_defaults): Set the $wtime variable\n\tdepending on the OS.  Eli Zaretskii <eliz@is.elta.co.il> reports\n\tthis seems to need to be *4* on DOS/Windows, not just 2.  Keep it\n\t1 for other systems.\n\t* scripts/features/vpathplus (touchfiles): Use the $wtime value\n\tinstead of hardcoding 2.\n\t* scripts/targets/SECONDARY: Ditto.\n\t* scripts/targets/INTERMEDIATE: Ditto.\n\n2000-01-27  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (toplevel): Don't try to run test scripts which\n\tare really directories.\n\n2000-01-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/include: Remove a check; the fix caused more\n\tproblems than the error, so I removed it and removed the test for\n\tit.\n\n2000-01-11  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/call: Add a test for PR/1517 and PR/1527: make\n\tsure $(call ...) doesn't eval its arguments and that you can\n\tinvoke foreach from it without looping forever.\n\n1999-12-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/targets/INTERMEDIATE: Add a test for PR/1423: make sure\n\t.INTERMEDIATE settings on files don't disable them as implicit\n\tintermediate possibilities.\n\n1999-12-01  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/double_colon: Add a test for PR/1476: Try\n\tdouble-colon rules as non-goal targets and during parallel builds\n\tto make sure they're handled serially.\n\n1999-11-17  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/functions/if: Add a test for PR/1429: put some text\n\tafter an if-statement to make sure it works.\n\n\t* scripts/features/targetvars: Add a test for PR/1380: handling +=\n\tin target-specific variable definitions correctly.\n\n1999-10-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/variables/MAKEFILES: This was really broken: it didn't\n\ttest anything at all, really.  Rewrote it, plus added a test for\n\tPR/1394.\n\n1999-10-13  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/options/dash-n: Add a test for PR/1379: \"-n doesn't\n\tbehave properly when used with recursive targets\".\n\n1999-10-08  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/targetvars: Add a check for PR/1378:\n\t\"Target-specific vars don't inherit correctly\"\n\n1999-09-29  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (get_osname): Change $fancy_file_names to\n\t$short_filenames and reverse the logic.\n\t(run_each_test): Change test of non-existent $port_host to use\n\t$short_filenames--problem reported by Eli Zaretskii.\n\n1999-09-23  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/parallelism: Add a check to ensure that the\n\tjobserver works when we re-invoke.  Also cleaned up the tests a\n\tlittle, reducing the number of rules we use so the test won't need\n\tas many \"sleep\" commands.\n\n1999-09-16  Paul D. Smith  <psmith@gnu.org>\n\n\t* scripts/features/reinvoke: Remove invocations of \"touch\" in\n\tmakefiles.  See the comments on the touch function rewrite below.\n\tNote that UNIX touch behaves the same way if the file already\n\texists: it sets the time to the _local_ time.  We don't want\n\tthis.  This is probably a good tip for makefile writers in\n\tgeneral, actually... where practical.\n\t* scripts/options/dash-l: Ditto.\n\t* scripts/options/dash-n: Ditto.\n\n\t* test_driver.pl (run_each_test): In retrospect, I don't like the\n\t.lN/.bN/.dN postfix required by DOS.  So, for non-DOS systems I\n\tchanged it back to use .log, .base, and .diff.\n\n\t* run_make_tests.pl (set_more_defaults): Move the check for the\n\tmake pathname to here from set_defaults (that's too early since it\n\thappens before the command line processing).\n\tCreate a new variable $port_type, calculated from $osname, to\n\tspecify what kind of system we're running on.  We should integrate\n\tthe VOS stuff here, too.\n\t(valid_option): Comment out the workdir/-work stuff so people\n\twon't be fooled into thinking it works... someone needs to fix\n\tthis, though!\n\n\t* scripts/functions/origin: Use $port_type instead of $osname.\n\t* scripts/functions/foreach: Ditto.\n\t* scripts/features/default_names: Ditto.\n\n1999-09-15  Paul D. Smith  <psmith@gnu.org>\n\n\t* test_driver.pl (touch): Rewrite this function.  Previously it\n\tused to use utime() to hard-set the time based on the current\n\tlocal clock, or, if the file didn't exist, it merely created it.\n\tThis mirrors exactly what real UNIX touch does, but it fails badly\n\ton networked filesystems where the FS server clock is skewed from\n\tthe local clock: normally modifying a file causes it to get a mod\n\ttime based on the _server's_ clock.  Hard-setting it based on the\n\t_local_ clock causes gratuitous errors and makes the tests\n\tunreliable except on local filesystems.  The new function will\n\tsimply modify the file, allowing the filesystem to set the mod\n\ttime as it sees fit.\n\n\t* scripts/features/parallelism: The second test output could\n\tchange depending on how fast some scripts completed; use \"sleep\"\n\tto force the order we want.\n\n\t* test_driver.pl (toplevel): A bug in Perl 5.000 to Perl 5.004\n\tmeans that \"%ENV = ();\" doesn't do the right thing.  This worked\n\tin Perl 4 and was fixed in Perl 5.004_01, but use a loop to delete\n\tthe environment rather than require specific versions.\n\n\t* run_make_tests.pl (set_more_defaults): Don't use Perl 5 s///\n\tmodifier \"s\", so the tests will run with Perl 4.\n\t(set_more_defaults): Set $pure_log to empty if there's no -logfile\n\toption in PURIFYOPTIONS.\n\t(setup_for_test): Don't remove any logs unless $pure_log is set.\n\n1999-09-15  Eli Zaretskii  <eliz@is.elta.co.il>\n\n\t* scripts/features/reinvoke: Put the SHELL definition in the right\n\ttest makefile.\n\n1999-09-15  Paul D. Smith  <psmith@gnu.org>\n\n\tChangeLog file for the test suite created.\n\f\n\nCopyright (C) 1992-2017 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "tests/NEWS",
    "content": "Changes from 0.4.9 to 3.78 (Sep 6, 1999):\n\n    Lots of new tests.  Renamed to follow the GNU Make scheme.  Also\n    added some support for using Purify with make.\n\n    Rob Tulloh contributed some changes to get the test suite running on\n    NT; I tweaked them a bit (hopefully I didn't break anything!)  Note\n    that NT doesn't grok the self-exec funkiness that Unix shells use,\n    so instead I broke that out into a separate shell script\n    \"run_make_tests\" that invokes perl with the (renamed) script\n    run_make_tests.pl.\n\n    Eli Zaretski contributed changes to get the test suite running on\n    DOS with DJGPP.  I also meddled in these somewhat.\n\n    If you're on DOS or NT you should run \"perl.exe run_make_tests.pl ...\"\n    If you're on Unix, you can continue to run \"./run_make_tests ...\" as\n    before.\n\nChanges from 0.4.8 to 0.4.9 (May 14, 1998):\n\n    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to\n    blame for problems in this version :).\n\n    Add some perl to test_driver.pl to strip out GNU Make clock skew\n    warning messages from the output before comparing it to the\n    known-good output.\n\n    A new test for escaped :'s in filenames (someone on VMS found this\n    didn't work anymore in 3.77): scripts/features/escape.\n\nChanges from 0.4.7 to 0.4.8 (May 14, 1998):\n\n    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to\n    blame for problems in this version :).\n\n    New tests for features to be included in GNU Make 3.77.\n\nChanges from 0.4.6 to 0.4.7 (August 18, 1997):\n\n    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to\n    blame for problems in this version :).\n\n    Reworked some tests to make sure they all work with both perl4 and perl5.\n\n    Work around a bug in perl 5.004 which doesn't clean the environment\n    correctly in all cases (fixed in at least 5.004_02).\n\n    Updated functions/strip to test for newline stripping.\n\n    Keep a $PURIFYOPTIONS env variable if present.\n\nChanges from 0.4.5 to 0.4.6 (April 07, 1997):\n\n    Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to\n    blame for problems in this version :).\n\n    Updated to work with GNU Make 3.76 (and pretests).\n\n    Added new tests and updated existing ones.  Note that the new tests\n    weren't tested with perl 4, however I think they should work.\n\n    Ignore any tests whose filenames end in \"~\", so that Emacs backup\n    files aren't run.\n\nChanges from 0.4.4 to 0.4.5 (April 29, 1995):\n\n    Updated to be compatible with perl 5.001 as well as 4.036.\n\n    Note: the test suite still won't work on 14-char filesystems\n    (sorry, Kaveh), but I will get to it.\n\n    Also, some tests and stuff still haven't made it in because I\n    haven't had time to write the test scripts for them.  But they,\n    too, will get in eventually.  Contributions of scripts (i.e., tests\n    that I can just drop in) are particularly welcome and will be\n    incorporated immediately.\n\nChanges from 0.4.3 to 0.4.4 (March 1995):\n\n    Updated for changes in make 3.72.12, and to ignore CVS directories\n    (thanks go to Jim Meyering for the patches for this).\n\n    Fixed uname call to not make a mess on BSD/OS 2.0 (whose uname -a\n    is very verbose).  Let me know if this doesn't work correctly on\n    your system.\n\n    Changed to display test name while it is running, not just when it\n    finishes.\n\n    Note: the test suite still won't work on 14-char filesystems\n    (sorry, Kaveh), but I will get to it.\n\n    Also, some tests and stuff still haven't made it in because I\n    haven't had time to write the test scripts for them.  But they,\n    too, will get in eventually.\n\nChanges from 0.4 to 0.4.3 (October 1994):\n\n    Fixed bugs (like dependencies on environment variables).\n\n    Caught up with changes in make.\n\n    The load_limit test should now silently ignore a failure due to\n    make not being able to read /dev/kmem.\n\n    Reorganized tests into subdirs and renamed lots of things so that\n    those poor souls who still have to deal with 14-char filename\n    limits won't hate me any more.  Thanks very much to Kaveh R. Ghazi\n    <ghazi@noc.rutgers.edu> for helping me with the implementation and\n    testing of these changes, and for putting up with all my whining\n    about it...\n\n    Added a $| = 1 so that systems that don't seem to automatically\n    flush their output for some reason will still print all the\n    output.  I'd hate for someone to miss out on the smiley that\n    you're supposed to get when all the tests pass... :-)\n\nChanges from 0.3 to 0.4 (August 1993):\n\n    Lost in the mists of time (and my hurry to get it out before I\n    left my job).\n\nChanges from 0.2 to 0.3 (9-30-92):\n\n    Several tests fixed to match the fact that MAKELEVEL > 0 or -C now\n    imply -w.\n\n    parallel_execution test fixed to not use double colon rules any\n    more since their behavior has changed.\n\n    errors_in_commands test fixed to handle different error messages\n    and return codes from rm.\n\n    Several tests fixed to handle -make_path with a relative path\n    and/or a name other than \"make\" for make.\n\n    dash-e-option test fixed to use $PATH instead of $USER (since the\n    latter does not exist on some System V systems).  This also\n    removes the dependency on getlogin (which fails under certain\n    weird conditions).\n\n    test_driver_core changed so that you can give a test name like\n    scripts/errors_in_commands and it will be handled correctly (handy\n    if you have a shell with filename completion).\n\nChanges from 0.1 to 0.2 (5-4-92):\n\n    README corrected to require perl 4.019, not 4.010.\n\n    -make_path replaces -old.\n\n    errors_in_commands test updated for change in format introduced in\n    make 3.62.6.\n\n    test_driver_core now uses a better way of figuring what OS it is\n    running on (thanks to meyering@cs.utexas.edu (Jim Meyering) for\n    suggesting this, as well as discovering the hard way that the old\n    way (testing for /mnt) fails on his machine).\n\n    Some new tests were added.\n\n\f\n-------------------------------------------------------------------------------\nCopyright (C) 1992-2024 Free Software Foundation, Inc.\nThis file is part of GNU Make.\n\nGNU Make is free software; you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free Software\nFoundation; either version 3 of the License, or (at your option) any later\nversion.\n\nGNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\nA PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along with\nthis program.  If not, see <https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "tests/config-flags.pm.W32",
    "content": "# This is a -*-perl-*- script\n#\n# Set variables for Windows systems.\n\n%CONFIG_FLAGS = (\n    USE_SYSTEM_GLOB => 'no'\n);\n\n1;\n"
  },
  {
    "path": "tests/config-flags.pm.in",
    "content": "# This is a -*-perl-*- script\n#\n# Set variables that were defined by configure, in case we need them\n# during the tests.\n\n%CONFIG_FLAGS = (\n    AM_LDFLAGS      => '@AM_LDFLAGS@',\n    AR              => '@AR@',\n    CC              => '@CC@',\n    CFLAGS          => '@CFLAGS@',\n    CPP             => '@CPP@',\n    CPPFLAGS        => '@CPPFLAGS@',\n    GUILE_CFLAGS    => '@GUILE_CFLAGS@',\n    GUILE_LIBS      => '@GUILE_LIBS@',\n    LDFLAGS         => '@LDFLAGS@',\n    LIBS            => '@LIBS@',\n    USE_SYSTEM_GLOB => '@USE_SYSTEM_GLOB@'\n);\n\n1;\n"
  },
  {
    "path": "tests/config_flags_pm.com",
    "content": "$!\n$! config_flags_pm.com  - Build config-flags.pm on VMS.\n$!\n$! Just good enough to run the self tests for now.\n$!\n$! Copyright (C) 2014-2024 Free Software Foundation, Inc.\n$! This file is part of GNU Make.\n$!\n$! GNU Make is free software; you can redistribute it and/or modify it under\n$! the terms of the GNU General Public License as published by the Free Software\n$! Foundation; either version 3 of the License, or (at your option) any later\n$! version.\n$!\n$! GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n$! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n$! FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n$! details.\n$!\n$! You should have received a copy of the GNU General Public License along with\n$! this program.  If not, see <https://www.gnu.org/licenses/>.\n$!\n$!\n$ open/read cfpm_in config-flags.pm.in\n$!\n$ outfile = \"sys$disk:[]config-flags.pm\"\n$!\n$ cflags = \"/include=([],[.lib]\"\n$!\n$ create 'outfile'\n$ open/append cfpm 'outfile'\n$!\n$cfpm_read_loop:\n$   read cfpm_in/end=cfpm_read_loop_end line_in\n$   line_in_len = f$length(line_in)\n$   if f$locate(\"@\", line_in) .lt. line_in_len\n$   then\n$       part1 = f$element(0, \"@\", line_in)\n$       key = f$element(1, \"@\", line_in)\n$       part2 = f$element(2, \"@\", line_in)\n$       value = \"\"\n$       if key .eqs. \"CC\" then value = \"CC\"\n$       if key .eqs. \"CPP\" then value = \"CPP\"\n$       if key .eqs. \"CFLAGS\" then value = cflags\n$       if key .eqs. \"GUILE_CFLAGS\" then value = cflags\n$       if key .eqs. \"USE_SYSTEM_GLOB\" then value = \"no\"\n$       write cfpm part1, value, part2\n$       goto cfpm_read_loop\n$   endif\n$   write cfpm line_in\n$   goto cfpm_read_loop\n$cfpm_read_loop_end:\n$ close cfpm_in\n$ close cfpm\n$!\n"
  },
  {
    "path": "tests/guile.supp",
    "content": "# Guile valgrind suppression file\n# Created with Guile 1.8.7\n\n# --- Garbage collection\n{\n  guilegc\n  Memcheck:Cond\n  ...\n  fun:scm_gc_for_newcell\n}\n{\n  guilegc\n  Memcheck:Value4\n  ...\n  fun:scm_gc_for_newcell\n}\n{\n  guilegc\n  Memcheck:Value8\n  ...\n  fun:scm_gc_for_newcell\n}\n\n\n# -- scm_alloc_struct\n{\n  guileheap\n  Memcheck:Leak\n  ...\n  fun:scm_alloc_struct\n}\n"
  },
  {
    "path": "tests/mkshadow",
    "content": "#!/bin/sh\n#\n# Simple script to make a \"shadow\" test directory, using symbolic links.\n# Typically you'd put the shadow in /tmp or another local disk\n#\n# Copyright (C) 1992-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\ncase \"$1\" in\n  \"\") echo 'Usage: mkshadow <destdir>'; exit 1 ;;\nesac\n\ndest=\"$1\"\n\nif [ ! -d \"$dest\" ]; then\n  echo \"Destination directory '$dest' must exist!\"\n  exit 1\nfi\n\nif [ ! -f run_make_tests ]; then\n  echo \"The current directory doesn't appear to contain the test suite!\"\n  exit 1\nfi\n\nsuite=`pwd | sed 's%^/tmp_mnt%%'`\nname=`basename \"$suite\"`\n\nfiles=`echo *`\n\nset -e\n\nmkdir \"$dest/$name\"\ncd \"$dest/$name\"\n\nln -s \"$suite\" .testdir\n\nfor f in $files; do\n  ln -s .testdir/$f .\ndone\n\nrm -rf work\n\necho \"Shadow test suite created in '$dest/$name'.\"\nexit 0\n"
  },
  {
    "path": "tests/run_make_tests",
    "content": "#!/bin/sh\nexec perl $0.pl ${1+\"$@\"}\n"
  },
  {
    "path": "tests/run_make_tests.bat",
    "content": "@echo off\nrem Copyright (C) 2017-2024 Free Software Foundation, Inc.\nrem This file is part of GNU Make.\nrem\nrem GNU Make is free software; you can redistribute it and/or modify it under\nrem the terms of the GNU General Public License as published by the Free\nrem Software Foundation; either version 3 of the License, or (at your option)\nrem any later version.\nrem\nrem GNU Make is distributed in the hope that it will be useful, but WITHOUT\nrem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\nrem FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for.\nrem more details.\nrem\nrem You should have received a copy of the GNU General Public License along\nrem with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nsetlocal\ncd \"%~dp0\"\n\nperl -I. .\\run_make_tests.pl %*\n"
  },
  {
    "path": "tests/run_make_tests.com",
    "content": "$! Test_make.com\n$!\n$! This is a wrapper for the GNU Make perl test programs on VMS.\n$!\n$! Parameter \"-help\" for description on how to use described below.\n$!\n$! Copyright (C) 2014-2024 Free Software Foundation, Inc.\n$! This file is part of GNU Make.\n$!\n$! GNU Make is free software; you can redistribute it and/or modify it under\n$! the terms of the GNU General Public License as published by the Free Software\n$! Foundation; either version 3 of the License, or (at your option) any later\n$! version.\n$!\n$! GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n$! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n$! FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n$! details.\n$!\n$! You should have received a copy of the GNU General Public License along with\n$! this program.  If not, see <https://www.gnu.org/licenses/>.\n$!\n$!\n$! Allow more than 8 parameters with using commas as a delimiter.\n$!\n$ params = \"''p1',''p2',''p3',''p4',''p5',''p6',''p7',''p8'\"\n$!\n$ test_flags = \",verbose,detail,keep,usage,help,debug,\"\n$ test_flags_len = f$length(test_flags)\n$ verbose_flag = \"\"\n$ detail_flag = \"\"\n$ keep_flag = \"\"\n$ usage_flag = \"\"\n$ help_flag = \"\"\n$ debug_flag = \"\"\n$!\n$ ignored_options = \"profile,make,srcdir,valgrind,memcheck,massif,\"\n$ ignored_option_len = f$length(ignored_options)\n$!\n$ testname = \"\"\n$ make :== $bin:make.exe\"\n$!\n$ i = 0\n$param_loop:\n$ param = f$element(i, \",\", params)\n$ i = i + 1\n$ if param .eqs. \"\" then goto param_loop\n$ if param .eqs. \",\" then goto param_loop_end\n$ param_len = f$length(param)\n$ if f$locate(\"/\", param) .lt. param_len\n$ then\n$   if testname .nes. \"\"\n$   then\n$       write sys$output \"Only the last test name specified will be run!\"\n$   endif\n$   testname = param\n$   goto param_loop\n$ endif\n$ lc_param = f$edit(param,\"LOWERCASE\") - \"-\"\n$ if f$locate(\",''lc_param',\", ignored_options) .lt. ignored_option_len\n$ then\n$   write sys$output \"parameter ''param' is ignored on VMS for now.\"\n$   goto param_loop\n$ endif\n$ if f$locate(\",''lc_param',\", test_flags) .lt. test_flags_len\n$ then\n$   'lc_param'_flag = \"-\" + lc_param\n$   goto param_loop\n$ endif\n$   write sys$output \"parameter ''param' is not known to VMS.\"\n$ goto param_loop\n$!\n$param_loop_end:\n$!\n$no_gnv = 1\n$no_perl = 1\n$!\n$!  Find GNV 2.1.3 + manditory updates\n$!  If properly updated, the GNV$GNU logical name is present.\n$!  Updated GNV utilities have a gnv$ prefix on them.\n$   gnv_root = f$trnlnm(\"GNV$GNU\", \"LNM$SYSTEM_TABLE\")\n$   if gnv_root .nes. \"\"\n$   then\n$       no_gnv = 0\n$       ! Check for update ar utility.\n$       new_ar = \"gnv$gnu:[usr.bin]gnv$ar.exe\"\n$       if f$search(new_ar) .nes. \"\"\n$       then\n$           ! See if a new port of ar exists.\n$           ar :== $'new_ar'\n$       else\n$           ! Fall back to legacy GNV AR wrapper.\n$           old_ar = \"gnv$gnu:[bin]ar.exe\"\n$           if f$search(old_ar) .nes. \"\"\n$           then\n$               ar :== $'old_ar'\n$           else\n$               no_gnv = 1\n$           endif\n$       endif\n$       ! Check for updated bash\n$       if no_gnv .eq. 0\n$       then\n$           new_bash = \"gnv$gnu:[bin]gnv$bash.exe\"\n$           if f$search(new_bash) .nes. \"\"\n$           then\n$               bash :== $'new_bash'\n$               sh :== $'new_bash'\n$           else\n$               no_gnv = 1\n$           endif\n$       endif\n$       ! Check for updated coreutils\n$       if no_gnv .eq. 0\n$       then\n$           new_cat = \"gnv$gnu:[bin]gnv$cat.exe\"\n$           if f$search(new_cat) .nes. \"\"\n$           then\n$               cat :== $'new_cat'\n$               cp :== $gnv$gnu:[bin]gnv$cp.exe\n$               echo :== $gnv$gnu:[bin]gnv$echo.exe\n$               false :== $gnv$gnu:[bin]gnv$false.exe\n$               true :== $gnv$gnu:[bin]gnv$true.exe\n$               touch :== $gnv$gnu:[bin]gnv$touch.exe\n$               mkdir :== $gnv$gnu:[bin]gnv$mkdir.exe\n$               rm :== $gnv$gnu:[bin]gnv$rm.exe\n$               sleep :== $gnv$gnu:[bin]gnv$sleep.exe\n$           else\n$               no_gnv = 1\n$           endif\n$       endif\n$       ! Check for updated diff utility.\n$       if no_gnv .eq. 0\n$       then\n$           new_diff = \"gnv$gnu:[usr.bin]gnv$diff.exe\"\n$           if f$search(new_diff) .nes. \"\"\n$           then\n$               ! See if a new port of diff exists.\n$               diff :== $'new_diff'\n$           else\n$               ! Fall back to legacy GNV diff\n$               old_diff = \"gnv$gnu:[bin]diff.exe\"\n$               if f$search(old_diff) .nes. \"\"\n$               then\n$                   diff :== $'old_diff'\n$               else\n$                   no_gnv = 1\n$               endif\n$           endif\n$       endif\n$   endif\n$!\n$if no_gnv\n$then\n$   write sys$output \"Could not find an up to date GNV installed!\"\n$   help_flag = 1\n$endif\n$!\n$! Find perl 5.18.1 or later.\n$!\n$! look in perl_root:[000000]perl_setup.com\n$ perl_root = f$trnlnm(\"perl_root\")\n$ ! This works with known perl installed from PCSI kits.\n$ if perl_root .nes. \"\"\n$ then\n$   perl_ver = f$element(1, \".\", perl_root)\n$   if f$locate(\"-\", perl_ver) .lt. f$length(perl_ver)\n$   then\n$       no_perl = 0\n$   endif\n$ endif\n$ if no_perl\n$ then\n$!  look for sys$common:[perl-*]perl_setup.com\n$   perl_setup = f$search(\"sys$common:[perl-*]perl_setup.com\")\n$   if perl_setup .eqs. \"\"\n$   then\n$       if gnv_root .nes. \"\"\n$       then\n$           gnv_device = f$parse(gnv_root,,,\"DEVICE\")\n$           perl_templ = \"[vms$common.perl-*]perl_setup.com\"\n$           perl_search = f$parse(perl_templ, gnv_device)\n$           perl_setup = f$search(perl_search)\n$       endif\n$   endif\n$   if perl_setup .nes. \"\"\n$   then\n$       @'perl_setup'\n$       no_perl = 0\n$   endif\n$ endif\n$!\n$ if no_perl\n$ then\n$   write sys$output \"Could not find an up to date Perl installed!\"\n$   help_flag = \"-help\"\n$ endif\n$!\n$!\n$ if help_flag .nes. \"\"\n$ then\n$   type sys$input\n$DECK\nThis is a test script wrapper for the run_make_tests.pl script.\n\nThis wrapper makes sure that the DCL symbols and logical names needed to\nrun the perl script are in place.\n\nThe test wrapper currently requires that the DCL symbols be global symbols.\nThose symbols will be left behind after the procedure is run.\n\nThe PERL_ROOT will be set to a compatible perl if such a perl is found and\nis not the default PERL_ROOT:.  This setting will persist after the test.\n\nThis wrapper should be run with the default set to the base directory\nof the make source.\n\nThe HELP parameter will bring up this text and then run the help script\nfor the Perl wrapper.  Not all options for the perl script have been\nimplemented, such as valgrind or specifying the make path or source path.\n\nRunning the wrapper script requires:\n  Perl 5.18 or later.\n  PCSI kits available from https://sourceforge.net/projects/vmsperlkit/files/\n\n  GNV 2.1.3 or later.  GNV 3.0.1 has not tested with this script.\n  Bash 4.2.47 or later.\n  Coreutils 8.21 or later.\n  https://sourceforge.net/projects/gnv/files/\n  Read before installing:\n     https://sourceforge.net/p/gnv/wiki/InstallingGNVPackages/\n  As updates for other GNV components get posted, those updates should\n  be used.\n\n$EOD\n$ endif\n$!\n$ if no_gnv .or. no_perl then exit 44\n$!\n$!\n$ default = f$environment(\"DEFAULT\")\n$ default_dev = f$element(0, \":\", default) + \":\"\n$ this = f$environment(\"PROCEDURE\")\n$ on error then goto all_error\n$ set default 'default_dev''f$parse(this,,,\"DIRECTORY\")'\n$!\n$! Need to make sure that the config-flags.pm exists.\n$ if f$search(\"config-flags.pm\") .eqs. \"\"\n$ then\n$   @config_flags_pm.com\n$ endif\n$ define/user bin 'default_dev'[-],gnv$gnu:[bin]\n$ define/user decc$filename_unix_noversion enable\n$ define/user decc$filename_unix_report enable\n$ define/user decc$readdir_dropdotnotype enable\n$ flags = \"\"\n$ if verbose_flag .nes. \"\" then flags = verbose_flag\n$ if detail_flag .nes. \"\" then flags = flags + \" \" + detail_flag\n$ if keep_flag .nes. \"\" then flags = flags + \" \" + keep_flag\n$ if usage_flag .nes. \"\" then flags = flags + \" \" + usage_flag\n$ if help_flag .nes. \"\" then flags = flags + \" \" + help_flag\n$ if debug_flag .nes. \"\" then flags = flags + \" \" + debug_flag\n$ flags = f$edit(flags, \"TRIM, COMPRESS\")\n$ if testname .nes. \"\"\n$ then\n$   perl run_make_tests.pl \"''testname'\" 'flags'\n$ else\n$   perl run_make_tests.pl 'flags'\n$ endif\n$all_error:\n$ set default 'default'\n$!\n"
  },
  {
    "path": "tests/run_make_tests.pl",
    "content": "#!/usr/bin/env perl\n# -*-perl-*-\n\n# Test driver for the Make test suite\n\n# Usage:  run_make_tests  [testname]\n#                         [-debug]\n#                         [-help]\n#                         [-verbose]\n#                         [-keep]\n#                         [-make <make prog>]\n#                        (and others)\n\n# Copyright (C) 1992-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n# Add the working directory to @INC and load the test driver\nuse FindBin;\nuse lib \"$FindBin::Bin\";\n\nour $testsroot = $FindBin::Bin;\n\nrequire \"test_driver.pl\";\n\nuse File::Spec;\n\nuse Cwd;\n$cwdpath = cwd();\n($cwdvol, $cwddir, $_) = File::Spec->splitpath($cwdpath, 1);\n\n# Some target systems might not have the POSIX module...\n$has_POSIX = eval { require \"POSIX.pm\" };\n\n%FEATURES = ();\n%DEFVARS = (\n    AR => undef,\n    CC => undef\n);\n\n$valgrind = 0;              # invoke make with valgrind\n$valgrind_args = '';\n$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full --suppressions=guile.supp';\n$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';\n$pure_log = undef;\n\n$make_path = undef;\n@make_command = ();\n\n$command_string = '';\n\n$all_tests = 0;\n\n# Shell commands\n\n$sh_name = '/bin/sh';\n$is_posix_sh = 1;\n\n$CMD_rmfile = 'rm -f';\n\n# rmdir broken in some Perls on VMS.\nif ($^O eq 'VMS')\n{\n  require VMS::Filespec;\n  VMS::Filespec->import();\n\n  sub vms_rmdir {\n    my $vms_file = vmspath($_[0]);\n    $vms_file = fileify($vms_file);\n    my $ret = unlink(vmsify($vms_file));\n    return $ret\n  };\n\n  *CORE::GLOBAL::rmdir = \\&vms_rmdir;\n\n  $CMD_rmfile = 'delete_file -no_ask';\n}\n\n%CONFIG_FLAGS = ();\n\n# Find the strings that will be generated for various error codes.\n# We want them from the C locale regardless of our current locale.\n\n$ERR_no_such_file = undef;\n$ERR_no_such_file_code = \"2\";\n$ERR_read_only_file = undef;\n$ERR_unreadable_file = undef;\n$ERR_nonexe_file = undef;\n$ERR_exe_dir = undef;\n$ERR_command_not_found = undef;\n\n#$SIG{INT} = sub { print STDERR \"Caught a signal!\\n\"; die @_; };\n\nsub valid_option\n{\n   local($option) = @_;\n\n   if ($option =~ /^-make([-_]?path)?$/i) {\n       $make_path = shift @argv;\n       if (! -f $make_path) {\n           print \"$option $make_path: Not found.\\n\";\n           exit 1;\n       }\n       return 1;\n   }\n\n   if ($option =~ /^-all([-_]?tests)?$/i) {\n       $all_tests = 1;\n       return 1;\n   }\n\n   if ($option =~ /^-(valgrind|memcheck)$/i) {\n       $valgrind = 1;\n       $valgrind_args = $memcheck_args;\n       return 1;\n   }\n\n   if ($option =~ /^-massif$/i) {\n       $valgrind = 1;\n       $valgrind_args = $massif_args;\n       return 1;\n   }\n\n# This doesn't work--it _should_!  Someone badly needs to fix this.\n#\n#   elsif ($option =~ /^-work([-_]?dir)?$/)\n#   {\n#      $workdir = shift @argv;\n#      return 1;\n#   }\n\n   return 0;\n}\n\n\n# This is an \"all-in-one\" function.  Arguments are as follows:\n#\n#  [0] (string):  The makefile to be tested.  undef means use the last one.\n#  [1] (string):  Arguments to pass to make.\n#  [2] (string):  Answer we should get back.\n#  [3] (integer): Exit code we expect.  A missing code means 0 (success)\n\n$makefile = undef;\n$old_makefile = undef;\n$mkpath = undef;\n$make_name = undef;\n$helptool = undef;\n\nsub subst_make_string\n{\n    my $wd = cwd();\n    local $_ = shift;\n    $makefile and s/#MAKEFILE#/$makefile/g;\n    s/#MAKEPATH#/$mkpath/g;\n    s/#MAKE#/$make_name/g;\n    s/#PERL#/$perl_name/g;\n    s/#PWD#/$wd/g;\n    s/#HELPER#/$perl_name $helptool/g;\n    return $_;\n}\n\nsub run_make_test\n{\n  local ($makestring, $options, $answer, $err_code, $timeout) = @_;\n  my @call = caller;\n\n  # If the user specified a makefile string, create a new makefile to contain\n  # it.  If the first value is not defined, use the last one (if there is\n  # one).\n\n  if (! defined $makestring) {\n    defined $old_makefile\n      or die \"run_make_test(undef) invoked before run_make_test('...')\\n\";\n    $makefile = $old_makefile;\n  } elsif ($makestring) {\n    if (! defined($makefile)) {\n      $makefile = &get_tmpfile();\n    }\n\n    # Make sure it ends in a newline and substitute any special tokens.\n    $makestring && $makestring !~ /\\n$/s and $makestring .= \"\\n\";\n    $makestring = subst_make_string($makestring);\n\n    # Populate the makefile!\n    open(MAKEFILE, \"> $makefile\") or die \"Failed to open $makefile: $!\\n\";\n    print MAKEFILE $makestring;\n    close(MAKEFILE) or die \"Failed to write $makefile: $!\\n\";\n  }\n\n  # Do the same processing on $answer as we did on $makestring.\n  if (defined $answer) {\n      $answer && $answer !~ /\\n$/s and $answer .= \"\\n\";\n      $answer = subst_make_string($answer);\n  }\n\n  run_make_with_options($makefile, $options, &get_logfile(0),\n                        $err_code, $timeout, @call);\n  &compare_output($answer, &get_logfile(1));\n\n  $old_makefile = $makefile;\n  $makefile = undef;\n}\n\nsub add_options {\n  my $cmd = shift;\n\n  foreach (@_) {\n    if (ref($cmd)) {\n      push(@$cmd, ref($_) ? @$_ : $_);\n    } else {\n      $cmd .= ' '.(ref($_) ? \"@$_\" : $_);\n    }\n  }\n\n  return $cmd;\n}\n\nsub create_command {\n  return !$_[0] || ref($_[0]) ? [@make_command] : join(' ', @make_command);\n}\n\n# The old-fashioned way...\n# $options can be a scalar (string) or a ref to an array of options\n# If it's a scalar the entire argument is passed to system/exec etc. as\n# a single string.  If it's a ref then the array is passed to system/exec.\n# Using a ref should be preferred as it's more portable but all the older\n# invocations use strings.\nsub run_make_with_options {\n  my ($filename, $options, $logname, $expected_code, $timeout, @call) = @_;\n  @call = caller unless @call;\n  my $code;\n  my $command = create_command($options);\n\n  $expected_code = 0 unless defined($expected_code);\n\n  # Reset to reflect this one test.\n  $test_passed = 1;\n\n  if ($filename) {\n    $command = add_options($command, '-f', $filename);\n  }\n\n  if ($options) {\n    if (!ref($options) && $^O eq 'VMS') {\n      # Try to make sure arguments are properly quoted.\n      # This does not handle all cases.\n      # We should convert the tests to use array refs not strings\n\n      # VMS uses double quotes instead of single quotes.\n      $options =~ s/\\'/\\\"/g;\n\n      # If the leading quote is inside non-whitespace, then the\n      # quote must be doubled, because it will be enclosed in another\n      # set of quotes.\n      $options =~ s/(\\S)(\\\".*\\\")/$1\\\"$2\\\"/g;\n\n      # Options must be quoted to preserve case if not already quoted.\n      $options =~ s/(\\S+)/\\\"$1\\\"/g;\n\n      # Special fixup for embedded quotes.\n      $options =~ s/(\\\"\\\".+)\\\"(\\s+)\\\"(.+\\\"\\\")/$1$2$3/g;\n\n      $options =~ s/(\\A)(?:\\\"\\\")(.+)(?:\\\"\\\")/$1\\\"$2\\\"/g;\n\n      # Special fixup for misc/general4 test.\n      $options =~ s/\"\"\\@echo\" \"cc\"\"/\\@echo cc\"/;\n      $options =~ s/\"\\@echo link\"\"\"/\\@echo link\"/;\n\n      # Remove shell escapes expected to be removed by bash\n      if ($options !~ /path=pre/) {\n        $options =~ s/\\\\//g;\n      }\n\n      # special fixup for options/eval\n      $options =~ s/\"--eval=\\$\\(info\" \"eval/\"--eval=\\$\\(info eval/;\n\n      print (\"Options fixup = -$options-\\n\") if $debug;\n    }\n\n    $command = add_options($command, $options);\n  }\n\n  my $cmdstr = cmd2str($command);\n  $command_string = \"# $call[1]:$call[2]:\\n$cmdstr\\n\";\n\n  if ($valgrind) {\n    print VALGRIND \"\\n\\nExecuting: $cmdstr\\n\";\n  }\n\n  {\n      my $old_timeout = $test_timeout;\n      $timeout and $test_timeout = $timeout;\n\n      # If valgrind is enabled, turn off the timeout check\n      $valgrind and $test_timeout = 0;\n\n      if (ref($command)) {\n          $code = run_command_with_output($logname, @$command);\n      } else {\n          $code = run_command_with_output($logname, $command);\n      }\n      $test_timeout = $old_timeout;\n  }\n\n  # Check to see if we have Purify errors.  If so, keep the logfile.\n  # For this to work you need to build with the Purify flag -exit-status=yes\n\n  if ($pure_log && -f $pure_log) {\n    if ($code & 0x7000) {\n      $code &= ~0x7000;\n\n      # If we have a purify log, save it\n      $tn = $pure_testname . ($num_of_logfiles ? \".$num_of_logfiles\" : \"\");\n      print(\"Renaming purify log file to $tn\\n\") if $debug;\n      rename($pure_log, \"$tn\") or die \"Can't rename $pure_log to $tn: $!\\n\";\n      ++$purify_errors;\n    } else {\n      unlink($pure_log);\n    }\n  }\n\n  if ($code != $expected_code) {\n    print \"Error running @make_command (expected $expected_code; got $code)\\n$call[1]:$call[2]: $cmdstr\\n\";\n    $test_passed = 0;\n    &create_file(get_runfile(), $command_string);\n    # If it's a SIGINT, stop here\n    if ($code & 127) {\n      print STDERR \"\\nCaught signal \".($code & 127).\"!\\n\";\n      ($code & 127) == 2 and exit($code);\n    }\n    return 0;\n  }\n\n  if ($profile & $vos) {\n    system \"add_profile @make_command\";\n  }\n\n  return 1;\n}\n\nsub print_usage\n{\n   &print_standard_usage (\"run_make_tests\",\n                          \"[-make MAKE_PATHNAME] [-memcheck] [-massif]\",);\n}\n\nsub print_help\n{\n   &print_standard_help (\n        \"-make\",\n        \"\\tYou may specify the pathname of the copy of make to run.\",\n        \"-valgrind\",\n        \"-memcheck\",\n        \"\\tRun the test suite under valgrind's memcheck tool.\",\n        \"\\tChange the default valgrind args with the VALGRIND_ARGS env var.\",\n        \"-massif\",\n        \"\\tRun the test suite under valgrind's massif tool.\",\n        \"\\tChange the default valgrind args with the VALGRIND_ARGS env var.\"\n       );\n}\n\nsub set_defaults\n{\n  # $profile = 1;\n  $testee = \"GNU Make\";\n  $make_path = \"make\";\n  $tmpfilesuffix = \"mk\";\n  if ($port_type eq 'UNIX') {\n    $scriptsuffix = '.sh';\n  } elsif ($port_type eq 'VMS') {\n    $scriptsuffix = '.com';\n  } else {\n    $scriptsuffix = '.bat';\n  }\n\n  $ENV{LC_ALL} = $makeENV{LC_ALL};\n  $ENV{LANG} = $makeENV{LANG};\n  $ENV{LANGUAGE} = $makeENV{LANGUAGE};\n\n  use locale;\n\n  my $loc = undef;\n  if ($has_POSIX) {\n      POSIX->import(qw(locale_h));\n      # Windows has POSIX locale, but only LC_ALL not LC_MESSAGES\n      $loc = POSIX::setlocale(&POSIX::LC_ALL);\n      POSIX::setlocale(&POSIX::LC_ALL, 'C');\n  }\n\n  if (open(my $F, '<', 'file.none')) {\n      print \"Opened non-existent file! Skipping related tests.\\n\";\n  } else {\n      $ERR_no_such_file = \"$!\";\n      if ($osname eq 'os390') {\n          $ERR_no_such_file_code = \"129\";\n      }\n  }\n\n  unlink('file.out');\n  touch('file.out');\n\n  chmod(0444, 'file.out');\n  if (open(my $F, '>', 'file.out')) {\n      print \"Opened read-only file! Skipping related tests.\\n\";\n      close($F);\n  } else {\n      $ERR_read_only_file = \"$!\";\n  }\n\n  $_ = `./file.out 2>&1`;\n  if ($? == 0) {\n      print \"Executed non-executable file!  Skipping related tests.\\n\";\n  } else {\n      $ERR_nonexe_file = \"$!\";\n  }\n\n  if ($^O =~ /cygwin/i) {\n      # For some reason the execute here gives a different answer than make's\n      print \"Skipping directory execution on $^O\\n\";\n  } else {\n      $_ = `./. 2>&1`;\n      if ($? == 0) {\n          print \"Executed directory!  Skipping related tests.\\n\";\n      } else {\n          $ERR_exe_dir = \"$!\";\n      }\n  }\n\n  chmod(0000, 'file.out');\n  if (open(my $F, '<', 'file.out')) {\n      print \"Opened unreadable file!  Skipping related tests.\\n\";\n      close($F);\n  } else {\n      $ERR_unreadable_file = \"$!\";\n  }\n\n  unlink('file.out') or die \"Failed to delete file.out: $!\\n\";\n\n  $_ = `/bin/sh -c 'bad-command 2>&1'`;\n  if ($? == 0) {\n      print \"Invoked invalid file!  Skipping related tests.\\n\";\n  } else {\n      s/\\r?\\n//g;\n      s/bad-command/#CMDNAME#/g;\n      $ERR_command_not_found = $_;\n  }\n\n  $loc and POSIX::setlocale(&POSIX::LC_ALL, $loc);\n\n  $ENV{LC_ALL} = $origENV{LC_ALL};\n  $ENV{LANG} = $origENV{LANG};\n  $ENV{LANGUAGE} = $origENV{LANGUAGE};\n}\n\n# This is no longer used: we import config-flags.pm instead\n# sub parse_status\n# {\n#   if (open(my $fh, '<', \"$_[0]/config.status\")) {\n#     while (my $line = <$fh>) {\n#       $line =~ m/^[SD]\\[\"([^\\\"]+)\"\\]=\" *(.*)\"/ and $CONFIG_FLAGS{$1} = $2;\n#     }\n#     return 1;\n#   }\n#   return 0;\n# }\n\nsub find_prog\n{\n  my $prog = $_[0];\n  my ($v, $d, $f) = File::Spec->splitpath($prog);\n\n  # If there's no directory then we need to search the PATH\n  if (! $d) {\n    foreach my $e (File::Spec->path()) {\n      $prog = File::Spec->catfile($e, $f);\n      if (-x $prog) {\n        ($v, $d, $f) = File::Spec->splitpath($prog);\n        last;\n      }\n    }\n  }\n\n  return ($v, $d, $f);\n}\n\nsub get_config\n{\n  return exists($CONFIG_FLAGS{$_[0]}) ? $CONFIG_FLAGS{$_[0]} : '';\n}\n\nsub set_more_defaults\n{\n  my $string;\n\n  # Try to find and load config-flags.pm.  They may be in the local directory\n  # or in the $srcpath if we're remote.\n\n  my $d = $cwd;\n  my $cfg = File::Spec->catfile($d, 'config-flags.pm');\n  if (! -f $cfg) {\n      # Nope, so look in the srcpath\n      my $d = $srcpath;\n      $cfg = File::Spec->catfile($d, 'config-flags.pm');\n  }\n\n  -f $cfg or die \"Can't locate config-flags.pm in $cwd\" . ($cwd eq $srcpath ? '' : \" or $srcpath\") . \"\\n\";\n\n  unshift(@INC, $d);\n  require \"config-flags.pm\";\n\n  # Find the full pathname of Make.  For DOS systems this is more\n  # complicated, so we ask make itself.\n  if ($osname eq 'VMS') {\n    $port_type = 'VMS-DCL' unless defined $ENV{\"SHELL\"};\n    # On VMS pre-setup make to be found with simply 'make'.\n    $make_path = 'make';\n  } else {\n    create_file('make.mk', 'all:;$(info $(MAKE))');\n    my $mk = `$make_path -sf make.mk`;\n    unlink('make.mk');\n    $mk =~ s/\\r?\\n$//;\n    $mk or die \"FATAL ERROR: Cannot determine the value of \\$(MAKE)\\n\";\n    $make_path = $mk;\n  }\n  ($mpv, $mpd, $mpf) = File::Spec->splitpath($make_path);\n\n  # Ask make what shell to use\n  create_file('shell.mk', 'all:;$(info $(SHELL))');\n  $sh_name = `$make_path -sf shell.mk`;\n  unlink('shell.mk');\n  $sh_name =~ s/\\r?\\n$//;\n  if (! $sh_name) {\n      print \"Cannot determine shell\\n\";\n      $is_posix_sh = 0;\n  } else {\n      my $o = `$sh_name -c ': do nothing' 2>&1`;\n      $is_posix_sh = $? == 0 && $o eq '';\n  }\n\n  $string = `$make_path -v`;\n  $string =~ /^(GNU Make [^,\\n]*)/ or die \"$make_path is not GNU Make.  Version:\\n$string\";\n  $testee_version = \"$1\\n\";\n\n  create_file('null.mk', '');\n\n  my $redir = '2>&1';\n  $redir = '' if os_name eq 'VMS';\n  $string = `$make_path -f null.mk $redir`;\n  if ($string =~ /(.*): \\*\\*\\* No targets\\.  Stop\\./) {\n    $make_name = $1;\n  } else {\n    $make_name = $mpf;\n  }\n\n  # prepend pwd if this is a relative path (ie, does not\n  # start with a slash, but contains one).  Thanks for the\n  # clue, Roland.\n\n  if ($mpd && !File::Spec->file_name_is_absolute($make_path) && $cwdvol eq $mpv) {\n     $mkpath = File::Spec->catpath($cwdvol, File::Spec->catdir($cwd, $mpd), $mpf);\n  } else {\n     $mkpath = $make_path;\n  }\n\n  # Find the helper tool\n  $helptool = File::Spec->catfile($srcpath, 'thelp.pl');\n\n  # It's difficult to quote this properly in all the places it's used so\n  # ensure it doesn't need to be quoted.\n  $helptool =~ s,\\\\,/,g if $port_type eq 'W32';\n  $helptool =~ s, ,\\\\ ,g;\n\n  # Get Purify log info--if any.\n\n  if (exists $ENV{PURIFYOPTIONS}\n      && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) {\n    $pure_log = $1 || '';\n    $pure_log =~ s/%v/$make_name/;\n    $purify_errors = 0;\n  }\n\n  $string = `$make_path -j 2 -f null.mk $redir`;\n  if ($string =~ /not supported/) {\n    $parallel_jobs = 0;\n  }\n  else {\n    $parallel_jobs = 1;\n  }\n\n  unlink('null.mk');\n\n  create_file('features.mk', 'all:;$(info $(.FEATURES))');\n  %FEATURES = map { $_ => 1 } split /\\s+/, `$make_path -sf features.mk`;\n  print \"$make_path FEATURES: @{[%FEATURES]}\\n\" if $verbose;\n  unlink('features.mk');\n\n  # Find the default values for different built-in variables\n  my $s = \"all:;\\n\";\n  foreach (keys %DEFVARS) {\n      $s .= \"\\$(info $_=\\$($_))\\n\";\n  }\n  create_file('defvars.mk', $s);\n  foreach (split \"\\n\", `$make_path -sf defvars.mk`) {\n      my @e = split /=/, $_, 2;\n      $DEFVARS{$e[0]} = $e[1];\n  }\n  unlink('defvars.mk');\n\n  # Set up for valgrind, if requested.\n\n  @make_command = ($make_path);\n\n  if ($valgrind) {\n    my $args = $valgrind_args;\n    open(VALGRIND, \"> valgrind.out\") or die \"Cannot open valgrind.out: $!\\n\";\n    #  -q --leak-check=yes\n    exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS};\n    @make_command = ('valgrind', '--log-fd='.fileno(VALGRIND));\n    push(@make_command, split(' ', $args));\n    push(@make_command, $make_path);\n    # F_SETFD is 2\n    fcntl(VALGRIND, 2, 0) or die \"fcntl(setfd) failed: $!\\n\";\n    system(\"echo Starting on `date` 1>&\".fileno(VALGRIND));\n    print \"Enabled valgrind support.\\n\";\n  }\n\n  if ($debug) {\n    print \"Port type:    $port_type\\n\";\n    print \"Make command: @make_command\\n\";\n    print \"Shell path:   $sh_name\".($is_posix_sh ? ' (POSIX)' : '').\"\\n\";\n    print \"#PWD#:        $cwdpath\\n\";\n    print \"#PERL#:       $perl_name\\n\";\n    print \"#MAKEPATH#:   $mkpath\\n\";\n    print \"#MAKE#:       $make_name\\n\";\n  }\n}\n\nsub setup_for_test\n{\n  $makefile = &get_tmpfile;\n  if (-f $makefile) {\n    unlink $makefile;\n  }\n\n  # Get rid of any Purify logs.\n  if ($pure_log) {\n    ($pure_testname = $testname) =~ tr,/,_,;\n    $pure_testname = \"$pure_log.$pure_testname\";\n    system(\"rm -f $pure_testname*\");\n    print(\"Purify testfiles are: $pure_testname*\\n\") if $debug;\n  }\n}\n\nexit !&toplevel;\n"
  },
  {
    "path": "tests/scripts/features/archives",
    "content": "#                                                              -*-mode: perl-*-\n\n$description = \"Test GNU Make's archive management features.\";\n\n$details = \"\\\nThis only works on systems that support it.\";\n\n# If this instance of make doesn't support archives, skip it\nexists $FEATURES{archives} or return -1;\n\n# In theory archive support exists on Windows but it doesn't use ar;\n# someone will need to port this test.\n$port_type eq 'W32' and return -1;\n\n# Create some .o files to work with\nif ($osname eq 'VMS') {\n  # VMS AR needs real object files at this time.\n  foreach $afile ('a1', 'a2', 'a3') {\n    # Use non-standard extension to prevent implicit rules from recreating\n    # objects when the test tampers with the timestamp.\n    1 while unlink \"$afile.c1\";\n    1 while unlink \"$afile.o\";\n    create_file(\"$afile.c1\", \"int $afile(void) {return 1;}\\n\");\n    system(\"cc $afile.c1 /object=$afile.o\");\n  }\n} else {\n  utouch(-60, qw(a1.o a2.o a3.o));\n}\n\n# Fallback if configure did not find AR\nmy $ar = get_config('AR') || 'ar';\n\nmy $redir = '2>&1';\n$redir = '' if $osname eq 'VMS';\n\n# This is the value from src/default.c\nmy $arflags = $osname eq 'aix' ? '-Xany -rv' : '-rv';\nmy $arvar = \"AR=\\\"$ar\\\"\";\n\n# Newer versions of binutils can be built with --enable-deterministic-archives\n# which forces all timestamps (among other things) to always be 0, defeating\n# GNU Make's archive support.  See if ar supports the U option to disable it.\nunlink('libxx.a');\n$_ = `$ar ${arflags}U libxx.a a1.o $redir`;\nif ($? == 0) {\n    $arflags = \"${arflags}U\";\n    $arvar = \"$arvar ARFLAGS=\\\"$arflags\\\"\";\n}\n\n# Some versions of ar print different things on creation.  Find out.\nunlink('libxx.a');\nmy $created = `$ar $arflags libxx.a a1.o $redir`;\n$created =~ s/a1\\.o/#OBJECT#/g;\n\n# Some versions of ar print different things on add.  Find out.\nmy $add = `$ar $arflags libxx.a a2.o $redir`;\n$add =~ s/a2\\.o/#OBJECT#/g;\n\n# Some versions of ar print different things on replacement.  Find out.\nmy $repl = `$ar $arflags libxx.a a2.o $redir`;\n$repl =~ s/a2\\.o/#OBJECT#/g;\n\nunlink('libxx.a');\n\n# Very simple\n($_ = $created) =~ s/#OBJECT#/a1.o/g;\nmy $answer = \"$ar $arflags libxx.a a1.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a1.o';\n}\nrun_make_test('all: libxx.a(a1.o)', $arvar, $answer);\n\n# Multiple .o's.  Add a new one to the existing library\n($_ = $add) =~ s/#OBJECT#/a2.o/g;\n\n$answer = \"$ar $arflags libxx.a a2.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a2.o';\n}\nrun_make_test('all: libxx.a(a1.o a2.o)', $arvar, $answer);\n\n# Touch one of the .o's so it's rebuilt\nif ($port_type eq 'VMS-DCL') {\n  # utouch is not changing what VMS library compare is testing for.\n  # So do a real change by regenerating the file.\n  1 while unlink('a1.o');\n  # Later time stamp than last insertion.\n  sleep(2);\n  system('cc a1.c1 /object=a1.o');\n  # Next insertion will have a later timestamp.\n  sleep(2);\n} else {\n  utouch(-40, 'a1.o');\n}\n\n($_ = $repl) =~ s/#OBJECT#/a1.o/g;\n$answer = \"$ar $arflags libxx.a a1.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a1.o';\n}\nrun_make_test(undef, $arvar, $answer);\n\n# Use wildcards\n$answer = \"#MAKE#: Nothing to be done for 'all'.\\n\";\nrun_make_test('all: libxx.a(*.o)', $arvar, $answer);\n\n# Touch one of the .o's so it's rebuilt\nif ($port_type eq 'VMS-DCL') {\n  # utouch is not changing what VMS library compare is testing for.\n  # So do a real change by regenerating the file.\n  1 while unlink('a1.o');\n  # Make timestamp later than last insertion.\n  sleep(2);\n  system('cc a1.c1 /object=a1.o');\n} else {\n  utouch(-30, 'a1.o');\n}\n($_ = $repl) =~ s/#OBJECT#/a1.o/g;\n$answer = \"$ar $arflags libxx.a a1.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a1.o';\n}\nrun_make_test(undef, $arvar, $answer);\n\n# Use both wildcards and simple names\nif ($port_type eq 'VMS-DCL') {\n  # utouch is not changing what VMS library compare is testing for.\n  # So do a real change by regenerating the file.\n  1 while unlink('a2.o');\n  sleep(2);\n  system('cc a2.c1 /object=a2.o');\n} else {\n  utouch(-50, 'a2.o');\n}\n($_ = $add) =~ s/#OBJECT#/a3.o/g;\n$_ .= \"$ar $arflags libxx.a a2.o\\n\";\n($_ .= $repl) =~ s/#OBJECT#/a2.o/g;\n$answer = \"$ar $arflags libxx.a a3.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a3.o';\n}\n\nrun_make_test('all: libxx.a(a3.o *.o)', $arvar, $answer);\n\n# Check whitespace handling\nif ($port_type eq 'VMS-DCL') {\n  # utouch is not changing what VMS library compare is testing for.\n  # So do a real change by regenerating the file.\n  1 while unlink('a2.o');\n  sleep(2);\n  system('cc a2.c1 /object=a2.o');\n} else {\n  utouch(-40, 'a2.o');\n}\n($_ = $repl) =~ s/#OBJECT#/a2.o/g;\n$answer = \"$ar $arflags libxx.a a2.o\\n$_\";\nif ($port_type eq 'VMS-DCL') {\n  $answer = 'library /replace libxx.a a2.o';\n}\nrun_make_test('all: libxx.a(  a3.o    *.o     )', $arvar, $answer);\n\nrmfiles(qw(a1.c1 a2.c1 a3.c1 a1.o a2.o a3.o libxx.a));\n\n# Check non-archive targets\n# See Savannah bug #37878\n$mk_string = q!\nall: foo(bar).baz\nfoo(bar).baz: ; @echo '$@'\n!;\n\nif ($port_type eq 'VMS-DCL') {\n    $mk_string =~ s/echo/write sys\\$\\$output/;\n    $mk_string =~ s/\\'/\\\"/g;\n}\nrun_make_test($mk_string, $arvar, \"foo(bar).baz\\n\");\n\n# Check renaming of archive targets.\n# See Savannah bug #38442\n\nmkdir('artest', 0777);\ntouch('foo.vhd');\n$mk_string = q!\nDIR = artest\nvpath % $(DIR)\ndefault: lib(foo)\n(%): %.vhd ; @cd $(DIR) && touch $(*F) && $(AR) $(ARFLAGS) $@ $(*F) >/dev/null 2>&1 && rm $(*F)\n.PHONY: default\n!;\nif ($port_type eq 'VMS-DCL') {\n  $mk_string =~ s#= artest#= sys\\$\\$disk:\\[.artest\\]#;\n  $mk_string =~ s#lib\\(foo\\)#lib.tlb\\(foo\\)#;\n  $mk_string =~ s#; \\@cd#; pipe SET DEFAULT#;\n  $mk_string =~\n    s#touch \\$\\(\\*F\\)#touch \\$\\(\\*F\\) && library/create/text sys\\$\\$disk:\\$\\@#;\n  $mk_string =~\n    s#library#if f\\$\\$search(\\\"\\$\\@\\\") \\.eqs\\. \\\"\\\" then library#;\n  # VMS needs special handling for null extension\n  $mk_string =~ s#\\@ \\$\\(\\*F\\)#\\@ \\$\\(\\*F\\)\\.#;\n  $mk_string =~ s#>/dev/null 2>&1 ##;\n}\nrun_make_test($mk_string, $arvar, \"\");\n\nrun_make_test(undef, $arvar, \"#MAKE#: Nothing to be done for 'default'.\\n\");\n\nunlink('foo.vhd');\nif ($osname eq 'VMS') {\n  remove_directory_tree(\"$cwdpath/artest\");\n} else {\n  remove_directory_tree('artest');\n}\n\n# Check long names for archive members.\n# See Savannah bug #54395\n\nif ($osname ne 'VMS' && $osname ne 'os390') {\n    my $pre = '1234567890123456';\n    my $lib = 'libxx.a';\n    my $cr = $created;\n    $cr =~ s/#OBJECT#/${pre}a/g;\n    my $ad = $add;\n    $ad =~ s/#OBJECT#/${pre}b/g;\n\n    run_make_test(qq!\n# Both member names > 16 characters long\ndefault: $lib(${pre}a) $lib(${pre}b)\n\n(%): % ; \\$(AR) \\$(ARFLAGS) \\$@ \\$%\n\n$pre%: ; touch \\$\\@\n!,\n                  $arvar, \"touch ${pre}a\\n$ar $arflags $lib ${pre}a\\n${cr}touch ${pre}b\\n$ar $arflags $lib ${pre}b\\n${ad}rm ${pre}a ${pre}b\\n\");\n\n    # Run it again; nothing should happen\n    run_make_test(undef, $arvar, \"#MAKE#: Nothing to be done for 'default'.\\n\");\n\n    unlink($lib);\n}\n\n# SV 61436 : Allow redefining archive rules to propagate timestamps\n\n# These don't work right on z/OS for some reason: archives not fully supported?\n\nif ($osname ne 'os390') {\n# Find the output when creating an archive from multiple files\n\nutouch(-10, 'a.o', 'b.o');\nmy $create2 = `$ar $arflags mylib.a a.o b.o $redir`;\ntouch('b.o');\nmy $add2 = `$ar $arflags mylib.a b.o $redir`;\nunlink('a.o', 'b.o', 'mylib.a');\n\n# Some systems complain when compiling empty files\ncreate_file('a.c', 'int i;');\ncreate_file('b.c', 'int j;');\nutouch(-20, 'a.c', 'b.c');\n\nmy $cc = get_config('CC') || 'cc';\nmy $vars = \"CC=\\\"$cc\\\" $arvar\";\n\nrun_make_test(q!\nmylib.a: mylib.a(a.o b.o)\n(%): % ;\n%.a: ; $(AR) $(ARFLAGS) $@ $?\n%.o : %.c ; @echo Compile $<; $(COMPILE.c) -o $@ $<\n!,\n              $vars, \"Compile a.c\\nCompile b.c\\n$ar $arflags mylib.a a.o b.o\\n${create2}rm b.o a.o\");\n\nrun_make_test(undef, $vars, \"#MAKE#: 'mylib.a' is up to date.\");\n\n# Now update one of the source files and it should be compiled and archived\n\nsleep(2);\ntouch('b.c');\n\nrun_make_test(undef, $vars, \"Compile b.c\\n$ar $arflags mylib.a b.o\\n${add2}rm b.o\");\n\nrun_make_test(undef, $vars, \"#MAKE#: 'mylib.a' is up to date.\");\n\nunlink('a.c', 'b.c', 'a.o', 'b.o', 'mylib.a');\n}\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/comments",
    "content": "$description = \"The following test creates a makefile to test comments\\n\"\n              .\"and comment continuation to the next line using a \\n\"\n              .\"backslash within makefiles.\";\n\n$details = \"To test comments within a makefile, a semi-colon was placed \\n\"\n          .\"after a comment was started.  This should not be reported as\\n\"\n          .\"an error since it is within a comment.  We then continue the \\n\"\n          .\"comment to the next line using a backslash.  To test whether\\n\"\n          .\"the comment really continued, we place an echo command with some\\n\"\n          .\"text on the line which should never execute since it should be \\n\"\n          .\"within a comment\\n\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<\\EOF;\n# Test comment vs semicolon parsing and line continuation\ntarget: # this ; is just a comment \\\n\t@echo This is within a comment. \n\t@echo There should be no errors for this makefile.\nEOF\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"There should be no errors for this makefile.\\n\";\n\n# COMPARE RESULTS\n\n&compare_output($answer,&get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/conditionals",
    "content": "#                                                                    -*-perl-*-\n$description = \"Check GNU Make conditionals.\";\n\n$details = \"Attempt various different flavors of GNU Make conditionals.\";\n\nrun_make_test('\narg1 = first\narg2 = second\narg3 = third\narg4 = cc\narg5 = second\n\nall:\nifeq ($(arg1),$(arg2))\n\t@echo arg1 equals arg2\nelse\n\t@echo arg1 NOT equal arg2\nendif\n\nifeq \\'$(arg2)\\' \"$(arg5)\"\n\t@echo arg2 equals arg5\nelse\n\t@echo arg2 NOT equal arg5\nendif\n\nifneq \\'$(arg3)\\' \\'$(arg4)\\'\n\t@echo arg3 NOT equal arg4\nelse\n\t@echo arg3 equal arg4\nendif\n\nifndef undefined\n\t@echo variable is undefined\nelse\n\t@echo variable undefined is defined\nendif\nifdef arg4\n\t@echo arg4 is defined\nelse\n\t@echo arg4 is NOT defined\nendif',\n              '',\n              'arg1 NOT equal arg2\narg2 equals arg5\narg3 NOT equal arg4\nvariable is undefined\narg4 is defined');\n\n\n# Test expansion of variables inside ifdef.\n\nrun_make_test('\nfoo = 1\n\nFOO = foo\nF = f\n\nDEF = no\nDEF2 = no\n\nifdef $(FOO)\nDEF = yes\nendif\n\nifdef $(F)oo\nDEF2 = yes\nendif\n\n\nDEF3 = no\nFUNC = $1\nifdef $(call FUNC,DEF)3\n  DEF3 = yes\nendif\n\nall:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)',\n              '',\n              'DEF=yes DEF2=yes DEF3=yes');\n\n\n# Test all the different \"else if...\" constructs\n\nrun_make_test('\narg1 = first\narg2 = second\narg3 = third\narg4 = cc\narg5 = fifth\n\nresult =\n\nifeq ($(arg1),$(arg2))\n  result += arg1 equals arg2\nelse ifeq \\'$(arg2)\\' \"$(arg5)\"\n  result += arg2 equals arg5\nelse ifneq \\'$(arg3)\\' \\'$(arg3)\\'\n  result += arg3 NOT equal arg4\nelse ifndef arg5\n  result += variable is undefined\nelse ifdef undefined\n  result += arg4 is defined\nelse\n  result += success\nendif\n\n\nall: ; @echo $(result)',\n              '',\n              'success');\n\n\n# Test some random \"else if...\" construct nesting\n\nrun_make_test('\narg1 = first\narg2 = second\narg3 = third\narg4 = cc\narg5 = second\n\nifeq ($(arg1),$(arg2))\n  $(info failed 1)\nelse ifeq \\'$(arg2)\\' \"$(arg2)\"\n  ifdef undefined\n    $(info failed 2)\n  else\n    $(info success)\n  endif\nelse ifneq \\'$(arg3)\\' \\'$(arg3)\\'\n  $(info failed 3)\nelse ifdef arg5\n  $(info failed 4)\nelse ifdef undefined\n  $(info failed 5)\nelse\n  $(info failed 6)\nendif\n\n.PHONY: all\nall: ; @:',\n              '',\n              'success');\n\n# SV 47960 : ensure variable assignments in non-taken legs don't cause problems\nrun_make_test('\nifneq ($(FOO),yes)\ntarget:\nelse\nBAR = bar\ntarget:\nendif\n\t@echo one\n',\n              '', \"one\\n\");\n\n# SV 64085: Ensure recipe prefixed conditionals are never considered\nrun_make_test(q!\nblah=1\nifdef blah\nelse\n\telse\nendif\nall:;\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\nblah=1\nifdef blah\nelse\n\tendif\nendif\nall:;\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\nblah=1\nifdef blah\nelse\n\tifdef blah\nendif\nall:;\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\nblah=1\nall:;\nfoo:\nifdef blah\n\tifdef blah\nendif\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\nblah=1\nall:;\nfoo:\nifdef blah\n\tendif\nendif\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\nblah=1\nall:;\nfoo:\nifdef blah\n\telse\nelse\nendif\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\n# SV 64402: parse braces in ifeq/ifneq properly\n\nrun_make_test(q!\nifeq ($(and a,b),)\nendif\nifeq (${and a,b},)\nendif\nifeq (${and $(x),${or $(z),${q}}},)\nendif\nifeq (${and ),(},)\nendif\nifeq ($(and },{),)\nendif\n# We can hide the comma in a variable\nC = ,\nifeq ((and a$Cb),)\nendif\nall:;\n!,\n    '', \"#MAKE#: 'all' is up to date.\");\n\n# The \",\" in \"$,\" is a variable name not a comma\nrun_make_test(q!\nifeq ($,,)\n$(info ok)\nendif\nall:;\n!,\n    '', \"ok\\n#MAKE#: 'all' is up to date.\");\n\n# Without variable references we don't do anything special with parens\nrun_make_test(q!\nifeq ((and a,b),)\nendif\nall:;\n!,\n    '', \"#MAKEFILE#:2: extraneous text after 'ifeq' directive\\n#MAKE#: 'all' is up to date.\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/features/default_names",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"This script tests to make sure that Make looks for\ndefault makefiles in the correct order (GNUmakefile,makefile,Makefile)\";\n\n# Create a makefile called \"GNUmakefile\"\n$makefile = \"GNUmakefile\";\n\nopen(MAKEFILE,\"> $makefile\");\nprint MAKEFILE \"FIRST: ; \\@echo It chose GNUmakefile\\n\";\nclose(MAKEFILE);\n\n# Create another makefile called \"makefile\"\nopen(MAKEFILE,\"> makefile\");\nprint MAKEFILE \"SECOND: ; \\@echo It chose makefile\\n\";\nclose(MAKEFILE);\n\n# DOS/W32/MacOSX platforms are case-insensitive / case-preserving, so\n# Makefile is the same file as makefile.  Just test what we can here.\n\nmy $case_sensitive = 0;\nif (! -f 'Makefile') {\n    # Create another makefile called \"Makefile\"\n    $case_sensitive = 1;\n    open(MAKEFILE,\"> Makefile\");\n    print MAKEFILE \"THIRD: ; \\@echo It chose Makefile\\n\";\n    close(MAKEFILE);\n}\n\nrun_make_with_options(\"\",\"\",&get_logfile);\ncompare_output(\"It chose GNUmakefile\\n\",&get_logfile(1));\nunlink($makefile);\n\nrun_make_with_options(\"\",\"\",&get_logfile);\ncompare_output(\"It chose makefile\\n\",&get_logfile(1));\nunlink(\"makefile\");\n\nif ($case_sensitive) {\n    run_make_with_options(\"\",\"\",&get_logfile);\n    compare_output(\"It chose Makefile\\n\",&get_logfile(1));\n    unlink(\"Makefile\");\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/dircache",
    "content": "#                                                               -*-mode: perl-*-\n\n$description = \"Test the directory cache behavior.\";\n\n# The first wildcard should bring the entire directory into the cache Then we\n# create a new file \"behind make's back\" then see if the next wildcard detects\n# it.\n\nrun_make_test(q!\n_orig := $(wildcard ./*)\n$(shell echo > anewfile)\n_new := $(wildcard ./*)\n$(info diff=$(filter-out $(_orig),$(_new)))\nall:;@:\n!,\n              '', \"diff=./anewfile\\n\");\n\nrmfiles('anewfile');\n\nrun_make_test(q!\n_orig := $(wildcard ./*)\n$(file >anewfile)\n_new := $(wildcard ./*)\n$(info diff=$(filter-out $(_orig),$(_new)))\nall:;@:\n!,\n              '', \"diff=./anewfile\\n\");\n\nrmfiles('anewfile');\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/double_colon",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test handling of double-colon rules.\";\n\n$details = \"\\\nWe test these features:\n\n  - Multiple commands for the same (double-colon) target\n  - Different prerequisites for targets: only out-of-date\n    ones are rebuilt.\n  - Double-colon targets that aren't the goal target.\n\nThen we do the same thing for parallel builds: double-colon\ntargets should always be built serially.\";\n\n# TEST 0: A simple double-colon rule that isn't the goal target.\n\nrun_make_test(q!\nall: baz\n\nfoo:: f1.h ; @echo foo FIRST\nfoo:: f2.h ; @echo foo SECOND\n\nbar:: ; @echo aaa; sleep 1; echo aaa done\nbar:: ; @echo bbb\n\nbaz:: ; @echo aaa\nbaz:: ; @echo bbb\n\nbiz:: ; @echo aaa\nbiz:: two ; @echo bbb\n\ntwo: ; @echo two\n\nf1.h f2.h: ; @echo $@\n\nd :: ; @echo ok\nd :: d ; @echo oops\n!,\n              \"all\", \"aaa\\nbbb\\n\");\n\n# TEST 1: As above, in parallel\n\nif ($parallel_jobs) {\n  run_make_test(undef, \"-j10 all\", \"aaa\\nbbb\\n\");\n}\n\n# TEST 2: A simple double-colon rule that is the goal target\n\nrun_make_test(undef, \"bar\", \"aaa\\naaa done\\nbbb\\n\");\n\n# TEST 3: As above, in parallel\n\nif ($parallel_jobs) {\n  run_make_test(undef, \"-j10 bar\", \"aaa\\naaa done\\nbbb\\n\");\n}\n\n# TEST 4: Each double-colon rule is supposed to be run individually\n\n&utouch(-5, 'f2.h');\n&touch('foo');\n\nrun_make_test(undef, \"foo\", \"f1.h\\nfoo FIRST\\n\");\n\n# TEST 5: Again, in parallel.\n\nif ($parallel_jobs) {\n  run_make_test(undef, \"-j10 foo\", \"f1.h\\nfoo FIRST\\n\");\n}\n\n# TEST 6: Each double-colon rule is supposed to be run individually\n\n&utouch(-5, 'f1.h');\nunlink('f2.h');\n&touch('foo');\n\nrun_make_test(undef, \"foo\", \"f2.h\\nfoo SECOND\\n\");\n\n# TEST 7: Again, in parallel.\n\nif ($parallel_jobs) {\n  run_make_test(undef, \"-j10 foo\", \"f2.h\\nfoo SECOND\\n\");\n}\n\n# TEST 8: Test circular dependency check; PR/1671\n\nrun_make_test(undef, \"d\", \"ok\\n$make_name: circular d <- d dependency dropped\\noops\\n\");\n\n# TEST 8: I don't grok why this is different than the above, but it is...\n#\n# Hmm... further testing indicates this might be timing-dependent?\n#\n#if ($parallel_jobs) {\n#  run_make_test(undef, \"-j10 biz\", \"aaa\\ntwo\\nbbb\\n\");\n#}\n\nunlink('foo','f1.h','f2.h');\n\n\n# TEST 9: make sure all rules in s double colon family get executed\n#         (Savannah bug #14334).\n#\n\n&touch('one');\n&touch('two');\n\nrun_make_test('\n.RECIPEPREFIX = >\n.PHONY: all\nall: result\n\nresult:: one\n> @echo $^ >>$@\n> @echo $^\n\nresult:: two\n> @echo $^ >>$@\n> @echo $^\n\n',\n'',\n'one\ntwo');\n\nunlink('result','one','two');\n\n# TEST 10: SV 33399 : check for proper backslash handling\n\nrun_make_test('\na\\ xb :: ; @echo one\na\\ xb :: ; @echo two\n',\n              '', \"one\\ntwo\\n\");\n\n# Test 11: SV 44742 : All double-colon rules should be run in parallel build.\n\nrun_make_test('\n.RECIPEPREFIX = >\nresult :: 01\n> @echo update\n> @touch $@\nresult :: 02\n> @echo update\n> @touch $@\nresult :: 03\n> @echo update\n> @touch $@\nresult :: 04\n> @echo update\n> @touch $@\nresult :: 05\n> @echo update\n> @touch $@\n01 02 03 04 05:\n> @touch 01 02 03 04 05\n',\n              '-j10 result', \"update\\nupdate\\nupdate\\nupdate\\nupdate\\n\");\n\nunlink('result', '01', '02', '03', '04', '05');\n\n# Test 12: SV 44742 : Double-colon rules with parallelism\n\nrun_make_test('\nroot: all ; echo root\nall:: ; echo all_one\nall:: 3 ; echo all_two\n%: ; sleep $*\n',\n              '-rs -j2 1 2 root', \"all_one\\nall_two\\nroot\\n\");\n\n# SV 47995 : Parallel double-colon rules with FORCE\n\nrun_make_test('\nall:: ; @echo one\n\nall:: joe ; @echo four\n\njoe: FORCE ; touch joe-is-forced\n\nFORCE:\n',\n              '-j5', \"one\\ntouch joe-is-forced\\nfour\\n\");\n\nunlink('joe-is-forced');\n\n# sv 60188.\n# Even though test.x is explicitly mentioned, terminal pattern rules still\n# apply only if the prerequisite exists.\ntouch('hello.z');\n\n# subtest 1. test.x is explicitly mentioned.\nrun_make_test(q!\nall: hello.z\n%.z:: test.x ; touch $@\n%.x: ;\n!,\n              '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.z');\n\n# subtest 2. hello.x is derived from the stem.\ntouch('hello.z');\n\nrun_make_test(q!\nall: hello.z\n%.z:: %.x; touch $@\n%.x: ; touch $@\n!,\n              '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.z');\n\n# subtest 3\n# hello.x is explicitly mentioned on an unrelated rule and thus is not an\n# intermediate file.\n# Terminal pattern rules do not apply anyway and there is no rule to built\n# 'hello.x'.\ntouch('hello.z');\nrun_make_test(q!\nall: hello.z\n%.z:: %.x; touch $@\n%.x: ;\nunrelated: hello.x\n!,\n              '', \"#MAKE#: *** No rule to make target 'hello.x', needed by 'hello.z'.  Stop.\\n\", 512);\n\n# SV 64016.\n# Test that update_goal_chain moves to the next target while the current\n# target is being built: hello.x recipe is started and update_goal_chain\n# begins to update bye.x.\n\nrun_make_test(q!\nhello.x::; @#HELPER# -q wait bye.x out $@\nbye.x::; @#HELPER# sleep 1 file $@\n!,\n              '-j2 hello.x bye.x', \"sleep 1\\nfile bye.x\\nhello.x\");\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/echoing",
    "content": "#                                                                    -*-perl-*-\n$description = \"The following test creates a makefile to test command\nechoing.  It tests that when a command line starts with\na '\\@', the echoing of that line is suppressed.  It also\ntests the -n option which tells make to ONLY echo the\ncommands and no execution happens.  In this case, even\nthe commands with '\\@' are printed. Lastly, it tests the\n-s flag which tells make to prevent all echoing, as if\nall commands started with a '\\@'.\";\n\n$details = \"This test is similar to the 'clean' test except that a '\\@' has\nbeen placed in front of the delete command line.  Four tests\nare run here.  First, make is run normally and the first echo\ncommand should be executed.  In this case there is no '\\@' so\nwe should expect make to display the command AND display the\nechoed message.  Secondly, make is run with the clean target,\nbut since there is a '\\@' at the beginning of the command, we\nexpect no output; just the deletion of a file which we check\nfor.  Third, we give the clean target again except this time\nwe give make the -n option.  We now expect the command to be\ndisplayed but not to be executed.  In this case we need only\nto check the output since an error message would be displayed\nif it actually tried to run the delete command again and the\nfile didn't exist. Lastly, we run the first test again with\nthe -s option and check that make did not echo the echo\ncommand before printing the message.\\n\";\n\n$example = \"EXAMPLE_FILE\";\n\ntouch($example);\n\n# TEST #1\n# -------\n\nrun_make_test(\"\nall:\n\\techo This makefile did not clean the dir... good\nclean:\n\\t\\@$CMD_rmfile $example\\n\",\n              '', 'echo This makefile did not clean the dir... good\nThis makefile did not clean the dir... good');\n\n# TEST #2\n# -------\n\nrun_make_test(undef, 'clean', '');\nif (-f $example) {\n  $test_passed = 0;\n  unlink($example);\n}\n\n# TEST #3\n# -------\n\nrun_make_test(undef, '-n clean', \"$CMD_rmfile $example\\n\");\n\n\n# TEST #4\n# -------\n\nrun_make_test(undef, '-s', \"This makefile did not clean the dir... good\\n\");\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/errors",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test ignored failures in recipe command lines\";\n\nrun_make_test(qq!\none:\n\\t-exit 1\n\\texit 0\ntwo:\n\\texit 1\n\\texit 0\n!,\n              \"one\", \"exit 1\\n#MAKE#: [#MAKEFILE#:3: one] Error 1 (ignored)\\nexit 0\\n\");\n\n# TEST #1\n# -------\n\nrun_make_test(undef, \" -i two\",\n              \"exit 1\\n#MAKE#: [#MAKEFILE#:6: two] Error 1 (ignored)\\nexit 0\\n\");\n\n# TEST #2\n# -------\n\n# Test that error line offset works\n\nrun_make_test(qq!\nall:\n\\t\\@echo hi\n\\t\\@echo there\n\\t\\@exit 1\n!,\n              '', \"hi\\nthere\\n#MAKE#: *** [#MAKEFILE#:5: all] Error 1\", 512);\n\n# Windows error look completely different :-/\n\nsub errors_getinfo\n{\n    my ($cmd, $args, $err) = @_;\n    if ($port_type eq 'W32') {\n        return (2, \"process_begin: CreateProcess(NULL, $cmd$args, ...) failed.\\nmake (e=2): The system cannot find the file specified.\");\n    }\n\n    if (!$err) { $err = $ERR_no_such_file; }\n    return (127, \"#MAKE#: $cmd: $err\");\n}\n\n# TEST #3\n# -------\n\n# Try failing due to unknown command\nmy $unk = './foobarbazbozblat';\nunlink($unk);\n\nmy ($ernum, $erstr) = errors_getinfo($unk, \" xx yy\");\nrun_make_test(qq!\none: ; -$unk xx yy\n!, 'one',\n              \"$unk xx yy\\n$erstr\\n#MAKE#: [#MAKEFILE#:2: one] Error $ernum (ignored)\\n\");\n\n# TEST #4\n# -------\n\n($ernum, $erstr) = errors_getinfo($unk, \" aa bb\");\nrun_make_test(qq!\ntwo: ; $unk aa bb\n!, 'two -i',\n              \"$unk aa bb\\n$erstr\\n#MAKE#: [#MAKEFILE#:2: two] Error $ernum (ignored)\\n\");\n\n# TEST #5\n# -------\n\nrun_make_test(undef, 'two',\n              \"$unk aa bb\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:2: two] Error $ernum\\n\", 512);\n\n# SV #56918 : Test the unknown command as the second recipe line\n\n($ernum, $erstr) = errors_getinfo($unk, \" qq rr\");\nrun_make_test(qq!\nthree:\n\\t\\@echo one\n\\t$unk qq rr\n!, 'three',\n              \"one\\n$unk qq rr\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:4: three] Error $ernum\\n\", 512);\n\n# Try failing due to non-executable file\n\nif ($ERR_nonexe_file) {\n    my $noexe = './barfooblatboz';\n    touch($noexe);\n\n    run_make_test(qq!\n    one: ; -$noexe xx yy\n    two: ; $noexe aa bb\n    !,\n                  'one', \"$noexe xx yy\\n#MAKE#: $noexe: $ERR_nonexe_file\\n#MAKE#: [#MAKEFILE#:2: one] Error 127 (ignored)\\n\");\n\n    unlink($noexe);\n}\n\n# Try failing by \"running\" a directory\n\nif ($ERR_exe_dir) {\n    mkdir('sd', 0775) or print \"mkdir: sd: $!\\n\";\n\n    ($ernum, $erstr) = errors_getinfo('sd', '', $ERR_exe_dir);\n\n    run_make_test(q!\nPATH := .\nall: ; sd\n!,\n              '', \"sd\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum\", 512);\n\n    if ($port_type eq 'W32') {\n        $ernum = 5;\n        $erstr = \"process_begin: CreateProcess(NULL, ./sd, ...) failed.\\nmake (e=5): Access is denied.\";\n    } else {\n        $ernum = 127;\n        $erstr = \"#MAKE#: ./sd: $ERR_exe_dir\";\n    }\n\n    run_make_test(q!\nall: ; ./sd\n!,\n              '', \"./sd\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:2: all] Error $ernum\", 512);\n\n    rmdir('sd');\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/escape",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test various types of escaping in makefiles.\";\n\n$details = \"\\\nMake sure that escaping of ':' works in target names.\nMake sure escaping of whitespace works in target names.\nMake sure that escaping of '#' works.\nMake sure that backslash before non-special characters are kept.\";\n\n\n# TEST 1\n\nrun_make_test(q!\nifdef NOESC\npath = pre:\nendif\nifdef ONEESC\npath = pre\\:\nendif\nifdef TWOESC\npath = pre\\\\\\\\:\nendif\n\n$(path)foo : ; @echo \"touch ($@)\"\n\nfoo\\ bar: ; @echo \"touch ($@)\"\n\nsharp: foo\\#bar.ext\nfoo\\#bar.ext: ; @echo \"foo#bar.ext = ($@)\"\n!,\n              '',\n              'touch (foo)');\n\n# TEST 2: This one should fail, since the \":\" is unquoted.\n\nrun_make_test(undef,\n              'NOESC=1',\n              \"#MAKEFILE#:12: *** target pattern contains no '%'.  Stop.\",\n              512);\n\n# TEST 3: This one should work, since we escape the \":\".\n\nrun_make_test(undef,\n              'ONEESC=1',\n              'touch (pre:foo)');\n\n# TEST 4: This one should fail, since the escape char is escaped.\n\nrun_make_test(undef,\n              'TWOESC=1',\n              \"#MAKEFILE#:12: *** target pattern contains no '%'.  Stop.\",\n              512);\n\n# TEST 5: This one should work\n\nrun_make_test(undef,\n              ['foo bar'],\n              'touch (foo bar)');\n\n# TEST 6: Test escaped comments\n\nrun_make_test(undef,\n              'sharp',\n              'foo#bar.ext = (foo#bar.ext)');\n\n# Test escaped colons in prerequisites\n# Quoting of backslashes in q!! is kind of messy.\n# Solaris sh does not properly handle backslashes even in '' so just\n# check the output make prints, not what the shell interprets.\nrun_make_test(q!\nfoo: foo\\\\:bar foo\\\\\\\\\\\\:bar foo\\\\\\\\\\\\\\\\\\\\:bar\nfoo foo\\\\:bar foo\\\\\\\\\\\\:bar foo\\\\\\\\\\\\\\\\\\\\:bar: ; : '$@'\n!,\n              '', \": 'foo:bar'\\n: 'foo\\\\:bar'\\n: 'foo\\\\\\\\:bar'\\n: 'foo'\\n\");\n\n# Test backslash before non-special chars: should be kept as-is\n\nrun_make_test(q!\nall: ..\\foo\n.DEFAULT: ; : '$@'\n!,\n              '', \": '..\\\\foo'\\n\");\n\n# Test escaped comments in variable assignments\nrun_make_test(q!\nself = $1\nfoo := $(call self,#foo#)#foo\nbar := $(call self,\\#bar\\#)#bar\nall:;@echo '$(foo) $(bar)'\n!,\n               '',\"#foo# \\\\#bar\\\\#\");\n\n# Test escaped comments in variable assignments in a variable\nrun_make_test(q!\nC = \\#\nself = $1\nfoo := $(call self,$Cfoo$C)#foo\nall:;@echo '$(foo)'\n!,\n               '',\"#foo#\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/exec",
    "content": "#                                                                    -*-perl-*-\n\nuse warnings;\n\nmy $description = \"Test that make can execute binaries as well as scripts with\"\n                 .\" various shabangs and without a shbang\";\nmy $details = \"The various shells that this test uses are the default\"\n             .\" /bin/sh, \\$SHELL and the perl interpreter that is\"\n             .\" executing this test program. The shells are used for the value\"\n             .\" of SHELL inside the test makefile and also as a shbang in the\"\n             .\" executed script. There is also a test which executes a script\"\n             .\" that has no shbang.\";\n\n# Only bother with this on UNIX systems\n$port_type eq 'UNIX' or return -1;\n$^O =~ /cygwin/ and return -1;\n\nmy @shbangs = ('#!/bin/sh', \"#!$perl_name\");\n\n# The exec in Valgrind's VM doesn't allow starting commands without any shbang\n$valgrind or push @shbangs, '';\n\nmy @shells = ('', 'SHELL=/bin/sh');\n\n# Try whatever shell the user has, as long as it's not a C shell.\n# The C shell is not usable with make, due to not correctly handling\n# file descriptors and possibly other issues.\nmy $usersh = $origENV{SHELL};\nif ($usersh !~ /csh/) {\n    push @shbangs, (\"#!$usersh\");\n    push @shells, (\"SHELL=$usersh\");\n}\n\nmy $answer = 'hello, world';\n\n# tests [0-11]\n# Have a makefile with various SHELL= exec a shell program with varios\n# shbangs or without a shbang at all.\nmy $stem = './exec.cmd';\nmy $k = 0;\nfor my $shbang (@shbangs) {\n    for my $shell (@shells) {\n        my $cmd = $k ? \"$stem.$k\" : $stem;\n        ++$k;\n        unlink $cmd;\n        open(CMD,\"> $cmd\");\n        print CMD \"$shbang\\n\";\n        print CMD \"printf \\\"$answer\\\\n\\\";\\n\";\n        close(CMD);\n        chmod 0700, $cmd;\n\n        run_make_test(\"# shbang=$shbang\\n# shell=$shell\" . q!\nall:; @$(CMD)\n!, \"$shell CMD=$cmd\", \"$answer\\n\");\n\n        rmfiles($cmd);\n    }\n}\n\n# tests [12-14]\n# Exec a binary from a makefile that has SHELL=.\nfor my $shell (@shells) {\n    run_make_test(q!\nall:; @#PERL# -e 'printf \"$(ANSWER)\\n\"';\n!, \"$shell ANSWER='$answer'\", \"$answer\\n\");\n}\n\n# test 15\n# Use perl as a shell.\nrun_make_test(q!\nSHELL = #PERL#\n.SHELLFLAGS = -e\nall:; @printf \"$(ANSWER)\\n\";\n!, \"ANSWER='$answer'\", \"$answer\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/expand",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test variable expansion.\";\n\n# sv 64124.\n# Expand a variable whose value exceeds 200 bytes.\n# 200 is the initial size of variable_buffer.\n# Value bigger than 200 bytes causes a realloc of variable_buffer.\n# In this test the variable being expanded is MAKEFLAGS and its value occupies\n# 12, 600 and 120000 bytes.\n\nmy $s = \"hello_world\\n\";\nmy @mult = (1, 50, 10000);\n\nfor my $m (@mult) {\n    my $answer = $s x $m;\n    $ENV{'MAKEFLAGS'} = \" -- hello=$answer\";\n    run_make_test(q!\n$(info x$(hello)y)\nall:\n!,\n              '', \"x${answer}y\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n}\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/export",
    "content": "#                                                                    -*-perl-*-\n$description = \"Check GNU Make export/unexport commands.\";\n\n$details = \"\";\n\n# The test driver cleans out our environment for us so we don't have to worry\n# about that here.\n\n&run_make_test('\nFOO = foo\nBAR = bar\nBOZ = boz\n\nexport BAZ = baz\nexport BOZ\n\nBITZ = bitz\nBOTZ = botz\n\nexport BITZ BOTZ\nunexport BOTZ\n\nifdef EXPORT_ALL\nexport\nendif\n\nifdef UNEXPORT_ALL\nunexport\nendif\n\nifdef EXPORT_ALL_PSEUDO\n.EXPORT_ALL_VARIABLES:\nendif\n\n.RECIPEPREFIX := >\nall:\n> @echo \"FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)\"\n> @echo \"FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ\"\n',\n           '', \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 1: make sure vars inherited from the parent are exported\n\n$ENV{FOO} = 1;\n\n&run_make_test(undef, '', \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 2: global export.  Explicit unexport takes precedence.\n\nrun_make_test(undef, \"EXPORT_ALL=1\" ,\n              \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 3: global unexport.  Explicit export takes precedence.\n\n&run_make_test(undef, \"UNEXPORT_ALL=1\",\n               \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 4: both: in the above makefile the unexport comes last so that rules.\n\n&run_make_test(undef, \"EXPORT_ALL=1 UNEXPORT_ALL=1\",\n               \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 5: test the pseudo target.\n\n&run_make_test(undef, \"EXPORT_ALL_PSEUDO=1\",\n               \"FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz\nFOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\\n\");\n\n# TEST 6: Test the expansion of variables inside export\n\n&run_make_test('\nfoo = f-ok\nbar = b-ok\n\nFOO = foo\nF = f\n\nBAR = bar\nB = b\n\nexport $(FOO)\nexport $(B)ar\n\n.RECIPEPREFIX := >\nall:\n> @echo foo=$(foo) bar=$(bar)\n> @echo foo=$$foo bar=$$bar\n',\n             \"\", \"foo=f-ok bar=b-ok\\nfoo=f-ok bar=b-ok\\n\");\n\n# TEST 7: Test the expansion of variables inside unexport\n\n&run_make_test('\nfoo = f-ok\nbar = b-ok\n\nFOO = foo\nF = f\n\nBAR = bar\nB = b\n\nexport foo bar\n\nunexport $(FOO)\nunexport $(B)ar\n\n.RECIPEPREFIX := >\nall:\n> @echo foo=$(foo) bar=$(bar)\n> @echo foo=$$foo bar=$$bar\n',\n              '', \"foo=f-ok bar=b-ok\\nfoo= bar=\\n\");\n\n# TEST 7: Test exporting multiple variables on the same line\n\n&run_make_test('\nA = a\nB = b\nC = c\nD = d\nE = e\nF = f\nG = g\nH = h\nI = i\nJ = j\n\nSOME = A B C\n\nexport F G H I J\n\nexport D E $(SOME)\n\nall: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J\n',\n               '', \"A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\\n\");\n\n# TEST 8: Test unexporting multiple variables on the same line\n\n@args{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);\n%ENV = (%ENV, %args);\n\n&run_make_test('\nA = a\nB = b\nC = c\nD = d\nE = e\nF = f\nG = g\nH = h\nI = i\nJ = j\n\nSOME = A B C\n\nunexport F G H I J\n\nunexport D E $(SOME)\n\nall: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J\n',\n               '', \"A= B= C= D= E= F= G= H= I= J=\\n\");\n\n# TEST 9: Check setting a variable named \"export\"\n\n&run_make_test('\nexport = 123\nexport export\nexport export = 456\na: ; @echo \"\\$$(export)=$(export) / \\$$export=$$export\"\n',\n               '', \"\\$(export)=456 / \\$export=456\\n\");\n\n# TEST 10: Check \"export\" as a target\n\n&run_make_test('\na: export\nexport: ; @echo \"$@\"\n',\n               '', \"export\\n\");\n\n# Check export and assignment of a variable on the same line\n\n$ENV{hello} = 'moon';\n\nrun_make_test(q!\nall: ; @echo hello=$(hello) hello=$$hello\nexport hello=sun\n!,\n              '', \"hello=sun hello=sun\\n\");\n\n# Check unexport and assignment of a variable on the same line\n\n$ENV{hello} = 'moon';\n\nrun_make_test(q!\nall: ; @echo hello=$(hello) hello=$$hello\nunexport hello=sun\n!,\n              '', \"hello=sun hello=\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/grouped_targets",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"This test is about grouped multiple targets indicated by &:\";\n$details = \"Here we test for requirements like\\n\"\n          .\"- if multiple such targets are updated, the recipe is run once\\n\"\n          .\"- parsing issues related to the &: syntax itself\\n\";\n\n# Parsing: &: allowed without any targets.\nrun_make_test(q{\n.PHONY: all\n&:;\nall: ;@printf ''\n},\n'', \"\");\n\n# Parsing: &: works not preceded by whitespace.\nrun_make_test(q{\nfoo&:;@echo foo\n},\n'foo', \"foo\");\n\n# Ordinary rule runs recipe four times for t1 t2 t3 t4.\n# Grouped target rule runs recipe once; others are considered updated.\nrun_make_test(q{\n.PHONY: t1 t2 t3 t4 g1 g2 g3 g4\nt1 t2 t3 t4: ; @echo $@\ng1 g2 g3 g4 &: ; @echo $@\n},\n't1 t2 t3 t4 g1 g2 g3 g4',\n\"t1\\n\"\n.\"t2\\n\"\n.\"t3\\n\"\n.\"t4\\n\"\n.\"g1\\n\"\n.\"#MAKE#: Nothing to be done for 'g2'.\\n\"\n.\"#MAKE#: Nothing to be done for 'g3'.\\n\"\n.\"#MAKE#: Nothing to be done for 'g4'.\");\n\n# Similar to previous test, but targets come from m1 phony\n# rather than from the command line. We don't see \"Nothing to\n# be done for\" messages. Also, note reversed order g4 g3 ...\n# Thus the auto variable $@ is \"g4\" when that rule fires.\nrun_make_test(q{\n.PHONY: m1 t1 t2 t3 t4 g1 g2 g3 g4\nm1: t1 t2 t3 t4 g4 g3 g2 g1\nt1 t2 t3 t4: ; @echo $@\ng1 g2 g3 g4&: ; @echo $@\n},\n'',\n\"t1\\nt2\\nt3\\nt4\\ng4\");\n\n# Set a grouped target recipe for existing targets\nrun_make_test(q{\n.PHONY: M a b\nM: a b\na:\na b&: ; @echo Y\nb:\n},\n'',\n\"Y\");\n\n# grouped targets require a recipe\nrun_make_test(q{\n.PHONY: M a b\nM: a b\na b&:\n},\n'',\n\"#MAKEFILE#:4: *** grouped targets must provide a recipe.  Stop.\", 512);\n\n# Pattern rules use grouped targets anyway so it's a no-op\nrun_make_test(q{\n.PHONY: M\nM: a.q b.q\na.% b.%&: ; @echo Y\n},\n'',\n\"Y\");\n\n# Double-colon grouped target rules.\nrun_make_test(q{\n.PHONY: M a b c d e f g h\nM: a b\na b c&:: ; @echo X\nc d e&:: ; @echo Y\nf g h&:: ; @echo Z\n},\n'',\n\"X\");\n\nrun_make_test(q{\n.PHONY: M a b c d e f g h\nM: c\na b c&:: ; @echo X\nc d e&:: ; @echo Y\nf g h&:: ; @echo Z\n},\n'',\n\"X\\nY\");\n\nrun_make_test(q{\n.PHONY: M a b c d e f g h\nM: a b c d e\na b c&:: ; @echo X\nc d e&:: ; @echo Y\nf g h&:: ; @echo Z\n},\n'',\n\"X\\nY\");\n\nrun_make_test(q{\n.PHONY: M a b c d e f g h\nM: d e\na b c&:: ; @echo X\nc d e&:: ; @echo Y\nf g h&:: ; @echo Z\n},\n'',\n\"Y\");\n\nrun_make_test(q{\n.PHONY: M a b c d e f g h\nM: f g h\na b c&:: ; @echo X\nc d e&:: ; @echo Y\nf g h&:: ; @echo Z\n},\n'',\n\"Z\");\n\n# sv 60188.\n# Test that a file explicitly mentioned by the user and made by an implicit\n# rule is not considered intermediate.\n\ntouch('hello.z');\ntouch('hello.q');\n\n# subtest 1\n# hello.x is not explicitly mentioned and thus is an intermediate file.\nrun_make_test(q!\nall: hello.z\n%.z %.q: %.x ; touch $*.z $*.q\n%.x: ;\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# subtest 2\n# test.x is explicitly mentioned and thus is not an intermediate file.\nrun_make_test(q!\nall: hello.z\n%.z %.q: %.x test.x ; @echo $*.z $*.q\n%.x: ;\n!, '', \"hello.z hello.q\\n\");\n\n# subtest 3\n# hello.x is explicitly mentioned on an unrelated rule and thus is not an\n# intermediate file.\nrun_make_test(q!\nall: hello.z\n%.z %.q: %.x; @echo $*.z $*.q\n%.x: ;\nunrelated: hello.x\n!, '', \"hello.z hello.q\\n\");\n\nunlink('hello.z');\nunlink('hello.q');\n\n# SV 62809: Missing grouped target peer causes remake regardless of which\n# target caused the rule to run.\ntouch(qw(gta));  # but not gtb\nrun_make_test(q!\ngta gtb &: ; touch gta gtb\n!,\n              'gta', \"touch gta gtb\\n\");\nunlink(qw(gta gtb));\n\n# Ensure both goal targets are built if they depend on a grouped prereq\ntouch(qw(gta));  # but not gtb\nrun_make_test(q!\nx1 x2: ; touch $@\n\nx1: gta\nx2: gtb\n\ngta gtb &: ; touch gta gtb\n!,\n              'x1 x2', \"touch gta gtb\\ntouch x1\\ntouch x2\\n\");\n\n# Now everything should be up to date\nrun_make_test(undef, 'x1 x2',\n              \"#MAKE#: 'x1' is up to date.\\n#MAKE#: 'x2' is up to date.\");\n\nunlink(qw(x1 x2 gta gtb));\n\n# If an also-make file is older than a prerequisite build both\n\nutouch(-20, 'gtb');\nutouch(-10, 'pre');\ntouch(qw(gta));\nrun_make_test(q!\ngta gtb &: pre ; touch gta gtb\n!,\n              'gta', \"touch gta gtb\\n\");\nunlink(qw(pre gta gtb));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/implicit_search",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test implicit rule search.\";\n\n$details = \"\";\n\n# sv 48643\n# Each test has a %.c rule ahead of %.f rule.\n# hello.f exists and hello.c is missing.\n\nunlink('hello.c', 'hello.tsk', 'hello.o', 'hello.x');\n\n# Run every test with and without a suffix.\nmy @suffixes = ('', '.o');\n# Run every test with single and double colon rules.\nmy @rules = ('', ':');\n\nfor my $s (@suffixes) {\nfor my $r (@rules) {\ntouch('hello.f');\n\n# Test that make finds the intended implicit rule based on existence of a\n# prerequisite in the filesystem.\n#\n# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r', \"hello.f\\n#MAKE#: Nothing to be done for 'all'.\");\n\n# Test that make finds the intended implicit rule based on the explicit\n# prerequisite of the top goal and despite the existence of a\n# prerequisite in the filesystem.\n#\n# hello.c is an explicit prerequisite of the top target (hello.o or hello).\n# hello.c ought to exist.\n# hello.c prerequisite causes '%.o: %.c' rule to be chosen.\nrun_make_test(\"\nhello$s: hello.c\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r',\n\"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'.  Stop.\\n\",\n512);\n\n# Test that make finds the intended implicit rule when the implicit\n# prerequisite matches a target of an unrelated rule and despite the existence\n# of a prerequisite of the other rule candidate in the filesystem.\n#\n# hello.c matches 'hello.c:' rule. This makes hello.c a target and thus ought\n# to exist.\n# hello.c prerequisite causes '%.o: %.c' rule to be chosen.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\nhello.c:; @#HELPER# fail 1\n\", '-r', \"fail 1\\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\\n\", 512);\n\n# Test that make finds the intended implicit rule based on existence of a\n# prerequisite in the filesystem, even when the prerequisite of another\n# candidate rule is mentioned explicitly on an unrelated rule.\n#\n# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen, even though hello.c\n# is mentioned explicitly on 'unrelated: hello.c'.\n# ought-to-exist does not apply to hello.c.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\nunrelated: hello.c\n\", '-r', \"hello.f\\n#MAKE#: Nothing to be done for 'all'.\");\n\n# Test that make finds the intended implicit rule based on existence of a\n# prerequisite in the filesystem.\n#\n# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.\n# Despite '%.o: %.c hello.c' rule having explicit prerequisite hello.c.\n# ought-to-exist does not apply to hello.c.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c hello.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r', \"hello.f\\n#MAKE#: Nothing to be done for 'all'.\");\n\n# '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen.\n# '%.o: %.f hello.f' rule has explicit prerequisite hello.f.\n# ought-to-exist does not apply to hello.c.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f hello.f; \\$(info hello.f)\n\", '-r', \"hello.f\\n#MAKE#: Nothing to be done for 'all'.\");\n\n# Rule '%: %.f' is chosen, because '%: %.f' requires no intermediates.\n# '%: %.c', on the other hand, requires intemediate hello.c to be built by the\n# default rule.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info \\$<)\n%$s:$r %.f; \\$(info \\$<)\n.DEFAULT:; \\$(info \\$\\@) true\nunrelated: hello.c\n\", '-r', \"hello.f\\n#MAKE#: Nothing to be done for 'all'.\");\n\n\n# hello.f is missing.\n# This time both hello.c and hello.f are missing and both '%: %.c' and '%: %.f'\n# require an intermediate.\n# The default rule builds intemerdiate hello.c.\n# '%: %.c' rule is chosen to build hello.\nunlink('hello.f');\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info \\$<)\n%$s:$r %.f; \\$(info \\$<)\n.DEFAULT:; \\@\\$(info \\$\\@) #HELPER# fail 1\nunrelated: hello.c\n\", '-r', \"hello.c\\nfail 1\\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\\n\", 512);\n\n# hello.f is missing.\n# No rule is found, because hello.c is not mentioned explicitly.\nrun_make_test(\"\nall: hello$s\n%$s:$r %.c; \\$(info \\$<)\n%$s:$r %.f; \\$(info \\$<)\n.DEFAULT:; \\@\\$(info \\$\\@) #HELPER# fail 1\n\", '-r', \"hello$s\\nfail 1\\n#MAKE#: *** [#MAKEFILE#:5: hello$s] Error 1\\n\", 512);\n\n}\n}\n\n# Almost the same tests as above, but this time an intermediate is built.\n\ntouch('hello.f');\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nmy $result = \"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'.  Stop.\\n\";\nmy $rcode = 512;\nif ($s or $r) {\n    $result = \"hello.f\\nhello.tsk\\n#MAKE#: Nothing to be done for 'all'.\";\n    $rcode = 0;\n}\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r', \"$result\", $rcode);\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s hello$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r', $result, $rcode);\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c hello$s; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r', $result, $rcode);\n\n}\n}\n\nfor my $r (@rules) {\n\n# Circular dependency hello.o <- hello.tsk is dropped.\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %.o; \\$(info hello.tsk)\n%.o:$r %.c; \\$(info hello.c)\n%.o:$r %.f %.tsk; \\$(info hello.f)\n\", '-r',\n\"#MAKE#: circular hello.o <- hello.tsk dependency dropped\\nhello.f\\nhello.tsk\\n#MAKE#: Nothing to be done for 'all'.\");\n\n}\n\n\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nrun_make_test(\"\nall: hello.tsk\nhello$s: hello.c\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\n\", '-r',\n\"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'.  Stop.\\n\",\n512);\n}\n}\n\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nmy $result = \"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'.  Stop.\\n\";\nif ($s or $r) {\n    $result = \"fail 1\\n#MAKE#: *** [#MAKEFILE#:6: hello.c] Error 1\\n\";\n}\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\nhello.c:; @#HELPER# fail 1\n\", '-r', $result, 512);\n}\n}\n\n\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\nunrelated: hello$s\n\", '-r', \"hello.f\\nhello.tsk\\n#MAKE#: Nothing to be done for 'all'.\");\n}\n}\n\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nmy $result = \"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'.  Stop.\\n\";\nmy $rcode = 512;\nif ($s or $r) {\n    $result = \"hello.f\\nhello.tsk\\n#MAKE#: Nothing to be done for 'all'.\";\n    $rcode = 0;\n}\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c; \\$(info hello.c)\n%$s:$r %.f hello.f; \\$(info hello.f)\n\", '-r', $result, $rcode);\n}\n}\n\n# One of the implicit rules has two prerequisites, hello.c and hello.x\n# hello.c does not qualify as ought to exit.\n# hello.x can be made from hello.z.\n# This test exercises the break, which prevents making hello.x as an\n# intermediate from hello.z during compatibility search.\nunlink('hello.f');\ntouch('hello.z');\nfor my $s (@suffixes) {\nfor my $r (@rules) {\n\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %$s; \\$(info hello.tsk)\n%$s:$r %.c %.x; \\$(info hello.c)\n%$s:$r %.f; \\$(info hello.f)\nunrelated: hello$s\n%.x:$r %.z; \\$(info hello.z)\n\", '-r',\n\"#MAKE#: *** No rule to make target 'hello$s', needed by 'hello.tsk'.  Stop.\\n\",\n512);\n}\n}\n\n# Test that prerequisite 'hello.x' mentioned explicitly on an unrelated rule is\n# not considered intermediate.\ntouch('hello.tsk');\nunlink('hello.x');\nrun_make_test(\"\nall: hello.tsk\n%.tsk: %.x; touch hello.tsk\n%.x: ;\nunrelated: hello.x\n\", '-r', \"touch hello.tsk\\n\");\nunlink('hello.tsk');\n\ntouch ('hello.f');\n# Test implicit search of builtin rules.\n\n# %: %.c (and other builtin rules) are skipped.\n# %: %.f is chosen.\nrun_make_test(q!\nall: hello\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=', \"f77 hello.f -o hello\\n\");\n\n# %.o: %.c (and other builtin rules) are skipped.\n# %.o: %.f is chosen.\nrun_make_test(q!\nall: hello.o\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=', \"f77 -c hello.f\\n\");\n\n\n# %: %.c is chosen.\n# hello.c is an explicit prerequisite of the top target hello.\n# hello.c ought to exist.\n# hello.c prerequisite causes '%: %.c' rule to be chosen.\nrun_make_test(q!\nhello: hello.c\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=',\n\"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello'.  Stop.\\n\",\n512);\n\n# %.o: %.c is chosen.\n# hello.c is an explicit prerequisite of the top target hello.o.\n# hello.c ought to exist.\n# hello.c prerequisite causes '%.o: %.c' rule to be chosen.\nrun_make_test(q!\nhello.o: hello.c\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=',\n\"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'.  Stop.\\n\",\n512);\n\n# %: %.c (and other builtin rules) are skipped.\n# %: %.f is chosen.\n# ought-to-exist does not apply to hello.c.\nrun_make_test(q!\nall: hello\nunrelated: hello.c\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=', \"f77 hello.f -o hello\\n\");\n\n# %.o: %.c (and other builtin rules) are skipped.\n# %.o: %.f is chosen.\n# ought-to-exist does not apply to hello.c.\nrun_make_test(q!\nall: hello.o\nunrelated: hello.c\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=', \"f77 -c hello.f\\n\");\n\n# builtin rule %.o: %.f is removed.\n# %.o: %.c (and other builtin rules) are skipped, because hello.c is missing.\n# ought-to-exist does not apply to hello.c.\n# %.o: %.c is chosen as a compatibility rule, because of hello.c.\nrun_make_test(q!\nall: hello.o\nunrelated: hello.c\n%.o: %.f\n!, '',\n\"#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'.  Stop.\\n\",\n512);\n\n\n# sv 17752.\n# In this test the builtin match-anything rule '%: %.f' is used to build\n# intermediate hello from hello.f, because hello is mentioned explicitly in\n# the makefile.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %; $(info $@ from $<)\nunrelated: hello\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=',\n\"f77 hello.f -o hello\\nhello.tsk from hello\\n\");\n\n# In this test the builtin match-anything rule %: %.f cannot be used to build\n# intermediate hello from hello.f, because hello is not mentioned explicitly in\n# the makefile.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %; $(info $@ from $<)\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=',\n\"#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'.  Stop.\\n\",\n512);\n\n# This is just like the one above, but compatibility rule '%.tsk: % %.x' has 2\n# prerequisites, '%' and '%.x'.\n# '%' expands to 'hello' and matches the explicit 'hello' on the unrelated rule.\n# '%.x' is an intermediate built from 'hello.xx' by rule '%.x: %.xx' during the\n# second pass (intermed_ok == 1) of compatibility search.\n# This test validates that compatibility search performs both intermed_ok == 0\n# and intermed_ok == 1 passes.\nunlink('hello.x');\ntouch('hello.xx');\nrun_make_test(q!\nall: hello.tsk\n%.tsk: % %.x; $(info $@ from $^)\nunrelated: hello\n%.x: %.xx; $(info $@ from $<)\n!, 'FC=\"@echo f77\" OUTPUT_OPTION=',\n\"f77 hello.f -o hello\\nhello.x from hello.xx\\nhello.tsk from hello hello.x\\n\");\n\nunlink('bye.o', 'bye.tsk', 'bye.x');\n# sv 21670.\n# Default recipe is used to build bye.o.\nrun_make_test(q!\nall: bye.tsk\n%.tsk: %.o; $(info $@ from $<)\n.DEFAULT:; $(info bye.o)\nunrelated: bye.o\n!, '-r', \"bye.o\\nbye.tsk from bye.o\\n#MAKE#: Nothing to be done for 'all'.\");\n\ntouch('bye.xx');\n# This is just like the one above, but compatibility rule '%.tsk: %.o %.x' has 2\n# prerequisites, '%.o' and '%.x'.\n# '%.o' expands to 'bye.o' and matches the explicit 'bye.o' on the unrelated rule.\n# '%.x' is an intermediate built from 'bye.xx' by rule '%.x: %.xx' during the\n# second pass (intermed_ok == 1) of compatibility search.\n# This test validates that compatibility search performs both intermed_ok == 0\n# and intermed_ok == 1 passes.\nrun_make_test(q!\nall: bye.tsk\n%.tsk: %.o %.x; $(info $@ from $^)\n.DEFAULT:; $(info bye.o)\nunrelated: bye.o\n%.x: %.xx; $(info $@ from $<)\n!, '-r',\n\"bye.o\\nbye.x from bye.xx\\nbye.tsk from bye.o bye.x\\n#MAKE#: Nothing to be done for 'all'.\");\n\nunlink('hello.f', 'hello.z', 'hello.xx', 'bye.xx');\n\n\n# A target specific variable causes the file to be entered to the database as a\n# prerequisite. Implicit search then treats this file as explicitly mentioned.\n# Test that implicit search keeps target specific variables of this file intact.\n# In this series of tests prerequisite 'hello.x' has a target specific variable\n# and is built as an intermediate. Implicit search treats 'hello.x' as\n# explicitly mentioned, but 'hello.x' does not qualify as ought-to-exist.\nunlink('hello.x', 'hello.tsk');\n\n# 'hello.x' is mentioned explicitly on the same implicit rule.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: hello.x; $(info $@)\n%.x:; $(flags)\nhello.x: flags:=true\n!, '-r', \"true\\nhello.tsk\\n\");\n\n# Similar to the one above, but this time 'hello.x' is derived from the stem.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.x; $(info $@)\n%.x:; $(flags)\nhello.x: flags:=true\n!, '-r', \"true\\nhello.tsk\\n\");\n\n# Similar to the one above, this time 'hello.x' is also mentioned explicitly on\n# an unrelated rule.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.x; $(info $@)\n%.x:; $(flags)\nhello.x: flags:=true\nunrelated: hello.x\n!, '-r', \"true\\nhello.tsk\\n\");\n\n# 'hello.x' has a pattern specific variable.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.x; $(info $@)\n%.x:; $(flags)\n%.x: flags:=true\n!, '-r', \"true\\nhello.tsk\\n\");\n\n# 'hello.x' has a target specific variable and a pattern specific variable.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.x; $(info $@)\n%.x:; $(flags)\nhello.x: flags+=good\n%.x: flags:=true\n!, '-r', \"true good\\nhello.tsk\\n\");\n\n# Intermediate prerequisite 'hello.x' has a target specific variable, a pattern\n# specific variable, matches on both rules '%.tsk: %.x' and 'big_%.tsk: %.x'.\nrun_make_test(q!\nall: hello.tsk big_hello.tsk\n%.tsk: %.x; $(info $@)\nbig_%.tsk: %.x; $(info $@)\n%.x:; $(flags)\nhello.x: flags+=good\n%.x: flags:=true\n!, '-r', \"true good\\nhello.tsk\\nbig_hello.tsk\\n\");\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/include",
    "content": "#                                                              -*-mode: perl-*-\n\n$description = \"Test various forms of the GNU Make 'include' command.\";\n\n$details = \"\\\nTest include, -include, sinclude and various regressions involving them.\nTest extra whitespace at the end of the include, multiple -includes and\nsincludes (should not give an error) and make sure that errors are reported\nfor targets that were also -included.\";\n\ncreate_file('incl.mk', \"ANOTHER: ; \\@echo This is another included makefile\\n\");\n\nrun_make_test(qq!#Extra space at the end of the following file name\ninclude incl.mk    ! . q!\nall: ; @echo There should be no errors for this makefile.\n\n-include nonexistent.mk\n-include nonexistent.mk\nsinclude nonexistent.mk\nsinclude nonexistent-2.mk\n-include makeit.mk\nsinclude makeit.mk\n\nerror: makeit.mk\n!,\n              \"all\", \"There should be no errors for this makefile.\\n\");\n\nrun_make_test(undef, \"ANOTHER\", \"This is another included makefile\\n\");\n\nunlink('incl.mk');\n\n# Try to build the \"error\" target; this will fail since we don't know\n# how to create makeit.mk, but we should also get a message (even though\n# the -include suppressed it during the makefile read phase, we should\n# see one during the makefile run phase).\n\nrun_make_test\n  ('\n-include foo.mk\nerror: foo.mk ; @echo $@\n',\n   '',\n   \"#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'.  Stop.\\n\",\n   512\n  );\n\n# The same as above with an additional include directory.\n\nmkdir('hellod', 0777);\n\nrun_make_test\n  ('\n-include foo.mk\nerror: foo.mk ; @echo $@\n',\n   '-Ihellod',\n   \"#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'.  Stop.\\n\",\n   512\n  );\n\nrmdir('hellod');\n\n# Make sure that target-specific variables don't impact things.  This could\n# happen because a file record is created when a target-specific variable is\n# set.\n\nrun_make_test\n  ('\nbar.mk: foo := baz\n-include bar.mk\nhello: ; @echo hello\n',\n   '',\n   \"hello\\n\"\n  );\n\n\n# Test inheritance of dontcare flag when rebuilding makefiles.\n#\nrun_make_test('\n.PHONY: all\nall: ; @:\n\n-include foo\n\nfoo: bar; @:\n', '', '');\n\n\n# Make sure that we don't die when the command fails but we dontcare.\n# (Savannah bug #13216).\n#\nrun_make_test('\n.PHONY: all\nall:; @:\n\n-include foo\n\nfoo: bar; @:\n\nbar:; @exit 1\n', '', '');\n\n# Check include, sinclude, -include with no filenames.\n# (Savannah bug #1761).\n\nrun_make_test('\n.PHONY: all\nall:; @:\ninclude\n-include\nsinclude', '', '');\n\n\n# Test that the diagnostics is issued even if the target has been\n# tried before with the dontcare flag (direct dependency case).\n#\nrun_make_test('\n-include foo\n\nall: bar\n\nfoo: baz\nbar: baz\n',\n'',\n\"#MAKE#: *** No rule to make target 'baz', needed by 'bar'.  Stop.\\n\",\n512);\n\n# Test that the diagnostics is issued even if the target has been\n# tried before with the dontcare flag (indirect dependency case).\n#\nrun_make_test('\n-include foo\n\nall: bar\n\nfoo: baz\nbar: baz\nbaz: end\n',\n'',\n\"#MAKE#: *** No rule to make target 'end', needed by 'baz'.  Stop.\\n\",\n512);\n\n# Test include of make-able file doesn't show an error (Savannah #102)\nrun_make_test(q!\n.PHONY: default\ndefault:; @echo DONE\n\ninc1:; echo > $@\ninclude inc1\ninclude inc2\ninc2:; echo > $@\n!,\n              '', \"echo > inc1\\necho > inc2\\nDONE\\n\");\n\nrmfiles('inc1', 'inc2');\n\n# Test include of make-able file doesn't show an error.\n# Specify an additional include directory.\n\nmkdir('hellod', 0777);\n\nrun_make_test(q!\n.PHONY: default\ndefault:; @echo DONE\n\ninc1:; echo > $@\ninclude inc1\ninclude inc2\ninc2:; echo > $@\n!,\n              '-Ihellod', \"echo > inc1\\necho > inc2\\nDONE\\n\");\n\nrmfiles('inc1', 'inc2');\n\n# Test include of make-able file doesn't show an error.\n# inc1 and inc2 are present in the specified include directory.\ntouch('hellod/inc1');\ntouch('hellod/inc2');\n\nrun_make_test(q!\n.PHONY: default\ndefault:; @echo DONE\n\ninc1:; echo > $@\ninclude inc1\ninclude inc2\ninc2:; echo > $@\n!,\n              '-Ihellod', \"DONE\\n\");\n\nrmfiles('inc1', 'inc2', 'hellod/inc1', 'hellod/inc2');\n\nrmdir('hellod');\n\n# No target gets correct error\nrun_make_test(\"\\n\", '', '#MAKE#: *** No targets.  Stop.', 512);\n\n# No target in included file either, still gets correct error.\ntouch('inc1.mk');\nrun_make_test('include inc1.mk', '', '#MAKE#: *** No targets.  Stop.', 512);\nrmfiles('inc1.mk');\n\n# Include same file multiple times\n\nrun_make_test(q!\ndefault:; @echo DEFAULT\ninclude inc1\ninc1:; echo > $@\ninclude inc1\n!,\n              '', \"echo > inc1\\nDEFAULT\\n\");\n\nrmfiles('inc1');\n\nif (defined $ERR_no_such_file) {\n\n    # Test that the diagnostics is issued even if the target has been\n    # tried before with the dontcare flag (include/-include case).\n    #\n    run_make_test('\ninclude bar\n-include foo\n\nall:\n\nfoo: baz\nbar: baz\nbaz: end\n',\n'',\n                  \"#MAKEFILE#:2: bar: $ERR_no_such_file\\n#MAKE#: *** No rule to make target 'end', needed by 'baz'.  Stop.\\n\",\n                  512);\n\n    # Test include of non-make-able file does show an error (Savannah #102)\n    run_make_test(q!\n.PHONY: default\ndefault:; @echo DONE\n\ninc1:; echo > $@\ninclude inc1\ninclude inc2\n!,\n                  '', \"echo > inc1\\n#MAKEFILE#:7: inc2: $ERR_no_such_file\\n#MAKE#: *** No rule to make target 'inc2'.  Stop.\\n\", 512);\n\n    rmfiles('inc1');\n\n    # Included file has a prerequisite that fails to build\n\n    run_make_test(q!\ndefault:; @echo DEFAULT\ninclude inc1\ninc1: foo; echo > $@\nfoo:; exit 1\n!,\n                  '', \"exit 1\\n#MAKEFILE#:3: inc1: $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:5: foo] Error 1\\n\", 512);\n\n    rmfiles('inc1');\n\n    # Included file has a prerequisite we don't know how to build\n\n    run_make_test(q!\ndefault:; @echo DEFAULT\ninclude inc1\ninc1: foo; echo > $@\n!,\n                  '', \"#MAKEFILE#:3: inc1: $ERR_no_such_file\\n#MAKE#: *** No rule to make target 'foo', needed by 'inc1'.  Stop.\\n\", 512);\n\n    rmfiles('inc1');\n\n    # Check that included double-colon targets with no prerequisites aren't\n    # built.  This should fail as hello.mk doesn't exist\n\n    run_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\ninclude hello.mk\nhello.mk:: ; echo 'FOO=bar' > $@\n!,\n                  '', \"#MAKEFILE#:4: hello.mk: $ERR_no_such_file\", 512);\n\n    # Check that included phony targets aren't built.\n    # This should fail as hello.mk doesn't exist\n\n    run_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\ninclude hello.mk\nhello.mk: ; echo 'FOO=bar' > $@\n.PHONY: hello.mk\n!,\n                  '', \"#MAKEFILE#:4: hello.mk: $ERR_no_such_file\", 512);\n}\n\nif (defined $ERR_unreadable_file) {\n    # Including files that can't be read should show an error\n    unlink('inc1');\n    create_file('inc1', 'FOO := foo');\n    chmod 0000, 'inc1';\n\n    run_make_test(q!\ninclude inc1\nall:;@echo $(FOO)\n!,\n                  '', \"#MAKEFILE#:2: inc1: $ERR_unreadable_file\\n#MAKE#: *** No rule to make target 'inc1'.  Stop.\", 512);\n\n    # Including files that can't be read should show an error, even when there\n    # is a readable file in a subsequent include directory.\n    mkdir('hellod', 0777);\n    touch(\"hellod/inc1\");\n\n    run_make_test(q!\ninclude inc1\nall:;@echo $(FOO)\n!,\n                  '-Ihellod', \"#MAKEFILE#:2: inc1: $ERR_unreadable_file\\n#MAKE#: *** No rule to make target 'inc1'.  Stop.\", 512);\n\n    # Unreadable files that we know how to successfully recreate should work\n\n    run_make_test(sprintf(q!\nall:;@echo $(FOO)\ninclude inc1\ninc1:; @%s $@ && echo FOO := bar > $@\n!, $CMD_rmfile),\n                  '', \"bar\");\n\n    # Unreadable files that we know how to successfully recreate should work.\n    # Even when there is a readable file in an additional include directory.\n\n    unlink('inc1');\n    create_file('inc1', 'FOO := foo');\n    chmod 0000, 'inc1';\n\n    run_make_test(sprintf(q!\nall:;@echo $(FOO)\ninclude inc1\ninc1:; @%s $@ && echo FOO := bar > $@\n!, $CMD_rmfile),\n                  '-Ihellod', \"bar\");\n\n    rmfiles('inc1', 'hellod/inc1');\n    rmdir('hellod');\n}\n\n# Check that the order of remaking include files is correct: should remake\n# them in the same order they were encountered in the makefile.  SV 58735\n\nrun_make_test(q!\n-include i1 i2\n-include i3\n-include i4\n%:;@echo $@\nall:;\n!,\n              '', \"i1\\ni2\\ni3\\ni4\\n#MAKE#: 'all' is up to date.\\n\");\n\n# Check that included files work if created after the first include failed\n# https://savannah.gnu.org/bugs/?57676\n\nrun_make_test(q!\ndefault:; @echo $(hello)\n-include hello.mk\n$(shell echo hello=world >hello.mk)\ninclude hello.mk\n!,\n              '', \"world\\n\");\n\nunlink('hello.mk');\n\n# Check that included double-colon targets with no prerequisites aren't built.\n# This should succeed since hello.mk already exists\n\ntouch('hello.mk');\n\nrun_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\ninclude hello.mk\nhello.mk:: ; echo 'FOO=bar' > $@\n!,\n              '', 'FOO=');\n\nunlink('hello.mk');\n\n# Check that included double-colon targets with no prerequisites aren't built.\n# This should succeed due to -include\n\nrun_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\n-include hello.mk\nhello.mk:: ; echo 'FOO=bar' > $@\n!,\n              '', 'FOO=');\n\n# Check that phony targets aren't built.\n# This should succeed since hello.mk already exists\n\ntouch('hello.mk');\n\nrun_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\ninclude hello.mk\nhello.mk: ; echo 'FOO=bar' > $@\n.PHONY: hello.mk\n!,\n              '', 'FOO=');\n\nunlink('hello.mk');\n\n# Check that included double-colon targets with no prerequisites aren't built.\n# This should succeed due to -include\n\nrun_make_test(q!\n.PHONY: default\ndefault:;@echo 'FOO=$(FOO)'\n-include hello.mk\nhello.mk: ; echo 'FOO=bar' > $@\n.PHONY: hello.mk\n!,\n              '', 'FOO=');\n\n# SV 56301 Verify pattern rules creating optional includes.\n# -k shouldn't matter when creating include files.\n\nrun_make_test(q!\nall:; @echo hello\n-include inc_a.mk\ninclude inc_b.mk\n%_a.mk %_b.mk:; exit 1\n!,\n              '', \"exit 1\\n#MAKEFILE#:4: failed to remake makefile 'inc_b.mk'\", 512);\n\nrun_make_test(undef, '-k', \"exit 1\\n#MAKEFILE#:4: failed to remake makefile 'inc_b.mk'\", 512);\n\n# It seems wrong to me that this gives a different error message, but at\n# least it doesn't keep going.\nrun_make_test(q!\nall:; @echo hello\ninclude inc_a.mk\n-include inc_b.mk\n%_a.mk %_b.mk:; exit 1\n!,\n              '', \"exit 1\\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\\n\", 512);\n\nrun_make_test(undef, '-k', \"exit 1\\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\\n#MAKEFILE#:3: failed to remake makefile 'inc_a.mk'\", 512);\n\n# Check the default makefiles... this requires us to invoke make with no\n# arguments.  Also check MAKEFILES\n\nif ($port_type eq 'W32') {\n    $defaults = \"GNUmakefile\\nmakefile\\nMakefile\\nmakefile.mak\";\n} else {\n    $defaults = \"GNUmakefile\\nmakefile\\nMakefile\";\n}\n\n$ENV{MAKEFILES} = 'foobar barfoo';\nrun_make_with_options(undef, ['-E', '%:;@echo $@', '-E', 'all:;', '-E', '-include bizbaz', '-E', '-include bazbiz'], get_logfile(0));\n$answer = \"bizbaz\\nbazbiz\\nfoobar\\nbarfoo\\n$defaults\\n#MAKE#: 'all' is up to date.\\n\";\n&compare_output(subst_make_string($answer), &get_logfile(1));\n\n# SV 63516\nif (exists $FEATURES{'dospaths'}) {\n    run_make_test(q!\ninclude C:__foobar\n%bar: ; @echo $@\nall: ;\n!,\n                  '', \"C:__foobar\\n#MAKE#: 'all' is up to date.\");\n}\n\n# sv 63484.\n# Test that included makefiles are not intermediate.\n# Here 'test.foo' is mentioned explicitly and cannot be considered\n# intermediate.\nutouch(-10, 'test.foo');\nutouch(-5, 'test.x');\ntouch('test');\nrun_make_test(q!\n.PHONY: force\ninclude test.foo\n%.foo: force; @echo force $@\n%.x: %.foo; touch $@\ntest: test.x; touch $@\n!, '', \"force test.foo\\n#MAKE#: 'test' is up to date.\\n\");\n\nunlink('test.foo', 'test.x', 'test');\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/jobserver",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test jobserver.\";\n\n$details = \"These tests are ones that specifically are different when the\njobserver feature is available.  Most -j tests are the same whether or not\njobserver is available, and those appear in the 'parallelism' test suite.\";\n\nexists $FEATURES{'jobserver'} or return -1;\n\nif (!$parallel_jobs) {\n  return -1;\n}\n\n# Shorthand\nmy $np = '--no-print-directory';\nmy $j1err = \"warning: jobserver unavailable: using -j1 (add '+' to parent make rule)\";\n\n# Simple test of MAKEFLAGS settings\nrun_make_test(q!\nSHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))\nrecurse: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -f #MAKEFILE# all\nall:;@echo $@: \"/$(SHOW)/\"\n!,\n              \"-j2 $np\", \"recurse: /-j2 --jobserver-auth=<auth> $np/\\nall: /-j2 --jobserver-auth=<auth> $np/\\n\");\n\n# Setting parallelism with the environment\n# Command line should take precedence over the environment\n$ENV{MAKEFLAGS} = \"-j2 $np\";\nrun_make_test(q!\nSHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))\nrecurse: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -f #MAKEFILE# all\nall:;@echo $@: \"/$(SHOW)/\"\n!,\n              '', \"recurse: /-j2 --jobserver-auth=<auth> $np/\\nall: /-j2 --jobserver-auth=<auth> $np/\\n\");\n\n# Test override of -jN\n$ENV{MAKEFLAGS} = \"-j9 $np\";\nrun_make_test(q!\nSHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))\nrecurse: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -j3 -f #MAKEFILE# recurse2\nrecurse2: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -f #MAKEFILE# all\nall:;@echo $@: \"/$(SHOW)/\"\n!,\n              \"-j2 $np\", \"recurse: /-j2 --jobserver-auth=<auth> $np/\\n#MAKE#[1]: warning: -j3 forced in submake: resetting jobserver mode\\nrecurse2: /-j3 --jobserver-auth=<auth> $np/\\nall: /-j3 --jobserver-auth=<auth> $np/\\n\");\n\n# Test override of -jN with -j\nrun_make_test(q!\nSHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))\nrecurse: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -j -f #MAKEFILE# recurse2\nrecurse2: ; @echo $@: \"/$(SHOW)/\"; $(MAKE) -f #MAKEFILE# all\nall:;@echo $@: \"/$(SHOW)/\"\n!,\n              \"-j2 $np\", \"recurse: /-j2 --jobserver-auth=<auth> $np/\\n#MAKE#[1]: warning: -j0 forced in submake: resetting jobserver mode\\nrecurse2: /-j $np/\\nall: /-j $np/\\n\");\n\n# Don't put --jobserver-auth into a re-exec'd MAKEFLAGS.\n# We can't test this directly because there's no way a makefile can\n# show the value of MAKEFLAGS we were re-exec'd with.  We can intuit it\n# by looking for \"disabling jobserver mode\" warnings; we should only\n# get one from the original invocation and none from the re-exec.\n# See Savannah bug #18124\n\nunlink('inc.mk');\n\nrun_make_test(q!\n.RECIPEPREFIX = >\n-include inc.mk\nrecur:\n#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'\n> @rm -f inc.mk\n> @$(MAKE) -j2 -f #MAKEFILE# all\nall:\n#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'\n> @echo $@\ninc.mk:\n#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'\n> @echo 'FOO = bar' > $@\n!,\n              \"$np -j2\", \"#MAKE#[1]: warning: -j2 forced in submake: resetting jobserver mode\\nall\\n\");\n\nunlink('inc.mk');\n\n# Test recursion which is hidden from make.\n# See Savannah bug #39934\n# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474\n# Environments that don't use a pipe won't close access, so this won't happen.\nif ($port_type ne 'W32') {\n    create_file('Makefile2', \"vpath %.c ../\\n\", \"foo:\\n\");\n\n    run_make_test(q!\ndefault: ; @ #MAKEPATH# -f Makefile2\n!,\n              \"--jobserver-style=pipe -j2 $np\",\n\"#MAKE#[1]: $j1err\n#MAKE#[1]: Nothing to be done for 'foo'.\");\n\n    rmfiles('Makefile2');\n}\n\n# For Windows and named pipes, we don't need to worry about recursion\nif ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {\n  create_file('Makefile2', \"vpath %.c ../\\n\", \"foo:\\n\");\n\n  run_make_test(q!\ndefault: ; @ #MAKEPATH# -f Makefile2\n!,\n              \"-j2 $np\",\n\"#MAKE#[1]: Nothing to be done for 'foo'.\");\n\n  rmfiles('Makefile2');\n}\n\n# SV 63981: Don't generat warnings if the user specifically disabled -j\n\nrun_make_test(q!\nall: ; @$(MAKE) -C . -f #MAKEFILE# recurse -j1\nrecurse: ; @echo hi\n!,\n              '-w -j2', \"#MAKE#: Entering directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nhi\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#: Leaving directory '#PWD#'\");\n\n# Ensure enter/leave directory messages appear before jobserver warnings\n\nrun_make_test(q!\nall: ; @$(MAKE) -C . -f #MAKEFILE# recurse -j10\nrecurse: ; @echo hi\n!,\n              '-w -j2', \"#MAKE#: Entering directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\n#MAKE#[1]: warning: -j10 forced in submake: resetting jobserver mode\nhi\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\n# Check for invalid jobserver-style options\n\nrun_make_test(q!\nall: a\nall a: ; @echo $@\n!,\n              '--jobserver-style=foo -j8',\n              \"#MAKE#: *** unknown jobserver auth style 'foo'.  Stop.\", 512);\n\n# Ensure the jobserver is not disabled even if only later commands are recursive\n\nrun_make_test(q!\n.RECIPEPREFIX := >\nall:\n> @echo $@ 1\n> @echo $@ 2\n> @$(MAKE) -f #MAKEFILE# recurse\n\nrecurse: ; @echo $@\n!,\n              \"$np -j8\", \"all 1\\nall 2\\nrecurse\");\n\nif ($port_type ne 'W32') {\n    run_make_test(undef, \"$np --jobserver-style=pipe -j8\",\n                  \"all 1\\nall 2\\nrecurse\");\n}\n\n# And with + instead of $(MAKE)\n\nrun_make_test(q!\n.RECIPEPREFIX := >\nall:\n> @echo $@ 1\n> @echo $@ 2\n> @+#MAKEPATH# -f #MAKEFILE# recurse\n\nrecurse: ; @echo $@\n!,\n              \"$np -j8\", \"all 1\\nall 2\\nrecurse\");\n\nif ($port_type ne 'W32') {\n    run_make_test(undef, \"$np --jobserver-style=pipe -j8\",\n                  \"all 1\\nall 2\\nrecurse\");\n}\n\n# We can't reset TMPDIR to something invalid when using valgrind\nif (exists $FEATURES{'jobserver-fifo'} && !$valgrind) {\n  # sv 62908.\n  # Test that when mkfifo fails, make switches to pipe and succeeds.\n  # Force mkfifo to fail by attempting to create a fifo in a non existent\n  # directory.\n  # run_make_test does not allow matching a multiline pattern, therefore run\n  # the test twice.\n  # First time look for /$ERR_no_such_file/ to ensure mkfifo failed.\n  # Second time look for /Nothing to be done/ to ensure make succeeded.\n  $ENV{TMPDIR} = \"nosuchdir\";\n  run_make_test(\"all:\\n\", '-j2', \"/$ERR_no_such_file/\");\n\n  $ENV{TMPDIR} = \"nosuchdir\";\n  run_make_test(undef, '-j2', \"/Nothing to be done/\");\n\n  # Verify that MAKE_TMPDIR is preferred if provided\n  $ENV{MAKE_TMPDIR} = '.';\n  $ENV{TMPDIR} = 'nosuchdir';\n\n  run_make_test(q!\nrecurse: ; @$(MAKE) -f #MAKEFILE# all\nall:;@echo \"$$MAKEFLAGS\"\n!,\n              \"-j2 --no-print-directory\", \"/--jobserver-auth=fifo:\\\\./\");\n\n  # Verify we fall back to -j1 but continue, of the auth is bad.\n  $ENV{MAKEFLAGS} = '-j2 --jobserver-auth=fifo:nosuchfile';\n  run_make_test(q!all:;@echo hi!, \"\", \"#MAKE#: cannot open jobserver nosuchfile: $ERR_no_such_file\\n#MAKE#: $j1err\\nhi\\n\");\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/load",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the load operator.\";\n\n$details = \"Test dynamic loading of modules.\";\n\n# Don't do anything if this system doesn't support \"load\"\nexists $FEATURES{'load'} or return -1;\n\nmy $cc = get_config('CC');\nif (! $cc) {\n    $verbose and print \"Skipping load test: no CC defined\\n\";\n    return -1;\n}\n\n# First build a shared object\n# Provide both a default and non-default load symbol\n\nunlink(qw(testload.c testload.so));\n\nopen(my $F, '> testload.c') or die \"open: testload.c: $!\\n\";\nprint $F <<'EOF' ;\n#include \"gnumake.h\"\n\nchar* getenv (const char*);\n\nint plugin_is_GPL_compatible;\n\nint testload_gmk_setup (unsigned int, gmk_floc *);\nint explicit_setup (unsigned int, gmk_floc *);\n\nint\ntestload_gmk_setup (unsigned int abi, gmk_floc *pos)\n{\n    (void)abi;\n    (void)pos;\n    gmk_eval (\"TESTLOAD = implicit\", 0);\n    if (getenv(\"TESTAPI_KEEP\"))\n      return -1;\n    return 1;\n}\n\nint\nexplicit_setup (unsigned int abi, gmk_floc *pos)\n{\n    (void)abi;\n    (void)pos;\n    gmk_eval (\"TESTLOAD = explicit\", 0);\n    if (getenv(\"TESTAPI_KEEP\"))\n      return -1;\n    return 1;\n}\nEOF\nclose($F) or die \"close: testload.c: $!\\n\";\n\n# Make sure we can compile\n\nmy $cppflags = get_config('CPPFLAGS') . ($srcdir ? \" -I$srcdir/src\" : '');\nmy $cflags = get_config('CFLAGS') . ' -fPIC';\nmy $ldflags = get_config('LDFLAGS') . ' -shared';\nmy $sobuild = \"$cc $cppflags $cflags $ldflags -o testload.so testload.c\";\n\nmy $clog = `$sobuild 2>&1`;\nif ($? != 0) {\n    $verbose and print \"Failed to build testload.so:\\n$sobuild\\n$clog\";\n    return -1;\n}\n\n# TEST 1\nrun_make_test(q!\nPRE := $(.LOADED)\nload testload.so\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\n!,\n              '--warn-undefined-variables', \"pre= post=testload.so implicit\\n\");\n\n# TEST 2\n# Load using an explicit function\nrun_make_test(q!\nPRE := $(.LOADED)\nload ./testload.so(explicit_setup)\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\n!,\n              '', \"pre= post=testload.so explicit\\n\");\n\n# TEST 3\n# Check multiple loads\nrun_make_test(q!\nPRE := $(.LOADED)\nload ./testload.so\nload testload.so(explicit_setup)\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\n!,\n              '', \"pre= post=testload.so implicit\\n\");\n\n# TEST 4\n# Check auto-rebuild of loaded file that's out of date\nutouch(-10, 'testload.so');\ntouch('testload.c');\n\nrun_make_test(q!\nPRE := $(.LOADED)\nload ./testload.so\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\ntestload.so: testload.c ; @echo \"rebuilding $@\"; !.$sobuild,\n              '', \"rebuilding testload.so\\npre= post=testload.so implicit\\n\");\n\n# TEST 5\n# Check auto-rebuild of loaded file when it doesn't exist\nunlink('testload.so');\n\nrun_make_test(q!\nPRE := $(.LOADED)\n-load ./testload.so(explicit_setup)\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\n%.so: %.c ; @echo \"rebuilding $@\"; !.$sobuild,\n              '', \"rebuilding testload.so\\npre= post=testload.so explicit\\n\");\n\n# sv 63044.\n# Test that the loaded shared object is present in .LOADED when the setup\n# routine returns -1.\n$ENV{TESTAPI_KEEP} = 1;\nrun_make_test(q!\nPRE := $(.LOADED)\nload testload.so\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\n!,\n              '--warn-undefined-variables', \"pre= post=testload.so implicit\\n\");\n\n# Check that we don't auto-rebuild of loaded file that's out of date\n# if we return -1 from the setup\nutouch(-10, 'testload.so');\ntouch('testload.c');\n\n$ENV{TESTAPI_KEEP} = 1;\nrun_make_test(q!\nPRE := $(.LOADED)\nload ./testload.so\nPOST := $(.LOADED)\nall: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)\ntestload.so: testload.c ; @echo \"rebuilding $@\"; !.$sobuild,\n              '', \"pre= post=testload.so implicit\\n\");\n\n# Check using load as a target or variable name\nrun_make_test(q!\nload: ; @echo $@\n-load&: ; @echo $@\n!,\n              \"\", \"load\\n\");\n\nrun_make_test(q!\nload : ; @echo $@\n-load &: ; echo $@\n!,\n              \"\", \"load\\n\");\n\nrun_make_test(q!\nload = @echo $@\nall: ; $(load)\nload |: ; echo $@\n!,\n              \"\", \"all\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/loadapi",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the shared object load API.\";\n\n$details = \"Verify the different aspects of the shared object API.\";\n\n# Don't do anything if this system doesn't support \"load\"\nexists $FEATURES{load} or return -1;\n\nmy $cc = get_config('CC');\nif (! $cc) {\n    $verbose and print \"Skipping load test: no CC defined\\n\";\n    return -1;\n}\n\n# First build a shared object\n# Provide both a default and non-default load symbol\n\nunlink(qw(testapi.c testapi.so));\n\nopen(my $F, '> testapi.c') or die \"open: testapi.c: $!\\n\";\nprint $F <<'EOF' ;\n#include <string.h>\n#include <stdio.h>\n\n#include \"gnumake.h\"\n\nchar *getenv (const char*);\n\nint plugin_is_GPL_compatible;\n\nint testapi_gmk_setup (unsigned int abi, const gmk_floc *floc);\n\nstatic char *\ntest_eval (const char *buf)\n{\n    gmk_eval (buf, 0);\n    return NULL;\n}\n\nstatic char *\ntest_expand (const char *val)\n{\n    return gmk_expand (val);\n}\n\nstatic char *\ntest_noexpand (const char *val)\n{\n    char *str = gmk_alloc (strlen (val) + 1);\n    strcpy (str, val);\n    return str;\n}\n\nstatic char *\nfunc_test (const char *funcname, unsigned int argc, char **argv)\n{\n    char *mem;\n\n    (void)argc;\n\n    if (strcmp (funcname, \"test-expand\") == 0)\n        return test_expand (argv[0]);\n\n    if (strcmp (funcname, \"test-eval\") == 0)\n        return test_eval (argv[0]);\n\n    if (strcmp (funcname, \"test-noexpand\") == 0)\n        return test_noexpand (argv[0]);\n\n    mem = gmk_alloc (sizeof (\"unknown\"));\n    strcpy (mem, \"unknown\");\n    return mem;\n}\n\nint\ntestapi_gmk_setup (unsigned int abi, const gmk_floc *floc)\n{\n    const char *verbose = getenv (\"TESTAPI_VERBOSE\");\n\n    (void)abi;\n\n    gmk_add_function (\"test-expand\", func_test, 1, 1, GMK_FUNC_DEFAULT);\n    gmk_add_function (\"test-noexpand\", func_test, 1, 1, GMK_FUNC_NOEXPAND);\n    gmk_add_function (\"test-eval\", func_test, 1, 1, GMK_FUNC_DEFAULT);\n    gmk_add_function (\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.\", func_test, 0, 0, 0);\n\n    if (verbose)\n      {\n        printf (\"testapi_gmk_setup\\n\");\n\n        if (verbose[0] == '2')\n          printf (\"%s:%lu\\n\", floc->filenm, floc->lineno);\n      }\n\n    if (getenv (\"TESTAPI_KEEP\"))\n      return -1;\n\n    return 1;\n}\n\nint\nalternative_setup ()\n{\n    gmk_add_function (\"test-expand\", func_test, 1, 1, GMK_FUNC_DEFAULT);\n    gmk_add_function (\"test-noexpand\", func_test, 1, 1, GMK_FUNC_NOEXPAND);\n    gmk_add_function (\"test-eval\", func_test, 1, 1, GMK_FUNC_DEFAULT);\n    gmk_add_function (\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.\", func_test, 0, 0, 0);\n\n    if (getenv (\"TESTAPI_VERBOSE\"))\n      printf (\"alternative_setup\\n\");\n\n    if (getenv (\"TESTAPI_KEEP\"))\n      return -1;\n\n    return 1;\n}\n\nvoid\ntestapi_gmk_unload ()\n{\n    const char *s = getenv (\"TESTAPI_VERBOSE\");\n    if (s && *s == '3')\n      printf (\"testapi_gmk_unload\\n\");\n}\n\nEOF\nclose($F) or die \"close: testapi.c: $!\\n\";\n\n# Make sure we can compile\n\nmy $cflags = get_config('CFLAGS');\nmy $cppflags = get_config('CPPFLAGS');\nmy $ldflags = get_config('LDFLAGS');\nmy $sobuild = \"$cc \".($srcdir? \"-I$srcdir/src\":'').\" $cppflags $cflags -shared -fPIC $ldflags -o testapi.so testapi.c\";\n\nmy $clog = `$sobuild 2>&1`;\nif ($? != 0) {\n    $verbose and print \"Failed to build testapi.so:\\n$sobuild\\n$_\";\n    return -1;\n}\n\n# TEST 1\n# Check the gmk_expand() function\nrun_make_test(q!\nEXPAND = expansion\nall: ; @echo $(test-expand $$(EXPAND))\nload testapi.so\n!,\n              '', \"expansion\\n\");\n\n# TEST 2\n# Check the eval operation.  Prove that the argument is expanded only once\nrun_make_test(q!\nload testapi.so\nTEST = bye\nASSIGN = VAR = $(TEST) $(shell echo there)\n$(test-eval $(value ASSIGN))\nTEST = hi\nall:;@echo '$(VAR)'\n!,\n              '', \"hi there\\n\");\n\n# TEST 2\n# Check the no-expand capability\nrun_make_test(q!\nload testapi.so\nTEST = hi\nall:;@echo '$(test-noexpand $(TEST))'\n!,\n              '', \"\\$(TEST)\\n\");\n\n\n# During all subsequent tests testapi.so exists.\n#\nmy @loads = ('', q!\nload testapi.so\nload testapi.so\n-load testapi.so\n-load testapi.so\n$(eval load testapi.so)\n$(eval -load testapi.so)\n!);\n\nfor my $extra_loads (@loads) {\nmy $n = 5;\nif ($extra_loads) {\n  $n = 12;\n}\n# sv 63045.\n# Test that having unloaded a shared object make loads it again, even if the\n# shared object is not updated.\n$ENV{TESTAPI_VERBOSE} = 1;\nrun_make_test(\"\nload testapi.so\n$extra_loads\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: force; \\$(info \\$@)\nforce:;\n.PHONY: force\n\", '', \"testapi_gmk_setup\\ntestapi.so\\ntestapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63045.\n# Same as above, but testapi_gmk_setup returned -1.\n$ENV{TESTAPI_KEEP} = 1;\n$ENV{TESTAPI_VERBOSE} = 1;\nrun_make_test(\"\nload testapi.so\n$extra_loads\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: force; \\$(info \\$@)\nforce:;\n.PHONY: force\n\", '', \"testapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63045.\n# Test that make exits, unless make can successfully update an unloaded shared\n# object.\n$ENV{TESTAPI_VERBOSE} = 1;\nrun_make_test(\"\nload testapi.so\n$extra_loads\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: force; @#HELPER# fail 1\nforce:;\n.PHONY: force\n\", '', \"testapi_gmk_setup\\nfail 1\\n#MAKE#: *** [#MAKEFILE#:$n: testapi.so] Error 1\\n\", 512);\n\n# sv 63045.\n# Same as above, but testapi_gmk_setup returned -1.\n$ENV{TESTAPI_KEEP} = 1;\n$ENV{TESTAPI_VERBOSE} = 1;\nrun_make_test(\"\nload testapi.so\n$extra_loads\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: force; @#HELPER# fail 1\nforce:;\n.PHONY: force\n\", '', \"testapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63100.\n# Test that make supplies the correct floc when the shared object is loaded\n# again.\n$ENV{TESTAPI_VERBOSE} = 2;\nrun_make_test(\"\nload testapi.so\n$extra_loads\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: force; \\$(info \\$@)\nforce:;\n.PHONY: force\n\", '', \"testapi_gmk_setup\\n#MAKEFILE#:2\\ntestapi.so\\ntestapi_gmk_setup\\n#MAKEFILE#:2\\nhello\\n#MAKE#: 'all' is up to date.\\n\");\n}\n\nmy @names  = ('testapi.so', './testapi.so', '#PWD#/testapi.so');\n\nfor my $name (@names) {\n\n# Test the make correctly figures out the name of the close function and runs\n# the close function.\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(\"\nload $name\nall:; \\$(info \\$(test-expand hello))\n\", '', \"testapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\ntestapi_gmk_unload\\n\");\n}\n\n# Same as above, but the setup function is custom.\n@names  = ('testapi.so(alternative_setup)', './testapi.so(alternative_setup)',\n           '#PWD#/testapi.so(alternative_setup)');\nfor my $name (@names) {\n\n# Test the close function.\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(\"\nload $name\nall:; \\$(info \\$(test-expand hello))\n\", '', \"alternative_setup\\nhello\\n#MAKE#: 'all' is up to date.\\ntestapi_gmk_unload\\n\");\n}\n\n# Test that makes runs the close function on failure.\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(q!\nload testapi.so\nall: bad_preqreq; :\n!, '', \"testapi_gmk_setup\\n#MAKE#: *** No rule to make target 'bad_preqreq', needed by 'all'.  Stop.\\ntestapi_gmk_unload\\n\", 512);\n\n# Test that make unloads a shared object, calls the close function, loads\n# the plugin again, and then calls the close function again on exit.\n&utouch(-10, 'testapi.so');\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(\"\nload testapi.so\nall:; \\$(info \\$(test-expand hello))\ntestapi.so: testapi.c; $sobuild\n\", '', \"testapi_gmk_setup\\ntestapi_gmk_unload\\n$sobuild\\ntestapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\ntestapi_gmk_unload\");\n\n# Test that make unloads a shared object, calls the close function, loads\n# the plugin again, and then calls the close function again on exit.\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(q!\nload testapi.so\nall:; $(info $(test-expand hello))\ntestapi.so: force; $(info $@)\nforce:;\n.PHONY: force\n!, '', \"testapi_gmk_setup\\ntestapi_gmk_unload\\ntestapi.so\\ntestapi_gmk_setup\\nhello\\n#MAKE#: 'all' is up to date.\\ntestapi_gmk_unload\\n\");\n\nunlink(qw(testapi.c testapi.so)) unless $keep;\n\n# Test that make does not run the close function, unless the shared object\n# loaded successfully.\nunlink('testapi.so');\n$ENV{TESTAPI_VERBOSE} = 3;\nrun_make_test(q!\nload testapi.so\nall:; :\n!, '', \"#MAKEFILE#:2: testapi.so: cannot open shared object file: $ERR_no_such_file\\n#MAKEFILE#:2: *** testapi.so: failed to load.  Stop.\\n\", 512);\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/mult_rules",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"\\\nThe following test creates a makefile to test the presence\nof multiple rules for one target.  One file can be the\ntarget of several rules if at most one rule has commands;\nthe other rules can only have dependencies.\";\n\n$details = \"\\\nThe makefile created in this test contains two hardcoded rules\nfor foo.o and bar.o.  It then gives another multiple target rule\nwith the same names as above but adding more dependencies.\nAdditionally, another variable extradeps is listed as a\ndependency but is defined to be null.  It can however be defined\non the make command line as extradeps=extra.h which adds yet\nanother dependency to the targets.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<EOF;\nobjects = foo.o bar.o\nfoo.o : defs.h\nbar.o : defs.h test.h\nextradeps =\n\\$(objects) : config.h \\$(extradeps)\n\\t\\@echo EXTRA EXTRA\nEOF\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&touch(\"defs.h\",\"test.h\",\"config.h\");\n\nif ($vos)\n{\n   $error_code = 3307;\n}\nelse\n{\n   $error_code = 512;\n}\n\n&run_make_with_options($makefile,\n                       \"extradeps=extra.h\",\n                       &get_logfile,\n                       $error_code);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"$make_name: *** No rule to make target 'extra.h', needed by 'foo.o'.  Stop.\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST #2\n# -------\n\n&touch(\"extra.h\");\n\n&run_make_with_options($makefile,\n                       \"extradeps=extra.h\",\n                       &get_logfile,\n                       0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"EXTRA EXTRA\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\nunlink(\"defs.h\",\"test.h\",\"config.h\",\"extra.h\");\n\n# sv 62650.\n# Test the message that make prints when a file found by directory search\n# is preferred over the local one.\nrun_make_test(q!\nvpath hello.c src\nall: hello.c; $(info $@ from $^)\nhello.c: ; $(info 1 $@)\nsrc/hello.c: ; $(info 2 $@)\n!, '',\n    \"#MAKEFILE#:4: recipe was specified for file 'hello.c' at #MAKEFILE#:4,\n#MAKEFILE#:4: but 'hello.c' is now considered the same file as 'src/hello.c'\n#MAKEFILE#:4: recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'\n2 src/hello.c\nall from src/hello.c\n#MAKE#: 'all' is up to date.\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/mult_targets",
    "content": "$description = \"The following test creates a makefile to test that a \\n \"\n              .\"rule with multiple targets is equivalent to writing \\n\"\n              .\"many rules, each with one target, and all identical aside\\n\"\n              .\"from that.\";\n\n$details = \"A makefile is created with one rule and two targets.  Make \\n\"\n          .\"is called twice, once for each target, and the output which \\n\"\n          .\"contains the target name with \\$@ is looked at for the changes.\\n\"\n          .\"This test also tests the substitute function by replacing \\n\"\n          .\"the word output with nothing in the target name giving either\\n\"\n          .\"an output of \\\"I am little\\\" or \\\"I am big\\\"\";  \n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"bigoutput littleoutput: test.h\\n\";\nprint MAKEFILE \"\\t\\@echo I am \\$(subst output,,\\$@)\\n\";  \n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&touch(\"test.h\");\n\n&run_make_with_options($makefile,\"bigoutput\",&get_logfile);\n\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"I am big\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\n&run_make_with_options($makefile,\"littleoutput\",&get_logfile);\n$answer = \"I am little\\n\";\n&compare_output($answer,&get_logfile(1));\n\nunlink \"test.h\";\n\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/features/order_only",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test order-only prerequisites.\";\n\n$details = \"\\\nCreate makefiles with various combinations of normal and order-only\nprerequisites and ensure they behave properly.  Test the \\$| variable.\";\n\n# TEST #0 -- Basics\n\nrun_make_test('\n%r: | baz ; @echo $< $^ $|\nbar: foo\nfoo:;@:\nbaz:;@:',\n              '', \"foo foo baz\\n\");\n\n# TEST #1 -- First try: the order-only prereqs need to be built.\n\nrun_make_test(q!\nfoo: bar | baz\n\t@echo '$$^ = $^'\n\t@echo '$$| = $|'\n\ttouch $@\n\n.PHONY: baz\n\nbar baz:\n\ttouch $@!,\n              '', \"touch bar\\ntouch baz\\n\\$^ = bar\\n\\$| = baz\\ntouch foo\\n\");\n\n\n# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated\n\nrun_make_test(undef, '', \"touch baz\\n\");\n\nunlink(qw(foo bar baz));\n\n# TEST #3 -- Make sure the order-only prereq was promoted to normal.\n\nrun_make_test(q!\nfoo: bar | baz\n\t@echo '$$^ = $^'\n\t@echo '$$| = $|'\n\ttouch $@\n\nfoo: baz\n\n.PHONY: baz\n\nbar baz:\n\ttouch $@!,\n              '', \"touch bar\\ntouch baz\\n\\$^ = bar baz\\n\\$| = \\ntouch foo\\n\");\n\n\n# TEST #4 -- now we do it again\n\nrun_make_test(undef, '', \"touch baz\\n\\$^ = bar baz\\n\\$| = \\ntouch foo\\n\");\n\nunlink(qw(foo bar baz));\n\n# Test empty normal prereqs\n\n# TEST #5 -- make sure the parser was correct.\n\nrun_make_test(q!\nfoo:| baz\n\t@echo '$$^ = $^'\n\t@echo '$$| = $|'\n\ttouch $@\n\n.PHONY: baz\n\nbaz:\n\ttouch $@!,\n              '', \"touch baz\\n\\$^ = \\n\\$| = baz\\ntouch foo\\n\");\n\n# TEST #6 -- now we do it again: this time foo won't be built\n\nrun_make_test(undef, '', \"touch baz\\n\");\n\nunlink(qw(foo baz));\n\n# Test order-only in pattern rules\n\n# TEST #7 -- make sure the parser was correct.\n\nrun_make_test(q!\n%.w : %.x | baz\n\t@echo '$$^ = $^'\n\t@echo '$$| = $|'\n\ttouch $@\n\nall: foo.w\n\n.PHONY: baz\nfoo.x baz:\n\ttouch $@!,\n              '',\n              \"touch foo.x\\ntouch baz\\n\\$^ = foo.x\\n\\$| = baz\\ntouch foo.w\\n\");\n\n# TEST #8 -- now we do it again: this time foo.w won't be built\n\nrun_make_test(undef, '', \"touch baz\\n\");\n\nunlink(qw(foo.w foo.x baz));\n\n# TEST #9 -- make sure that $< is set correctly in the face of order-only\n# prerequisites in pattern rules.\n\nrun_make_test('\n%r: | baz ; @echo $< $^ $|\nbar: foo\nfoo:;@:\nbaz:;@:',\n              '', \"foo foo baz\\n\");\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/output-sync",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test --output-sync (-O) option.\";\n\n$details = \"Test the synchronization of output from parallel jobs.\";\n\n# If we don't have output sync support, never mind.\nexists $FEATURES{'output-sync'} or return -1;\n\n# Output sync can't be tested without parallelization\n$parallel_jobs or return -1;\n\n\n# The following subdirectories with Makefiles are used in several\n# of the following tests.  The model is:\n#   foo/Makefile - has a \"foo\" target that waits for the bar target\n#   bar/Makefile - has a \"bar\" target that runs immediately\n#                - has a \"baz\" target that waits for the foo target\n#\n# So, you start the two sub-makes in parallel and first the \"bar\" target is\n# built, followed by \"foo\", followed by \"baz\".  The trick is that first each\n# target prints a \"start\" statement, then waits (if appropriate), then prints\n# an end statement.  Thus we can tell if the -O flag is working, since\n# otherwise these statements would be mixed together.\n\n@syncfiles = ();\n\nsub output_sync_clean {\n    rmfiles('foo/Makefile', 'bar/Makefile', @syncfiles);\n    rmdir('foo');\n    rmdir('bar');\n}\n\n# We synchronize the different jobs by having them wait for a sentinel file to\n# be created, instead of relying on a certain amount of time passing.\n# Unfortunately in this test we have to sleep after we see the sync file,\n# since we also want to make the obtaining of the write synchronization lock\n# reliable.  If things are too fast, then sometimes a different job will steal\n# the output sync lock and the output is mis-ordered from what we expect.\nsub output_sync_wait {\n    return subst_make_string(\"#HELPER# \\$Q wait ../mksync.$_[0] sleep 1\");\n}\nsub output_sync_set {\n    return subst_make_string(\"#HELPER# \\$Q file ../mksync.$_[0]\");\n}\n\n@syncfiles = qw(mksync.foo mksync.foo_start mksync.bar mksync.bar_start);\n\n$tmout = 30;\n\noutput_sync_clean();\nmkdir('foo', 0777);\nmkdir('bar', 0777);\n\n$set_foo = output_sync_set('foo');\n$set_bar = output_sync_set('bar');\n$set_foo_start = output_sync_set('foo_start');\n$set_bar_start = output_sync_set('bar_start');\n\n$wait_foo = output_sync_wait('foo');\n$wait_bar = output_sync_wait('bar');\n$wait_foo_start = output_sync_set('foo_start');\n$wait_bar_start = output_sync_set('bar_start');\n\nopen(MAKEFILE,\"> foo/Makefile\");\nprint MAKEFILE <<EOF;\nall: foo\n\nfoo: foo-base ; $set_foo\n\nfoo-base:\n\\t\\@echo foo: start\n\\t$wait_bar\n\\t\\@echo foo: end\n\nfoo-job: foo-job-base ; $set_foo\n\nfoo-job-base:\n\\t$wait_bar_start\n\\t\\@echo foo: start\n\\t$set_foo_start\n\\t$wait_bar\n\\t\\@echo foo: end\n\nfoo-fail:\n\\t\\@echo foo-fail: start\n\\t$wait_bar\n\\t\\@echo foo-fail: end\n\\texit 1\n\nV :=\n\\$V.SILENT:\nQ :=\n\\$VQ := -q\nEOF\nclose(MAKEFILE);\n\nopen(MAKEFILE,\"> bar/Makefile\");\nprint MAKEFILE <<EOF;\nall: bar baz\n\nbar: bar-base ; $set_bar\nbar-base:\n\\t\\@echo bar: start\n\\t\\@echo bar: end\n\nbar-job: bar-job-base ; $set_bar\n\nbar-job-base:\n\\t\\@echo bar: start\n\\t$set_bar_start\n\\t$wait_foo_start\n\\t\\@echo bar: end\n\nbaz: baz-base\nbaz-base:\n\\t\\@echo baz: start\n\\t$wait_foo\n\\t\\@echo baz: end\n\nV :=\n\\$V.SILENT:\nQ :=\n\\$VQ := -q\nEOF\nclose(MAKEFILE);\n\n# Test per-make synchronization.\n# Note we have to sleep again here after starting the foo makefile before\n# starting the bar makefile, otherwise the \"entering/leaving\" messages for the\n# submakes might be ordered differently than we expect.\n\nunlink(@syncfiles);\nrun_make_test(qq!\nall: make-foo make-bar\n\nmake-foo: ; \\$(MAKE) -C foo\n\nmake-bar: ; #HELPER# -q sleep 1 ; \\$(MAKE) -C bar!,\n              '-j -Orecurse',\n\"#MAKEPATH# -C foo\n#MAKE#[1]: Entering directory '#PWD#/foo'\nfoo: start\nfoo: end\n#MAKE#[1]: Leaving directory '#PWD#/foo'\n#HELPER# -q sleep 1 ; #MAKEPATH# -C bar\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbar: start\nbar: end\nbaz: start\nbaz: end\n#MAKE#[1]: Leaving directory '#PWD#/bar'\\n\", 0, $tmout);\n\n# Test per-target synchronization.\n# Note we have to sleep again here after starting the foo makefile before\n# starting the bar makefile, otherwise the \"entering/leaving\" messages for the\n# submakes might be ordered differently than we expect.\n\nunlink(@syncfiles);\nrun_make_test(qq!\nx=1\n\\$xMAKEFLAGS += --no-print-directory\n\nall: make-foo make-bar\n\nmake-foo: ; \\$(MAKE) -C foo\n\nmake-bar: ; #HELPER# -q sleep 1 ; \\$(MAKE) -C bar!,\n              '-j --output-sync=target',\n\"#MAKEPATH# -C foo\n#HELPER# -q sleep 1 ; #MAKEPATH# -C bar\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbar: start\nbar: end\n#MAKE#[1]: Leaving directory '#PWD#/bar'\n#MAKE#[1]: Entering directory '#PWD#/foo'\nfoo: start\nfoo: end\n#MAKE#[1]: Leaving directory '#PWD#/foo'\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbaz: start\nbaz: end\n#MAKE#[1]: Leaving directory '#PWD#/bar'\\n\", 0, $tmout);\n\n# Rerun but this time suppress the directory tracking\nunlink(@syncfiles);\nrun_make_test(undef, '-j --output-sync=target x=',\n              \"#MAKEPATH# -C foo\n#HELPER# -q sleep 1 ; #MAKEPATH# -C bar\nbar: start\nbar: end\nfoo: start\nfoo: end\nbaz: start\nbaz: end\\n\", 0, $tmout);\n\n# Test that messages from make itself are enclosed with\n# \"Entering/Leaving directory\" messages.\nunlink(@syncfiles);\nrun_make_test(qq!\nall: make-foo-fail make-bar-bar\n\nmake-foo-fail: ; \\$(MAKE) -C foo foo-fail\n\nmake-bar-bar: ; #HELPER# -q sleep 1 ; \\$(MAKE) -C bar bar!,\n              '-j -O',\n\"#MAKEPATH# -C foo foo-fail\n#HELPER# -q sleep 1 ; #MAKEPATH# -C bar bar\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbar: start\nbar: end\n#MAKE#[1]: Leaving directory '#PWD#/bar'\n#MAKE#[1]: Entering directory '#PWD#/foo'\nfoo-fail: start\nfoo-fail: end\n#MAKE#[1]: *** [Makefile:23: foo-fail] Error 1\n#MAKE#[1]: Leaving directory '#PWD#/foo'\n#MAKE#: *** [#MAKEFILE#:4: make-foo-fail] Error 2\\n\",\n512);\n\n# Test the per-job synchronization.\n# For this we'll have bar-job:\n#   print start, invoke bar-start, wait for foo-start, print end, print-bar-end\n# And foo-job:\n#   wait for bar-start, print foo-start, wait for bar-end, print end\n\nunlink(@syncfiles);\nrun_make_test(qq!\nall: make-foo make-bar\n\nmake-foo: ; \\$(MAKE) -C foo foo-job\n\nmake-bar: ; #HELPER# -q sleep 1 ; \\$(MAKE) -C bar bar-job!,\n              '-j --output-sync=line',\n\"#MAKEPATH# -C foo foo-job\n#HELPER# -q sleep 1 ; #MAKEPATH# -C bar bar-job\n#MAKE#[1]: Entering directory '#PWD#/foo'\nfoo: start\n#MAKE#[1]: Leaving directory '#PWD#/foo'\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbar: start\n#MAKE#[1]: Leaving directory '#PWD#/bar'\n#MAKE#[1]: Entering directory '#PWD#/bar'\nbar: end\n#MAKE#[1]: Leaving directory '#PWD#/bar'\n#MAKE#[1]: Entering directory '#PWD#/foo'\nfoo: end\n#MAKE#[1]: Leaving directory '#PWD#/foo'\\n\", 0, $tmout);\n\n# Remove temporary directories and contents.\noutput_sync_clean();\n\n# Ensure recursion doesn't mis-order or double-print output\nrun_make_test(qq!\nall:\n\\t\\@echo foo\n\\t\\@+echo bar\n!,\n              '-j -Oline', \"foo\\nbar\\n\");\n\nrun_make_test(undef, '-j -Otarget', \"foo\\nbar\\n\");\n\n# Ensure when make writes out command it's not misordered\nrun_make_test(qq!\nall:\n\\t\\@echo foobar\n\\ttrue\n!,\n              '-j -Oline', \"foobar\\ntrue\\n\");\n\nrun_make_test(undef, '-j -Otarget', \"foobar\\ntrue\\n\");\n\n# Ensure that shell functions inside recipes write stderr to the sync file\nrun_make_test(q!\nall: ; @: $(shell echo foo 1>&2)\n!,\n              '-w -Oline', \"#MAKE#: Entering directory '#PWD#'\\nfoo\\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\n# Ensure that output generated while parsing makefiles is synced\n# when appropriate.\nrun_make_test(q!\n$(shell echo foo 1>&2)\nall: ; echo bar\n!,\n              '-s -w -Otarget', \"#MAKE#: Entering directory '#PWD#'\\nfoo\\n#MAKE#: Leaving directory '#PWD#'\\n#MAKE#: Entering directory '#PWD#'\\nbar\\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\n# Test recursion\n$m1 = get_tmpfile();\n$m2 = get_tmpfile();\n\nopen(M1, \"> $m1\");\nprint M1 <<'EOF';\n$(shell echo d1 stderr 1>&2)\n$(info d1 stdout)\nall:; @:\nEOF\nclose(M1);\n\nopen(M2, \"> $m2\");\nprint M2 <<'EOF';\n$(shell echo d2 stderr 1>&2)\n$(info d2 stdout)\nall:; @:\n# Force an ordering on the output\n$(shell sleep 1)\nEOF\nclose(M2);\n\nrun_make_test(qq!\nall: t1 t2\nt1: ; \\@\\$(MAKE) -f $m1\nt2: ; \\@\\$(MAKE) -f $m2\n!,\n              \"-j -Oline\", \"#MAKE#[1]: Entering directory '#PWD#'\\nd1 stderr\\nd1 stdout\\n#MAKE#[1]: Leaving directory '#PWD#'\\n#MAKE#[1]: Entering directory '#PWD#'\\nd2 stderr\\nd2 stdout\\n#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\nrmfiles($m1, $m2);\n\n# Ensure that output generated while parsing makefiles is synced\n# when appropriate.\n$m1 = get_tmpfile();\n\nopen(M1, \"> $m1\");\nprint M1 <<'EOF';\n$(shell echo d1 stderr 1>&2)\n$(info d1 stdout)\n$(error d1 failed)\nall:; @:\nEOF\nclose(M1);\n\nrun_make_test(qq!\nall: t1\nt1: ; -\\@\\$(MAKE) -f $m1\n!,\n              \"-j -Oline\", \"#MAKE#[1]: Entering directory '#PWD#'\\nd1 stderr\\nd1 stdout\\n$m1:3: *** d1 failed.  Stop.\\n#MAKE#[1]: Leaving directory '#PWD#'\\n#MAKE#: [#MAKEFILE#:3: t1] Error 2 (ignored)\\n\");\n\nrmfiles($m1);\n\n# Test $(error ...) functions in recipes\n\nrun_make_test(q!\nfoo: $(OBJS) ; echo $(or $(filter %.o,$^),$(error fail))\n!,\n              '-O', \"#MAKEFILE#:2: *** fail.  Stop.\\n\", 512);\n\n# SV 47365: Make sure exec failure error messages are shown\n# Needs to be ported to Windows\nif ($port_type ne 'W32') {\n    run_make_test(q!\nall:: ; @./foo bar baz\n!,\n              '-O', \"#MAKE#: ./foo: $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:2: all] Error 127\\n\", 512);\n}\n\nif ($port_type eq 'UNIX') {\n# POSIX doesn't require sh to set PPID so test this\nmy $cmd = create_command();\nadd_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);\nmy $fout = 'ppidtest.out';\nrun_command_with_output($fout, @$cmd);\n$_ = read_file_into_string($fout);\ns/\\r?\\n//g;\nif (/^[0-9]+$/) {\nuse POSIX ();\n# SV 63157.\n# Test that make removes temporary files, even when a signal is received.  The\n# general test_driver postprocessing will ensure the temporary file used to\n# synchronize output and the jobserver fifo are both removed.  sleep is needed\n# to let make write its \"... Terminated\" message to the log file.  Must use\n# REGEX because some systems (MacOS) add extra text after Terminated.\nrun_make_test(q!\npid:=$(shell echo $$PPID)\nall:; @#HELPER# -q term $(pid) sleep 10\n!, '-O -j2', '/#MAKE#: \\*\\*\\* \\[#MAKEFILE#:3: all] Terminated/', POSIX::SIGTERM);\n}\nunlink($fout);\n\n# SV 63333. Test that make continues to run without output sync when we\n# cannot create a temporary file.\n# Create a non-writable temporary directory.\n# Run the test twice, because run_make_test cannot match a regex against a\n# multiline input.\n\n# If we do this Valgrind fails because it cannot write temp files... the docs\n# don't describe any way to tell valgrind to use a directory other than TMPDIR.\n\nif (!$valgrind) {\n    my $tdir = 'test_tmp_dir';\n    mkdir($tdir, 0500);\n    $ENV{'TMPDIR'} = $tdir;\n\n    run_make_test(q!\nall:; $(info hello, world)\n!, '-Orecurse', \"/suppressing output-sync/\");\n\n    run_make_test(undef, '-Orecurse', \"/#MAKE#: 'all' is up to date./\");\n\n    rmdir($tdir);\n}\n}\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/override",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the override directive on variable assignments.\";\n\n$details = \"\";\n\n# TEST 0: Basic override\n\nrun_make_test('\nX = start\noverride recur = $(X)\noverride simple := $(X)\nX = end\nall: ; @echo \"$(recur) $(simple)\"\n',\n              'recur=I simple=J', \"end start\\n\");\n\n# TEST 1: Override with append\n\nrun_make_test('\nX += X1\noverride X += X2\noverride Y += Y1\nY += Y2\nall: ; @echo \"$(X) $(Y)\"\n',\n              '', \"X1 X2 Y1\\n\");\n\n# TEST 2: Override with append to the command line\n\nrun_make_test(undef, 'X=C Y=C', \"C X2 C Y1\\n\");\n\n# Test override of define/endef\n\nrun_make_test('\noverride define foo\n@echo First comes the definition.\n@echo Then comes the override.\nendef\nall: ; $(foo)\n',\n              'foo=Hello', \"First comes the definition.\\nThen comes the override.\\n\");\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/parallelism",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test parallelism (-j) option.\";\n$details = \"\";\n\nif (!$parallel_jobs) {\n  return -1;\n}\n\nrun_make_test(q!\nall : def_1 def_2 def_3\ndef_1 : ; @#HELPER# file ONE wait THREE out TWO\ndef_2 : ; @#HELPER# wait FOUR file THREE\ndef_3 : ; @#HELPER# wait ONE file FOUR!,\n              '-j4', \"file ONE\\nwait ONE\\nfile FOUR\\nwait FOUR\\nfile THREE\\nwait THREE\\nTWO\");\nrmfiles(qw(ONE TWO THREE FOUR));\n\n# Verify -j added to MAKEFLAGS in the makefile\nrun_make_test(q!\nMAKEFLAGS += -j4\nall : def_1 def_2 def_3\ndef_1 : ; @#HELPER# file ONE wait THREE out TWO\ndef_2 : ; @#HELPER# wait FOUR file THREE\ndef_3 : ; @#HELPER# wait ONE file FOUR!,\n              '', \"file ONE\\nwait ONE\\nfile FOUR\\nwait FOUR\\nfile THREE\\nwait THREE\\nTWO\");\nrmfiles(qw(ONE TWO THREE FOUR));\n\n# Command line should take precedence\nrun_make_test(q!\nMAKEFLAGS += -j2\nall : def_1 def_2 def_3\ndef_1 : ; @#HELPER# file ONE wait THREE out TWO\ndef_2 : ; @#HELPER# wait FOUR file THREE\ndef_3 : ; @#HELPER# wait ONE file FOUR!,\n              '-j4', \"file ONE\\nwait ONE\\nfile FOUR\\nwait FOUR\\nfile THREE\\nwait THREE\\nTWO\");\nrmfiles(qw(ONE TWO THREE FOUR));\n\n# Test parallelism with included files.  Here we sleep/echo while\n# building the included files, to test that they are being built in\n# parallel.\nrun_make_test(q!\nall: 1 2; @#HELPER# out success\n-include 1.inc 2.inc\n.RECIPEPREFIX := >\n1.inc:\n> @#HELPER# file ONE.inc wait THREE.inc file TWO.inc\n> @echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@\n2.inc:\n> @#HELPER# wait ONE.inc file THREE.inc\n> @echo '2: ; @#HELPER# wait ONE file THREE' > $@!,\n              \"-j4\",\n              \"file ONE.inc\\nwait ONE.inc\\nfile THREE.inc\\nwait THREE.inc\\nfile TWO.inc\\nfile ONE\\nwait ONE\\nfile THREE\\nwait THREE\\nfile TWO\\nsuccess\\n\", 0, 7);\nrmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));\n\n\n# Test parallelism with included files--this time recurse first and make\n# sure the jobserver works.\nrun_make_test(q!\nrecurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all\nall: 1 2; @#HELPER# out success\n\nINC = no\nifeq ($(INC),yes)\n-include 1.inc 2.inc\nendif\n\n1.inc: ; @#HELPER# file ONE.inc wait THREE.inc file TWO.inc; echo '1: ; @#HELPER# file ONE wait THREE file TWO' > $@\n2.inc: ; @#HELPER# wait ONE.inc file THREE.inc; echo '2: ; @#HELPER# wait ONE file THREE' > $@!,\n              \"-j4\",\n              \"file ONE.inc\\nwait ONE.inc\\nfile THREE.inc\\nwait THREE.inc\\nfile TWO.inc\\nfile ONE\\nwait ONE\\nfile THREE\\nwait THREE\\nfile TWO\\nsuccess\\n\", 0, 7);\nrmfiles(qw(ONE.inc TWO.inc THREE.inc ONE TWO THREE 1.inc 2.inc));\n\n# Grant Taylor reports a problem where tokens can be lost (not written back\n# to the pipe when they should be): this happened when there is a $(shell ...)\n# function in an exported recursive variable.  I added some code to check\n# for this situation and print a message if it occurred.  This test used\n# to trigger this code when I added it but no longer does after the fix.\n\nrun_make_test(q!\nexport HI = $(shell $($@.CMD))\nfirst.CMD = #HELPER# out hi\nsecond.CMD = #HELPER# sleep 4\n\n.PHONY: all first second\nall: first second\n\nfirst second: ; @#HELPER# out $@ sleep 1 out $@!,\n              '-j2', \"first\\nsleep 1\\nfirst\\nsecond\\nsleep 1\\nsecond\", 0);\n\n# Michael Matz <matz@suse.de> reported a bug where if make is running in\n# parallel without -k and two jobs die in a row, but not too close to each\n# other, then make will quit without waiting for the rest of the jobs to die.\n\nrun_make_test(q!\n.PHONY: all fail.1 fail.2 fail.3 ok\nall: fail.1 ok fail.2 fail.3\n\nfail.1: ; @#HELPER# -q sleep 1 out $@ file fail.1 fail 1\nfail.2: ; @#HELPER# -q sleep 2 out $@ wait fail.1 file fail.2 fail 1\nfail.3: ; @#HELPER# -q sleep 3 out $@ wait fail.2 file fail.3 fail 1\n\nok: ; @#HELPER# -q sleep 4 wait fail.3 out OK!,\n              '-rR -j5', \"fail.1\n#MAKE#: *** [#MAKEFILE#:5: fail.1] Error 1\n#MAKE#: *** Waiting for unfinished jobs....\nfail.2\n#MAKE#: *** [#MAKEFILE#:6: fail.2] Error 1\nfail.3\n#MAKE#: *** [#MAKEFILE#:7: fail.3] Error 1\nOK\",\n             512);\n\nrmfiles(qw(fail.1 fail.2 fail.3));\n\n# Test for Savannah bug #15641.\n#\nrun_make_test('\n.PHONY: all\nall:; @:\n\n-include foo.d\n\nfoo.d: comp ; @#HELPER# out $@\n\ncomp: mod_a.o mod_b.o; @:\n\nmod_a.o mod_b.o: ; @#HELPER# fail 1\n', '-j2', \"fail 1\\nfail 1\\n\");\n\n\n# TEST #9 -- Savannah bugs 3330 and 15919\n# In earlier versions of make this will either give the wrong answer, or hang.\n\nutouch(-10, 'target');\nrun_make_test('target: intermed ; #HELPER# file $@\n\n.INTERMEDIATE: intermed\nintermed: | phony ; #HELPER# file $@\n\n.PHONY: phony\nphony: ; : phony', '-rR -j', ': phony');\nrmfiles('target');\n\n# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec\n# See Savannah bug #33873\n\n$ENV{MAKEFLAGS} = '-j4';\n\nrun_make_test(q!\nthings = thing1 thing2\nall: $(things)\nthing1:; @#HELPER# wait thing2start file $@start wait thing2end out $@end\nthing2:; @#HELPER# file $@start wait thing1start file $@end\n-include inc.mk\ninc.mk: ; @touch $@\n!,\n              '', \"file thing2start\\nwait thing2start\\nfile thing1start\\nwait thing1start\\nfile thing2end\\nwait thing2end\\nthing1end\\n\");\n\nrmfiles(qw(inc.mk thing1start thing1end thing2start thing2end));\n\n# Ensure intermediate/secondary files are not pruned incorrectly.\n# See Savannah bug #30653\n\nutouch(-15, 'file2');\nutouch(-10, 'file4');\nutouch(-5,  'file1');\n\nrun_make_test(q!\n.INTERMEDIATE: file3\nfile4: file3 ; @mv -f $< $@\nfile3: file2 ; touch $@\nfile2: file1 ; @touch $@\n!,\n              '--no-print-directory -j2', \"touch file3\");\n\nrmfiles('file1', 'file2', 'file3', 'file4');\n\n# Ensure that the jobserver is preserved across make re-exec.\n\nrun_make_test(q!\nall: one two\none: ;@ #HELPER# wait TWO file ONE\ntwo: ;@ #HELPER# file TWO\ninclude fff1.mk\nfff1.mk: ; touch $@\n!,\n              '-j2', \"touch fff1.mk\\nfile TWO\\nwait TWO\\nfile ONE\\n\");\n\nrmfiles('fff1.mk', 'ONE', 'TWO');\n\n# Test if a sub-make needs to re-exec and the makefile is built via\n# sub-make.  Reported by Masahiro Yamada <yamada.masahiro@socionext.com>\n\nrun_make_test(q!\nall: ; @$(MAKE) -f #MAKEFILE# recurse\n\nrecurse: one two ; @#HELPER# out $@\none: ;@ #HELPER# wait TWO file ONE\ntwo: ;@ #HELPER# file TWO\n\nmkinclude: ; touch fff1.mk\n\nifeq ($(MAKECMDGOALS),recurse)\ninclude fff1.mk\nfff1.mk: ; @$(MAKE) -f #MAKEFILE# mkinclude\nendif\n!,\n              '--no-print-directory -j2', \"touch fff1.mk\\nfile TWO\\nwait TWO\\nfile ONE\\nrecurse\\n\");\n\nrmfiles('fff1.mk', 'ONE', 'TWO');\n\n\n# Make sure that all jobserver FDs are closed if we need to re-exec the\n# master copy.\n#\n# First, find the \"default\" file descriptors we normally use\n# Then make sure they're still used.\n#\n# Right now we don't have a way to run a makefile and capture the output\n# without checking it, so we can't really write this test.\n\n# run_make_test('\n# submake: ; @$(MAKE) --no-print-directory -f #MAKEFILE# fdprint 5>output\n\n# dependfile: ; @echo FOO=bar > $@\n\n# INCL := true\n\n# FOO=foo\n# ifeq ($(INCL),true)\n# -include dependfile\n# endif\n\n# fdprint: ; @echo $(filter --jobserver%,$(MAKEFLAGS))\n\n# recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# submake INCL=true',\n#               '-j2 INCL=false fdprint',\n#               'bar');\n\n# rmfiles(qw(dependfile output));\n\n\n# # Do it again, this time where the include is done by the non-master make.\n# run_make_test(undef, '-j2 recurse INCL=false', 'bar');\n\n# rmfiles(qw(dependfile output));\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/patspecific_vars",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test pattern-specific variable settings.\";\n\n$details = \"\\\nCreate a makefile containing various flavors of pattern-specific variable\nsettings, override and non-override, and using various variable expansion\nrules, semicolon interference, etc.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<'EOF';\nall: one.x two.x three.x\nFOO = foo\nBAR = bar\nBAZ = baz\none.x: override FOO = one\n%.x: BAR = two\nt%.x: BAR = four\nthr% : override BAZ = three\none.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ)\nfour.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ)\nbaz: ; @echo $@: $(FOO) $(BAR) $(BAZ)\n\n# test matching multiple patterns\na%: AAA = aaa\n%b: BBB = ccc\na%: BBB += ddd\n%b: AAA ?= xxx\n%b: AAA += bbb\n.PHONY: ab\nab: ; @echo $(AAA); echo $(BBB)\nEOF\n\nclose(MAKEFILE);\n\n\n# TEST #1 -- basics\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n$answer = \"one.x: one two baz\\ntwo.x: foo four baz\\nthree.x: foo four three\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST #2 -- try the override feature\n\n&run_make_with_options($makefile, \"BAZ=five\", &get_logfile);\n$answer = \"one.x: one two five\\ntwo.x: foo four five\\nthree.x: foo four three\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST #3 -- make sure patterns are inherited properly\n\n&run_make_with_options($makefile, \"four.x\", &get_logfile);\n$answer = \"baz: foo two baz\\nfour.x: foo two baz\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST #4 -- test multiple patterns matching the same target\n\n&run_make_with_options($makefile, \"ab\", &get_logfile);\n$answer = \"aaa bbb\\nccc ddd\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# TEST #5 -- test pattern-specific exported variables\n#\nrun_make_test('\n/%: export foo := foo\n\n/bar:\n\t@echo $(foo) $$foo\n', '', 'foo foo');\n\n\n# TEST #6 -- test expansion of pattern-specific simple variables\n#\nrun_make_test('\n.PHONY: all\n\nall: inherit := good $$t\nall: bar baz\n\nb%: pattern := good $$t\n\nglobal := original $$t\n\n\n# normal target\n#\nifdef rec\nbar: a = global: $(global) pattern: $(pattern) inherit: $(inherit)\nelse\nbar: a := global: $(global) pattern: $(pattern) inherit: $(inherit)\nendif\n\nbar: ; @echo \\'normal: $a;\\'\n\n\n# pattern target\n#\nifdef rec\n%z: a = global: $(global) pattern: $(pattern) inherit: $(inherit)\nelse\n%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit)\nendif\n\n%z: ; @echo \\'pattern: $a;\\'\n\n\nglobal := new $$t\n',\n'',\n'normal: global: original $t pattern:  inherit: ;\npattern: global: original $t pattern:  inherit: ;');\n\n\n# TEST #7 -- test expansion of pattern-specific recursive variables\n#\nrun_make_test(undef, # reuse previous makefile\n'rec=1',\n'normal: global: new $t pattern: good $t inherit: good $t;\npattern: global: new $t pattern: good $t inherit: good $t;');\n\n# TEST #8: override in pattern-specific variables\n\nrun_make_test('\na%: override FOO += f1\na%: FOO += f2\nab: ; @echo \"$(FOO)\"\n',\n              '', \"f1\\n\");\n\nrun_make_test(undef, 'FOO=C', \"C f1\\n\");\n\n# TEST #9: Test shortest stem selection in pattern-specific variables.\n\nrun_make_test('\n%-mt.x: x := two\n%.x: x := one\n\nall: foo.x foo-mt.x\n\nfoo.x: ;@echo $x\nfoo-mt.x: ;@echo $x\n',\n'',\n\"one\\ntwo\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/patternrules",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test pattern rules.\";\n\n$details = \"\";\n\nuse Cwd;\n\n$dir = cwd;\n$dir =~ s,.*/([^/]+)$,../$1,;\n\n\n# TEST #0: Make sure that multiple patterns where the same target\n#          can be built are searched even if the first one fails\n#          to match properly.\n#\n\nrun_make_test(q!\n.PHONY: all\n\nall: case.1 case.2 case.3 case.4\n\n# We can't have this, due to \"Implicit Rule Search Algorithm\" step 5c\n#xxx: void\n\n# 1 - existing file\n%.1: void ; @exit 1\n%.1: #MAKEFILE# ; @exit 0\n\n# 2 - phony\n%.2: void ; @exit 1\n%.2: 2.phony ; @exit 0\n.PHONY: 2.phony\n\n# 3 - implicit-phony\n%.3: void ; @exit 1\n%.3: 3.implicit-phony ; @exit 0\n\n3.implicit-phony:\n\n# 4 - explicitly mentioned file made by an implicit rule\n%.4: void ; @exit 1\n%.4: test.x ; @exit 0\n%.x: ;\n!,\n              '', '');\n\n# TEST #1: make sure files that are built via implicit rules are marked\n#          as targets (Savannah bug #12202).\n#\nrun_make_test('\nTARGETS := foo foo.out\n\n.PHONY: all foo.in\n\nall: $(TARGETS)\n\n%: %.in ; @echo $@\n\n%.out: % ; @echo $@\n\nfoo.in: ; @:\n\n',\n              '', \"foo\\nfoo.out\");\n\n\n# TEST #2: make sure intermediate files that also happened to be\n#          prerequisites are not removed (Savannah bug #12267).\n#\nrun_make_test('\n$(dir)/foo.o:\n\n$(dir)/foo.y: ; @echo $@\n\n%.c: %.y ; touch $@\n\n%.o: %.c ; @echo $@\n\n.PHONY: install\ninstall: $(dir)/foo.c\n\n',\n              \"dir=$dir\", \"$dir/foo.y\\ntouch $dir/foo.c\\n$dir/foo.o\");\n\nunlink(\"$dir/foo.c\");\n\n\n# TEST #3: make sure precious flag is set properly for targets\n#          that are built via implicit rules (Savannah bug #13218).\n#\nrun_make_test('\n.DELETE_ON_ERROR:\n\n.PRECIOUS: %.bar\n\n%.bar:; @touch $@ && exit 1\n\n$(dir)/foo.bar:\n\n',\n              \"dir=$dir\",\n              \"#MAKE#: *** [#MAKEFILE#:6: $dir/foo.bar] Error 1\", 512);\n\nunlink(\"$dir/foo.bar\");\n\n\n# TEST #4: make sure targets of a matched implicit pattern rule are\n#          never considered intermediate (Savannah bug #13022).\n#\nrun_make_test('\n.PHONY: all\nall: foo.c foo.o\n\n%.h %.c: %.in ; touch $*.h ; touch $*.c\n\n%.o: %.c %.h ; echo $+ >$@\n\n%.o: %.c ; @echo wrong rule\n\nfoo.in: ; touch $@\n\n',\n              '', \"touch foo.in\\ntouch foo.h ; touch foo.c\\necho foo.c foo.h >foo.o\\nrm foo.h\");\n\nunlink('foo.in', 'foo.h', 'foo.c', 'foo.o');\n\n# TEST #5: make sure both prefix and suffix patterns work with multiple\n#          target patterns (Savannah bug #26593).\n#\nrun_make_test('\nall: foo.s1 foo.s2 p1.foo p2.foo\n\np1.% p2.%: %.orig ; @echo $@\n%.s1 %.s2: %.orig ; @echo $@\n\n.PHONY: foo.orig\n',\n              '', \"foo.s1\\np1.foo\\n\");\n\n# TEST 6: Make sure that non-target files are still eligible to be created\n# as part of implicit rule chaining.  Savannah bug #17752.\n\nrun_make_test(sprintf(q!\nBIN = xyz\nCOPY = $(BIN).cp\nSRC = $(BIN).c\nallbroken: $(COPY) $(BIN) ; @echo ok\n$(SRC): ; @echo 'main(){}' > $@\n%%.cp: %% ; @cp $< $@\n%% : %%.c ; @cp $< $@\nclean: ; @%s $(SRC) $(COPY) $(BIN)\n!, $CMD_rmfile),\n              '', \"ok\\n\");\n\nunlink(qw(xyz xyz.cp xyz.c));\n\n# TEST 7: Make sure that all prereqs of all \"also_make\" targets get created\n# before any of the things that depend on any of them.  Savannah bug #19108.\n\nrun_make_test(q!\nfinal: x ; @echo $@\nx: x.t1 x.t2 ; @echo $@\nx.t2: dep\ndep: ; @echo $@\n%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2\n!,\n              '', \"dep\\nx.t1\\nx.t2\\nx\\nfinal\\n\");\n\n\n# TEST 8: Verify we can remove pattern rules.  Savannah bug #18622.\n\nmy @f = (qw(foo.w foo.ch));\ntouch(@f);\n\nrun_make_test(q!\nCWEAVE := :\n\n# Disable builtin rules\n%.tex : %.w\n%.tex : %.w %.ch\n!,\n              'foo.tex',\n              \"#MAKE#: *** No rule to make target 'foo.tex'.  Stop.\", 512);\n\nunlink(@f);\n\n# TEST #9: Test shortest stem selection in pattern rules.\n\nrun_make_test('\n%.x: ;@echo one\n%-mt.x: ;@echo two\n\nall: foo.x foo-mt.x\n',\n              '', \"one\\ntwo\");\n\n# Test pattern rules building the same targets\n# See SV 54233.\n\ntouch('a.c');\n\n# a.lnk isn't listed as removed, because it's not actually created\nrun_make_test(q!\nall: a.elf a.dbg\n\n%.elf %.lnk: %.c ; : $*.elf $*.lnk\n\n%.elf %.dbg: %.lnk ; : $*.elf $*.dbg\n!,\n    '-j2', \": a.elf a.lnk\\n: a.elf a.dbg\\n\");\n\n# SV 60435 : a.lnk is removed, because it is intermediate.\nrun_make_test(q!\nall: a.elf a.dbg\n\n%.elf %.lnk: %.c ; touch $*.elf $*.lnk\n\n%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg\n!,\n              '-j2', \"touch a.elf a.lnk\\ntouch a.elf a.dbg\\nrm a.lnk\\n\");\n\nunlink('a.elf', 'a.dbg');\n\n# SV 60435 : a.lnk is not intermediate, because it is explicitly mentioned.\nrun_make_test(q!\nall: a.elf a.dbg\n\n%.elf %.lnk: %.c ; touch $*.elf $*.lnk\n\n%.elf %.dbg: %.lnk ; touch $*.elf $*.dbg\n\ninstall: a.lnk\n.PHONY: install\n!,\n              '-j2', \"touch a.elf a.lnk\\ntouch a.elf a.dbg\\n\");\n\nunlink('a.c', 'a.elf', 'a.dbg', 'a.lnk');\n\n# SV 56655: Test patterns matching files containing whitespace\ntouch('some file.yy');\nrun_make_test(q!\n%.xx : %.yy ; @echo matched\n!,\n              '\"some file.xx\"', \"matched\\n\");\n\nunlink('some file.xx', 'some file.yy');\n\n\n# sv 60188.\n# Test that a file explicitly mentioned by the user and made by an implicit\n# rule is not considered intermediate.\n\ntouch('hello.z');\nunlink('hello.x', 'test.x');\n\n# subtest 1\n# hello.x is not explicitly mentioned and thus is an intermediate file.\nrun_make_test(q!\nall: hello.z\n%.z: %.x ; touch $@\n%.x: ;\n!,\n              '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# subtest 2\n# test.x is explicitly mentioned and thus is not an intermediate file.\nrun_make_test(q!\nall: hello.z\n%.z: %.x test.x ; touch $@\n%.x: ;\n!,\n              '', \"touch hello.z\");\n\n# subtest 3\n# hello.x is explicitly mentioned on an unrelated rule and thus is not an\n# intermediate file.\ntouch('hello.z');\nrun_make_test(q!\nall: hello.z\n%.z: %.x; touch $@\n%.x: ;\nunrelated: hello.x\n!,\n              '', \"touch hello.z\");\n\nunlink('hello.z');\n\n# sv 60188.\n# Test that a file explicitly mentioned by the user and made by an implicit\n# rule is not considered intermediate, even when the builtin rules are used.\n\ntouch('hello.x');\ntouch('test.x');\ntouch('hello.tsk');\n\n# subtest 1\n# hello.o is not explicitly mentioned and thus is an intermediate file.\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.z ; @echo $@\n%.z : %.x ; @echo $@\n!,\n              '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# subtest 2\n# test.z is explicitly mentioned and thus is not an intermediate file.\n# test.z is built first because until it's built we don't know if we\n# need to rebuild the intermediate hello.z\nrun_make_test(q!\nall: hello.tsk\n%.tsk: %.z test.z ; @echo $@\n%.z : %.x ; @echo $@\n!,\n              '', \"test.z\\nhello.z\\nhello.tsk\\n\");\n\n# subtest 3\n# hello.o is not explicitly mentioned and thus is an intermediate file.\nrun_make_test(q!\nall: hello.tsk\ndep:=%.o\n%.tsk: $(dep) ; @echo $@\n!,\n              '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# subtest 4\n# Even when test.z is constructed from 2 variables it is still explicitly\n# mentioned and thus is not an intermediate file.\n# test.z is built first because until it's built we don't know if we\n# need to rebuild the intermediate hello.z\nrun_make_test(q!\nall: hello.tsk\nname:=test\nsuf:=.z\n%.tsk: %.z $(name)$(suf) ; @echo $@\n%.z: %.x ; @echo $@\n!,\n              '', \"test.z\\nhello.z\\nhello.tsk\\n\");\n\nunlink('hello.x', 'test.x', 'hello.tsk');\n\n# Test that chained pattern rules with multiple targets remove all intermediate\n# files.\n# sv 60435.\n\n# subtest 1.\n# a.1 and a.2 are intermediate and should be removed.\n\nrun_make_test(q!\na.4:\n%.4: %.1 %.15 ; cat $^ >$@\n%.1 %.15: ; touch $*.1 $*.15\n!,\n              '', \"touch a.1 a.15\\ncat a.1 a.15 >a.4\\nrm a.15 a.1\");\n\nunlink('a.4');\n\n# subtest 2.\n# a.1 and a.2 are intermediate and should be removed.\n# a.3 is explicit and should not be removed.\nrun_make_test(q!\na.4:\n%.4: %.1 %.15 a.3 ; cat $^ >$@\n%.1 %.15: ; touch $*.1 $*.15\n%.3: ; touch $@\n!,\n              '', \"touch a.3\\ntouch a.1 a.15\\ncat a.1 a.15 a.3 >a.4\\nrm a.15 a.1\");\n\nunlink('a.3', 'a.4');\n\n# subtest 3.\n# a.1 and a.2 are intermediate and should be removed.\n# a.3 is explicit and should not be removed.\nrun_make_test(q!\na.4:\n%.4: %.1 %.15 a.3 ; cat $^ >$@\n%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3\n!,\n              '', \"touch a.1 a.15 a.3\\ncat a.1 a.15 a.3 >a.4\\nrm a.15 a.1\");\n\nunlink('a.3', 'a.4');\n\n# subtest 4.\n# a.1 and a.2 are intermediate and should be removed.\n# a.3 is explicit and should not be removed.\nrun_make_test(q!\na.4:\n%.4: %.1 %.15 a.3 ; cat $^ >$@\n%.3 %.1 %.15: ; touch $*.1 $*.15 $*.3\n!,\n              '', \"touch a.1 a.15 a.3\\ncat a.1 a.15 a.3 >a.4\\nrm a.15 a.1\");\n\nunlink('a.3', 'a.4');\n\n# subtest 5.\n# a.1 and a.2 are intermediate and should be removed.\n# a.3 is explicit and should not be removed.\nrun_make_test(q!\na.4:\n%.4: a.3 %.1 %.15 ; cat $^ >$@\n%.1 %.15 %.3: ; touch $*.1 $*.15 $*.3\n!,\n              '', \"touch a.1 a.15 a.3\\ncat a.3 a.1 a.15 >a.4\\nrm a.15 a.1\");\n\nunlink('a.3', 'a.4');\n\n# subtest 6.\n# a.2 is intermediate and should be removed.\n# a.1 is mentioned explicitly on an unrelated rule and should not be removed.\nrun_make_test(q!\na.3:\n%.3: %.1 %.2 ; cat $^ >$@\n%.1 %.2: ; touch $*.1 $*.2\ninstall: a.1\n.PHONY: install\n!,\n              '', \"touch a.1 a.2\\ncat a.1 a.2 >a.3\\nrm a.2\");\n\nunlink('a.1', 'a.3');\n\n# Test removal of intermediate files.\n\n# subtest 1.\n# hello.x is removed, because it is intermediate.\nrun_make_test(q!\nhello.tsk:\n%.tsk: %.x; touch $@\n%.x: ; touch $@\n!,\n              '', \"touch hello.x\\ntouch hello.tsk\\nrm hello.x\");\n\nunlink('hello.tsk');\n\n# subtest 2.\n# Even though hello.x is intermediate, it is not removed, because it is not\n# created.\ntouch('hello.x');\n\nrun_make_test(q!\nhello.tsk:\n%.tsk: %.x; touch $@\n%.x: ; touch $@\n!,\n              '', \"touch hello.tsk\");\n\nunlink('hello.x', 'hello.tsk');\n\n# subtest 2.\n# Even though hello.x is intermediate, it is not removed, because it is not\n# created.\nrun_make_test(q!\nhello.tsk:\n%.tsk: %.x; touch $@\n%.x: ; : $@\n!,\n              '', \": hello.x\\ntouch hello.tsk\");\n\nunlink('hello.tsk');\n\n# A target explicitly listed as a prerequisite of a pattern rule, is still\n# considered mentioned and \"ought to exist\".\n\nrun_make_test(q!\n1.all: 1.q ; touch $@\n%.q: 1.r ; touch $@\n%.r: ; touch $@\n!,\n              '', \"touch 1.r\\ntouch 1.q\\ntouch 1.all\\n\");\n\nunlink('1.all', '1.q', '1.r');\n\n# SV 63098: Verify that missing also_made in pattern rules gives a warning but\n# doesn't fail.\n\nrun_make_test(q!\n%a %b : ; touch $*a\n!,\n              'gta', \"touch gta\\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'gtb'\\n\");\nunlink(qw(gta));\n\n# We don't warn if we didn't update the file\nutouch(-10, qw(gta));\nrun_make_test(q!\n%a %b : xyzzy ; $(OP)\nxyzzy: ;\nifdef RUN\nOP = @echo no\nendif\n!,\n              '-rR gta', \"#MAKE#: 'gta' is up to date.\\n\");\n\nrun_make_test(undef, '-rR gta RUN=1', \"no\\n\");\nunlink(qw(gta));\n\nrun_make_test(q!\nall:;\ninclude gta\n%a %b : ; touch $*a\n!,\n              '', \"touch gta\\n#MAKEFILE#:4: warning: pattern recipe did not update peer target 'gtb'\\n#MAKE#: 'all' is up to date.\");\nunlink(qw(gta));\n\nrun_make_test(q!\n%.c %.h : %.y; touch $*.c\n%.o: %.c; touch $@\nfoo.y: ; touch $@\n!,\n              'foo.o', \"touch foo.y\\ntouch foo.c\\n#MAKEFILE#:2: warning: pattern recipe did not update peer target 'foo.h'\\ntouch foo.o\\nrm foo.c\");\nunlink(qw(foo.y foo.c foo.o));\n\nif (0) {\n# SV 12078: Missing grouped pattern peer causes remake regardless of which\n# target caused the rule to run.\ntouch(qw(gta));  # but not gtb\nrun_make_test(q!\n%a %b : ; touch $*a $*b\n!,\n              'gta', \"touch gta gtb\\n\");\nunlink(qw(gta gtb));\n\n# Ensure both goal targets are built if they depend on a grouped pattern\ntouch(qw(gta));  # but not gtb\nrun_make_test(q!\nx y: ; touch $@\n\nx: gta\ny: gtb\n\n%a %b : ; touch $*a $*b\n!,\n              'x y', \"touch gta gtb\\ntouch x\\ntouch y\\n\");\n\n# Now everything should be up to date\nrun_make_test(undef, 'x y',\n              \"#MAKE#: 'x' is up to date.\\n#MAKE#: 'y' is up to date.\");\n\nunlink(qw(x y gta gtb));\n\n# sv 12078 : make sure we notice when all targets need to be rebuilt\n# a.1st exists but b.1st doesn't: make sure a.2nd is out of date as well\n\nutouch(-20, 'a.1st');\nutouch(-10, 'a.2nd', 'b.2nd');\n\nrun_make_test(q!\n1st := a.1st b.1st\n2nd := ${1st:.1st=.2nd}\n.PHONY: all\nall: ${2nd}\na.% b.% : ; touch a.$* b.$*\n${2nd}: %.2nd: %.1st ; cp $< $@\n!\n              , '', \"touch a.1st b.1st\\ncp a.1st a.2nd\\ncp b.1st b.2nd\\n\");\n\nunlink(qw(a.1st b.1st a.2nd b.2nd));\n\n# Variation: b.1st exists but is newer\n\nutouch(-20, 'a.1st');\nutouch(-10, 'a.2nd', 'b.2nd');\ntouch(qw(b.1st));\n\nrun_make_test(undef, '', \"cp b.1st b.2nd\\n\");\n\nunlink(qw(a.1st b.1st a.2nd b.2nd));\n}\n\n# sv 62206.\n\n# The following combinations are generated with and without second expansion.\n# 1.\n# all: bye.x\n# %.x: ...\n#\n# 2.\n# all: lib/bye.x\n# %.x: ...\n#\n# 3.\n# all: lib/bye.x\n# lib/%.x: ...\n#\n# The following combination is not generated, because there is no rule to\n# build bye.x, no stem substitution takes place, not of interest of this test.\n# 4.\n# all: bye.x\n# lib/%.x: ...\n\nmy @dir = ('', 'lib/'); # With and without last slash.\nmy @secondexpansion = ('', '.SECONDEXPANSION:');\n\nfor my $se (@secondexpansion) {\nfor my $d (@dir) { # The directory of the prerequisite of 'all'.\nfor my $r (@dir) { # The directory of the target in the rule definition.\n(!$d && $r) && next; # Combination 4.\nmy $dollar = $se ? '$' : '';\n\n# The prerequisite should only have directory if the prerequisite of 'all' has\n# it and if the prerequisite pattern in the rule definition does not have it.\n# That is combination 2.\nmy $pdir = $d && !$r ? $d : '';\n\nmy $prereqs = \"${pdir}bye.1\";\n\n# One func, one %.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(firstword %.1); \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2\";\n\n# Multiple funcs, each has one %.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(firstword %.1) $dollar\\$(firstword %.2); \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4\";\n\n# Multiple funcs, each has multiple %.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(wordlist 1, 99, %.1 %.2) $dollar\\$(wordlist 1, 99, %.3 %.4); \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4\";\n\n# Nested functions.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(wordlist 1, 99, $dollar\\$(wordlist 1, 99, %.1 %.2)) $dollar\\$(wordlist 1, 99, $dollar\\$(wordlist 1,99, %.3 %.4)); \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n$prereqs = \"${pdir}bye1%2% ${pdir}bye ${pdir}3bye4%5 ${pdir}6bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% ${pdir}11bye12 13\";\n\n# Multiple funcs, each has multiple words, each word has multiple %, sole %,\n# various corner cases.\n# Make should substitute the first % and only the first % in each word with the\n# stem.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\\$(wordlist 1, 99, %10% 11%12) 13; \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\nif ($port_type eq 'UNIX') {\n# Test that make does not use some hardcoded array of a finite size on stack.\n# Long prerequisite name. This prerequisite name is over 66K long.\nmy $prefix = 'abcdefgh' x 128 x 33; # 33K long.\nmy $suffix = 'stuvwxyz' x 128 x 33; # 33K long.\n$prereqs = \"${pdir}${prefix}bye${suffix}.1 ${pdir}${prefix}bye${suffix}.2\";\n\nrun_make_test(\"\n$se\nall: ${d}bye.x\n$r%.x: $dollar\\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \\$(info \\$@ from \\$^)\n.PHONY: $prereqs\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n}\n\n}\n}\n}\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/quoting",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test using \\n\" .\n               \"quotes within makefiles.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<'EOM';\nTEXFONTS = NICEFONT\nDEFINES = -DDEFAULT_TFM_PATH=\\\".:$(TEXFONTS)\\\"\ntest: ; @\"echo\" 'DEFINES = $(DEFINES)'\nEOM\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n\n\n# Create the answer to what should be produced by this Makefile\n$answer = 'DEFINES = -DDEFAULT_TFM_PATH=\\\".:NICEFONT\\\"' . \"\\n\";\n\n# COMPARE RESULTS\n\n&compare_output($answer,&get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/recursion",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test recursion.\";\n\n$details = \"DETAILS\";\n\n# Test some basic recursion.\nrun_make_test('\n.RECIPEPREFIX := |\nall:\n|       $(MAKE) -f #MAKEFILE# foo\nfoo:\n|       @echo $(MAKE)\n|       @echo MAKELEVEL = $(MAKELEVEL)\n|       $(MAKE) -f #MAKEFILE# last\nlast:\n|       @echo $(MAKE)\n|       @echo MAKELEVEL = $(MAKELEVEL)\n|       @echo THE END\n',\n              ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')),\n              ($vos\n               ? \"#MAKE#: Entering directory '#PWD#'\nmake 'CFLAGS=-O' -f #MAKEFILE# foo\nmake CFLAGS=-O\nMAKELEVEL = 0\nmake 'CFLAGS=-O' -f #MAKEFILE# last\nmake CFLAGS=-O\nMAKELEVEL = 0\nTHE END\n#MAKE#: Leaving directory '#PWD#'\"\n               : \"#MAKE#: Entering directory '#PWD#'\n#MAKEPATH# -f #MAKEFILE# foo\n#MAKE#[1]: Entering directory '#PWD#'\n#MAKEPATH#\nMAKELEVEL = 1\n#MAKEPATH# -f #MAKEFILE# last\n#MAKE#[2]: Entering directory '#PWD#'\n#MAKEPATH#\nMAKELEVEL = 2\nTHE END\n#MAKE#[2]: Leaving directory '#PWD#'\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#: Leaving directory '#PWD#'\"));\n\n\n# Test command line overrides.\nrun_make_test('\nrecur: all ; @$(MAKE) --no-print-directory -f #MAKEFILE# a=AA all\nall: ; @echo \"MAKEOVERRIDES = $(MAKEOVERRIDES)\"\n',\n              'a=ZZ',\n              'MAKEOVERRIDES = a=ZZ\nMAKEOVERRIDES = a=AA\n');\n\n# SV 46013: Ensure that MAKEOVERRIDES is passed even if set in the makefile\nrun_make_test(q!\nifeq ($(MAKELEVEL),0)\nMAKEOVERRIDES += FOO+=bar\nendif\n.PHONY: M R\nM: ; @$(MAKE) --no-print-directory -f #MAKEFILE# R\nR: ; @echo '$(FOO)'\n!,\n              '', 'bar');\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/reinvoke",
    "content": "#                                                              -*-mode: perl-*-\n\n$description = \"Test GNU Make's auto-reinvocation feature.\";\n\n$details = \"\\\nIf the makefile or one it includes can be rebuilt then it is, and make\nis reinvoked.  We create a rule to rebuild the makefile from a temp\nfile, then touch the temp file to make it newer than the makefile.\";\n\n$omkfile = $makefile;\n\n&utouch(-600, 'incl.mk');\n# For some reason if we don't do this then the test fails for systems\n# with sub-second timestamps, maybe + NFS?  Not sure.\n&utouch(-1, 'incl-1.mk');\n\nrun_make_test('\nall: ; @echo running rules.\n\n#MAKEFILE# incl.mk: incl-1.mk ; @echo rebuilding $@; echo >> $@\n\ninclude incl.mk',\n              '', \"rebuilding incl.mk\\nrunning rules.\\n\");\n\n# Make sure updating the makefile itself also works\n\n&utouch(-600, $omkfile);\n\nrun_make_test(undef, '', \"rebuilding #MAKEFILE#\\nrunning rules.\\n\");\n\n&rmfiles('incl.mk', 'incl-1.mk');\n\n\n# In this test we create an included file that's out-of-date, but then\n# the rule doesn't update it.  Make shouldn't re-exec.\n\n&utouch(-600, 'b','a');\n#&utouch(-10, 'a');\n&touch('c');\n\nrun_make_test('\nall: ; @echo hello\n\na : b ; echo >> $@\n\nb : c ; test -f $@ || echo >> $@\n\nc: ; echo >> $@\n\ninclude $(F)',\n              'F=a', \"test -f b || echo >> b\\nhello\\n\");\n\n# Now try with the file we're not updating being the actual file we're\n# including: this and the previous one test different parts of the code.\n\nrun_make_test(undef, 'F=b', \"test -f b || echo >> b\\nhello\\n\");\n\n&rmfiles('a','b','c');\n\n# Ensure command line variables are preserved properly across re-exec\n# Tests for Savannah bug #30723\n\nrun_make_test('\nifdef RECURSE\n-include foo30723\nendif\nrecurse: ; @$(MAKE) -f $(MAKEFILE_LIST) RECURSE=1 test\ntest: ; @echo F.O=$(F.O)\nfoo30723: ; @touch $@\n',\n              '--no-print-directory F.O=bar', \"F.O=bar\\n\");\n\nunlink('foo30723');\n\n# If ANY makefile is rebuilt then we should re-exec\n\nrun_make_test('\nall: ; @echo RESTARTS=$(MAKE_RESTARTS)\n\nm1.d: ; @echo $@; touch $@\n\nm2.d: m1.d ; @test -f $< || { echo $@; touch $@; }\n\ninclude m1.d\n-include m2.d\n',\n              '', \"m1.d\\nRESTARTS=1\\n\");\n\nunlink('m1.d', 'm2.d');\n\n# Same as before but be sure we get error messages for un-created makefiles\nrun_make_test('\nall: ; @echo RESTARTS=$(MAKE_RESTARTS)\n\nm1.d: ; @echo $@; touch $@\n\nm2.d: m1.d ; @test -f $< || { echo $@; touch $@; }\n\ninclude m1.d m2.d\n', '',\n              # This runs afoul of https://savannah.gnu.org/bugs/?61226\n              0 ? \"m1.d\\n#MAKEFILE#:8: m2.d: $ERR_no_such_file\"\n                  : \"m1.d\\nRESTARTS=1\",\n              0 ? 512 : 0);\n\nunlink('m1.d', 'm2.d');\n\n# sv 61226.\n# This set of four cases tests two aspects of make.\n#\n# 1. If a rule has no prerequisites or recipe, and the target of the rule is a\n# nonexistent file, then make imagines this target to have been updated\n# whenever its rule is run.\n#\n# 2. Make does not re-execute itself in this case of imagined target.\n#\n# Test case 1.\n# Make imagines hello.d was updated by a rule without recipe and without\n# prereqs.\n# This should succeed.\n# Make should not re-execute itself.\nrun_make_test('\nhello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))\nhello.d:\ninclude hello.d\n', '', \"RESTARTS=\\n#MAKE#: 'hello.o' is up to date.\");\n\n# Test case 2.\n# Make imagines hello.d was updated by a rule with a recipe and without\n# prereqs.\n# This should succeed.\n# Make should not re-execute itself.\nrun_make_test('\nhello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))\nhello.d:; $(info $@)\ninclude hello.d\n', '', \"hello.d\\nRESTARTS=\\n#MAKE#: 'hello.o' is up to date.\");\n\n&touch('hello.td');\n# Test case 3.\n# Make imagines hello.d was updated by a rule without a recipe and with\n# prereqs.\n# This should succeed.\n# Make should not re-execute itself.\nrun_make_test('\nhello.o: hello.d; $(info RESTARTS=$(MAKE_RESTARTS))\nhello.d: hello.td\ninclude hello.d\n', '', \"RESTARTS=\\n#MAKE#: 'hello.o' is up to date.\");\n\n# Test case 4.\n# Same test as three tests above, but the rule has both recipe and prereqs.\n# Make should report this error.\nrun_make_test('\nhello.o: hello.d; $(info $@)\nhello.d: hello.td; $(info $@)\ninclude hello.d\n', '',\n              # This runs afoul of https://savannah.gnu.org/bugs/?61226\n              0 ? \"hello.d\\n#MAKEFILE#:4: hello.d: $ERR_no_such_file\"\n                  : \"hello.d\\nhello.o\\n#MAKE#: 'hello.o' is up to date.\",\n              0 ? 512 : 0);\n\nunlink('hello.td');\n\n# Test SV 62088 : make sure we don't re-invoke for stdin makefiles.\n# The test framework doesn't seem to have a good way to do this.\n\ncreate_file('input.mk', \"all:;\\$(info all)\\n\");\n\nclose(STDIN);\nopen(STDIN, \"<\", 'input.mk') || die \"input.mk: $!\\n\";\n\nrun_make_test('', '-sf -', \"all\\n\");\n\n\n# This close MUST come at the end of the test!!\nclose(STDIN);\nunlink('input.mk');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/rule_glob",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test globbing in targets and prerequisites.\";\n\n$details = \"\";\n\ntouch(qw(a.one a.two a.three));\n\n# Test wildcards in regular targets and prerequisites\nrun_make_test(q{\n.PHONY: all a.one a.two a.three\nall: a.one* a.t[a-z0-9]o a.th[!q]ee\na.o[Nn][Ee] a.t*: ; @echo $@\n},\n              '', \"a.one\\na.two\\na.three\");\n\n# Test wildcards in pattern targets and prerequisites\nrun_make_test(q{\n.PHONY: all\nall: a.four\n%.four : %.t* ; @echo $@: $(sort $^)\n},\n              '', \"a.four: a.three a.two\");\n\n# Test wildcards in second expansion targets and prerequisites\nrun_make_test(q{\n.PHONY: all\nall: a.four\n.SECONDEXPANSION:\n%.four : $$(sort %.t*) ; @echo $@: $(sort $^)\n},\n              '', \"a.four: a.three a.two\");\n\nunlink(qw(a.one a.two a.three));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/se_explicit",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test second expansion in ordinary rules.\";\n\n$details = \"\";\n\n# TEST #0: Test handing of '$' in prerequisites with and without second\n# expansion.\n\n# If we don't support archives then the prerequisite is different\nmy $prereq = exists $FEATURES{'archives'} ? '$' : '$(PRE)';\n\nrun_make_test(q!\nifdef SE\n  .SECONDEXPANSION:\nendif\nfoo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^'\nPRE = one two\nbar$$baz: $$(PRE)\nbaraz: $$(PRE)\nPRE = three four\n.DEFAULT: ; @echo '$@'\n!,\n              '',\n              \"$prereq\\nbar\\$biz\\nfoo\\$bar : bar\\$baz bar\\$biz\");\n\nrun_make_test(undef, 'SE=1', \"three\\nfour\\nbariz\\nfoo\\$bar : baraz bariz\");\n\n# TEST #1: automatic variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nfoo: bar baz\n\nfoo: biz | buz\n\nfoo: $$@.1 \\\n     $$<.2 \\\n     $$(addsuffix .3,$$^) \\\n     $$(addsuffix .4,$$+) \\\n     $$|.5 \\\n     $$*.6\n\n!,\n'',\n'bar\nbaz\nbiz\nbuz\nfoo.1\nbar.2\nbar.3\nbaz.3\nbiz.3\nbar.4\nbaz.4\nbiz.4\nbuz.5\n.6\n');\n\n\n# Test #2: target/pattern -specific variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nfoo.x: $$a $$b\n\nfoo.x: a := bar\n\n%.x: b := baz\n!,\n'',\n'bar\nbaz\n');\n\n\n# Test #3: order of prerequisites.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nall: foo bar baz\n\n# Subtest #1\nfoo: foo.1; @:\nfoo: foo.2\nfoo: foo.3\n\n# Subtest #2\nbar: bar.2\nbar: bar.1; @:\nbar: bar.3\n\n# Subtest #3\nbaz: baz.1\nbaz: baz.2\nbaz: ; @:\n!,\n'',\n'foo.1\nfoo.2\nfoo.3\nbar.1\nbar.2\nbar.3\nbaz.1\nbaz.2\n');\n\n# TEST #4: eval in a context where there is no reading_file\nrun_make_test(q!\n.SECONDEXPANSION:\nall : $$(eval $$(info test))\n!,\n            '', \"test\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new\n# target/prereq relationships.\n\nrun_make_test(q!\n.SECONDEXPANSION:\nproj1.exe : proj1.o $$(eval $$(test))\ndefine test\nproj1.o : proj1.c\nproj1.c: proj1.h\nendef\n!,\n              '', \"#MAKE#: *** prerequisites cannot be defined in recipes.  Stop.\\n\", 512);\n\n\n# Automatic $$+ variable expansion issue.  Savannah bug #25780\nrun_make_test(q!\nall : foo foo\n.SECONDEXPANSION:\nall : $$+ ; @echo '$+'\nfoo : ;\n!,\n                  '', \"foo foo foo foo\\n\");\n\n\n# Automatic $$+ variable expansion issue.  Savannah bug #25780\nrun_make_test(q!\nall : bar bar\nbar : ;\nq%x : ;\n.SECONDEXPANSION:\na%l: q1x $$+ q2x ; @echo '$+'\n!,\n                  '', \"q1x bar bar q2x bar bar\\n\");\n\n\n# Allow patsubst shorthand in second expansion context.\n# Requires the colon to be quoted.  Savannah bug #16545\nrun_make_test(q!\n.PHONY: foo.bar\n.SECONDEXPANSION:\nfoo: $$(@\\\\:%=%.bar); @echo '$^'\n!,\n              '', \"foo.bar\\n\");\n\n# SV 54549 : Ensure we don't free used variable_sets\nrun_make_test(q!\nfoo: -lcat\n\n# Removing second expansion prevents segfault\n.SECONDEXPANSION:\nfoo: $$@.o ;\n\n# Having an empty command here prevents segfault unless,\n# the environment is empty. `env -i make foo`\n# MFLAGS=-w or MAKEFLAGS=-w `env MFLAGS=-w make foo`\n# libcat.a target calls an extra command, `@true \\n @touch $@`\n# odd.\n%.o: ; @true\n\n# Having an empty command prevents segfault.\n-l%: lib%.a ; @true\n\n# Not creating libcat.a here prevents segfault,\nlibcat.a: ; @touch $@\n!,\n              '', q!#MAKEFILE#:16: recipe was specified for file '-lcat' at #MAKEFILE#:16,\n#MAKEFILE#:16: but '-lcat' is now considered the same file as 'libcat.a'\n#MAKEFILE#:16: recipe for '-lcat' will be ignored in favor of the one for 'libcat.a'!);\nunlink('libcat.a');\n\n# SV 28456 : Don't reset $$< for default recipes\nrun_make_test(q!\n.SECONDEXPANSION:\n\n.PHONY: biz baz\nbiz: baz ;\nbiz: $$(info $$<)\n!,\n              '', \"baz\\n#MAKE#: Nothing to be done for 'biz'.\\n\");\n\n\n# sv 60659. Second expansion of automatic variables inside a function in the\n# prerequisite list.\n# $$@ expands to the target in the 1st and following rules.\n# $$<,$$^,$$+,$$|,$$?,$$*,$$% expand to the empty string in the prerequisite\n# list of the 1st rule.\n# $$<,$$^,$$+,$$|,$$?,$$*,$$% in the prerequisite list of the 2nd (and\n# following) rule expand to the values from the 1st rule.\n\n\n# subtest 1. Explicit rules. 1st rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n2.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 2. Explicit rules. 2nd rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 15.x 1.x\n15.x: 5.z 6.z 5.z | 7.z 7.z 8.z\n1.x: 1.z 2.z 2.z | 3.z 4.z\n15.x 1.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=\n@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 3. Grouped targets in explicit rules. 1st rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 15.x\n15.x 1.x&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=15.x,<=,^=,+=,|=,?=,*=,%=\n@=1.x,<=,^=,+=,|=,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 4. Grouped targets in explicit rules. 2nd rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 15.x 1.x\n15.x: 5.z 6.z 5.z | 7.z 7.z 8.z\n1.x: 1.z 2.z 2.z | 3.z 4.z\n15.x 1.x&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=,%=\n@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Double colon rules.\n# Because each double colon rule is independent of the other double colon rules\n# for the same target, each automatic variable in the prerequisite list, other\n# than $$@, second expands to the empty string in any rule, 1st, 2nd or later.\n\n# subtest 5. 1st double colon rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n2.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 6. 2nd double colon rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 15.x 1.x\n15.x:: 5.z 6.z 5.z | 7.z 7.z 8.z ;\n1.x:: 1.z 2.z 2.z | 3.z 4.z ;\n15.x 1.x:: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*,%=$$%) ;\n%.z: ;\n!, '',\n\"@=15.x,<=,^=,+=,|=,?=,*=,%=\n@=1.x,<=,^=,+=,|=,?=,*=,%=\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# sv 62324.\n# Integrity self check.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: bye.x\nbye.x: $$(firstword bye.1;\n!, '', \"#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'.  Stop.\", 512);\n\nunlink('hello.tsk', 'test.o', 'bye.tsk', 'hello.o', 'hello.h', 'hello.q', 'bye.c', 'bye.o');\n\n# sv 62706.\n# Test that makes avoids second expanding prerequisites of the targets which\n# are not built.\n# Here, hello.tsk is built and its prerequisites are second expanded.\n# bye.tsk is not built and its prerequisites are not second expanded.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Multiple rules per target.\nrun_make_test(q!\n.SECONDEXPANSION:\n\nall: hello.tsk\ndep1:=hello.o\ndep2:=hello.h\nhello.tsk: $$(dep1)\nhello.tsk: $$(dep2); $(info $@ from $^)\nhello.o:; $(info $@)\nhello.h:; $(info $@)\n!, 'hello.tsk',\n\"hello.h\nhello.o\nhello.tsk from hello.h hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Multiple targets per rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk bye.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk: bye.o $$(info second expansion of $$@ prereqs)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Grouped targets.\nrun_make_test(q!\n.SECONDEXPANSION:\nworld.tsk: world.o $$(info 1 second expansion of $$@ prereqs)\nhello.tsk world.tsk &: hello.o $$(info 2 second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nworld.o: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"2 second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\n2 second expansion of world.tsk prereqs\n1 second expansion of world.tsk prereqs\nsecond expansion of world.o prereqs\nworld.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Order only.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:| hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)\nbye.tsk:| bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)\nhello.o:| $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o:| $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Double colon. 1 rule per target.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk:: bye.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nhello.o:: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o:: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Double colon. 2 rules per targets.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:: hello.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)\nhello.tsk:: hello.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)\nbye.tsk:: bye.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)\nbye.tsk:: bye.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)\nhello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)\nhello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)\nbye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)\nbye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)\n!, 'hello.tsk',\n\"1 second expansion of hello.tsk prereqs\n1 second expansion of hello.o prereqs\n1 hello.o\n2 second expansion of hello.o prereqs\n2 hello.o\n1 hello.tsk from hello.o\n2 second expansion of hello.tsk prereqs\n2 hello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Test that the prerequisites of 'hello.tsk' are second expanded once.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: hello.tsk hello.q\nhello.tsk: hello.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nhello.q: hello.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)\n!, '',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\nsecond expansion of hello.q prereqs\nhello.q from hello.tsk\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# sv 62706.\n# Merge vpath file and local file.\n# Test that both sets of prerequisites from 'hello.c' rule and from\n# 'src/hello.c' rule are second expanded.\nrun_make_test(q!\n.SECONDEXPANSION:\nvpath hello.c src\nall: hello.c; $(info $@ from $^)\nhello.c: $$(info second expansion of hello.c prereqs); $(info 1 $@)\nsrc/hello.c: $$(info second expansion of src/hello.c prereqs); $(info 2 $@)\n!, '',\n\"#MAKEFILE#:5: recipe was specified for file 'hello.c' at #MAKEFILE#:5,\n#MAKEFILE#:5: but 'hello.c' is now considered the same file as 'src/hello.c'\n#MAKEFILE#:5: recipe for 'hello.c' will be ignored in favor of the one for 'src/hello.c'\nsecond expansion of src/hello.c prereqs\nsecond expansion of hello.c prereqs\n2 src/hello.c\nall from src/hello.c\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 62706.\n# .DEFAULT.\nrun_make_test(q!\n.SECONDEXPANSION:\nbye:=bye.c\nall: hello.o\n.DEFAULT: $$(info second expansion of prereqs of default recipe @ = $$@) ; $(info default recipe $@)\n!, '',\n\"default recipe hello.o\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.1');\n\n# sv 62706.\n# No side effects from second expansion of unrelated rules.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:; exit 1\nunrelated: $$(shell touch hello.1);\n!, '',\n\"exit 1\n#MAKE#: *** [#MAKEFILE#:3: hello.tsk] Error 1\\n\", 512);\n\n# sv 62706.\n# Second expansion of intermediate prerequisites.\n# The rule to build hello.x is explicit.\n# .SECONDARY marks hello.x as intermediate.\n# Test that $$(deps) is secondary expanded.\nrun_make_test(q!\ndeps:=hello.h\n.SECONDEXPANSION:\n.SECONDARY: hello.x\nall: hello.x\nhello.x: $$(deps); $(info $@)\nhello.h:; $(info $@)\n!, '', \"hello.h\\nhello.x\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/se_implicit",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test second expansion in implicit rules.\";\n\n$details = \"\";\n\nuse Cwd;\n\n$dir = cwd;\n$dir =~ s,.*/([^/]+)$,../$1,;\n\n\n# Test #1: automatic variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nfoo.a: bar baz\n\nfoo.a: biz | buz\n\nfoo.%: 1.$$@ \\\n       2.$$< \\\n       $$(addprefix 3.,$$^) \\\n       $$(addprefix 4.,$$+) \\\n       5.$$| \\\n       6.$$* ; @:\n\n1.foo.a \\\n2.bar \\\n3.bar \\\n3.baz \\\n3.biz \\\n4.bar \\\n4.baz \\\n4.biz \\\n5.buz \\\n6.a: ; @echo '$@'\n\n!,\n'',\n'1.foo.a\n2.bar\n3.bar\n3.baz\n3.biz\n4.bar\n4.baz\n4.biz\n5.buz\n6.a\nbar\nbaz\nbiz\nbuz\n');\n\n\n# Test #2: target/pattern -specific variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\nfoo.x:\n\nfoo.%: $$(%_a) $$(%_b) bar ; @:\n\nfoo.x: x_a := bar\n\n%.x: x_b := baz\n\nbar baz: ; @echo '$@'\n!,\n              '', \"bar\\nbaz\\n\");\n\n\n# Test #3: order of prerequisites.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nall: foo bar baz\n\n\n# Subtest #1\n#\n%oo: %oo.1; @:\n\nfoo: foo.2\n\nfoo: foo.3\n\nfoo.1: ; @echo '$@'\n\n\n# Subtest #2\n#\nbar: bar.2\n\n%ar: %ar.1; @:\n\nbar: bar.3\n\nbar.1: ; @echo '$@'\n\n\n# Subtest #3\n#\nbaz: baz.1\n\nbaz: baz.2\n\n%az: ; @:\n!,\n              '',\n'foo.1\nfoo.2\nfoo.3\nbar.1\nbar.2\nbar.3\nbaz.1\nbaz.2\n');\n\n\n# Test #4: stem splitting logic.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n$(dir)/tmp/bar.o:\n\n$(dir)/tmp/foo/bar.c: ; @echo '$@'\n$(dir)/tmp/bar/bar.c: ; @echo '$@'\nfoo.h: ; @echo '$@'\n\n%.o: $$(addsuffix /%.c,foo bar) foo.h ; @echo '$@: {$<} $^'\n!,\n              \"dir=$dir\", \"$dir/tmp/foo/bar.c\n$dir/tmp/bar/bar.c\nfoo.h\n$dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h\n\");\n\n\n# Test #5: stem splitting logic and order-only prerequisites.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n$(dir)/tmp/foo.o: $(dir)/tmp/foo.c\n$(dir)/tmp/foo.c: ; @echo '$@'\nbar.h: ; @echo '$@'\n\n%.o: %.c|bar.h ; @echo '$@: {$<} {$|} $^'\n\n!,\n              \"dir=$dir\", \"$dir/tmp/foo.c\nbar.h\n$dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c\n\");\n\n\n# Test #6: lack of implicit prerequisites.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\nfoo.o: foo.c\nfoo.c: ; @echo '$@'\n\n%.o: ; @echo '$@: {$<} $^'\n!,\n              '', \"foo.c\\nfoo.o: {foo.c} foo.c\\n\");\n\n\n# Test #7: Test stem from the middle of the name.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\nfoobarbaz:\n\nfoo%baz: % $$*.1 ; @echo '$*'\n\nbar bar.1: ; @echo '$@'\n!,\n              '', \"bar\\nbar.1\\nbar\\n\");\n\n\n# Test #8: Make sure stem triple-expansion does not happen.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\nfoo$$bar:\n\nf%r: % $$*.1 ; @echo '$*'\n\noo$$ba oo$$ba.1: ; @echo '$@'\n!,\n              '', 'oo$ba\noo$ba.1\noo$ba\n');\n\n# Test #9: Check the value of $^\nrun_make_test(q!\n.SECONDEXPANSION:\n\n%.so: | $$(extra) ; @echo $^\n\nfoo.so: extra := foo.o\nfoo.so:\nfoo.o:\n!,\n              '', \"\\n\");\n\n# Test #10: Test second expansion with second expansion prerequisites\n# Ensures pattern_search() recurses with SE prereqs.\ntouch('a');\nrun_make_test(q!\n.SECONDEXPANSION:\nsim_base_rgg := just_a_name\nsim_base_src := a\nsim_base_f := a a a\nsim_%.f: $${sim_$$*_f} ; echo $@\nsim_%.src: $${sim_$$*_src} ; echo $@\nsim_%: \\\n        $$(if $$(sim_$$*_src),sim_%.src) \\\n        $$(if $$(sim_$$*_f),sim_%.f) \\\n        $$(if $$(sim_$$*_rgg),$$(sim_$$*_rgg).s) ; echo $@\n!,\n              '-s sim_base', \"#MAKE#: *** No rule to make target 'sim_base'.  Stop.\", 512);\n\nunlink('a');\n\n# Ensure that order-only tokens embedded in second expansions are parsed\nrun_make_test(q!\n.SECONDEXPANSION:\nPREREQS=p1|p2\nP2=p2\nall : foo bar\nf%o: $$(PREREQS) ; @echo '$@' from '$^' and '$|'\nb%r: p1|$$(P2)   ; @echo '$@' from '$^' and '$|'\np% : ; : $@\n!,\n              \"\", \": p1\\n: p2\\nfoo from p1 and p2\\nbar from p1 and p2\\n\");\n\n# SV 28456 : Don't reset $$< for default recipes\nrun_make_test(q!\n.SECONDEXPANSION:\n\n.PHONY: foo bar\nfoo: bar\nfoo: $$(info $$<)\n%oo: ;\n!,\n              '', \"bar\\n#MAKE#: Nothing to be done for 'foo'.\\n\");\n\n# SV 54161: Expand $$* properly when it contains a path\n\nrun_make_test(q!\n.SECONDEXPANSION:\n%x: $$(info $$*); @echo '$*'\n!,\n              'q/ux', \"q/u\\nq/u\\n\");\n\n\n\n# sv 60188.\n# Test that a file explicitly mentioned by the user and made by an implicit\n# rule is not considered intermediate.\n\ntouch('hello.z');\n\n# subtest 1.\n# hello.x is derived from the stem and thus is an intermediate file.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=.x\nall: hello.z\n%.z: %$$(dep) ; @echo $@\n%.x: ;\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 2.\n# test.x is explicitly mentioned and thus is not an intermediate file.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=test.x\nall: hello.z\n%.z: %.x $$(dep) ; @echo $@\n%.x: ;\n!, '', \"hello.z\\n\");\n\n# subtest 3.\n# make is building hello.z and does not second expand the prerequisites of rule\n# 'unrelated: $$(dep)'. '$$(dep)' stays not expanded and 'hello.x' is never\n# entered to the database. Make considers 'hello.x' intermediate while building\n# 'hello.z'. Because 'hello.z' is present and 'hello.x' is missing and\n# 'hello.x' is intermediate, there is no need to rebuild 'hello.z'.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=hello.x\nall: hello.z\n%.z: %.x; @echo $@\n%.x: ;\nunrelated: $$(dep)\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# subtest 4.\n# Just like subtest 3. $$(dep) is not second expanded. 'hello.x' is\n# intermediate.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=hello.x\nall: hello.z\n%.z: %.x; @echo $@\n%.x: ;\n%.q: $$(dep)\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.z');\n\n\n# sv 60188.\n# Test that a file explicitly mentioned by the user and made by an implicit\n# rule is not considered intermediate, even when the builtin rules are used.\n\ntouch('hello.x');\ntouch('hello.tsk');\n\n# subtest 1.\n# hello.z is explicitly mentioned and thus is not an intermediate file.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=hello.z\nall: hello.tsk\n%.tsk: $$(dep) ; @echo $@\n%.z : %.x ; @echo $@\n!, '', \"hello.z\\nhello.tsk\");\n\n# subtest 2.\n# hello.z is derived from the stem and thus is an intermediate file.\nrun_make_test(q!\n.SECONDEXPANSION:\ndep:=.z\nall: hello.tsk\n%.tsk: %$$(dep) ; @echo $@\n%.z : %.x ; @echo $@\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.x');\nunlink('hello.tsk');\n\n\n# sv 60659. Second expansion of automatic variables inside a function in the\n# prerequisite list.\n# $$@ expands to the target in the 1st and following rules.\n# $$* expands to the stem in the 1st and following rules.\n# $$<,$$^,$$+,$$|,$$?,$$% expand to the empty string in the prerequisite list\n# of the 1st rule.\n# $$<,$$^,$$+,$$|,$$?,$$% in the prerequisite list of the 2nd (and following)\n# rule expand to the values from the 1st rule.\n# $$% cannot be used in prerequisites, because in pattern rules % is\n# substituted for stem.\n\n\n# subtest 1. Pattern rules. 1st rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n%.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=2\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 2. Pattern rules. 2nd rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x 1.x\n2.x: 5.z 6.z 5.z | 7.z 7.z 8.z\n1.x: 1.z 2.z 2.z | 3.z 4.z\n%.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2\n@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 3. Static pattern rules. 1st rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n2.x: %.x: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=2\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 4. Static pattern rules. 2nd rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 15.x 1.x\n15.x: 5.z 6.z 5.z | 7.z 7.z 8.z\n1.x: 1.z 2.z 2.z | 3.z 4.z\n15.x 1.x: %.x: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=15.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=15\n@=1.x,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 5. Grouped targets in implicit rules. 1st rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n%.x %.xx&: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=2\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 6. Grouped targets in implicit rules. 2nd rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x 1.xx\n2.x: 5.z 6.z 5.z | 7.z 7.z 8.z\n1.xx: 1.z 2.z 2.z | 3.z 4.z\n%.x %.xx&: 9.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n%.z: ;\n!, '',\n\"@=2.x,<=5.z,^=5.z 6.z,+=5.z 6.z 5.z,|=7.z 8.z,?=,*=2\n@=1.xx,<=1.z,^=1.z 2.z,+=1.z 2.z 2.z,|=3.z 4.z,?=,*=1\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# subtest 7. Double colon rule.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: 2.x\n%.x:: 5.z 6.z 5.z $$(info @=$$@,<=$$<,^=$$^,+=$$+,|=$$|,?=$$?,*=$$*) ;\n5.z 6.z: ;\n!, '',\n\"@=2.x,<=,^=,+=,|=,?=,*=2\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# sv 62324.\n# Integrity self check.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: bye.x\n%.x: $$(firstword %.1;\n!, '', \"#MAKE#: *** unterminated call to function 'firstword': missing ')'.  Stop.\", 512);\n\n# sv 62706.\n# Test that makes avoids second expanding prerequisites of the rules which are\n# not tried during implicit search.\n# Here, make tries rules '%.tsk: %.o' and '%.o' and their prerequisites are\n# second expanded.\n# Rules '%.bin: %.x' and '%.x:' are not used in implicit search for 'hello.tsk'\n# and 'hello.o' and their prerequisites are not expanded.\nrun_make_test(q!\n.SECONDEXPANSION:\n%.bin: %.x $$(info second expansion of $$@ prereqs); $(info $@ from $<)\n%.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\n%.x: $$(info second expansion of $$@ prereqs); $(info $@)\n%.o: $$(info second expansion of $$@ prereqs); $(info $@)\n!, '-R hello.tsk',\n\"second expansion of hello.o prereqs\nsecond expansion of hello.tsk prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# No side effects from second expansion of unrelated rules.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: hello.tsk\n%.tsk: %.o; exit 1\nhello.o:;\n%.q: $$(shell touch hello.1);\n!, '',\n\"exit 1\n#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\\n\", 512);\n\n# sv 62706.\n# Second expansion of intermediate prerequisites.\n# The rule to build hello.x is implicit.\n# Test that $$(deps) is secondary expanded.\nrun_make_test(q!\ndeps:=hello.h\n.SECONDEXPANSION:\nall: hello.tsk\n%.tsk: %.x; $(info $@)\n%.x: $$(deps); $(info $@)\nhello.h:; $(info $@)\n!, '', \"hello.h\\nhello.x\\nhello.tsk\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/se_statpat",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test second expansion in static pattern rules.\";\n\n$details = \"\";\n\n# Test #1: automatic variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nfoo.a foo.b: foo.%: bar.% baz.%\nfoo.a foo.b: foo.%: biz.% | buz.%\n\nfoo.a foo.b: foo.%: $$@.1 \\\n                    $$<.2 \\\n                    $$(addsuffix .3,$$^) \\\n                    $$(addsuffix .4,$$+) \\\n                    $$|.5 \\\n                    $$*.6\n!,\n              '', 'bar.a\nbaz.a\nbiz.a\nbuz.a\nfoo.a.1\nbar.a.2\nbar.a.3\nbaz.a.3\nbiz.a.3\nbar.a.4\nbaz.a.4\nbiz.a.4\nbuz.a.5\na.6\n');\n\n\n# Test #2: target/pattern -specific variables.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nfoo.x foo.y: foo.%: $$(%_a) $$($$*_b)\n\nfoo.x: x_a := bar\n\n%.x: x_b := baz\n!,\n              '', \"bar\\nbaz\\n\");\n\n\n# Test #3: order of prerequisites.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\n.DEFAULT: ; @echo '$@'\n\nall: foo.a bar.a baz.a\n\n# Subtest #1\nfoo.a foo.b: foo.%: foo.%.1; @:\nfoo.a foo.b: foo.%: foo.%.2\nfoo.a foo.b: foo.%: foo.%.3\n\n\n# Subtest #2\nbar.a bar.b: bar.%: bar.%.2\nbar.a bar.b: bar.%: bar.%.1; @:\nbar.a bar.b: bar.%: bar.%.3\n\n\n# Subtest #3\nbaz.a baz.b: baz.%: baz.%.1\nbaz.a baz.b: baz.%: baz.%.2\nbaz.a baz.b: ; @:\n!,\n             '', 'foo.a.1\nfoo.a.2\nfoo.a.3\nbar.a.1\nbar.a.2\nbar.a.3\nbaz.a.1\nbaz.a.2\n');\n\n\n# Test #4: Make sure stem triple-expansion does not happen.\n#\nrun_make_test(q!\n.SECONDEXPANSION:\nfoo$$bar: f%r: % $$*.1 ; @echo '$*'\n\noo$$ba oo$$ba.1: ; @echo '$@'\n!,\n              '', 'oo$ba\noo$ba.1\noo$ba\n');\n\n# sv 62324.\n# Integrity self check.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: bye.x\nbye.x: %.x: $$(firstword %.1;\n!, '', \"#MAKEFILE#:4: *** unterminated call to function 'firstword': missing ')'.  Stop.\", 512);\n\n#unlink('hello.tsk', 'bye.tsk', 'hello.o', 'hello.q', 'bye.o');\n\n# sv 62706.\n# Test that makes avoids second expanding prerequisites of the targets which\n# are not built.\n# Here, hello.tsk is built and its prerequisites are second expanded.\n# bye.tsk is not built and its prerequisites are not second expanded.\n\n# Static pattern rules.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Order only prereqs.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)\nbye.tsk: %.tsk:| %.o $$(info second expansion of $$@ prereqs); $(info $@ from $|)\nhello.o:| $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o:| $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Double colon. 1 rule per target.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nbye.tsk:: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $<)\nhello.o:: $$(info second expansion of $$@ prereqs); $(info $@)\nbye.o:: $$(info second expansion of $$@ prereqs); $(info $@)\n!, 'hello.tsk',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Double colon. 2 rules per target.\nrun_make_test(q!\n.SECONDEXPANSION:\nhello.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)\nhello.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)\nbye.tsk:: %.tsk: %.o $$(info 1 second expansion of $$@ prereqs); $(info 1 $@ from $<)\nbye.tsk:: %.tsk: %.o $$(info 2 second expansion of $$@ prereqs); $(info 2 $@ from $<)\nhello.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)\nhello.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)\nbye.o:: $$(info 1 second expansion of $$@ prereqs); $(info 1 $@)\nbye.o:: $$(info 2 second expansion of $$@ prereqs); $(info 2 $@)\n!, 'hello.tsk',\n\"1 second expansion of hello.tsk prereqs\n1 second expansion of hello.o prereqs\n1 hello.o\n2 second expansion of hello.o prereqs\n2 hello.o\n1 hello.tsk from hello.o\n2 second expansion of hello.tsk prereqs\n2 hello.tsk from hello.o\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n# sv 62706.\n# Test that the prerequisites of 'hello.tsk' are second expanded once.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: hello.tsk hello.q\nhello.tsk: %.tsk: %.o $$(info second expansion of $$@ prereqs); $(info $@ from $^)\nhello.o: $$(info second expansion of $$@ prereqs); $(info $@)\nhello.q: %.q: %.tsk $$(info second expansion of $$@ prereqs); $(info $@ from $^)\n!, '',\n\"second expansion of hello.tsk prereqs\nsecond expansion of hello.o prereqs\nhello.o\nhello.tsk from hello.o\nsecond expansion of hello.q prereqs\nhello.q from hello.tsk\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.1');\n\n# sv 62706.\n# No side effects from second expansion of unrelated rules.\nrun_make_test(q!\n.SECONDEXPANSION:\nall: hello.tsk\nhello.tsk: %.tsk: %.o; exit 1\nhello.o:;\nbye.tsk: %.tsk: $$(shell touch hello.1);\n!, '',\n\"exit 1\n#MAKE#: *** [#MAKEFILE#:4: hello.tsk] Error 1\\n\", 512);\n\n# sv 62706.\n# Second expansion of intermediate prerequisites.\n# The rule to build hello.x is static pattern.\n# .SECONDARY marks hello.x as intermediate.\n# Test that $$(deps) is secondary expanded.\nrun_make_test(q!\ndeps:=hello.h\n.SECONDEXPANSION:\n.SECONDARY: hello.x\nall: hello.x\nhello.x: %.x: $$(deps); $(info $@)\nhello.h:; $(info $@)\n!, '', \"hello.h\\nhello.x\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/shell_assignment",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test BSD-style shell assignments (VAR != VAL) for variables.\";\n\n$details = \"\";\n\n# TEST 0: Basic shell assignment (!=).\n\nrun_make_test('\n.POSIX:\n\ndemo1!=printf \\'  1   2 3\\n4\\n\\n5 \\n \\n 6\\n\\n\\n\\n\\'\ndemo2 != printf \\'7 8\\n \\'\ndemo3 != printf \\'$$(demo2)\\'\ndemo4 != printf \\' 2 3 \\n\\'\ndemo5 != printf \\' 2 3 \\n\\n\\'\nall: ; @echo \"<$(demo1)> <$(demo2)> <$(demo3)> <$(demo4)> <${demo5}>\"\n',\n              '', \"<  1   2 3 4  5     6   > <7 8  > <7 8  > < 2 3 > < 2 3  >\\n\");\n\n# TEST 1: Handle '#' the same way as BSD make\n$hashOctal = \"\\\\043\";\nif ($osname eq 'os390') {\n  $hashOctal = \"\\\\173\";\n}\n\nrun_make_test('\nfoo1!=echo bar#baz\nhash != printf \\'' . $hashOctal . '\\'\nfoo2!= echo \"bar$(hash)baz\"\n\nall: ; @echo \"<$(foo1)> <$(hash)> <$(foo2)>\"\n',\n              '', \"<bar> <#> <bar#baz>\\n\");\n\n# TEST 2: shell assignment variables (from !=) should be recursive.\n# Note that variables are re-evaluated later, so the shell can output\n# a value like $(XYZZY) as part of !=.  The $(XYZZY) will be EVALUATED\n# when the value containing it is evaluated.  On the negative side, this\n# means if you don't want this, you need to escape dollar signs as $$.\n# On the positive side, it means that shell programs can output macros\n# that are then evaluated as they are traditionally evaluated.. and that\n# you can use traditional macro evaluation semantics to implement !=.\n\nrun_make_test('\nXYZZY = fiddle-dee-dee\ndollar = $$\nVAR3 != printf \\'%s\\' \\'$(dollar)(XYZZY)\\'\n\nall: ; @echo \"<$(VAR3)>\"\n',\n              '', \"<fiddle-dee-dee>\\n\");\n\n\n# TEST 3: Overrides invoke shell anyway; they just don't store the result\n# in a way that is visible.\n\nrun_make_test('\n\noverride != echo abc > ,abc ; cat ,abc\n\nall: ; @echo \"<$(override)>\" ; cat ,abc\n',\n              'override=xyz', \"<xyz>\\nabc\\n\");\n\nunlink(',abc');\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/statipattrules",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test handling of static pattern rules.\";\n\n$details = \"\\\nThe makefile created in this test has three targets.  The\nfilter command is used to get those target names ending in\n.o and statically creates a compile command with the target\nname and the target name with .c.  It also does the same thing\nfor another target filtered with .elc and creates a command\nto emacs a .el file\";\n\n&touch('bar.c', 'lose.c');\n\n#   TEST #0\n#   -------\n\nrun_make_test('\nfiles = foo.elc bar.o lose.o\n\n$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@\n\n$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<\n',\n              '',\n              'CC -c bar.c -o bar.o');\n\n#  TEST #1\n#  -------\n\nrun_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o');\n\n\n#   TEST #2\n#   -------\n&touch(\"foo.el\");\n\nrun_make_test(undef, 'foo.elc', 'emacs foo.el');\n\n# Clean up after the first tests.\nunlink('foo.el', 'bar.c', 'lose.c');\n\n\n# TEST #3 -- PR/1670: don't core dump on invalid static pattern rules\n# -------\n\nrun_make_test('\n.DEFAULT: ; @echo $@\nfoo: foo%: % %.x % % % y.% % ; @echo $@\n',\n              '', \".x\\ny.\\nfoo\");\n\n\n# TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty\n#                        prerequisite list.\nrun_make_test('\nfoo.x bar.x: %.x : ; @echo $@\n\n',\n              '', 'foo.x');\n\n\n# TEST #5 -- bug #13881: double colon static pattern rule does not\n#                        substitute %.\nrun_make_test('\nfoo.bar:: %.bar: %.baz\nfoo.baz: ;@:\n',\n              '', '');\n\n\n# TEST #6: make sure the second stem does not overwrite the first\n#          perprerequisite's stem (Savannah bug #16053).\n#\nrun_make_test('\n.RECIPEPREFIX := >\n\nall.foo.bar: %.foo.bar: %.one\n\nall.foo.bar: %.bar: %.two\n\nall.foo.bar:\n>\t@echo $*\n>\t@echo $^\n\n.DEFAULT:;@:\n',\n'',\n'all.foo\nall.one all.foo.two');\n\n\n# TEST #7: make sure the second stem does not overwrite the first\n#          perprerequisite's stem when second expansion is enabled\n#          (Savannah bug #16053).\n#\nrun_make_test('\n.RECIPEPREFIX := >\n.SECONDEXPANSION:\n\nall.foo.bar: %.foo.bar: %.one $$*-one\n\nall.foo.bar: %.bar: %.two $$*-two\n\nall.foo.bar:\n>\t@echo $*\n>\t@echo $^\n\n.DEFAULT:;@:\n',\n'',\n'all.foo\nall.one all-one all.foo.two all.foo-two');\n\n# Test #8:\n# sv 60188.\n# Static pattern rules are considered explicit rules: no prerequisite of\n# a static pattern rule can ever be considered intermediate.\n\ntouch('hello.z');\n\n# subtest 1\nrun_make_test(q!\nhello.z: %.z: %.x ; @echo $@\n%.x: ;\n!, '', \"hello.z\\n\");\n\n# subtest 2\nrun_make_test(q!\nhello.z: %.z: %.x test.x ; @echo $@\n%.x: ;\n!, '', \"hello.z\\n\");\n\n# subtest 3\n# 'hello.x' is mentioned explicitly on an unrelated rule.\nrun_make_test(q!\nhello.z: %.z: %.x ; @echo $@\n%.x: ;\nunrelated: hello.x\n!, '', \"hello.z\\n\");\n\nunlink('hello.z');\n\n# sv 17374 Ensure double-colon static pattern rules work\n\ntouch(qw(a.src b.src));\n\nrun_make_test(q!\nall: a.tgt b.tgt\na.tgt b.tgt:: %.tgt : %.src ; cp $< $@\n!,\n    '', \"cp a.src a.tgt\\ncp b.src b.tgt\\n\");\n\nunlink(qw(a.src b.src a.tgt b.tgt));\n\nmy @dir = ('', 'lib/'); # With and without last slash.\nmy @secondexpansion = ('', '.SECONDEXPANSION:');\n\n# The following combinations are generated with and without second expansion.\n# 1.\n# all: bye.x\n# bye.x: %.x: ...\n#\n# 2.\n# all: lib/bye.x\n# lib/bye.x: %.x: ...\n#\n# 3.\n# all: lib/bye.x\n# lib/bye.x: lib/%.x: ...\n#\n# The following combination is not generated, because there is no rule to\n# build bye.x, no stem substitution takes place, not of interest of this test.\n# 4.\n# all: bye.x\n# bye.x: lib/%.x: ...\n#\n\nfor my $se (@secondexpansion) {\nfor my $d (@dir) { # The directory of the prerequisite of 'all'.\nfor my $r (@dir) { # The directory of the prerequisite in the rule definition.\n(!$d && $r) && next; # Combination 4.\nmy $dollar = $se ? '$' : '';\n\n# The prerequisite should only have directory if the prerequisite of 'all' has\n# it and if the prerequisite pattern in the rule definition does not have it.\n# That is combination 2.\nmy $pdir = $d && !$r ? $d : '';\n\n\n# One func, one %.\nmy $prereqs = \"${pdir}bye.1\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(firstword %.1); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Multiple funcs, each has one %.\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(firstword %.1) $dollar\\$(firstword %.2); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Multiple funcs, each has multiple %.\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(wordlist 1, 99, %.1 %.2) $dollar\\$(wordlist 1, 99, %.3 %.4); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Multiple funcs, each has multiple %, each prerequisite has multiple %.\n$prereqs = \"${pdir}bye_%_%.1 ${pdir}bye_%_%.2 ${pdir}bye_%_%.3 ${pdir}bye_%_%.4\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(wordlist 1, 99, %_%_%.1 %_%_%.2) $dollar\\$(wordlist 1, 99, %_%_%.3 %_%_%.4); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Nested functions.\n$prereqs = \"${pdir}bye.1 ${pdir}bye.2 ${pdir}bye.3 ${pdir}bye.4\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(wordlist 1, 99, $dollar\\$(wordlist 1, 99, %.1 %.2)) $dollar\\$(wordlist 1, 99, $dollar\\$(wordlist 1,99, %.3 %.4)); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# Multiple funcs, each has multiple words, each word has multiple %, sole %,\n# various corner cases.\n# Make should substitute the first % and only the first % in each word with the\n# stem.\n$prereqs = \"${pdir}bye1%2% ${pdir}bye 3${pdir}bye4%5 6${pdir}bye ${pdir}bye7%8 ${pdir}bye9 ${pdir}bye10% 11${pdir}bye12 13\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(wordlist 1, 99, %1%2% % 3%4%5 6%) %7%8 %9 $dollar\\$(wordlist 1, 99, %10% 11%12) 13; \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\nif ($port_type eq 'UNIX') {\n# Test that make does not use some hardcoded array of a finite size on stack.\n# Long prerequisite name. This prerequisite name is over 66K long.\nmy $prefix = 'abcdefgh' x 128 x 33; # 33K long.\nmy $suffix = 'stuvwxyz' x 128 x 33; # 33K long.\n$prereqs = \"${prefix}${pdir}bye${suffix}.1 ${prefix}${pdir}bye${suffix}.2\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(wordlist 1, 99, ${prefix}%${suffix}.1 ${prefix}%${suffix}.2); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n}\n\n\n# Empty stem.\n$prereqs = \"${pdir}.1\";\nrun_make_test(\"\n$se\n.PHONY: $prereqs\nall: ${d}bye.x\n${d}bye.x: $r%bye.x: $dollar\\$(firstword %.1); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n\n# A word expands to an empty prerequisite.\nrun_make_test(\"\n$se\nall: ${d}bye.x\n${d}bye.x: $r%.x: $dollar\\$(%); \\$(info \\$@ from \\$^)\n\", '', \"${d}bye.x from \\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n}\n}\n}\n\n# Escaped %.\n# The following combinations are generated without second expansion.\n# 1.\n# all: the%weird\\\\_hello_pattern\\\\.x\n# the\\\\%weird\\\\_hello_pattern\\\\.x: the\\\\%weird\\\\_%_pattern\\\\.x: ...\n#\n# 2.\n# all: lib/the%weird\\\\_hello_pattern\\\\.x\n# lib/the\\\\%weird\\\\_hello_pattern\\\\.x: lib/the\\\\%weird\\\\_%_pattern\\\\.x: ...\n#\n# Other combinations or second expansion are not tested, because escaped % is\n# not implemented for those.\n\nfor my $d (@dir) {\nmy $prereqs = \"${d}the%weird\\\\\\\\_hello_pattern%\\\\\\\\.1 ${d}the%weird\\\\\\\\_hello_pattern%\\\\\\\\.2\";\nrun_make_test(\"\n.PHONY: $prereqs\nall: ${d}the%weird\\\\\\\\_hello_pattern\\\\\\\\.x\n${d}the\\\\%weird\\\\\\\\_hello_pattern\\\\\\\\.x: ${d}the\\\\%weird\\\\\\\\_%_pattern\\\\\\\\.x: \\$(wordlist 1, 99, ${d}the\\\\%weird\\\\\\\\_%_pattern%\\\\\\\\.1 ${d}the\\\\%weird\\\\\\\\_%_pattern%\\\\\\\\.2); \\$(info \\$@ from \\$^)\n\", '', \"${d}the%weird\\\\\\\\_hello_pattern\\\\\\\\.x from $prereqs\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/suffixrules",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test suffix rules.\";\n\n$details = \"\";\n\n# TEST #0: Clear all suffixes\n\ntouch('foo.c');\n\nrun_make_test(q!\n.SUFFIXES:\nall: foo.o ; @echo $@ $<\n!,\n              '', \"#MAKE#: *** No rule to make target 'foo.o', needed by 'all'.  Stop.\\n\", 512);\n\nunlink('foo.c');\n\n# Test #1: Add a simple suffix rule\n\ntouch('foo.baz');\n\nrun_make_test(q!\n.SUFFIXES: .biz .baz\n\n.baz.biz: ; @echo make $@\n!,\n              'foo.biz', \"make foo.biz\\n\");\n\nunlink('foo.baz');\n\n# Test #2: Make sure the defaults still work\n\ntouch('foo.c');\n\nrun_make_test(undef, 'foo.o COMPILE.c=@echo OUTPUT_OPTION=', \"foo.c\\n\");\n\nunlink('foo.c');\n\n# Test #3: Replacing all suffixes\n\ntouch('foo.baz');\n\nrun_make_test(q!\n.SUFFIXES:\n.SUFFIXES: .biz .baz\n\n.baz.biz: ; @echo make $@\n!,\n              'foo.biz', \"make foo.biz\\n\");\n\nunlink('foo.baz');\n\n# SV 40657: \"Suffix rules\" with deps are normal rules\n\nmy $prewarn = 'warning: ignoring prerequisites on suffix rule definition';\n\ntouch('foo.bar');\n\n# Verify warnings for single-suffix rules\n\nrun_make_test(q!\n.SUFFIXES:\n.SUFFIXES: .baz\n\n.baz: foo.bar ; @echo make $@ from $<\n\n$X.POSIX:\n!,\n              'X=1 .baz', \"#MAKEFILE#:5: $prewarn\\nmake .baz from foo.bar\\n\");\n\n# In POSIX mode we don't get a warning\n\nrun_make_test(undef, 'X= .baz', \"make .baz from foo.bar\\n\");\n\n# Test double-suffix rules\n\nrun_make_test(q!\n.SUFFIXES:\n.SUFFIXES: .biz .baz\n\n$X.POSIX:\n\n.baz.biz: foo.bar ; @echo make $@ from $<\n!,\n              'X=1 .baz.biz', \"#MAKEFILE#:7: $prewarn\\nmake .baz.biz from foo.bar\\n\");\n\n# SV 40657: In POSIX mode we don't get a warning\n\nrun_make_test(undef, 'X= .baz.biz', \"make .baz.biz from foo.bar\\n\");\n\nunlink('foo.bar');\n\n# SV 40657: In POSIX mode, no pattern rules should be created\n\nutouch(-20, 'foo.baz');\n\nrun_make_test(undef,\n              'X= foo.biz', \"#MAKE#: *** No rule to make target 'foo.biz'.  Stop.\\n\", 512);\n\n# SV 40657: In Non-POSIX mode, a pattern rule is created\n\nrun_make_test(undef,\n              'X=1 foo.biz', \"#MAKEFILE#:7: $prewarn\\nmake foo.biz from foo.baz\\n\");\n\n# SV 40657: ... but any prerequisites are ignored\n\nutouch(-10, 'foo.biz');\ntouch('foo.bar');\n\nrun_make_test(undef,\n              'X=1 foo.biz', \"#MAKEFILE#:7: $prewarn\\n#MAKE#: 'foo.biz' is up to date.\\n\");\n\nunlink('foo.baz', 'foo.biz', 'foo.bar');\n\n\ntouch('hello.c');\nunlink('hello.o');\n\n# sv 63821.\n# Default suffix rule .c.o.\n\nrun_make_test('all: hello.o', 'COMPILE.c=@echo OUTPUT_OPTION=', 'hello.c');\n\n# User defined rules beat built-in rules.\n\nrun_make_test(q!\nall: hello.o\n.c.o:; $(info $@ user defined .c.o rule)\n!, '', \"hello.o user defined .c.o rule\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# sv 63821.\n# The same as above, but suffixes are cleared.\n\nrun_make_test(q!\nall: hello.o\n.SUFFIXES:\n.c.o:; $(info $@ user defined .c.o rule)\n!, '', \"#MAKE#: *** No rule to make target 'hello.o', needed by 'all'.  Stop.\\n\", 512);\n\n# sv 63821.\n# Suffixes are cleared and defined in the makefile.\n\nrun_make_test(q!\nall: hello.o\n.SUFFIXES:\n.SUFFIXES: .c .o\n.c.o:; $(info $@ user defined .c.o rule)\n!, '', \"hello.o user defined .c.o rule\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# sv 63821.\n# When built-in rules are disabled, but certain suffixes are added to\n# .SUFFIXES, make should exit with the 'No rule...' error message.\n\nrun_make_test(q!\n.SUFFIXES: .c .o\nall: hello.o\n!, '-r', \"#MAKE#: *** No rule to make target 'hello.o', needed by 'all'.  Stop.\\n\", 512);\n\n# sv 63821.\n# Same as above, but this time built-in rules are disabled inside the makefile.\n\nrun_make_test(q!\nMAKEFLAGS += -r\n.SUFFIXES: .c .o\nall: hello.o\n!, '', \"#MAKE#: *** No rule to make target 'hello.o', needed by 'all'.  Stop.\\n\", 512);\n\n# sv 63821.\n# Same as above, but this time there is a rule.\n\nrun_make_test(q!\nall: hello.o\nMAKEFLAGS += -r\n.SUFFIXES: .c .o\n.c.o:; $(info $@ user defined .c.o rule)\n!, '', \"hello.o user defined .c.o rule\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.c', 'hello.o');\n\n# sv 65324.\n# Crash in disable_builtins.\nrun_make_test(q!\nall:;\n!, '-r MAKEFLAGS=', \"#MAKE#: 'all' is up to date.\\n\");\n\n\n# Complete\n1;\n"
  },
  {
    "path": "tests/scripts/features/targetvars",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test target-specific variable settings.\";\n\n$details = \"\\\nCreate a makefile containing various flavors of target-specific variable\nvalues, override and non-override, and using various variable expansion\nrules, semicolon interference, etc.\";\n\nrun_make_test('\nexport FOO = foo\nexport BAR = bar\none: override FOO = one\none two: ; @echo $(FOO) $(BAR)\ntwo: BAR = two\n.RECIPEPREFIX = >\nthree: ; BAR=1000\n> @echo $(FOO) $(BAR)\n# Some things that shouldn not be target vars\nfunk : override\nfunk : override adelic\nadelic override : ; echo $@\n# Test per-target recursive variables\nfour:FOO=x\nfour:VAR$(FOO)=ok\nfour: ; @echo \"$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)\"\nfive:FOO=x\nfive six : VAR$(FOO)=good\nfive six: ;@echo \"$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)\"\n# Test per-target variable inheritance\nseven: eight\nseven eight: ; @echo $@: $(FOO) $(BAR)\nseven: BAR = seven\nseven: FOO = seven\neight: BAR = eight\n# Test the export keyword with per-target variables\nnine: ; @echo $(FOO) $(BAR) $$FOO $$BAR\nnine: FOO = wallace\nnine-a: export BAZ = baz\nnine-a: ; @echo $$BAZ\n# Test = escaping\nEQ = =\nten: one$(EQ)two\nten: one $(EQ) two\nten one$(EQ)two $(EQ):;@echo $@\n.PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two\n# Test target-specific vars with pattern/suffix rules\nQVAR = qvar\nRVAR = =\n%.q : ; @echo $(QVAR) $(RVAR)\nfoo.q : RVAR += rvar\n# Target-specific vars with multiple LHS pattern rules\n%.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR)\nfoo.r : RVAR += rvar\nfoo.t : TVAR := $(QVAR)\n',\n                 \"one two three\", \"one bar\\nfoo two\\nBAR=1000\\nfoo bar\\n\");\n\n# TEST #2\n\nrun_make_test(undef, \"one two FOO=1 BAR=2\", \"one 2\\n1 2\\n\");\n\n# TEST #3\n\nrun_make_test(undef, \"four\", \"x ok  ok\\n\");\n\n# TEST #4\n\nrun_make_test(undef, \"seven\", \"eight: seven eight\\nseven: seven seven\\n\");\n\n# TEST #5\n\nrun_make_test(undef, \"nine\", \"wallace bar wallace bar\\n\");\n\n# TEST #5-a\n\nrun_make_test(undef, \"nine-a\", \"baz\\n\");\n\n# TEST #6\n\nrun_make_test(undef, \"ten\", \"one=two\\none bar\\n=\\nfoo two\\nten\\n\");\n\n# TEST #6\n\nrun_make_test(undef, \"foo.q bar.q\", \"qvar = rvar\\nqvar =\\n\");\n\n# TEST #7\n\nrun_make_test(undef, \"foo.t bar.s\", \"qvar = qvar\\nqvar =\\n\");\n\n# TEST #8\n# For PR/1378: Target-specific vars don't inherit correctly\n\nrun_make_test('\nfoo: FOO = foo\nbar: BAR = bar\nfoo: bar\nbar: baz\nbaz: ; @echo $(FOO) $(BAR)\n', \"\", \"foo bar\\n\");\n\n# TEST #9\n# For PR/1380: Using += assignment in target-specific variables sometimes fails\n# Also PR/1831\n\nrun_make_test('\n.PHONY: all one\nall: FOO += baz\nall: one; @echo $(FOO)\n\nFOO = bar\n\none: FOO += biz\none: FOO += boz\none: ; @echo $(FOO)\n',\n              '', \"bar baz biz boz\\nbar baz\\n\");\n\n# Test #10\n\nrun_make_test(undef, 'one', \"bar biz boz\\n\");\n\n# Test #11\n# PR/1709: Test semicolons in target-specific variable values\n\nrun_make_test('\nfoo : FOO = ; ok\nfoo : ; @echo \"$(FOO)\"\n',\n              '', \"; ok\\n\");\n\n# Test #12\n# PR/2020: More hassles with += target-specific vars.  I _really_ think\n# I nailed it this time :-/.\n\nrun_make_test('\n.PHONY: a\n\nBLAH := foo\nCOMMAND = echo $(BLAH)\n\na: ; @$(COMMAND)\n\na: BLAH := bar\na: COMMAND += snafu $(BLAH)\n',\n              '', \"bar snafu bar\\n\");\n\n# Test #13\n# Test double-colon rules with target-specific variable values\n\nrun_make_test('\nW = bad\nX = bad\nfoo: W = ok\nfoo:: ; @echo $(W) $(X) $(Y) $(Z)\nfoo:: ; @echo $(W) $(X) $(Y) $(Z)\nfoo: X = ok\n\nY = foo\nbar: foo\nbar: Y = bar\n\nZ = nopat\nifdef PATTERN\n  fo% : Z = pat\nendif\n',\n             'foo', \"ok ok foo nopat\\nok ok foo nopat\\n\");\n\n# Test #14\n# Test double-colon rules with target-specific variable values and\n# inheritance\n\nrun_make_test(undef, 'bar', \"ok ok bar nopat\\nok ok bar nopat\\n\");\n\n# Test #15\n# Test double-colon rules with pattern-specific variable values\n\nrun_make_test(undef, 'foo PATTERN=yes', \"ok ok foo pat\\nok ok foo pat\\n\");\n\n# Test #16\n# Test target-specific variables with very long command line\n# (> make default buffer length)\n\nrun_make_test('\nbase_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions        CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if test -f               \"build_information.generate\"   ; then echo \"$(OBJ_DIR)/build_information.o\"; else echo \"no build information\"; fi  )\n\ndeals_changed_since: ; @echo $(BUILD_OBJ)\n',\n              '', \"no build information\\n\");\n\n# TEST #17\n\n# Test a merge of set_lists for files, where one list is much longer\n# than the other.  See Savannah bug #15757.\n\nmkdir('t1', 0777);\ntouch('t1/rules.mk');\n\nrun_make_test('\nVPATH = t1\ninclude rules.mk\n.PHONY: all\nall: foo.x\nfoo.x : rules.mk ; @echo MYVAR=$(MYVAR) FOOVAR=$(FOOVAR) ALLVAR=$(ALLVAR)\nall: ALLVAR = xxx\nfoo.x: FOOVAR = bar\nrules.mk : MYVAR = foo\n.INTERMEDIATE: foo.x rules.mk\n',\n              '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx');\n\nrmfiles('t1/rules.mk');\nrmdir('t1');\n\n# TEST #18\n\n# Test appending to a simple variable containing a \"$\": avoid a\n# double-expansion.  See Savannah bug #15913.\n\nrun_make_test('\nVAR := $$FOO\nfoo: VAR += BAR\nfoo: ; @echo '.\"'\".'$(VAR)'.\"'\".'\n',\n              '', '$FOO BAR');\n\n# TEST #19: Override with append variables\n\nrun_make_test('\na: override FOO += f1\na: FOO += f2\na: ; @echo \"$(FOO)\"\n',\n              '', \"f1\\n\");\n\nrun_make_test(undef, 'FOO=C', \"C f1\\n\");\n\n# TEST #19: Conditional variables with command-line settings\n\nrun_make_test('\na: FOO ?= f1\na: ; @echo \"$(FOO)\"\n',\n              '', \"f1\\n\");\n\nrun_make_test(undef, 'FOO=C', \"C\\n\");\n\n# TEST #20: Check for continuation after semicolons\n\nrun_make_test(q!\na: A = 'hello;\\\nworld'\na: ; @echo $(A)\n!,\n              '', \"hello; world\\n\");\n\n# TEST #21: SV-56834 Ensure setting PATH in a target var works properly\nmy $sname = \"foobar$scriptsuffix\";\n\nmkdir('sd', 0775);\ncreate_file(\"sd/$sname\", \"exit 0\\n\");\nchmod 0755, \"sd/$sname\";\n\nrun_make_test(qq!\nall: PATH := sd\nall: ; $sname >/dev/null\n!,\n              '', \"$sname >/dev/null\\n\");\n\n# Don't use the general PATH if not found on the target path\n\n$ENV{PATH} = \"$ENV{PATH}:sd\";\n\nmy ($ernum, $erstr);\nif ($port_type eq 'W32') {\n    $ernum = 1;\n    $erstr = \"'$sname' is not recognized as an internal or external command,\\noperable program or batch file.\";\n} else {\n    $ernum = 127;\n    $erstr = \"#MAKE#: $sname: $ERR_no_such_file\";\n}\n\nrun_make_test(qq!\nall: PATH := ..\nall: ; $sname\n!,\n              '', \"$sname\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum\", 512);\n\nunlink(\"sd/$sname\");\nrmdir ('sd');\n\n# SV 59230: Conditional (non-)assignment of target-specific variables should\n# preserve export settings.\n\n$ENV{hello} = 'moon';\nrun_make_test(q!\nall:; @echo hello=$$hello\ndummy: hello?=world\n!,\n              '', 'hello=moon');\n\n# SV 59230: Assignment of a global variable should not affect export of a\n# target specific variable.\n\n$ENV{hello} = \"moon\";\nrun_make_test(q!\nall:; @echo hello=$$hello\nhello=sun\ndummy: hello?=world\n!,\n              '', 'hello=sun');\n\n# Support target-specific unexport\n\n$ENV{hello} = \"moon\";\nrun_make_test(q!\nunexport hello=sun\nall: base exp\nbase exp: ; @echo hello=$$hello\nexp: export hello=world\n!,\n              '', \"hello=\\nhello=world\\n\");\n\n$ENV{hello} = \"moon\";\nrun_make_test(q!\nhello=sun\nall: base exp\nbase exp: ; @echo hello=$$hello\nexp: unexport hello=world\n!,\n              '', \"hello=sun\\nhello=\\n\");\n\nrun_make_test(q!\nall:; @echo hello=$$hello\nunexport hello=sun\ndummy: hello?=world\n!,\n              '', 'hello=');\n\n$ENV{hello} = \"moon\";\nrun_make_test(q!\nall:; @echo hello=$$hello\nhello=sun\ndummy: unexport hello=world\n!,\n              '', 'hello=sun');\n\nrun_make_test(q!\nall: mid\nmid: base\n\nifeq ($(midexport),export)\nmid: export hello=mid\nelse ifeq ($(midexport),unexport)\nmid: unexport hello=mid\nelse\nmid: hello=mid\nendif\n\nifeq ($(baseexport),export)\nbase: export hello=base\nelse ifeq ($(baseexport),unexport)\nbase: unexport hello=base\nelse\nbase: hello=base\nendif\n\nall mid base:; @echo $@ make=$(hello) shell=$$hello\n!,\n              '', \"base make=base shell=\\nmid make=mid shell=\\nall make= shell=\\n\");\n\n# Test base settings with env var\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              '', \"base make=base shell=base\\nmid make=mid shell=mid\\nall make=environ shell=environ\\n\");\n\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'baseexport=export', \"base make=base shell=base\\nmid make=mid shell=mid\\nall make=environ shell=environ\\n\");\n\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'baseexport=unexport', \"base make=base shell=\\nmid make=mid shell=mid\\nall make=environ shell=environ\\n\");\n\n# Test mid settings with env var\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'midexport=export', \"base make=base shell=base\\nmid make=mid shell=mid\\nall make=environ shell=environ\\n\");\n\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'midexport=export baseexport=unexport', \"base make=base shell=\\nmid make=mid shell=mid\\nall make=environ shell=environ\\n\");\n\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'midexport=unexport', \"base make=base shell=\\nmid make=mid shell=\\nall make=environ shell=environ\\n\");\n\n$ENV{hello} = \"environ\";\nrun_make_test(undef,\n              'midexport=unexport baseexport=export', \"base make=base shell=base\\nmid make=mid shell=\\nall make=environ shell=environ\\n\");\n\n# Test base settings without env var\nrun_make_test(undef,\n              'baseexport=export', \"base make=base shell=base\\nmid make=mid shell=\\nall make= shell=\\n\");\n\nrun_make_test(undef,\n              'baseexport=unexport', \"base make=base shell=\\nmid make=mid shell=\\nall make= shell=\\n\");\n\n# Test mid settings with env var\nrun_make_test(undef,\n              'midexport=export', \"base make=base shell=base\\nmid make=mid shell=mid\\nall make= shell=\\n\");\n\nrun_make_test(undef,\n              'midexport=export baseexport=unexport', \"base make=base shell=\\nmid make=mid shell=mid\\nall make= shell=\\n\");\n\nrun_make_test(undef,\n              'midexport=unexport', \"base make=base shell=\\nmid make=mid shell=\\nall make= shell=\\n\");\n\nrun_make_test(undef,\n              'midexport=unexport baseexport=export', \"base make=base shell=base\\nmid make=mid shell=\\nall make= shell=\\n\");\n\n\n\n# TEST #19: Test define/endef variables as target-specific vars\n\n# run_make_test('\n# define b\n# @echo global\n# endef\n# a: define b\n# @echo local\n# endef\n\n# a: ; $(b)\n# ',\n#               '', \"local\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/temp_stdin",
    "content": "#                                                              -*-mode: perl-*-\n\n$description = \"Test handling of temporary file created from stdin.\";\n\n# These tests rely on the test_driver checking for leftover temporary content\n\ncreate_file('input.mk', \"world:=1\\n\");\ncreate_file('bye.mk', \"moon:=2\\n\");\n\n# sv 62118,62145.\n# Test that makes leaves no temp file when make code is piped to stdin and -v,\n# -h or an invalid option is specified.\nmy @opts = ('-v', '-h', '--nosuchopt');\nmy @exit_codes = (0, 0, 512);\nfor my $i (0 .. $#opts) {\n    close(STDIN);\n    open(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\n    run_make_test(q!\nall:; $(info hello world)\n!,\n                  \"$opts[$i] -f-\", \"/uilt for /\", $exit_codes[$i]);\n}\n\n# sv 62118,62145.\n# Test that a stdin temp file is removed.\nclose(STDIN);\nopen(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\nrun_make_test(q!\nall:; $(info world=$(world))\n!,\n              '-f-', \"world=1\\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 62118,62145.\n# Test that a stdin temp file is removed, even when make re-execs.\n# Also test that make honors TMPDIR to create the temp file.\n# Ensure touching bye.mk causes re-exec.\n&utouch(-600, 'bye.mk');\nclose(STDIN);\nopen(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\nrun_make_test(q!\ninclude bye.mk\nall:; $(info hello)\n$(MAKE_RESTARTS)bye.mk: force; touch $@\nforce:\n!,\n              '-R --debug=b -f-', \"/Re-executing.+?--temp-stdin=\\Q$temppath\\E/\");\n\nif ($port_type eq 'UNIX') {\n# POSIX doesn't require sh to set PPID so test this\nmy $cmd = create_command();\nadd_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);\nmy $fout = 'ppidtest.out';\nrun_command_with_output($fout, @$cmd);\n$_ = read_file_into_string($fout);\ns/\\r?\\n//g;\nif (/^[0-9]+$/) {\nuse POSIX ();\n\n# sv 63157.\n# Test that make removes the temporary file which holds make code from stdin,\n# even when a signal is received.  include bye.mk and bye.mk: rule is needed\n# to cause make to keep the temporary file for re-exec. Without re-exec make\n# will remove the file before the signal arrives.  sleep is needed to let make\n# write its \"... Terminated\" message to the log file.  Must use REGEX because\n# some systems (MacOS) add extra text after Terminated.\n&utouch(-600, 'bye.mk');\nclose(STDIN);\nopen(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\n\nrun_make_test(q!\ninclude bye.mk\npid := $(shell echo $$PPID)\nall:;\nbye.mk: force; @#HELPER# -q term $(pid) sleep 10\nforce:\n!,\n              '-f-', '/#MAKE#: \\*\\*\\* \\[#MAKEFILE#:5: bye.mk] Terminated/', POSIX::SIGTERM);\n}\nunlink($fout);\n\n# sv 62118,62145.\n# Test that a stdin temp file is removed, when execvp fails to re-exec make.\n# In order to cause execvp to fail, copy the tested make binary to the temp\n# directory and take away the 'x' bit.\nuse File::Spec;\nuse File::Copy;\n\nmy $tmakedir = File::Spec->catfile($cwdpath, 'tmakedir');\nmkdir($tmakedir, 0770);\nmy $makecopy = File::Spec->catfile($tmakedir, 'make');\ncopy(\"$mkpath\", $makecopy);\n# Set file mode bits, because perl copy won't.\nchmod 0700, $makecopy;\n\nmy @make_orig = @make_command;\n@make_command = ($makecopy);\n\n# Ensure touching bye.mk causes re-exec.\n&utouch(-600, 'bye.mk');\nclose(STDIN);\nopen(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\nrun_make_test(\"\ninclude bye.mk\nall:; \\$(info hello)\n\\$(MAKE_RESTARTS)bye.mk: force; touch \\$@ && chmod u-x $makecopy\nforce:\n\",\n              \"-f-\", \"touch bye.mk && chmod u-x $makecopy\\nmake: $makecopy: $ERR_nonexe_file\\n\", 32512);\n\n@make_command = @make_orig;\nunlink($makecopy);\nrmdir($tmakedir);\n\n# SV 63333. Test that make exits with an error message if we cannot store a\n# makefile from stdin to a temporary file.\n# Create a non-writable temporary directory.\n\n# If we do this Valgrind fails because it cannot write temp files... the docs\n# don't describe any way to tell valgrind to use a directory other than TMPDIR.\n\nif (!$valgrind) {\n    my $tdir = 'test_tmp_dir';\n    mkdir($tdir, 0500);\n    $ENV{'TMPDIR'} = $tdir;\n    close(STDIN);\n    open(STDIN, \"<\", 'input.mk') || die \"$0: cannot open input.mk for reading: $!\";\n\n    run_make_test(q!\nall:; $(info hello, world)\n!, '-f-', '/cannot store makefile from stdin to a temporary file.  Stop./', 512);\n    rmdir($tdir);\n}\n}\n\n# This close MUST come at the end of the test!!\nclose(STDIN);\nunlink('input.mk', 'bye.mk');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/utf8",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test support for UTF-8.\";\n\n$details = \"\";\n\n# Verify that the UTF-8 BOM is ignored.\nrun_make_test(\"\\xEF\\xBB\\xBFall: ; \\@echo \\$\\@\\n\", '', \"all\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/features/varnesting",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test recursive variables\";\n\n$details = \"\";\n\nrun_make_test('\nx = variable1\nvariable2 := Hello\ny = $(subst 1,2,$(x))\nz = y\na := $($($(z)))\nall: ; @echo $(a)\n',\n              '', \"Hello\\n\");\n\n# This tests resetting the value of a variable while expanding it.\n# You may only see problems with this if you're using valgrind or\n# some other memory checker that poisons freed memory.\n# See Savannah patch #7534\n\nrun_make_test('\nVARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)\nwololo: ; @$(VARIABLE)\n',\n              '', \"hi\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/vpath",
    "content": "#                                                                     -*-perl-*-\n\n$description = \"Test vpath for particular classes of filenames.\";\n\n$details = \"\";\n\nmkdir('work');\n\n@files_to_touch = (\"work${pathsep}main.c\",\"work${pathsep}defs.h\",\n                   \"work${pathsep}kbd.c\",\"work${pathsep}command.h\",\n                   \"work${pathsep}commands.c\",\"work${pathsep}display.c\",\n                   \"work${pathsep}buffer.h\",\"work${pathsep}insert.c\",\n                   \"work${pathsep}command.c\");\n\n&touch(@files_to_touch);\n\nrun_make_test(q!\nvpath %.c foo\nvpath %.c work\nvpath %.h work\nobjects = main.o kbd.o commands.o display.o insert.o\nedit: $(objects) ; @echo cc -o $@ $^\nmain.o : main.c defs.h ; @echo cc -c $(firstword $^)\nkbd.o : kbd.c defs.h command.h ; @echo cc -c kbd.c\ncommands.o : command.c defs.h command.h ; @echo cc -c commands.c\ndisplay.o : display.c defs.h buffer.h ; @echo cc -c display.c\ninsert.o : insert.c defs.h buffer.h ; @echo cc -c insert.c\n!,\n    '', \"cc -c work${pathsep}main.c\\ncc -c kbd.c\\ncc -c commands.c\\n\"\n        .\"cc -c display.c\\ncc -c insert.c\\n\"\n        .\"cc -o edit main.o kbd.o commands.o display.o insert.o\\n\");\n\nunlink(@files_to_touch);\n\n# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency\n# warnings due to change of struct file ptr.  Savannah bug #13529.\n\nmkdir('vpath-d', 0777);\n\nrun_make_test(q!\nvpath %.te vpath-d/\n.SECONDARY:\ndefault: vpath-d/a vpath-d/b\nvpath-d/a: fail.te\nvpath-d/b : fail.te\nvpath-d/fail.te:\n!,\n              '', \"#MAKE#: Nothing to be done for 'default'.\\n\");\n\nrmdir('vpath-d');\n\n# Test VPATH vs vpath\n\nrun_make_test(q!\nVPATH = work:#PWD#\nvpath %.c foo\nvpath %.c work\nvpath %.c #PWD#\nvpath %.h work\nvpath %.c\nvpath\nall: ; @echo ALL IS WELL\n!,\n              '', \"ALL IS WELL\\n\");\n\n# Test interaction of -lfoo and vpath\n\nmy @dirs_to_make = qw(a1 b1 a2 b2 b3);\nfor my $d (@dirs_to_make) {\n    mkdir($d, 0777);\n}\n\nmy @files_to_touch = (\"a1${pathsep}lib1.a\",\n                      \"a1${pathsep}libc.a\",\n                      \"b1${pathsep}lib1.so\",\n                      \"a2${pathsep}lib2.a\",\n                      \"b2${pathsep}lib2.so\",\n                      \"lib3.a\",\n                      \"b3${pathsep}lib3.so\");\n&touch(@files_to_touch);\n\nmy $answer = \"a1${pathsep}lib1.a a1${pathsep}libc.a \" .\n             \"a2${pathsep}lib2.a lib3.a\\n\";\nif ($port_type eq 'VMS-DCL') {\n    $answer =~ s/ /,/g;\n}\n\nrun_make_test('\nvpath %.h b3\nvpath %.a a1\nvpath %.so b1\nvpath % a2 b2\nvpath % b3\nall: -l1 -lc -l2 -l3; @echo $^\n',\n              '', $answer);\n\nunlink(@files_to_touch);\nfor my $d (@dirs_to_make) {\n    rmdir($d);\n}\n\n# Check that if we find find files with VPATH, we don't do pattern search\n\nmkdir(\"vpa\");\n\nrun_make_test(q!\nVPATH = vpa\n%.x: ; @echo pattern $@\nvpa/foo.x: ; @echo vpath $@\n!,\n              'foo.x', \"vpath vpa/foo.x\\n\");\n\nrmdir(\"vpa\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/vpathgpath",
    "content": "#                                                                    -*-perl-*-\n$description = \"Tests VPATH+/GPATH functionality.\";\n\n$details = \"\";\n\nmkdir('work');\n\n$VP = \"work$pathsep\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"VPATH = $VP\\n\";\n\nprint MAKEFILE <<'EOMAKE';\n\nGPATH = $(VPATH)\n\n.SUFFIXES: .a .b .c .d\n.PHONY: general rename notarget intermediate\n\n%.a:\n%.b:\n%.c:\n%.d:\n\n%.a : %.b ; cat $^ > $@\n%.b : %.c ; cat $^ > $@\n%.c :: %.d ; cat $^ > $@\n\n# General testing info:\n\ngeneral: foo.b\nfoo.b: foo.c bar.c\n\nEOMAKE\n\nclose(MAKEFILE);\n\n@touchedfiles = ();\n\n$off = -500;\n\nsub gtouchfiles {\n  foreach (@_) {\n    ($f = $_) =~ s,VP/,$VP,g;\n    &utouch($off, $f);\n    $off += 10;\n    push(@touchedfiles, $f);\n  }\n}\n\n# Run the general-case test\n\n&gtouchfiles(\"VP/foo.d\", \"VP/bar.d\", \"VP/foo.c\", \"VP/bar.c\", \"foo.b\", \"bar.d\");\n\n&run_make_with_options($makefile,\"general\",&get_logfile());\n\npush(@touchedfiles, \"bar.c\");\n\n$answer = \"$make_name: Nothing to be done for 'general'.\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\nunlink(@touchedfiles) unless $keep;\n\n1;\n"
  },
  {
    "path": "tests/scripts/features/vpathplus",
    "content": "#                                                                    -*-perl-*-\n$description = \"Tests the new VPATH+ functionality added in 3.76.\";\n\n$details = \"\";\n\nmkdir('work');\n\n$VP = \"work$pathsep\";\n\n@touchedfiles = ();\n\n$off = -500;\n\nsub touchfiles {\n  foreach (@_) {\n    &utouch($off, $_);\n    $off += 10;\n    push(@touchedfiles, $_);\n  }\n}\n\n&touchfiles(\"$VP/foo.d\", \"$VP/bar.d\", \"$VP/foo.c\", \"$VP/bar.c\", \"foo.b\", \"bar.d\");\n\n# Run the general-case test\n\nrun_make_test(qq!VPATH = $VP! . q!\n.SUFFIXES: .a .b .c .d\n.PHONY: general rename notarget intermediate\n\n%.a:\n%.b:\n%.c:\n%.d:\n\n%.a : %.b ; cat $^ > $@\n%.b : %.c ; cat $^ > $@ 2>/dev/null || exit 1\n%.c :: %.d ; cat $^ > $@\n\n# General testing info:\n\ngeneral: foo.b\nfoo.b: foo.c bar.c\n\n# Rename testing info:\n\nrename: $(VPATH)/foo.c foo.d\n\n# Target not made testing info:\n\nnotarget: notarget.b\nnotarget.c: notarget.d ; -@echo \"not creating $@ from $^\"\n\n# Intermediate files:\n\nintermediate: inter.a\n!,\n    'general', \"cat bar.d > bar.c\\ncat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1\\n\");\n\npush(@touchedfiles, \"bar.c\");\n\n# Test rules that don't make the target correctly\n\n&touchfiles(\"$VP/notarget.c\", \"notarget.b\", \"notarget.d\");\n\nrun_make_test(undef, 'notarget', \"not creating notarget.c from notarget.d\\ncat notarget.c > notarget.b 2>/dev/null || exit 1\\n#MAKE#: *** [#MAKEFILE#:11: notarget.b] Error 1\\n\", 512);\n\n# Test intermediate file handling (part 1)\n\n&touchfiles(\"$VP/inter.d\");\n\nmy $be = pack(\"L\", 1) eq pack(\"N\", 1);\nmy $intfiles = $be ? \"inter.c inter.b\" : \"inter.b inter.c\";\n\nrun_make_test(undef, 'intermediate', \"cat ${VP}inter.d > inter.c\\ncat inter.c > inter.b 2>/dev/null || exit 1\\ncat inter.b > inter.a\\nrm $intfiles\\n\");\n\npush(@touchedfiles, \"inter.a\", \"inter.b\");\n\n# Test intermediate file handling (part 2)\n\n&utouch(-20, \"inter.a\");\n&utouch(-10, \"$VP/inter.b\");\n&touch(\"$VP/inter.d\");\n\nrun_make_test(undef, 'intermediate', \"cat ${VP}inter.d > inter.c\\ncat inter.c > inter.b 2>/dev/null || exit 1\\ncat inter.b > inter.a\\nrm inter.c\\n\");\n\npush(@touchedfiles, \"$VP/inter.b\", \"$VP/inter.d\");\n\nunlink @touchedfiles unless $keep;\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/abspath",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the abspath functions.\";\n\n$details = \"\";\n\n# Someone needs to rewrite this to be portable for Windows\n$port_type eq 'W32' and return -1;\n\nrun_make_test('\nifneq ($(realpath $(abspath .)),$(CURDIR))\n  $(warning .: abs=\"$(abspath .)\" real=\"$(realpath $(abspath .))\" curdir=\"$(CURDIR)\")\nendif\n\nifneq ($(realpath $(abspath ./)),$(CURDIR))\n  $(warning ./: abs=\"$(abspath ./)\" real=\"$(realpath $(abspath ./))\" curdir=\"$(CURDIR)\")\nendif\n\nifneq ($(realpath $(abspath .///)),$(CURDIR))\n  $(warning .///: abs=\"$(abspath .///)\" real=\"$(realpath $(abspath .///))\" curdir=\"$(CURDIR)\")\nendif\n\nifneq ($(abspath /),/)\n  $(warning /: abspath=\"$(abspath /)\")\nendif\n\nifneq ($(abspath ///),/)\n  $(warning ///: abspath=\"$(abspath ///)\")\nendif\n\nifneq ($(abspath /.),/)\n  $(warning /.: abspath=\"$(abspath /.)\")\nendif\n\nifneq ($(abspath ///.),/)\n  $(warning ///.: abspath=\"$(abspath ///.)\")\nendif\n\nifneq ($(abspath /./),/)\n  $(warning /./: abspath=\"$(abspath /./)\")\nendif\n\nifneq ($(abspath /.///),/)\n  $(warning /.///: abspath=\"$(abspath /.///)\")\nendif\n\nifneq ($(abspath /..),/)\n  $(warning /..: abspath=\"$(abspath /..)\")\nendif\n\nifneq ($(abspath ///..),/)\n  $(warning ///..: abspath=\"$(abspath ///..)\")\nendif\n\nifneq ($(abspath /../),/)\n  $(warning /../: abspath=\"$(abspath /../)\")\nendif\n\nifneq ($(abspath /..///),/)\n  $(warning /..///: abspath=\"$(abspath /..///)\")\nendif\n\n\nifneq ($(abspath /foo/bar/..),/foo)\n  $(warning /foo/bar/..: abspath=\"$(abspath /foo/bar/..)\")\nendif\n\nifneq ($(abspath /foo/bar/../../../baz),/baz)\n  $(warning /foo/bar/../../../baz: abspath=\"$(abspath /foo/bar/../../../baz)\")\nendif\n\nifneq ($(abspath /foo/bar/../ /..),/foo /)\n  $(warning /foo/bar/../ /..: abspath=\"$(abspath /foo/bar/../ /..)\")\nendif\n\n\n.PHONY: all\nall: ; @:\n',\n'',\n'');\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/functions/addprefix",
    "content": "$description = \"The following test creates a makefile to test the addprefix \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(addprefix src${pathsep},a.b.z.foo hacks) \\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"src${pathsep}a.b.z.foo src${pathsep}hacks\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/addsuffix",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the addsuffix function.\";\n\n$details = \"\";\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<EOMAKE;\nstring := \\$(addsuffix .c,src${pathsep}a.b.z.foo hacks)\none: ; \\@echo \\$(string)\n\ntwo: ; \\@echo \\$(addsuffix foo,)\nEOMAKE\n\nclose(MAKEFILE);\n\n\n# TEST 0\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n$answer = \"src${pathsep}a.b.z.foo.c hacks.c\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST 1\n\n&run_make_with_options($makefile, \"two\", &get_logfile);\n$answer = \"\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/functions/andor",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the and & or functions.\\n\";\n\n$details = \"Try various uses of and & or to ensure they all give the correct\nresults.\\n\";\n\n# TEST #0\n# For $(and ...), it will either be empty or the last value\nrun_make_test('\nNEQ = $(subst $1,,$2)\nf =\nt = true\n\nall:\n\t@echo 1 $(and    ,$t)\n\t@echo 2 $(and $t)\n\t@echo 3 $(and $t,)\n\t@echo 4 $(and z,true,$f,false)\n\t@echo 5 $(and $t,$f,$(info bad short-circuit))\n\t@echo 6 $(and $(call NEQ,a,b),true)\n\t@echo 7 $(and $(call NEQ,a,a),true)\n\t@echo 8 $(and z,true,fal,se) hi\n\t@echo 9 $(and ,true,fal,se)there\n\t@echo 10 $(and   $(e) ,$t)',\n              '',\n              \"1\\n2 true\\n3\\n4\\n5\\n6 true\\n7\\n8 se hi\\n9 there\\n10\\n\");\n\n# TEST #1\n# For $(or ...), it will either be empty or the first true value\nrun_make_test('\nNEQ = $(subst $1,,$2)\nf =\nt = true\n\nall:\n\t@echo 1 $(or    ,    )\n\t@echo 2 $(or $t)\n\t@echo 3 $(or ,$t)\n\t@echo 4 $(or z,true,$f,false)\n\t@echo 5 $(or $t,$(info bad short-circuit))\n\t@echo 6 $(or $(info short-circuit),$t)\n\t@echo 7 $(or $(call NEQ,a,b),true)\n\t@echo 8 $(or $(call NEQ,a,a),true)\n\t@echo 9 $(or z,true,fal,se) hi\n\t@echo 10 $(or ,true,fal,se)there\n\t@echo 11 $(or   $(e) ,$f)',\n              '',\n              \"short-circuit\\n1\\n2 true\\n3 true\\n4 z\\n5 true\\n6 true\\n7 b\\n8 true\\n9 z hi\\n10 truethere\\n11\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/basename",
    "content": "$description = \"The following test creates a makefile to test the suffix \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(basename src${pathsep}a.b.z.foo.c src${pathsep}hacks src.bar${pathsep}a.b.z.foo.c src.bar${pathsep}hacks hacks) \\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"src${pathsep}a.b.z.foo src${pathsep}hacks src.bar${pathsep}a.b.z.foo src.bar${pathsep}hacks hacks\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/call",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the call function.\\n\";\n\n$details = \"Try various uses of call and ensure they all give the correct\nresults.\\n\";\n\nrun_make_test(q!\n# Simple, just reverse two things\n#\nreverse = $2 $1\n\n# A complex 'map' function, using recursive 'call'.\n#\nmap = $(foreach a,$2,$(call $1,$a))\n\n# Test using a builtin; this is silly as it's simpler to do without call\n#\nmy-notdir = $(call notdir,$(1))\n\n# Test using non-expanded builtins\n#\nmy-foreach = $(foreach $(1),$(2),$(3))\nmy-if      = $(if $(1),$(2),$(3))\n\n# Test recursive invocations of call with different arguments\n#\none = $(1) $(2) $(3)\ntwo = $(call one,$(1),foo,$(2))\n\n# Test recursion on the user-defined function.  As a special case make\n# won't error due to this.\n# Implement transitive closure using $(call ...)\n#\nDEP_foo = bar baz quux\nDEP_baz = quux blarp\nrest = $(wordlist 2,$(words ${1}),${1})\ntclose = $(if $1,$(firstword $1)\\\n\t\t$(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1))))\n\nall: ; @echo '$(call reverse,bar,foo)'; \\\n        echo '$(call map,origin,MAKE reverse map)'; \\\n        echo '$(call my-notdir,a/b   c/d      e/f)'; \\\n        echo '$(call my-foreach)'; \\\n        echo '$(call my-foreach,a,,,)'; \\\n        echo '$(call my-if,a,b,c)'; \\\n        echo '$(call two,bar,baz)'; \\\n\techo '$(call tclose,foo)';\n!,\n              \"\", \"foo bar\\ndefault file file\\nb d f\\n\\n\\nb\\nbar foo baz\\nfoo bar baz blarp quux \\n\");\n\n# These won't work because call expands all its arguments first, before\n# passing them on, then marks them as resolved/simple, so they're not\n# expanded again by the function.\n#\n#        echo '$(call my-foreach,a,x y z,$$(a)$$(a))'; \\\n#        echo '$(call my-if,,$$(info don't print this),$$(info do print this))'\n#\n# $answer = \"xx yy zz\\ndo print this\\n\";\n\n# TEST eclipsing of arguments when invoking sub-calls\n\nrun_make_test(q!\nall = $1 $2 $3 $4 $5 $6 $7 $8 $9\n\nlevel1 = $(call all,$1,$2,$3,$4,$5)\nlevel2 = $(call level1,$1,$2,$3)\nlevel3 = $(call level2,$1,$2,$3,$4,$5)\n\nall:\n\t@echo $(call all,1,2,3,4,5,6,7,8,9,10,11)\n\t@echo $(call level1,1,2,3,4,5,6,7,8)\n\t@echo $(call level2,1,2,3,4,5,6,7,8)\n\t@echo $(call level3,1,2,3,4,5,6,7,8)\n!,\n              \"\", \"1 2 3 4 5 6 7 8 9\\n1 2 3 4 5\\n1 2 3\\n1 2 3\\n\");\n\n# Ensure that variables are defined in global scope even in a $(call ...)\n\ndelete $ENV{X123};\n\nrun_make_test('\ntst = $(eval export X123)\n$(call tst)\nall: ; @echo \"$${X123-not set}\"\n',\n              '', \"\\n\");\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/functions/dir",
    "content": "$description = \"The following test creates a makefile to test the dir \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(dir src${pathsep}foo.c hacks) \\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"src${pathsep} .${pathsep}\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/error",
    "content": "#                                                                    -*-Perl-*-\n\n$description = \"\\\nThe following test creates a makefile to test the error function.\";\n\n$details = \"\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE 'err = $(error Error found!)\n\nifdef ERROR1\n$(error error is $(ERROR1))\nendif\n\nifdef ERROR2\n$(error error is $(ERROR2))\nendif\n\nifdef ERROR3\nall: some; @echo $(error error is $(ERROR3))\nendif\n\nifdef ERROR4\nall: some; @echo error is $(ERROR4)\n\t@echo $(error error is $(ERROR4))\nendif\n\nsome: ; @echo Some stuff\n\ntestvar: ; @: $(err)\n';\n\nclose(MAKEFILE);\n\n# Test #1\n\n&run_make_with_options($makefile, \"ERROR1=yes\", &get_logfile, 512);\n$answer = \"$makefile:4: *** error is yes.  Stop.\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #2\n\n&run_make_with_options($makefile, \"ERROR2=no\", &get_logfile, 512);\n$answer = \"$makefile:8: *** error is no.  Stop.\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #3\n\n&run_make_with_options($makefile, \"ERROR3=maybe\", &get_logfile, 512);\n$answer = \"Some stuff\\n$makefile:12: *** error is maybe.  Stop.\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #4\n\n&run_make_with_options($makefile, \"ERROR4=definitely\", &get_logfile, 512);\n$answer = \"Some stuff\\n$makefile:17: *** error is definitely.  Stop.\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #5\n\n&run_make_with_options($makefile, \"testvar\", &get_logfile, 512);\n$answer = \"$makefile:22: *** Error found!.  Stop.\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/functions/eval",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the eval function.\";\n\n$details = \"This is a test of the eval function in GNU Make.\nThis function will evaluate inline makefile syntax and incorporate the\nresults into its internal database.\\n\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<'EOF';\ndefine Y\n  all:: ; @echo $AA\n  A = B\nendef\n\nX = $(eval $(value Y))\n\n$(eval $(shell echo A = A))\n$(eval $(Y))\n$(eval A = C)\n$(eval $(X))\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"AA\\nBA\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\n# Test to make sure defining variables when we have extra scope pushed works\n# as expected.\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile2\");\n\nprint MAKEFILE <<'EOF';\nVARS = A B\n\nVARSET = $(1) = $(2)\n\n$(foreach v,$(VARS),$(eval $(call VARSET,$v,$v)))\n\nall: ; @echo A = $(A) B = $(B)\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile2, \"\", &get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"A = A B = B\\n\";\n\n&compare_output($answer,&get_logfile(1));\n\n# Test to make sure eval'ing inside conditionals works properly\n\n$makefile3 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile3\");\n\nprint MAKEFILE <<'EOF';\nFOO = foo\n\nall:: ; @echo it\n\ndefine Y\n  all:: ; @echo worked\nendef\n\nifdef BAR\n$(eval $(Y))\nendif\n\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile3, \"\", &get_logfile);\n$answer = \"it\\n\";\n&compare_output($answer,&get_logfile(1));\n\n&run_make_with_options($makefile3, \"BAR=1\", &get_logfile);\n$answer = \"it\\nworked\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST very recursive invocation of eval\n\n$makefile3 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile3\");\n\nprint MAKEFILE <<'EOF';\n..9 := 0 1 2 3 4 5 6 7 8 9\nrev=$(eval res:=)$(foreach word,$1,$(eval res:=${word} ${res}))${res}\na:=$(call rev,${..9})\nall: ; @echo '[$(a)]'\n\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile3, \"\", &get_logfile);\n$answer = \"[         9 8 7 6 5 4 3 2 1 0 ]\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST eval with no filename context.\n# The trick here is that because EVAR is taken from the environment, it must\n# be evaluated before every command is invoked.  Make sure that works, when\n# we have no file context for reading_file (bug # 6195)\n\n$makefile4 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile4\");\n\nprint MAKEFILE <<'EOF';\nEVAR = $(eval FOBAR = 1)\nall: ; @echo \"OK\"\n\nEOF\n\nclose(MAKEFILE);\n\n$ENV{EVAR} = '1';\n&run_make_with_options($makefile4, \"\", &get_logfile);\n$answer = \"OK\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# Clean out previous information to allow new run_make_test() interface.\n# If we ever convert all the above to run_make_test() we can remove this line.\n$makefile = undef;\n\n# Test handling of backslashes in strings to be evaled.\n\nrun_make_test('\ndefine FOO\nall: ; @echo hello \\\nworld\nendef\n$(eval $(FOO))\n', '', 'hello world');\n\nrun_make_test('\ndefine FOO\nall: ; @echo '.\"'\".'he\\llo'.\"'\".'\n\t@echo world\nendef\n$(eval $(FOO))\n', '', 'he\\llo\nworld');\n\n\n# We don't allow new target/prerequisite relationships to be defined within a\n# command script, because these are evaluated after snap_deps() and that\n# causes lots of problems (like core dumps!)\n# See Savannah bug # 12124.\n\nrun_make_test('deps: ; $(eval deps: foo)', '',\n              '#MAKEFILE#:1: *** prerequisites cannot be defined in recipes.  Stop.',\n              512);\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/file",
    "content": "#                                                                    -*-perl-*-\n\n$description = 'Test the $(file ...) function.';\n\n# Test > and >>\nrun_make_test(q!\ndefine A\na\nb\nendef\nB = c d\n$(file >file.out,$(A))\n$(foreach L,$(B),$(file >>     file.out,$L))\nx:;@echo hi; cat file.out\n!,\n              '', \"hi\\na\\nb\\nc\\nd\");\n\nunlink('file.out');\n\n# Test >> to a non-existent file\nrun_make_test(q!\ndefine A\na\nb\nendef\n$(file     >>     file.out    ,$(A))\nx:;@cat file.out\n!,\n              '', \"a\\nb\");\n\nunlink('file.out');\n\n# Test > with no content\nrun_make_test(q!\n$(file >4touch)\n.PHONY:x\nx:;@cat 4touch\n!,\n              '', '');\n\n# Test >> with no content\nrun_make_test(q!\n$(file >>4touch)\n.PHONY:x\nx:;@cat 4touch\n!,\n              '', '');\nunlink('4touch');\n\n# Test > to a read-only file\nif (defined $ERR_read_only_file) {\n    touch('file.out');\n    chmod(0444, 'file.out');\n\n    run_make_test(q!\ndefine A\na\nb\nendef\n$(file     >     file.out,$(A))\nx:;@cat file.out\n!,\n                  '', \"#MAKEFILE#:6: *** open: file.out: $ERR_read_only_file.  Stop.\",\n                  512);\n\n    unlink('file.out');\n}\n\n# Use variables for operator and filename\nrun_make_test(q!\ndefine A\na\nb\nendef\nOP = >\nFN = file.out\n$(file     $(OP)     $(FN),$(A))\nx:;@cat file.out\n!,\n              '', \"a\\nb\");\n\nunlink('file.out');\n\n# Don't add newlines if one already exists\nrun_make_test(q!\ndefine A\na\nb\n\nendef\n$(file >file.out,$(A))\nx:;@cat file.out\n!,\n              '', \"a\\nb\");\n\nunlink('file.out');\n\n# Empty text\nrun_make_test(q!\n$(file >file.out,)\n$(file >>file.out,)\nx:;@cat file.out\n!,\n              '', \"\\n\\n\");\n\nunlink('file.out');\n\n# Reading files\nrun_make_test(q!\n$(file >file.out,A = foo)\nX1 := $(file <file.out)\n$(file >>file.out,B = bar)\n$(eval $(file <file.out))\n\nx:;@echo '$(X1)'; echo '$(A)'; echo '$(B)'\n!,\n              '', \"A = foo\\nfoo\\nbar\\n\");\n\nunlink('file.out');\n\n# Read an empty file.\ntouch(\"file.out\");\nrun_make_test(q!# empty file\nX1 := x$(file <file.out)y\nx:;@echo '$(X1)'\n!,\n              '', \"xy\\n\");\n\nunlink('file.out');\n\n# Read a file whose full contents is a newline.\ncreate_file('file.out', \"\\n\");\nrun_make_test(q!# <nl>\nX1 := x$(file <file.out)y\nx:;@echo '$(X1)'\n!,\n              '', \"xy\\n\");\n\nunlink('file.out');\n\n# Read a file which does not end with a newline.\ncreate_file('file.out', \"hello\");\n# echo prints a trailig newline, because run_make_test appends a newline.\nrun_make_test(q!# hello\nX1 := x$(file <file.out)y\nx:;@echo $(X1)\n!,\n              '', \"xhelloy\\n\");\n\nunlink('file.out');\n\n# Read a file which ends with a newline.\ncreate_file('file.out', \"hello\\n\");\n# echo prints a trailig newline, because run_make_test appends a newline.\nrun_make_test(q!# hello<nl>\nX1 := x$(file <file.out)y\nx:;@echo '$(X1)'\n!,\n              '', \"xhelloy\\n\");\n\n\nunlink('file.out');\n\n# Read a file which ends with multiple newlines.\ncreate_file('file.out', \"hello\\n\\n\");\nrun_make_test(q!# hello<nl><nl>\nX1 := x$(file <file.out)y\nexport X1\nx:;@echo \"$$X1\"\n!,\n              '', \"xhello\\ny\\n\");\n\nunlink('file.out');\n\n# Read a file whose contents exceed 200 bytes.\n# 200 is the initial size of variable_buffer.\n# File bigger than 200 bytes causes a realloc.\n# The size of the file in this test not only exceeds 200 bytes, it exceeds 65k.\n# Use $(info ...) here to avoid command line limitations\n\nmy $s = \"hello world, hello world, hello world, hello world, hello world\";\nmy $answer = $s x 2000;\ncreate_file('file.out', $answer);\nrun_make_test(q!# <hugestring>\nX1 := x$(file <file.out)y\nx:;@$(info $(X1))\n!,\n              '', \"x${answer}y\\n#MAKE#: 'x' is up to date.\\n\");\n\nunlink('file.out');\n\n# Reading from non-existent file\nrun_make_test(q!\nX1 := $(file <file.out)\nx:;@echo '$(X1)';\n!,\n              '', \"\\n\");\n\n# Extra arguments in read mode\nrun_make_test(q!\nX1 := $(file <file.out,foo)\nx:;@echo '$(X1)';\n!,\n              '', \"#MAKEFILE#:2: *** file: too many arguments.  Stop.\\n\", 512);\n\n\n# Missing filename\nrun_make_test('$(file >)', '',\n              \"#MAKEFILE#:1: *** file: missing filename.  Stop.\\n\", 512);\n\nrun_make_test('$(file >>)', '',\n              \"#MAKEFILE#:1: *** file: missing filename.  Stop.\\n\", 512);\n\nrun_make_test('$(file <)', '',\n              \"#MAKEFILE#:1: *** file: missing filename.  Stop.\\n\", 512);\n\n# Bad call\n\nrun_make_test('$(file foo)', '',\n              \"#MAKEFILE#:1: *** file: invalid file operation: foo.  Stop.\\n\", 512);\n\n# SV 17448: check whitespace\ncreate_file('out1', \"1\\n\");\n\nrun_make_test(q!\nall:;$(info $(file <  out1  ))\n!,\n              '', \"1\\n#MAKE#: 'all' is up to date.\");\n\nunlink('out1');\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/filter-out",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the filter and filter-out functions.\";\n\n$details = \"The makefile created in this test has two variables.  The\nfilter-out function is first used to discard names ending in\n.o with a single simple pattern.  The second filter-out function\naugments the simple pattern with three literal names, which are\nalso added to the text argument.  This tests an internal hash table\nwhich is only used if there are multiple literals present in both\nthe pattern and text arguments.  The result of both filter-out\nfunctions is the same single .elc name.\\n\";\n\n# Basic test -- filter\nrun_make_test(q!\nfiles1 := $(filter %.o, foo.elc bar.o lose.o)\nfiles2 := $(filter %.o foo.i, foo.i bar.i lose.i foo.elc bar.o lose.o)\nall: ; @echo '$(files1) $(files2)'\n!,\n              '', \"bar.o lose.o foo.i bar.o lose.o\\n\");\n\n# Basic test -- filter-out\nrun_make_test(q!\nfiles1 := $(filter-out %.o, foo.elc bar.o lose.o)\nfiles2 := $(filter-out foo.i bar.i lose.i %.o, foo.i bar.i lose.i foo.elc bar.o lose.o)\nall: ; @echo '$(files1) $(files2)'\n!,\n              '', \"foo.elc foo.elc\\n\");\n\n# Force use of hash (see function.c:func_filter_filterout for params)\n\nmy $base = 'foo.1 foo.2 foo.3 foo.4 foo.5 foo.6 foo.7 foo.8 foo.9 foo.10';\n\nmy $base10 = join(' ', ($base) x 10);\nmy $out3 = join(' ', ('foo.3') x 10);\nmy $out456 = join(' ', ('foo.4 foo.5 foo.6') x 10);\n\nrun_make_test(\"words := $base10\" . q!\nfiles1 := $(filter %.3, $(words))\nfiles2 := $(filter %.4 foo.5 foo.6, $(words))\nall: ; @echo '$(files1) $(files2)'\n!,\n              '', \"$out3 $out456\\n\");\n\n\n# Escaped patterns\nrun_make_test(q!all:;@echo '$(filter foo\\%bar,foo%bar fooXbar)'!,\n              '', \"foo%bar\\n\");\n\nrun_make_test(q!all:;@echo '$(filter foo\\%\\%\\\\\\\\\\%\\%bar,foo%%\\\\%%bar fooX\\\\Ybar)'!,\n              '', \"foo%%\\\\%%bar\\n\");\n\nrun_make_test(q!\nX = $(filter foo\\\\\\\\\\%bar,foo\\%bar foo\\Xbar)\nall:;@echo '$(X)'!,\n              '', \"foo\\\\%bar\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/findstring",
    "content": "$description = \"The following test creates a makefile to test the findstring \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(findstring port, reporter)\\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\n                       \"\",\n                       &get_logfile,\n                       0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"port\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/flavor",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the flavor function.\";\n\n$details = \"\";\n\n\n# Test #1: Test general logic.\n#\nrun_make_test('\ns := s\nr = r\n\n$(info u $(flavor u))\n$(info s $(flavor s))\n$(info r $(flavor r))\n\nra += ra\nrc ?= rc\n\n$(info ra $(flavor ra))\n$(info rc $(flavor rc))\n\ns += s\nr += r\n\n$(info s $(flavor s))\n$(info r $(flavor r))\n\n\n.PHONY: all\nall:;@:\n',\n'',\n'u undefined\ns simple\nr recursive\nra recursive\nrc recursive\ns simple\nr recursive');\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/functions/foreach",
    "content": "#                                                                    -*-perl-*-\n# $Id$\n\n$description = \"Test the foreach function.\";\n\n$details = \"This is a test of the foreach function in gnu make.\nThis function starts with a space separated list of\nnames and a variable. Each name in the list is substituted\ninto the variable and the given text evaluated. The general\nform of the command is $(foreach var,\\$list,\\$text). Several\ntypes of foreach loops are tested\\n\";\n\n\n# TEST 0\n\n# Set an environment variable that we can test in the makefile.\n$ENV{FOOFOO} = 'foo foo';\n\nrun_make_test(\"space = ' '\".'\nnull :=\nauto_var = udef space CC null FOOFOO MAKE foo CFLAGS WHITE @ <\nfoo = bletch null @ garf\nav = $(foreach var, $(auto_var), $(origin $(var)) )\noverride WHITE := BLACK\nfor_var = $(addsuffix .c,foo $(null) $(foo) $(space) $(av) )\nfe = $(foreach var2, $(for_var),$(subst .c,.o, $(var2) ) )\nall: auto for2\nauto : ; @echo $(av)\nfor2: ; @echo $(fe)',\n              '-e WHITE=WHITE CFLAGS=',\n              \"undefined file default file environment override default file command line override automatic automatic\nfoo.o bletch.o null.o @.o garf.o .o    .o undefined.o file.o default.o file.o environment.o override.o default.o file.o command.o line.o override.o automatic.o automatic.o\");\n\n# TEST 1: Test that foreach variables take precedence over global\n# variables in a global scope (like inside an eval).  Tests bug #11913\n\nrun_make_test('\n.PHONY: all target\nall: target\n\nx := BAD\n\ndefine mktarget\ntarget: x := $(x)\ntarget: ; @echo \"$(x)\"\nendef\n\nx := GLOBAL\n\n$(foreach x,FOREACH,$(eval $(value mktarget)))',\n              '',\n              'FOREACH');\n\n# Allow variable names with trailing space\nrun_make_test(q!\n$(foreach \\\n  a \\\n, b c d \\\n, $(info $a))\nall:;@:\n!,\n              \"\", \"b\\nc\\nd\\n\");\n\n# Allow empty variable names.  We still expand the body.\n\nrun_make_test('\nx = $(foreach ,1 2 3,a)\ny := $x\n\nall: ; @echo $y',\n              '', \"a a a\\n\");\n\n# Check some error conditions.\n\nrun_make_test('\nx = $(foreach )\ny = $x\n\nall: ; @echo $y',\n              '',\n              \"#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'.  Stop.\",\n              512);\n\nrun_make_test('\nx = $(foreach x,y)\ny := $x\n\nall: ; @echo $y',\n              '',\n              \"#MAKEFILE#:2: *** insufficient number of arguments (2) to function 'foreach'.  Stop.\",\n              512);\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/guile",
    "content": "#                                                                    -*-perl-*-\n\n$description = 'Test the $(guile ...) function.';\n\n$details = 'This only works on systems that support it.';\n\n# If this instance of make doesn't support GNU Guile, skip it\n# This detects if guile is loaded using the \"load\" directive\n# $makefile = get_tmpfile();\n# open(MAKEFILE, \"> $makefile\") || die \"Failed to open $makefile: $!\\n\";\n# print MAKEFILE q!\n# -load guile\n# all: ; @echo $(filter guile,$(.LOADED))\n# !;\n# close(MAKEFILE) || die \"Failed to write $makefile: $!\\n\";\n# $cmd = subst_make_string(\"#MAKEPATH# -f $makefile\");\n# $log = get_logfile(0);\n# $code = run_command_with_output($log, $cmd);\n# read_file_into_string ($log) eq \"guile\\n\" and $FEATURES{guile} = 1;\n\n# If we don't have Guile support, never mind.\nexists $FEATURES{guile} or return -1;\n\n# Guile and Valgrind/ASAN don't play together at all.\nexists $FEATURES{sanitize} and return -1;\n$valgrind and return -1;\n\n# Verify simple data type conversions\n# Currently we don't support vectors:\n#    echo '$(guile (vector 1 2 3))'; \\\nrun_make_test(q!\nx:;@echo '$(guile #f)'; \\\n    echo '$(guile #t)'; \\\n    echo '$(guile #\\c)'; \\\n    echo '$(guile 1234)'; \\\n    echo '$(guile 'foo)'; \\\n    echo '$(guile \"bar\")'; \\\n    echo '$(guile (cons 'a 'b))'; \\\n    echo '$(guile '(a b (c . d) 1 (2) 3))'\n!,\n              '', \"\\n#t\\nc\\n1234\\nfoo\\nbar\\na b\\na b c d 1 2 3\");\n\n# Verify guile functions in variables -- SV 43378\nrun_make_test(q!\nres := $(guile #f) \\\n       $(guile #t) \\\n       $(guile #\\c) \\\n       $(guile 1234) \\\n       $(guile 'foo) \\\n       $(guile \"bar\") \\\n       $(guile (cons 'a 'b)) \\\n       $(guile '(a b (c . d) 1 (2) 3))\nx:;@echo '$(res)'\n!,\n              '', \" #t c 1234 foo bar a b a b c d 1 2 3\");\n\n# Verify the gmk-expand function\nrun_make_test(q!\nVAR = $(guile (gmk-expand \"$(shell echo hi)\"))\nx:;@echo '$(VAR)'\n!,\n              '', \"hi\");\n\n# Verify the gmk-eval function\n# Prove that the string is expanded only once (by eval)\nrun_make_test(q!\nTEST = bye\nEVAL = VAR = $(TEST) $(shell echo there)\n$(guile (gmk-eval \"$(value EVAL)\"))\nTEST = hi\nx:;@echo '$(VAR)'\n!,\n              '', \"hi there\");\n\n# Verify the gmk-eval function with a list\nrun_make_test(q!\n$(guile (gmk-eval '(VAR = 1 (2) () 3)))\nx:;@echo '$(VAR)'\n!,\n              '', \"1 2 3\");\n\n# Verify the gmk-var function\nrun_make_test(q!\nVALUE = hi $(shell echo there)\nVAR = $(guile (gmk-var \"VALUE\"))\nx:;@echo '$(VAR)'\n!,\n              '', \"hi there\");\n\n# Verify the gmk-var function with a symbol\nrun_make_test(q!\nVALUE = hi $(shell echo there)\nVAR = $(guile (gmk-var 'VALUE))\nx:;@echo '$(VAR)'\n!,\n              '', \"hi there\");\n\n# Write a Guile program using define and run it\nrun_make_test(q!\n# Define the \"fib\" function in Guile\ndefine fib\n;; A procedure for counting the n:th Fibonacci number\n;; See SICP, p. 37\n(define (fib n)\n  (cond ((= n 0) 0)\n        ((= n 1) 1)\n        (else (+ (fib (- n 1))\n                 (fib (- n 2))))))\nendef\n$(guile $(fib))\n\n# Now run it\nx:;@echo $(guile (fib $(FIB)))\n!,\n              'FIB=10', \"55\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/if",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the if function.\\n\";\n\n$details = \"Try various uses of if and ensure they all give the correct\nresults.\\n\";\n\nopen(MAKEFILE, \"> $makefile\");\n\nprint MAKEFILE <<EOMAKE;\nNEQ = \\$(subst \\$1,,\\$2)\ne =\n\nall:\n\\t\\@echo 1 \\$(if    ,true,false)\n\\t\\@echo 2 \\$(if ,true,)\n\\t\\@echo 3 \\$(if ,true)\n\\t\\@echo 4 \\$(if z,true,false)\n\\t\\@echo 5 \\$(if z,true,\\$(shell echo hi))\n\\t\\@echo 6 \\$(if ,\\$(shell echo hi),false)\n\\t\\@echo 7 \\$(if \\$(call NEQ,a,b),true,false)\n\\t\\@echo 8 \\$(if \\$(call NEQ,a,a),true,false)\n\\t\\@echo 9 \\$(if z,true,fal,se) hi\n\\t\\@echo 10 \\$(if ,true,fal,se)there\n\\t\\@echo 11 \\$(if \\$(e) ,true,false)\nEOMAKE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n$answer = \"1 false\\n2\\n3\\n4 true\\n5 true\\n6 false\\n7 true\\n8 false\\n9 true hi\\n10 fal,sethere\\n11 false\\n\";\n&compare_output($answer, &get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/intcmp",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the intcmp function.\\n\";\n\n$details = \"Try various uses of intcmp and ensure they all give the correct\nresults.\\n\";\n\nrun_make_test('# Negative\nn = -10\n# Zero\nz = 0\n# Positive\np = 888\nq = 889\nhuge = 8857889956778499040639527525992734031025567913257255490371761260681427\n.RECIPEPREFIX = >\nall:\n> @echo 0_1 $(intcmp $n,$n)\n> @echo 0_2 $(intcmp $z,$z)\n> @echo 0_3 $(intcmp -$z,$z)\n> @echo 0_4 $(intcmp $p,$p)\n> @echo 0_5 $(intcmp $n,$z)\n> @echo 0_6 $(intcmp $z,$n)\n> @echo 1_1 $(intcmp $n,$n,$(shell echo lt))\n> @echo 1_2 $(intcmp $n,$z,$(shell echo lt))\n> @echo 1_3 $(intcmp $z,$n,$(shell echo lt))\n> @echo 2_1 $(intcmp $n,$p,lt,ge)\n> @echo 2_2 $(intcmp $z,$z,lt,ge)\n> @echo 2_3 $(intcmp $p,$n,lt,ge)\n> @echo 3_0 $(intcmp $p,$n,lt,eq,)\n> @echo 3_1 $(intcmp $z,$p,lt,eq,gt)\n> @echo 3_2 $(intcmp $p,$z,lt,eq,gt)\n> @echo 3_3 $(intcmp $p,$p,lt,eq,gt)\n> @echo 3_4 $(intcmp $p,$q,lt,eq,gt)\n> @echo 3_5 $(intcmp $q,$p,lt,eq,gt)\n> @echo 3_6 $(intcmp -$p,-$q,lt,eq,gt)\n> @echo 3_7 $(intcmp -$q,-$p,lt,eq,gt)\n> @echo 4_1 $(intcmp -$(huge),$(huge),lt,eq,gt)\n> @echo 4_2 $(intcmp $(huge),-$(huge),lt,eq,gt)\n> @echo 4_3 $(intcmp -$(huge),-$(huge),lt,eq,gt)\n> @echo 4_4 $(intcmp +$(huge),$(huge),lt,eq,gt)\n', '', '0_1 -10\n0_2 0\n0_3 0\n0_4 888\n0_5\n0_6\n1_1\n1_2 lt\n1_3\n2_1 lt\n2_2 ge\n2_3 ge\n3_0\n3_1 lt\n3_2 gt\n3_3 eq\n3_4 lt\n3_5 gt\n3_6 gt\n3_7 lt\n4_1 lt\n4_2 gt\n4_3 eq\n4_4 eq\n');\n\n# Test error conditions\n\nrun_make_test('\nintcmp-e1: ; @echo $(intcmp 12a,1,foo)\nintcmp-e2: ; @echo $(intcmp 0,,foo)\nintcmp-e3: ; @echo $(intcmp -1,)\nintcmp-e4: ; @echo $(intcmp ,55)',\n              'intcmp-e1',\n              \"#MAKEFILE#:2: *** non-numeric first argument to 'intcmp' function: '12a'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'intcmp-e2',\n              \"#MAKEFILE#:3: *** non-numeric second argument to 'intcmp' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'intcmp-e3',\n              \"#MAKEFILE#:4: *** non-numeric second argument to 'intcmp' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'intcmp-e4',\n              \"#MAKEFILE#:5: *** non-numeric first argument to 'intcmp' function: empty value.  Stop.\",\n              512);\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/functions/join",
    "content": "$description = \"The following test creates a makefile to test the join \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(join a b c,foo      hacks .pl1) \\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"afoo bhacks c.pl1\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/let",
    "content": "#                                                                    -*-perl-*-\n# $Id$\n\n$description = \"Test the let function.\";\n\n$details = \"This is a test of the let function in gnu make.\nThis function destructures a list of values and binds each\nvalue to a variable name in a list of variable names.\nSuperfluous variable names are assigned the empty string and\nthe remaining values are assigned to the last variable name.\nThe binding holds for the duration of the evaluation of the\ngiven text and no longer.  The general form of the command\nis $(let \\$vars,\\$list,\\$text).  Several types of let\nassignments are tested\\n\";\n\n# check for mismatched var and list word counts\nrun_make_test(q!\na = bad\nb = news\nx = $(let a b,1 2,$a $b)\ny = $(let a,1 2,$a)\nz = $(let a b,1,$a $b)\nall:;@echo 'a=,$a,' 'b=,$b,' 'x=,$x,' 'y=,$y,' 'z=,$z,'\n!,\n    '', \"a=,bad, b=,news, x=,1 2, y=,1 2, z=,1 ,\\n\");\n\n# check for whitespace\nrun_make_test(q!\na = bad\nb = news\nx = $(let a b,   1   2   ,+$a+$b+)\ny = $(let a,   1  2   ,+$a+)\nz = $(let a b,  1   ,+$a+$b+)\nall:;@echo 'a=,$a,' 'b=,$b,' 'x=,$x,' 'y=,$y,' 'z=,$z,'\n!,\n    '', \"a=,bad, b=,news, x=,+1+2   +, y=,+1  2   +, z=,+1++,\\n\");\n\n# Allow empty variable names and empty value list.\n# We still expand the list and body.\nrun_make_test('\nnull =\nv = $(let    ,$(info blankvar),abc)\nx = $(let $(null),$(info side-effect),abc)\ny = $(let y,,$ydef)\nz = $(let a b, ,+$a+$b+)\n\nall: ; @echo $v/$x/$y/$z',\n              '', \"blankvar\\nside-effect\\nabc/abc/def/+++\\n\");\n\n# The example macro from the manual.\nrun_make_test('\nreverse = $(let first rest,$1,$(if $(rest),$(call reverse,$(rest)) )$(first))\n\nall: ; @echo $(call reverse, \\\n                 moe   miny  meeny eeny \\\n              )',\n              '', \"eeny meeny miny moe\\n\");\n\n\n# Set an environment variable that we can test in the makefile.\n$ENV{FOOFOO} = 'foo foo';\n\n# Verify masking: expansion outside the scope of let is unaffected.\nrun_make_test('\nauto_var = \\\n  udef \\\n  CC \\\n  FOOFOO \\\n  MAKE \\\n  foo \\\n  CFLAGS \\\n  WHITE \\\n  @ \\\n  <\nav = $(foreach var, $(auto_var), $(origin $(var)) )\nfoo = bletch null @ garf\noverride WHITE := BLACK\n\ndefine mktarget\ntarget: foo := $(foo)\ntarget: ; @echo $(AR)_$(foo)_\nendef\n\nall: auto target\nauto: ; @echo $(let $(auto_var),,$(av)) $(av)\n$(let AR foo,bar foo ,$(eval $(value mktarget)))',\n              '-e WHITE=WHITE CFLAGS=',\n              \"automatic automatic automatic automatic automatic automatic automatic automatic automatic undefined default environment override default file command line override automatic automatic\nar_foo _\n\");\n\n\n# Check some error conditions.\nrun_make_test('\nx = $(let )\ny = $x\n\nall: ; @echo $y',\n              '',\n              \"#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'let'.  Stop.\",\n              512);\n\nrun_make_test('\nx = $(let x,y)\ny := $x\n\nall: ; @echo $y',\n              '',\n              \"#MAKEFILE#:2: *** insufficient number of arguments (2) to function 'let'.  Stop.\",\n              512);\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/notdir",
    "content": "$description = \"The following test creates a makefile to test the notdir \"\n              .\"function.\";\n\n$details = \"\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string := \\$(notdir ${pathsep}src${pathsep}foo.c hacks) \\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(string) \\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"foo.c hacks\\n\";\n\n# COMPARE RESULTS\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/origin",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the origin function.\";\n\n$details = \"This is a test of the origin function in gnu make.\nThis function will report on where a variable was\ndefined per the following list:\n\n'undefined'            never defined\n'default'              default definition\n'environment'          environment var without -e\n'environment override' environment var with    -e\n'file'                 defined in makefile\n'command line'         defined on the command line\n'override'             defined by override in makefile\n'automatic'            Automatic variable\\n\";\n\n# Set an environment variable\n$ENV{MAKETEST} = 1;\n\nrun_make_test('\nfoo := bletch garf\nauto_var = undefined CC MAKETEST MAKE foo CFLAGS WHITE @\nav = $(foreach var, $(auto_var), $(origin $(var)) )\noverride WHITE := BLACK\n.RECIPEPREFIX = >\nall: auto\n> @echo $(origin undefined)\n> @echo $(origin CC)\n> @echo $(origin MAKETEST)\n> @echo $(origin MAKE)\n> @echo $(origin foo)\n> @echo $(origin CFLAGS)\n> @echo $(origin WHITE)\n> @echo $(origin @)\nauto :\n> @echo $(av)',\n    '-e WHITE=WHITE CFLAGS=',\n    'undefined default environment override default file command line override automatic\nundefined\ndefault\nenvironment override\ndefault\nfile\ncommand line\noverride\nautomatic');\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/realpath",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the realpath functions.\";\n\n$details = \"\";\n\n# Check the local directory's realpath\nrun_make_test('\nifneq ($(realpath .),$(CURDIR))\n  $(warning $(realpath .) != $(CURDIR))\nendif\n\nifneq ($(realpath ./),$(CURDIR))\n  $(warning $(realpath ./) != $(CURDIR))\nendif\n\nifneq ($(realpath .///),$(CURDIR))\n  $(warning $(realpath .///) != $(CURDIR))\nendif\n\n.PHONY: all\nall: ; @:\n',\n              '', '');\n\n# Find the realpath to the root of the partition\ncreate_file('root.mk', 'all:;$(info $(realpath /))');\nmy $root = `$make_path -sf root.mk`;\nunlink('root.mk');\n$root =~ s/\\r?\\n//g;\n\nmy $tst = '\nifneq ($(realpath /.),#ROOT#)\n  $(warning $(realpath /.) != #ROOT#)\nendif\n\nifneq ($(realpath /./),#ROOT#)\n  $(warning $(realpath /./) != #ROOT#)\nendif\n\nifneq ($(realpath /.///),#ROOT#)\n  $(warning $(realpath /.///) != #ROOT#)\nendif\n\nifneq ($(realpath /..),#ROOT#)\n  $(warning $(realpath /..) != #ROOT#)\nendif\n\nifneq ($(realpath /../),#ROOT#)\n  $(warning $(realpath /../) != #ROOT#)\nendif\n\nifneq ($(realpath /..///),#ROOT#)\n  $(warning $(realpath /..///) != #ROOT#)\nendif\n\nifneq ($(realpath . /..),$(CURDIR) #ROOT#)\n  $(warning $(realpath . /..) != $(CURDIR) #ROOT#)\nendif\n\n.PHONY: all\nall: ; @:\n';\n$tst =~ s/#ROOT#/$root/g;\nrun_make_test($tst, '', '');\n\n# On Windows platforms \"//\" means something special.  So, don't do these tests\n# there.\n\nif ($port_type ne 'W32') {\n  $tst = '\nifneq ($(realpath ///),#ROOT#)\n  $(warning $(realpath ///) != #ROOT#)\nendif\n\nifneq ($(realpath ///.),#ROOT#)\n  $(warning $(realpath ///.) != #ROOT#)\nendif\n\nifneq ($(realpath ///..),#ROOT#)\n  $(warning $(realpath ///..) != #ROOT#)\nendif\n\n.PHONY: all\nall: ; @:';\n  $tst =~ s/#ROOT#/$root/g;\n\n  run_make_test($tst, '', '');\n}\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/functions/shell",
    "content": "#                                                                    -*-perl-*-\n\n$description = 'Test the $(shell ...) function.';\n\n$details = '';\n\n# Test standard shell\nrun_make_test('.PHONY: all\nOUT := $(shell echo hi)\nall: ; @echo $(OUT)\n              ','','hi');\n\n# Test shells inside rules.\nrun_make_test('.PHONY: all\nall: ; @echo $(shell echo hi)\n              ','','hi');\n\n# Verify .SHELLSTATUS\nrun_make_test('.PHONY: all\nPRE := $(.SHELLSTATUS)\n$(shell exit 0)\nOK := $(.SHELLSTATUS)\n$(shell exit 1)\nBAD := $(.SHELLSTATUS)\nall: ; @echo PRE=$(PRE) OK=$(OK) BAD=$(BAD)\n              ','','PRE= OK=0 BAD=1');\n\n# Test unescaped comment characters in shells.  Savannah bug #20513\nrun_make_test(q!\nFOO := $(shell echo '#')\nfoo: ; echo '$(FOO)'\n!,\n              '', \"echo '#'\\n#\\n\");\n\n# Test that exported variables are passed to $(shell ...)\n$ENV{FOO} = 'baz';\nrun_make_test(q!\nOUT = $(shell echo $$FOO)\nfoo: ; @echo '$(OUT)'\n!,\n              '', 'baz');\n\n$ENV{FOO} = 'baz';\nrun_make_test(q!\nFOO = bar\nOUT = $(shell echo $$FOO)\nfoo: ; @echo '$(OUT)'\n!,\n              '', 'bar');\n\nrun_make_test(q!\nexport FOO = bar\nOUT = $(shell echo $$FOO)\nfoo: ; @echo '$(OUT)'\n!,\n              '', 'bar');\n\n# Test shells inside exported environment variables, simply expanded.\nrun_make_test('\nexport HI := $(shell echo hi)\n.PHONY: all\nall: ; @echo $$HI\n',\n              '','hi');\n\n# Test shells inside exported environment variables.  See SV 10593\nrun_make_test('\nexport HI = $(shell echo hi)\n.PHONY: all\nall: ; @echo $$HI\n',\n              '',\"hi\");\n\n$ENV{HI} = 'foo';\nrun_make_test('\nHI = $(shell echo hi)\n.PHONY: all\nall: ; @echo $$HI\n',\n              '',\"hi\");\n\n$ENV{HI} = 'foo';\nrun_make_test('\nHI = $(shell echo hi)\nbad := $(HI)\n.PHONY: all\nall: ; @echo $$HI $(bad)\n',\n              '',\"hi hi\");\n\n# SV 63016: Exported variable that contains a variable containing $(shell...)\n\nrun_make_test('\nHI = $(shell echo hi)\nexport bad = $(HI)\n.PHONY: all\nall:; : $(HI)\n',\n              '',\": hi\");\n\n$ENV{HI} = 'outer';\nrun_make_test('\nexport HI = $(shell echo $$HI)\n.PHONY: all\nall:; @echo $$HI\n',\n              '',\"outer\");\n\n$ENV{HI} = 'outer';\nrun_make_test('\nexport HI = $(shell echo $$HI)\n.PHONY: all\nall:; : $(HI)\n',\n              '',\": outer\");\n\nif ($port_type ne 'W32') {\n    # Test shell errors in recipes including offset\n    # This needs to be ported to Windows, or else Windows error messages\n    # need to converted to look like more normal make errors.\n    run_make_test('\n.RECIPEPREFIX = >\nall:\n>@echo hi\n>$(shell ./basdfdfsed there)\n>@echo $(.SHELLSTATUS)\n',\n                  '', \"#MAKE#: ./basdfdfsed: $ERR_no_such_file\\nhi\\n127\\n\");\n\n    run_make_test('\n$(shell ./basdfdfsed where)\nall: ; @echo $(.SHELLSTATUS)\n',\n                  '', \"#MAKE#: ./basdfdfsed: $ERR_no_such_file\\n127\\n\");\n\n    # Test SHELLSTATUS for kill.\n    # This test could be ported to Windows, using taskkill ... ?\n\n    # Figure out the exit code for SIGINT\n    my $pid = fork();\n    if (! $pid) {\n        exec('kill -2 $$') or die \"exec: Cannot execute sleep\\n\";\n    }\n    waitpid($pid, 0);\n    # .SHELLSTATUS for a signal gives 128 + the signal number\n    my $ret = $?;\n    if ($ret > 255) {\n       # Solaris 10 perl 5.8.4 puts signal number + 128 into the high 8 bits.\n       $ret >>= 8;\n    }\n    if ($osname ne 'os390') {\n      $ret |= 128;\n    }\n\n    run_make_test('.PHONY: all\n$(shell kill -2 $$$$)\nSTAT := $(.SHELLSTATUS)\nall: ; @echo STAT=$(STAT)\n              ','',\"STAT=$ret\\n\");\n\n    # Test that not-found errors can be redirected\n    if ($ERR_command_not_found) {\n        $_ = $ERR_command_not_found;\n        s/#CMDNAME#/bad-command/g;\n        run_make_test(q!\nout := $(shell bad-command 2>&1)\nall: ; @echo '$(.SHELLSTATUS): $(out)'\n!,\n                      '', \"127: $_\\n\");\n    }\n\n    # If we're using pipes for jobserver, then we will close them and not\n    # allow them to be available to sub-makes invoked via $(shell ...)\n    if (exists $FEATURES{'jobserver'}) {\n        run_make_test(q!\nifeq ($(ELT),)\ndefault:; @$(MAKE) -f #MAKEFILE# ELT=1\nelse ifeq ($(ELT),1)\nOUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)\n$(info $(OUTPUT))\ndefault:;: $(ELT)\nelse\ndefault:;: $(ELT)\nendif\n!,\n                      '--no-print-directory -j2 --jobserver-style=pipe', \"#MAKE#[2]: warning: jobserver unavailable: using -j1 (add '+' to parent make rule)\\n: 2\\n: 1\");\n    }\n\n    # This crashes if we use vfork and don't reset environ properly\n    run_make_test(q!\nexport PATH = $(shell echo \"tests:$$PATH\")\nfoo = $(shell echo yes)\n\nall:;echo $(foo)\n!,\n                  '', \"echo yes\\nyes\\n\");\n}\n\n# If we're not using pipes for jobserver, then they are available in sub-makes\n# invoked by $(shell ...)\nif ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {\n    run_make_test(q!\nifeq ($(ELT),)\ndefault:; @$(MAKE) -f #MAKEFILE# ELT=1\nelse ifeq ($(ELT),1)\nOUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)\n$(info $(OUTPUT))\ndefault:;: $(ELT)\nelse\ndefault:;: $(ELT)\nendif\n!,\n                  '--no-print-directory -j2', \": 2\\n: 1\");\n}\n\n# sv 65323. Check for bash, because such long variable name causes ksh to\n# segfault.\nif (-x '/bin/bash') {\n    # sv 65172.\n    # Buffer overrun in recursively_expand_for_file on a variable with a long\n    # name.\n    my $v = \"a1234567890\" x 4 x 1000;\n    run_make_test(\"\nSHELL:=/bin/bash\nexport $v=\\$(shell echo hello)\nall:; \\@echo \\$\\$$v\n\", '', \"hello\\n\");\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/sort",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to verify\nthe ability of make to sort lists of object. Sort\nwill also remove any duplicate entries. This will also\nbe tested.\";\n\n$details = \"The make file is built with a list of object in a random order\nand includes some duplicates. Make should sort all of the elements\nremove all duplicates\\n\";\n\nrun_make_test('\nfoo := moon_light days\nfoo1:= jazz\nbar := captured \nbar2 = boy end, has rise A midnight \nbar3:= $(foo)\ns1  := _by\ns2  := _and_a\nt1  := $(addsuffix $(s1), $(bar) )\nt2  := $(addsuffix $(s2), $(foo1) )\nt3  := $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) \nt4  := $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) \nt5  := $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) \nt6  := $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) \nt7  := $(t6) $(t6) $(t6) \np1  := $(addprefix $(foo1), $(s2) )\nblank:= \nall:\n\t@echo $(sort $(bar2) $(foo)  $(addsuffix $(s1), $(bar) ) $(t2) $(bar2) $(bar3))\n\t@echo $(sort $(blank) $(foo) $(bar2) $(t1) $(p1) )\n\t@echo $(sort $(foo) $(bar2) $(t1) $(t4) $(t5) $(t7) $(t6) )\n',\n              '', 'A boy captured_by days end, has jazz_and_a midnight moon_light rise\nA boy captured_by days end, has jazz_and_a midnight moon_light rise\nA boy captured_by days end, has jazz_and_a midnight moon_light rise\n');\n\n\n# Test with non-space/tab whitespace.  Note that you can't see the\n# original bug except using valgrind.\n\nrun_make_test(\"FOO = a b\\tc\\rd\\fe \\f \\f \\f \\f \\ff\nall: ; \\@echo \\$(words \\$(sort \\$(FOO)))\\n\",\n              '', \"6\\n\");\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/functions/strip",
    "content": "#                                                                    -*-perl-*-\n$description = \"The following test creates a makefile to verify\nthe ability of make to strip white space from lists of object.\\n\";\n\n\n$details = \"The make file is built with a list of objects that contain white space\nThese are then run through the strip command to remove it. This is then\nverified by echoing the result.\\n\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<'EOMAKE';\nTEST1 := \"Is this TERMINAL fun?                                                               What makes you believe is this terminal fun?                                                                                                                                               JAPAN is a WONDERFUL planet -- I wonder if we will ever reach                                         their level of COMPARATIVE SHOPPING...\"\nE :=\nTEST2 := $E   try this     and\t\tthis     \t$E\n\ndefine TEST3\n\nand these\t        test out\n\n\nsome\nblank lines\n\n\n\nendef\n\n.PHONY: all\nall:\n\t@echo '$(strip  $(TEST1) )'\n\t@echo '$(strip  $(TEST2) )'\n\t@echo '$(strip  $(TEST3) )'\n\nspace: ; @echo '$(strip ) $(strip  \t   )'\n\nEOMAKE\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n$answer = \"\\\"Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING...\\\"\ntry this and this\nand these test out some blank lines\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n&run_make_with_options($makefile,\"space\",&get_logfile);\n$answer = \" \\n\";\n&compare_output($answer,&get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/substitution",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the subst and patsubst functions\";\n\n$details = \"\";\n\n# Generic patsubst test: test both the function and variable form.\n\nrun_make_test('\nfoo := a.o b.o c.o\nbar := $(foo:.o=.c)\nbar2:= $(foo:%.o=%.c)\nbar3:= $(patsubst %.c,%.o,x.c.c bar.c)\nall:;@echo $(bar); echo $(bar2); echo $(bar3)',\n'',\n'a.c b.c c.c\na.c b.c c.c\nx.c.o bar.o');\n\n# Patsubst without '%'--shouldn't match because the whole word has to match\n# in patsubst.  Based on a bug report by Markus Mauhart <qwe123@chello.at>\n\nrun_make_test('all:;@echo $(patsubst Foo,Repl,FooFoo)', '', 'FooFoo');\n\n# Variable subst where a pattern matches multiple times in a single word.\n# Based on a bug report by Markus Mauhart <qwe123@chello.at>\n\nrun_make_test('\nA := fooBARfooBARfoo\nall:;@echo $(A:fooBARfoo=REPL)', '', 'fooBARREPL');\n\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/suffix",
    "content": "$description = \"The following test creates a makefile to test the suffix\\n\"\n              .\"function. \\n\";\n\n$details = \"The suffix function will return the string following the last _._\\n\"\n          .\"the list provided. It will provide all of the unique suffixes found\\n\"\n          .\"in the list. The long strings are sorted to remove duplicates.\\n\";\n\n# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET\n# THE NAME OF THE MAKEFILE.  THIS INSURES CONSISTENCY AND KEEPS TRACK OF\n# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.\n# EXAMPLE: $makefile2 = &get_tmpfile;\n\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"string  := word.pl general_test2.pl1 FORCE.pl word.pl3 generic_test.perl /tmp.c/bar foo.baz/bar.c MAKEFILES_variable.c\\n\"\n              .\"string2 := \\$(string) \\$(string) \\$(string) \\$(string) \\$(string) \\$(string) \\$(string)\\n\"\n              .\"string3 := \\$(string2) \\$(string2) \\$(string2) \\$(string2) \\$(string2) \\$(string2) \\$(string2)\\n\"\n              .\"string4 := \\$(string3) \\$(string3) \\$(string3) \\$(string3) \\$(string3) \\$(string3) \\$(string3)\\n\"\n              .\"all: \\n\"\n              .\"\\t\\@echo \\$(suffix \\$(string)) \\n\"\n              .\"\\t\\@echo \\$(sort \\$(suffix \\$(string4))) \\n\"\n              .\"\\t\\@echo \\$(suffix \\$(string) a.out) \\n\"\n              .\"\\t\\@echo \\$(sort \\$(suffix \\$(string3))) \\n\";\n\n\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile,\"\",&get_logfile,0);\n\n# Create the answer to what should be produced by this Makefile\n\n# COMPARE RESULTS\n$answer = \".pl .pl1 .pl .pl3 .perl .c .c\\n\"\n         .\".c .perl .pl .pl1 .pl3\\n\"\n         .\".pl .pl1 .pl .pl3 .perl .c .c .out\\n\"\n         .\".c .perl .pl .pl1 .pl3\\n\";\n\n# In this call to compare output, you should use the call &get_logfile(1)\n# to send the name of the last logfile created.  You may also use\n# the special call &get_logfile(1) which returns the same as &get_logfile(1).\n\n&compare_output($answer,&get_logfile(1));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/functions/value",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the value function.\";\n\n$details = \"This is a test of the value function in GNU Make.\nThis function will evaluate to the value of the named variable with no\nfurther expansion performed on it.\\n\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<'EOF';\nexport FOO = foo\n\nrecurse = FOO = $FOO\nstatic := FOO = $(value FOO)\n\nall: ; @echo $(recurse) $(value recurse) $(static) $(value static)\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"FOO = OO FOO = foo FOO = foo FOO = foo\\n\";\n\n\n&compare_output($answer,&get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/warning",
    "content": "#                                                                    -*-Perl-*-\n\n$description = \"\\\nThe following test creates a makefile to test the warning function.\";\n\n$details = \"\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<'EOF';\nifdef WARNING1\n$(warning warning is $(WARNING1))\nendif\n\nifdef WARNING2\n$(warning warning is $(WARNING2))\nendif\n\nifdef WARNING3\nall: some; @echo hi $(warning warning is $(WARNING3))\nendif\n\nifdef WARNING4\nall: some; @echo hi\n\t@echo there $(warning warning is $(WARNING4))\nendif\n\nsome: ; @echo Some stuff\n\nEOF\n\nclose(MAKEFILE);\n\n# Test #1\n\n&run_make_with_options($makefile, \"WARNING1=yes\", &get_logfile, 0);\n$answer = \"$makefile:2: warning is yes\\nSome stuff\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #2\n\n&run_make_with_options($makefile, \"WARNING2=no\", &get_logfile, 0);\n$answer = \"$makefile:6: warning is no\\nSome stuff\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #3\n\n&run_make_with_options($makefile, \"WARNING3=maybe\", &get_logfile, 0);\n$answer = \"Some stuff\\n$makefile:10: warning is maybe\\nhi\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test #4\n\n&run_make_with_options($makefile, \"WARNING4=definitely\", &get_logfile, 0);\n$answer = \"Some stuff\\n$makefile:15: warning is definitely\\nhi\\nthere\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# Test linenumber offset\n\nrun_make_test(q!\nall: one two\n\t$(warning in $@ line 3)\n\t@true\n\t$(warning in $@ line 5)\n\none two:\n\t$(warning in $@ line 8)\n\t@true\n\t$(warning in $@ line 10)\n!,\n              '', \"#MAKEFILE#:8: in one line 8\n#MAKEFILE#:10: in one line 10\n#MAKEFILE#:8: in two line 8\n#MAKEFILE#:10: in two line 10\n#MAKEFILE#:3: in all line 3\n#MAKEFILE#:5: in all line 5\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/functions/wildcard",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test wildcard\nexpansions and the ability to put a command on the same\nline as the target name separated by a semi-colon.\";\n\n$details = \"\\\nThis test creates 4 files by the names of 1.example,\ntwo.example and 3.example.  We execute three tests.  The first\nexecutes the print1 target which tests the '*' wildcard by\nechoing all filenames by the name of '*.example'.  The second\ntest echo's all files which match '?.example' and\n[a-z0-9].example.  Lastly we clean up all of the files using\nthe '*' wildcard as in the first test\";\n\ntouch(\"example.1\");\ntouch(\"example.two\");\ntouch(\"example.3\");\ntouch(\"example.for\");\ntouch(\"example._\");\n\n# TEST #1\n# -------\n\nrun_make_test(qq/\n.PHONY: print1 print2 clean\nprint1: ;\\@echo \\$(wildcard example.*)\nprint2:\n\\t\\@echo \\$(wildcard example.?)\n\\t\\@echo \\$(wildcard example.[a-z0-9])\n\\t\\@echo \\$(wildcard example.[!A-Za-z_\\\\!])\nclean:\n\\t$CMD_rmfile \\$(wildcard example.*)\n/,\n              'print1', \"example.1 example.3 example._ example.for example.two\\n\");\n\n# TEST #2\n# -------\n\nrun_make_test(undef, 'print2', \"example.1 example.3 example._\\n\"\n                               .\"example.1 example.3\\n\"\n                               .\"example.1 example.3\\n\");\n\n# TEST #3\n# -------\n\n$answer = \"$CMD_rmfile example.1 example.3 example._ example.for example.two\";\nif ($vos)\n{\n   $answer .= \" \\n\";\n}\nelse\n{\n   $answer .= \"\\n\";\n}\n\nrun_make_test(undef, 'clean', $answer);\n\n# TEST #4: Verify that failed wildcards don't return the pattern\n\nrun_make_test(q!\nall: ; @echo $(wildcard xz--y*.7)\n!,\n              '', \"\\n\");\n\n# TEST #5: wildcard used to verify file existence\n\ntouch('xxx.yyy');\n\nrun_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!, '', \"file=xxx.yyy\\n\");\n\nunlink('xxx.yyy');\n\nrun_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!, '', \"file=\\n\");\n\n# TEST #7: verify that when the input pattern has a trailing slash wildcard\n# returns only directories.\n#\n# Currently this doesn't work with our embedded GLOB so disable it.\n# -------\n\nif (get_config('USE_SYSTEM_GLOB') eq 'yes') {\n  touch(\"hellof\");\n  mkdir(\"hellod\", 0770);\n  mkdir(\"hellod/worldd\", 0770);\n  touch(\"hellod/worldf\");\n  mkdir(\"hellod/worldd/kend1\", 0770);\n  mkdir(\"hellod/worldd/kend2\", 0770);\n  touch(\"hellod/worldd/kenf1\");\n  touch(\"hellod/worldd/kenf2\");\n\n  run_make_test(qq!\nprint3:\n\\t\\@echo \\$(wildcard hello*)\n\\t\\@echo \\$(wildcard hello*/)\n\\t\\@echo \\$(wildcard hellod/world*)\n\\t\\@echo \\$(wildcard hellod/world*/)\n\\t\\@echo \\$(wildcard hello* hellod/world*)\n\\t\\@echo \\$(wildcard hello*/ hellod/world*/)\n\\t\\@echo \\$(wildcard hellod/*)\n\\t\\@echo \\$(wildcard hellod/*/)\n\\t\\@echo \\$(wildcard */world*)\n\\t\\@echo \\$(wildcard */worldd/)\n\\t\\@echo \\$(wildcard hellod/*/ken*/)\n\\t\\@echo \\$(wildcard hellod/*/ken?[12])\n\\t\\@echo \\$(wildcard hellod/*/ken?[12]/)\n!, '',\n                \"hellod hellof\\n\"\n                .\"hellod/\\n\"\n                .\"hellod/worldd hellod/worldf\\n\"\n                .\"hellod/worldd/\\n\"\n                .\"hellod hellof hellod/worldd hellod/worldf\\n\"\n                .\"hellod/ hellod/worldd/\\n\"\n                .\"hellod/worldd hellod/worldf\\n\"\n                .\"hellod/worldd/\\n\"\n                .\"hellod/worldd hellod/worldf\\n\"\n                .\"hellod/worldd/\\n\"\n                .\"hellod/worldd/kend1/ hellod/worldd/kend2/\\n\"\n                .\"hellod/worldd/kend1 hellod/worldd/kend2 \"\n                .\"hellod/worldd/kenf1 hellod/worldd/kenf2\\n\"\n                .\"hellod/worldd/kend1/ hellod/worldd/kend2/\\n\");\n\n  unlink('hellof', 'hellod/worldf', 'hellod/worldd/kenf1',\n         'hellod/worldd/kenf2');\n  foreach $d ('hellod/worldd/kend1', 'hellod/worldd/kend2', 'hellod/worldd',\n              'hellod') {\n    rmdir($d);\n  }\n}\n\nif ($port_type ne 'W32') {\n  # Check wildcard on the root directory\n  run_make_test('print4: ; @echo $(wildcard /)', '', \"/\\n\");\n}\n\nif ($port_type ne 'W32' && eval { symlink(\"\",\"\"); 1 }) {\n\n  # TEST #6: check for wildcards matching directories\n  # See SV 53465\n\n  my $dir = '__rdir';\n  my $lnk = '__ldir';\n  mkdir($dir, 0777);\n  symlink($dir, $lnk);\n\n  run_make_test(qq!all: ; \\@echo \\$(wildcard $lnk*/.)!, '', \"$lnk/.\");\n\n  unlink($lnk);\n  rmdir($dir);\n\n  # Test for dangling symlinks\n  # This doesn't work with the built-in glob... needs to be updated!\n  # It also for some obscure reason, will break if we use ASAN!!\n\n  if (get_config('USE_SYSTEM_GLOB') eq 'yes' && !exists($FEATURES{sanitize})) {\n    symlink($dir, $lnk);\n\n    run_make_test(qq!all: ; \\@echo \\$(wildcard $lnk)!, '', \"$lnk\");\n\n    unlink($lnk);\n  }\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/functions/word",
    "content": "#                                                                    -*-perl-*-\n$description = \"\\\nTest the word, words, wordlist, firstword, and lastword functions.\\n\";\n\n$details = \"\\\nProduce a variable with a large number of words in it,\ndetermine the number of words, and then read each one back.\\n\";\n\nrun_make_test('\nstring  := word.pl general_test2.pl   FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\nstring2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)\nstring3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)\nstring4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)\n.RECIPEPREFIX = >\nall:\n> @echo $(words $(string))\n> @echo $(words $(string4))\n> @echo $(word 1, $(string))\n> @echo $(word 100, $(string))\n> @echo $(word 1  , $(string))\n> @echo $(word 1000, $(string3))\n> @echo $(word 9223372036854775807, $(string2))\n> @echo $(wordlist 3, 4, $(string))\n> @echo $(wordlist 4, 3, $(string))\n> @echo $(wordlist 1 , 6  , $(string))\n> @echo $(wordlist 5,7, $(string))\n> @echo $(wordlist 100, 110, $(string))\n> @echo $(wordlist 7, 10, $(string2))\n> @echo $(wordlist 9223372036854775807, 0, $(string2))\n', '', \"6\\n\"\n      .\"2058\\n\"\n      .\"word.pl\\n\"\n      .\"\\n\"\n      .\"word.pl\\n\"\n      .\"\\n\"\n      .\"\\n\"\n      .\"FORCE.pl word.pl\\n\"\n      .\"\\n\"\n      .\"word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\\n\"\n      .\"generic_test.perl MAKEFILES_variable.pl\\n\"\n      .\"\\n\"\n      .\"word.pl general_test2.pl FORCE.pl word.pl\\n\"\n      .\"\\n\"\n);\n\n# Test error conditions\n\nrun_make_test('FOO = foo bar biz baz\n\nword-e1: ; @echo $(word ,$(FOO))\nword-e2: ; @echo $(word abc ,$(FOO))\nword-e3: ; @echo $(word 1a,$(FOO))\nword-e4: ; @echo $(word 9999999999999999999,$(FOO))\n\nwordlist-e1: ; @echo $(wordlist ,,$(FOO))\nwordlist-e2: ; @echo $(wordlist abc ,,$(FOO))\nwordlist-e3: ; @echo $(wordlist 1, 12a ,$(FOO))',\n              'word-e1',\n              \"#MAKEFILE#:3: *** invalid first argument to 'word' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'word-e2',\n              \"#MAKEFILE#:4: *** invalid first argument to 'word' function: 'abc '.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'word-e3',\n              \"#MAKEFILE#:5: *** invalid first argument to 'word' function: '1a'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'word-e4',\n              \"#MAKEFILE#:6: *** invalid first argument to 'word' function: '9999999999999999999' out of range.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e1',\n              \"#MAKEFILE#:8: *** invalid first argument to 'wordlist' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e2',\n              \"#MAKEFILE#:9: *** invalid first argument to 'wordlist' function: 'abc '.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e3',\n              \"#MAKEFILE#:10: *** invalid second argument to 'wordlist' function: ' 12a '.  Stop.\",\n              512);\n\n# Test error conditions again, but this time in a variable reference\n\nrun_make_test('FOO = foo bar biz baz\n\nW = $(word $x,$(FOO))\nWL = $(wordlist $s,$e,$(FOO))\n\nword-e: ; @echo $(W)\nwordlist-e: ; @echo $(WL)',\n              'word-e x=',\n              \"#MAKEFILE#:3: *** invalid first argument to 'word' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'word-e x=abc',\n              \"#MAKEFILE#:3: *** invalid first argument to 'word' function: 'abc'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'word-e x=0',\n              \"#MAKEFILE#:3: *** first argument to 'word' function must be greater than 0.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e s= e=',\n              \"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: empty value.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e s=abc e=',\n              \"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: 'abc'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e s=4 e=12a',\n              \"#MAKEFILE#:4: *** invalid second argument to 'wordlist' function: '12a'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e s=0 e=12',\n              \"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'.  Stop.\",\n              512);\n\nrun_make_test(undef,\n              'wordlist-e s=1 e=-1',\n              \"#MAKEFILE#:4: *** invalid second argument to 'wordlist' function: '-1'.  Stop.\",\n              512);\n\n\n# TEST #8 -- test $(firstword )\n#\nrun_make_test('\nvoid :=\nlist := $(void) foo bar baz #\n\na := $(word 1,$(list))\nb := $(firstword $(list))\n\n.PHONY: all\n\nall: ; @test \"$a\" = \"$b\" && echo $a\n',\n'',\n'foo');\n\n\n# TEST #9 -- test $(lastword )\n#\nrun_make_test('\nvoid :=\nlist := $(void) foo bar baz #\n\na := $(word $(words $(list)),$(list))\nb := $(lastword $(list))\n\n.PHONY: all\n\nall: ; @test \"$a\" = \"$b\" && echo $a\n',\n'',\n'baz');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/misc/bs-nl",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test backslash-newline handling.\";\n\n$details = \"\";\n\n# TEST #1\n# -------\n\n# Backslash-newlines in recipes\n\n# These are basic backslash-newlines with no tricks\nrun_make_test(\"fast:;\\@echo fa\\\\\\nst\\n\",\n              '', 'fast');\n\nrun_make_test(\"slow:;\\@: no-op; echo sl\\\\\\now\\n\",\n              '', 'slow');\n\nrun_make_test(\"dquote:;\\@echo \\\"dqu\\\\\\note\\\"\\n\",\n              '', 'dquote');\n\n# Single quotes don't behave the same in Windows\nif ($port_type ne 'W32') {\n    run_make_test(\"squote:;\\@echo 'squ\\\\\\note'\\n\",\n              '', \"squ\\\\\\note\");\n}\n\n# Ensure that a leading prefix character is omitted\nrun_make_test(\"fast:;\\@echo fa\\\\\\n\\tst\\n\",\n              '', 'fast');\n\nrun_make_test(\"slow:;\\@: no-op; echo sl\\\\\\n\\tow\\n\",\n              '', 'slow');\n\nrun_make_test(\"dquote:;\\@echo \\\"dqu\\\\\\n\\tote\\\"\\n\",\n              '', 'dquote');\n\n# Single quotes don't behave the same in Windows\nif ($port_type ne 'W32') {\n    run_make_test(\"squote:;\\@echo 'squ\\\\\\n\\tote'\\n\",\n              '', \"squ\\\\\\note\");\n}\n\n# Ensure that ONLY the leading prefix character is omitted\nrun_make_test(\"fast:;\\@echo fa\\\\\\n\\t  st\\n\",\n              '', 'fa st');\n\nrun_make_test(\"slow:;\\@: no-op; echo sl\\\\\\n\\t\\tow\\n\",\n              '', \"sl ow\");\n\nrun_make_test(\"dquote:;\\@echo \\\"dqu\\\\\\n\\t    ote\\\"\\n\",\n              '', 'dqu    ote');\n\nrun_make_test(\"squote:;\\@echo 'squ\\\\\\n\\t\\t   ote'\\n\",\n              '', \"squ\\\\\\n\\t   ote\");\n\n# Backslash-newlines in variable values\n\n# Simple\nrun_make_test(q!\nvar = he\\\nllo\nvar:;@echo '|$(var)|'!,\n              '', \"|he llo|\");\n\n# Condense trailing space\nrun_make_test(q!\nvar = he  \\\nllo\nvar:;@echo '|$(var)|'!,\n              '', \"|he llo|\");\n\n# Remove leading space\nrun_make_test(q!\nvar = he\\\n    llo\nvar:;@echo '|$(var)|'!,\n              '', \"|he llo|\");\n\n# Multiple bs/nl condensed\nrun_make_test(q!\nvar = he\\\n\\\n\\\n    llo\nvar:;@echo '|$(var)|'!,\n              '', \"|he llo|\");\n\n# POSIX: Preserve trailing space\nrun_make_test(q!\n.POSIX:\nvar = he  \\\nllo\nvar:;@echo '|$(var)|'!,\n              '', \"|he   llo|\");\n\n# POSIX: One space per bs-nl\nrun_make_test(q!\n.POSIX:\nvar = he\\\n\\\n\\\n    llo\nvar:;@echo '|$(var)|'!,\n              '', \"|he   llo|\");\n\n# Savannah #39035: handle whitespace in call\nrun_make_test(q!\nf = echo $(1)\nt:; @$(call f,\"a \\\n            b\"); \\\n        $(call f,\"a \\\n            b\")\n!,\n              '', \"a b\\na b\\n\");\n\n# Savannah #38945: handle backslash CRLF\n# We need our own makefile so we can set binmode\nmy $m1 = get_tmpfile();\nopen(MAKEFILE, \"> $m1\");\nbinmode(MAKEFILE);\nprint MAKEFILE \"FOO = foo \\\\\\r\\n\";\nclose(MAKEFILE);\n\nmy $m2 = get_tmpfile();\nopen(MAKEFILE, \"> $m2\");\nprint MAKEFILE \"include $m1\\ndefine BAR\\nall: ; \\@echo \\$(FOO) bar\\nendef\\n\\$(eval \\$(BAR))\\n\";\nclose(MAKEFILE);\n\nrun_make_with_options($m2, '', get_logfile());\ncompare_output(\"foo bar\\n\", get_logfile(1));\n\n# Test different types of whitespace, and bsnl inside functions\n\nsub xlate\n{\n    $_ = $_[0];\n    s/\\\\r/\\r/g;\n    s/\\\\t/\\t/g;\n    s/\\\\f/\\f/g;\n    s/\\\\n/\\n/g;\n    return $_;\n}\n\nrun_make_test(xlate(q!\n$(foreach\\r  a \\t , b\\t  c \\r ,$(info    $a  \\r  )      )\nall:;@:\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\nrun_make_test(xlate(q!\nall:;@:$(foreach\\r  a \\t , b\\t  c \\r ,$(info    $a  \\r  )      )\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\nrun_make_test(xlate(q!\n$(foreach \\\n\\r  a \\t\\\n , b\\t \\\n c \\r ,$(info  \\\n  $a  \\r  )  \\\n    )\nall:;@:\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\nrun_make_test(xlate(q!\nall:;@:$(foreach \\\n\\r  a \\t\\\n , b\\t \\\n c \\r ,$(info  \\\n  $a  \\r  )  \\\n    )\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\nrun_make_test(xlate(q!\ndefine FOO\n$(foreach\n\\r  a \\t\n , b\\t\n c \\r ,$(info\n  $a  \\r  )\n    )\nendef\n$(FOO)\nall:;@:\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\nrun_make_test(xlate(q!\ndefine FOO\n$(foreach\n\\r  a \\t\n , b\\t\n c \\r ,$(info\n  $a  \\r  )\n    )\nendef\nall:;@:$(FOO)\n!),\n              '', \"b  \\r  \\nc  \\r  \\n\");\n\n# Test variables in recipes that expand to multiple lines\n\nrun_make_test(q!\ndefine var\n\necho foo\n\n\necho bar\nendef\nall:;$(var)\n!,\n              '', \"echo foo\\nfoo\\necho bar\\nbar\\n\");\n\nrun_make_test(q!\ndefine var\n\necho foo\n\n@\n\necho bar\nendef\nall:;$(var)\n!,\n              '', \"echo foo\\nfoo\\necho bar\\nbar\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/close_stdout",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Make sure make exits with an error if stdout is full.\";\n\n-e '/dev/full' or return -1;\n\n# In Strawberry Perl, /dev/full \"exists\" but does nothing :-/\n$port_type eq 'W32' and return -1;\n\nrun_make_test(\"\\n\", '-v > /dev/full', '/^#MAKE#: write error/', 256);\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/failure",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test miscellaneous failures.\";\n\n\n# Test that the \"did you mean TAB\" message is printed properly\n\nrun_make_test(q!\n$x.\n!,\n              '', '#MAKEFILE#:2: *** missing separator.  Stop.', 512);\n\nrun_make_test(q!\nfoo:\n        bar\n!,\n              '', '#MAKEFILE#:3: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.', 512);\n\nrun_make_test(q!\n.RECIPEPREFIX = :\nfoo:\n        bar\n!,\n              '', '#MAKEFILE#:4: *** missing separator.  Stop.', 512);\n\nfor my $kw ('eq', 'neq') {\nrun_make_test(qq!\nif$kw(foo,bar)\n\\$(error ouch)\nendif\n!,\n              '', '#MAKEFILE#:2: *** missing separator (ifeq/ifneq must be followed by whitespace).  Stop.', 512);\n\nrun_make_test(qq!\nif$kw\n\\$(error ouch)\nendif\n!,\n              '', '#MAKEFILE#:2: *** invalid syntax in conditional.  Stop.', 512);\n\nrun_make_test(qq!\nif$kw blah\n\\$(error ouch)\nendif\n!,\n              '', '#MAKEFILE#:2: *** invalid syntax in conditional.  Stop.', 512);\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/fopen-fail",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Make sure make exits with an error if fopen fails.\";\n\n# For some reason on Cygwin, make exits with no error message after\n# it recurses for a while.\n$^O =~ /cygwin/ and return -1;\n\n# Recurse infinitely until we run out of open files, and ensure we\n# fail with a non-zero exit code.  Don't bother to test the output\n# since it's hard to know what it will be, exactly.\n# See Savannah bug #27374.\n\n# Use a longer-than-normal timeout: some systems have more FDs available?\n# We also set ulimit -n 512 in check-regression in Makefile.am, which see.\n# See Savannah bug #42390.\nrun_make_test(q!\ninclude $(lastword $(MAKEFILE_LIST))\n!,\n              '', undef, 512, 300);\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/general1",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test the\nsimple functionality of make.  It mimics the\nrebuilding of a product with dependencies.\nIt also tests the simple definition of VPATH.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<EOF;\nVPATH = work\nedit:  main.o kbd.o commands.o display.o \\\\\n       insert.o\n\\t\\@echo cc -o edit main.o kbd.o commands.o display.o \\\\\n                  insert.o\nmain.o : main.c defs.h\n\\t\\@echo cc -c main.c\nkbd.o : kbd.c defs.h command.h\n\\t\\@echo cc -c kbd.c\ncommands.o : command.c defs.h command.h\n\\t\\@echo cc -c commands.c\ndisplay.o : display.c defs.h buffer.h\n\\t\\@echo cc -c display.c\ninsert.o : insert.c defs.h buffer.h\n\\t\\@echo cc -c insert.c\nEOF\n\nclose(MAKEFILE);\n\n\nmkdir('work');\n@files_to_touch = (\"work${pathsep}main.c\",\"work${pathsep}defs.h\",\n               \"work${pathsep}kbd.c\",\"work${pathsep}command.h\",\n               \"work${pathsep}commands.c\",\"work${pathsep}display.c\",\n               \"work${pathsep}buffer.h\",\"work${pathsep}insert.c\",\n               \"work${pathsep}command.c\");\n\n&touch(@files_to_touch);\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"cc -c main.c\\ncc -c kbd.c\\ncc -c commands.c\\ncc -c display.c\ncc -c insert.c\\ncc -o edit main.o kbd.o commands.o display.o insert.o\\n\";\n\n# COMPARE RESULTS\n\nif (&compare_output($answer,&get_logfile(1))) {\n  unlink @files_to_touch;\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/general2",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test the\nsimple functionality of make.  It is the same as\ngeneral_test1 except that this one tests the\ndefinition of a variable to hold the object filenames.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The contents of the Makefile ...\n\nprint MAKEFILE <<EOF;\nVPATH = work\nobjects = main.o kbd.o commands.o display.o insert.o\nedit:  \\$(objects)\n\\t\\@echo cc -o edit \\$(objects)\nmain.o : main.c defs.h\n\\t\\@echo cc -c main.c\nkbd.o : kbd.c defs.h command.h\n\\t\\@echo cc -c kbd.c\ncommands.o : command.c defs.h command.h\n\\t\\@echo cc -c commands.c\ndisplay.o : display.c defs.h buffer.h\n\\t\\@echo cc -c display.c\ninsert.o : insert.c defs.h buffer.h\n\\t\\@echo cc -c insert.c\nEOF\n\nclose(MAKEFILE);\n\n\nmkdir('work');\n@files_to_touch = (\"work${pathsep}main.c\",\"work${pathsep}defs.h\",\n               \"work${pathsep}kbd.c\",\"work${pathsep}command.h\",\n               \"work${pathsep}commands.c\",\"work${pathsep}display.c\",\n               \"work${pathsep}buffer.h\",\"work${pathsep}insert.c\",\n               \"work${pathsep}command.c\");\n\n&touch(@files_to_touch);\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"cc -c main.c\\ncc -c kbd.c\\ncc -c commands.c\\ncc -c display.c\ncc -c insert.c\\ncc -o edit main.o kbd.o commands.o display.o insert.o\\n\";\n\nif (&compare_output($answer,&get_logfile(1))) {\n  unlink @files_to_touch;\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/general3",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"\\\nThis tests random features of the parser that need to be supported, and\nwhich have either broken at some point in the past or seem likely to\nbreak.\";\n\nrun_make_test(\"\n# We want to allow both empty commands _and_ commands that resolve to empty.\nEMPTY =\n\n.PHONY: all a1 a2 a3 a4\nall: a1 a2 a3 a4\n\na1:;\na2:\n\\t\na3:;\\$(EMPTY)\na4:\n\\t\\$(EMPTY)\n\n\\# Non-empty lines that expand to nothing should also be ignored.\nSTR =     \\# Some spaces\nTAB =   \\t  \\# A TAB and some spaces\n\n\\$(STR)\n\n\\$(STR) \\$(TAB)\",\n              '', \"#MAKE#: Nothing to be done for 'all'.\");\n\n# TEST 2\n\n# Make sure files without trailing newlines are handled properly.\n# Have to use the old style invocation to test this.\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\nprint MAKEFILE \"all:;\\@echo FOO = \\$(FOO)\\nFOO = foo\";\nclose(MAKEFILE);\n\n&run_make_with_options($makefile2,\"\",&get_logfile);\n$answer = \"FOO = foo\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# TEST 3\n\n# Check semicolons in variable references\n\nrun_make_test('\n$(if true,$(info true; true))\nall: ; @:\n',\n              '', 'true; true');\n\n# TEST 4\n\n# Check that backslashes in command scripts are handled according to POSIX.\n# Checks Savannah bug # 1332.\n\n# Test the fastpath / no quotes\nrun_make_test('\nall:\n\t@echo foo\\\nbar\n\t@echo foo\\\n\tbar\n\t@echo foo\\\n    bar\n\t@echo foo\\\n\t    bar\n\t@echo foo \\\nbar\n\t@echo foo \\\n\tbar\n\t@echo foo \\\n    bar\n\t@echo foo \\\n\t    bar\n',\n              '', 'foobar\nfoobar\nfoo bar\nfoo bar\nfoo bar\nfoo bar\nfoo bar\nfoo bar');\n\n# Test the fastpath / single quotes\n# Single quotes don't behave the same in Windows\nif ($port_type ne 'W32') {\n    run_make_test(q!\nall:\n\t@echo 'foo\\\nbar'\n\t@echo 'foo\\\n\tbar'\n\t@echo 'foo\\\n    bar'\n\t@echo 'foo\\\n\t    bar'\n\t@echo 'foo \\\nbar'\n\t@echo 'foo \\\n\tbar'\n\t@echo 'foo \\\n    bar'\n\t@echo 'foo \\\n\t    bar'\n!,\n              '', 'foo\\\nbar\nfoo\\\nbar\nfoo\\\n    bar\nfoo\\\n    bar\nfoo \\\nbar\nfoo \\\nbar\nfoo \\\n    bar\nfoo \\\n    bar');\n}\n\n# Test the fastpath / double quotes\nrun_make_test('\nall:\n\t@echo \"foo\\\nbar\"\n\t@echo \"foo\\\n\tbar\"\n\t@echo \"foo\\\n    bar\"\n\t@echo \"foo\\\n\t    bar\"\n\t@echo \"foo \\\nbar\"\n\t@echo \"foo \\\n\tbar\"\n\t@echo \"foo \\\n    bar\"\n\t@echo \"foo \\\n\t    bar\"\n',\n              '', 'foobar\nfoobar\nfoo    bar\nfoo    bar\nfoo bar\nfoo bar\nfoo     bar\nfoo     bar');\n\n# Test the slow path / no quotes\nrun_make_test('\nall:\n\t@echo hi; echo foo\\\nbar\n\t@echo hi; echo foo\\\n\tbar\n\t@echo hi; echo foo\\\n bar\n\t@echo hi; echo foo\\\n\t bar\n\t@echo hi; echo foo \\\nbar\n\t@echo hi; echo foo \\\n\tbar\n\t@echo hi; echo foo \\\n bar\n\t@echo hi; echo foo \\\n\t bar\n',\n              '', 'hi\nfoobar\nhi\nfoobar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar');\n\n# Test the slow path / no quotes.  This time we put the slow path\n# determination _after_ the backslash-newline handling.\nrun_make_test('\nall:\n\t@echo foo\\\nbar; echo hi\n\t@echo foo\\\n\tbar; echo hi\n\t@echo foo\\\n bar; echo hi\n\t@echo foo\\\n\t bar; echo hi\n\t@echo foo \\\nbar; echo hi\n\t@echo foo \\\n\tbar; echo hi\n\t@echo foo \\\n bar; echo hi\n\t@echo foo \\\n\t bar; echo hi\n',\n              '', 'foobar\nhi\nfoobar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo bar\nhi');\n\n# Test the slow path / single quotes\nrun_make_test(q!\nall:\n\t@echo hi; echo 'foo\\\nbar'\n\t@echo hi; echo 'foo\\\n\tbar'\n\t@echo hi; echo 'foo\\\n    bar'\n\t@echo hi; echo 'foo\\\n\t    bar'\n\t@echo hi; echo 'foo \\\nbar'\n\t@echo hi; echo 'foo \\\n\tbar'\n\t@echo hi; echo 'foo \\\n    bar'\n\t@echo hi; echo 'foo \\\n\t    bar'\n!,\n              '', 'hi\nfoo\\\nbar\nhi\nfoo\\\nbar\nhi\nfoo\\\n    bar\nhi\nfoo\\\n    bar\nhi\nfoo \\\nbar\nhi\nfoo \\\nbar\nhi\nfoo \\\n    bar\nhi\nfoo \\\n    bar');\n\n# Test the slow path / double quotes\nrun_make_test('\nall:\n\t@echo hi; echo \"foo\\\nbar\"\n\t@echo hi; echo \"foo\\\n\tbar\"\n\t@echo hi; echo \"foo\\\n    bar\"\n\t@echo hi; echo \"foo\\\n\t    bar\"\n\t@echo hi; echo \"foo \\\nbar\"\n\t@echo hi; echo \"foo \\\n\tbar\"\n\t@echo hi; echo \"foo \\\n    bar\"\n\t@echo hi; echo \"foo \\\n\t    bar\"\n',\n              '', 'hi\nfoobar\nhi\nfoobar\nhi\nfoo    bar\nhi\nfoo    bar\nhi\nfoo bar\nhi\nfoo bar\nhi\nfoo     bar\nhi\nfoo     bar');\n\nrun_make_test('x:;@-exit 1', '', \"#MAKE#: [#MAKEFILE#:1: x] Error 1 (ignored)\\n\");\n\n# Slow path with odd setups\n\nif ($port_type ne 'W32') {\n    run_make_test(q!\n    slow: SHELL := echo\n    slow: .SHELLFLAGS := hoho\n    slow:; @foo bar\n    !,\n                  '', \"hoho foo bar\\n\");\n\n    run_make_test(q!\n    slow: SHELL := echo hi\n    slow: .SHELLFLAGS := ho ho\n    slow:; @foo bar\n    !,\n                  '', \"hi ho ho foo bar\\n\");\n\n    run_make_test(q!\n    slow: SHELL := echo hi\n    slow: .SHELLFLAGS := 'ho;ho'\n    slow:; @foo bar\n    !,\n                  '', \"hi ho;ho foo bar\\n\");\n}\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/misc/general4",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"\\\nThis tests random features of make's algorithms, often somewhat obscure,\nwhich have either broken at some point in the past or seem likely to\nbreak.\";\n\nrun_make_test('\n# Make sure that subdirectories built as prerequisites are actually handled\n# properly.\n\nall: dir/subdir/file.a\n\ndir/subdir: ; @echo mkdir -p dir/subdir\n\ndir/subdir/file.b: dir/subdir ; @echo touch dir/subdir/file.b\n\ndir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@',\n              '', \"mkdir -p dir/subdir\\ntouch dir/subdir/file.b\\ncp dir/subdir/file.b dir/subdir/file.a\\n\");\n\n# Test implicit rules\n\n&touch('foo.c');\nrun_make_test('foo: foo.o',\n              'CC=\"@echo cc\" OUTPUT_OPTION=',\n              'cc -c foo.c\ncc foo.o -o foo');\nunlink('foo.c');\n\n\n# Test implicit rules with '$' in the name (see se_implicit)\n\nrun_make_test(q!\n%.foo : baz$$bar ; @echo 'done $<'\n%.foo : bar$$baz ; @echo 'done $<'\ntest.foo:\nbaz$$bar bar$$baz: ; @echo '$@'\n!,\n              '',\n              \"baz\\$bar\\ndone baz\\$bar\");\n\n\n# Test implicit rules with '$' in the name (see se_implicit)\n# Use the '$' in the pattern.\n\nrun_make_test(q!\n%.foo : %$$bar ; @echo 'done $<'\ntest.foo:\ntest$$bar: ; @echo '$@'\n!,\n              '',\n              \"test\\$bar\\ndone test\\$bar\");\n\n# Make sure that subdirectories built as prerequisites are actually handled\n# properly... this time with '$'\n\nrun_make_test(q!\n\nall: dir/subdir/file.$$a\n\ndir/subdir: ; @echo mkdir -p '$@'\n\ndir/subdir/file.$$b: dir/subdir ; @echo touch '$@'\n\ndir/subdir/%.$$a: dir/subdir/%.$$b ; @echo 'cp $< $@'\n!,\n              '', \"mkdir -p dir/subdir\\ntouch dir/subdir/file.\\$b\\ncp dir/subdir/file.\\$b dir/subdir/file.\\$a\\n\");\n\n# Test odd whitespace at the beginning of a line\n\nrun_make_test(\"\nall:\n   \\f\n\n    \\\\\n \\f  \\\\\n    \\013 \\\\\nall: ; \\@echo hi\n\",\n              '', \"hi\\n\");\n\n# SV-56834 Ensure setting PATH in the makefile works properly\nmy $sname = \"foobar$scriptsuffix\";\n\nmkdir('sd', 0775);\ncreate_file(\"sd/$sname\", \"exit 0\\n\");\nchmod 0755, \"sd/$sname\";\n\nrun_make_test(qq!\nPATH := sd\nall: ; $sname >/dev/null\n!,\n              '', \"$sname >/dev/null\\n\");\n\n# Don't use the general PATH if not found on the target path\n\n$ENV{PATH} = \"$ENV{PATH}:sd\";\n\nmy ($ernum, $erstr);\n\nif ($port_type eq 'W32') {\n    $ernum = 2;\n    $erstr = \"process_begin: CreateProcess(NULL, $sname, ...) failed.\\nmake (e=2): The system cannot find the file specified.\";\n} else {\n    $ernum = 127;\n    $erstr = \"#MAKE#: $sname: $ERR_no_such_file\";\n}\n\nrun_make_test(qq!\nPATH := ..\nall: ; $sname\n!,\n              '', \"$sname\\n$erstr\\n#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum\", 512);\n\nunlink(\"sd/$sname\");\nrmdir('sd');\n\n# Ensure that local programs are not found if \".\" is not on the PATH\n\ncreate_file($sname, '');\nchmod 0755, $sname;\n\nif ($port_type eq 'W32') {\n    $ernum = -1;\n    $erstr = \"\";\n} else {\n    $ernum = 127;\n    $erstr = \"#MAKE#: $sname: $ERR_no_such_file\\n\";\n}\n\nrun_make_test(qq!\nPATH := ..\nall: ; $sname\n!,\n              '', \"$sname\\n$erstr#MAKE#: *** [#MAKEFILE#:3: all] Error $ernum\", 512);\n\nunlink($sname);\n\nif ($port_type eq 'UNIX') {\n    # SV 57674: ensure we use a system default PATH if one is not set\n    delete $ENV{PATH};\n    run_make_test(q!\na: ; @echo hi\n!,\n                  '', \"hi\\n\");\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/misc/utf8",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test utf8 handling.\";\n\n$details = \"\";\n\n# Variable names containing UTF8 characters\nrun_make_test(\"\n\\xe2\\x96\\xaa := hello\n\\$(info \\$(\\xe2\\x96\\xaa))\nall:\n\",\n              '', \"hello\\n#MAKE#: Nothing to be done for 'all'.\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-B",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test make -B (always remake) option.\\n\";\n\n$details = \"\\\nConstruct a simple makefile that builds a target.\nInvoke make once, so it builds everything.  Invoke it again and verify\nthat nothing is built.  Then invoke it with -B and verify that everything\nis built again.\";\n\n&touch('bar.x');\n\nrun_make_test('\n.SUFFIXES:\n\n.PHONY: all\nall: foo\n\nfoo: bar.x\n\t@echo cp $< $@\n\t@echo \"\" > $@\n',\n              '', 'cp bar.x foo');\n\nrun_make_test(undef, '', \"#MAKE#: Nothing to be done for 'all'.\");\nrun_make_test(undef, '-B', 'cp bar.x foo');\n\n# Put the timestamp for foo into the future; it should still be remade.\n# There are clock skew errors printed here but they will be cleared by\n# the comparison code.\nutouch(1000, 'foo');\nrun_make_test(undef, '', \"#MAKE#: Nothing to be done for 'all'.\");\nrun_make_test(undef, '-B', 'cp bar.x foo');\n\n# Clean up\n\nrmfiles('bar.x', 'foo');\n\n# Test -B with the re-exec feature: we don't want to re-exec forever\n# Savannah bug # 7566\n\nrun_make_test('\nall: ; @:\n$(info MAKE_RESTARTS=$(MAKE_RESTARTS))\ninclude foo.x\nfoo.x: ; @touch $@\n',\n              '-B', 'MAKE_RESTARTS=\nMAKE_RESTARTS=1');\n\nrmfiles('foo.x');\n\n# Test -B with the re-exec feature: we DO want -B in the \"normal\" part of the\n# makefile.\n\n&touch('blah.x');\n\nrun_make_test('\nall: blah.x ; @echo $@\n$(info MAKE_RESTARTS=$(MAKE_RESTARTS))\ninclude foo.x\nfoo.x: ; @touch $@\nblah.x: ; @echo $@\n',\n              '-B', 'MAKE_RESTARTS=\nMAKE_RESTARTS=1\nblah.x\nall');\n\nrmfiles('foo.x', 'blah.x');\n\n# Test that $? is set properly with -B; all prerequisites will be newer!\n\nutouch(-10, 'x.b');\ntouch('x.a');\n\nrun_make_test(q!\nx.a: x.b ; @echo $?\n!,\n              '-B', \"x.b\\n\");\n\nunlink(qw(x.a x.b));\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/options/dash-C",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -C option to GNU Make.\";\n\nuse File::Spec;\n\n# Pre-set $makefile to be in a subdirectory\n$makefile = 'Makefile';\n\nmy $_srcdir = 'src';\nmkdir($_srcdir, 0775);\n\nmy $_incdir = 'inc';\nmkdir($_incdir, 0775);\n\nmy $_mkpath = File::Spec->catfile($_srcdir, $makefile);\ncreate_file($_mkpath, \"include \\$(file)\\nall: ;\\n\");\n\n# TEST #1\n# -------\nrun_make_test('', \"-C $_srcdir --no-print-directory\",\n              \"#MAKE#: 'all' is up to date.\");\n\n# TEST #2\n# -------\n# Do it again with trailing \"/\"; this should work the same\n\nrun_make_test(undef, \"-C $_srcdir/ --no-print-directory\",\n              \"#MAKE#: 'all' is up to date.\");\n\n# Test stringing together multiple -C options\n\nrun_make_test(undef, \"-C $_incdir -C .. -C $_srcdir --no-print-directory\",\n              \"#MAKE#: 'all' is up to date.\");\n\n# SV 63552 - Ensure -I is considered after -C\n\nmy $_incfile = 'test';\nmy $_incpath = File::Spec->catfile($_incdir, $_incfile);\ncreate_file($_incpath, '$(info included)');\n\nmy $_incopt = File::Spec->catfile('..', $_incdir);\n\nrun_make_test(undef, \"-C src -I $_incopt --no-print-directory file=$_incfile\",\n              \"included\\n#MAKE#: 'all' is up to date.\");\n\nunlink($_incpath);\nrmdir($_incdir);\n\nunlink($_mkpath);\nrmdir($_srcdir);\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-I",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test the -I option.\";\n\n$details = \"\\\nThis test tests the -I option by including a filename in\nanother directory and giving make that directory name\nunder -I in the command line.  Without this option, the make\nwould fail to find the included file.  It also checks to make\nsure that the -I option gets passed to recursive makes.\";\n\nuse File::Spec;\n\n# Create a directory and put a makefile in it.\n# We can't put it in the current directory since that's automatically searched\n# anyway.\nmy $subdir = 'idir';\nmkdir($subdir, 0777);\n\nmy $included = 'ifile.mk';\nmy $ipath = File::Spec->catfile($subdir, $included);\ncreate_file($ipath, \"\nANOTHER:\n\\t\\@echo This is another included makefile\nrecurse:\n\\t\\@\\$(MAKE) ANOTHER -f \\$(main_makefile)\\n\");\n\nmy $nosuch = \"#MAKEFILE#:5: $included: $ERR_no_such_file\n#MAKE#: *** No rule to make target '$included'.  Stop.\\n\";\n\n\n# Verify that we get an error if we don't have -I\nrun_make_test(qq!\nmain_makefile := \\$(firstword \\$(MAKEFILE_LIST))\nall:\n\\t\\@echo There should be no errors for this makefile\ninclude $included\n!,\n              '', $nosuch, 512);\n\n# Check basic -I works\nrun_make_test(undef, \"-I $subdir all\",\n              \"There should be no errors for this makefile\\n\");\n\n# Check that the included target works\nrun_make_test(undef, \"-I $subdir ANOTHER\",\n              \"This is another included makefile\\n\");\n\n# Check that -I is passed down through MAKEFLAGS\nrun_make_test(undef, \"-I $subdir recurse\",\n              \"#MAKE#[1]: Entering directory '#PWD#'\nThis is another included makefile\n#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\n# Verify that we get an error if we add -I- to delete previous includes\nrun_make_test(undef, \"-I $subdir -I- all\", $nosuch, 512);\n\n# Make another directory with the same name and make sure the right one is\n# chosen if -I- stops the path.\n\nmkdir('idir2', 0777);\nmy $ipath2 = File::Spec->catfile('idir2', $included);\ncreate_file($ipath2, \"This is a bad makefile!!\\n\");\n\nrun_make_test(undef, \"-I idir2 -I $subdir ANOTHER\",\n              \"$included:1: *** missing separator.  Stop.\\n\", 512);\n\nrun_make_test(undef, \"-I idir2 -I - -I $subdir ANOTHER\",\n              \"This is another included makefile\\n\");\n\n# Check that -I- is passed down through MAKEFLAGS\nrun_make_test(undef, \"-I idir2 -I - -I $subdir recurse\",\n              \"#MAKE#[1]: Entering directory '#PWD#'\nThis is another included makefile\n#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\nunlink($ipath2);\nrmdir('idir2');\n\n# The only way to check if -I- voids included directories is to see if a file\n# exists in one and try to include it.  We very likely can't add our own files\n# to the default directories since they're probably write-protected.  This\n# won't work if none of the default directories contain any files :-/\n\ncreate_file('defaultdirs.mk', \"\\$(info \\$(.INCLUDE_DIRS))\\nall:;\\@:\\n\");\nmy $cmd = subst_make_string(\"#MAKEPATH# -f defaultdirs.mk\");\nmy @dirs = `$cmd`;\nmy $dirs = $dirs[0];\n$dirs =~ s/\\r?\\n//g;\nunlink('defaultdirs.mk');\n\nmy $fn = undef;\nforeach my $dn (split ' ', $dirs) {\n    # On Windows the default is \".\" which is bogus!\n    if ($dn ne '.') {\n        my @files = glob(File::Spec->catfile($dn, \"*\"));\n        if (@files) {\n            (undef, undef, $fn) = File::Spec->splitpath($files[0]);\n            last;\n        }\n    }\n}\n\nif ($fn) {\n    run_make_test(\"\nall:;\ninclude $fn\n\",\n                  '-I-', \"#MAKEFILE#:3: $fn: $ERR_no_such_file\n#MAKE#: *** No rule to make target '$fn'.  Stop.\\n\", 512);\n}\n\nunlink($ipath);\nrmdir($subdir);\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-W",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test make -W (what if) option.\\n\";\n\n# Basic build\n\nrun_make_test('\na.x: b.x\na.x b.x: ; echo >> $@\n',\n              '', \"echo >> b.x\\necho >> a.x\");\n\n# Run it again: nothing should happen\n\nrun_make_test(undef, '', \"#MAKE#: 'a.x' is up to date.\");\n\n# Now run it with -W b.x: should rebuild a.x\n\nrun_make_test(undef, '-W b.x', 'echo >> a.x');\n\n# Put the timestamp for a.x into the future; it should still be remade.\n# There are clock skew errors printed here but they will be cleared by\n# the comparison code.\nutouch(1000, 'a.x');\nrun_make_test(undef, '', \"#MAKE#: 'a.x' is up to date.\");\nrun_make_test(undef, '-W b.x', 'echo >> a.x');\n\n# Clean up\n\nrmfiles('a.x', 'b.x');\n\n# Test -W with the re-exec feature: we don't want to re-exec forever\n# Savannah bug # 7566\n\n# First set it up with a normal build\n\nrun_make_test('\nall: baz.x ; @:\ninclude foo.x\nfoo.x: bar.x\n\t@echo \"\\$$(info restarts=\\$$(MAKE_RESTARTS))\" > $@\n\t@echo \"touch $@\"\nbar.x: ; echo >> $@\nbaz.x: bar.x ; @echo \"touch $@\"\n',\n              '', 'echo >> bar.x\ntouch foo.x\nrestarts=1\ntouch baz.x');\n\n# Now run with -W bar.x\n\n# Tweak foo.x's timestamp so the update will change it.\n# There are clock skew errors printed here but they will be cleared by\n# the comparison code.\n&utouch(1000, 'foo.x');\n\nrun_make_test(undef, '-W bar.x', \"restarts=\\ntouch foo.x\\nrestarts=1\\ntouch baz.x\");\n\nrmfiles('foo.x', 'bar.x');\n\n# Test -W on vpath-found files: it should take effect.\n# Savannah bug # 15341\n\nmkdir('x-dir', 0777);\nutouch(-20, 'x-dir/x');\ntouch('y');\n\nrun_make_test('\ny: x ; @echo cp $< $@\n',\n              '-W x-dir/x VPATH=x-dir',\n              'cp x-dir/x y');\n\n# Make sure ./ stripping doesn't interfere with the match.\n\nrun_make_test('\ny: x ; @echo cp $< $@\n',\n              '-W ./x-dir/x VPATH=x-dir',\n              'cp x-dir/x y');\n\nrun_make_test(undef,\n              '-W x-dir/x VPATH=./x-dir',\n              'cp ./x-dir/x y');\n\nunlink(qw(y x-dir/x));\nrmdir('x-dir');\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/options/dash-d",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test make -d option.\\n\";\n\n# sv 60777.\n# Test that debug output is printed when both -d and --trace are specified.\nrun_make_test('all: ; :', '-d --trace', \"/GNU Make/\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-e",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -e (environment overrides) option\";\n\n$ENV{GOOGLE} = 'boggle';\n\nrun_make_test(q!\nGOOGLE = bazzle\nall:; @echo \"$(GOOGLE)\"\n!,\n              '-e', \"boggle\\n\");\n\n# Ensure variables set on the command line have the origin correct\n# See SV 61218\n\nrun_make_test(q!\n$(info FOO [$(origin FOO)]: $(value FOO))\nall: ;\nrecurse: ; @$(MAKE) -f #MAKEFILE#\n!,\n              '-e --no-print-directory FOO=1 recurse',\n              \"FOO [command line]: 1\\nFOO [command line]: 1\\n#MAKE#[1]: 'all' is up to date.\");\n\n# SV 64803.\n# Test that the origin of an env variable is 'enviroment override' when -e\n# is set and the makefile does not modify the variable.\n# First run the test without -e and then with -e.\n\nmkdir('lib', 0777);\n\ncreate_file('lib/makefile',\n'$(info in submake value=$(hello), origin=$(origin hello))\nall:; @echo \"value=$(hello), origin=$(origin hello)\"'.\"\\n\");\n\n# No -e.\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib\n.PHONY: lib all\n!,\n              '-s',\n              \"value=world, origin=environment\\nvalue=world, origin=environment\\n\".\n              \"in submake value=world, origin=environment\\nvalue=world, origin=environment\");\n\n# -e is specified on the command line.\nmy @opts = ('-e', '--environment-overrides');\nfor my $opt (@opts) {\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib\n.PHONY: lib all\n!,\n              \"-s $opt\",\n              \"value=world, origin=environment override\\nvalue=world, origin=environment override\\n\".\n              \"in submake value=world, origin=environment override\\nvalue=world, origin=environment override\");\n}\n\n# MAKEFLAGS from env affects top level make.\n$ENV{hello} = 'world';\n$ENV{MAKEFLAGS} = 'e';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib\n.PHONY: lib all\n!,\n              \"-s\",\n              \"value=world, origin=environment override\\nvalue=world, origin=environment override\\n\".\n              \"in submake value=world, origin=environment override\\nvalue=world, origin=environment override\");\n\n# -e is passed to submake on the command line.\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -e -C lib\n.PHONY: lib all\n!,\n              \"-s\",\n              \"value=world, origin=environment\\nvalue=world, origin=environment\\n\".\n              \"in submake value=world, origin=environment override\\nvalue=world, origin=environment override\");\n\n# MAKEFLAGS is reset for submake.\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib MAKEFLAGS=\n.PHONY: lib all\n!,\n              \"-se\",\n              \"value=world, origin=environment override\\nvalue=world, origin=environment override\\n\".\n              \"in submake value=world, origin=environment\\nvalue=world, origin=environment\");\n\n# Some MAKEFLAGS in top make env.\n# This MAKEFLAGS does not conform to the format that make itself produces for\n# submake. However, make still parses and honors this MAKEFLAGS.\n# This test checks that make does not confuse 'e' in 'extramk' with '-e'.\n$ENV{MAKEFLAGS} = 'r -Iextramk -k bye=moon';\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib\n.PHONY: lib all\n!,\n              \"-s\",\n              \"value=world, origin=environment\\nvalue=world, origin=environment\\n\".\n              \"in submake value=world, origin=environment\\nvalue=world, origin=environment\");\n\n# Some MAKEFLAGS in top make env.\n# This MAKEFLAGS does not conform to the format that make itself produces for\n# submake. However, make still parses and honors this MAKEFLAGS.\n# This test checks that make detects '-e' in this MAKEFLAGS.\n$ENV{MAKEFLAGS} = 'r -Iextramk -ke bye=moon';\n$ENV{hello} = 'world';\nrun_make_test(q!\n.RECIPEPREFIX = >\n$(info value=$(hello), origin=$(origin hello))\nall:\n> @echo \"value=$(hello), origin=$(origin hello)\"\n> @$(MAKE) -C lib\n.PHONY: lib all\n!,\n              \"-s\",\n              \"value=world, origin=environment override\\nvalue=world, origin=environment override\\n\".\n              \"in submake value=world, origin=environment override\\nvalue=world, origin=environment override\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-f",
    "content": "#                                                                    -*-perl-*-\n$description = \"The following test tests that if you specify greater \\n\"\n              .\"than one '-f makefilename' on the command line, \\n\"\n              .\"that make concatenates them.  This test creates three \\n\"\n              .\"makefiles and specifies all of them with the -f option \\n\"\n              .\"on the command line.  To make sure they were concatenated, \\n\"\n              .\"we then call make with the rules from the concatenated \\n\"\n              .\"makefiles one at a time.  Finally, it calls all three \\n\"\n              .\"rules in one call to make and checks that the output\\n\"\n              .\"is in the correct order.\";\n\n$makefile2 = &get_tmpfile;\n$makefile3 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE \"all: \\n\";\nprint MAKEFILE \"\\t\\@echo This is the output from the original makefile\\n\";\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n# Create a second makefile\nopen(MAKEFILE,\"> $makefile2\");\nprint MAKEFILE \"TWO: \\n\";\nprint MAKEFILE \"\\t\\@echo This is the output from makefile 2\\n\";\nclose(MAKEFILE);\n\n# Create a third makefile\nopen(MAKEFILE,\"> $makefile3\");\nprint MAKEFILE \"THREE: \\n\";\nprint MAKEFILE \"\\t\\@echo This is the output from makefile 3\\n\";\nclose(MAKEFILE);\n\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"This is the output from the original makefile\\n\";\n\n# Run make to catch the default rule\n&run_make_with_options($makefile,\"-f $makefile2 -f $makefile3\",&get_logfile,0);\n\n&compare_output($answer,&get_logfile(1));\n\n\n# Run Make again with the rule from the second makefile: TWO\n$answer = \"This is the output from makefile 2\\n\";\n\n&run_make_with_options($makefile,\"-f $makefile2 -f $makefile3 TWO\",&get_logfile,0);\n\n&compare_output($answer,&get_logfile(1));\n\n\n# Run Make again with the rule from the third makefile: THREE\n\n$answer = \"This is the output from makefile 3\\n\";\n&run_make_with_options($makefile,\n                       \"-f $makefile2 -f $makefile3 THREE\",\n                       &get_logfile,\n                       0);\n&compare_output($answer,&get_logfile(1));\n\n\n# Run Make again with ALL three rules in the order 2 1 3 to make sure\n# that all rules are executed in the proper order\n\n$answer = \"This is the output from makefile 2\\n\";\n$answer .= \"This is the output from the original makefile\\n\";\n$answer .= \"This is the output from makefile 3\\n\";\n&run_make_with_options($makefile,\n                       \"-f $makefile2 -f $makefile3 TWO all THREE\",\n                       &get_logfile,\n                       0);\n&compare_output($answer,&get_logfile(1));\n\n\n# sv 62118.\n# Validate all sorts of -f etc. options\n\nmy $hello = 'hello.mk';\nmy $bye = 'bye.mk';\nmy $byesrc = 'bye.mk.src';\n\ncreate_file($hello, 'all:; $(info hello, world)\n');\n\ncreate_file($bye, 'def:; $(info bye, world)\nbye.mk: bye.mk.src; touch $@\nbye.mk.src:; touch $@\n');\n\n# These invocations use the empty filename string so that the test framework\n# doesn't add any -f options on its own.\n\n# Incorrect order of options. -R follows -f.\n# Invocation of make is equivalent to\n#   echo 'all:; $(info hello, world)' | make -f bye.mk -fR - all\n# There is bye.mk, but there is no 'R'.\n# make runs the recipes from bye.mk and prints the error about missing 'R'.\n\n# Ensure the newly created bye.src.mk is newer than bye.mk.\n&utouch(-600, $bye);\nrun_make_test('', \"-f$bye -fR - all\", \"#MAKE#: R: No such file or directory\ntouch bye.mk.src\ntouch bye.mk\n#MAKE#: *** No rule to make target 'R'.  Stop.\n\", 512);\n\nmy @opts;\nmy $answer;\n\n# Test double -f-.\n@opts = ('-f- -f-', '-f - -f -', '-f- -f -', '-f - -f-',\n         '-f- --file=-', '-f- --file -', '-f - --file=-', '-f - --file -',\n         '-f- --makefile=-', '-f- --makefile -',\n         '-f - --makefile=-', '-f - --makefile -',\n         '--file=- --makefile=-', '--file=- --makefile -',\n         '--file - --makefile=-', '--file - --makefile -');\n\nfor my $opt (@opts) {\n    # We shouldn't need this; if the options are wrong then make shouldn't try\n    # to read from stdin.\n    close(STDIN);\n    open(STDIN, \"<\", $hello) || die \"$0: cannot open $hello for reading: $!\";\n    run_make_test('', \"-f$bye $opt\", \"#MAKE#: *** Makefile from standard input specified twice.  Stop.\\n\", 512);\n}\n\n# -f is not followed by filename.\n@opts = ('-f', '--file', '--makefile');\n$answer = \"/requires an argument/\";\nfor my $opt (@opts) {\n    run_make_test('', $opt, $answer, 512);\n}\n\n# Test that make correctly parses all possible syntaxes to pipe make code to\n# the standard input.\n\n$answer = \"touch bye.mk.src\ntouch bye.mk\nhello, world\n#MAKE#: 'all' is up to date.\\n\";\n\n@opts = ('-f- all', '-f - all', '-Rf- all', '-Rf - all',\n         '--file=- all', '--file - all',\n         '--makefile=- all', '--makefile - all');\nfor my $opt (@opts) {\n    unlink($byesrc);\n    close(STDIN);\n    open(STDIN, \"<\", $hello) || die \"$0: cannot open $hello for reading: $!\";\n    # Ensure the newly created bye.src.mk is newer than bye.mk.\n    &utouch(-600, $bye);\n\n    run_make_test('', \"-f$bye $opt\", $answer);\n}\n\n\n# This close MUST come at the end of the test!!\nclose(STDIN);\nunlink($hello, $bye, $byesrc);\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-k",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the make -k (don't stop on error) option.\\n\";\n\n$details = \"\\\nThe makefile created in this test is a simulation of building\na small product.  However, the trick to this one is that one\nof the dependencies of the main target does not exist.\nWithout the -k option, make would fail immediately and not\nbuild any part of the target.  What we are looking for here,\nis that make builds the rest of the dependencies even though\nit knows that at the end it will fail to rebuild the main target.\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<EOF;\nVPATH = work\nedit:  main.o kbd.o commands.o display.o\n\\t\\@echo cc -o edit main.o kbd.o commands.o display.o\n\nmain.o : main.c defs.h\n\\t\\@echo cc -c main.c\n\nkbd.o : kbd.c defs.h command.h\n\\t\\@echo cc -c kbd.c\n\ncommands.o : command.c defs.h command.h\n\\t\\@echo cc -c commands.c\n\ndisplay.o : display.c defs.h buffer.h\n\\t\\@echo cc -c display.c\nEOF\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n\nmkdir('work');\n@files_to_touch = (\"work${pathsep}main.c\",\"work${pathsep}defs.h\",\n               \"work${pathsep}command.h\",\n               \"work${pathsep}commands.c\",\"work${pathsep}display.c\",\n               \"work${pathsep}buffer.h\",\n               \"work${pathsep}command.c\");\n\n&touch(@files_to_touch);\n\nif ($vos) {\n  $error_code = 3307;\n}\nelse {\n  $error_code = 512;\n}\n\n&run_make_with_options($makefile, \"-k\", &get_logfile, $error_code);\n\n# Create the answer to what should be produced by this Makefile\n$answer = \"cc -c main.c\n$make_name: *** No rule to make target 'kbd.c', needed by 'kbd.o'.\ncc -c commands.c\ncc -c display.c\n$make_name: Target 'edit' not remade because of errors.\\n\";\n\n# COMPARE RESULTS\n\n&compare_output($answer, &get_logfile(1));\n\nunlink(@files_to_touch) unless $keep;\n\n\n# TEST 1: Make sure that top-level targets that depend on targets that\n# previously failed to build, aren't attempted.  Regression for PR/1634.\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\nprint MAKEFILE <<'EOF';\n.SUFFIXES:\n\nall: exe1 exe2; @echo making $@\n\nexe1 exe2: lib; @echo cp $^ $@\n\nlib: foo.o; @echo cp $^ $@\n\nfoo.o: ; exit 1\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile2, \"-k\", &get_logfile, $error_code);\n\n$answer = \"exit 1\n$make_name: *** [$makefile2:9: foo.o] Error 1\n$make_name: Target 'all' not remade because of errors.\\n\";\n\n&compare_output($answer, &get_logfile(1));\n\n# TEST -- make sure we keep the error code if we can't create an included\n# makefile.\n\nif (defined $ERR_no_such_file) {\n    run_make_test('all: ; @echo hi\ninclude ifile\nifile: no-such-file; exit 1\n',\n                  '-k',\n                  \"#MAKEFILE#:2: ifile: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'.\n#MAKEFILE#:2: failed to remake makefile 'ifile'\",\n                  512);\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-l",
    "content": "#                                                                    -*-perl-*-\n# Date: Tue, 11 Aug 1992 09:34:26 -0400\n# From: pds@lemming.webo.dg.com (Paul D. Smith)\n\n$description = \"Test load balancing (-l) option.\";\n\n$details = \"\\\nThis test creates a makefile where all depends on three rules\nwhich contain the same body.  Each rule checks for the existence\nof a temporary file; if it exists an error is generated.  If it\ndoesn't exist then it is created, the rule sleeps, then deletes\nthe temp file again.  Thus if any of the rules are run in\nparallel the test will fail.  When make is called in this test,\nit is given the -l option with a value of 0.0001.  This ensures\nthat the load will be above this number and make will therefore\ndecide that it cannot run more than one job even though -j 4 was\nalso specified on the command line.\";\n\n# On Windows a very different algorithm is used.\n$port_type eq 'W32' and return -1;\n\nopen(MAKEFILE,\"> $makefile\");\nprintf MAKEFILE subst_make_string(q!\ntest = #HELPER# noexist test-file file test-file sleep 2 rm test-file\n\nall : ONE TWO THREE\nONE : ; @$(test)\nTWO : ; @$(test)\nTHREE : ; @$(test)\n!);\nclose(MAKEFILE);\nmy $ans = \"noexist test-file\\nfile test-file\\nsleep 2\\nrm test-file\\n\";\n\n$mkoptions = \"-l 0.0001\";\n$mkoptions .= \" -j 4\" if ($parallel_jobs);\n\n# We have to wait longer than the default (5s).\n&run_make_with_options($makefile, $mkoptions, &get_logfile, 0, 10);\n\n$slurp = &read_file_into_string(&get_logfile(1));\nif ($slurp =~ /cannot enforce load limit/) {\n  return -1;\n}\n&compare_output(\"$ans$ans$ans\", &get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-n",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the -n option.\\n\";\n\n$details = \"Try various uses of -n and ensure they all give the correct results.\\n\";\n\ntouch('orig');\n\nrun_make_test(q!\nfinal: intermediate ; echo >> $@\nintermediate: orig ; echo >> $@\n!,\n              '', \"echo >> intermediate\\necho >> final\\n\");\n\n# TEST 1\n\nrun_make_test(undef, '-Worig -n', \"echo >> intermediate\\necho >> final\\n\");\n\n# We consider the actual updated timestamp of targets with all\n# recursive commands, even with -n.  Switching this to the new model\n# is non-trivial because we use a trick below to change the log content\n# before we compare it ...\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\n\nprint MAKEFILE <<'EOF';\n.SUFFIXES:\nBAR =     # nothing\nFOO = +$(BAR)\na: b; echo > $@\nb: c; $(FOO)\nEOF\n\nclose(MAKEFILE);\n\n&utouch(-20, 'b');\n&utouch(-10, 'a');\n&touch('c');\n\n# TEST 2\n\n&run_make_with_options($makefile2, \"\", &get_logfile);\n$answer = \"$make_name: 'a' is up to date.\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST 3\n\n&run_make_with_options($makefile2, \"-n\", &get_logfile);\n$answer = \"$make_name: 'a' is up to date.\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST 4\n\nunlink(qw(a b));\n\n&run_make_with_options($makefile2, \"-t -n\", &get_logfile);\n\nopen(DASH_N_LOG, \">>\" . &get_logfile(1));\nprint DASH_N_LOG \"a exists but should not!\\n\" if -e 'a';\nprint DASH_N_LOG \"b exists but should not!\\n\" if -e 'b';\nclose(DASH_N_LOG);\n\n&compare_output(\"touch b\\ntouch a\\n\", &get_logfile(1));\n\n# Ensure -n continues to be included with recursive/re-execed make\n# See Savannah bug #38051\n\n$topmake = &get_tmpfile;\n$submake = &get_tmpfile;\n\nopen(MAKEFILE, \"> $topmake\");\nprint MAKEFILE <<\"EOF\";\nfoo: ; \\@\\$(MAKE) -f \"$submake\" bar\nEOF\nclose(MAKEFILE);\n\n# The bar target should print what would happen, but not actually run\nopen(MAKEFILE, \"> $submake\");\nprint MAKEFILE <<'EOF';\ninc: ; touch $@\n-include inc\nbar: ; @echo $(strip $(MAKEFLAGS))\nEOF\nclose(MAKEFILE);\n\n&run_make_with_options($topmake, '-n --no-print-directory', &get_logfile);\n$answer = subst_make_string(\"#MAKEPATH# -f \\\"$submake\\\" bar\\ntouch inc\\necho n --no-print-directory\\n\");\n&compare_output($answer, &get_logfile(1));\n\n# SV 65917: Verify handling of -n with multi-target pattern rules\n\n# This is what the makefile below would run\nutouch(-12, qw(alpha.p));\nutouch(-10, qw(alpha.x alpha.y));\nutouch(-8, qw(beta.p));\nutouch(-6, qw(beta.x beta.y));\nutouch(-4, qw(alpha.q));\nutouch(-2, qw(beta.q));\n\n# Now make some things out of date\ntouch(qw(alpha.p));\n\nrun_make_test(q!\n.SUFFIXES:\n.RECIPEPREFIX := >\n\nall: alpha.q beta.q\n\nalpha.p beta.p:\n> touch $@\n\n%.x %.y: %.p\n> touch $*.x $*.y\n\nalpha.q: alpha.x alpha.y beta.y\n> touch $@\n\nbeta.q: beta.x beta.y alpha.y\n> touch $@\n!,\n    '-n', \"touch alpha.x alpha.y\\ntouch alpha.q\\ntouch beta.q\\n\");\n\n# This is what the makefile below would run\nutouch(-12, qw(quark.p));\nutouch(-10, qw(quark.x quark.y));\nutouch(-8, qw(meson.p));\nutouch(-6, qw(meson.x meson.y));\nutouch(-4, qw(quark.q));\nutouch(-2, qw(meson.q));\n\n# Now make some things out of date\ntouch(qw(quark.p));\n\nrun_make_test(q!\n.SUFFIXES:\n.RECIPEPREFIX := >\n\nall: quark.q meson.q\n\nquark.p meson.p:\n> touch $@\n\nquark.x quark.y &: quark.p\n> touch quark.x quark.y\n\nmeson.x meson.y &: meson.p\n> touch meson.x meson.y\n\nquark.q: quark.x quark.y meson.y\n> touch $@\n\nmeson.q: meson.x meson.y quark.y\n> touch $@\n!,\n    '-n', \"touch quark.x quark.y\\ntouch quark.q\\ntouch meson.q\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-q",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the -q option.\\n\";\n\n$details = \"Try various uses of -q and ensure they all give the correct results.\\n\";\n\n# TEST 0\n\nrun_make_test(qq!\none:\ntwo: ;\nthree: ; :\nfour: ; \\$(.XY)\nfive: ; \\\\\n \\$(.XY)\nsix: ; \\\\\n \\$(.XY)\n\\t\\$(.XY)\nseven: ; \\\\\n \\$(.XY)\n\\t: foo\n\\t\\$(.XY)\n!,\n              '-q one', '');\n\n# TEST 1\n\nrun_make_test(undef, '-q two', '');\n\n# TEST 2\n\nrun_make_test(undef, '-q three', '', 256);\n\n# TEST 3\n\nrun_make_test(undef, '-q four', '');\n\n# TEST 4\n\nrun_make_test(undef, '-q five', '');\n\n# TEST 5\n\nrun_make_test(undef, '-q six', '');\n\n# TEST 6\n\nrun_make_test(undef, '-q seven', '', 256);\n\n# TEST 7 : Savannah bug # 7144\n\nrun_make_test('\none:: ; @echo one\none:: ; @echo two\n',\n              '-q', '', 256);\n\n# TEST 7 : Savannah bug # 42249\n# Make sure we exit with 1 even for prerequisite updates\nrun_make_test('\nbuild-stamp: ; echo $@\nbuild-arch: build-stamp\nbuild-x: build-arch\nbuild-y: build-x\n',\n              '-q build-y', '', 256);\n\n# TEST 8\n# Make sure we exit with 2 on error even with -q\nrun_make_test('\nbuild-stamp: ; echo $@\nbuild-arch: build-stamp-2\nbuild-x: build-arch\nbuild-y: build-x\n',\n              '-q build-y', \"#MAKE#: *** No rule to make target 'build-stamp-2', needed by 'build-arch'.  Stop.\\n\", 512);\n\n# TEST 9 : Savannah bug # 47151\n# Make sure we exit with 1 when invoking a recursive make\nrun_make_test('\nfoo: bar ; echo foo\nbar: ; @$(MAKE) -f #MAKEFILE# baz\nbaz: ; echo baz\n',\n              '-q foo', '', 256);\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-r",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test removing default rules and variables\";\n\ntouch('xxx.c');\n\n# Simple check\nrun_make_test(\"\\n\", '-r COMPILE.c=echo xxx.o',\n              \"#MAKE#: *** No rule to make target 'xxx.o'.  Stop.\", 512);\n\n# Make sure we can set it from within the makefile too\nrun_make_test(q!\nCOMPILE.c = echo\nMAKEFLAGS += -r\n!,\n              'xxx.o',\n              \"#MAKE#: *** No rule to make target 'xxx.o'.  Stop.\", 512);\n\nunlink('xxx.c');\n\n# Simple check for -R\nrun_make_test(q!\nall:;$(info CC='$(CC)')\n!,\n              '-sR', \"CC=''\");\n\n# Make sure we can set -R from within the makefile too\nrun_make_test(q!\nMAKEFLAGS += -R\nall:;$(info CC='$(CC)')\n!,\n              '-s', \"CC=''\");\n\n# sv 62356.\n# Setting -R in MAKEFLAGS sets -r.\nrun_make_test(q!\nMAKEFLAGS := -R\n.PHONY: hello.c\nall: hello.o\n!, '', \"#MAKE#: *** No rule to make target 'hello.o', needed by 'all'.  Stop.\", 512);\n\nmy @flavors = ('=', ':=', ':::=', '+=');\n\n# sv 64107.\n\n# Use $answer to test that -R in the makefile has the same effect as -R on the\n# command line.\n\nmy $answer = \"at parse time TEX=\\nat build time TEX=\\n#MAKE#: 'all' is up to date.\\n\";\n\n# Subtest 1.\n# First run with -R command line switch.\n\nfor my $fl (@flavors) {\nrun_make_test(\"\n\\$(info at parse time TEX=\\$(TEX))\nall:; \\$(info at build time TEX=\\$(TEX))\n\", '-R', \"$answer\");\n}\n\n# Subtest 2.\n# Set -R in the makefile.\n# Also, test that setting -R in MAKEFLAGS takes effect immediately.\n\nfor my $fl (@flavors) {\nrun_make_test(\"\n\\$(info at start time TEX=\\$(TEX))\nMAKEFLAGS ${fl} -R\n\\$(info at parse time TEX=\\$(TEX))\nall:; \\$(info at build time TEX=\\$(TEX))\n\", '', \"at start time TEX=tex\\n$answer\");\n}\n\n# Same as above, but also set TEX conditionally.\n\n$answer = \"at parse time TEX=hello\\nat build time TEX=hello\\n#MAKE#: 'all' is up to date.\\n\";\n\n# Subtest 3.\n# -R on the command line.\n\nfor my $fl (@flavors) {\nrun_make_test(\"\nTEX ?= hello\n\\$(info at parse time TEX=\\$(TEX))\nall:; \\$(info at build time TEX=\\$(TEX))\n\", '-R', \"$answer\");\n}\n\n# Subtest 4.\n# -R in the makefile.\n\nfor my $fl (@flavors) {\nrun_make_test(\"\n\\$(info at start time TEX=\\$(TEX))\nMAKEFLAGS ${fl} -R\nTEX ?= hello\n\\$(info at parse time TEX=\\$(TEX))\nall:; \\$(info at build time TEX=\\$(TEX))\n\", '', \"at start time TEX=tex\\n$answer\");\n}\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-s",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -s (silent) and --no-silent options.\\n\";\n\nrun_make_test(q!\nall: one two\none: ; @echo MAKEFLAGS=$$MAKEFLAGS\ntwo: ; echo two\n!,\n              '', \"MAKEFLAGS=\\necho two\\ntwo\");\n\nrun_make_test(undef, '-s', \"MAKEFLAGS=s\\ntwo\");\nrun_make_test(undef, '--silent', \"MAKEFLAGS=s\\ntwo\");\nrun_make_test(undef, '--quiet', \"MAKEFLAGS=s\\ntwo\");\n\nrun_make_test(undef, '--no-silent', \"MAKEFLAGS= --no-silent\\necho two\\ntwo\");\n\nrun_make_test(undef, '-s --no-silent', \"MAKEFLAGS= --no-silent\\necho two\\ntwo\");\nrun_make_test(undef, '--silent --no-silent', \"MAKEFLAGS= --no-silent\\necho two\\ntwo\");\nrun_make_test(undef, '--quiet --no-silent', \"MAKEFLAGS= --no-silent\\necho two\\ntwo\");\n\nrun_make_test(undef, '--no-silent -s', \"MAKEFLAGS=s\\ntwo\");\nrun_make_test(undef, '--no-silent --silent', \"MAKEFLAGS=s\\ntwo\");\nrun_make_test(undef, '--no-silent --quiet', \"MAKEFLAGS=s\\ntwo\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/dash-t",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -t option.\\n\";\n\n$details = \"Look out for regressions of prior bugs related to -t.\\n\";\n# That means, nobody has even tried to make the tests below comprehensive\n\n# TEST 0\n# bug reported by Henning Makholm <henning@makholm.net> on 2001-11-03:\n#   make 3.79.1 touches only interm-[ab] but reports final-[a] as\n#   'up to date' without touching them.\n# The 'obvious' fix didn't work for double-colon rules, so pay special\n# attention to them.\n\nopen(MAKEFILE, \"> $makefile\");\nprint MAKEFILE <<'EOMAKE';\nfinal-a: interm-a ; echo >> $@\nfinal-b: interm-b ; echo >> $@\ninterm-a:: orig1-a ; echo >> $@\ninterm-a:: orig2-a ; echo >> $@\ninterm-b:: orig1-b ; echo >> $@\ninterm-b:: orig2-b ; echo >> $@\nEOMAKE\nclose(MAKEFILE);\n\n&utouch(-30, 'orig1-a','orig2-b');\n&utouch(-20, 'interm-a','interm-b');\n&utouch(-10, 'final-a','final-b');\n&touch('orig2-a','orig1-b');\n\n&run_make_with_options($makefile, \"-t final-a final-b\", &get_logfile);\n$answer = \"touch interm-a\\ntouch final-a\\ntouch interm-b\\ntouch final-b\\n\";\n&compare_output($answer, &get_logfile(1));\n\nunlink('orig1-a', 'orig2-a', 'interm-a', 'final-a');\nunlink('orig1-b', 'orig2-b', 'interm-b', 'final-b');\n\n# TEST 1\n# -t should not touch files with no commands.\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\nprint MAKEFILE <<'EOMAKE';\n\nPHOOEY: xxx\nxxx: ; @:\n\nEOMAKE\nclose(MAKEFILE);\n\n&run_make_with_options($makefile2, \"-t\", &get_logfile);\n$answer = \"touch xxx\\n\";\n&compare_output($answer, &get_logfile(1));\n\nunlink('xxx');\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/eval",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the --eval option.\";\n\n$details = \"Verify that --eval options take effect,\nand are passed to sub-makes.\";\n\n# Verify that --eval is evaluated first\nrun_make_test(q!\n$(info infile)\nBAR = bar\nall: ; @echo all\nrecurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!,\n              ['--eval=$(info eval)', 'FOO=$(BAR)'], \"eval\\ninfile\\nall\");\n\n# Make sure that --eval is handled correctly during recursion\nrun_make_test(undef, ['--no-print-directory', '--eval=$(info eval)', 'recurse'],\n              \"eval\\ninfile\\neval\\ninfile\\nall\\nrecurse\");\n\n# Make sure that --eval is not passed in MAKEFLAGS\nrun_make_test(q!\nall: ; @echo \"MAKEFLAGS=$$MAKEFLAGS\"\n!,\n              ['--eval=$(info eval)'],\n              \"eval\\n\".'MAKEFLAGS= --eval=$$(info\\ eval)');\n\n# Make sure that --eval is handled correctly during restarting\nrun_make_test(q!\nall: ; @echo $@\n-include gen.mk\ngen.mk: ; @echo > $@\n!,\n              ['--eval=$(info eval)'], \"eval\\neval\\nall\");\n\nunlink('gen.mk');\n\n# Check -E\nrun_make_test(q!\nBAR = bar\nall: ; @echo all\nrecurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!,\n              ['-E', '$(info eval)', 'FOO=$(BAR)'], \"eval\\nall\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/general",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test generic option processing.\\n\";\n\n# TEST 0\n\nif (!$parallel_jobs) {\n  $answer = \"#MAKE#: Parallel jobs (-j) are not supported on this platform.\\n#MAKE#: Resetting to single job (-j1) mode.\\n1foo\\n\";\n}\nelse {\n  $answer = \"1foo\\n\";\n}\n\nrun_make_test(q!\nfoo 1foo: ; @echo $@\n!,\n              \"-j 1foo\", $answer);\n\n# TEST 1\n\n# This test prints the usage string; I don't really know a good way to\n# test it.  I guess I could invoke make with a known-bad option to see\n# what the usage looks like, then compare it to what I get here... :(\n\n# On UNIX I can invoke it with 2>/dev/null, then just check the error code.\n\nif ($port_type ne 'W32') {\n    run_make_test(undef, \"-j1foo 2>/dev/null\", '', 512);\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/print-directory",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -w option to GNU Make.\";\n\nmy $enter = \"#MAKE#: Entering directory '#PWD#'\";\nmy $leave = \"#MAKE#: Leaving directory '#PWD#'\";\n\n# Simple test without -w\nrun_make_test(q!\nall: ; @echo hi\n!,\n        \"\", \"hi\\n\");\n\nmy $ans = \"$enter\\nhi\\n$leave\\n\";\n\n# Simple test with -w\nrun_make_test(undef, \"-w\", $ans);\n\n# Simple test with overriding -w\nrun_make_test(undef, \"-w --no-print-directory\", \"hi\\n\");\n\n# Simple test with overriding --no-print-directory\nrun_make_test(undef, \"--no-print-directory --print-directory\", $ans);\n\n# Test makefile rebuild to ensure no enter/leave\nrun_make_test(q!\ninclude foo\nall: ;@:\nfoo: ; touch foo\n!,\n        \"\", \"touch foo\\n\");\nunlink('foo');\n\n$ans = \"$enter\\ntouch foo\\n$leave\\n\";\n\n# Test makefile rebuild with -w\nrun_make_test(undef, \"-w\", $ans);\nunlink('foo');\n\n# Test makefile rebuild with -w overridden\nrun_make_test(undef, \"-w --no-print-directory\", \"touch foo\\n\");\nunlink('foo');\n\n# Test makefile rebuild with --no-print-directory overridden\nrun_make_test(undef, \"--no-print-directory --print-directory\", $ans);\nunlink('foo');\n\nmy $enter1 = \"#MAKE#[1]: Entering directory '#PWD#'\";\nmy $leave1 = \"#MAKE#[1]: Leaving directory '#PWD#'\";\n\n$ans = \"$enter1\\nhi\\n$leave1\\n\";\n\n# Test makefile recursion with default enter/leave\nrun_make_test(q!\nall: ;@$(MAKE) -f #MAKEFILE# recurse\nrecurse: ; @echo hi\n!,\n        \"\", $ans);\n\n# Disable enter/leave\nrun_make_test(undef, \"--no-print-directory\", \"hi\\n\");\n\n# Re-enable enter/leave\n$ans = \"$enter\\n$ans$leave\\n\";\nrun_make_test(undef, \"--no-print-directory -w\", $ans);\n\n# Override enter/leave\nrun_make_test(undef, \"-w --no-print-directory\", \"hi\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/print-targets",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the --print-targets option to GNU Make.\";\n\n# Define various things and verify the output\nrun_make_test(q!\n.PHONY: all\nall: ;@:\n\n# \"special\" target\n.BOGUS: ;@:\n\n# Check various forms of suffix rule\n.SUFFIXES: .q\n.q: ;@:\n.c.o: ;@:\n\n# Not a suffix rule\n.x.z: ;@:\n\n# Verify included files aren't built / don't fail\n\ninclude badfile\ninclude goodfile\n\nsubmake: ; $(MAKE) all\nalways: ; +echo always\ngoodfile: ; touch goodfile\n!,\n        \"--print-targets\", \"submake\\n.x.z\\nalways\\nall\\ngoodfile\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/shuffle",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the --shuffle option.\";\n\n$details = \"Verify that --shuffle has expected effect on target order and argument order.\";\n\n#\n# Test --shuffle=random\n#\n\n# TEST 1: Fixed seed should yield the same order from run to run.\n\n$makefile = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile\");\nprint MAKEFILE <<'EOF';\n# More target prerequisites lower collision chance in TEST 2\nall: a_ b_ c_ d_ e_ f_ g_ i_ j_ k_ l_\n%: ; echo $@\nEOF\nclose(MAKEFILE);\n\n$log1 = &get_logfile;\n$log2 = &get_logfile;\n&run_make_with_options($makefile, \"--shuffle=12345\", $log1);\n&run_make_with_options($makefile, \"--shuffle=12345\", $log2);\n\n&compare_output(&read_file_into_string($log1), $log2);\n\n# TEST 2: Sequential runs should produce different orders.\n\n$log3 = &get_logfile;\n$log4 = &get_logfile;\n&run_make_with_options($makefile, \"--shuffle\", $log3);\n&run_make_with_options($makefile, \"--shuffle\", $log4);\n\n++$tests_run;\nif (&read_file_into_string($log3) ne &read_file_into_string($log4)) {\n  print \"ok\\n\" if $debug;\n  ++$tests_passed;\n}\n\n#\n# Test --shuffle=reverse\n#\n\nrun_make_test('\n%: ; @echo $@\nall: a b c\n',\n              '--shuffle=reverse', \"c\\nb\\na\\nall\");\n\nrun_make_test('\n%: ; @echo $@\nall: a b c\n',\n              '--shuffle=none', \"a\\nb\\nc\\nall\");\n\nrun_make_test('\n%: ; @echo $@\nall: a b c\n',\n              '--shuffle=identity', \"a\\nb\\nc\\nall\");\n\n# Make sure prerequisites get reverse order and commands don't get affected.\nrun_make_test('\nall: foo.o ; @echo $@\n%.o : %.c ; @echo cc -c -o $@ $<\nfoo.o : foo.c foo.h bar.h baz.h\n%.h: ; @echo $@\n%.c: ; @echo $@\n',\n              '--shuffle=reverse',\n              \"baz.h\\nbar.h\\nfoo.h\\nfoo.c\\ncc -c -o foo.o foo.c\\nall\");\n\n# Make sure pattern prerequisites get reverse order and commands don't get\n# affected.\nrun_make_test('\nall: foo_ ; @echo $@\nfoo%: arg%1 arg%2 arg%3 arg%4 ; @echo bld $@ $< $(word 3,$^) $(word 2,$^) $(word 4,$^)\n\narg%: ; @echo $@\n',\n              '--shuffle=reverse',\n              \"arg_4\\narg_3\\narg_2\\narg_1\\nbld foo_ arg_1 arg_3 arg_2 arg_4\\nall\");\n\n# Check if make can survive circular dependency.\nrun_make_test('\nall: a_ b_ ; @echo $@\n%_: ; @echo $@\n\na_: b_\nb_: a_\n',\n              '--shuffle=reverse', \"#MAKE#: circular a_ <- b_ dependency dropped\\na_\\nb_\\nall\");\n\n# Check if order-only dependencies get reordered.\nrun_make_test('\nall: a_ ; @echo $@\n%_: ; @echo $@\na_: b_ c_ | d_ e_\n',\n              '--shuffle=reverse', \"e_\\nd_\\nc_\\nb_\\na_\\nall\");\n\n# Check if goals are reordered.\nrun_make_test('\n%_: ; @echo $@\n',\n              '--shuffle=reverse a_ b_ c_', \"c_\\nb_\\na_\");\n\n# .NOTPARALLEL should prevent reordering from happening.\nrun_make_test('\n%_: ; @echo $@\n# disable shuffling\n.NOTPARALLEL:\n',\n              '--shuffle=reverse a_ b_ c_', \"a_\\nb_\\nc_\");\n\n# Check if SECONDEXPANSION targets also get reshuffled.\nrun_make_test('\n.SECONDEXPANSION:\nall: $$(var)\n%_: ; @echo $@\nvar = a_ b_ c_\n',\n              '--shuffle=reverse', \"c_\\nb_\\na_\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/symlinks",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the -L option.\";\n\n$details = \"Verify that symlink handling with and without -L works properly.\";\n\n# Only run these tests if the system sypports symlinks\n\nexists $FEATURES{'check-symlink'} or return -1;\n\nuse File::Spec;\n\n# Set up a symlink sym -> dep\n# We'll make both dep and targ older than sym\n&utouch(-10, 'dep');\n&utouch(-5, 'targ');\n\nmy $dirnm = (File::Spec->splitdir($testpath))[-1];\nmy $dep = File::Spec->catfile(File::Spec->updir(), $dirnm, 'dep');\nsymlink($dep, 'sym') or die \"Cannot create symlink sym -> $dep\\n\";\n\n# Without -L, nothing should happen\n# With -L, it should update targ\nrun_make_test('targ: sym ; @echo make $@ from $<', '',\n              \"#MAKE#: 'targ' is up to date.\");\nrun_make_test(undef, '-L', \"make targ from sym\");\n\n# Now update dep; in all cases targ should be out of date.\n&touch('dep');\nrun_make_test(undef, '', \"make targ from sym\");\nrun_make_test(undef, '-L', \"make targ from sym\");\n\n# Now update targ; in all cases targ should be up to date.\n&touch('targ');\nrun_make_test(undef, '', \"#MAKE#: 'targ' is up to date.\");\nrun_make_test(undef, '-L', \"#MAKE#: 'targ' is up to date.\");\n\n# Add in a new link between sym and dep.  Be sure it's newer than targ.\nsleep(1);\nrename('dep', 'dep1');\nsymlink('dep1', 'dep');\n\n# Without -L, nothing should happen\n# With -L, it should update targ\nrun_make_test(undef, '', \"#MAKE#: 'targ' is up to date.\");\nrun_make_test(undef, '-L', \"make targ from sym\");\n\nrmfiles('targ', 'dep', 'sym', 'dep1');\n\n# Check handling when symlinks point to non-existent files.  Without -L we\n# should get an error: with -L we should use the timestamp of the symlink.\n\nsymlink(\"../$dirnm/dep\", 'sym');\nrun_make_test('targ: sym ; @echo make $@ from $<', '',\n              \"#MAKE#: *** No rule to make target 'sym', needed by 'targ'.  Stop.\", 512);\n\nrun_make_test('targ: sym ; @echo make $@ from $<', '-L',\n              'make targ from sym');\n\n\nrmfiles('targ', 'sym');\n\n1;\n"
  },
  {
    "path": "tests/scripts/options/warn",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the --warn option.\";\n\nmy %warn_test = (\n    '--warn' => '', '--warn=warn' => '', '--warn=error --warn=warn' => '',\n    '--warn --warn=error' => '=error',\n    '--warn=ignore --warn=error --warn=ignore --warn=invalid-ref,invalid-var,undefined-var' => '=ignore,invalid-ref,invalid-var,undefined-var',\n    '--warn=invalid-ref:ignore --warn=error --warn=invalid-var:warn,,,,,undefined-var:error,,,,,' => '=error,invalid-ref:ignore,invalid-var,undefined-var:error'\n);\n\n# Verify the deprecated --warn-undefined-variables option\nrun_make_test(q!\n$(info MF=$(MAKEFLAGS))\nall:; @#HELPER# env MAKEFLAGS\n!,\n              '--warn-undefined-variables', \"MF= --warn=undefined-var\\nMAKEFLAGS= --warn=undefined-var\");\n\n# sv 64115.\n# Verify that -R along with --warn-undefined-variables do not warn about\n# internal variables, such as GNUMAKEFLAGS.\n\nrun_make_test(q!\n$(info MF=$(MAKEFLAGS))\nall:; @#HELPER# env MAKEFLAGS\n!,\n              '-R --warn-undefined-variables', \"MF=rR --warn=undefined-var\\nMAKEFLAGS=rR --warn=undefined-var\");\n\n\n# Verify parsing of --warn in various forms.\n\nwhile (my ($f, $r) = each %warn_test) {\n    run_make_test(undef, $f, \"MF= --warn$r\\nMAKEFLAGS= --warn$r\");\n}\n\n# Verify that values set in MAKEFLAGS take effect\n\nwhile (my ($f, $r) = each %warn_test) {\n    run_make_test(qq!\nMAKEFLAGS += $f\n\\$(info MF=\\$(MAKEFLAGS))\nall:; \\@#HELPER# env MAKEFLAGS\n!,\n                  '', \"MF= --warn$r\\nMAKEFLAGS= --warn$r\");\n}\n\n# Verify that make's special variables don't warn even if they're not set\nrun_make_test(q!\nvars := $(.VARIABLES) $(MAKECMDGOALS) $(MAKE_RESTARTS) $(CURDIR)\nvars += $(GNUMAKEFLAGS) $(MAKEFLAGS) $(MFLAGS) $(MAKE_COMMAND) $(MAKE)\nvars += $(MAKEFILE_LIST) $(MAKEOVERRIDES) $(-*-command-variables-*-)\nvars += $(.RECIPEPREFIX) $(.LOADED) $(.FEATURES)\nvars += $(SHELL) $(.SHELLFLAGS) $(MAKE_TERMOUT) $(MAKE_TERMERR)\nvars += $(.DEFAULT) $(.DEFAULT_GOAL) $(-*-eval-flags-*-) $(SUFFIXES)\nvars += $(VPATH) $(GPATH)\nall:;\n!,\n              '--warn=undefined-var', \"#MAKE#: 'all' is up to date.\");\n\n# sv 63609.\n# Test for buffer overrun in warn_undefined.\nrun_make_test(q!\nall:;\nX := $(averyveryveryloooooooooooooooooooooooooooongvariablename)\n!,\n              '--warn=undefined-var',\n              \"#MAKEFILE#:3: warning: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename'\n#MAKE#: 'all' is up to date.\\n\"\n);\n\n# Check undefined variable warnings\n\n# With no options or with ignore, nothing should happen\nrun_make_test('\nEMPTY =\nEREF = $(EMPTY)\nUREF = $(UNDEFINED)\n\nSEREF := $(EREF)\nSUREF := $(UREF)\n\nall: ; @echo ref $(EREF) $(UREF)',\n              '', 'ref');\n\nrun_make_test(undef, '--warn=undefined-var:ignore', 'ref');\n\n# Check warnings\nrun_make_test(undef, '--warn=undefined-var',\n              \"#MAKEFILE#:7: warning: reference to undefined variable 'UNDEFINED'\n#MAKEFILE#:9: warning: reference to undefined variable 'UNDEFINED'\nref\");\n\n# Check and errors\nrun_make_test(undef, '--warn=undefined-var:error',\n              \"#MAKEFILE#:7: *** reference to undefined variable 'UNDEFINED'.  Stop.\", 512);\n\n# Check invalid variable reference warnings\n\n# With no options we still check for invalid references\nrun_make_test('\nIREF = $(bad variable)\nSIREF := $(IREF)\n\ndefine nl\n\n\nendef\n\nall: ; @echo ref $(also$(nl)bad) $(IREF) $(SIREF)',\n              '', \"#MAKEFILE#:2: warning: invalid variable reference 'bad variable'\n#MAKEFILE#:10: warning: invalid variable reference 'also\\nbad'\n#MAKEFILE#:2: warning: invalid variable reference 'bad variable'\nref\");\n\nrun_make_test(undef, '--warn=ignore', 'ref');\n\nrun_make_test(undef, '--warn=invalid-ref:ignore', 'ref');\n\n# Check and errors\nrun_make_test(undef, '--warn=invalid-ref:error',\n              \"#MAKEFILE#:2: *** invalid variable reference 'bad variable'.  Stop.\", 512);\n\n# Check invalid variable name warnings\n\n# With no options we still check for invalid references\nrun_make_test('\nEMPTY =\nSPACE = $(EMPTY) $(EMPTY)\nBAD$(SPACE)VAR = foo\n\ndefine nl\n\n\nendef\n\nNL$(nl)VAR = bar\n\ndefine BAD$(SPACE)DEF :=\nfoo\nendef\n\ndefine NL$(nl)DEF :=\nfoo\nendef\n\nall: ; @echo ref',\n              '', \"#MAKEFILE#:4: warning: invalid variable name 'BAD VAR'\n#MAKEFILE#:11: warning: invalid variable name 'NL\\nVAR'\n#MAKEFILE#:13: warning: invalid variable name 'BAD DEF'\n#MAKEFILE#:17: warning: invalid variable name 'NL\\nDEF'\nref\");\n\nrun_make_test(undef, '--warn=ignore', 'ref');\n\nrun_make_test(undef, '--warn=invalid-var:ignore', 'ref');\n\n# Check errors\nrun_make_test(undef, '--warn=invalid-var:error',\n              \"#MAKEFILE#:4: *** invalid variable name 'BAD VAR'.  Stop.\", 512);\n\n# Make sure unknown warnings and actions fail when given on the command line.\n\nrun_make_test(undef, '--warn=no-such-warn',\n    \"#MAKE#: *** unknown warning 'no-such-warn'.  Stop.\", 512);\n\nrun_make_test(undef, '--warn=invalid-var:no-such-action',\n    \"#MAKE#: *** unknown warning action 'no-such-action'.  Stop.\", 512);\n\n# sv 65739. Circular dependency.\nrun_make_test(q!\nhello: hello; @:\n!,\n              '', \"#MAKE#: circular hello <- hello dependency dropped\\n\");\n\nrun_make_test(undef, '--warn=error', \"#MAKE#: *** circular hello <- hello dependency detected.  Stop.\\n\", 512);\nrun_make_test(undef, '--warn=circular-dep:error', \"#MAKE#: *** circular hello <- hello dependency detected.  Stop.\\n\", 512);\nrun_make_test(undef, '--warn=warn', \"#MAKE#: circular hello <- hello dependency dropped\\n\");\nrun_make_test(undef, '--warn=circular-dep:warn', \"#MAKE#: circular hello <- hello dependency dropped\\n\");\nrun_make_test(undef, '--warn=ignore', '');\nrun_make_test(undef, '--warn=circular-dep:ignore', '');\n\n1;\n"
  },
  {
    "path": "tests/scripts/targets/DEFAULT",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to override part\\n\"\n              .\"of one Makefile with Another Makefile with the .DEFAULT\\n\"\n              .\"rule.\";\n\n$details = \"This tests the use of the .DEFAULT special target to say that \\n\"\n          .\"to remake any target that cannot be made fram the information\\n\"\n          .\"in the containing makefile, make should look in another makefile\\n\"\n          .\"This test gives this makefile the target bar which is not \\n\"\n          .\"defined here but passes the target bar on to another makefile\\n\"\n          .\"which does have the target bar defined.\\n\";\n\ncreate_file('defsub.mk', q!\nbar: ; @echo Executing rule BAR\n!);\n\nrun_make_test(q!\nfoo:; @echo Executing rule FOO\n\n.DEFAULT: ; @$(MAKE) -f defsub.mk $@\n!,\n                       'bar',\"#MAKE#[1]: Entering directory '#PWD#'\\n\"\n                       . \"Executing rule BAR\\n\"\n                       . \"#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\nunlink('defsub.mk');\n\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/targets/DELETE_ON_ERROR",
    "content": "#! -*-perl-*-\n\n$description = \"Test the behaviour of the .DELETE_ON_ERROR target.\";\n\n$details = \"\";\n\nrun_make_test('\n.DELETE_ON_ERROR:\nall: ; exit 1 > $@\n',\n              '', \"exit 1 > all\\n#MAKE#: *** [#MAKEFILE#:3: all] Error 1\\n#MAKE#: *** deleting file 'all'\", 512);\n\nrun_make_test('\n.DELETE_ON_ERROR:\nall: foo.x ;\n%.x : %.q ; echo > $@\n%.q : ; exit 1 > $@\n',\n              '', \"exit 1 > foo.q\\n#MAKE#: *** [#MAKEFILE#:5: foo.q] Error 1\\n#MAKE#: *** deleting file 'foo.q'\", 512);\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/FORCE",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following tests rules without Commands or Dependencies.\";\n\n# Create a file named \"clean\".  This is the same name as the target clean\n# and tricks the target into thinking that it is up to date.  (Unless you\n# use the .PHONY target.\ntouch('clean');\n\nrun_make_test(qq!\n.IGNORE :\nclean: FORCE ; $CMD_rmfile clean\nFORCE:\n!,\n              '', \"$CMD_rmfile clean\");\n\nrmfiles('clean');\n\n1;\n"
  },
  {
    "path": "tests/scripts/targets/IGNORE",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .IGNORE target.\";\n\n$details = \"\";\n\n# Without any ignore\nrun_make_test(q!\nall: ; @#HELPER# -q fail 1\n!,\n              '', \"#MAKE#: *** [#MAKEFILE#:2: all] Error 1\", 512);\n\n# Global .IGNORE\nrun_make_test(q!\n.IGNORE:\nall: ; @#HELPER# -q fail 1\n!,\n              '', \"#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\");\n\n# Specific .IGNORE\n\nrun_make_test(q!\n.IGNORE: all\nall: ; @#HELPER# -q fail 1\n!,\n              '', \"#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/targets/INTERMEDIATE",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .INTERMEDIATE target.\";\n\n$details = \"\\\nTest the behavior of the .INTERMEDIATE special target.\nCreate a makefile where a file would not normally be considered\nintermediate, then specify it as .INTERMEDIATE.  Build and ensure it's\ndeleted properly.  Rebuild to ensure that it's not created if it doesn't\nexist but doesn't need to be built.  Change the original and ensure\nthat the intermediate file and the ultimate target are both rebuilt, and\nthat the intermediate file is again deleted.\n\nTry this with implicit rules and explicit rules: both should work.\\n\";\n\n# TEST #0\n\n&utouch(-20, 'foo.f', 'bar.f');\n\nrun_make_test(q!\n.INTERMEDIATE: foo.e bar.e\n\n# Implicit rule test\n%.d : %.e ; cp $< $@\n%.e : %.f ; cp $< $@\n\nfoo.d: foo.e\n\n# Explicit rule test\nfoo.c: foo.e bar.e; cat $^ > $@\n!,\n    'foo.d', \"cp foo.f foo.e\\ncp foo.e foo.d\\nrm foo.e\\n\");\n\n# TEST #1\n\nrun_make_test(undef, 'foo.d', \"#MAKE#: 'foo.d' is up to date.\\n\");\n\n# TEST #2\n\n&utouch(-10, 'foo.d');\n&touch('foo.f');\n\nrun_make_test(undef, 'foo.d', \"cp foo.f foo.e\\ncp foo.e foo.d\\nrm foo.e\\n\");\n\n# TEST #3\n\nrun_make_test(undef, 'foo.c', \"cp foo.f foo.e\\ncp bar.f bar.e\\ncat foo.e bar.e > foo.c\\nrm foo.e bar.e\\n\");\n\n# TEST #4\n\nrun_make_test(undef, 'foo.c', \"#MAKE#: 'foo.c' is up to date.\\n\");\n\n# TEST #5\n\n&utouch(-10, 'foo.c');\n&touch('foo.f');\n\nrun_make_test(undef, 'foo.c', \"cp foo.f foo.e\\ncp bar.f bar.e\\ncat foo.e bar.e > foo.c\\nrm foo.e bar.e\\n\");\n\n# TEST #6 -- added for PR/1669: don't remove files mentioned on the cmd line.\n\nrun_make_test(undef, 'foo.e', \"cp foo.f foo.e\\n\");\n\nunlink('foo.f', 'foo.e', 'foo.d', 'foo.c', 'bar.f', 'bar.e', 'bar.d', 'bar.c');\n\n# TEST #7 -- added for PR/1423\n\nrun_make_test(q!\nall: foo\nfoo.a: ; touch $@\n%: %.a ; touch $@\n.INTERMEDIATE: foo.a\n!,\n              '-R',  \"touch foo.a\\ntouch foo\\nrm foo.a\\n\");\n\nunlink('foo');\n\n# sv 60188.\n# A file made by an implicit rule, but explicitly mentioned by the user, is\n# still considered intermediate if it's a prereq to .INTERMEDIATE.\n\ntouch('hello.z');\nunlink('test.x');\n\nrun_make_test(q!\nall: hello.z\n%.z: test.x; touch $@\n%.x: ;\n.INTERMEDIATE: test.x\n!, '', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nunlink('hello.z');\n\n# A target explicitly listed as a prerequisite of a pattern rule, is still\n# considered mentioned and \"ought to exist\".\n\nrun_make_test(q!\n1.all: 1.q ; touch $@\n%.q: 1.r ; touch $@\n%.r: ; touch $@\n.INTERMEDIATE: 1.r\n!,\n              '', \"touch 1.r\\ntouch 1.q\\ntouch 1.all\\nrm 1.r\\n\");\n\nunlink('1.all', '1.q', '1.r');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/NOTINTERMEDIATE",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .NOTINTERMEDIATE target.\";\n\n$details = \"\\\nTest the behavior of the .NOTINTERMEDIATE special target.\\n\";\n\ntouch('hello.z');\nunlink('hello.x');\n\n\n# Test 1. A file which matches a .NOTINTERMEDIATE pattern is not intermediate.\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE: %.q %.x\n!, '', \"touch hello.z\\n\");\n\n# Test 2. .NOTINTERMEDIATE: %.q pattern has no effect on hello.x.\ntouch('hello.z');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE: %.q\n!, '', \"#MAKE#: 'hello.z' is up to date.\\n\");\n\n# Test 3. A file which is a prereq of .NOTINTERMEDIATE is not intermediate.\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE: %.q hello.x\n!, '', \"touch hello.z\\n\");\n\n# Test 4. .NOTINTERMEDIATE without prerequisites makes everything\n# notintermediate.\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE:\n!, '', \"touch hello.z\\n\");\n\n# Test 5. Same file cannot be intermediate and notintermediate.\nrun_make_test(q!\n.INTERMEDIATE: hello.x\n.NOTINTERMEDIATE: hello.x\n!, '', \"#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .INTERMEDIATE.  Stop.\\n\", 512);\n\n# Test 6. Same file cannot be secondary and notintermediate.\nrun_make_test(q!\n.SECONDARY: hello.x\n.NOTINTERMEDIATE: hello.x\n!, '', \"#MAKE#: *** hello.x cannot be both .NOTINTERMEDIATE and .SECONDARY.  Stop.\\n\", 512);\n\n# Test 7. All .SECONDARY and all .NOTINTERMEDIATE are mutually exclusive.\nrun_make_test(q!\n.SECONDARY:\n.NOTINTERMEDIATE:\n!, '', \"#MAKE#: *** .NOTINTERMEDIATE and .SECONDARY are mutually exclusive.  Stop.\\n\", 512);\n\n# Test 8. .INTERMEDIATE file takes priority over a .NOTINTERMEDIATE pattern.\nunlink('hello.x');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.INTERMEDIATE: hello.x\n.NOTINTERMEDIATE: %.q %.x\n!, '', \"#MAKE#: 'hello.z' is up to date.\\n\");\n\n# Test 9. Everything is notintermediate, except hello.x.\nunlink('hello.x');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.INTERMEDIATE: hello.x\n.NOTINTERMEDIATE:\n!, '', \"#MAKE#: 'hello.z' is up to date.\\n\");\n\n# Test 10. Everything is notintermediate, except hello.x.\nunlink('hello.x');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.SECONDARY: hello.x\n.NOTINTERMEDIATE:\n!, '', \"#MAKE#: 'hello.z' is up to date.\\n\");\n\n# Test 11. Everything is secondary, except %.q, hello.x.\nunlink('hello.x');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE: %.q hello.x\n.SECONDARY:\n!, '', \"touch hello.z\\n\");\n\n# Test 12. Everything is secondary, except %.q %.x.\nunlink('hello.x');\nrun_make_test(q!\nhello.z:\n%.z: %.x; touch $@\n%.x: ;\n.NOTINTERMEDIATE: %.q %.x\n.SECONDARY:\n!, '', \"touch hello.z\\n\");\n\nunlink('hello.z');\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/ONESHELL",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .ONESHELL target.\";\n\n$details = \"\";\n\nmy $multi_ok = 0;\n\nif ($port_type ne 'W32') {\n    # Some shells (*shakes fist at Solaris*) cannot handle multiple flags in\n    # separate arguments.\n    my $t = `$sh_name -e -c true 2>/dev/null`;\n    $multi_ok = $? == 0;\n}\n\n# Simple\n\nrun_make_test(q!\n.ONESHELL:\nall:\n\ta=$$$$\n\t[ 0\"$$a\" -eq \"$$$$\" ] || echo fail\n!,\n              '', 'a=$$\n[ 0\"$a\" -eq \"$$\" ] || echo fail\n');\n\n# Simple but use multi-word SHELLFLAGS\n\nif ($multi_ok) {\n    run_make_test(q!\n.ONESHELL:\n.SHELLFLAGS = -e -c\nall:\n\ta=$$$$\n\t[ 0\"$$a\" -eq \"$$$$\" ] || echo fail\n!,\n              '', 'a=$$\n[ 0\"$a\" -eq \"$$\" ] || echo fail\n');\n}\n\n# Again, but this time with inner prefix chars\n\nrun_make_test(q!\n.ONESHELL:\nall:\n\ta=$$$$\n\t@-+    [ 0\"$$a\" -eq \"$$$$\" ] || echo fail\n!,\n              '', 'a=$$\n[ 0\"$a\" -eq \"$$\" ] || echo fail\n');\n\n# This time with outer prefix chars\n\nrun_make_test(q!\n.ONESHELL:\nall:\n\t   @a=$$$$\n\t    [ 0\"$$a\" -eq \"$$$$\" ] || echo fail\n!,\n              '', '');\n\n\n# This time with outer and inner prefix chars\n\nrun_make_test(q!\n.ONESHELL:\nall:\n\t   @a=$$$$\n\t    -@     +[ 0\"$$a\" -eq \"$$$$\" ] || echo fail\n!,\n              '', '');\n\n\n# Now try using a different interpreter\n# This doesn't work on Windows right now\nif ($port_type ne 'W32') {\n    run_make_test(q!\n.RECIPEPREFIX = >\n.ONESHELL:\nSHELL = #PERL#\n.SHELLFLAGS = -e\nall:\n>\t   @$$a=5\n>\t    +7;\n>\t@y=qw(a b c);\n>print \"a = $$a, y = (@y)\\n\";\n!,\n                  '', \"a = 12, y = (a b c)\\n\");\n\n    # Simple .SHELLFLAGS, no quotes.\n    # sv 61805.\n    run_make_test(q!\n.ONESHELL:\nSHELL = #PERL#\n.SHELLFLAGS = -e\nall:; @print \"it works\\n\"\n!, '', 'it works');\n\n    # Pass a quoted string with spaces to oneshell.\n    # sv 61805.\n    run_make_test(q!\n.ONESHELL:\nSHELL = #PERL#\n.SHELLFLAGS = -w -E 'use warnings FATAL => \"all\";' -E\nall:; @print \"it works\\n\"\n!, '', 'it works');\n\n    # Empty .SHELLFLAGS.\n    # sv 61805.\n    run_make_test(q!\n.ONESHELL:\nSHELL = #PERL#\n.SHELLFLAGS =\nall:; @print \"it works\"\n!, '', \"Can't open perl script \\\"print \\\"it works\\\"\\\": $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:5: all] Error $ERR_no_such_file_code\", 512);\n\n    # No .SHELLFLAGS.\n    # sv 61805.\n    run_make_test(q!\n.ONESHELL:\nSHELL = #PERL#\nall:; @print \"it works\"\n!, '', \"Can't open perl script \\\"print \\\"it works\\\"\\\": $ERR_no_such_file\\n#MAKE#: *** [#MAKEFILE#:4: all] Error $ERR_no_such_file_code\", 512);\n\n    # Pass a quoted string with spaces to oneshell.\n    # sv 61805.\n    run_make_test(q!\n.ONESHELL:\nSHELL = #PERL#\n.SHELLFLAGS = -w -E 'use warnings FATAL => \"all\";' -E 'my $$foo = \"bar\";' -E\nall:; @print \"it works: $$foo\\n\"\n!, '', 'it works: bar');\n}\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/targets/PHONY",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following tests the use of a PHONY target.  It makes\\n\"\n              .\"sure that the rules under a target get executed even if\\n\"\n              .\"a filename of the same name of the target exists in the\\n\"\n              .\"directory.\\n\";\n\n$details = \"This makefile in this test declares the target clean to be a \\n\"\n          .\"PHONY target.  We then create a file named \\\"clean\\\" in the \\n\"\n          .\"directory.  Although this file exists, the rule under the target\\n\"\n          .\"clean should still execute because of it's phony status.\";\n\n$example = \"EXAMPLE_FILE\";\n\ntouch($example);\n\n# Create a file named \"clean\".  This is the same name as the target clean\n# and tricks the target into thinking that it is up to date.  (Unless you\n# use the .PHONY target.\ntouch('clean');\n\nopen(MAKEFILE, \"> $makefile\");\nprint MAKEFILE qq!\n.PHONY : clean\nall: ; \\@echo This makefile did not clean the dir ... good\nclean: ; $CMD_rmfile $example clean\n!;\nclose(MAKEFILE);\n\n$answer = \"$CMD_rmfile $example clean\\n\";\n&run_make_with_options($makefile,\"clean\",&get_logfile);\n\nif (-f $example) {\n  $test_passed = 0;\n}\n\n&compare_output($answer,&get_logfile(1));\n\n# Just in case\nunlink($example, 'clean');\n\n1;\n"
  },
  {
    "path": "tests/scripts/targets/POSIX",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .POSIX target.\";\n\n$details = \"\";\n\n\n# Ensure turning on .POSIX enables the -e flag for the shell\n\nrun_make_test(q!\n.POSIX:\nall: ; @#HELPER# -q fail 1; #HELPER# out hello\n!,\n              '', \"#MAKE#: *** [#MAKEFILE#:3: all] Error 1\\n\", 512);\n\n# But explicit settings must still take precedence\n\nrun_make_test(q!\n.POSIX:\nall: ; @-#HELPER# -q fail 1; #HELPER# out hello\n.SHELLFLAGS = -c\n!,\n              '', \"hello\");\n\nrun_make_test(q!\n.POSIX:\nall: ; @-#HELPER# -q fail 1; #HELPER# out hello\nall: .SHELLFLAGS = -c\n!,\n              '', \"hello\");\n\n# SV 63667: We shouldn't add -e to sh if errors are ignored\n\nrun_make_test(q!\n.POSIX:\nall: ; @-#HELPER# -q fail 1; #HELPER# out hello\n!,\n              '', \"hello\\n\");\n\n# SV 64085: Also don't add -e if -i or .IGNORE is used\n\nrun_make_test(q!\n.POSIX:\nall: ; @#HELPER# -q fail 1; #HELPER# out hello\n!,\n              '-i', \"hello\\n\");\n\nrun_make_test(q!\n.POSIX:\n.IGNORE:\nall: ; @#HELPER# -q fail 1; #HELPER# out hello\n!,\n              '', \"hello\\n\");\n\nrun_make_test(q!\n.POSIX:\n.IGNORE: all\nall: ; @#HELPER# -q fail 1; #HELPER# out hello\n!,\n              '', \"hello\\n\");\n\n# But explicit settings must still take precedence\n\nrun_make_test(q!\n.POSIX:\nall: ; @-#HELPER# -q fail 1; #HELPER# out hello\n.SHELLFLAGS = -ec\n!,\n              '', \"#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\\n\");\n\nrun_make_test(q!\n.POSIX:\nall: ; @-#HELPER# -q fail 1; #HELPER# out hello\nall: .SHELLFLAGS = -ec\n!,\n              '', \"#MAKE#: [#MAKEFILE#:3: all] Error 1 (ignored)\\n\");\n\n# User settings must override .POSIX\n# In the standard .POSIX must be the first thing in the makefile\n# but we relax that rule in GNU Make.\n\n# Different versions of sh generate different output for -x so check it\nmy $script = subst_make_string('#HELPER# -q fail 1; true');\nmy $flags = '-xc';\nmy $out = `$sh_name $flags '$script' 2>&1`;\n\nrun_make_test(qq!\n.SHELLFLAGS = $flags\n.POSIX:\nall: ; \\@$script\n!,\n              '', $out);\n\n# Test the default value of various POSIX-specific variables\nmy %POSIX = (AR => 'ar', ARFLAGS => '-rv',\n             YACC => 'yacc', YFLAGS => '',\n             LEX => 'lex', LFLAGS => '',\n             LDFLAGS => '',\n             CC => 'c99', CFLAGS => '-O1',\n             FC => 'fort77', FFLAGS => '-O1',\n             SCCSFLAGS => '', SCCSGETFLAGS => '-s');\nmy $make = join('', map { \"\\t\\@echo '$_=\\$($_)'\\n\" } sort keys %POSIX);\nmy $r = join('', map { \"$_=$POSIX{$_}\\n\"} sort keys %POSIX);\nrun_make_test(qq!\n.POSIX:\nall:\n$make\n!,\n              '', $r);\n\n# Make sure that local settings take precedence\n%ENV = (%ENV, map { $_ => \"xx-$_\" } keys %POSIX);\n$r = join('', map { \"$_=xx-$_\\n\"} sort keys %POSIX);\nrun_make_test(undef, '', $r);\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/SECONDARY",
    "content": "#! -*-perl-*-\n\n$description = \"Test the behaviour of the .SECONDARY target.\";\n\n$details = \"\\\nTest the behavior of the .SECONDARY special target.\nCreate a makefile where a file would not normally be considered\nintermediate, then specify it as .SECONDARY.  Build and note that it's\nnot automatically deleted.  Delete the file.  Rebuild to ensure that\nit's not created if it doesn't exist but doesn't need to be built.\nChange the original and ensure that the secondary file and the ultimate\ntarget are both rebuilt, and that the secondary file is not deleted.\n\nTry this with implicit rules and explicit rules: both should work.\\n\";\n\nopen(MAKEFILE,\"> $makefile\");\n\nprint MAKEFILE <<'EOF';\n\n.SECONDARY: foo.e\n\n# Implicit rule test\n%.d : %.e ; cp $< $@\n%.e : %.f ; cp $< $@\n\nfoo.d: foo.e\n\n# Explicit rule test\nfoo.c: foo.e ; cp $< $@\nEOF\n\nclose(MAKEFILE);\n\n# TEST #1\n\n&utouch(-20, 'foo.f');\n\n&run_make_with_options($makefile,'foo.d',&get_logfile);\n$answer = \"cp foo.f foo.e\\ncp foo.e foo.d\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #2\n\nunlink('foo.e');\n\n&run_make_with_options($makefile,'foo.d',&get_logfile);\n$answer = \"$make_name: 'foo.d' is up to date.\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #3\n\n&utouch(-10, 'foo.d');\n&touch('foo.f');\n\n&run_make_with_options($makefile,'foo.d',&get_logfile);\n$answer = \"cp foo.f foo.e\\ncp foo.e foo.d\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #4\n\n&run_make_with_options($makefile,'foo.c',&get_logfile);\n$answer = \"cp foo.e foo.c\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #5\n\nunlink('foo.e');\n\n&run_make_with_options($makefile,'foo.c',&get_logfile);\n$answer = \"$make_name: 'foo.c' is up to date.\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #6\n\n&utouch(-10, 'foo.c');\n&touch('foo.f');\n\n&run_make_with_options($makefile,'foo.c',&get_logfile);\n$answer = \"cp foo.f foo.e\\ncp foo.e foo.c\\n\";\n&compare_output($answer, &get_logfile(1));\n\nunlink('foo.f', 'foo.e', 'foo.d', 'foo.c');\n\n# TEST #7 -- test the \"global\" .SECONDARY, with no targets.\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\n\nprint MAKEFILE <<'EOF';\n.SECONDARY:\n\nfinal: intermediate\nintermediate: source\n\nfinal intermediate source: ; echo $< > $@\nEOF\n\nclose(MAKEFILE);\n\n&utouch(-10, 'source');\ntouch('final');\n\n&run_make_with_options($makefile2, '', &get_logfile);\n$answer = \"$make_name: 'final' is up to date.\\n\";\n&compare_output($answer, &get_logfile(1));\n\nunlink('source', 'final', 'intermediate');\n\n\n# TEST #8 -- test the \"global\" .SECONDARY, with .PHONY.\n\ntouch('version2');\nrun_make_test('\n.PHONY: version\n.SECONDARY:\nversion2: version ; @echo GOOD\nall: version2',\n              'all', 'GOOD');\n\nunlink('version2');\n\n# TEST #9 -- Savannah bug #15919\n# The original fix for this bug caused a new bug, shown here.\n\ntouch(qw(1.a 2.a));\n\nrun_make_test('\n%.c : %.b ; cp $< $@\n%.b : %.a ; cp $< $@\nall : 1.c 2.c\n2.a: 1.c', '-rR -j',\n'cp 1.a 1.b\ncp 1.b 1.c\ncp 2.a 2.b\ncp 2.b 2.c\nrm 2.b 1.b');\n\nunlink(qw(1.a 2.a 1.c 2.c));\n\n# TEST #10 -- Savannah bug #15919\ntouch('test.0');\nrun_make_test('\n.SECONDARY : test.1 test.2 test.3\n\ntest : test.4\n\n%.4 : %.int %.3 ; touch $@\n\n%.int : %.3 %.2 ; touch $@\n\n%.3 : | %.2 ; touch $@\n\n%.2 : %.1 ; touch $@\n\n%.1 : %.0 ; touch $@', '-rR -j 2',\n'touch test.1\ntouch test.2\ntouch test.3\ntouch test.int\ntouch test.4\nrm test.int');\n\n# After a touch of test.0 it should give the same output, except we don't need\n# to rebuild test.3 (order-only)\nsleep(1);\ntouch('test.0');\nrun_make_test(undef, '-rR -j 2',\n'touch test.1\ntouch test.2\ntouch test.int\ntouch test.4\nrm test.int');\n\n# With both test.0 and test.3 updated it should still build everything except\n# test.3\nsleep(1);\ntouch('test.0', 'test.3');\nrun_make_test(undef, '-rR -j 2',\n'touch test.1\ntouch test.2\ntouch test.int\ntouch test.4\nrm test.int');\n\nunlink(qw(test.0 test.1 test.2 test.3 test.4));\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/SILENT",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the special target .SILENT.\";\n\nrun_make_test(q!\n.PHONY: M a b\nM: a b\n.SILENT : b\na b: ; echo $@\n!,\n              '', \"echo a\\na\\nb\");\n\nrun_make_test(q!\n.PHONY: M a b\nM: a b\n.SILENT:\na b: ; echo $@\n!,\n              '', \"a\\nb\");\n\n# SV 54740 : don't inherit .SILENT settings in sub-makes\nrun_make_test(q!\n.PHONY: M r a b\nr: a b ; @$(MAKE) -f #MAKEFILE# M V=x\na b: ; echo $@\n\nV =\n$V.SILENT:\nM: a b\n!,\n              '--no-print-directory', \"a\\nb\\necho a\\na\\necho b\\nb\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/targets/WAIT",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the behaviour of the .WAIT target.\";\n\n$details = \"\";\n\n# Ensure .WAIT doesn't appear in any automatic variables\n\nrun_make_test(q!\nall: .WAIT pre1 .WAIT pre2 | .WAIT pre3 ; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'\npre1 pre2 pre3:;\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n    '', '<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3');\n\nrun_make_test(q!\n.SECONDEXPANSION:\nall: $$(pre) ; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'\npre1 pre2 pre3:;\n\npre = .WAIT pre1 .WAIT pre2 | .WAIT pre3\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n    '', '<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3');\n\nrun_make_test(q!\nall: pre\np% : .WAIT p%1 .WAIT p%2 | .WAIT p%3; @echo '<=$< ^=$^ ?=$? +=$+ |=$|'\npre1 pre2 pre3: ;\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '', \"<=pre1 ^=pre1 pre2 ?=pre1 pre2 +=pre1 pre2 |=pre3\\n\");\n\n# Unfortunately I don't think we can get away from using sleep here; at least\n# I can't think of any way to make sure .WAIT works without it.  Even with it,\n# it's not reliable (in that even if .WAIT is not working we MIGHT succeed the\n# test--it shouldn't ever be the case that we fail the test unexpectedly).\n# That makes this test suite slow to run :-/.\n\nrun_make_test(q!\nall : pre1 .WAIT pre2\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# Ensure .WAIT doesn't add extra a dependency between its targets\n\nrun_make_test(undef, '-j10 pre2', \"pre2\\n\");\n\n# sv 63856.\n# .WAIT on the command line.\n\nrun_make_test(q!\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 pre1 .WAIT pre2', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# Multiple consecutive .WAITs.\n\nrun_make_test(q!\nall : pre1 .WAIT .WAIT .WAIT pre2\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# First and last prerequsites are .WAIT.\n\nrun_make_test(q!\nall : .WAIT pre1 .WAIT pre2 .WAIT\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# All prerequisites are .WAITs.\n\nrun_make_test(q!\nall : .WAIT .WAIT .WAIT\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\nrun_make_test(q!\nall:\n!,\n              '-j10 .WAIT', \"#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# Wait between the duplicate goals.\n\nrun_make_test(q!\nall: hello.tsk .WAIT hello.tsk\nhello.tsk:; $(info $@)\n!,\n              '-j10', \"hello.tsk\\n#MAKE#: Nothing to be done for 'all'.\\n\");\n\n# Wait between the duplicate command line goals.\n\nrun_make_test(q!\nhello.tsk:; $(info $@)\n!,\n              '-j10 hello.tsk .WAIT hello.tsk', \"hello.tsk\\n#MAKE#: 'hello.tsk' is up to date.\\n#MAKE#: 'hello.tsk' is up to date.\\n\");\n\n\n# Ensure .WAIT doesn't wait between all targets\n\nrun_make_test(q!\nall : pre1 .WAIT pre2 pre3\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out start-$@ file TWO wait THREE out end-$@\npre3: ; @#HELPER# -q wait TWO out $@ file THREE\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\nstart-pre2\\npre3\\nend-pre2\\n\");\n\nunlink(qw(TWO THREE));\n\n# Ensure .WAIT on the command line doesn't wait between all targets.\n\nrun_make_test(q!\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out start-$@ file TWO wait THREE out end-$@\npre3: ; @#HELPER# -q wait TWO out $@ file THREE\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 pre1 .WAIT pre2 pre3', \"start-pre1\\nend-pre1\\nstart-pre2\\npre3\\nend-pre2\\n\");\n\nunlink(qw(TWO THREE));\n\n# Ensure .WAIT waits for ALL targets on the left before ANY targets on the right\n\nrun_make_test(q!\nall : pre1 pre2 .WAIT post1 post2\npre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 sleep 1 out end-$@\npre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2\n\npost1: ; @#HELPER# -q wait POST2 out $@ file POST1\npost2: ; @#HELPER# -q file POST2 wait POST1 out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\npre2\\nend-pre1\\npost1\\npost2\\n\");\n\nunlink(qw(PRE1 PRE2 POST1 POST2));\n\n# Ensure .WAIT on the command line waits for ALL targets on the left before ANY\n# targets on the right.\n\nrun_make_test(q!\npre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 sleep 1 out end-$@\npre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2\n\npost1: ; @#HELPER# -q wait POST2 out $@ file POST1\npost2: ; @#HELPER# -q file POST2 wait POST1 out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 pre1 pre2 .WAIT post1 post2', \"start-pre1\\npre2\\nend-pre1\\npost1\\npost2\\n\");\n\nunlink(qw(PRE1 PRE2 POST1 POST2));\n\n# See if .WAIT takes effect between different lists of prereqs\n# In the current implementation, .WAIT waits only between two prerequisites\n# in a given target.  These same two targets might be run in a different\n# order if they appear as prerequisites of another target.  This is the way\n# other implementations of .WAIT work.  I personally think it's gross and\n# makes .WAIT just a toy when it comes to ordering, but it's much simpler\n# to implement than creating an actual edge in the DAG to represent .WAIT\n# and since that's what users expect, we'll do the same for now.\n\nrun_make_test(q!\nall : one two\none: pre1 .WAIT pre2\ntwo: pre2 pre1\npre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 out end-$@\npre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2\n\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\npre2\\nend-pre1\\n\");\nunlink(qw(PRE1 PRE2));\n\n# Check that .WAIT works with pattern rules\n\nrun_make_test(q!\nall: pre\np% : p%1 .WAIT p%2;\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# Check that .WAIT works with secondarily expanded rules\n\nrun_make_test(q!\n.SECONDEXPANSION:\nall: $$(pre)\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\npre3: ; @#HELPER# -q out $@\n\npre = .WAIT pre1 .WAIT pre2 | .WAIT pre3\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\npre3\\n\");\n\n# Verify NOTPARALLEL works\n\nrun_make_test(q!\nall : pre1 pre2\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n.NOTPARALLEL:\n!,\n              '-j10', \"start-pre1\\nend-pre1\\npre2\\n\");\n\nrun_make_test(q!\nall : p1 .WAIT np1\n\np1: pre1 pre2\npre1: ; @#HELPER# -q out start-$@ file PRE1 wait PRE2 out end-$@\npre2: ; @#HELPER# -q wait PRE1 out $@ file PRE2\n\n\nnp1: npre1 npre2\nnpre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\nnpre2: ; @#HELPER# -q out $@\n\n.NOTPARALLEL: np1\n!,\n              '-j10', \"start-pre1\\npre2\\nend-pre1\\nstart-npre1\\nend-npre1\\nnpre2\\n\");\nunlink(qw(PRE1 PRE2));\n\n# Ensure we don't shuffle if .WAIT is set\n\nrun_make_test(q!\nall : pre1 .WAIT pre2\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 --shuffle=reverse', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# Ensure we don't shuffle if .WAIT is set on the command line.\n\nrun_make_test(q!\npre1: ; @#HELPER# -q out start-$@ sleep 1 out end-$@\npre2: ; @#HELPER# -q out $@\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 --shuffle=reverse pre1 .WAIT pre2', \"start-pre1\\nend-pre1\\npre2\\n\");\n\n# Warn about invalid .WAIT definitions\n\nrun_make_test(q!\n.WAIT: foo\n.WAIT: ; echo oops\nall:;@:\n!,\n              '', \"#MAKEFILE#:2: .WAIT should not have prerequisites\\n#MAKEFILE#:3: .WAIT should not have commands\\n\");\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# Then run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nall: A B\nA ::; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB ::; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"A-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\n# Subtest 2.\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n\nrun_make_test(q!\nall: A .WAIT B\nA ::; @#HELPER# -q out $@-1 out $@-1-done\nA ::; @#HELPER# -q out $@-2 out $@-2-done\nA ::; @#HELPER# -q out $@-3 out $@-3-done\nB ::; @#HELPER# -q out $@-1 out $@-1-done\nB ::; @#HELPER# -q out $@-2 out $@-2-done\nB ::; @#HELPER# -q out $@-3 out $@-3-done\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"A-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\n# sv 63856.\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# Then run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n# The targets are specified on the command line.\n\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nA ::; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB ::; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 A B', \"A-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\n# Subtest 2.\n# sv 63856.\n# Wait for all double colon targets on the left, before building targets on the\n# right. The targets are specified on the command line.\n\nrun_make_test(q!\nA ::; @#HELPER# -q out $@-1 out $@-1-done\nA ::; @#HELPER# -q out $@-2 out $@-2-done\nA ::; @#HELPER# -q out $@-3 out $@-3-done\nB ::; @#HELPER# -q out $@-1 out $@-1-done\nB ::; @#HELPER# -q out $@-2 out $@-2-done\nB ::; @#HELPER# -q out $@-3 out $@-3-done\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 A .WAIT B', \"A-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Regular targets which have double colon targets as prerequisites.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# The targets are specified in the makefile.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nall: C .WAIT A B\nA ::; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB ::; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\nC: D E\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: C D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"D\\nE\\nE-done\\nD-done\\nA-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Regular targets which have double colon targets as prerequisites.\n# Subtest 2.\n# Run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n# The targets are specified in the makefile.\n#\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nall: C .WAIT A .WAIT B\nA ::; @#HELPER# -q out $@-1 out $@-1-done\nA ::; @#HELPER# -q out $@-2 out $@-2-done\nA ::; @#HELPER# -q out $@-3 out $@-3-done\nB ::; @#HELPER# -q out $@-1 out $@-1-done\nB ::; @#HELPER# -q out $@-2 out $@-2-done\nB ::; @#HELPER# -q out $@-3 out $@-3-done\n\nC: D E\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: C D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"D\\nE\\nE-done\\nD-done\\nA-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Regular targets which have double colon targets as prerequisites.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# The targets are specified on the command line.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nA ::; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB ::; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\nC: D E\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: C D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 C .WAIT A B', \"D\\nE\\nE-done\\nD-done\\nA-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Regular targets which have double colon targets as prerequisites.\n# Subtest 2.\n# Run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n# The targets are specified on the command line.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nA ::; @#HELPER# -q out $@-1 out $@-1-done\nA ::; @#HELPER# -q out $@-2 out $@-2-done\nA ::; @#HELPER# -q out $@-3 out $@-3-done\nB ::; @#HELPER# -q out $@-1 out $@-1-done\nB ::; @#HELPER# -q out $@-2 out $@-2-done\nB ::; @#HELPER# -q out $@-3 out $@-3-done\n\nC: D E\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: C D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 C .WAIT A .WAIT B', \"D\\nE\\nE-done\\nD-done\\nA-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Double colon targets have reqular targets as prerequisites.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# The targets are specified in the makefile.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nall: A B\nA :: D; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB :: E; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"D\\nE\\nE-done\\nD-done\\nA-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Double colon targets have reqular targets as prerequisites.\n# Subtest 2.\n# Run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n# The targets are specified in the makefile.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nall: A .WAIT B\nA :: D; @#HELPER# -q out $@-1 out $@-1-done\nA ::  ; @#HELPER# -q out $@-2 out $@-2-done\nA ::  ; @#HELPER# -q out $@-3 out $@-3-done\nB :: E; @#HELPER# -q out $@-1 out $@-1-done\nB ::  ; @#HELPER# -q out $@-2 out $@-2-done\nB ::  ; @#HELPER# -q out $@-3 out $@-3-done\n\nD:; @#HELPER# -q out D out D-done\nE:; @#HELPER# -q out E out E-done\n\n.PHONY: D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10', \"D\\nD-done\\nA-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nE\\nE-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Double colon targets have reqular targets as prerequisites.\n# Subtest 1. First run this test without .WAIT and observe and A recipes\n# interleave with B recipes.\n# The targets are specified on the command line.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nA :: D; @#HELPER# -q out A-1 file A-1-done wait B-1-done out A-1-done\nA ::; @#HELPER# -q out A-2 file A-2-done wait B-2-done out A-2-done\nA ::; @#HELPER# -q out A-3 file A-3-done wait B-3-done out A-3-done\nB :: E; @#HELPER# -q wait A-1-done out B-1 out B-1-done file B-1-done\nB ::; @#HELPER# -q wait A-2-done out B-2 out B-2-done file B-2-done\nB ::; @#HELPER# -q wait A-3-done out B-3 out B-3-done file B-3-done\n\nD:; @#HELPER# -q out D file D wait E-done out D-done\nE:; @#HELPER# -q wait D out E out E-done file E-done\n\n.PHONY: D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 A B', \"D\\nE\\nE-done\\nD-done\\nA-1\\nB-1\\nB-1-done\\nA-1-done\\nA-2\\nB-2\\nB-2-done\\nA-2-done\\nA-3\\nB-3\\nB-3-done\\nA-3-done\\n\");\n\n# Wait for all double colon targets on the left, before building targets on the\n# right.\n# Double colon targets have reqular targets as prerequisites.\n# Subtest 2.\n# Run the same test with .WAIT and observe that all A recipes get started\n# sequentially before the 1st B recipe gets started and then all B recipes get\n# started sequentially.\n# The targets are specified on the command line.\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\nrun_make_test(q!\nA :: D; @#HELPER# -q out $@-1 out $@-1-done\nA ::  ; @#HELPER# -q out $@-2 out $@-2-done\nA ::  ; @#HELPER# -q out $@-3 out $@-3-done\nB :: E; @#HELPER# -q out $@-1 out $@-1-done\nB ::  ; @#HELPER# -q out $@-2 out $@-2-done\nB ::  ; @#HELPER# -q out $@-3 out $@-3-done\n\nD:; @#HELPER# -q out D out D-done\nE:; @#HELPER# -q out E out E-done\n\n.PHONY: D E\n\n# This is just here so we don't fail with older versions of make\n.WAIT:\n!,\n              '-j10 A .WAIT B', \"D\\nD-done\\nA-1\\nA-1-done\\nA-2\\nA-2-done\\nA-3\\nA-3-done\\nE\\nE-done\\nB-1\\nB-1-done\\nB-2\\nB-2-done\\nB-3\\nB-3-done\\n\");\n\nunlink('D', 'D-done', 'E', 'E-done');\nunlink('A-1-done', 'A-2-done', 'A-3-done', 'B-1-done', 'B-2-done', 'B-3-done');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/targets/clean",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to delete a \\n\"\n              .\"file in the directory.  It tests to see if make will \\n\"\n              .\"NOT execute the command unless the rule is given in \\n\"\n              .\"the make command line.\";\n\n$example = \"EXAMPLE_FILE\";\n\nopen(MAKEFILE,\"> $makefile\");\nprint MAKEFILE qq!\nall: ; \\@echo This makefile did not clean the dir... good\nclean: ; $CMD_rmfile $example\n!;\nclose(MAKEFILE);\n\ntouch($example);\nrun_make_with_options($makefile,\"\",&get_logfile,0);\n\n$answer = \"This makefile did not clean the dir... good\\n\";\ncompare_output($answer,&get_logfile(1)) || error(\"abort\");\n\n\n$answer = \"$CMD_rmfile $example\\n\";\nrun_make_with_options($makefile,\"clean\",&get_logfile,0);\nif (-f $example) {\n  $test_passed = 0;\n}\ncompare_output($answer,&get_logfile(1)) || error(\"abort\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/test_template",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"<FILL IN SHORT DESCRIPTION HERE>\";\n$details = \"<FILL IN DETAILS OF HOW YOU TEST WHAT YOU SAY YOU ARE TESTING>\";\n\n# Run a make test.  See the documentation of run_make_test() in\n# run_make_tests.pl, but briefly the first argument is a string with the\n# contents of a makefile to be tested, the second is a string containing the\n# arguments to be passed to the make invocation, the third is a string\n# containing the expected output.  The fourth is the expected exit code for\n# make.  If not specified, it's assumed that the make program should succeed\n# (exit with 0).\n\nrun_make_test('Your test makefile goes here',\n              'Arguments to pass to make go here',\n              'Expected output from the invocation goes here');\n\n# There are various special tokens, options, etc.  See the full documentation\n# in run_make_tests.pl.\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/variables/CURDIR",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"This tests the CURDIR variable.\";\n\n$details = \"Echo CURDIR both with and without -C.  Also ensure overrides work.\";\n\n\n# TEST #1\n# -------\n\nrun_make_test(q!\nall: ; @echo $(CURDIR)\n!,\n              '', \"#PWD#\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/DEFAULT_GOAL",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the .DEFAULT_GOAL special variable.\";\n\n$details = \"\";\n\n\n# Test #1: basic logic.\n#\nrun_make_test('\n# Basics.\n#\nfoo: ; @:\n\nifneq ($(.DEFAULT_GOAL),foo)\n$(error )\nendif\n\n# Reset to empty.\n#\n.DEFAULT_GOAL :=\n\nbar: ; @:\n\nifneq ($(.DEFAULT_GOAL),bar)\n$(error )\nendif\n\n# Change to a different goal.\n#\n\n.DEFAULT_GOAL := baz\n\nbaz: ; @echo $@\n',\n'',\n'baz');\n\n\n# Test #2: unknown goal.\n#\nrun_make_test('\n.DEFAULT_GOAL = foo\n',\n'',\n\"#MAKE#: *** No rule to make target 'foo'.  Stop.\",\n512);\n\n\n# Test #3: more than one goal.\n#\nrun_make_test('\n.DEFAULT_GOAL := foo bar\n',\n'',\n'#MAKE#: *** .DEFAULT_GOAL contains more than one target.  Stop.',\n512);\n\n\n# Test #4: Savannah bug #12226.\n#\nrun_make_test('\ndefine rule\nfoo: ; @echo $$@\nendef\n\ndefine make-rule\n$(eval $(rule))\nendef\n\n$(call make-rule)\n\n',\n'',\n'foo');\n\n# TEST #5: .DEFAULT_GOAL containing just whitespace (Savannah bug #25697)\n\nrun_make_test('\nN =\n.DEFAULT_GOAL = $N  $N  # Just whitespace\n\nfoo: ; @echo \"boo\"\n',\n              '', \"#MAKE#: *** No targets.  Stop.\\n\", 512);\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/variables/EXTRA_PREREQS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the .EXTRA_PREREQS special variable.\";\n$details = \"\";\n\n# Simple global .EXTRA_PREREQS and automatic variable settings\nrun_make_test('\n.EXTRA_PREREQS = tick tack\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS}/$@/$</$^/$?/$+/$|/$*/\ntick tack: ; @echo $@\n',\n              '', \"tick\\ntack\\ntick tack/all///////\\n\");\n\n# Global .EXTRA_PREREQS and pattern rules\nrun_make_test('\n.EXTRA_PREREQS = tick tack\na%: ; @echo ${.EXTRA_PREREQS}/$@/$</$^/$?/$+/$|/$*/\ntick tack: ; @echo $@\n',\n              'all', \"tick\\ntack\\ntick tack/all//////ll/\\n\");\n\n# Simple target-specific .EXTRA_PREREQS and automatic variable settings\nrun_make_test('\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS}/$@/$</$^/$?/$+/$|/$*/\nall: .EXTRA_PREREQS = tick tack\ntick tack: ; @echo $@\n',\n              '', \"tick\\ntack\\ntick tack/all///////\\n\");\n\n# Simple pattern-specific .EXTRA_PREREQS and automatic variable settings\n# This is not currently supported :-/\nif (0) {\n    run_make_test('\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS}/$@/$</$^/$?/$+/$|/$*/\na%: .EXTRA_PREREQS = tick tack\ntick tack: ; @echo $@\n',\n                  '', \"tick\\ntack\\ntick tack/all///////\\n\");\n}\n\ntouch('hi');\n\n# Basic test target specific .EXTRA_PREREQS:\nrun_make_test('\nDEPENDENCY_ONLY_PREREQUISITES = ho hey\nOTHER_PREREQUISITES := foo bar baz\ntarget: .EXTRA_PREREQS := hi ${DEPENDENCY_ONLY_PREREQUISITES}\ntarget: ${OTHER_PREREQUISITES} ; @echo ${.EXTRA_PREREQS} $^\n.PHONY: target ${DEPENDENCY_ONLY_PREREQUISITES} ${OTHER_PREREQUISITES}\n${DEPENDENCY_ONLY_PREREQUISITES} ${OTHER_PREREQUISITES}: ; @echo $@\n',\n              '', \"foo\\nbar\\nbaz\\nho\\nhey\\nhi ho hey foo bar baz\\n\");\n\n# Test target specific .EXTRA_PREREQS and pattern rules:\nrun_make_test('\nall: target.dst\nDEPENDENCY_ONLY_PREREQUISITES = ho hey\ntarget.dst: .EXTRA_PREREQS := hi ${DEPENDENCY_ONLY_PREREQUISITES}\n%.dst: %.src ; @echo ${.EXTRA_PREREQS} $^\n.PHONY: ${DEPENDENCY_ONLY_PREREQUISITES} target.src\n${DEPENDENCY_ONLY_PREREQUISITES} target.src: ; @echo $@\n',\n              '', \"target.src\\nho\\nhey\\nhi ho hey target.src\\n\");\n\n# Test that global .EXTRA_PREREQS are built first:\nrun_make_test('\n.EXTRA_PREREQS = hi ho hey\nOTHER_PREREQUISITES := foo bar baz\ntarget: ${OTHER_PREREQUISITES} ; @echo ${.EXTRA_PREREQS} $^\n.PHONY: target ${.EXTRA_PREREQS} ${OTHER_PREREQUISITES}\n${.EXTRA_PREREQS} ${OTHER_PREREQUISITES}: ; @echo $@\n',\n              '', \"hi\\nho\\nhey\\nfoo\\nbar\\nbaz\\nhi ho hey foo bar baz\\n\");\n\n# Test that target specific .EXTRA_PREREQS override global .EXTRA_PREREQS:\nrun_make_test('\n.EXTRA_PREREQS = tick tack\nDEPENDENCY_ONLY_PREREQUISITES = ho hey\nOTHER_PREREQUISITES := foo bar baz\ntarget: .EXTRA_PREREQS := hi ${DEPENDENCY_ONLY_PREREQUISITES}\ntarget: ${OTHER_PREREQUISITES} ; @echo ${.EXTRA_PREREQS} $^\n.PHONY: target ${DEPENDENCY_ONLY_PREREQUISITES} ${OTHER_PREREQUISITES} ${.EXTRA_PREREQS}\n${DEPENDENCY_ONLY_PREREQUISITES} ${OTHER_PREREQUISITES} ${.EXTRA_PREREQS}: ; @echo $@\n',\n              '', \"tick\\ntack\\nfoo\\nbar\\nbaz\\nho\\nhey\\nhi ho hey foo bar baz\\n\");\n\n# Cleanup:\nunlink('hi');\n\n# Test error reporting of global .EXTRA_PREREQS:\nrun_make_test('\n.EXTRA_PREREQS = tick tack\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS} $^\n',\n              '', \"#MAKE#: *** No rule to make target 'tick', needed by 'all'.  Stop.\", 512);\n\n# Test error reporting of global .EXTRA_PREREQS and keep-going:\nrun_make_test('\n.EXTRA_PREREQS = tick tack\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS} $^\n',\n              '-k', \"#MAKE#: *** No rule to make target 'tick', needed by 'all'.\\n#MAKE#: *** No rule to make target 'tack', needed by 'all'.\\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n\n# Test error reporting of target specific .EXTRA_PREREQS and keep-going:\nrun_make_test('\nall: .EXTRA_PREREQS = tick tack\n.PHONY: all\nall: ; @echo ${.EXTRA_PREREQS} $^\n',\n              '-k',\n              \"#MAKE#: *** No rule to make target 'tick', needed by 'all'.\n#MAKE#: *** No rule to make target 'tack', needed by 'all'.\n#MAKE#: Target 'all' not remade because of errors.\\n\", 512);\n\n# Test wildcard\n\ntouch('tick', 'tack');\n\nrun_make_test('\n.EXTRA_PREREQS = *ck\n.PHONY: all tick tack\nall: ; @echo ${.EXTRA_PREREQS} $^\ntick tack: ; @echo $@\n',\n              '', \"tack\\ntick\\ntack tick\\n\");\n\nrun_make_test('\n.PHONY: all tick tack\nall: ; @echo ${.EXTRA_PREREQS} $^\nall: .EXTRA_PREREQS = *ck\ntick tack: ; @echo $@\n',\n              '', \"tack\\ntick\\ntack tick\\n\");\n\nrun_make_test('\n.PHONY: tick tack\na%: ; @echo ${.EXTRA_PREREQS} $^\n.EXTRA_PREREQS = *ck\ntick tack: ; @echo $@\n',\n              'all', \"tack\\ntick\\ntack tick\\n\");\n\n# SV 65006. Second expansion of global .EXTRA_PREQREQS.\nrun_make_test('\n.SECONDEXPANSION:\nextradep:=tick tack\n.EXTRA_PREREQS=$$(extradep)\n%.x:; @echo $@\n',\n              'hello.x', \"hello.x\\n\");\n\nunlink('tick', 'tack');\n\n# SV 65006. Second expansion of a target-specific .EXTRA_PREQREQS.\nrun_make_test('\n.SECONDEXPANSION:\nall: hello.x;\nextradep=tick tack\nhello.x: .EXTRA_PREREQS=$$(extradep)\n%.x:; @echo $@\ntick tack:; @echo $@\n',\n              '', \"tick\\ntack\\nhello.x\\n\");\n\n# SV 65006. Second expansion of a target-specific .EXTRA_PREQREQS.\n# The value of .EXTRA_PREQREQS contains automatic variables.\nrun_make_test('\n.SECONDEXPANSION:\nall: hello.x world.x\nhello.x world.x: .EXTRA_PREREQS=$$@.d\n%.x:; @echo $@\n%.d:; @echo $@\n',\n              '', \"hello.x.d\\nhello.x\\nworld.x.d\\nworld.x\\n\");\n\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/variables/GNUMAKEFLAGS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test proper behavior of GNUMAKEFLAGS\";\n\n# Accept flags from GNUMAKEFLAGS as well as MAKEFLAGS\n# Results always go in MAKEFLAGS\n\n$ENV{'GNUMAKEFLAGS'} = '-e -r -R';\n\nrun_make_test(q!\nall: ; @echo $(MAKEFLAGS)\n!,\n              '', 'erR');\n\n# Long arguments mean everything is prefixed with \"-\"\n\n$ENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace';\n\nrun_make_test(q!\nall: ; @echo $(MAKEFLAGS)\n!,\n              '', \"#MAKEFILE#:2: update target 'all' due to: target does not exist\necho erR --trace --no-print-directory\nerR --trace --no-print-directory\");\n\n# Verify that re-exec / recursion doesn't duplicate flags from GNUMAKEFLAGS\n\nunlink('x.mk');\n\n$ENV{GNUMAKEFLAGS} = '-Itst/bad';\n\nrun_make_test(q!\nrecurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all\nall: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS\n-include x.mk\nx.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@\n!,\n              \"\", \"x.mk\\nMAKEFLAGS = -Itst/bad\\nGNUMAKEFLAGS =\\nrecurse\\nMAKEFLAGS = -Itst/bad\\nGNUMAKEFLAGS =\\n#MAKE#[1]: Entering directory '#PWD#'\\nall\\nMAKEFLAGS = -Itst/bad\\nGNUMAKEFLAGS =\\n#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\nunlink('x.mk');\n\n# Ensure that we don't add GNUMAKEFLAGS to the environment if it's not there\nrun_make_test(q!\nall: ; @#HELPER# env GNUMAKEFLAGS\n!,\n              '', 'GNUMAKEFLAGS=<unset>');\n\n$ENV{GNUMAKEFLAGS} = '-Itst/bad';\nrun_make_test(q!\nall: ; @#HELPER# env GNUMAKEFLAGS\n!,\n              '', 'GNUMAKEFLAGS=');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/INCLUDE_DIRS",
    "content": "#                                                                    -*-perl-*-\n$description = \"Test the .INCLUDE_DIRS special variable.\";\n\n$details = \"\";\n\nuse Cwd;\n\n$dir = cwd;\n$dir =~ s,.*/([^/]+)$,../$1,;\n\nif (-d '/usr/include') {\n  # Test #1: The content of .INCLUDE_DIRS depends on the platform for which\n  #          make was built. What we know for sure is that it shouldn't be\n  #          empty.\n  #\n  run_make_test('\nifeq ($(.INCLUDE_DIRS),)\n$(warning .INCLUDE_DIRS is empty)\nendif\n\n.PHONY: all\nall:;@:\n',\n                '', '');\n}\n\n# Test #2: Make sure -I paths end up in .INCLUDE_DIRS.\n#\nrun_make_test('\nifeq ($(dir),)\n$(warning dir is empty)\nendif\n\nifeq ($(filter $(dir),$(.INCLUDE_DIRS)),)\n$(warning .INCLUDE_DIRS does not contain $(dir): $(.INCLUDE_DIRS))\nendif\n\n.PHONY: all\nall:;@:\n',\n              \"-I$dir dir=$dir\", '');\n\n# Find the default .INCLUDE_DIRS\ncreate_file('defaultdirs.mk', \"\\$(info \\$(.INCLUDE_DIRS))\\nall:;\\@:\\n\");\nmy $cmd = subst_make_string(\"#MAKEPATH# -f defaultdirs.mk\");\nmy @dirs = `$cmd`;\nmy $dirs = $dirs[0];\n$dirs =~ s/\\r?\\n//g;\nunlink('defaultdirs.mk');\n\nrun_make_test(\"\nifneq (\\$(.INCLUDE_DIRS),$dirs)\n\\$(warning Mismatched \\$(.INCLUDE_DIRS) != $dirs)\nendif\nall:;\\@:\n\",\n              '', '');\n\n# Verify that -I- disables content from .INCLUDE_DIRS\n\nrun_make_test(q/\nifneq ($(.INCLUDE_DIRS),)\n$(warning Mismatched $(.INCLUDE_DIRS) != )\nendif\nall:;@:\n/,\n              '-I-', '');\n\n# Prefix -I dirs to the front\nmkdir('somedir', 0777);\n\nmy $xdirs = $dirs ? \" $dirs\" : '';\nrun_make_test(\"\nifneq (\\$(.INCLUDE_DIRS),somedir$xdirs)\n\\$(warning Mismatched '\\$(.INCLUDE_DIRS)' != 'somedir$xdirs')\nendif\nall:;\\@:\n\",\n              '-I somedir', '');\n\n# Verify .INCLUDE_DIRS contains files after -I-\n\nrun_make_test(q/\nifneq ($(.INCLUDE_DIRS),somedir)\n$(warning Mismatched $(.INCLUDE_DIRS) != somedir)\nendif\nall:;@:\n/,\n              '-I - -I somedir', '');\n\nrmdir('somedir');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/variables/LIBPATTERNS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test .LIBPATTERNS special variable.\";\n\n$details = \"\";\n\n# TEST 0: basics\n\ntouch('mtest_foo.a');\n\nrun_make_test('\n.LIBPATTERNS = mtest_%.a\nall: -lfoo ; @echo \"build $@ from $<\"\n',\n              '', \"build all from mtest_foo.a\\n\");\n\n# TEST 1: Handle elements that are not patterns.\n\nrun_make_test('\n.LIBPATTERNS = mtest_foo.a mtest_%.a\nall: -lfoo ; @echo \"build $@ from $<\"\n',\n              '', \"#MAKE#: .LIBPATTERNS element 'mtest_foo.a' is not a pattern\nbuild all from mtest_foo.a\\n\");\n\n# TEST 2: target-specific override\n\n# Uncomment this when we add support, see Savannah bug #25703\n# run_make_test('\n# .LIBPATTERNS = mbad_%.a\n# all: .LIBPATTERNS += mtest_%.a\n# all: -lfoo ; @echo \"build $@ from $<\"\n# ',\n#               '', \"build all from mtest_foo.a\\n\");\n\nunlink('mtest_foo.a');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MAKE",
    "content": "#\t\t\t\t\t\t\t\t     -*-perl-*-\n\n$description = \"Test proper behavior of the MAKE variable\";\n\n$details = \"DETAILS\";\n\nrun_make_test(q!\nTMP  := $(MAKE)\nMAKE := $(subst X=$(X),,$(MAKE))\nall:\n\t@echo $(TMP)\n\t$(MAKE) -f #MAKEFILE# foo\n\nfoo:\n\t@echo $(MAKE)\n!,\n              '',\n              \"#MAKEPATH#\\n#MAKEPATH# -f #MAKEFILE# foo\\n\"\n              . \"#MAKE#[1]: Entering directory '#PWD#'\\n\"\n              . \"#MAKEPATH#\\n#MAKE#[1]: Leaving directory '#PWD#'\\n\");\n\nrmfiles(\"foo\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MAKECMDGOALS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the MAKECMDGOALS variable.\";\n\n$details = \"\\\nWe construct a makefile with various targets, all of which print out\n\\$(MAKECMDGOALS), then call it different ways.\";\n\nopen(MAKEFILE,\"> $makefile\");\nprint MAKEFILE \"\\\n.DEFAULT all:\n\t\\@echo \\$(MAKECMDGOALS)\n\";\nclose(MAKEFILE);\n\n# TEST #1\n\n&run_make_with_options($makefile,\n                       \"\",\n                       &get_logfile,\n                       0);\n$answer = \"\\n\";\n&compare_output($answer,&get_logfile(1));\n\n# TEST #2\n\n&run_make_with_options($makefile,\n                       \"all\",\n                       &get_logfile,\n                       0);\n$answer = \"all\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# TEST #3\n\n&run_make_with_options($makefile,\n                       \"foo bar baz yaz\",\n                       &get_logfile,\n                       0);\n$answer = \"foo bar baz yaz\\nfoo bar baz yaz\\nfoo bar baz yaz\\nfoo bar baz yaz\\n\";\n&compare_output($answer,&get_logfile(1));\n\n\n# This tells the test driver that the perl test script executed properly.\n1;\n\n\n\n\n\n\n"
  },
  {
    "path": "tests/scripts/variables/MAKEFILES",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the MAKEFILES variable.\";\n\n$makefile2 = &get_tmpfile;\n$makefile3 = &get_tmpfile;\n\nopen(MAKEFILE,\"> $makefile2\");\nprint MAKEFILE <<EOF;\nM2 = m2\nNDEF: ; \\@echo RULE FROM MAKEFILE 2\nEOF\nclose(MAKEFILE);\n\n\nopen(MAKEFILE,\"> $makefile3\");\nprint MAKEFILE <<EOF;\nM3 = m3\nNDEF3: ; \\@echo RULE FROM MAKEFILE 3\nEOF\nclose(MAKEFILE);\n\nrun_make_test(q!\nall: ; @echo DEFAULT RULE: M2=$(M2) M3=$(M3)\n!,\n              [\"MAKEFILES=$makefile2 $makefile3\"], \"DEFAULT RULE: M2=m2 M3=m3\\n\");\n\n# TEST 2: Verify that included makefiles don't set the default goal.\n# See Savannah bug #13401.\n\ncreate_file('xx-inc.mk', '\ninclude_goal: ; @echo $@\ninclude xx-ind.mk\n');\n\ncreate_file('xx-ind.mk', '\nindirect_goal: ; @echo $@\n');\n\nrun_make_test(q!\ntop: ; @echo $@\n!,\n              'MAKEFILES=xx-inc.mk', \"top\\n\");\n\nunlink(qw(xx-inc.mk xx-ind.mk));\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MAKEFLAGS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test proper behavior of MAKEFLAGS\";\n\n$details = \"DETAILS\";\n\n# Normal flags aren't prefixed with \"-\"\nrun_make_test(q!\nall: ; @echo /$(MAKEFLAGS)/\n!,\n              '-e -r -R', '/erR/');\n\n# Long arguments mean everything is prefixed with \"-\"\nrun_make_test(q!\nall: ; @echo /$(MAKEFLAGS)/\n!,\n              '--no-print-directory -e -r -R --trace', \"#MAKEFILE#:2: update target 'all' due to: target does not exist\necho /erR --trace --no-print-directory/\n/erR --trace --no-print-directory/\");\n\n\n# Recursive invocations of make should accumulate MAKEFLAGS values.\n# Savannah bug #2216\nrun_make_test(q!\nMSG = Fails\n.RECIPEPREFIX = >\nall:\n> @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'\n> @MSG=Works $(MAKE) -e -f #MAKEFILE# jump\njump:\n> @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'\n> @$(MAKE) -f #MAKEFILE# print\nprint:\n> @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'\n.PHONY: all jump print\n!,\n                  '--no-print-directory',\n                  'all: MAKEFLAGS= --no-print-directory\njump Works: MAKEFLAGS=e --no-print-directory\nprint Works: MAKEFLAGS=e --no-print-directory');\n\n# Ensure MAKEFLAGS updates are handled immediately rather than later\n\nmkdir('foo', 0777);\nmkdir('bar', 0777);\n\nrun_make_test(q!\n$(info MAKEFLAGS=$(MAKEFLAGS))\n$(info INCLUDE_DIRS=$(.INCLUDE_DIRS))\nMAKEFLAGS += -Ibar\n$(info MAKEFLAGS=$(MAKEFLAGS))\n$(info INCLUDE_DIRS=$(.INCLUDE_DIRS))\n.PHONY: all\nall: ; @echo 'MAKEFLAGS=$(MAKEFLAGS)' \"\\$$MAKEFLAGS=$$MAKEFLAGS\"\n!,\n              '-I- -Ifoo', 'MAKEFLAGS= -I- -Ifoo\nINCLUDE_DIRS=foo\nMAKEFLAGS= -I- -Ifoo -Ibar\nINCLUDE_DIRS=foo bar\nMAKEFLAGS= -I- -Ifoo -Ibar $MAKEFLAGS= -I- -Ifoo -Ibar');\n\nrmdir('foo');\nrmdir('bar');\n\n# Test that command line switches are all present in MAKEFLAGS.\n# sv 62514.\nmy @opts;\nmy @flavors;\n\n# Simple flags.\n@opts = ('i', 'k', 'n', 'q', 'r', 's', 'w', 'd');\nexists $FEATURES{'check-symlink'} and push @opts, 'L';\n@flavors = ('=', ':=', ':::=', '+=-');\n\nfor my $fl (@flavors) {\nfor my $opt (@opts) {\n  run_make_test(\"\nMAKEFLAGS${fl}B\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\", \"-$opt\", \"/makeflags='B$opt'/\");\n}\n}\n\n# Strawberry Perl's exec()--or something!--appears to replace all /tmp with the\n# user's %TEMP% value so we can't use that for -I testing.  Make a directory.\n\nmkdir('localtmp', 0777);\n\n# Switches which carry arguments.\n@opts = (' -Ilocaltmp', ' -Onone', ' --debug=b', ' -l2.5');\nfor my $fl (@flavors) {\nfor my $opt (@opts) {\n  run_make_test(\"\nMAKEFLAGS${fl}B\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\", \"$opt\", \"/makeflags='B$opt'/\");\n}\n}\n\n# Long options which take no arguments.\n# sv 62514.\n@opts = (' --no-print-directory', ' --warn=undefined-var', ' --trace');\nfor my $fl (@flavors) {\nfor my $opt (@opts) {\nrun_make_test(\"\nMAKEFLAGS${fl}B\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\", \"$opt\", \"/makeflags='B$opt'/\");\n}\n}\n\n# Test that make filters out duplicates.\n# Each option is specified in the makefile, env and on the command line.\n@opts = (' -Ilocaltmp', ' -Onone', ' --debug=b', ' -l2.5');\nfor my $fl (@flavors) {\nfor my $opt (@opts) {\n$ENV{'MAKEFLAGS'} = $opt;\n  run_make_test(\"\nMAKEFLAGS${fl}B $opt\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\", \"$opt\", \"/makeflags='B$opt'/\");\n}\n}\n\n# Test that make filters out duplicates.\n# Each option is specified in the makefile, env and on the command line.\n# decode_switches reallocates when the number of parameters in sl->list exceeds 5.\n# This test exercises the realloc branch.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2';\nrun_make_test(\"\nMAKEFLAGS${fl}B -I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6 -I2 -I2\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\",\n'-I1 -Onone --debug=b -l2.5 -I2 -I3 -I4 -I5 -I6',\n\"/makeflags='B -I1 -I2 -I3 -I4 -I5 -I6 -l2.5 -Onone --debug=b'/\");\n}\n\n# A mix of multiple flags from env, the makefile and command line.\n# Skip -L since it's not available everywhere\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var --trace';\nrun_make_test(\"\nMAKEFLAGS${fl}iknqrswd -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5\nall:; \\$(info makeflags='\\$(MAKEFLAGS)')\n\",\n'-Onone -l2.5 -l2.5 -Onone -Ilocaltmp -iknqrswd -i -n -s -k -Ilocaltmp',\n\"/makeflags='Bdiknqrsw -Ilocaltmp -l2.5 -Onone --trace --warn=undefined-var'/\");\n}\n\n# Verify MAKEFLAGS are all available to shell function at parse time.\nfor my $fl (@flavors) {\nmy $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn=undefined-var';\n$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var';\nrun_make_test(\"\nMAKEFLAGS${fl}iknqrsw -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5 --no-print-directory\n\\$(info at parse time '\\$(MAKEFLAGS)')\nXX := \\$(shell echo \\\"\\$\\$MAKEFLAGS\\\")\nall:; \\$(info at build time makeflags='\\$(XX)')\n\",\n'-Onone -l2.5 -l2.5 -Onone -Ilocaltmp -iknqrs -i -n -s -k -Ilocaltmp',\n\"at parse time '$answer'\nat build time makeflags='$answer'\");\n}\n\n# Verify MAKEFLAGS and command line definitions are all available to shell function at parse time.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var';\nmy $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn=undefined-var -- hello=world';\nrun_make_test(\"\nMAKEFLAGS${fl}iknqrsw -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5 --no-print-directory\n\\$(info at parse time '\\$(MAKEFLAGS)')\nXX := \\$(shell echo \\\"\\$\\$MAKEFLAGS\\\")\nall:; \\$(info at build time makeflags='\\$(XX)')\n\",\n'-Onone -l2.5 -l2.5 -Onone -Ilocaltmp -iknqrs -i -n -s -k -Ilocaltmp hello=world',\n\"at parse time '$answer'\nat build time makeflags='$answer'\");\n}\n\n# Verify that command line arguments are included in MAKEFLAGS\nrun_make_test(q!\nall: ; @echo $(MAKEFLAGS)\n!,\n              '-e FOO=bar -r -R', 'erR -- FOO=bar');\n\n# Long arguments mean everything is prefixed with \"-\"\nrun_make_test(q!\nall: ; @echo /$(MAKEFLAGS)/\n!,\n              '--no-print-directory -e -r -R --trace FOO=bar',\n              \"#MAKEFILE#:2: update target 'all' due to: target does not exist\necho /erR --trace --no-print-directory -- FOO=bar/\n/erR --trace --no-print-directory -- FOO=bar/\");\n\n\n# sv 63347.\n# Verify that command line arguments are included in MAKEFLAGS\n# when makefiles are parsed.\nmy $answer = 'erR -- hello:=world FOO=bar';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-e FOO=bar -r -R hello:=world',\n\"$answer\n$answer\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63347.\n# Same as above, with makefile setting the value of the same variables as\n# defined on the cli.\n$answer = 'erR -- hello:=world FOO=bar';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nFOO=moon\nhello:=moon\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-e FOO=bar -r -R hello:=world',\n\"$answer\n$answer\n$answer\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63347.\n# Same as above, with makefile overriding the value of cli definition.\n$answer = 'erR -- hello:=world FOO=bar';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\noverride FOO=moon\noverride hello:=moon\nexport hello\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-e FOO=bar -r -R hello:=world',\n\"$answer\n$answer\n$answer\n#MAKE#: 'all' is up to date.\\n\");\n\n# Same as above, and makefile overrides the value of cli definition.\n# resets MAKEOVERRIDES.\n$answer = 'rR -- hello:=world FOO=bar';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\noverride FOO=moon\noverride hello:=moon\nexport hello\n$(info $(MAKEFLAGS))\nMAKEOVERRIDES=\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, 'FOO=bar -r -R hello:=world',\n\"$answer\n$answer\nrR -- \\nrR\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63347.\n# MAKEFLAGS set is env and makefile sets MAKEFLAGS and there is a command\n# line definition.\n$answer = ' -- bye=moon hello=world';\n$ENV{'MAKEFLAGS'} = 'hello=world';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, 'bye=moon',\n\" -- bye=moon hello=world\n -- bye=moon hello=world\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63347.\n# Conditional assignment and MAKEFLAGS.\n$answer = 'B -- bye=moon hello=world';\n$ENV{'MAKEFLAGS'} = 'hello=world';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nMAKEFLAGS?=-k\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-B bye=moon',\n\"$answer\n$answer\n$answer\n#MAKE#: 'all' is up to date.\\n\");\n\n# sv 63347.\n# MAKEFLAGS set is env and makefile sets MAKEFLAGS and there is a command\n# line definition.\nfor my $fl (@flavors) {\nmy $answer = ' -- bye=moon hello=world';\n$ENV{'MAKEFLAGS'} = 'hello=world';\nrun_make_test(\"\n\\$(info \\$(MAKEFLAGS))\nMAKEFLAGS${fl}R\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", 'bye=moon',\n\"$answer\nrR$answer\nrR$answer\n#MAKE#: 'all' is up to date.\\n\");\n}\n\n# sv 63347.\n# Test changes introduced by makefiles to MAKEFLAGS.\nfor my $fl (@flavors) {\nmy $answer = 'rR --no-print-directory -- hello:=world FOO=bar';\nrun_make_test(q!\nMAKEFLAGS+=--no-print-directory\n$(info $(MAKEFLAGS))\nMAKEFLAGS+=-k\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, 'FOO=bar -r -R hello:=world',\n\"$answer\nk$answer\nk$answer\n#MAKE#: 'all' is up to date.\\n\");\n}\n\n# sv 63347.\n# Test changes introduced by makefiles to MAKEFLAGS.\n# Same as above, but with -e.\nfor my $fl (@flavors) {\nmy $answer = 'erR -- hello:=world FOO=bar';\nrun_make_test(q!\nMAKEFLAGS+=--no-print-directory\n$(info $(MAKEFLAGS))\nMAKEFLAGS+=-k\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-e FOO=bar -r -R hello:=world',\n\"$answer\n$answer\n$answer\n#MAKE#: 'all' is up to date.\\n\");\n}\n\nmkdir('bye', 0777);\n\ncreate_file('bye/makefile',\n'hello=moon\nall:; $(info $(hello))');\n\n# sv 63347.\n# Test that a cli definition takes precedence over a definition set in\n# submake.\nrun_make_test(q!\nv:=$(shell $(MAKE) -C bye --no-print-directory)\nall: ; $(info $(v))\n!, 'hello=world', \"world #MAKE#[1]: 'all' is up to date.\\n#MAKE#: 'all' is up to date.\");\n\n# Same as above with the shell assignment operator.\nrun_make_test(q!\nv \\!= $(MAKE) -C bye --no-print-directory\nall: ; $(info $(v))\n!, 'hello=world', \"world #MAKE#[1]: 'all' is up to date.\\n#MAKE#: 'all' is up to date.\");\n\nunlink('bye/makefile');\nrmdir('bye');\n\n# sv 63347\n# Invalid command line variable definition.\nrun_make_test(q!\nall:; $(info $(hello))\n!, 'hello=\\'$(world\\'', \"#MAKEFILE#:2: *** unterminated variable reference.  Stop.\\n\", 512);\n\n# sv 63347\n# An unused invalid command line variable definition is ignored.\nrun_make_test(q!\nall:; $(info good)\n!, 'hello=\\'$(world\\'', \"good\\n#MAKE#: 'all' is up to date.\\n\");\n\n\n\n# sv 63537\n# Certain switches can be flipped on and off.\n# -k/-S, -w/--no-print-directory and -s/--no-silent.\n# Test the following aspects of behavior of these switches\n# 1. A switch can be enabled or disabled in makefile.\n# 2. A switch can be enabled or disabled in env.\n# 3. A switch can be enabled or disabled on the command line.\n# 4. Command line beats makefile.\n# 5. Env beats makefile.\n# 6. Command line beats env.\n# 7. MAKEFLAGS contains each specified switch at parse and build time.\n# 8. If contradicting switches are specified in multiple origins, MAKEFLAGS\n#    contains the winning switch at parse and build time.\n# 9. MAKEFLAGS does not contain the beaten switch.\n\n@flavors = ('=', ':=', ':::=', '+=');\n\n# sv 63537\n# -w vs --no-print-directory\n\n# -w on the command line.\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-w',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKE#: 'all' is up to date.\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\n# -w in the env.\n$ENV{'MAKEFLAGS'} = '-w';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKE#: 'all' is up to date.\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\n# -w in env, --no-print-directory on the command line.\n$ENV{'MAKEFLAGS'} = '-w';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '--no-print-directory',\n\" --no-print-directory\n --no-print-directory\n#MAKE#: 'all' is up to date.\\n\");\n\n# --no-print-directory in env, -w on the command line.\n$ENV{'MAKEFLAGS'} = '--no-print-directory';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-w',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKE#: 'all' is up to date.\n#MAKE#: Leaving directory '#PWD#'\\n\");\n\ndelete $ENV{'MAKEFLAGS'};\n\n# -w in makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-w\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKE#: 'all' is up to date.\n#MAKE#: Leaving directory '#PWD#'\\n\");\n}\n\n# sv 63537\n# -w in makefile, --no-print-directory on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-w\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '--no-print-directory',\n\" --no-print-directory\n --no-print-directory\n#MAKE#: 'all' is up to date.\\n\");\n}\n\nmkdir('lib2', 0777);\ncreate_file('lib2/makefile', 'all:; $(info $(MAKEFLAGS))');\n\n# sv 63537\n# Default, no -w or --no-print-directory is specified.\nrun_make_test(q!\nall:; $(MAKE) -C lib2\n!, '',\n\"#MAKEPATH# -C lib2\n#MAKE#[1]: Entering directory '#PWD#/lib2'\n\n#MAKE#[1]: 'all' is up to date.\n#MAKE#[1]: Leaving directory '#PWD#/lib2'\\n\");\n\n# sv 63537\n# --no-print-directory in makefile, -w on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--no-print-directory\n\\$(info \\$(MAKEFLAGS))\nall:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t \\$(MAKE) -C lib2\n\", '-w',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKEPATH# -C lib2\n#MAKE#[1]: Entering directory '#PWD#/lib2'\nw\n#MAKE#[1]: 'all' is up to date.\n#MAKE#[1]: Leaving directory '#PWD#/lib2'\n#MAKE#: Leaving directory '#PWD#'\\n\");\n}\n\n# sv 63537\n# --no-print-directory in makefile, -w in the env.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '-w';\nrun_make_test(\"\nMAKEFLAGS${fl}--no-print-directory\n\\$(info \\$(MAKEFLAGS))\nall:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t \\$(MAKE) -C lib2\n\", '',\n\"#MAKE#: Entering directory '#PWD#'\nw\nw\n#MAKEPATH# -C lib2\n#MAKE#[1]: Entering directory '#PWD#/lib2'\nw\n#MAKE#[1]: 'all' is up to date.\n#MAKE#[1]: Leaving directory '#PWD#/lib2'\n#MAKE#: Leaving directory '#PWD#'\\n\");\n}\n\nunlink('lib2/makefile');\nrmdir('lib2');\n\n# sv 63537\n# -k vs -S.\n\n\n# -S in env.\n$ENV{'MAKEFLAGS'} = '-S';\nrun_make_test(q!\n.RECIPEPREFIX := >\n$(info $(MAKEFLAGS))\nall: one two\none:\n> $(info $(MAKEFLAGS))\n> #HELPER# -q fail 1\ntwo:; $(info $@)\n!, '',\n\"S\nS\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\", 512);\n\n# -S in env, -k on the command line.\n$ENV{'MAKEFLAGS'} = '-S';\nrun_make_test(q!\n.RECIPEPREFIX := >\n$(info $(MAKEFLAGS))\nall: one two\none:\n> $(info $(MAKEFLAGS))\n> #HELPER# -q fail 1\ntwo:; $(info $@)\n!, '-k',\n\"k\nk\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\ntwo\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n\n# -k in env.\n$ENV{'MAKEFLAGS'} = '-k';\nrun_make_test(q!\n.RECIPEPREFIX := >\n$(info $(MAKEFLAGS))\nall: one two\none:\n> $(info $(MAKEFLAGS))\n> #HELPER# -q fail 1\ntwo:; $(info $@)\n!, '',\n\"k\nk\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\ntwo\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n\n# -k in env, -S on the command line.\n$ENV{'MAKEFLAGS'} = '-k';\nrun_make_test(q!\n.RECIPEPREFIX := >\n$(info $(MAKEFLAGS))\nall: one two\none:\n> $(info $(MAKEFLAGS))\n> #HELPER# -q fail 1\ntwo:; $(info $@)\n!, '-S',\n\"S\nS\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\", 512);\n\ndelete $ENV{'MAKEFLAGS'};\n\n# -k in makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-k\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '',\n\"k\nk\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\ntwo\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n}\n\n# sv 63537\n# -k in makefile and -S on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-k\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '-S',\n\"S\nS\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\", 512);\n}\n\n# sv 63537\n# -k in makefile and -S in the env.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '-S';\nrun_make_test(\"\nMAKEFLAGS${fl}-k\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '',\n\"S\nS\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\", 512);\n}\n\ndelete $ENV{'MAKEFLAGS'};\n\n# sv 63537\n# -S in makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-S\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '',\n\"S\nS\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\", 512);\n}\n\n# -S in makefile and -k on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-S\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '-k',\n\"k\nk\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\ntwo\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n}\n\n# sv 63537\n# -S in makefile and -k in the env.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '-k';\nrun_make_test(\"\nMAKEFLAGS${fl}-S\n\\$(info \\$(MAKEFLAGS))\nall: one two\none:\n\\t \\$(info \\$(MAKEFLAGS))\n\\t #HELPER# -q fail 1\ntwo:; \\$(info \\$@)\n\", '',\n\"k\nk\n#HELPER# -q fail 1\n#MAKE#: *** [#MAKEFILE#:7: one] Error 1\ntwo\n#MAKE#: Target 'all' not remade because of errors.\", 512);\n}\n\n\n# sv 63537\n# -s vs --no-silent.\n\n# -s in env.\n$ENV{'MAKEFLAGS'} = '-s';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '', \"s\\ns\");\n\n# -s in env, --no-silent on the command line.\n$ENV{'MAKEFLAGS'} = '-s';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '--no-silent',\n\" --no-silent\n --no-silent\n#MAKE#: 'all' is up to date.\\n\");\n\n# --no-silent in env.\n$ENV{'MAKEFLAGS'} = '--no-silent';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '',\n\" --no-silent\n --no-silent\n#MAKE#: 'all' is up to date.\\n\");\n\n# --no-silent in env, -s on the command line.\n$ENV{'MAKEFLAGS'} = '--no-silent';\nrun_make_test(q!\n$(info $(MAKEFLAGS))\nall:; $(info $(MAKEFLAGS))\n!, '-s', \"s\\ns\");\n\ndelete $ENV{'MAKEFLAGS'};\n\n# -s in the makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-s\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '', \"s\\ns\");\n}\n\n# sv 63537\n# -s in makefile and --no-silent on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}-s\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '--no-silent',\n\" --no-silent\n --no-silent\n#MAKE#: 'all' is up to date.\\n\");\n}\n\n# sv 63537\n# -s in makefile and --no-silent in the env.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '--no-silent';\nrun_make_test(\"\nMAKEFLAGS${fl}-s\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '',\n\" --no-silent\n --no-silent\n#MAKE#: 'all' is up to date.\\n\");\n}\n\ndelete $ENV{'MAKEFLAGS'};\n\n# sv 63537\n# --no-silent in makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--no-silent\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '',\n\" --no-silent\n --no-silent\n#MAKE#: 'all' is up to date.\\n\");\n}\n\n# sv 63537\n# --no-silent in makefile and -s on the command line.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--no-silent\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '-s', \"s\\ns\");\n}\n\n# sv 63537\n# --no-silent in makefile and -s in the env.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '-s';\nrun_make_test(\"\nMAKEFLAGS${fl}--no-silent\n\\$(info \\$(MAKEFLAGS))\nall:; \\$(info \\$(MAKEFLAGS))\n\", '', \"s\\ns\");\n}\n\ndelete $ENV{'MAKEFLAGS'};\n\n# sv 63537\n# Multiple --debug switches from various origins are all combined.\n# Because run_make_test regex matching facility does not allow to match against\n# multiple lines, run the test twice. During the first run match the output of\n# --debug=b, during the second run match the output of --debug=-j.\n#\n# --debug=b in makefile.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--debug=b\nhello:; touch \\$@\n.PHONY: hello\n\", '', \"/Updating makefiles/\");\n}\n\n# --debug=b in makefile, --debug=j on the command line.\n# Test for --debug=j output.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--debug=b\nhello:; touch \\$@\n.PHONY: hello\n\", '--debug=j', \"/Putting child/\");\n}\n\n# --debug=b in makefile, --debug=j on the command line.\n# Test for --debug=b output.\nfor my $fl (@flavors) {\nrun_make_test(\"\nMAKEFLAGS${fl}--debug=b\nhello:; touch \\$@\n.PHONY: hello\n\", '--debug=j', \"/Updating makefiles/\");\n}\n\n# --debug=j in makefile, --debug=b on the command line.\n# Test that MAKEFLAGS contains --debug=b.\nrun_make_test(q!\nMAKEFLAGS=--debug=j\n$(info makeflags=$(MAKEFLAGS))\nhello:; touch $@\n.PHONY: hello\n!, '--debug=b', \"/makeflags= --debug=b/\");\n\n# --debug=b in makefile, --debug=j in the env.\n# Test for --debug=j output.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '--debug=j';\nrun_make_test(\"\nMAKEFLAGS${fl}--debug=b\nhello:; touch \\$@\n.PHONY: hello\n\", '', \"/Putting child/\");\n}\n\n# --debug=b in makefile, --debug=j in the env.\n# Test for --debug=b output.\nfor my $fl (@flavors) {\n$ENV{'MAKEFLAGS'} = '--debug=j';\nrun_make_test(\"\nMAKEFLAGS${fl}--debug=b\nhello:; touch \\$@\n.PHONY: hello\n\", '', \"/Updating makefiles/\");\n}\n\nunlink('hello');\n\nrmdir('localtmp');\n\n# sv 66037. An infinite loop when MAKEFLAGS is specified on the command line.\nmy @cli= ('-r MAKEFLAGS=-k hello=world',\n'-r MAKEFLAGS=-k hello=world MAKEFLAGS=-R',\n'-r MAKEFLAGS=\"-R -- hello=world MAKEFLAGS=-k\"');\nfor my $c (@cli) {\nrun_make_test(q!\n$(info hello=$(hello))\nall:;\n!, $c, \"hello=world\\n#MAKE#: 'all' is up to date.\\n\");\n}\n\nrun_make_test(q!\n$(info hello=$(hello))\nall:;\n!, '-r MAKEFLAGS=\"-R -- hello=world MAKEFLAGS=hello=bye\"',\n\"hello=bye\\n#MAKE#: 'all' is up to date.\\n\");\n\nrun_make_test(q!\n$(info hello=$(hello))\nall:;\n!, '-r MAKEFLAGS=\"-R -- hello=world MAKEFLAGS=-s\"',\n\"hello=world\\n\");\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MAKELEVEL",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"The following test creates a makefile to test\nmakelevels in Make. It prints \\$(MAKELEVEL) and then\nprints the environment variable MAKELEVEL\";\n\nopen(MAKEFILE,\"> $makefile\");\n\n# The Contents of the MAKEFILE ...\n\nprint MAKEFILE <<EOF;\nall:\n\\t\\@echo MAKELEVEL is \\$(MAKELEVEL)\n\\techo \\$\\$MAKELEVEL\nEOF\n\n# END of Contents of MAKEFILE\n\nclose(MAKEFILE);\n\n# RUN MAKE\n\n&run_make_with_options($makefile,\"\",&get_logfile);\n\n# SET ANSWER\n\n$answer = \"MAKELEVEL is 0\\necho \\$MAKELEVEL\\n1\\n\";\n\n# COMPARE RESULTS\n\n&compare_output($answer,&get_logfile(1));\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MAKE_RESTARTS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the MAKE_RESTARTS variable.\";\n\n# Test basic capability\n\nrun_make_test('\nall: ; @:\n$(info MAKE_RESTARTS=$(MAKE_RESTARTS))\ninclude foo.x\nfoo.x: ; @touch $@\n',\n              '', 'MAKE_RESTARTS=\nMAKE_RESTARTS=1');\n\nrmfiles('foo.x');\n\n# Test multiple restarts\n\nrun_make_test('\nall: ; @:\n$(info MAKE_RESTARTS=$(MAKE_RESTARTS))\ninclude foo.x\nfoo.x: ; @echo \"include bar.x\" > $@\nbar.x: ; @touch $@\n',\n              '', 'MAKE_RESTARTS=\nMAKE_RESTARTS=1\nMAKE_RESTARTS=2');\n\nrmfiles('foo.x', 'bar.x');\n\n# Test multiple restarts and make sure the variable is cleaned up\n\nrun_make_test('\n.RECIPEPREFIX = >\nrecurse:\n> @echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS\n> @$(MAKE) -f #MAKEFILE# all\nall: ; @echo all MAKE_RESTARTS=$$MAKE_RESTARTS\n$(info MAKE_RESTARTS=$(MAKE_RESTARTS))\ninclude foo.x\nfoo.x: ; @echo \"include bar.x\" > $@\nbar.x: ; @touch $@\n',\n              '', \"MAKE_RESTARTS=\nMAKE_RESTARTS=1\nMAKE_RESTARTS=2\nrecurse MAKE_RESTARTS=\n#MAKE#[1]: Entering directory '#PWD#'\nMAKE_RESTARTS=\nall MAKE_RESTARTS=\n#MAKE#[1]: Leaving directory '#PWD#'\");\n\nrmfiles('foo.x', 'bar.x');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/MFILE_LIST",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the MAKEFILE_LIST variable.\";\n\ncreate_file('incl2', \"m2 := \\$(MAKEFILE_LIST)\\n\");\n\nrun_make_test(qq!\nm1 := \\$(MAKEFILE_LIST)\ninclude incl2\nm3 := \\$(MAKEFILE_LIST)\n\nall:\n\\t\\@echo \\$(m1)\n\\t\\@echo \\$(m2)\n\\t\\@echo \\$(m3)\n!,\n              '', \"#MAKEFILE#\\n#MAKEFILE# incl2\\n#MAKEFILE# incl2\\n\");\n\nunlink('incl2');\n\n# SV 50823 -- makefiles containing '$' chars\n\ncreate_file('foo$bar', \"m2 := \\$(MAKEFILE_LIST)\\n\");\n\nrun_make_test(qq!\nm1 := \\$(MAKEFILE_LIST)\ninclude foo\\$\\$bar\nm3 := \\$(MAKEFILE_LIST)\n\nall:\n\\t\\@echo '\\$(m1)'\n\\t\\@echo '\\$(m2)'\n\\t\\@echo '\\$(m3)'\n\\t\\@echo '\\$(value MAKEFILE_LIST)'\n!,\n              '', \"#MAKEFILE#\\n#MAKEFILE# foo\\$bar\\n#MAKEFILE# foo\\$bar\\n#MAKEFILE# foo\\$bar\\n\");\n\nunlink('foo$bar');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/SHELL",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test proper handling of SHELL.\";\n\n# If we don't have a POSIX shell available, never mind\n$is_posix_sh or return -1;\n\n# On Windows, shell names might not match\nif ($port_type eq 'W32') {\n    return -1;\n}\n\n$mshell = $sh_name;\n\n# According to POSIX, the value of SHELL in the environment has no impact on\n# the value in the makefile.\n\n$ENV{SHELL} = '/dev/null';\nrun_make_test('all:;@echo \"$(SHELL)\"', '', $mshell);\n\n# According to POSIX, any value of SHELL set in the makefile should not be\n# exported to the subshell.  A more portable option might be to set SHELL to\n# be $^X (perl) in the makefile, and set .SHELLFLAGS to -e.\n\n$ENV{SHELL} = $mshell;\n\nmy $altshell = \"/./$mshell\";\nmy $altshell2 = \"/././$mshell\";\n\nif ($mshell =~ m,^([a-zA-Z]:)([\\\\/])(.*),) {\n    $altshell = \"$1$2.$2$3\";\n    $altshell2 = \"$1$2.$2.$2$3\";\n}\n\nrun_make_test(\"SHELL := $altshell\\n\".'\nall:;@echo \"$(SHELL) $$SHELL\"\n', '', \"$altshell $mshell\");\n\n# As a GNU Make extension, if make's SHELL variable is explicitly exported,\n# then we really _DO_ export it.\n\n$ENV{SHELL} = $mshell;\n\nrun_make_test(\"export SHELL := $altshell\\n\".'\nall:;@echo \"$(SHELL) $$SHELL\"\n', '', \"$altshell $altshell\");\n\n\n# Test out setting of SHELL, both exported and not, as a target-specific\n# variable.\n\n$ENV{SHELL} = $mshell;\n\nrun_make_test(\"all: SHELL := $altshell\\n\".'\nall:;@echo \"$(SHELL) $$SHELL\"\n', '', \"$altshell $mshell\");\n\n$ENV{SHELL} = $mshell;\n\nrun_make_test(\"\nSHELL := $altshell2\none: two\ntwo: export SHELL := $altshell\\n\".'\none two:;@echo \"$@: $(SHELL) $$SHELL\"\n', '', \"two: $altshell $altshell\\none: $altshell2 $mshell\\n\");\n\n# Test .SHELLFLAGS\n\n# We don't know the output here: on some systems, for example, every line\n# printed by the shell in -x mode has a trailing space!\nmy $script = 'true; true';\nmy $flags = '-xc';\nmy $out = `$sh_name $flags '$script' 2>&1`;\n\nrun_make_test(qq!\n.SHELLFLAGS = $flags\nall: ; \\@$script\n!,\n              '', $out);\n\n# Do it again but add spaces to SHELLFLAGS\n\n# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in\n# separate arguments.\nmy $t = `$sh_name -e -c true 2>/dev/null`;\nmy $multi_ok = $? == 0;\n\nif ($multi_ok) {\n    $flags = '-x -c';\n    run_make_test(qq!\n.SHELLFLAGS = $flags\nall: ; \\@$script\n!,\n              '', $out);\n}\n\n$script = subst_make_string('true; #HELPER# -q fail 1; true');\n$flags = '-xec';\n$out = `$sh_name $flags '$script' 2>&1`;\n\nrun_make_test(qq!\n.SHELLFLAGS = $flags\nall: ; \\@$script\n!,\n              '', \"${out}#MAKE#: *** [#MAKEFILE#:3: all] Error 1\", 512);\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/WARNINGS",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test the .WARNINGS variable.\";\n\nmy %warn_test = (\n    'warn' => 'warn', 'error warn' => 'warn',\n    'error' => 'error',\n    'ignore error ignore invalid-var,invalid-ref,undefined-var' => 'ignore,invalid-var,invalid-ref,undefined-var',\n    'invalid-ref:ignore error invalid-var:warn,,,,,undefined-var:error,,,,,' => '=error,invalid-var,invalid-ref:ignore,undefined-var:error'\n);\n\n# Verify that values set in .WARNINGS don't get passed to sub-makes\n\nwhile (my ($f, $r) = each %warn_test) {\n    run_make_test(qq!\n.WARNINGS = error\n\\$(info MF=\\$(MAKEFLAGS))\nall:; \\@#HELPER# env MAKEFLAGS\n!,\n                  '', \"MF=\\nMAKEFLAGS=\");\n}\n\n# Verify that make's special variables don't warn even if they're not set\nrun_make_test(q!\n.WARNINGS = undefined-var\nvars := $(.VARIABLES) $(MAKECMDGOALS) $(MAKE_RESTARTS) $(CURDIR)\nvars += $(GNUMAKEFLAGS) $(MAKEFLAGS) $(MFLAGS) $(MAKE_COMMAND) $(MAKE)\nvars += $(MAKEFILE_LIST) $(MAKEOVERRIDES) $(-*-command-variables-*-)\nvars += $(.RECIPEPREFIX) $(.LOADED) $(.FEATURES)\nvars += $(SHELL) $(.SHELLFLAGS) $(MAKE_TERMOUT) $(MAKE_TERMERR)\nvars += $(.DEFAULT) $(.DEFAULT_GOAL) $(-*-eval-flags-*-) $(SUFFIXES)\nvars += $(VPATH) $(GPATH)\nall:;\n!,\n              '', \"#MAKE#: 'all' is up to date.\");\n\n# sv 63609.\n# Test for buffer overrun in warn_undefined.\nrun_make_test(q!\n.WARNINGS = undefined-var\nall:;\nX := $(averyveryveryloooooooooooooooooooooooooooongvariablename)\n!,\n              '', \"#MAKEFILE#:4: warning: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename'\n#MAKE#: 'all' is up to date.\\n\"\n);\n\n# Check undefined variable warnings\n\n# With no options or with ignore, nothing should happen\nrun_make_test('\n.WARNINGS := $(warnval)\nEMPTY =\nEREF = $(EMPTY)\nUREF = $(UNDEFINED)\n\nSEREF := $(EREF)\nSUREF := $(UREF)\n\nall: ; @echo ref $(EREF) $(UREF)',\n              '', 'ref');\n\nrun_make_test(undef, 'warnval=undefined-var:ignore', 'ref');\n\n# Check warnings\nrun_make_test(undef, 'warnval=undefined-var',\n              \"#MAKEFILE#:8: warning: reference to undefined variable 'UNDEFINED'\n#MAKEFILE#:10: warning: reference to undefined variable 'UNDEFINED'\nref\");\n\n# Check and errors\nrun_make_test(undef, 'warnval=undefined-var:error',\n              \"#MAKEFILE#:8: *** reference to undefined variable 'UNDEFINED'.  Stop.\", 512);\n\n# Check invalid variable reference warnings\n\n# With no options we still check for invalid references\nrun_make_test('\n.WARNINGS = $(warnval)\nIREF = $(bad variable)\nSIREF := $(IREF)\n\ndefine nl\n\n\nendef\n\nall: ; @echo ref $(also$(nl)bad) $(IREF) $(SIREF)',\n              '', \"#MAKEFILE#:3: warning: invalid variable reference 'bad variable'\n#MAKEFILE#:11: warning: invalid variable reference 'also\\nbad'\n#MAKEFILE#:3: warning: invalid variable reference 'bad variable'\nref\");\n\nrun_make_test(undef, 'warnval=ignore', 'ref');\n\nrun_make_test(undef, 'warnval=invalid-ref:ignore', 'ref');\n\n# Check and errors\nrun_make_test(undef, 'warnval=invalid-ref:error',\n              \"#MAKEFILE#:3: *** invalid variable reference 'bad variable'.  Stop.\", 512);\n\n# Check invalid variable name warnings\n\n# With no options we still check for invalid references\nrun_make_test('\n.WARNINGS = $(warnval)\nEMPTY =\nSPACE = $(EMPTY) $(EMPTY)\nBAD$(SPACE)VAR = foo\n\ndefine nl\n\n\nendef\n\nNL$(nl)VAR = bar\n\ndefine BAD$(SPACE)DEF :=\nfoo\nendef\n\ndefine NL$(nl)DEF :=\nfoo\nendef\n\nall: ; @echo ref',\n              '', \"#MAKEFILE#:5: warning: invalid variable name 'BAD VAR'\n#MAKEFILE#:12: warning: invalid variable name 'NL\\nVAR'\n#MAKEFILE#:14: warning: invalid variable name 'BAD DEF'\n#MAKEFILE#:18: warning: invalid variable name 'NL\\nDEF'\nref\");\n\nrun_make_test(undef, 'warnval=ignore', 'ref');\n\nrun_make_test(undef, 'warnval=invalid-var:ignore', 'ref');\n\n# Check errors\nrun_make_test(undef, 'warnval=invalid-var:error',\n              \"#MAKEFILE#:5: *** invalid variable name 'BAD VAR'.  Stop.\", 512);\n\n# Make sure unknown warnings and actions are only noted but not failed on:\n# this allows makefiles to be portable to older versions where those warnings\n# didn't exist\n\nrun_make_test(q!\n.WARNINGS = no-such-warn\nall:;\n!,\n    '',\"#MAKEFILE#:2: unknown warning 'no-such-warn': ignored\\n#MAKE#: 'all' is up to date.\");\n\nrun_make_test(q!\n.WARNINGS = invalid-var:no-such-action\nall:;\n!,\n    '',\"#MAKEFILE#:2: unknown warning action 'no-such-action': ignored\\n#MAKE#: 'all' is up to date.\");\n\n# sv 65739. Circular dependency.\nrun_make_test(q!\nhello: hello; @:\n!,\n              '', \"#MAKE#: circular hello <- hello dependency dropped\\n\");\nrun_make_test(q!\n.WARNINGS = circular-dep:error\nhello: hello; @:\n!,\n              '', \"#MAKE#: *** circular hello <- hello dependency detected.  Stop.\\n\", 512);\nrun_make_test(q!\n.WARNINGS = circular-dep:warn\nhello: hello; @:\n!,\n              '', \"#MAKE#: circular hello <- hello dependency dropped\\n\");\nrun_make_test(q!\n.WARNINGS = circular-dep:ignore\nhello: hello; @:\n!,\n              '', '');\n\n\n# Validate .WARNINGS set as target-specific variables\n# This is not supported (yet...?)\n\n# run_make_test(q!\n# ok := $(undef)\n# ref = $(undef)\n\n# all: enabled disabled enabled2 ;\n\n# .WARNINGS = undefined-var\n\n# enabled enabled2 disabled ref: ; $(info $@:$(ref))\n\n# disabled: .WARNINGS =\n# disabled: ref\n# !,\n#     '', \"#MAKEFILE#:9: reference to undefined variable 'undef'\\nenabled:\n# ref:\n# disabled:\n# #MAKEFILE#:9: reference to undefined variable 'undef'\\nenabled2:\n# #MAKE#: 'all' is up to date.\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/append",
    "content": "#                                                                    -*-perl-*-\n\nuse warnings;\n\nmy $description = \"Test appending to variables of various origins.\";\n\n# sv 64822, sv 36486.\n# Test various combinations of appends in the presence and absence of command\n# line definitions, env overrides and makefile overrides.\n# Test the following statements.\n# A target or pattern specific definition or append is available at build time\n# only.\n# A definition with a makefile override can only be appended to with another\n# override.\n# A definition with a makefile override can only be redefined with another\n# override.\n# A target or pattern specific definition takes precedence over a global\n# definition for that target.\n# A global variable is immune to a target or pattern specific definition or\n# append.\n# A target or pattern specific definition is immune to another target or pattern\n# specific definition or append.\n# A prerequisite inherits a target or pattern specific value from its target.\n# \"phobos\" inherits the value of \"hello\" from \"mars\".\n\nmy @goals = ('phobos', 'mars');\nmy @specificities = ('', 's: ', '%: ');\nmy @inits = ('', 'hello=file', 'hello:=file', 'override hello=file');\nmy @global_append = ('', 'hello+=red');\nmy @blue_override = ('', 'override ');\nmy @yellow_override = ('', 'override ');\nmy @cmdline = ('', 'hello=cmd', 'hello:=cmd hello+=cmd2');\nmy @env_ovr = ('', '-e');\nmy @envs = ('', 'env');\n\nfor my $goal (@goals) {\n for my $spec (@specificities) {\n  for my $init (@inits) {\n   for my $ga (@global_append) {\n    for my $bovr (@blue_override) {\n     for my $yovr (@yellow_override) {\n      for my $dashe (@env_ovr) {\n       for my $env (@envs) {\n        for my $cmd (@cmdline) {\n\n        if ($env) {\n            $ENV{'hello'} = 'env';\n        } else {\n            delete $ENV{'hello'};\n        }\n\n        my $parse_time_answer = '';\n        my $build_time_answer = '';\n\n        # For goal \"phobos\" target is \"\", \"phobos: \" and \"phobo%: \".\n        # For goal \"mars\" target is \"\", \"mars: \" and \"mar%: \".\n        my $target = '';\n        if ($spec) {\n            $target = $goal;\n            chop($target);\n            $target .= $spec;\n        }\n\n        if ($init =~ 'override') {\n            $build_time_answer = 'file';\n        } elsif ($cmd) {\n            $build_time_answer = $cmd =~ 'cmd2' ? 'cmd cmd2' : 'cmd';\n        } elsif ($dashe and $env) {\n            $build_time_answer = 'env';\n        } elsif ($init and !$target and $ga) {\n            $build_time_answer = 'file red';\n        } elsif ($init) {\n            $build_time_answer = 'file';\n        } elsif ($env and $ga) {\n            $build_time_answer = 'env red';\n        } elsif ($env) {\n            $build_time_answer = 'env';\n        } elsif ($ga) {\n            $build_time_answer = 'red';\n        }\n\n        if ($bovr and $yovr) {\n            $build_time_answer .= ' ' if ($build_time_answer);\n            $build_time_answer .= 'blue yellow';\n        } elsif ($bovr) {\n            $build_time_answer .= ' ' if ($build_time_answer);\n            $build_time_answer .= 'blue';\n        } elsif ($yovr and !($init =~ 'override') and !$cmd and !($dashe and $env)) {\n            $build_time_answer .= ' ' if ($build_time_answer);\n            $build_time_answer .= 'blue yellow';\n        } elsif ($yovr) {\n            $build_time_answer .= ' ' if ($build_time_answer);\n            $build_time_answer .= 'yellow';\n        } elsif ($init =~ 'override') {\n        } elsif ($cmd) {\n        } elsif ($dashe and $env) {\n        } else {\n            $build_time_answer .= ' ' if ($build_time_answer);\n            $build_time_answer .= 'blue yellow';\n        }\n\n\n        if ($cmd and $target) {\n            $parse_time_answer = $cmd =~ 'cmd2' ? 'cmd cmd2' : 'cmd';\n        } elsif ($env and !$dashe and $target and $ga) {\n            $parse_time_answer = 'env red';\n        } elsif ($env and $target) {\n            $parse_time_answer = 'env';\n        } elsif ($target and $ga) {\n            $parse_time_answer = 'red';\n        } elsif ($target) {\n            $parse_time_answer = '';\n        } else {\n            $parse_time_answer = $build_time_answer;\n        }\n\n        my $i = $init ? \"$target$init\" : '';\n\n        # moon and satur% specific settings test that target and pattern\n        # settings specific to one target do not affect another target.\n\n        my $answer = $goal eq \"mars\" ?\n            \"$parse_time_answer\\n$build_time_answer\\n\" # From parse time and from \"phobos\" recipe.\n          . \"$build_time_answer\\n#MAKE#: 'mars' is up to date.\\n\" :  # From \"mars\" recipe.\n            \"$parse_time_answer\\n$build_time_answer\\n#MAKE#: 'phobos' is up to date.\\n\";\n\n\n        run_make_test(\"\n# goal = $goal\n# init = $init\n# target = $target\n# ga = $ga\n# bovr = $bovr\n# yovr = $yovr\n# cmd = $cmd\n# env = $env\n# dashe = $dashe\n\nmoon: hello=1\nmoon: override hello+=2\n\n$i\n$ga\n$target${bovr}hello+=blue\n$target${yovr}hello+=yellow\n\nsatur%: override hello:=3\nsatur%: hello+=4\n\n\\$(info \\$(hello))\nphobos:; \\$(info \\$(hello))\nmars: phobos; \\$(info \\$(hello))\nsaturn:; \\$(info \\$(hello))\n\", \"$dashe $cmd $goal\", \"$answer\");\n        }\n       }\n      }\n     }\n    }\n   }\n  }\n }\n}\n\n# Preferably, we would want to run the tests below for all the combinations,\n# generated by the loop above. However, that causes the test to take a lot of\n# time.\n\n# The fix for sv 64822 went to recursively_expand_for_file.\n# There are three code paths that lead to recursively_expand_for_file.\n#  - export of a variable to target environment.\n#  - expansion of a substitution reference.\n#  - other expansions of a variable that was appended to.\n# Test target env, substitution reference in parse and build modes.;\n# Also test a mix of pattern and target specific definitions and appends.\n\nrun_make_test(q!\nal%: hello=file\nal%: hello+=one\nall: hello+=two\n$(info $(hello))\nall:; $(info $(hello))\n!, \"\", \"\\nfile one two\\n#MAKE#: 'all' is up to date.\\n\");\n\nrun_make_test(q!\nhello=file\nal%: hello+=one\nall: hello+=two\n$(info $(hello:X=Y))\nall:; $(info $(hello:X=Y))\n!, \"\", \"file\\nfile one two\\n#MAKE#: 'all' is up to date.\\n\");\n\nrun_make_test(q!\nhello=file\nal%: hello+=one\nall: hello+=two\nexport hello\n$(info $(shell echo $$hello))\nall:; $(info $(shell echo $$hello))\n!, \"\", \"file\\nfile one two\\n#MAKE#: 'all' is up to date.\\n\");\n\n# \"phobos\" inherits the value of \"hello\" from \"mars\". On top of that there are\n# also \"phobos\" specific appends.\nfor my $goal (@goals) {\nmy $answer = $goal eq \"mars\" ?\n    \"\\nminit mone mtwo pone ptwo\\n\" # From parse time and from \"phobos\" recipe.\n  . \"minit mone mtwo\\n#MAKE#: 'mars' is up to date.\\n\" :  # From \"mars\" recipe.\n    \"\\npone ptwo\\n#MAKE#: 'phobos' is up to date.\\n\"; # From parse time and from \"phobos\" recipe.\n\nrun_make_test(\"\nmar%: hello=minit\nmar%: hello+=mone\nmars: hello+=mtwo\nphobo%: hello+=pone\nphobos: hello+=ptwo\n\\$(info \\$(hello))\nphobos:; \\$(info \\$(hello))\nmars: phobos; \\$(info \\$(hello))\n\", \"$goal\", \"$answer\");\n}\n\n# This test is similar to the one above. The difference is that here there is a\n# pattern-specific definition of \"hello\" that matches \"phobos\".\nrun_make_test(q!\nmar%: hello:=minit\nmar%: hello+=mone\nmars: hello+=mtwo\nphobo%: hello:=pinit\nphobo%: hello+=pone\nphobos: hello+=ptwo\n$(info $(hello))\nphobos:; $(info $(hello))\nmars: phobos; $(info $(hello))\n!, 'phobos', \"\\npinit pone ptwo\\n#MAKE#: 'phobos' is up to date.\\n\");\n\n# Test pattern and target specific appends to a global variable that has origin override.\n# sv 36486.\nmy @ops = ('=', '+=', ':=');\n@inits = ('', 'override ', 'al%: override ');\n@specificities = ('', 'all: ', 'al%: ');\nfor my $init (@inits) {\n for my $spec (@specificities) {\n  for my $op (@ops) {\n\n  my $build_time_answer = '';\n  if ($init =~ ':' and $op eq '+=' and !$spec) {\n      # This is the case where global variable obtains value 'one two three' at\n      # parse time and later at build time a pattern or target specific\n      # 'hello+=file' appends 'file'.\n      # e.g.\n      # al%: override hello+=file\n      # hello+=one\n      # hello+=two\n      # hello+=three\n      $build_time_answer = 'one two three file';\n  } elsif ($init =~ 'override') {\n      $build_time_answer = 'file';\n  } else {\n      $build_time_answer = 'file one two three';\n  }\n\n  my $parse_time_answer = $init =~ ':' ? '' : 'file';\n  if (!$spec and ($init ne 'override ')) {\n      $parse_time_answer .= ' ' if $parse_time_answer;\n      $parse_time_answer .= 'one two three';\n  }\n\n  run_make_test(\"\n${init}hello${op}file\n${spec}hello+=one\n${spec}hello+=two\n${spec}hello+=three\n\\$(info \\$(hello))\nall:; \\$(info \\$(hello))\n\", \"\", \"$parse_time_answer\\n$build_time_answer\\n#MAKE#: 'all' is up to date.\\n\");\n  }\n }\n}\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/automatic",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test automatic variable setting.\";\n\n$details = \"\";\n\nuse Cwd;\n\n$dir = cwd;\n$dir =~ s,.*/([^/]+)$,../$1,;\n\nopen(MAKEFILE, \"> $makefile\");\nprint MAKEFILE \"dir = $dir\\n\";\nprint MAKEFILE <<'EOF';\n.SUFFIXES:\n.SUFFIXES: .x .y .z\n$(dir)/foo.x : baz.z $(dir)/bar.y baz.z\n\t@echo '$$@ = $@, $$(@D) = $(@D), $$(@F) = $(@F)'\n\t@echo '$$* = $*, $$(*D) = $(*D), $$(*F) = $(*F)'\n\t@echo '$$< = $<, $$(<D) = $(<D), $$(<F) = $(<F)'\n\t@echo '$$^ = $^, $$(^D) = $(^D), $$(^F) = $(^F)'\n\t@echo '$$+ = $+, $$(+D) = $(+D), $$(+F) = $(+F)'\n\t@echo '$$? = $?, $$(?D) = $(?D), $$(?F) = $(?F)'\n\ttouch $@\n\n$(dir)/bar.y baz.z : ; touch $@\nEOF\nclose(MAKEFILE);\n\n# TEST #0 -- simple test\n# -------\n\n# Touch these into the past\n&utouch(-10, qw(foo.x baz.z));\n\n&run_make_with_options($makefile, \"\", &get_logfile);\n$answer = \"touch $dir/bar.y\n\\$\\@ = $dir/foo.x, \\$(\\@D) = $dir, \\$(\\@F) = foo.x\n\\$* = $dir/foo, \\$(*D) = $dir, \\$(*F) = foo\n\\$< = baz.z, \\$(<D) = ., \\$(<F) = baz.z\n\\$^ = baz.z $dir/bar.y, \\$(^D) = . $dir, \\$(^F) = baz.z bar.y\n\\$+ = baz.z $dir/bar.y baz.z, \\$(+D) = . $dir ., \\$(+F) = baz.z bar.y baz.z\n\\$? = $dir/bar.y, \\$(?D) = $dir, \\$(?F) = bar.y\ntouch $dir/foo.x\\n\";\n&compare_output($answer, &get_logfile(1));\n\nunlink(qw(foo.x bar.y baz.z));\n\n# TEST #1 -- test the SysV emulation of $$@ etc.\n# -------\n\n$makefile2 = &get_tmpfile;\n\nopen(MAKEFILE, \"> $makefile2\");\nprint MAKEFILE \"dir = $dir\\n\";\nprint MAKEFILE <<'EOF';\n.SECONDEXPANSION:\n.SUFFIXES:\n.DEFAULT: ; @echo '$@'\n\n$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x\n\n$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%\n\n$(dir)/biz: $$(@).x $${@}.x $${@D}.x $${@F}.x\nEOF\n\nclose(MAKEFILE);\n\n&run_make_with_options($makefile2, \"$dir/foo $dir/bar\", &get_logfile);\n$answer = \".x\\n$dir/foo.x\\nx\\n\\$@.x\\n$dir.x\\nfoo.x\\n$dir/bar.x\\nbar.x\\n\";\n&compare_output($answer, &get_logfile(1));\n\n&run_make_with_options($makefile2, \"$dir/x.z $dir/y.z\", &get_logfile);\n$answer = \".x\\n$dir/x.z.x\\nx\\n\\$@.x\\n$dir.x\\nx.z.x\\n.y\\n$dir/y.z.y\\ny\\n\\$@.y\\n$dir.y\\ny.z.y\\n\";\n&compare_output($answer, &get_logfile(1));\n\n&run_make_with_options($makefile2, \"$dir/biz\", &get_logfile);\n$answer = \"$dir/biz.x\\n$dir.x\\nbiz.x\\n\";\n&compare_output($answer, &get_logfile(1));\n\n# TEST #2 -- test for Savannah bug #12320.\n#\nrun_make_test('\n.SUFFIXES: .b .src\n\nmbr.b: mbr.src\n\t@echo $*\n\nmbr.src: ; @:',\n              '',\n              'mbr');\n\n# Same as above with second expansion.\n#\nrun_make_test('\n.SECONDEXPANSION:\n.SUFFIXES: .b .src\n\np:=mbr.src\nmbr.b: $$p\n\t@echo $*\n\nmbr.src: ; @:',\n              '',\n              'mbr');\n\n# Test that $* is set to empty string for unknown suffixes.\n\nrun_make_test('\nmbr.b: mbr.src\n\t@echo star=$*\n\nmbr.src: ; @:',\n              '',\n              \"star=\\n\");\n\n# TEST #3 -- test for Savannah bug #8154\n# Make sure that nonexistent prerequisites are listed in $?, since they are\n# considered reasons for the target to be rebuilt.\n#\n# See also Savannah bugs #16002 and #16051.\n\ntouch('foo');\n\nrun_make_test('\nfoo: bar ; @echo \"\\$$? = $?\"\nbar: ;',\n              '',\n              '$? = bar');\n\nunlink('foo');\n\n# TEST #4: ensure prereq ordering is correct when the command target has none\n# See Savannah bug #21198\n\nrun_make_test('\nall : A B\nall : ; @echo $@ -- $^ -- $<\nall : C D\nall : E F\nA B C D E F G H : ; @:\n',\n              '', \"all -- A B C D E F -- A\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/conditional",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test various flavors of conditional variable setting.\";\n\n$details = \"\";\n\n# Test ?=\n\nrun_make_test(q!\nx = bar\ny = baz\nfoo ?= $(x)\nbiz?=$(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=10 biz=20\");\n\nrun_make_test(q!\nfoo=1\nbiz=2\nx = bar\ny = baz\nfoo ?= $(x)\nbiz?=$(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=1 biz=2\");\n\n# Test ?:=\n\nrun_make_test(q!\nx = bar\ny = baz\nfoo ?:= $(x)\nbiz?:=$(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=bar biz=baz\");\n\nrun_make_test(q!\nfoo=1\nbiz=2\nx = bar\ny = baz\nfoo ?:= $(x)$(info expanded)\nbiz?:=$(y)$(info expanded)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=1 biz=2\");\n\n# Test ?::=\n\nrun_make_test(q!\nx = bar\ny = baz\nfoo ?::= $(x)\nbiz?::=$(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=bar biz=baz\");\n\nrun_make_test(q!\nfoo=1\nbiz=2\nx = bar\ny = baz\nfoo ?::= $(x)$(info expanded)\nbiz?::=$(y)$(info expanded)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=1 biz=2\");\n\n# Test ?:::=\n\nrun_make_test(q!\nx = bar\ny = baz\nfoo ?:::= $(x)\nbiz?:::=$(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=bar biz=baz\");\n\nrun_make_test(q!\nfoo=1\nbiz=2\nx = bar\ny = baz\nfoo ?:::= $(x)$(info expanded)\nbiz?:::=$(y)$(info expanded)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n!,\n              '', \"foo=1 biz=2\");\n\n# Test ?!=\n\nrun_make_test(q/\nx = bar\ny = baz\nfoo ?!= echo $(x)\nbiz?!=echo $(y)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n/,\n              '', \"foo=bar biz=baz\");\n\nrun_make_test(q/\nfoo=1\nbiz=2\nx = bar\ny = baz\nfoo ?!= echo $(x)$(info expanded)\nbiz?!=echo $(y)$(info expanded)\nx = 10\ny = 20\nall:;@: $(info foo=$(foo) biz=$(biz))\n/,\n              '', \"foo=1 biz=2\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/define",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test define/endef variable assignments.\";\n\n$details = \"\";\n\n# TEST 0: old-style basic define/endef\n\nrun_make_test('\ndefine multi\n@echo hi\necho there\nendef\n\nall: ; $(multi)\n',\n              '', \"hi\\necho there\\nthere\\n\");\n\n# TEST 1: Various new-style define/endef\n\nrun_make_test('\nFOO = foo\n\ndefine multi =\necho hi\n@echo $(FOO)\nendef # this is the end\n\ndefine simple :=\n@echo $(FOO)\nendef\n\ndefine posix ::=\n@echo $(FOO)\nendef\n\nappend = @echo a\n\ndefine append +=\n\n@echo b\nendef\n\ndefine cond ?= # this is a conditional\n@echo first\nendef\n\ndefine cond ?=\n@echo second\nendef\n\nFOO = there\n\nall: ; $(multi)\n\t$(simple)\n\t$(posix)\n\t$(append)\n\t$(cond)\n',\n              '', \"echo hi\\nhi\\nthere\\nfoo\\nfoo\\na\\nb\\nfirst\\n\");\n\n# TEST 1a: Various new-style define/endef, with no spaces\n\nrun_make_test(q!\nFOO = foo\n\ndefine multi=\necho hi\n@echo $(FOO)\nendef # this is the end\n\ndefine simple:=\n@echo $(FOO)\nendef\n\ndefine posix::=\n@echo $(FOO)\nendef\n\ndefine posixbsd:::=\n@echo '$(FOO)$$bar'\nendef\n\nappend = @echo a\n\ndefine append+=\n\n@echo b\nendef\n\ndefine cond?= # this is a conditional\n@echo first\nendef\n\ndefine cond?=\n@echo second\nendef\n\nFOO = there\n\nall: ; $(multi)\n\t$(simple)\n\t$(posix)\n\t$(posixbsd)\n\t$(append)\n\t$(cond)\n!,\n              '', \"echo hi\\nhi\\nthere\\nfoo\\nfoo\\nfoo\\$bar\\na\\nb\\nfirst\\n\");\n\n# TEST 2: define in true section of conditional (containing conditional)\n\nrun_make_test('\nFOO = foo\nNAME = def\ndef =\nifdef BOGUS\n define  $(subst e,e,$(NAME))     =\n  ifeq (1,1)\n   FOO = bar\n  endif\n endef\nendif\n\n$(eval $(def))\nall: ; @echo $(FOO)\n',\n              'BOGUS=1', \"bar\\n\");\n\n# TEST 3: define in false section of conditional (containing conditional)\n\nrun_make_test(undef, '', \"foo\\n\");\n\n# TEST 4: nested define (supported?)\n\nrun_make_test('\ndefine outer\n define inner\n  A = B\n endef\nendef\n\n$(eval $(outer))\n\nouter: ; @echo $(inner)\n',\n              '', \"A = B\\n\");\n\n# TEST 5: NEGATIVE: Missing variable name\n\nrun_make_test('\nNAME =\ndefine $(NAME)  =\nouch\nendef\nall: ; @echo ouch\n',\n              '', \"#MAKEFILE#:3: *** empty variable name.  Stop.\\n\", 512);\n\n# TEST 6: NEGATIVE: extra text after define\n\nrun_make_test('\nNAME =\ndefine NAME = $(NAME)\nouch\nendef\nall: ; @echo ok\n',\n              '', \"#MAKEFILE#:3: extraneous text after 'define' directive\\nok\\n\");\n\n# TEST 7: NEGATIVE: extra text after endef\n\nrun_make_test('\nNAME =\ndefine NAME =\nouch\nendef $(NAME)\nall: ; @echo ok\n',\n              '', \"#MAKEFILE#:5: extraneous text after 'endef' directive\\nok\\n\");\n\n# TEST 8: NEGATIVE: missing endef\n\nrun_make_test('\nNAME =\nall: ; @echo ok\ndefine NAME =\nouch\nendef$(NAME)\n',\n              '', \"#MAKEFILE#:4: *** missing 'endef', unterminated 'define'.  Stop.\\n\", 512);\n\n# -------------------------\n# Make sure that prefix characters apply properly to define/endef values.\n#\n# There's a bit of oddness here if you try to use a variable to hold the\n# prefix character for a define.  Even though something like this:\n#\n#       define foo\n#       echo bar\n#       endef\n#\n#       all: ; $(V)$(foo)\n#\n# (where V=@) can be seen by the user to be obviously different than this:\n#\n#       define foo\n#       $(V)echo bar\n#       endef\n#\n#       all: ; $(foo)\n#\n# and the user thinks it should behave the same as when the \"@\" is literal\n# instead of in a variable, that can't happen because by the time make\n# expands the variables for the command line and sees it begins with a \"@\" it\n# can't know anymore whether the prefix character came before the variable\n# reference or was included in the first line of the variable reference.\n\n# TEST #5\n# -------\n\nrun_make_test('\ndefine FOO\n$(V1)echo hello\n$(V2)echo world\nendef\nall: ; @$(FOO)\n', '', 'hello\nworld');\n\n# TEST #6\n# -------\n\nrun_make_test(undef, 'V1=@ V2=@', 'hello\nworld');\n\n# TEST #7\n# -------\n\nrun_make_test('\ndefine FOO\n$(V1)echo hello\n$(V2)echo world\nendef\nall: ; $(FOO)\n', 'V1=@', 'hello\necho world\nworld');\n\n# TEST #8\n# -------\n\nrun_make_test(undef, 'V2=@', 'echo hello\nhello\nworld');\n\n# TEST #9\n# -------\n\nrun_make_test(undef, 'V1=@ V2=@', 'hello\nworld');\n\n# TEST #10\n# -------\n# Test the basics; a \"@\" internally to the variable applies to only one line.\n# A \"@\" before the variable applies to the entire variable.\n\nrun_make_test('\ndefine FOO\n@echo hello\necho world\nendef\ndefine BAR\necho hello\necho world\nendef\n\nall: foo bar\nfoo: ; $(FOO)\nbar: ; @$(BAR)\n', '', 'hello\necho world\nworld\nhello\nworld\n');\n\n# Ensure that define can be a target when not appearing in a variable\n# definition context.  See SV 59870\n\nrun_make_test(q!\ndefine = define\n\n$(define) : ;@echo $@\n\n%:define\n\nall: define foo\n\n%.x : define\n\nfoo:;\n!,\n    '', \"define\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/flavors",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test various flavors of make variable setting.\";\n\n$details = \"\";\n\n# TEST 0: Recursive\n\nrun_make_test('\nugh = Goodbye\nfoo = $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Hello\\n\");\n\n# TEST 1: Simple\n\nrun_make_test('\nbar = Goodbye\nfoo := $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Goodbye\\n\");\n\n# TEST 2: Append to recursive\n\nrun_make_test('\nfoo = Hello\nugh = Goodbye\nfoo += $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Hello Hello\\n\");\n\n# TEST 3: Append to simple\n\nrun_make_test('\nfoo := Hello\nugh = Goodbye\nbar = ${ugh}\nfoo += $(bar)\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Hello Goodbye\\n\");\n\n# TEST 4: Conditional pre-set\n\nrun_make_test('\nfoo = Hello\nugh = Goodbye\nbar = ${ugh}\nfoo ?= $(bar)\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Hello\\n\");\n\n# TEST 5: Conditional unset\n\nrun_make_test('\nugh = Goodbye\nbar = ${ugh}\nfoo ?= $(bar)\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Hello\\n\");\n\n# TEST 6: Simple using POSIX syntax\nrun_make_test('\nbar = Goodbye\nfoo ::= $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Goodbye\\n\");\n\n# TEST 7: POSIX syntax no spaces\nrun_make_test('\nbar = Goodbye\nfoo::=$(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Goodbye\\n\");\n\n# TEST 8: Append to empty\nrun_make_test(q!\nrecur =\nrecur += foo\nsimple :=\nsimple += bar\nrecur_empty = foo\nrecur_empty +=\nsimple_empty := bar\nsimple_empty +=\nempty_recur =\nempty_recur +=\nempty_simple :=\nempty_simple +=\n\nall: ; @: $(info recur=/$(recur)/ simple=/$(simple)/ recure=/$(recur_empty)/ simplee=/$(simple_empty)/ erecur=/$(empty_recur)/ esimple=/$(empty_simple)/)\n!,\n              '', \"recur=/foo/ simple=/bar/ recure=/foo/ simplee=/bar/ erecur=// esimple=//\\n\");\n\n# TEST 9: Line continuation\nrun_make_test(q!\nrecur = $\\\n  zero  $\\\n  one$$\\\n  two$$$\\\n  three\nsimple := $\\\n  four  $\\\n  five$$\\\n  six$$$\\\n  seven\n\nall: d$\\\n     e$\\\n     p; @:\n\n.PHONY: dep\ndep: ; @: $(info recur=/$(recur)/ simple=/$(simple)/)\n!,\n             '', \"recur=/zeroone\\$ two\\$three/ simple=/fourfive\\$ six\\$seven/\\n\");\n\n# TEST 9: Line continuation with POSIX\nrun_make_test(q!\n.POSIX:\nrecur = $\\\n  zero  $\\\n  one$$\\\n  two$$$\\\n  three\nsimple := $\\\n  four  $\\\n  five$$\\\n  six$$$\\\n  seven\n\nall: d$\\\n     e$\\\n     p; @:\n\n.PHONY: dep\ndep: ; @: $(info recur=/$(recur)/ simple=/$(simple)/)\n!,\n             '', \"recur=/zero  one\\$ two\\$three/ simple=/four  five\\$ six\\$seven/\\n\");\n\n# Test POSIX :::=\n# This creates a recursive variable, but it expands the RHS first.  Any\n# variable escapes ('$$') are preserved so that this recursive variable can be\n# expanded again without changing its contents.\nrun_make_test('\nbar = Goodbye\nfoo :::= $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n',\n              '', \"Goodbye\");\n\n# POSIX :::= no spaces\nrun_make_test(q!\nbar = Goodbye\nfoo:::=$(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo $(foo)\n!,\n              '', \"Goodbye\");\n\n# Variable escapes ('$$') are preserved.\nrun_make_test(q!\nbar = Good$$bye\nfoo :::= $(bar) $$what\nbar = ${ugh}\nugh = Hello\nall: ; @echo '$(foo)'\n!,\n              '', 'Good$bye $what');\n\n# Append works as expected\nrun_make_test(q!\nbar = Good$$bye\nfoo :::= $(bar)\nfoo += $$what $(bar)\nbar = ${ugh}\nugh = Hello\nall: ; @echo '$(foo)'\n!,\n              '', 'Good$bye $what Hello');\n\n# Target-specific variable\nrun_make_test(q!\nbar = Good$$bye\nall: foo :::= $(bar)\nall: ; @echo '$(foo)'\n!,\n              '', 'Good$bye');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/negative",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Run some negative tests (things that should fail).\";\n\nmy $unterm = '*** unterminated variable reference.  Stop.';\n\n# TEST #0\n# Check that non-terminated variable references are detected (and\n# reported using the best filename/lineno info\nrun_make_test('\nfoo = bar\nx = $(foo\ny = $x\n\nall: ; @echo $y\n',\n              '', \"#MAKEFILE#:3: $unterm\",\n              512);\n\n# TEST #1\n# Bogus variable value passed on the command line.\nrun_make_test(undef, ['x=$(other'], \"#MAKEFILE#:4: $unterm\", 512);\n\n# TEST #2\n# Again, but this time while reading the makefile.\nrun_make_test('\nfoo = bar\nx = $(foo\ny = $x\n\nz := $y\n\nall: ; @echo $y\n',\n              '', \"#MAKEFILE#:3: $unterm\", 512);\n\n# TEST #3\n# Bogus variable value passed on the command line.\nrun_make_test(undef, ['x=$(other'], \"#MAKEFILE#:4: $unterm\", 512);\n\nmy $nosep = '*** missing separator.  Stop.';\n\n# Whitespace not allowed in variable names\nrun_make_test('x y =', '', \"#MAKEFILE#:1: $nosep\", 512);\n\nrun_make_test('x y=', '', \"#MAKEFILE#:1: $nosep\", 512);\n\n# In theory an empty variable should be ignored, but during parsing it's a\n# real token and so this fails.  I'm not 100% sure if this is right or not.\n\nrun_make_test('x $X=', '', \"#MAKEFILE#:1: $nosep\", 512);\n\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/private",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test 'private' variables.\";\n\n$details = \"\";\n\n# 1: Simple verification that private variables are not inherited\n&run_make_test('\na:\nF = g\na: F = a\nb: private F = b\n\na b c: ; @echo $@: F=$(F)\na: b\nb: c\n',\n              '', \"c: F=a\\nb: F=b\\na: F=a\\n\");\n\n# 2: Again, but this time we start with \"b\" so \"a\"'s variable is not in scope\n&run_make_test(undef, 'b', \"c: F=g\\nb: F=b\\n\");\n\n# 3: Verification with pattern-specific variables\n&run_make_test('\nt.a:\n\nF1 = g\nF2 = g\n%.a: private F1 = a\n%.a: F2 = a\n\nt.a t.b: ; @echo $@: F1=$(F1) / F2=$(F2)\nt.a: t.b\n',\n               '', \"t.b: F1=g / F2=a\\nt.a: F1=a / F2=a\\n\");\n\n# 4: Test private global variables\n&run_make_test('\na:\nprivate F = g\nG := $(F)\na:\nb: F = b\n\na b: ; @echo $@: F=$(F) / G=$(G)\na: b\n',\n               '', \"b: F=b / G=g\\na: F= / G=g\\n\");\n\n# Exported private global variables\nrun_make_test('\nprivate export F = global\n$(info $(shell #HELPER# env F))\na: b\nb: export F=b\na b: ; @#HELPER# raw $@ env F\n',\n               '', \"F=global\\nbF=b\\naF=<unset>\");\n\n\n# 5: Multiple conditions on the same variable.  Test export.\ndelete $ENV{'_X'};\n&run_make_test('\n_X = x\na: export override private _X = a\na: ; @echo _X=$(_X) / _X=$$_X\n',\n               '', \"_X=a / _X=a\");\n\n# 6: Test override.\n&run_make_test(undef, '_X=c', \"_X=a / _X=a\\n\");\n\n# 7: Ensure keywords still work as targets\n&run_make_test('\na: export override private foo bar\nfoo bar export override private: ; @echo $@\n',\n               '', \"export\\noverride\\nprivate\\nfoo\\nbar\\n\");\n\n# 8: Ensure keywords still work as variables\n&run_make_test('\nprivate = g\na: private = a\na: b\na b: ; @echo $@=$(private)\n',\n               '', \"b=a\\na=a\\n\");\n\n# 9: make sure private suppresses inheritance\nrun_make_test(q!\nDEFS = FOO\nall: bar1\nbar1: private DEFS += 1\nbar3: private DEFS += 3\nbar1: bar2\nbar2: bar3\nbar1 bar2 bar3: ; @echo '$@: $(DEFS)'\n!,\n              '', \"bar3: FOO 3\\nbar2: FOO\\nbar1: FOO 1\\n\");\n\n# 10: Test append with pattern-specific variables and private\n\nrun_make_test(q!\nIA = global\nPA = global\nPS = global\nS = global\nPS = global\nSV = global\nb%: IA += b%\nb%: private PA += b%\nb%: private PS = b%\nbar: all\nbar: IA += bar\nbar: private PA += bar\nbar: private PS = bar\na%: IA += a%\na%: private PA += a%\na%: private PS = a%\nall: IA += all\nall: private PA += all\nall: private PS = all\n\nbar all: ; @echo '$@: IA=$(IA)'; echo '$@: PA=$(PA)'; echo '$@: PS=$(PS)'\n!,\n              '', \"all: IA=global b% bar a% all\nall: PA=global a% all\nall: PS=all\nbar: IA=global b% bar\nbar: PA=global b% bar\nbar: PS=bar\\n\");\n\n# SV 61463: Private parent variables should not be exported\n\nrun_make_test(q!\na: private export FOO := a\na: b\nb: ; @#HELPER# env FOO\n!,\n              '', 'FOO=<unset>');\n\nrun_make_test(q!\na: private export FOO := a\na: b\nb: FOO := b\nb: ; @#HELPER# env FOO\n!,\n              '', 'FOO=<unset>');\n\nrun_make_test(q!\nexport FOO := g\na: private export FOO := a\na: b\nb:\nb: ; @#HELPER# env FOO\n!,\n              '', 'FOO=g');\n\nrun_make_test(q!\nexport FOO := g\na: private export FOO := a\na: b\nb: FOO := b\nb: ; @#HELPER# env FOO\n!,\n              '', 'FOO=b');\n\nrun_make_test(q!\nprivate export FOO := g\na: private export FOO := a\na: b\nb: FOO := b\nb: ; @#HELPER# env FOO\n!,\n              '', 'FOO=<unset>');\n\n1;\n"
  },
  {
    "path": "tests/scripts/variables/special",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test special GNU Make variables.\";\n\n$details = \"\";\n\n&run_make_test('\n\nX1 := $(sort $(filter FOO BAR,$(.VARIABLES)))\n\nFOO := foo\n\nX2 := $(sort $(filter FOO BAR,$(.VARIABLES)))\n\nBAR := bar\n\nall: ; @echo X1 = $(X1); echo X2 = $(X2); echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES)))\n',\n               '', \"X1 =\\nX2 = FOO\\nLAST = BAR FOO\\n\");\n\n# SV 45728: Test that undefining a variable is reflected properly\n\n&run_make_test('\nFOO := foo\nBAR := bar\n$(info one: $(sort $(filter FOO BAR BAZ,$(.VARIABLES))))\nundefine BAR\nBAZ := baz\n$(info two: $(sort $(filter FOO BAR BAZ,$(.VARIABLES))))\nall:;@:\n',\n               '', \"one: BAR FOO\\ntwo: BAZ FOO\\n\");\n\n# $makefile2 = &get_tmpfile;\n# open(MAKEFILE, \"> $makefile2\");\n\n# print MAKEFILE <<'EOF';\n\n# X1 := $(sort $(.TARGETS))\n\n# all: foo\n#\t@echo X1 = $(X1)\n#\t@echo X2 = $(X2)\n#\t@echo LAST = $(sort $(.TARGETS))\n\n# X2 := $(sort $(.TARGETS))\n\n# foo:\n\n# EOF\n\n# close(MAKEFILE);\n\n# # TEST #2\n# # -------\n\n# &run_make_with_options($makefile2, \"\", &get_logfile);\n# $answer = \"X1 =\\nX2 = all\\nLAST = all foo\\n\";\n# &compare_output($answer, &get_logfile(1));\n\n# Test the .RECIPEPREFIX variable\n&run_make_test('\ndefine foo\n: foo-one\\\nfoo-two\n: foo-three\n\t: foo-four\nendef\n\norig: ; : orig-one\n\t: orig-two \\\norig-three \\\n\torig-four \\\n\t\torig-five \\\\\\\\\n\t: orig-six\n\t$(foo)\n\n.RECIPEPREFIX = >\ntest: ; : test-one\n>: test-two \\\ntest-three \\\n>test-four \\\n>\ttest-five \\\\\\\\\n>: test-six\n>$(foo)\n\n.RECIPEPREFIX =\nreset: ; : reset-one\n\t: reset-two \\\nreset-three \\\n\treset-four \\\n\t\treset-five \\\\\\\\\n\t: reset-six\n\t$(foo)\n',\n               'orig test reset',\n               ': orig-one\n: orig-two \\\norig-three \\\norig-four \\\n\torig-five \\\\\\\\\n: orig-six\n: foo-one foo-two\n: foo-three\n: foo-four\n: test-one\n: test-two \\\ntest-three \\\ntest-four \\\n\ttest-five \\\\\\\\\n: test-six\n: foo-one foo-two\n: foo-three\n: foo-four\n: reset-one\n: reset-two \\\nreset-three \\\nreset-four \\\n\treset-five \\\\\\\\\n: reset-six\n: foo-one foo-two\n: foo-three\n: foo-four');\n\n1;\n\n### Local Variables:\n### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))\n### End:\n"
  },
  {
    "path": "tests/scripts/variables/undefine",
    "content": "#                                                                    -*-perl-*-\n\n$description = \"Test variable undefine.\";\n\n$details = \"\";\n\n# TEST 0: basic undefine functionality\n\nrun_make_test('\na = a\nb := b\ndefine c\nc\nendef\n\n$(info $(flavor a) $(flavor b) $(flavor c))\n\nn := b\n\nundefine a\nundefine $n\nundefine c\n\n$(info $(flavor a) $(flavor b) $(flavor c))\n\n\nall: ;@:\n',\n'', \"recursive simple recursive\\nundefined undefined undefined\");\n\n\n# TEST 1: override\n\nrun_make_test('\nundefine a\noverride undefine b\n\n$(info $(flavor a) $(flavor b))\n\n\nall: ;@:\n',\n'a=a b=b', \"recursive undefined\");\n\n1;\n\n# TEST 2: undefine in eval (make sure we undefine from the global var set)\n\nrun_make_test('\ndefine undef\n$(eval undefine $$1)\nendef\n\na := a\n$(call undef,a)\n$(info $(flavor a))\n\n\nall: ;@:\n',\n'', \"undefined\");\n\n\n# TEST 3: Missing variable name\n\nrun_make_test('\na =\nundefine $a\nall: ;@echo ouch\n',\n'', \"#MAKEFILE#:3: *** empty variable name.  Stop.\\n\", 512);\n\n# Ensure that define can be a target when not appearing in a variable\n# definition context.  See SV 59870\n\nrun_make_test(q!\nundefine = undefine\n\n$(undefine) : ;@echo $@\n\n%:undefine\n\nall: undefine foo\n\n%.x : undefine\n\nfoo:;\n!,\n    '', \"undefine\\n\");\n\n1;\n"
  },
  {
    "path": "tests/scripts/vms/library",
    "content": "#                                                              -*-mode: perl-*-\n\n$description = \"Test GNU Make's VMS Library management features.\";\n\n$details = \"\\\nThis only works on VMS systems.\";\n\nreturn -1 if $osname ne 'VMS';\n\n# Help library\n$mk_string = \"help : help.hlb(file1.hlp)\\n\\n\" .\n\"file1.hlp :\\n\" .\n\"\\t\\@pipe open/write xxx file1.hlp ; write xxx \\\"1 help\\\" ; close xxx\\n\";\n\nmy $answer = \"library /replace help.hlb file1.hlp\";\n\nrun_make_test($mk_string,\n              '', $answer);\n\nunlink('help.hlb');\nunlink('file1.hlp');\n\n#Text library\n$mk_string = \"text : text.tlb(file1.txt)\\n\\n\" .\n\"file1.txt :\\n\" .\n\"\\t\\@pipe open/write xxx file1.txt ; write xxx \\\"text file\\\" ; close xxx\\n\";\n\n$answer = \"library /replace text.tlb file1.txt\";\n\nrun_make_test($mk_string,\n              '', $answer);\n\nunlink('text.tlb');\nunlink('file1.txt');\n\n\n#Macro library\n$mk_string = \"macro : macro.mlb(file1.mar)\\n\\n\" .\n\"file1.mar :\\n\" .\n\"\\tpipe open/write xxx file1.mar ; \" .\n\"write xxx \\\".macro a b\\\" ; write xxx \\\".endm\\\" ; close xxx\\n\";\n\n$answer = \"library /replace macro.mlb file1.mar\";\n\nrun_make_test($mk_string,\n              '', $answer);\n\nunlink('macro.mlb');\nunlink('file1.mar');\n\n$mk_string =\n\"all:imagelib.olb(file2.exe)\\n\" .\n\"file2.exe : file2.obj file2.opt\\n\" .\n\"\\t\\@link /share=\\$\\@ \\$\\*,\\$\\*/opt\\n\\n\" .\n\"file2.opt :\\n\" .\n\"\\t\\@pipe open/write xxx file2.opt ; \" .\n\"write xxx \\\"CASE_SENSITIVE=YES\\\" ; close xxx\\n\" .\n\"file2.c :\\n\" .\n\"\\t\\@pipe open/write xxx file2.c ; write xxx \\\"file2(){}\\\" ; close xxx\\n\";\n\n$answer = \"library /replace imagelib.olb file2.exe\";\n\nrun_make_test($mk_string,\n              '', $answer);\n\nunlink('imagelib.olb');\nunlink('file2.c');\nunlink('file2.obj');\nunlink('file2.exe');\nunlink('file2.opt');\n\n# This tells the test driver that the perl test script executed properly.\n1;\n"
  },
  {
    "path": "tests/test_driver.pl",
    "content": "#!/usr/bin/perl\n# -*-perl-*-\n#\n# Modification history:\n# Written 91-12-02 through 92-01-01 by Stephen McGee.\n# Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize.\n#\n# Copyright (C) 1991-2024 Free Software Foundation, Inc.\n# This file is part of GNU Make.\n#\n# GNU Make is free software; you can redistribute it and/or modify it under\n# the terms of the GNU General Public License as published by the Free Software\n# Foundation; either version 3 of the License, or (at your option) any later\n# version.\n#\n# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program.  If not, see <https://www.gnu.org/licenses/>.\n\n\n# Test driver routines used by a number of test suites, including\n# those for SCS, make, roll_dir, and scan_deps (?).\n#\n# this routine controls the whole mess; each test suite sets up a few\n# variables and then calls &toplevel, which does all the real work.\n\n# $Id$\n\nuse Config;\nuse Cwd;\nuse File::Spec;\nuse File::Temp;\n\n$debug = 0;                 # debug flag\n$profile = 0;               # profiling flag\n$verbose = 0;               # verbose mode flag\n$detail = 0;                # detailed verbosity\n$keep = 0;                  # keep temp files around\n\n# The number of test categories we've run\n$categories_run = 0;\n# The number of test categroies that have passed\n$categories_passed = 0;\n# The total number of individual tests that have been run\n$total_tests_run = 0;\n# The total number of individual tests that have passed\n$total_tests_passed = 0;\n# Set to true if something failed.  It could be that tests_run == tests_passed\n# even with failures, if we don't run tests for some reason.\n$some_test_failed = 0;\n# The number of tests in this category that have been run\n$tests_run = 0;\n# The number of tests in this category that have passed\n$tests_passed = 0;\n# Info on which tests failed\n@failure_info = ();\n\n$port_type = undef;\n$osname = undef;\n$vos = undef;\n$pathsep = undef;\n\n$testee = undef;\n$testee_version = undef;\n\n# Yeesh.  This whole test environment is such a hack!\n$test_passed = 1;\n\n# Timeout in seconds.  If the test takes longer than this we'll fail it.\n# This is to prevent hung tests.\n$test_timeout = 60;\n\n$diff_name = undef;\n\n# Path to Perl\n$perl_name = $^X;\nif ($^O ne 'VMS') {\n    $perl_name .= $Config{_exe} unless $perl_name =~ m/$Config{_exe}$/i;\n}\n\nsub which {\n  my $cmd = $_[0];\n\n  # Poor man's File::Which\n  my ($v,$d,$f) = File::Spec->splitpath($cmd);\n  if ($d) {\n    # The command has a pathname so don't look for it in PATH.\n    # Use forward-slashes even on Windows, else it fails in recipes.\n    (-f $cmd and -x _) or return undef;\n    $cmd =~ tr,\\\\,/,;\n    return $cmd;\n  }\n\n  my @ext;\n  if ($port_type eq 'UNIX' || $port_type eq 'VMS-DCL') {\n    @ext = ('');\n  } else {\n    @ext = index($f, '.') == -1 ? () : ('');\n    push @ext, split /;/, $ENV{PATHEXT};\n  }\n\n  foreach my $dir (File::Spec->path()) {\n    foreach my $e (@ext) {\n      my $p = File::Spec->catfile($dir, \"$cmd$e\");\n      (-f $p and -x _) or next;\n      # Use forward-slashes even on Windows, else it fails in recipes.\n      $p =~ tr,\\\\,/,;\n      return $p;\n    }\n  }\n  return undef;\n}\n\n# %makeENV is the cleaned-out environment.  Tests must not modify it.\nmy %makeENV = ();\n\nsub vms_get_process_logicals {\n  # Sorry for the long note here, but to keep this test running on\n  # VMS, it is needed to be understood.\n  #\n  # Perl on VMS by default maps the %ENV array to the system wide logical\n  # name table.\n  #\n  # This is a very large dynamically changing table.\n  # On Linux, this would be the equivalent of a table that contained\n  # every mount point, temporary pipe, and symbolic link on every\n  # file system.  You normally do not have permission to clear or replace it,\n  # and if you did, the results would be catastrophic.\n  #\n  # On VMS, added/changed %ENV items show up in the process logical\n  # name table.  So to track changes, a copy of it needs to be captured.\n\n  my $raw_output = `show log/process/access_mode=supervisor`;\n  my @raw_output_lines = split('\\n',$raw_output);\n  my %log_hash;\n  foreach my $line (@raw_output_lines) {\n    if ($line =~ /^\\s+\"([A-Za-z\\$_]+)\"\\s+=\\s+\"(.+)\"$/) {\n      $log_hash{$1} = $2;\n    }\n  }\n  return \\%log_hash\n}\n\n# %origENV is the caller's original environment\nif ($^O ne 'VMS') {\n  %origENV = %ENV;\n} else {\n  my $proc_env = vms_get_process_logicals;\n  %origENV = %{$proc_env};\n}\n\nsub resetENV\n{\n  # We used to say \"%ENV = ();\" but this doesn't work in Perl 5.000\n  # through Perl 5.004.  It was fixed in Perl 5.004_01, but we don't\n  # want to require that here, so just delete each one individually.\n\n  if ($osname ne 'VMS') {\n    foreach $v (keys %ENV) {\n      delete $ENV{$v};\n    }\n\n    %ENV = %makeENV;\n  } else {\n    my $proc_env = vms_get_process_logicals();\n    my %delta = %{$proc_env};\n    foreach my $v (keys %delta) {\n      if (exists $origENV{$v}) {\n        if ($origENV{$v} ne $delta{$v}) {\n          $ENV{$v} = $origENV{$v};\n        }\n      } else {\n        delete $ENV{$v};\n      }\n    }\n  }\n}\n\n# Returns a string-ified version of cmd which is a value provided to exec()\n# so it can either be a ref of a list or a string.\nsub cmd2str\n{\n    my @c;\n    my $cmd = $_[0];\n    if (!ref($cmd)) {\n        push @c, $cmd;\n    } else {\n        foreach (@$cmd) {\n            if (/[][#;\"*?&|<>(){}\\$`^~!]/) {\n                s/\\'/\\'\\\\'\\'/g;\n                push @c, \"'$_'\";\n            } else {\n                push @c, $_;\n            }\n        }\n    }\n\n    if ($testpath eq $cwd) {\n        return join(' ', @c);\n    }\n    return \"(cd $testpath && \" . join(' ', @c) . ')';\n}\n\nsub toplevel\n{\n  %origENV = %ENV unless $^O eq 'VMS';\n\n  # Pull in benign variables from the user's environment\n\n  foreach (# POSIX-specific things\n           'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH',\n           'LD_LIBRARY_PATH',\n           # *SAN things\n           'ASAN_OPTIONS', 'UBSAN_OPTIONS', 'LSAN_OPTIONS',\n           # Purify things\n           'PURIFYOPTIONS',\n           # Windows-specific things\n           'Path', 'SystemRoot', 'TEMP', 'TMP', 'USERPROFILE', 'PATHEXT',\n           # z/OS specific things\n           'LIBPATH', '_BPXK_AUTOCVT',\n           '_TAG_REDIR_IN',  '_TAG_REDIR_OUT',\n           # DJGPP-specific things\n           'DJDIR', 'DJGPP', 'SHELL', 'COMSPEC', 'HOSTNAME', 'LFN',\n           'FNCASE', '387', 'EMU387', 'GROUP'\n          ) {\n    $makeENV{$_} = $ENV{$_} if $ENV{$_};\n  }\n\n  # Make sure our compares are not foiled by locale differences\n\n  $makeENV{LC_ALL} = 'C';\n  $makeENV{LANG} = 'C';\n  $makeENV{LANGUAGE} = 'C';\n\n  $| = 1;                     # unbuffered output\n\n  $debug = 0;                 # debug flag\n  $profile = 0;               # profiling flag\n  $verbose = 0;               # verbose mode flag\n  $detail = 0;                # detailed verbosity\n  $keep = 0;                  # keep temp files around\n  $workdir = \"work\";          # The directory where the test will start running\n  $tempdir = \"_tmp\";          # A temporary directory\n  $scriptdir = \"scripts\";     # The directory where we find the test scripts\n  $tmpfilesuffix = \"t\";       # the suffix used on tmpfiles\n  $default_output_stack_level = 0;  # used by attach_default_output, etc.\n  $default_input_stack_level = 0;   # used by attach_default_input, etc.\n\n  &get_osname;  # sets $osname, $vos, $pathsep, and $short_filenames\n\n  # Locate the test directory.  It's the one that contains this script.\n  my @sp = File::Spec->splitpath(__FILE__);\n  $srcpath = File::Spec->canonpath(File::Spec->catpath($sp[0], $sp[1], ''));\n\n  # Locate the top source directory.\n  $toppath = File::Spec->rel2abs(File::Spec->updir(), $srcpath);\n\n  local $cwd = cwd();\n\n  $workpath = \"$workdir\";\n\n  $scriptpath = $srcpath eq $cwd ? $scriptdir : File::Spec->catdir($srcpath, $scriptdir);\n\n  $perl_name = which($perl_name);\n\n  # See if we have a diff\n  $diff_name = which('diff');\n  if (!$diff_name) {\n      print \"No diff found; differences will not be shown\\n\";\n  }\n\n  &set_defaults;  # suite-defined\n\n  &parse_command_line (@ARGV);\n\n  print \"OS name = '$osname'\\n\" if $debug;\n\n  $temppath = File::Spec->rel2abs($tempdir);\n\n  if (-d $temppath) {\n    &remove_directory_tree(\"$temppath/\")\n      or &error (\"Couldn't wipe out $temppath: $!\\n\");\n  } else {\n    mkdir ($temppath, 0777) or error (\"Cannot mkdir $temppath: $!\\n\");\n  }\n\n  # This is used by POSIX systems\n  $makeENV{TMPDIR} = $temppath;\n\n  # These are used on Windows\n  $makeENV{TMP} = $temppath;\n  $makeENV{TEMP} = $temppath;\n\n  # Replace the environment with the new one\n  resetENV();\n\n  &set_more_defaults;  # suite-defined\n\n  &print_banner;\n\n  if ($osname eq 'VMS' && $scriptpath eq $scriptdir) {\n    # Porting this script to VMS revealed a small bug in opendir() not\n    # handling search lists correctly when the directory only exists in\n    # one of the logical_devices.  Need to find the first directory in\n    # the search list, as that is where things will be written to.\n    my @dirs = split('/', $cwdpath);\n\n    my $logical_device = $ENV{$dirs[1]};\n    if ($logical_device =~ /([A-Za-z0-9_]+):(:?.+:)+/) {\n      # A search list was found.  Grab the first logical device\n      # and use it instead of the search list.\n      $dirs[1]=$1;\n      my $lcl_pwd = join('/', @dirs);\n      $workpath = $lcl_pwd . '/' . $workdir\n    }\n  }\n\n  print \"Finding tests in $scriptpath...\\n\";\n  if (-d $workpath) {\n    print \"Clearing $workpath...\\n\";\n    &remove_directory_tree(\"$workpath/\")\n      or &error (\"Couldn't wipe out $workpath: $!\\n\");\n  } else {\n    mkdir ($workpath, 0777) or &error (\"Cannot mkdir $workpath: $!\\n\");\n  }\n\n  if (!-d $scriptpath) {\n    &error (\"Failed to find $scriptpath containing perl test scripts.\\n\");\n  }\n\n  if (@TESTS) {\n    print \"Creating dirs in $workpath...\\n\";\n    foreach $test (@TESTS) {\n      if ($test =~ /^([^\\/]+)\\//) {\n        $dir = $1;\n        push (@rmdirs, $dir);\n        -d \"$workpath/$dir\"\n            or mkdir (\"$workpath/$dir\", 0777)\n            or &error (\"Couldn't mkdir $workpath/$dir: $!\\n\");\n      }\n    }\n  } else {\n    print \"Searching for tests...\\n\";\n    opendir (SCRIPTDIR, $scriptpath)\n        or &error (\"Couldn't opendir $scriptpath: $!\\n\");\n    @dirs = grep (!/^(\\..*|CVS|RCS)$/, readdir (SCRIPTDIR) );\n    closedir (SCRIPTDIR);\n    print \"Creating dirs in $workpath...\\n\";\n    foreach my $dir (@dirs) {\n      next if ($dir =~ /^(\\..*|CVS|RCS)$/ || ! -d \"$scriptpath/$dir\");\n      push (@rmdirs, $dir);\n      # VMS can have overlaid file systems, so directories may repeat.\n      next if -d \"$workpath/$dir\";\n      mkdir (\"$workpath/$dir\", 0777)\n          or &error (\"Couldn't mkdir $workpath/$dir: $!\\n\");\n      opendir (SCRIPTDIR, \"$scriptpath/$dir\")\n          or &error (\"Couldn't opendir $scriptpath/$dir: $!\\n\");\n      @files = grep (!/^(\\..*|CVS|RCS|.*~)$/, readdir (SCRIPTDIR) );\n      closedir (SCRIPTDIR);\n      foreach my $test (@files) {\n        -d $test and next;\n        push (@TESTS, \"$dir/$test\");\n      }\n    }\n  }\n\n  if (@TESTS == 0) {\n    &error (\"\\nNo tests in $scriptpath, and none were specified.\\n\");\n  }\n\n  print \"\\n\";\n\n  run_all_tests();\n\n  foreach my $dir (@rmdirs) {\n    rmdir (\"$workpath/$dir\");\n  }\n  rmdir ($workpath);\n\n  rmdir ($temppath);\n\n  $| = 1;\n\n  $categories_failed = $categories_run - $categories_passed;\n  $total_tests_failed = $total_tests_run - $total_tests_passed;\n\n  if ($total_tests_failed) {\n    print \"\\n$total_tests_failed Test\";\n    print \"s\" unless $total_tests_failed == 1;\n    print \" in $categories_failed Categor\";\n    print ($categories_failed == 1 ? \"y\" : \"ies\");\n    print \" Failed :-(\\n\\n\";\n    my $i = 0;\n    for my $e (@failure_info) {\n        ++$i;\n        print \"  Failure $i:\\n\";\n        print \"    run:  $e->{'run'}\\n\" if exists($e->{'run'});\n        print \"    base: $e->{'base'}\\n\";\n        print \"    diff: $e->{'diff'}\\n\" if exists($e->{'diff'});\n    }\n    return 0;\n  }\n\n  if ($some_test_failed) {\n      # Something failed but no tests were marked failed... probably a syntax\n      # error in a test script\n    print \"\\nSome tests failed (See output for details) :-(\\n\\n\";\n    return 0;\n  }\n\n  print \"\\n$total_tests_passed Test\";\n  print \"s\" unless $total_tests_passed == 1;\n  print \" in $categories_passed Categor\";\n  print ($categories_passed == 1 ? \"y\" : \"ies\");\n  print \" Complete ... No Failures :-)\\n\\n\";\n  return 1;\n}\n\nsub get_osname\n{\n  # Set up an initial value.  In perl5 we can do it the easy way.\n  $osname = defined($^O) ? $^O : '';\n  $vos = 0;\n  $pathsep = \"/\";\n\n  # find the type of the port.  We do this up front to have a single\n  # point of change if it needs to be tweaked.\n  #\n  # This is probably not specific enough.\n  #\n  if ($osname =~ /MSWin32/i || $osname =~ /Windows/i || $osname =~ /msys/i\n      || $osname =~ /MINGW32/i || $osname =~ /CYGWIN_NT/i) {\n    $port_type = 'W32';\n  }\n  # Bleah, the osname is so variable on DOS.  This kind of bites.\n  # Well, as far as I can tell if we check for some text at the\n  # beginning of the line with either no spaces or a single space, then\n  # a D, then either \"OS\", \"os\", or \"ev\" and a space.  That should\n  # match and be pretty specific.\n  elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) {\n    $port_type = 'DOS';\n  }\n  # Check for OS/2\n  elsif ($osname =~ m%OS/2%) {\n    $port_type = 'OS/2';\n  }\n  # VMS has a GNV Unix mode or a DCL mode.\n  # The SHELL environment variable should not be defined in VMS-DCL mode.\n  elsif ($osname eq 'VMS' && !defined $ENV{\"SHELL\"}) {\n    $port_type = 'VMS-DCL';\n  }\n  # Everything else, right now, is UNIX.  Note that we should integrate\n  # the VOS support into this as well and get rid of $vos\n  else {\n    $port_type = 'UNIX';\n  }\n\n  if ($osname eq 'VMS') {\n    return;\n  }\n\n  # Find a path to Perl\n\n  # See if the filesystem supports long file names with multiple\n  # dots.  DOS doesn't.\n  $short_filenames = 0;\n  (open (TOUCHFD, '>', 'fancy.file.name') and close (TOUCHFD))\n      or $short_filenames = 1;\n  unlink (\"fancy.file.name\") or $short_filenames = 1;\n\n  if (! $short_filenames) {\n    # Thanks go to meyering@cs.utexas.edu (Jim Meyering) for suggesting a\n    # better way of doing this.  (We used to test for existence of a /mnt\n    # dir, but that apparently fails on an SGI Indigo (whatever that is).)\n    # Because perl on VOS translates /'s to >'s, we need to test for\n    # VOSness rather than testing for Unixness (ie, try > instead of /).\n\n    mkdir (\".ostest\", 0777) or &error (\"Couldn't create .ostest: $!\\n\", 1);\n    open (TOUCHFD, \"> .ostest>ick\") and close (TOUCHFD);\n    chdir (\".ostest\") or &error (\"Couldn't chdir to .ostest: $!\\n\", 1);\n  }\n\n  if (! $short_filenames && -f \"ick\") {\n    $osname = \"vos\";\n    $vos = 1;\n    $pathsep = \">\";\n\n  } elsif ($osname eq '') {\n    # the following is regrettably gnarly, but it seems to be the only way\n    # to not get ugly error messages if uname can't be found.\n    # Hmmm, BSD/OS 2.0's uname -a is excessively verbose.  Let's try it\n    # with switches first.\n    eval \"chop (\\$osname = `sh -c 'uname -nmsr 2>&1'`)\";\n    if ($osname =~ /not found/i) {\n      $osname = \"(something posixy with no uname)\";\n\n    } elsif ($@ ne \"\" || $?) {\n      eval \"chop (\\$osname = `sh -c 'uname -a 2>&1'`)\";\n      if ($@ ne \"\" || $?) {\n        $osname = \"(something posixy)\";\n      }\n    }\n  }\n\n  if (! $short_filenames) {\n    chdir (\"..\") or &error (\"Couldn't chdir to ..: $!\\n\", 1);\n    unlink (\".ostest>ick\");\n    rmdir (\".ostest\") or &error (\"Couldn't rmdir .ostest: $!\\n\", 1);\n  }\n}\n\nsub parse_command_line\n{\n  @argv = @_;\n\n  # use @ARGV if no args were passed in\n\n  if (@argv == 0) {\n    @argv = @ARGV;\n  }\n\n  # look at each option; if we don't recognize it, maybe the suite-specific\n  # command line parsing code will...\n\n  while (@argv) {\n    $option = shift @argv;\n    if ($option =~ /^-usage$/i) {\n      &print_usage;\n      exit 0;\n    }\n    if ($option =~ /^-(h|help)$/i) {\n      &print_help;\n      exit 0;\n    }\n\n    if ($option =~ /^-debug$/i) {\n      print \"\\nDEBUG ON\\n\";\n      $debug = 1;\n\n    } elsif ($option =~ /^-profile$/i) {\n      $profile = 1;\n\n    } elsif ($option =~ /^-verbose$/i) {\n      $verbose = 1;\n\n    } elsif ($option =~ /^-detail$/i) {\n      $detail = 1;\n      $verbose = 1;\n\n    } elsif ($option =~ /^-keep$/i) {\n      $keep = 1;\n\n    } elsif (&valid_option($option)) {\n      # The suite-defined subroutine takes care of the option\n\n    } elsif ($option =~ /^-/) {\n      print \"Invalid option: $option\\n\";\n      &print_usage;\n      exit 0;\n\n    } else { # must be the name of a test\n      $option =~ s/\\.pl$//;\n      push(@TESTS,$option);\n    }\n  }\n}\n\nsub max\n{\n  my $num = shift @_;\n  my $newnum;\n\n  while (@_) {\n    $newnum = shift @_;\n    if ($newnum > $num) {\n      $num = $newnum;\n    }\n  }\n\n  return $num;\n}\n\nsub print_centered\n{\n  my ($width, $string) = @_;\n\n  if (length ($string)) {\n    my $pad = \" \" x ( ($width - length ($string) + 1) / 2);\n    print \"$pad$string\";\n  }\n}\n\nsub print_banner\n{\n  # $testee is suite-defined\n  my $info = \"Running tests for $testee on $osname\";\n  my $len = &max (length($info), length($testee_version), 77) + 2;\n  my $line = (\"-\" x $len) . \"\\n\";\n\n  &print_centered ($len, $line);\n  &print_centered ($len, $info.\"\\n\");\n  &print_centered ($len, $testee_version);\n  &print_centered ($len, $line);\n  print \"\\n\";\n}\n\nsub run_all_tests\n{\n  # Make sure we always run the tests from the current directory\n  unshift(@INC, cwd());\n\n  $categories_run = 0;\n\n  # Make a copy of STDIN so we can reset it\n  open(INCOPY, \"<&STDIN\");\n\n  # Leave enough space in the extensions to append a number, even\n  # though it needs to fit into 8+3 limits.\n  if ($short_filenames) {\n    $logext = 'l';\n    $diffext = 'd';\n    $baseext = 'b';\n    $runext = 'r';\n    $extext = '';\n  } else {\n    $logext = 'log';\n    $diffext = 'diff';\n    $baseext = 'base';\n    $runext = 'run';\n    $extext = $osname eq 'VMS' ? '_' : '.';\n  }\n\n  $lasttest = '';\n  # $testname is published\n  foreach $testname (sort @TESTS) {\n    # Skip duplicates on VMS caused by logical name search lists.\n    next if $testname eq $lasttest;\n\n    $lasttest = $testname;\n    $suite_passed = 1;       # reset by test on failure\n    $num_of_logfiles = 0;\n    $num_of_tmpfiles = 0;\n    $description = \"\";\n    $details = \"\";\n    $old_makefile = undef;\n    $testname =~ s/^$scriptpath$pathsep//;\n    $testname =~ s/(\\.pl|\\.perl)$//;\n\n    $perl_testname = File::Spec->catfile($scriptpath, $testname);\n    -f $perl_testname or die \"Invalid test: $testname\\n\\n\";\n\n    local $testpath = File::Spec->catdir($workpath, $testname);\n\n    remove_directory_tree($testpath);\n    mkdir($testpath, 0777) or &error(\"Couldn't mkdir $testpath: $!\\n\", 1);\n\n    setup_for_test();\n\n    $output = \"........................................................ \";\n\n    substr($output, 0, length($testname)) = \"$testname \";\n\n    print $output;\n\n    $tests_run = 0;\n    $tests_passed = 0;\n\n    # Run the test!\n    chdir($testpath) or error(\"Can't change to $testpath: $!\\n\", 1);\n    $code = do $perl_testname;\n    chdir($cwd) or error(\"Can't change back to $cwd: $!\\n\", 1);\n\n    # Reset STDIN from the copy in case it was changed\n    open(STDIN, \"<&INCOPY\");\n\n    ++$categories_run;\n    $total_tests_run += $tests_run;\n    $total_tests_passed += $tests_passed;\n\n    # How did it go?\n    if (!defined($code)) {\n      # Failed to parse or called die\n      if (length ($@)) {\n        warn \"\\n*** Test died ($testname): $@\\n\";\n      } else {\n        warn \"\\n*** Couldn't parse $perl_testname\\n\";\n      }\n      $status = \"FAILED ($tests_passed/$tests_run passed)\";\n      $some_test_failed = 1;\n\n    } elsif ($code == -1) {\n      # Skipped... not supported\n      $status = \"N/A\";\n      --$categories_run;\n      remove_directory_tree($testpath);\n\n    } elsif ($code != 1) {\n      # Bad result... this shouldn't really happen.  Usually means that\n      # the suite forgot to end with \"1;\".\n      warn \"\\n*** Test returned $code\\n\";\n      $status = \"FAILED ($tests_passed/$tests_run passed)\";\n      $some_test_failed = 1;\n\n    } elsif ($tests_run == 0) {\n      # Nothing was done!!\n      $status = \"FAILED (no tests found!)\";\n      $some_test_failed = 1;\n\n    } elsif ($tests_run > $tests_passed) {\n      # Lose!\n      $status = \"FAILED ($tests_passed/$tests_run passed)\";\n      $some_test_failed = 1;\n\n    } else {\n      # Win!\n      ++$categories_passed;\n      $status = \"ok     ($tests_passed passed)\";\n\n      # Clean up\n      if (!$keep) {\n        remove_directory_tree($testpath);\n      }\n    }\n\n    # If the verbose option has been specified, then a short description\n    # of each test is printed before displaying the results of each test\n    # describing WHAT is being tested.\n\n    if ($verbose) {\n      if ($detail) {\n        print \"\\nWHAT IS BEING TESTED\\n\";\n        print \"--------------------\";\n      }\n      print \"\\n\\n$description\\n\\n\";\n    }\n\n    # If the detail option has been specified, then the details of HOW\n    # the test is testing what it says it is testing in the verbose output\n    # will be displayed here before the results of the test are displayed.\n\n    if ($detail) {\n      print \"\\nHOW IT IS TESTED\\n\";\n      print \"----------------\";\n      print \"\\n\\n$details\\n\\n\";\n    }\n\n    print \"$status\\n\";\n  }\n\n  close(INCOPY);\n}\n\n# Deletes all filenames that are sent to it.\n\nsub rmfiles\n{\n  return (unlink @_);\n}\n\nsub print_standard_usage\n{\n  my ($plname, @moreusage) = @_;\n\n  print \"usage:\\t$plname [testname] [-verbose] [-detail] [-keep]\\n\";\n  print \"\\t\\t\\t[-profile] [-usage] [-help] [-debug]\\n\";\n  foreach (@moreusage) {\n    print \"\\t\\t\\t$_\\n\";\n  }\n}\n\nsub print_standard_help\n{\n  my (@morehelp) = @_;\n  my $t = \"      \";\n\n  my $line = \"Test Driver For $testee\";\n  print \"$line\\n\";\n  $line = \"=\" x length ($line);\n  print \"$line\\n\";\n\n  print_usage();\n\n  print \"\\ntestname\\n\"\n      . \"${t}You may, if you wish, run only ONE test if you know the name\\n\"\n      . \"${t}of that test and specify this name anywhere on the command\\n\"\n      . \"${t}line.  Otherwise ALL existing tests in the scripts directory\\n\"\n      . \"${t}will be run.\\n\"\n      . \"-verbose\\n\"\n      . \"${t}If this option is given, a description of every test is\\n\"\n      . \"${t}displayed before the test is run. (Not all tests may have\\n\"\n      . \"${t}descriptions at this time)\\n\"\n      . \"-detail\\n\"\n      . \"${t}If this option is given, a detailed description of every\\n\"\n      . \"${t}test is displayed before the test is run. (Not all tests\\n\"\n      . \"${t}have descriptions at this time)\\n\"\n      . \"-profile\\n\"\n      . \"${t}If this option is given, then the profile file\\n\"\n      . \"${t}is added to other profiles every time $testee is run.\\n\"\n      . \"${t}This option only works on VOS at this time.\\n\"\n      . \"-keep\\n\"\n      . \"${t}You may give this option if you DO NOT want ANY\\n\"\n      . \"${t}of the files generated by the tests to be deleted. \\n\"\n      . \"${t}Without this option, all files generated by the test will\\n\"\n      . \"${t}be deleted IF THE TEST PASSES.\\n\"\n      . \"-debug\\n\"\n      . \"${t}Use this option if you would like to see all of the system\\n\"\n      . \"${t}calls issued and their return status while running the tests\\n\"\n      . \"${t}This can be helpful if you're having a problem adding a test\\n\"\n      . \"${t}to the suite, or if the test fails!\\n\";\n\n  foreach $line (@morehelp) {\n    my $tline = $line;\n    if (substr ($tline, 0, 1) eq \"\\t\") {\n      substr ($tline, 0, 1) = $t;\n    }\n    print \"$tline\\n\";\n  }\n}\n\n#######################################################################\n###########         Generic Test Driver Subroutines         ###########\n#######################################################################\n\nsub get_caller\n{\n  my $depth = defined ($_[0]) ? $_[0] : 1;\n  my ($pkg, $filename, $linenum) = caller ($depth + 1);\n  return \"$filename: $linenum\";\n}\n\nsub error\n{\n  my $message = $_[0];\n  my $caller = &get_caller (1);\n\n  if (defined ($_[1])) {\n    $caller = &get_caller ($_[1] + 1) . \" -> $caller\";\n  }\n\n  die \"$caller: $message\";\n}\n\nsub compare_answer_vms\n{\n  my ($kgo, $log) = @_;\n\n  # VMS has extra blank lines in output sometimes.\n  # Ticket #41760\n  $log =~ s/\\n\\n+/\\n/gm;\n  $log =~ s/\\A\\n+//g;\n  return 1 if ($kgo eq $log);\n\n  # VMS adding a \"Waiting for unfinished jobs...\"\n  # Remove it for now to see what else is going on.\n  $log =~ s/^.+\\*\\*\\* Waiting for unfinished jobs.+$//m;\n  $log =~ s/\\n\\n/\\n/gm;\n  $log =~ s/^\\n+//gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS wants target device to exist or generates an error,\n  # Some test targets look like VMS devices and trip this.\n  $log =~ s/^.+\\: no such device or address.*$//gim;\n  $log =~ s/\\n\\n/\\n/gm;\n  $log =~ s/^\\n+//gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS error message has a different case\n  $log =~ s/no such file /No such file /gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS is putting comas instead of spaces in output\n  $log =~ s/,/ /gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS Is sometimes adding extra leading spaces to output?\n  {\n     (my $mlog = $log) =~ s/^ +//gm;\n     return 1 if ($mlog eq $kgo);\n  }\n\n  # VMS port not handling POSIX encoded child status\n  # Translate error case it for now.\n  $log =~ s/0x1035a00a/1/gim;\n  return 1 if ($log =~ /\\Q$kgo\\E/i);\n\n  $log =~ s/0x1035a012/2/gim;\n  return 1 if ($log eq $kgo);\n\n  # Tests are using a UNIX null command, temp hack\n  # until this can be handled by the VMS port.\n  # ticket # 41761\n  $log =~ s/^.+DCL-W-NOCOMD.*$//gim;\n  $log =~ s/\\n\\n+/\\n/gm;\n  $log =~ s/^\\n+//gm;\n  return 1 if ($log eq $kgo);\n\n  # Tests are using exit 0;\n  # this generates a warning that should stop the make, but does not\n  $log =~ s/^.+NONAME-W-NOMSG.*$//gim;\n  $log =~ s/\\n\\n+/\\n/gm;\n  $log =~ s/^\\n+//gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS is sometimes adding single quotes to output?\n  $log =~ s/\\'//gm;\n  return 1 if ($log eq $kgo);\n\n  # And missing an extra space in output\n  $kgo =~ s/\\h\\h+/ /gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS adding ; to end of some lines.\n  $log =~ s/;\\n/\\n/gm;\n  return 1 if ($log eq $kgo);\n\n  # VMS adding trailing space to end of some quoted lines.\n  $log =~ s/\\h+\\n/\\n/gm;\n  return 1 if ($log eq $kgo);\n\n  # And VMS missing leading blank line\n  $kgo =~ s/\\A\\n//g;\n  return 1 if ($log eq $kgo);\n\n  # Unix double quotes showing up as single quotes on VMS.\n  $kgo =~ s/\\\"//g;\n  return 1 if ($log eq $kgo);\n\n  return 0;\n}\n\nsub convert_answer_zos\n{\n  my ($log) = @_;\n\n  # z/OS emits \"Error 143\" or \"SIGTERM\" instead of terminated\n  $log =~ s/Error 143/Terminated/igm;\n  $log =~ s/SIGTERM/Terminated/igm;\n\n  # z/OS error messages have a prefix\n  $log =~ s/EDC5129I No such file or directory\\./No such file or directory/igm;\n  $log =~ s/FSUM7351 not found/not found/igm;\n\n  return $log;\n}\n\nsub compare_answer\n{\n  my ($kgo, $log) = @_;\n  my ($mkgo, $mlog);\n\n  # For make, get rid of any time skew error before comparing--too bad this\n  # has to go into the \"generic\" driver code :-/\n  $log =~ s/^.*modification time .*in the future.*\\n//igm;\n  $log =~ s/^.*clock skew detected.*\\n//igm;\n  return 1 if ($log eq $kgo);\n\n  # Get rid of newline differences, forever\n  $kgo =~ s,\\r\\n,\\n,gs;\n  $log =~ s,\\r\\n,\\n,gs;\n  return 1 if ($log eq $kgo);\n\n  # Keep the originals in case it's a regex\n  $mkgo = $kgo;\n  $mlog = $log;\n\n  # z/OS has quirky outputs\n  if ($osname eq 'os390') {\n    $mlog = convert_answer_zos($mlog);\n    return 1 if ($mlog eq $kgo);\n  }\n\n  # Some versions of Perl on Windows use /c instead of C:\n  $mkgo =~ s,\\b([A-Z]):,/\\L$1,g;\n  $mlog =~ s,\\b([A-Z]):,/\\L$1,g;\n  return 1 if ($mlog eq $mkgo);\n\n  # See if it is a backslash problem (only on W32?)\n  $mkgo =~ tr,\\\\,/,;\n  $mlog =~ tr,\\\\,/,;\n  return 1 if ($mlog eq $mkgo);\n\n  # VMS is a whole thing...\n  return 1 if ($osname eq 'VMS' && compare_answer_vms($kgo, $log));\n\n  # See if the answer might be a regex.\n  if ($kgo =~ m,^/(.+)/$,) {\n    # Check the regex against both the original and modified strings\n    return 1 if ($log =~ /$1/);\n    return 1 if ($mlog =~ /$1/);\n  }\n\n  return 0;\n}\n\nmy %old_tempfiles = ();\n\nsub compare_output\n{\n  my ($answer, $logfile) = @_;\n  my ($slurp, $matched, $extra) = ('', 0, 0);\n\n  ++$tests_run;\n\n  # Check to see if any temporary files were leftover after the run completes\n  my @tf = ();\n  foreach my $file (glob(File::Spec->catfile($temppath, \"*\"))) {\n    if (!exists $old_tempfiles{$file}) {\n      push @tf, $file;\n      $old_tempfiles{$file} = 1;\n    }\n  }\n  if (@tf) {\n    open (LOGFILE, '>>', $logfile) or die \"Cannot open log file $logfile: $!\\n\";\n    print LOGFILE \"Leftover temporary files: @tf\\n\";\n    close (LOGFILE);\n    $extra = 1;\n  }\n\n  if (! defined $answer) {\n    print \"Ignoring output ........ \" if $debug;\n    $matched = 1;\n  } else {\n    print \"Comparing output ........ \" if $debug;\n    $matched = compare_answer($answer, &read_file_into_string ($logfile));\n  }\n\n  my $base = get_basefile();\n  my $run = get_runfile();\n  my $diff = get_difffile();\n\n  my %e = ('base' => File::Spec->catdir($testpath, $base));\n\n  if (! $matched) {\n    &create_file($base, $answer);\n    &create_file($run, $command_string);\n    $e{'run'} = File::Spec->catdir($testpath, $run);\n  }\n\n  if ($matched && $test_passed && !$extra) {\n    print \"ok\\n\" if $debug;\n    ++$tests_passed;\n    return 1;\n  }\n\n  if (! $matched) {\n    # Create the difference file\n    if ($diff_name) {\n        run_command_with_output($diff, \"$diff_name -c $base $logfile\");\n    } else {\n        create_file($diff, \"Log file $logfile differs from base file $base\\n\");\n    }\n\n    $e{'diff'} = File::Spec->catdir($testpath, $diff);\n  }\n\n  push @failure_info, \\%e;\n\n  return 0;\n}\n\nsub read_file_into_string\n{\n  my ($filename) = @_;\n  my $oldslash = $/;\n  undef $/;\n\n  open (RFISFILE, '<', $filename) or return \"\";\n  my $slurp = <RFISFILE>;\n  close (RFISFILE);\n\n  $/ = $oldslash;\n\n  return $slurp;\n}\n\nmy @OUTSTACK = ();\nmy @ERRSTACK = ();\n\nsub attach_default_output\n{\n  my ($filename) = @_;\n\n  if ($vos)\n  {\n    my $code = system \"++attach_default_output_hack $filename\";\n    $code == -2 or &error (\"ado death\\n\", 1);\n    return 1;\n  }\n\n  my $dup = undef;\n  open($dup, '>&', STDOUT) or error(\"ado: $! duping STDOUT\\n\", 1);\n  push @OUTSTACK, $dup;\n\n  $dup = undef;\n  open($dup, '>&', STDERR) or error(\"ado: $! duping STDERR\\n\", 1);\n  push @ERRSTACK, $dup;\n\n  open(STDOUT, '>', $filename) or error(\"ado: $filename: $!\\n\", 1);\n  open(STDERR, \">&STDOUT\") or error(\"ado: $filename: $!\\n\", 1);\n}\n\n# close the current stdout/stderr, and restore the previous ones from\n# the \"stack.\"\n\nsub detach_default_output\n{\n  if ($vos)\n  {\n    my $code = system \"++detach_default_output_hack\";\n    $code == -2 or &error (\"ddoh death\\n\", 1);\n    return 1;\n  }\n\n  @OUTSTACK or error(\"default output stack has flown under!\\n\", 1);\n\n  close(STDOUT);\n  close(STDERR) unless $osname eq 'VMS';\n\n\n  open (STDOUT, '>&', pop @OUTSTACK) or error(\"ddo: $! duping STDOUT\\n\", 1);\n  open (STDERR, '>&', pop @ERRSTACK) or error(\"ddo: $! duping STDERR\\n\", 1);\n}\n\nsub _run_with_timeout\n{\n  my $code;\n  if ($osname eq 'VMS') {\n    #local $SIG{ALRM} = sub {\n    #    my $e = $ERRSTACK[0];\n    #    print $e \"\\nTest timed out after $test_timeout seconds\\n\";\n    #    die \"timeout\\n\";\n    #};\n    #alarm $test_timeout;\n    system(@_);\n    #alarm 0;\n    my $severity = ${^CHILD_ERROR_NATIVE} & 7;\n    $code = 0;\n    if (($severity & 1) == 0) {\n      $code = 512;\n    }\n\n    # Get the vms status.\n    my $vms_code = ${^CHILD_ERROR_NATIVE};\n\n    # Remove the print status bit\n    $vms_code &= ~0x10000000;\n\n    # Posix code translation.\n    if (($vms_code & 0xFFFFF000) == 0x35a000) {\n      $code = (($vms_code & 0xFFF) >> 3) * 256;\n    }\n\n  } elsif ($port_type eq 'W32' && $^O ne 'msys') {\n    # Using ActiveState Perl (?)\n    my $pid = system(1, @_);\n    $pid > 0 or die \"Cannot execute $_[0]: $!\\n\";\n    local $SIG{ALRM} = sub {\n      my $e = $ERRSTACK[0];\n      print $e \"\\nTest timed out after $test_timeout seconds\\n\";\n      kill -9, $pid;\n      die \"timeout\\n\";\n    };\n    alarm $test_timeout;\n    my $r = waitpid($pid, 0);\n    alarm 0;\n    $r == -1 and die \"No such pid: $pid\\n\";\n    # This shouldn't happen since we wait forever or timeout via SIGALRM\n    $r == 0 and die \"No process exited.\\n\";\n    $code = $?;\n\n  } else {\n    my $pid = fork();\n    if (! $pid) {\n      exec(@_) or die \"exec: Cannot execute $_[0]: $!\\n\";\n    }\n    local $SIG{ALRM} = sub {\n      my $e = $ERRSTACK[0];\n      print $e \"\\nTest timed out after $test_timeout seconds\\n\";\n      # Resend the alarm to our process group to kill the children.\n      $SIG{ALRM} = 'IGNORE';\n      kill -14, $$;\n      die \"timeout\\n\";\n    };\n    alarm $test_timeout;\n    my $r = waitpid($pid, 0);\n    alarm 0;\n    $r == -1 and die \"No such pid: $pid\\n\";\n    # This shouldn't happen since we wait forever or timeout via SIGALRM\n    $r == 0 and die \"No process exited.\\n\";\n    $code = $?;\n  }\n\n  return $code;\n}\n\n# This runs a command without any debugging info.\nsub _run_command\n{\n  my $orig = $SIG{ALRM};\n  my $code = eval { _run_with_timeout(@_); };\n  $SIG{ALRM} = $orig;\n\n  # Reset then environment so that it's clean for the next test.\n  resetENV();\n\n  if ($@) {\n    # The eval failed.  If it wasn't SIGALRM then die.\n    $@ eq \"timeout\\n\" or die \"Command failed: $@\";\n    $code = 14;\n  }\n\n  return $code;\n}\n\n# run one command (passed as a list of arg 0 - n), returning 0 on success\n# and nonzero on failure.\n\nsub run_command\n{\n  print \"\\nrun_command: @_\\n\" if $debug;\n  my $code = _run_command(@_);\n  print \"run_command returned $code.\\n\" if $debug;\n  print \"vms status = ${^CHILD_ERROR_NATIVE}\\n\" if $debug and $osname eq 'VMS';\n  return $code;\n}\n\n# run one command (passed as a list of arg 0 - n, with arg 0 being the\n# second arg to this routine), returning 0 on success and non-zero on failure.\n# The first arg to this routine is a filename to connect to the stdout\n# & stderr of the child process.\n\nsub run_command_with_output\n{\n  my $filename = shift;\n\n  print \"\\nrun_command_with_output($filename,$runname): @_\\n\" if $debug;\n  &attach_default_output ($filename);\n  my $code = eval { _run_command(@_) };\n  my $err = $@;\n  &detach_default_output;\n\n  $err and die $err;\n\n  print \"run_command_with_output returned $code.\\n\" if $debug;\n  print \"vms status = ${^CHILD_ERROR_NATIVE}\\n\" if $debug and $osname eq 'VMS';\n  return $code;\n}\n\n# performs the equivalent of an \"rm -rf\" on the first argument.  Like\n# rm, if the path ends in /, leaves the (now empty) directory; otherwise\n# deletes it, too.\n\nsub remove_directory_tree\n{\n  my ($targetdir) = @_;\n  my ($nuketop) = 1;\n\n  my $ch = substr ($targetdir, length ($targetdir) - 1);\n  if ($ch eq \"/\" || $ch eq $pathsep) {\n    $targetdir = substr ($targetdir, 0, length ($targetdir) - 1);\n    $nuketop = 0;\n  }\n\n  -e $targetdir or return 1;\n\n  &remove_directory_tree_inner (\"RDT00\", $targetdir) or return 0;\n  if ($nuketop && !rmdir ($targetdir)) {\n    print \"Cannot remove $targetdir: $!\\n\";\n    return 0;\n  }\n\n  return 1;\n}\n\nsub remove_directory_tree_inner\n{\n  my ($dirhandle, $targetdir) = @_;\n\n  opendir ($dirhandle, $targetdir) or return 0;\n  my $subdirhandle = $dirhandle;\n  $subdirhandle++;\n  while (my $object = readdir ($dirhandle)) {\n    $object =~ /^(\\.\\.?|CVS|RCS)$/ and next;\n    $object = \"$targetdir$pathsep$object\";\n\n    lstat ($object);\n    if (-d _ && &remove_directory_tree_inner ($subdirhandle, $object)) {\n      if (!rmdir($object)) {\n        print \"Cannot remove $object: $!\\n\";\n        return 0;\n      }\n    } else {\n      if ($osname ne 'VMS') {\n        if (!unlink $object) {\n          print \"Cannot unlink $object: $!\\n\";\n          return 0;\n        }\n      } else {\n        # VMS can have multiple versions of a file.\n        1 while unlink $object;\n      }\n    }\n  }\n  closedir ($dirhandle);\n  return 1;\n}\n\n# We used to use this behavior for this function:\n#\n#sub touch\n#{\n#  my (@filenames) = @_;\n#  my $now = time;\n#\n#  foreach my $file (@filenames) {\n#    utime ($now, $now, $file)\n#          or (open (TOUCHFD, '>>', $file) and close (TOUCHFD))\n#               or &error (\"Couldn't touch $file: $!\\n\", 1);\n#  }\n#  return 1;\n#}\n#\n# But this behaves badly on networked filesystems where the time is\n# skewed, because it sets the time of the file based on the _local_\n# host.  Normally when you modify a file, it's the _remote_ host that\n# determines the modtime, based on _its_ clock.  So, instead, now we open\n# the file and write something into it to force the remote host to set\n# the modtime correctly according to its clock.\n#\n\nsub touch\n{\n  foreach my $file (@_) {\n    (open(T, '>>', $file) and print(T \"\\n\") and close(T))\n        or &error(\"Couldn't touch $file: $!\\n\", 1);\n  }\n\n  return @_;\n}\n\n# Touch with a time offset.  To DTRT, call touch() then use stat() to get the\n# access/mod time for each file and apply the offset.\n\nsub utouch\n{\n  my $off = shift;\n\n  &touch(@_);\n\n  foreach my $f (@_) {\n      my @s = stat($f);\n      utime($s[8]+$off, $s[9]+$off, $f);\n  }\n\n  return @_;\n}\n\n# open a file, write some stuff to it, and close it.\n\nsub create_file\n{\n  my ($filename, @lines) = @_;\n\n  open (CF, '>', $filename) or &error (\"Couldn't open '$filename': $!\\n\", 1);\n  foreach $line (@lines) {\n    print CF $line;\n  }\n  close (CF);\n}\n\n# create a directory tree described by an associative array, wherein each\n# key is a relative pathname (using slashes) and its associated value is\n# one of:\n#    DIR            indicates a directory\n#    FILE:contents  indicates a file, which should contain contents +\\n\n#    LINK:target    indicates a symlink, pointing to $basedir/target\n# The first argument is the dir under which the structure will be created\n# (the dir will be made and/or cleaned if necessary); the second argument\n# is the associative array.\n\nsub create_dir_tree\n{\n  my ($basedir, %dirtree) = @_;\n\n  &remove_directory_tree (\"$basedir\");\n  mkdir ($basedir, 0777) or &error (\"Couldn't mkdir $basedir: $!\\n\", 1);\n\n  foreach my $path (sort keys (%dirtree)) {\n    if ($dirtree {$path} =~ /^DIR$/) {\n      mkdir (\"$basedir/$path\", 0777)\n          or &error (\"Couldn't mkdir $basedir/$path: $!\\n\", 1);\n\n    } elsif ($dirtree {$path} =~ /^FILE:(.*)$/) {\n      &create_file (\"$basedir/$path\", $1 . \"\\n\");\n\n    } elsif ($dirtree {$path} =~ /^LINK:(.*)$/) {\n      symlink (\"$basedir/$1\", \"$basedir/$path\")\n          or &error (\"Couldn't symlink $basedir/$path -> $basedir/$1: $!\\n\", 1);\n\n    } else {\n      &error (\"Bogus dirtree type: \\\"$dirtree{$path}\\\"\\n\", 1);\n    }\n  }\n  if ($just_setup_tree) {\n    die \"Tree is setup...\\n\";\n  }\n}\n\n# compare a directory tree with an associative array in the format used\n# by create_dir_tree, above.\n# The first argument is the dir under which the structure should be found;\n# the second argument is the associative array.\n\nsub compare_dir_tree\n{\n  my ($basedir, %dirtree) = @_;\n  my $bogus = 0;\n\n  opendir (DIR, $basedir) or &error (\"Couldn't open $basedir: $!\\n\", 1);\n  my @allfiles = grep (!/^(\\.\\.?|CVS|RCS)$/, readdir (DIR) );\n  closedir (DIR);\n  if ($debug) {\n    print \"dirtree: (%dirtree)\\n$basedir: (@allfiles)\\n\";\n  }\n\n  foreach my $path (sort keys (%dirtree))\n  {\n    if ($debug) {\n      print \"Checking $path ($dirtree{$path}).\\n\";\n    }\n\n    my $found = 0;\n    foreach my $i (0 .. $#allfiles) {\n      if ($allfiles[$i] eq $path) {\n        splice (@allfiles, $i, 1);  # delete it\n        if ($debug) {\n          print \"     Zapped $path; files now (@allfiles).\\n\";\n        }\n        lstat (\"$basedir/$path\");\n        $found = 1;\n        last;\n      }\n    }\n\n    if (!$found) {\n      print \"compare_dir_tree: $path does not exist.\\n\";\n      $bogus = 1;\n      next;\n    }\n\n    if ($dirtree {$path} =~ /^DIR$/) {\n      if (-d _ && opendir (DIR, \"$basedir/$path\") ) {\n        my @files = readdir (DIR);\n        closedir (DIR);\n        @files = grep (!/^(\\.\\.?|CVS|RCS)$/ && ($_ = \"$path/$_\"), @files);\n        push (@allfiles, @files);\n        if ($debug)\n        {\n          print \"     Read in $path; new files (@files).\\n\";\n        }\n\n      } else {\n        print \"compare_dir_tree: $path is not a dir.\\n\";\n        $bogus = 1;\n      }\n\n    } elsif ($dirtree {$path} =~ /^FILE:(.*)$/) {\n      if (-l _ || !-f _) {\n        print \"compare_dir_tree: $path is not a file.\\n\";\n        $bogus = 1;\n        next;\n      }\n\n      if ($1 ne \"*\") {\n        my $contents = &read_file_into_string (\"$basedir/$path\");\n        if ($contents ne \"$1\\n\") {\n          print \"compare_dir_tree: $path contains wrong stuff.\"\n              . \"  Is:\\n$contentsShould be:\\n$1\\n\";\n          $bogus = 1;\n        }\n      }\n\n    } elsif ($dirtree {$path} =~ /^LINK:(.*)$/) {\n      my $target = $1;\n      if (!-l _) {\n        print \"compare_dir_tree: $path is not a link.\\n\";\n        $bogus = 1;\n        next;\n      }\n\n      my $contents = readlink (\"$basedir/$path\");\n      $contents =~ tr/>/\\//;\n      my $fulltarget = \"$basedir/$target\";\n      $fulltarget =~ tr/>/\\//;\n      if (!($contents =~ /$fulltarget$/)) {\n        if ($debug) {\n          $target = $fulltarget;\n        }\n        print \"compare_dir_tree: $path should be link to $target, \"\n            . \"not $contents.\\n\";\n        $bogus = 1;\n      }\n\n    } else {\n      &error (\"Bogus dirtree type: \\\"$dirtree{$path}\\\"\\n\", 1);\n    }\n  }\n\n  if ($debug) {\n    print \"leftovers: (@allfiles).\\n\";\n  }\n\n  foreach my $file (@allfiles) {\n    print \"compare_dir_tree: $file should not exist.\\n\";\n    $bogus = 1;\n  }\n\n  return !$bogus;\n}\n\n# this subroutine generates the prefix name used to keep tmp filenames,\n# log filenames, etc., unique.\n\nsub get_prefix\n{\n  my ($num) = @_;\n  return sprintf(\"t%03d.\", $num);\n}\n\n# just like logfile, only a generic tmp filename for use by the test.\n# they are automatically cleaned up unless -keep was used, or the test fails.\n# Pass an argument of 1 to return the same filename as the previous call.\n\nsub get_tmpfile\n{\n  my ($no_increment) = @_;\n\n  $num_of_tmpfiles += !$no_increment;\n\n  return (&get_prefix ($num_of_tmpfiles) . $tmpfilesuffix);\n}\n\n# This subroutine returns a log filename with a number appended to\n# the end corresponding to how many logfiles have been created in the\n# current running test.  An optional parameter may be passed (0 or 1).\n# If a 1 is passed, then it does NOT increment the logfile counter\n# and returns the name of the latest logfile.  If either no parameter\n# is passed at all or a 0 is passed, then the logfile counter is\n# incremented and the new name is returned.\n\nsub get_logfile\n{\n  my ($no_increment) = @_;\n\n  $num_of_logfiles += !$no_increment;\n\n  return (&get_prefix ($num_of_logfiles) . $logext);\n}\n\n# This subroutine returns a base (answer) filename with a number\n# appended to the end corresponding to how many logfiles (and thus\n# base files) have been created in the current running test.\n# NO PARAMETERS ARE PASSED TO THIS SUBROUTINE.\n\nsub get_basefile\n{\n  return (&get_prefix ($num_of_logfiles) . $baseext);\n}\n\n# This subroutine returns a difference filename with a number appended\n# to the end corresponding to how many logfiles (and thus diff files)\n# have been created in the current running test.\n\nsub get_difffile\n{\n  return (&get_prefix ($num_of_logfiles) . $diffext);\n}\n\n# This subroutine returns a command filename with a number appended\n# to the end corresponding to how many logfiles (and thus command files)\n# have been created in the current running test.\n\nsub get_runfile\n{\n  return (&get_prefix ($num_of_logfiles) . $runext);\n}\n\n1;\n"
  },
  {
    "path": "tests/thelp.pl",
    "content": "#!/usr/bin/env perl\n# -*-perl-*-\n#\n# This script helps us write tests in a portable way, without relying on a lot\n# of shell features.  Since we already have Perl to run the tests, use that.\n#\n# The arguments represent a set of steps that will be run one at a time.\n# Each step consists of an operator and argument.\n#\n# It supports the following operators:\n#  out <word>     : echo <word> to stdout with a newline\n#  raw <word>     : echo <word> to stdout without adding anything\n#  env <word>     : echo the value of the env.var. <word>, or \"<unset>\"\n#  file <word>    : echo <word> to stdout AND create the file <word>\n#  dir <word>     : echo <word> to stdout AND create the directory <word>\n#  rm <word>      : echo <word> to stdout AND delete the file/directory <word>\n#  wait <word>    : wait for a file named <word> to exist\n#  exist <word>   : echo <word> AND fail if a file named <word> doesn't exist\n#  noexist <word> : echo <word> AND fail if a file named <word> exists\n#  tmout <secs>   : Change the timeout for waiting.  Default is 4 seconds.\n#  sleep <secs>   : Sleep for <secs> seconds then echo <secs>\n#  term <pid>     : send SIGTERM to PID <pid>\n#  fail <err>     : echo <err> to stdout then exit with error code err\n#\n# If given -q only the \"out\", \"raw\", and \"env\" commands generate output.\n\n# Force flush\n$| = 1;\n\nmy $quiet = 0;\nmy $timeout = 10;\n\nsub op {\n    my ($op, $nm) = @_;\n\n    defined $nm or die \"Missing value for $op\\n\";\n\n    if ($op eq 'out') {\n        print \"$nm\\n\";\n        return 1;\n    }\n    if ($op eq 'raw') {\n        print \"$nm\";\n        return 1;\n    }\n\n    if ($op eq 'env') {\n        print \"$nm=\" unless $quiet;\n        if (exists $ENV{$nm}) {\n            print \"$ENV{$nm}\\n\";\n        } else {\n            print \"<unset>\\n\";\n        }\n        return 1;\n    }\n\n    # Show the output before creating the file\n    if ($op eq 'file') {\n        print \"file $nm\\n\" unless $quiet;\n        open(my $fh, '>', $nm) or die \"$nm: open: $!\\n\";\n        close(my $fh);\n        return 1;\n    }\n\n    if ($op eq 'exist') {\n        -f \"$nm\" || die \"$nm: file should exist: $!\\n\";\n        print \"exist $nm\\n\" unless $quiet;\n        return 1\n    }\n\n    if ($op eq 'noexist') {\n        -f \"$nm\" && die \"$nm: file exists\\n\";\n        print \"noexist $nm\\n\" unless $quiet;\n        return 1\n    }\n\n    # Show the output before creating the directory\n    if ($op eq 'dir') {\n        print \"dir $nm\\n\" unless $quiet;\n        mkdir($nm) or die \"$nm: mkdir: $!\\n\";\n        return 1;\n    }\n\n    # Show the output after removing the file\n    if ($op eq 'rm') {\n        if (-f $nm) {\n            unlink($nm) or die \"$nm: unlink: $!\\n\";\n        } elsif (-d $nm) {\n            rmdir($nm) or die \"$nm: rmdir: $!\\n\";\n        } else {\n            die \"$nm: not file or directory: $!\\n\";\n        }\n        print \"rm $nm\\n\" unless $quiet;\n        return 1;\n    }\n\n    if ($op eq 'tmout') {\n        $timeout = $nm;\n        print \"tmout $nm\\n\" unless $quiet;\n        return 1;\n    }\n\n    # Show the output after the file exists\n    if ($op eq 'wait') {\n        my $start = time();\n        my $end = $start + $timeout;\n        while (time() <= $end) {\n            if (-f $nm) {\n                print \"wait $nm\\n\" unless $quiet;\n                return 1;\n            }\n            select(undef, undef, undef, 0.1);\n        }\n        die \"wait $nm: timeout after \".(time()-$start-1).\" seconds\\n\";\n    }\n\n    # Show the output after sleeping\n    if ($op eq 'sleep') {\n        sleep($nm);\n        print \"sleep $nm\\n\" unless $quiet;\n        return 1;\n    }\n\n    if ($op eq 'term') {\n        print \"term $nm\\n\" unless $quiet;\n        kill('TERM', $nm);\n        return 1;\n    }\n\n    if ($op eq 'fail') {\n        print \"fail $nm\\n\" unless $quiet;\n        exit($nm);\n    }\n\n    die(\"Invalid command: $op $nm\\n\");\n}\n\nif (@ARGV && $ARGV[0] eq '-q') {\n    $quiet = 1;\n    shift;\n}\n\nwhile (@ARGV) {\n    if (op($ARGV[0], $ARGV[1])) {\n        shift;\n        shift;\n    }\n}\n\nexit(0);\n"
  },
  {
    "path": "vms_export_symbol_test.com",
    "content": "$! VMS_EXPORT_SYMBOL_TEST.COM\n$!\n$! Verify the VMS_EXPORT_SYMBOL.C module\n$!\n$! 22-May-2014   J. Malmberg\n$!\n$!=========================================================================\n$!\n$ cc/names=(as_is)/define=(DEBUG=1,_POSIX_EXIT=1) vms_export_symbol.c\n$!\n$ link vms_export_symbol\n$!\n$ delete vms_export_symbol.obj;*\n$!\n$! Need a foreign command to test.\n$ vms_export_symbol := $sys$disk:[]vms_export_symbol.exe\n$ save_export_symbol = vms_export_symbol\n$!\n$ vms_export_symbol\n$ if $severity .ne. 1\n$ then\n$    write sys$output \"Test program failed!\";\n$ endif\n$!\n$ if vms_export_symbol .nes. save_export_symbol\n$ then\n$   write sys$output \"Test failed to restore foreign command!\"\n$ endif\n$ if f$type(test_export_symbol) .nes. \"\"\n$ then\n$   write sys$output \"Test failed to clear exported symbol!\"\n$ endif\n$ if f$type(test_putenv_symbol) .nes. \"\"\n$ then\n$   write sys$output \"Test failed to clear putenv exported symbol!\"\n$ endif\n$!\n"
  }
]