summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/COPYING674
-rw-r--r--tests/ChangeLog.11429
-rw-r--r--tests/NEWS178
-rw-r--r--tests/README102
-rw-r--r--tests/config-flags.pm19
-rw-r--r--tests/config-flags.pm.in19
-rwxr-xr-xtests/config_flags_pm.com53
-rw-r--r--tests/guile.supp31
-rwxr-xr-xtests/mkshadow57
-rwxr-xr-xtests/run_make_tests2
-rwxr-xr-xtests/run_make_tests.com272
-rw-r--r--tests/run_make_tests.pl491
-rw-r--r--tests/scripts/features/archives97
-rw-r--r--tests/scripts/features/comments35
-rw-r--r--tests/scripts/features/conditionals146
-rw-r--r--tests/scripts/features/default_names44
-rw-r--r--tests/scripts/features/double_colon164
-rw-r--r--tests/scripts/features/echoing64
-rw-r--r--tests/scripts/features/errors95
-rw-r--r--tests/scripts/features/escape74
-rw-r--r--tests/scripts/features/export186
-rw-r--r--tests/scripts/features/include179
-rw-r--r--tests/scripts/features/jobserver61
-rw-r--r--tests/scripts/features/load110
-rw-r--r--tests/scripts/features/loadapi116
-rw-r--r--tests/scripts/features/mult_rules78
-rw-r--r--tests/scripts/features/mult_targets46
-rw-r--r--tests/scripts/features/order_only118
-rw-r--r--tests/scripts/features/output-sync341
-rw-r--r--tests/scripts/features/override45
-rw-r--r--tests/scripts/features/parallelism216
-rw-r--r--tests/scripts/features/patspecific_vars148
-rw-r--r--tests/scripts/features/patternrules225
-rw-r--r--tests/scripts/features/quoting32
-rw-r--r--tests/scripts/features/recursion55
-rw-r--r--tests/scripts/features/reinvoke80
-rw-r--r--tests/scripts/features/rule_glob37
-rw-r--r--tests/scripts/features/se_explicit167
-rw-r--r--tests/scripts/features/se_implicit260
-rw-r--r--tests/scripts/features/se_statpat107
-rw-r--r--tests/scripts/features/shell_assignment65
-rw-r--r--tests/scripts/features/statipattrules111
-rw-r--r--tests/scripts/features/targetvars273
-rw-r--r--tests/scripts/features/utf811
-rw-r--r--tests/scripts/features/varnesting35
-rw-r--r--tests/scripts/features/vpath81
-rw-r--r--tests/scripts/features/vpath245
-rw-r--r--tests/scripts/features/vpath335
-rw-r--r--tests/scripts/features/vpathgpath66
-rw-r--r--tests/scripts/features/vpathplus129
-rw-r--r--tests/scripts/functions/abspath81
-rw-r--r--tests/scripts/functions/addprefix44
-rw-r--r--tests/scripts/functions/addsuffix36
-rw-r--r--tests/scripts/functions/andor50
-rw-r--r--tests/scripts/functions/basename44
-rw-r--r--tests/scripts/functions/call110
-rw-r--r--tests/scripts/functions/dir44
-rw-r--r--tests/scripts/functions/error73
-rw-r--r--tests/scripts/functions/eval169
-rw-r--r--tests/scripts/functions/file118
-rw-r--r--tests/scripts/functions/filter-out42
-rw-r--r--tests/scripts/functions/findstring47
-rw-r--r--tests/scripts/functions/flavor44
-rw-r--r--tests/scripts/functions/foreach77
-rw-r--r--tests/scripts/functions/guile99
-rw-r--r--tests/scripts/functions/if33
-rw-r--r--tests/scripts/functions/join44
-rw-r--r--tests/scripts/functions/notdir44
-rw-r--r--tests/scripts/functions/origin51
-rw-r--r--tests/scripts/functions/realpath82
-rw-r--r--tests/scripts/functions/shell32
-rw-r--r--tests/scripts/functions/sort47
-rw-r--r--tests/scripts/functions/strip57
-rw-r--r--tests/scripts/functions/substitution38
-rw-r--r--tests/scripts/functions/suffix57
-rw-r--r--tests/scripts/functions/value30
-rw-r--r--tests/scripts/functions/warning65
-rw-r--r--tests/scripts/functions/wildcard103
-rw-r--r--tests/scripts/functions/word167
-rw-r--r--tests/scripts/misc/bs-nl129
-rw-r--r--tests/scripts/misc/close_stdout9
-rw-r--r--tests/scripts/misc/fopen-fail15
-rw-r--r--tests/scripts/misc/general151
-rw-r--r--tests/scripts/misc/general250
-rw-r--r--tests/scripts/misc/general3313
-rw-r--r--tests/scripts/misc/general482
-rw-r--r--tests/scripts/misc/utf814
-rw-r--r--tests/scripts/options/dash-B85
-rw-r--r--tests/scripts/options/dash-C71
-rw-r--r--tests/scripts/options/dash-I59
-rw-r--r--tests/scripts/options/dash-W88
-rw-r--r--tests/scripts/options/dash-e24
-rw-r--r--tests/scripts/options/dash-f85
-rw-r--r--tests/scripts/options/dash-k115
-rw-r--r--tests/scripts/options/dash-l56
-rw-r--r--tests/scripts/options/dash-n100
-rw-r--r--tests/scripts/options/dash-q77
-rw-r--r--tests/scripts/options/dash-t58
-rw-r--r--tests/scripts/options/eval29
-rw-r--r--tests/scripts/options/general35
-rw-r--r--tests/scripts/options/print-directory33
-rw-r--r--tests/scripts/options/symlinks68
-rw-r--r--tests/scripts/options/warn-undefined-variables25
-rw-r--r--tests/scripts/targets/DEFAULT53
-rw-r--r--tests/scripts/targets/FORCE40
-rw-r--r--tests/scripts/targets/INTERMEDIATE108
-rw-r--r--tests/scripts/targets/ONESHELL88
-rw-r--r--tests/scripts/targets/PHONY54
-rw-r--r--tests/scripts/targets/POSIX57
-rw-r--r--tests/scripts/targets/SECONDARY190
-rw-r--r--tests/scripts/targets/SILENT42
-rw-r--r--tests/scripts/targets/clean50
-rw-r--r--tests/scripts/test_template29
-rw-r--r--tests/scripts/variables/CURDIR20
-rw-r--r--tests/scripts/variables/DEFAULT_GOAL87
-rw-r--r--tests/scripts/variables/GNUMAKEFLAGS42
-rw-r--r--tests/scripts/variables/INCLUDE_DIRS46
-rw-r--r--tests/scripts/variables/LIBPATTERNS38
-rw-r--r--tests/scripts/variables/MAKE24
-rw-r--r--tests/scripts/variables/MAKECMDGOALS52
-rw-r--r--tests/scripts/variables/MAKEFILES53
-rw-r--r--tests/scripts/variables/MAKEFLAGS41
-rw-r--r--tests/scripts/variables/MAKELEVEL33
-rw-r--r--tests/scripts/variables/MAKE_RESTARTS62
-rw-r--r--tests/scripts/variables/MFILE_LIST30
-rw-r--r--tests/scripts/variables/SHELL103
-rw-r--r--tests/scripts/variables/automatic122
-rw-r--r--tests/scripts/variables/define282
-rw-r--r--tests/scripts/variables/flavors96
-rw-r--r--tests/scripts/variables/negative46
-rw-r--r--tests/scripts/variables/private122
-rw-r--r--tests/scripts/variables/special141
-rw-r--r--tests/scripts/variables/undefine73
-rw-r--r--tests/test_driver.pl1474
134 files changed, 14801 insertions, 0 deletions
diff --git a/tests/COPYING b/tests/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/tests/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/tests/ChangeLog.1 b/tests/ChangeLog.1
new file mode 100644
index 0000000..9abe731
--- /dev/null
+++ b/tests/ChangeLog.1
@@ -0,0 +1,1429 @@
+2013-10-09 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/patspecific_vars: Typo fixes.
+
+2013-10-05 Paul Smith <psmith@gnu.org>
+
+ * test_driver.pl (run_all_tests): Rewrite to be more clear.
+ * scripts/features/jobserver: Avoid using $ENV{HOME} as it doesn't
+ exist everywhere.
+ * scripts/features/default_names: End with 1;
+
+ * scripts/features/loadapi: Use new calling signatures. Verify
+ the NOEXPAND flag works. Test with all valid function name
+ characters.
+
+2013-09-29 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: Solaris /bin/sh can't handle options in
+ multiple words; skip that test.
+ * scripts/targets/ONESHELL: Ditto.
+
+ * scripts/variables/GNUMAKEFLAGS: Verify that GNUMAKEFLAGS is
+ cleared and options are not duplicated.
+
+2013-09-23 Paul Smith <psmith@gnu.org>
+
+ * scripts/options/print-directory: Rename dash-w to
+ print-directory to avoid conflicts with dash-W on case-insensitive
+ filesystems.
+
+2013-09-22 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/se_implicit: Verify that order-only tokens
+ inside second expansion are parsed correctly.
+ Test for Savannah bug #31155.
+
+ * run_make_tests.pl (set_more_defaults): If we can't find
+ gnumake.h based on the make program we might be running from a
+ remote build directory. Parse the Makefile for the right path.
+
+ Fix some test issues on Solaris.
+
+ * scripts/features/archives: Determine what output ar gives when
+ adding and replacing objects and compare with that.
+ * scripts/features/escape: Solaris /bin/sh doesn't properly handle
+ backslashes inside single quotes, so don't rely on it.
+ * scripts/features/output-sync: false(1) gives different exit
+ codes on different systems; use "exit 1" instead.
+ * scripts/features/parallelism: Increase the timeout for slower systems.
+
+2013-09-21 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/archives: Some versions of ar (MacOSX) generate
+ different output when creating archives. Run it and verify the
+ real output.
+ * scripts/features/default_names: MacOSX is, like Windows,
+ case-preserving / case-insensitive. Redo the test to avoid
+ checking for "UNIX".
+ * test_driver.pl (attach_default_output): Don't dup stdout into
+ stderr. Reported by Denis Excoffier <bug-tar@Denis-Excoffier.org>
+
+ * scripts/features/se_explicit: Fix a test that behaves
+ differently with/without archive capability enabled.
+ * scripts/features/output-sync: Don't test output-sync if it's not
+ enabled. We also skip it if parallelism is not enabled, although
+ strictly speaking some of the output-sync tests are valid even
+ without parallelism.
+ * scripts/features/jobserver: Move some tests that require the
+ jobserver from features/parallelism to a separate suite. Only run
+ this if jobserver mode is enabled.
+
+ * scripts/features/output-sync: Test shell functions writing to
+ stderr in recipes: ensure it's captured via output-sync. Test
+ output generated while reading makefiles and make sure it's
+ captured via output-sync. Make sure that fatal errors dump the
+ output so it's not lost.
+
+ * scripts/options/dash-w: Add a test for -w flag.
+
+2013-09-15 Paul Smith <psmith@gnu.org>
+
+ * scripts/misc/fopen-fail: Check for failure on infinite recursion.
+ * run_make_tests.pl (run_make_test): Allow the answer string to be
+ undef, which means that we shouldn't compare it at all. Only the
+ exit code matters in this case.
+ * test_driver.pl (compare_output): Ditto.
+ Test for Savannah bug #27374.
+
+ * scripts/features/parallelism: Test broken jobserver on recursion.
+ Test for Savannah bug #39934.
+
+ * scripts/options/eval: Verify --eval during restart.
+ Test for Savannah bug #39203.
+
+2013-09-14 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync: Verify -Orecurse properly.
+
+2013-09-12 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync: Modify for output sync behavior.
+ * scripts/variables/MAKE_RESTARTS: Ditto.
+ * scripts/variables/MAKEFLAGS: Remove mode for --trace.
+ * scripts/variables/GNUMAKEFLAGS: Ditto.
+
+2013-07-22 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/rule_glob: Add tests for wildcards in rules.
+ Test for Savannah bug #39310.
+
+2013-07-09 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/se_implicit: Add a test for SE rules depending
+ on other SE rules to be built.
+
+2013-05-26 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/archives: Test for Savannah bug #38442.
+
+ * scripts/misc/bs-nl: Test for Savannah bug #39035.
+ Add a test for Savannah bug #38945.
+
+2013-05-22 Paul Smith <psmith@gnu.org>
+
+ * scripts/options/dash-n: Fix results after MAKEFLAGS fixes.
+ * scripts/variables/MAKEFLAGS: Ditto.
+ * scripts/variables/GNUMAKEFLAGS: Ditto.
+
+2013-05-14 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/loadapi: Add plugin_is_GPL_compatible symbol.
+ * scripts/features/load: Ditto.
+
+2013-05-13 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync (output_sync_set): Update for new
+ --trace behavior.
+
+2013-05-05 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync (output_sync_set): Remove
+ extraneous enter/leave lines, which are no longer printed.
+ Add tests for syncing command line printing.
+ (output_sync_set): Rename options: "job"->"line"; "make"->"recurse"
+
+2013-05-04 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/loadapi: Use the new alloc functions.
+
+ * scripts/features/output-sync (output_sync_set): New test for
+ ordered recursive output for -Ojob / -Otarget.
+
+2013-05-03 Eli Zaretskii <eliz@gnu.org>
+
+ * scripts/features/load: Fix signatures of testload_gmk_setup and
+ explicit_setup, to bring them in line with the documentation.
+
+2013-04-28 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync (output_sync_set): Add tests for
+ the per-job syntax mode.
+ (output_sync_set): Test improved error message location.
+
+2013-04-15 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync (output_sync_set): New arg syntax.
+
+2013-04-14 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/output-sync: Rewrite to be more reliable.
+
+ * test_driver.pl (_run_command): Don't set SIGALRM until after we
+ start the child. Print errors to the top-level output, which will
+ be stderr.
+ (attach_default_output): Use a list of file handles as the stack.
+ (detach_default_output): Ditto.
+
+ * scripts/features/output-sync: Add a test for output-sync.
+
+2013-02-25 Paul Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (valid_option): Support the -srcdir flag.
+ (set_more_defaults): Set up $srcdir if it's not set yet.
+
+ * scripts/functions/guile: Verify gmk-eval doesn't expand twice.
+ * scripts/features/load: Rework to test just the load capability.
+ * scripts/features/loadapi: New set of tests for the load API.
+
+2013-01-19 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/load: Test loaded files with and without "./"
+ prefix. Add tests for automatically rebuilding loaded files if
+ they are out of date or non-existent.
+
+2013-01-13 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/archives: Add a check targets that have parens,
+ but are not archives. See Savannah bug #37878.
+
+ * scripts/options/dash-n: Verify -n is preserved after recursive /
+ re-exec. See Savannah bug #38051.
+
+2013-01-12 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Change rule so it doesn't depend
+ on invocation order, etc.
+
+2012-10-29 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/load: New test suite for the "load" directive.
+
+2012-09-09 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/file: Get errors in the C locale, not the
+ current locale. Fixes Savannah bug #35764.
+
+ * scripts/features/escape: Check that backslashes before
+ non-special characters are not removed.
+
+ * scripts/features/utf8: New test for UTF-8 support.
+ See Savannah bug #36529.
+
+ * scripts/targets/POSIX: Add tests for default macro values as
+ specified by IEEE Std 1003.1-2008. See Savannah bug #37069.
+
+2012-03-04 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/se_explicit: Test $(x:%=%) format in secondary
+ expansion prerequisite lists. See Savannah bug #16545.
+
+ * scripts/features/escape: Test escaped ":" in prerequisite lists.
+ See Savannah bug #12126.
+
+ * scripts/variables/private: Test appending private variables in
+ pattern-specific target rules. See Savannah bug #35468.
+
+2012-03-03 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: Ensure .SHELLFLAGS works with options
+ separated by whitespace.
+
+ * scripts/targets/ONESHELL: Try .ONESHELL in combination with
+ whitespace-separated options in .SHELLFLAGS. See Savannah bug #35397.
+
+ * scripts/functions/filter-out: Add filter tests and test escape
+ operations. See Savannah bug #35410.
+
+ * guile.supp: Suppress valgrind errors from Guile
+ * run_make_tests.pl: Use the Guile suppression file.
+
+ * scripts/misc/bs-nl: Check for POSIX and non-POSIX
+ backslash/newline handling. Addresses Savannah bug #16670.
+
+2012-01-29 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/flavors: Add tests for ::=
+ * scripts/variables/define: Ditto
+
+ * scripts/functions/file: Test the new $(file ...) function.
+
+2012-01-12 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/guile: New regression tests for Guile support.
+
+2011-12-10 Paul Smith <psmith@gnu.org>
+
+ * scripts/targets/SECONDARY: Add prereq statements to ensure rules
+ are printed in the right order for test #9
+
+2011-11-14 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/double_colon: Check double-colon with escaped
+ filenames. See Savannah bug #33399.
+
+2011-09-18 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: On re-exec make sure we preserve
+ the value of MAKEFLAGS when necessary. See Savannah bug #33873.
+
+ * scripts/features/vpath3: Verify handling of -lfoo libraries
+ found via vpath vs. the standard directory search.
+ See Savannah bug #32511.
+
+2011-09-12 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/call: Verify that using export in a $(call ...)
+ context creates a global variable. See Savannah bug #32498.
+
+2011-09-02 Paul Smith <psmith@gnu.org>
+
+ * scripts/options/dash-n: Verify that in "-n -t", the -n takes
+ priority. Patch from Michael Witten <mfwitten@gmail.com>.
+
+2011-08-29 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/varnesting: Test resetting of variables while
+ expanding them. See Savannah patch #7534
+
+2011-06-12 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/archives: Check archives with whitespace at the
+ beginning, end, and extra in the middle.
+ Another test for Savannah bug #30612.
+
+2011-05-07 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/private: Ensure we skip private variables when
+ appending. Test for Savannah bug #32872.
+
+ * scripts/functions/wildcard: Verify wildcard used to test for
+ file existence/non-existence.
+
+2011-05-02 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/sort: Add a test for Savannah bug #33125.
+
+2011-04-17 David A. Wheeler <dwheeler@dwheeler.com>
+
+ * scripts/features/shell_assignment: Regression for "!=" feature
+
+2010-11-06 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Fix known-good output for BS/NL changes.
+ * scripts/functions/call: Ditto.
+ * scripts/variables/special: Ditto.
+
+ * scripts/misc/bs-nl: New test suite for backslash/newline testing.
+
+2010-08-29 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/errors: Add new error message to output text.
+ * scripts/variables/SHELL: Ditto.
+ * scripts/targets/POSIX: Ditto.
+ * scripts/options/dash-k: Ditto.
+ * scripts/features/vpathplus: Ditto.
+ * scripts/features/patternrules: Ditto.
+ * scripts/features/parallelism: Ditto.
+
+2010-08-13 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/archives: New regression tests for archive
+ support. Test for fix to Savannah bug #30612.
+
+ * run_make_tests.pl (set_more_defaults): Set a %FEATURES hash to
+ the features available in $(.FEATURES).
+
+2010-08-10 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/reinvoke: Ensure command line variable settings
+ are preserved across make re-exec. Tests Savannah bug #30723.
+
+2010-07-28 Paul Smith <psmith@gnu.org>
+
+ * scripts/targets/POSIX: Compatibility issues with Solaris (and
+ Tru64?); "false" returns different exit codes, and set -x shows
+ output with extra whitespace. Run the commands by hand first to
+ find out what the real shell would do, then compare what make does.
+ * scripts/variables/SHELL: Ditto.
+
+2010-07-12 Paul Smith <psmith@gnu.org>
+
+ * test_driver.pl: Add a new $perl_name containing the path to Perl.
+ * run_make_tests.pl (run_make_test): Replace the special string
+ #PERL# in a makefile etc. with the path the Perl executable so
+ makefiles can use it.
+
+ * scripts/targets/ONESHELL: Add a new set of regression tests for
+ the .ONESHELL feature.
+
+2010-07-06 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: Test the new .SHELLFLAGS variable.
+
+ * scripts/targets/POSIX: New file. Test the .POSIX special target.
+ Verify that enabling .POSIX changes the shell flags to set -e.
+
+2010-07-01 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/recursion: Add a space to separate command-line
+ args. Fixes Savannah bug #29968.
+
+2009-11-12 Boris Kolpackov <boris@codesynthesis.com>
+
+ * scripts/features/vpath3: Test for the new library search
+ behavior.
+
+2009-10-06 Boris Kolpackov <boris@codesynthesis.com>
+
+ * scripts/features/se_explicit: Enable the test for now fixed
+ Savannah bug 25780.
+
+2009-10-06 Boris Kolpackov <boris@codesynthesis.com>
+
+ * scripts/variables/undefine: Tests for the new undefine feature.
+
+2009-10-03 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Test for open Savannah bug #26846.
+
+ * scripts/variables/MAKE: Rewrite for new run_make_test() format.
+
+ * scripts/variables/MAKEFLAGS: Created.
+ Add test for Savannah bug #2216 (still open).
+
+ * scripts/features/include: Test for Savannah bug #102 (still open).
+
+2009-09-30 Boris Kolpackov <boris@codesynthesis.com>
+
+ * scripts/features/include: Add diagnostics issuing tests for
+ cases where targets have been updated and failed with the
+ dontcare flag. Savannah bugs #15110, #25493, #12686, #17740.
+
+2009-09-28 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/shell: Add regression test for Savannah bug
+ #20513 (still open).
+
+ * scripts/features/se_explicit: Add regression tests for Savannah
+ bug #25780 (still open).
+
+ * run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)?
+ that runs tests we know will fail. This allows us to add
+ regression tests to the test suite for bugs that haven't been
+ fixed yet.
+
+2009-09-28 Boris Kolpackov <boris@codesynthesis.com>
+
+ * scripts/features/patspecific_vars: Add a test for the shortest
+ stem first order.
+
+ * scripts/features/patternrules: Add a test for the shortest stem
+ first order.
+
+2009-09-24 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/se_implicit: Add a test for order-only
+ secondary expansion prerequisites.
+
+2009-09-23 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/patternrules: Test that we can remove pattern
+ rules, both single and multiple prerequisites. Savannah bug #18622.
+
+ * scripts/features/echoing: Rework for run_make_test().
+
+2009-06-14 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/vpath: Verify we don't get bogus circular
+ dependency warnings if we choose a different file via vpath during
+ update. Savannah bug #13529.
+
+2009-06-13 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/MAKEFILES: Verify that MAKEFILES included
+ files (and files included by them) don't set the default goal.
+ Savannah bug #13401.
+
+ * scripts/functions/wildcard: Test that wildcards with
+ non-existent glob matchers return empty.
+
+2009-06-09 Paul Smith <psmith@gnu.org>
+
+ * scripts/options/dash-B: Test the $? works correctly with -B.
+ Savannah bug #17825.
+
+ * scripts/features/patternrules: Test that dependencies of
+ "also_make" targets are created properly. Savannah bug #19108.
+
+ * test_driver.pl (compare_output): Create a "run" file for failed
+ tests containing the command that was run.
+ (get_runfile): New function.
+
+ * run_make_tests.pl (valid_option): Enhanced support for valgrind:
+ allow memcheck and massif tools.
+
+ * scripts/features/patternrules: Have to comment out a line in the
+ first test due to backing out a change that broke the implicit
+ rule search algorithm. Savannah bug #17752.
+ * scripts/misc/general4: Remove a test that is redundant with
+ patternrules.
+
+ * scripts/features/parallelism: Add a test for re-exec with
+ jobserver master override. Savannah bug #18124.
+
+2009-06-08 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Add a test for continued target
+ vars after a semicolon. Savannah bug #17521.
+
+2009-06-07 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/se_explicit: Make sure we catch defining
+ prereqs during snap_deps(). Savannah bug #24622.
+
+ * scripts/variables/automatic: Check prereq ordering when the
+ target with the recipe has no prereqs. Savannah bug #21198.
+
+ * scripts/variables/LIBPATTERNS: Add a new set of test for
+ $(.LIBPATTERNS) (previously untested!)
+
+2009-06-04 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: The export target-specific SHELL test
+ has an incorrect known-good-value.
+
+ * scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.)
+
+ * scripts/features/se_explicit: Add tests for Savannah bug #24588.
+
+2009-05-31 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697.
+
+ * scripts/features/targetvars: Add tests of overrides for Savannah
+ bug #26207.
+ * scripts/features/patspecific_vars: Ditto.
+
+ * scripts/features/patternrules: Add a test for Savannah bug #26593.
+
+2009-05-30 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/flavors: Update with new variable flavor tests.
+ * scripts/variables/define: Create a new set of tests for
+ define/endef and move those aspects of the flavors suite here.
+
+2009-05-25 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Ditto.
+
+ * scripts/features/export: Test new variable parsing abilities.
+
+2009-02-23 Ramon Garcia <ramon.garcia.f@gmail.com>
+
+ * scripts/variables/private: Create a new suite of tests for 'private'.
+
+2007-11-04 Paul Smith <psmith@gnu.org>
+
+ * scripts/functions/eval: Update error message for command -> recipe.
+
+ * test_driver.pl (compare_output): Allow the answer to be a regex,
+ if surrounded by '/'.
+ * scripts/misc/close_stdout: Use a regex for the answer, since
+ sometimes the error will have a description and sometimes it won't.
+
+2007-09-10 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/special: Add tests for .RECIPEPREFIX variable.
+
+2007-08-15 Paul Smith <psmith@gnu.org>
+
+ These test cases were contributed by
+ Icarus Sparry <savannah@icarus.freeuk.com> and J. David Bryan for
+ Savannah bugs #3330 and #15919.
+
+ * scripts/targets/SECONDARY: Add tests for Savannah bugs 3330 and
+ 15919.
+
+ * scripts/features/parallelism: Add tests for wrong answer/hang
+ combining INTERMEDIATE, order-only prereqs, and parallelism.
+ See Savannah bugs 3330 and 15919.
+
+2007-07-13 Paul Smith <psmith@gnu.org>
+
+ Install a timeout so tests can never loop infinitely.
+ Original idea and patch for a single-test version provided by
+ Icarus Sparry <savannah@icarus.freeuk.com>
+
+ * test_driver.pl (_run_command): New function: this is called by
+ other functions to actually run a command. Before we run it,
+ install a SIGALRM handler and set up a timer to go off in the
+ future (default is 5s; this can be overridden by individual tests).
+ (run_command): Call it.
+ (run_command_with_output): Call it.
+
+ * run_make_tests.pl (run_make_with_options): Override the default
+ timeout if the caller requests it.
+ (run_make_test): Pass any timeout override to run_make_with_options.
+
+ * scripts/features/parallelism: Increase the timeout for long tests.
+ * scripts/options/dash-l: Ditto.
+
+2006-10-01 Paul Smith <psmith@paulandlesley.org>
+
+ * run_make_tests.pl (set_more_defaults): Remove setting of LANG in
+ ENV here. This doesn't always work.
+ * test_driver.pl (toplevel): Set LC_ALL to 'C' in the make
+ environment. Fixes Savannah bug #16698.
+
+2006-09-30 Paul Smith <psmith@paulandlesley.org>
+
+ * scripts/variables/automatic: Add back the test for bug #8154.
+
+2006-04-01 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/realpath: Don't run tests with multiple
+ initial slashes on Windows: those paths mean something different.
+
+2006-03-19 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Test that the jobserver is
+ properly managed when we have to re-exec the master instance of
+ make.
+
+2006-03-17 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/statipattrules: Add tests for bug #16053.
+
+2006-03-09 Paul Smith <psmith@gnu.org>
+
+ * scripts/features/escape: Use "pre:" not "p:" to avoid conflicts
+ with DOS drive letters. Fixes Savannah bug #15947.
+
+ * test_driver.pl (run_each_test): Set the status properly even
+ when a test fails to execute. Fixes Savannah bug #15942.
+
+ * scripts/functions/foreach: Use a different environment variable
+ other than PATH to avoid differences with Windows platforms.
+ Fixes Savannah bug #15938.
+
+2006-03-05 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (set_more_defaults): Add CYGWIN_NT as a port
+ type W32. Fixed Savannah bug #15937.
+
+ * scripts/features/default_names: Don't call error() when the test
+ fails. Fixes Savannah bug #15941.
+
+2006-02-17 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Test a complex construction which
+ guarantees that we have to merge variable lists of different
+ sizes. Tests for Savannah bug #15757.
+
+2006-02-15 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/error: Make sure filename/lineno information
+ is related to where the error is expanded, not where it's set.
+ * scripts/functions/warning: Ditto.
+ * scripts/functions/foreach: Check for different error conditions.
+ * scripts/functions/word: Ditto.
+ * scripts/variables/negative: Test some variable reference failure
+ conditions.
+ * scripts/options/warn-undefined-variables: Test the
+ --warn-undefined-variables flag.
+
+2006-02-09 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (set_more_defaults): Update valgrind support
+ for newer versions.
+ * test_driver.pl (toplevel): Skip all hidden files/directories (ones
+ beginning with ".").
+
+ * scripts/functions/andor: Tests for $(and ...) and $(or ...)
+ functions.
+
+2006-02-08 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/parallelism: Add a test for bug #15641.
+
+2006-02-06 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-W: Add a test for bug #15341.
+
+2006-01-03 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Add a test for bug #8154.
+
+ * README: Update to reflect the current state of the test suite.
+
+2005-12-12 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism, scripts/functions/wildcard,
+ scripts/targets/FORCE, scripts/targets/PHONY,
+ scripts/targets/SILENT: Use the default setting for
+ $delete_command. Fixes bug #15085.
+
+ * run_make_tests.pl (get_this_pwd) [VMS]: Use -no_ask with delete_file.
+
+2005-12-11 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/misc/general4: Test implicit rules with '$' in the
+ prereq list & prereq patterns.
+ * scripts/features/se_implicit: Add in .SECONDEXPANSION settings.
+
+2005-12-09 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/patternrules: Add a test for bug #13022.
+
+2005-12-07 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/double_colon: Add a test for bug #14334.
+
+2005-11-17 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/functions/flavor: Add a test for the flavor function.
+
+2005-11-14 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/variables/INCLUDE_DIRS: Add a test for the .INCLUDE_DIRS
+ special variable.
+
+2005-10-24 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/misc/general4: Test '$$' in prerequisites list.
+ * scripts/features/statipattrules: Rewrite to use run_make_test().
+ Add various static pattern info.
+ * scripts/features/se_statpat: Enable .SECONDEXPANSION target.
+ * scripts/features/se_explicit: Add tests for handling '$$' in
+ prerequisite lists with and without setting .SECONDEXPANSION.
+ * scripts/features/order_only: Convert to run_make_test().
+ * run_make_tests.pl (set_more_defaults): If we can't get the value
+ of $(MAKE) from make, then fatal immediately.
+
+2005-08-31 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (get_this_pwd): Require the POSIX module (in
+ an eval to trap errors) and if it exists, use POSIX::getcwd to
+ find the working directory. If it doesn't exist, go back to the
+ previous methods. This tries to be more accurate on Windows
+ systems.
+
+2005-08-29 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/abspath: Add some text to the error messages
+ to get a better idea of what's wrong. Make warnings instead of
+ errors.
+
+ * scripts/features/patspecific_vars: Don't use "test", which is
+ UNIX specific. Print the values and let the test script match
+ them.
+
+2005-08-25 Paul Smith <psmith@gnu.org>
+
+ * scripts/variables/SHELL: Use a /./ prefix instead of //: the
+ former works better with non-UNIX environments. Fixes Savannah
+ bug #14129.
+
+2005-08-13 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/functions/wildcard: Wrap calls to $(wildcard) with
+ $(sort) so that the resulting order is no longer filesystem-
+ dependent.
+
+2005-08-10 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/statipattrules: Add a test for Savannah bug #13881.
+
+2005-08-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Add a test for a bug reported by
+ Michael Matz (matz@suse.de) in which make exits without waiting
+ for all its children in some situations during parallel builds.
+
+2005-07-08 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl: Reset the environment to a clean value every
+ time before we invoke make. I'm suspicious that the environment
+ isn't handled the same way in Windows as it is in UNIX, and some
+ variables are leaking out beyond the tests they are intended for.
+ Create an %extraENV hash tests can set to add more env. vars.
+ * tests/scripts/features/export: Change to use %extraENV.
+ * tests/scripts/functions/eval: Ditto.
+ * tests/scripts/functions/origin: Ditto.
+ * tests/scripts/options/dash-e: Ditto.
+ * tests/scripts/variables/SHELL: Ditto.
+
+2005-06-27 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-W: Use 'echo >>' instead of touch to update
+ files.
+ * scripts/features/reinvoke: Rewrite to be safer on systems with
+ subsecond timestamps.
+ * scripts/features/patternrules: False exits with different error
+ codes on different systems (for example, Linux => 1, Solaris => 255).
+
+ * scripts/options/dash-W: Set the timestamp to foo.x in the future,
+ to be sure it will be considered updated when it's remade.
+
+2005-06-26 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/shell: New test suite for the shell function.
+
+2005-06-25 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/include: Test include/-include/sinclude with no
+ arguments. Tests fix for Savannah bug #1761.
+
+ * scripts/misc/general3: Implement comprehensive testing of
+ backslash-newline behavior in command scripts: various types of
+ quoting, fast path / slow path, etc.
+ Tests fix for Savannah bug #1332.
+
+ * scripts/options/symlinks: Test symlinks to non-existent files.
+ Tests fix for Savannah bug #13280.
+
+ * scripts/misc/general3: Test semicolons in variable references.
+ Tests fix for Savannah bug #1454.
+
+ * scripts/variables/MAKE_RESTARTS: New file: test the
+ MAKE_RESTARTS variable.
+ * scripts/options/dash-B: Test re-exec doesn't loop infinitely.
+ Tests fix for Savannah bug #7566.
+ * scripts/options/dash-W: New file: test the -W flag, including
+ re-exec infinite looping.
+
+2005-06-12 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/misc/close_stdout: Add a test for Savannah bug #1328.
+ This test only works on systems that have /dev/full (e.g., Linux).
+
+2005-06-09 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/foreach: Add a test for Savannah bug #11913.
+
+2005-05-31 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/include: Add a test for Savannah bug #13216.
+ * scripts/features/patternrules: Add a test for Savannah bug #13218.
+
+2005-05-13 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/conditionals: Add tests for the new if... else
+ if... endif syntax.
+
+2005-05-03 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to
+ DEFAULT_GOAL.
+
+2005-05-02 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Add a test for exporting recursive
+ variables containing $(shell) calls. Rewrite this script to use
+ run_make_test() everywhere.
+
+2005-04-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/targets/SECONDARY: Add a test for Savannah bug #12331.
+
+2005-03-15 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/variables/automatic: Add a test for Savannah bug #12320.
+
+2005-03-10 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/patternrules: Add a test for Savannah bug #12267.
+
+2005-03-09 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/variables/DEFAULT_TARGET: Add a test for Savannah
+ bug #12266.
+
+2005-03-04 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/patternrules: Add a test for Savannah bug #12202.
+
+2005-03-03 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/se_implicit: Add a test for stem
+ termination bug. Add a test for stem triple-expansion bug.
+
+ * scripts/features/se_statpat: Add a test for stem
+ triple-expansion bug.
+
+ * scripts/features/statipattrules: Change test #4 to reflect
+ new way empty prerequisite list is handled.
+
+
+2005-03-01 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/statipattrules: Add a test for
+ Savannah bug #12180.
+
+2005-02-28 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-q: Add a test for Savannah bug # 7144.
+
+ * scripts/options/symlinks: New file to test checking of symlink
+ timestamps. Can't use filename dash-L because it conflicts with
+ dash-l on case-insensitive filesystems.
+
+ * scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST:
+ Rename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3
+ unique filenames.
+
+2005-02-28 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET
+ special variable.
+
+2005-02-27 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/se_explicit: Test the second expansion in
+ explicit rules.
+ * scripts/features/se_implicit: Test the second expansion in
+ implicit rules.
+ * scripts/features/se_statpat: Test the second expansion in
+ static pattern rules.
+ * scripts/variables/automatic: Fix to work with the second
+ expansion.
+
+ * scripts/misc/general4: Add a test for bug #12091.
+
+2005-02-27 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/eval: Check that eval of targets within
+ command scripts fails. See Savannah bug # 12124.
+
+2005-02-26 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (compare_output): If a basic comparison of the
+ log and answer doesn't match, try harder: change all backslashes
+ to slashes and all CRLF to LF. This helps on DOS/Windows systems.
+
+2005-02-09 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/recursion: Test command line variable settings:
+ only one instance of a given variable should be provided.
+
+2004-11-30 Boris Kolpackov <boris@kolpackov.net>
+
+ * tests/scripts/functions/abspath: New file: test `abspath'
+ built-in function.
+
+ * tests/scripts/functions/realpath: New file: test `realpath'
+ built-in function.
+
+2004-11-28 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252;
+ this doesn't really test anything useful in UNIX but...
+
+ * scripts/variables/SHELL: New file: test proper handling of SHELL
+ according to POSIX rules. Fixes bug #1276.
+
+2004-10-21 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/functions/word: Test $(firstword ) and $(lastword ).
+
+2004-10-05 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/patspecific_vars: Test simple/recursive
+ variable expansion.
+
+2004-09-28 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/include: Test dontcare flag inheritance
+ when rebuilding makefiles.
+
+2004-09-27 Boris Kolpackov <boris@kolpackov.net>
+
+ * scripts/features/patspecific_vars: Test exported variables.
+
+2004-09-22 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (run_make_test): Don't add newlines to the
+ makestring or answer if they are completely empty.
+
+ * scripts/features/patternrules: Rename from implicit_prereq_eval.
+
+ * scripts/test_template: Rework the template.
+
+2004-09-21 Boris Kolpackov <boris@kolpackov.net>
+
+ * run_make_tests.pl: Change `#!/usr/local/bin/perl' to be
+ `#!/usr/bin/env perl'.
+
+ * scripts/features/implicit_prereq_eval: Test implicit rule
+ prerequisite evaluation code.
+
+2004-09-21 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (run_make_test): Enhance to allow the make
+ string to be undef: in that case it reuses the previous make
+ string. Allows multiple tests on the same makefile.
+
+ * scripts/variables/flavors: Add some tests for prefix characters
+ interacting with define/endef variables.
+
+2004-09-20 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/substitution: Rewrite to use run_make_test()
+ interface, and add test for substitution failures reported by
+ Markus Mauhart <qwe123@chello.at>.
+
+2004-03-22 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (run_each_test, toplevel, compare_output): Change
+ to track both the testing categories _AND_ the number of
+ individual tests, and report both sets of numbers.
+
+2004-02-21 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/origin: Set our own environment variable
+ rather than relying on $HOME.
+
+2004-01-21 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/conditionals: Test arguments to ifn?def which
+ contain whitespace (such as a function that is evaluated). Bug
+ #7257.
+
+2004-01-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/order_only: Test order-only prerequisites in
+ pattern rules (patch #2349).
+
+2003-11-02 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/if: Test if on conditionals with trailing
+ whitespace--bug #5798.
+
+ * scripts/functions/eval: Test eval in a non-file context--bug #6195.
+
+2003-04-19 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/patspecific_vars: Test multiple patterns
+ matching the same target--Bug #1405.
+
+2003-04-09 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (set_more_defaults): A new $port_type of
+ 'OS/2' for (surprise!) OS/2. Also choose a wait time of 2 seconds
+ for OS/2.
+
+2003-03-28 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/targets/SECONDARY: Test the "global" .SECONDARY (with
+ not prerequisites)--Bug #2515.
+
+2003-01-30 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Test very long target-specific
+ variable definition lines (longer than the default make buffer
+ length). Tests patch # 1022.
+
+ * scripts/functions/eval: Test very recursive $(eval ...) calls
+ with simple variable expansion (bug #2238).
+
+ * scripts/functions/word: Test error handling for word and
+ wordlist functions (bug #2407).
+
+2003-01-22 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/call: Test recursive argument masking (bug
+ #1744).
+
+2002-10-25 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/eval: Test using $(eval ...) inside
+ conditionals (Bug #1516).
+
+2002-10-14 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-t: Add a test for handling -t on targets
+ with no commands (Bug #1418).
+
+2002-10-13 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Add a test for exporting
+ target-specific vars (Bug #1391).
+
+2002-10-05 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Add tests for $$(@), $${@}, $${@D},
+ and $${@F}.
+
+2002-09-23 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/escape: Test handling of escaped comment
+ characters in targets and prerequisites.
+
+2002-09-18 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/export: Test export/unexport of multiple
+ variables in a single command.
+
+2002-09-17 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Tests for Bug #940: test
+ target-specific and pattern-specific variables in conjunction with
+ double-colon targets.
+
+2002-09-10 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (compare_output): Match the new format for time
+ skew error messages.
+
+ * scripts/features/export: Created. Add tests for export/unexport
+ capabilities, including exporting/unexporting expanded variables.
+
+ * scripts/features/conditionals: Add a test for expanded variables
+ in ifdef conditionals.
+
+2002-09-04 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/reinvoke: Change touch/sleep combos to utouch
+ invocations.
+ * scripts/features/vpathgpath: Ditto.
+ * scripts/features/vpathplus: Ditto.
+ * scripts/options/dash-n: Ditto.
+ * scripts/targets/INTERMEDIATE: Ditto.
+ * scripts/targets/SECONDARY: Ditto.
+
+ * scripts/options/dash-t: Added a test for the -t bug fixed by
+ Henning Makholm. This test was also contributed by Henning.
+
+ * scripts/misc/general4: Add a test suite for obscure algorithmic
+ features of make. First test: make sure creation subdirectories
+ as prerequisites of targets works properly.
+
+ * scripts/misc/version: Remove this bogus test.
+
+2002-08-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/misc/general3: Add a test for makefiles that don't end
+ in newlines.
+
+ * scripts/variables/special: Create tests for the special
+ variables (.VARIABLES and .TARGETS). Comment out .TARGETS test
+ for now as it's not yet supported.
+
+2002-08-01 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-B: Add a test for the new -B option.
+
+2002-07-11 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (valid_option): Add support for Valgrind. Use
+ -valgrind option to the test suite.
+ (set_more_defaults): Set up the file descriptor to capture
+ Valgrind output. We have to unset its close-on-exec flag; we
+ hardcode the value for F_SETFD (2) rather than load it; hopefully
+ this will help us avoid breaking the Windows/DOS test suite.
+
+2002-07-10 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Add some tests for $$@, $$(@D), and
+ $$(@F).
+
+ * test_driver.pl (utouch): Create a new function that creates a
+ file with a specific timestamp offset. Use of this function will
+ let us avoid lots of annoying sleep() invocations in the tests
+ just to get proper timestamping, which will make the tests run a
+ lot faster. So far it's only used in the automatic test suite.
+
+2002-07-09 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/automatic: Create a test for automatic variables.
+
+2002-07-08 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/order_only: Test new order-only prerequisites.
+
+2002-07-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/eval: Test new function.
+ * scripts/functions/value: Test new function.
+ * scripts/variables/MAKEFILE_LIST: Test new variable.
+
+2002-04-28 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/call: New test: transitive closure
+ implementation using $(call ...) to test variable recursion.
+
+2002-04-21 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (compare_dir_tree): Ignore CVS and RCS
+ directories in the script directories.
+
+2001-05-02 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/flavors: Test define/endef scripts where only
+ one of the command lines is quiet.
+
+2000-06-22 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-q: New file; test the -q option. Includes
+ a test for PR/1780.
+
+2000-06-21 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Added a test for PR/1709: allowing
+ semicolons in target-specific variable values.
+
+2000-06-19 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/addsuffix: Test for an empty final argument.
+ Actually this bug might have happened for any function, but this
+ one was handy.
+
+2000-06-17 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * scripts/options/general: If parallel jobs are not supported,
+ expect a warning message from Make.
+
+2000-06-15 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * scripts/options/general: Don't try -jN with N != 1 if parallel
+ jobs are not supported.
+
+2000-05-24 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/general: Test general option processing (PR/1716).
+
+2000-04-11 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/strip: Test empty value to strip (PR/1689).
+
+2000-04-08 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * scripts/features/reinvoke: Sleep before updating the target
+ files in the first test, to ensure its time stamp really gets
+ newer; otherwise Make might re-exec more than once.
+
+2000-04-07 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * scripts/features/double_colon: Don't run the parallel tests if
+ parallel jobs aren't supported.
+
+2000-04-04 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/word: wordlist doesn't swap arguments anymore.
+
+2000-03-27 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/statipattrules: Test that static pattern rules
+ whose prerequisite patterns resolve to empty strings throw an
+ error (instead of dumping core). Fixes PR/1670.
+
+ * scripts/features/reinvoke: Make more robust by touching "b"
+ first, to ensure it's not newer than "a".
+ Reported by Marco Franzen <Marco.Franzen@Thyron.com>.
+ * scripts/options/dash-n: Ditto.
+
+ * scripts/functions/call: Whoops. The fix to PR/1527 caused
+ recursive invocations of $(call ...) to break. I can't come up
+ with any way to get both working at the same time, so I backed out
+ the fix to 1527 and added a test case for recursive calls. This
+ also tests the fix for PR/1610.
+
+ * scripts/features/double_colon: Test that circular dependencies
+ in double-colon rule sets are detected correctly (PR/1671).
+
+2000-03-26 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/targets/INTERMEDIATE: Test that make doesn't remove
+ .INTERMEDIATE files when given on the command line (PR/1669).
+
+2000-03-08 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-k: Add a test for error detection by
+ multiple targets depending on the same prerequisite with -k.
+ For PR/1634.
+
+2000-02-07 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/escape: Add a test for backslash-escaped spaces
+ in a target name (PR/1586).
+
+2000-02-04 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/patspecific_vars: Add a test for pattern-specific
+ target variables inherited from the parent target (PR/1407).
+
+2000-02-02 Paul D. Smith <psmith@gnu.org>
+
+ * run_make_tests.pl (set_more_defaults): Hard-code the LANG to C
+ to make sure sorting order, etc. is predictable.
+ Reported by Andreas Jaeger <aj@suse.de>.
+
+ * run_make_tests.pl (set_more_defaults): Set the $wtime variable
+ depending on the OS. Eli Zaretskii <eliz@is.elta.co.il> reports
+ this seems to need to be *4* on DOS/Windows, not just 2. Keep it
+ 1 for other systems.
+ * scripts/features/vpathplus (touchfiles): Use the $wtime value
+ instead of hardcoding 2.
+ * scripts/targets/SECONDARY: Ditto.
+ * scripts/targets/INTERMEDIATE: Ditto.
+
+2000-01-27 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (toplevel): Don't try to run test scripts which
+ are really directories.
+
+2000-01-23 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/include: Remove a check; the fix caused more
+ problems than the error, so I removed it and removed the test for
+ it.
+
+2000-01-11 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/call: Add a test for PR/1517 and PR/1527: make
+ sure $(call ...) doesn't eval its arguments and that you can
+ invoke foreach from it without looping forever.
+
+1999-12-15 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/targets/INTERMEDIATE: Add a test for PR/1423: make sure
+ .INTERMEDIATE settings on files don't disable them as implicit
+ intermediate possibilities.
+
+1999-12-01 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/double_colon: Add a test for PR/1476: Try
+ double-colon rules as non-goal targets and during parallel builds
+ to make sure they're handled serially.
+
+1999-11-17 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/functions/if: Add a test for PR/1429: put some text
+ after an if-statement to make sure it works.
+
+ * scripts/features/targetvars: Add a test for PR/1380: handling +=
+ in target-specific variable definitions correctly.
+
+1999-10-15 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/variables/MAKEFILES: This was really broken: it didn't
+ test anything at all, really. Rewrote it, plus added a test for
+ PR/1394.
+
+1999-10-13 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/options/dash-n: Add a test for PR/1379: "-n doesn't
+ behave properly when used with recursive targets".
+
+1999-10-08 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/targetvars: Add a check for PR/1378:
+ "Target-specific vars don't inherit correctly"
+
+1999-09-29 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (get_osname): Change $fancy_file_names to
+ $short_filenames and reverse the logic.
+ (run_each_test): Change test of non-existent $port_host to use
+ $short_filenames--problem reported by Eli Zaretskii.
+
+1999-09-23 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/parallelism: Add a check to ensure that the
+ jobserver works when we re-invoke. Also cleaned up the tests a
+ little, reducing the number of rules we use so the test won't need
+ as many "sleep" commands.
+
+1999-09-16 Paul D. Smith <psmith@gnu.org>
+
+ * scripts/features/reinvoke: Remove invocations of "touch" in
+ makefiles. See the comments on the touch function rewrite below.
+ Note that UNIX touch behaves the same way if the file already
+ exists: it sets the time to the _local_ time. We don't want
+ this. This is probably a good tip for makefile writers in
+ general, actually... where practical.
+ * scripts/options/dash-l: Ditto.
+ * scripts/options/dash-n: Ditto.
+
+ * test_driver.pl (run_each_test): In retrospect, I don't like the
+ .lN/.bN/.dN postfix required by DOS. So, for non-DOS systems I
+ changed it back to use .log, .base, and .diff.
+
+ * run_make_tests.pl (set_more_defaults): Move the check for the
+ make pathname to here from set_defaults (that's too early since it
+ happens before the command line processing).
+ Create a new variable $port_type, calculated from $osname, to
+ specify what kind of system we're running on. We should integrate
+ the VOS stuff here, too.
+ (valid_option): Comment out the workdir/-work stuff so people
+ won't be fooled into thinking it works... someone needs to fix
+ this, though!
+
+ * scripts/functions/origin: Use $port_type instead of $osname.
+ * scripts/functions/foreach: Ditto.
+ * scripts/features/default_names: Ditto.
+
+1999-09-15 Paul D. Smith <psmith@gnu.org>
+
+ * test_driver.pl (touch): Rewrite this function. Previously it
+ used to use utime() to hard-set the time based on the current
+ local clock, or, if the file didn't exist, it merely created it.
+ This mirrors exactly what real UNIX touch does, but it fails badly
+ on networked filesystems where the FS server clock is skewed from
+ the local clock: normally modifying a file causes it to get a mod
+ time based on the _server's_ clock. Hard-setting it based on the
+ _local_ clock causes gratuitous errors and makes the tests
+ unreliable except on local filesystems. The new function will
+ simply modify the file, allowing the filesystem to set the mod
+ time as it sees fit.
+
+ * scripts/features/parallelism: The second test output could
+ change depending on how fast some scripts completed; use "sleep"
+ to force the order we want.
+
+ * test_driver.pl (toplevel): A bug in Perl 5.000 to Perl 5.004
+ means that "%ENV = ();" doesn't do the right thing. This worked
+ in Perl 4 and was fixed in Perl 5.004_01, but use a loop to delete
+ the environment rather than require specific versions.
+
+ * run_make_tests.pl (set_more_defaults): Don't use Perl 5 s///
+ modifier "s", so the tests will run with Perl 4.
+ (set_more_defaults): Set $pure_log to empty if there's no -logfile
+ option in PURIFYOPTIONS.
+ (setup_for_test): Don't remove any logs unless $pure_log is set.
+
+1999-09-15 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * scripts/features/reinvoke: Put the SHELL definition in the right
+ test makefile.
+
+1999-09-15 Paul D. Smith <psmith@gnu.org>
+
+ ChangeLog file for the test suite created.
+
+
+Copyright (C) 1992-2014 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3 of the License, or (at your option) any later
+version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/tests/NEWS b/tests/NEWS
new file mode 100644
index 0000000..584f4a4
--- /dev/null
+++ b/tests/NEWS
@@ -0,0 +1,178 @@
+Changes from 0.4.9 to 3.78 (Sep 6, 1999):
+
+ Lots of new tests. Renamed to follow the GNU make scheme. Also
+ added some support for using Purify with make.
+
+ Rob Tulloh contributed some changes to get the test suite running on
+ NT; I tweaked them a bit (hopefully I didn't break anything!) Note
+ that NT doesn't grok the self-exec funkiness that Unix shells use,
+ so instead I broke that out into a separate shell script
+ "run_make_tests" that invokes perl with the (renamed) script
+ run_make_tests.pl.
+
+ Eli Zaretski contributed changes to get the test suite running on
+ DOS with DJGPP. I also meddled in these somewhat.
+
+ If you're on DOS or NT you should run "perl.exe run_make_tests.pl ..."
+ If you're on Unix, you can continue to run "./run_make_tests ..." as
+ before.
+
+Changes from 0.4.8 to 0.4.9 (May 14, 1998):
+
+ Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+ blame for problems in this version :).
+
+ Add some perl to test_driver.pl to strip out GNU make clock skew
+ warning messages from the output before comparing it to the
+ known-good output.
+
+ A new test for escaped :'s in filenames (someone on VMS found this
+ didn't work anymore in 3.77): scripts/features/escape.
+
+Changes from 0.4.7 to 0.4.8 (May 14, 1998):
+
+ Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+ blame for problems in this version :).
+
+ New tests for features to be included in GNU make 3.77.
+
+Changes from 0.4.6 to 0.4.7 (August 18, 1997):
+
+ Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+ blame for problems in this version :).
+
+ Reworked some tests to make sure they all work with both perl4 and perl5.
+
+ Work around a bug in perl 5.004 which doesn't clean the environment
+ correctly in all cases (fixed in at least 5.004_02).
+
+ Updated functions/strip to test for newline stripping.
+
+ Keep a $PURIFYOPTIONS env variable if present.
+
+Changes from 0.4.5 to 0.4.6 (April 07, 1997):
+
+ Release by Paul D. Smith <psmith@baynetworks.com>; I'm the one to
+ blame for problems in this version :).
+
+ Updated to work with GNU make 3.76 (and pretests).
+
+ Added new tests and updated existing ones. Note that the new tests
+ weren't tested with perl 4, however I think they should work.
+
+ Ignore any tests whose filenames end in "~", so that Emacs backup
+ files aren't run.
+
+Changes from 0.4.4 to 0.4.5 (April 29, 1995):
+
+ Updated to be compatible with perl 5.001 as well as 4.036.
+
+ Note: the test suite still won't work on 14-char filesystems
+ (sorry, Kaveh), but I will get to it.
+
+ Also, some tests and stuff still haven't made it in because I
+ haven't had time to write the test scripts for them. But they,
+ too, will get in eventually. Contributions of scripts (i.e., tests
+ that I can just drop in) are particularly welcome and will be
+ incorporated immediately.
+
+Changes from 0.4.3 to 0.4.4 (March 1995):
+
+ Updated for changes in make 3.72.12, and to ignore CVS directories
+ (thanks go to Jim Meyering for the patches for this).
+
+ Fixed uname call to not make a mess on BSD/OS 2.0 (whose uname -a
+ is very verbose). Let me know if this doesn't work correctly on
+ your system.
+
+ Changed to display test name while it is running, not just when it
+ finishes.
+
+ Note: the test suite still won't work on 14-char filesystems
+ (sorry, Kaveh), but I will get to it.
+
+ Also, some tests and stuff still haven't made it in because I
+ haven't had time to write the test scripts for them. But they,
+ too, will get in eventually.
+
+Changes from 0.4 to 0.4.3 (October 1994):
+
+ Fixed bugs (like dependencies on environment variables).
+
+ Caught up with changes in make.
+
+ The load_limit test should now silently ignore a failure due to
+ make not being able to read /dev/kmem.
+
+ Reorganized tests into subdirs and renamed lots of things so that
+ those poor souls who still have to deal with 14-char filename
+ limits won't hate me any more. Thanks very much to Kaveh R. Ghazi
+ <ghazi@noc.rutgers.edu> for helping me with the implementation and
+ testing of these changes, and for putting up with all my whining
+ about it...
+
+ Added a $| = 1 so that systems that don't seem to automatically
+ flush their output for some reason will still print all the
+ output. I'd hate for someone to miss out on the smiley that
+ you're supposed to get when all the tests pass... :-)
+
+Changes from 0.3 to 0.4 (August 1993):
+
+ Lost in the mists of time (and my hurry to get it out before I
+ left my job).
+
+Changes from 0.2 to 0.3 (9-30-92):
+
+ Several tests fixed to match the fact that MAKELEVEL > 0 or -C now
+ imply -w.
+
+ parallel_execution test fixed to not use double colon rules any
+ more since their behavior has changed.
+
+ errors_in_commands test fixed to handle different error messages
+ and return codes from rm.
+
+ Several tests fixed to handle -make_path with a relative path
+ and/or a name other than "make" for make.
+
+ dash-e-option test fixed to use $PATH instead of $USER (since the
+ latter does not exist on some System V systems). This also
+ removes the dependency on getlogin (which fails under certain
+ weird conditions).
+
+ test_driver_core changed so that you can give a test name like
+ scripts/errors_in_commands and it will be handled correctly (handy
+ if you have a shell with filename completion).
+
+Changes from 0.1 to 0.2 (5-4-92):
+
+ README corrected to require perl 4.019, not 4.010.
+
+ -make_path replaces -old.
+
+ errors_in_commands test updated for change in format introduced in
+ make 3.62.6.
+
+ test_driver_core now uses a better way of figuring what OS it is
+ running on (thanks to meyering@cs.utexas.edu (Jim Meyering) for
+ suggesting this, as well as discovering the hard way that the old
+ way (testing for /mnt) fails on his machine).
+
+ Some new tests were added.
+
+
+-------------------------------------------------------------------------------
+Copyright (C) 1992-2014 Free Software Foundation, Inc.
+This file is part of GNU Make.
+
+GNU Make is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 3 of the License, or (at your option) any later
+version.
+
+GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..3b699ee
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,102 @@
+The test suite was originally written by Steve McGee and Chris Arthur.
+It is covered by the GNU General Public License (Version 2), described
+in the file COPYING. It has been maintained as part of GNU make proper
+since GNU make 3.78.
+
+This entire test suite, including all test files, are copyright and
+distributed under the following terms:
+
+ -----------------------------------------------------------------------------
+ Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ This file is part of GNU Make.
+
+ GNU Make is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3 of the License, or (at your option) any later
+ version.
+
+ GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <http://www.gnu.org/licenses/>.
+ -----------------------------------------------------------------------------
+
+The test suite requires Perl. These days, you should have at least Perl
+5.004 (available from ftp.gnu.org, and portable to many machines). It
+used to work with Perl 4.036 but official support for Perl 4.x was
+abandoned a long time ago, due to lack of testbeds, as well as interest.
+
+The test suite assumes that the first "diff" it finds on your PATH is
+GNU diff, but that only matters if a test fails.
+
+To run the test suite on a UNIX system, use "perl ./run_make_tests"
+(or just "./run_make_tests" if you have a perl on your PATH).
+
+To run the test suite on Windows NT or DOS systems, use
+"perl.exe ./run_make-tests.pl".
+
+By default, the test engine picks up the first executable called "make"
+that it finds in your path. You may use the -make_path option (i.e.,
+"perl run_make_tests -make_path /usr/local/src/make-3.78/make") if
+you want to run a particular copy. This now works correctly with
+relative paths and when make is called something other than "make" (like
+"gmake").
+
+Tests cannot end with a "~" character, as the test suite will ignore any
+that do (I was tired of having it run my Emacs backup files as tests :))
+
+Also, sometimes the tests may behave strangely on networked
+filesystems. You can use mkshadow to create a copy of the test suite in
+/tmp or similar, and try again. If the error disappears, it's an issue
+with your network or file server, not GNU make (I believe). This
+shouldn't happen very often anymore: I've done a lot of work on the
+tests to reduce the impacts of this situation.
+
+The options/dash-l test will not really test anything if the copy of
+make you are using can't obtain the system load. Some systems require
+make to be setgid sys or kmem for this; if you don't want to install
+make just to test it, make it setgid to kmem or whatever group /dev/kmem
+is (i.e., "chgrp kmem make;chmod g+s make" as root). In any case, the
+options/dash-l test should no longer *fail* because make can't read
+/dev/kmem.
+
+A directory named "work" will be created when the tests are run which
+will contain any makefiles and "diff" files of tests that fail so that
+you may look at them afterward to see the output of make and the
+expected result.
+
+There is a -help option which will give you more information about the
+other possible options for the test suite.
+
+
+Open Issues
+-----------
+
+The test suite has a number of problems which should be addressed. One
+VERY serious one is that there is no real documentation. You just have
+to see the existing tests. Use the newer tests: many of the tests
+haven't been updated to use the latest/greatest test methods. See the
+ChangeLog in the tests directory for pointers.
+
+The second serious problem is that it's not parallelizable: it scribbles
+all over its installation directory and so can only test one make at a
+time. The third serious problem is that it's not relocatable: the only
+way it works when you build out of the source tree is to create
+symlinks, which doesn't work on every system and is bogus to boot. The
+fourth serious problem is that it doesn't create its own sandbox when
+running tests, so that if a test forgets to clean up after itself that
+can impact future tests.
+
+
+Bugs
+----
+
+Any complaints/suggestions/bugs/etc. for the test suite itself (as
+opposed to problems in make that the suite finds) should be handled the
+same way as normal GNU make bugs/problems (see the README for GNU make).
+
+
+ Paul D. Smith
+ Chris Arthur
diff --git a/tests/config-flags.pm b/tests/config-flags.pm
new file mode 100644
index 0000000..903c468
--- /dev/null
+++ b/tests/config-flags.pm
@@ -0,0 +1,19 @@
+# This is a -*-perl-*- script
+#
+# Set variables that were defined by configure, in case we need them
+# during the tests.
+
+%CONFIG_FLAGS = (
+ AM_LDFLAGS => '-Wl,--export-dynamic',
+ AR => 'ar',
+ CC => 'gcc',
+ CFLAGS => '-g -O2',
+ CPP => 'gcc -E',
+ CPPFLAGS => '',
+ GUILE_CFLAGS => '-pthread -I/usr/include/guile/2.0 ',
+ GUILE_LIBS => '-lguile-2.0 -lgc ',
+ LDFLAGS => '',
+ LIBS => '-ldl '
+);
+
+1;
diff --git a/tests/config-flags.pm.in b/tests/config-flags.pm.in
new file mode 100644
index 0000000..29ba146
--- /dev/null
+++ b/tests/config-flags.pm.in
@@ -0,0 +1,19 @@
+# This is a -*-perl-*- script
+#
+# Set variables that were defined by configure, in case we need them
+# during the tests.
+
+%CONFIG_FLAGS = (
+ AM_LDFLAGS => '@AM_LDFLAGS@',
+ AR => '@AR@',
+ CC => '@CC@',
+ CFLAGS => '@CFLAGS@',
+ CPP => '@CPP@',
+ CPPFLAGS => '@CPPFLAGS@',
+ GUILE_CFLAGS => '@GUILE_CFLAGS@',
+ GUILE_LIBS => '@GUILE_LIBS@',
+ LDFLAGS => '@LDFLAGS@',
+ LIBS => '@LIBS@'
+);
+
+1;
diff --git a/tests/config_flags_pm.com b/tests/config_flags_pm.com
new file mode 100755
index 0000000..3f5adff
--- /dev/null
+++ b/tests/config_flags_pm.com
@@ -0,0 +1,53 @@
+$!
+$! config_flags_pm.com - Build config-flags.pm on VMS.
+$!
+$! Just good enough to run the self tests for now.
+$!
+$! Copyright (C) 2014 Free Software Foundation, Inc.
+$! This file is part of GNU Make.
+$!
+$! GNU Make is free software; you can redistribute it and/or modify it under
+$! the terms of the GNU General Public License as published by the Free Software
+$! Foundation; either version 3 of the License, or (at your option) any later
+$! version.
+$!
+$! GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+$! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+$! FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+$! details.
+$!
+$! You should have received a copy of the GNU General Public License along with
+$! this program. If not, see <http://www.gnu.org/licenses/>.
+$!
+$!
+$ open/read cfpm_in config-flags.pm.in
+$!
+$ outfile = "sys$disk:[]config-flags.pm"
+$!
+$ cflags = "/include=([],[.glob]"
+$!
+$ create 'outfile'
+$ open/append cfpm 'outfile'
+$!
+$cfpm_read_loop:
+$ read cfpm_in/end=cfpm_read_loop_end line_in
+$ line_in_len = f$length(line_in)
+$ if f$locate("@", line_in) .lt. line_in_len
+$ then
+$ part1 = f$element(0, "@", line_in)
+$ key = f$element(1, "@", line_in)
+$ part2 = f$element(2, "@", line_in)
+$ value = ""
+$ if key .eqs. "CC" then value = "CC"
+$ if key .eqs. "CPP" then value = "CPP"
+$ if key .eqs. "CFLAGS" then value = cflags
+$ if key .eqs. "GUILE_CFLAGS" then value = cflags
+$ write cfpm part1, value, part2
+$ goto cfpm_read_loop
+$ endif
+$ write cfpm line_in
+$ goto cfpm_read_loop
+$cfpm_read_loop_end:
+$ close cfpm_in
+$ close cfpm
+$!
diff --git a/tests/guile.supp b/tests/guile.supp
new file mode 100644
index 0000000..9e9b01b
--- /dev/null
+++ b/tests/guile.supp
@@ -0,0 +1,31 @@
+# Guile valgrind suppression file
+# Created with Guile 1.8.7
+
+# --- Garbage collection
+{
+ guilegc
+ Memcheck:Cond
+ ...
+ fun:scm_gc_for_newcell
+}
+{
+ guilegc
+ Memcheck:Value4
+ ...
+ fun:scm_gc_for_newcell
+}
+{
+ guilegc
+ Memcheck:Value8
+ ...
+ fun:scm_gc_for_newcell
+}
+
+
+# -- scm_alloc_struct
+{
+ guileheap
+ Memcheck:Leak
+ ...
+ fun:scm_alloc_struct
+}
diff --git a/tests/mkshadow b/tests/mkshadow
new file mode 100755
index 0000000..aa9b3bc
--- /dev/null
+++ b/tests/mkshadow
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Simple script to make a "shadow" test directory, using symbolic links.
+# Typically you'd put the shadow in /tmp or another local disk
+#
+# Copyright (C) 1992-2014 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+case "$1" in
+ "") echo 'Usage: mkshadow <destdir>'; exit 1 ;;
+esac
+
+dest="$1"
+
+if [ ! -d "$dest" ]; then
+ echo "Destination directory '$dest' must exist!"
+ exit 1
+fi
+
+if [ ! -f run_make_tests ]; then
+ echo "The current directory doesn't appear to contain the test suite!"
+ exit 1
+fi
+
+suite=`pwd | sed 's%^/tmp_mnt%%'`
+name=`basename "$suite"`
+
+files=`echo *`
+
+set -e
+
+mkdir "$dest/$name"
+cd "$dest/$name"
+
+ln -s "$suite" .testdir
+
+for f in $files; do
+ ln -s .testdir/$f .
+done
+
+rm -rf work
+
+echo "Shadow test suite created in '$dest/$name'."
+exit 0
diff --git a/tests/run_make_tests b/tests/run_make_tests
new file mode 100755
index 0000000..b68b784
--- /dev/null
+++ b/tests/run_make_tests
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec perl $0.pl ${1+"$@"}
diff --git a/tests/run_make_tests.com b/tests/run_make_tests.com
new file mode 100755
index 0000000..2f17f7f
--- /dev/null
+++ b/tests/run_make_tests.com
@@ -0,0 +1,272 @@
+$! Test_make.com
+$!
+$! This is a wrapper for the GNU make perl test programs on VMS.
+$!
+$! Parameter "-help" for description on how to use described below.
+$!
+$! Copyright (C) 2014 Free Software Foundation, Inc.
+$! This file is part of GNU Make.
+$!
+$! GNU Make is free software; you can redistribute it and/or modify it under
+$! the terms of the GNU General Public License as published by the Free Software
+$! Foundation; either version 3 of the License, or (at your option) any later
+$! version.
+$!
+$! GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+$! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+$! FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+$! details.
+$!
+$! You should have received a copy of the GNU General Public License along with
+$! this program. If not, see <http://www.gnu.org/licenses/>.
+$!
+$!
+$! Allow more than 8 paramters with using commas as a delimiter.
+$!
+$ params = "''p1',''p2',''p3',''p4',''p5',''p6',''p7',''p8'"
+$!
+$ test_flags = ",verbose,detail,keep,usage,help,debug,"
+$ test_flags_len = f$length(test_flags)
+$ verbose_flag = ""
+$ detail_flag = ""
+$ keep_flag = ""
+$ usage_flag = ""
+$ help_flag = ""
+$ debug_flag = ""
+$!
+$ ignored_options = "profile,make,srcdir,valgrind,memcheck,massif,"
+$ ignored_option_len = f$length(ignored_options)
+$!
+$ testname = ""
+$ make :== $bin:make.exe"
+$!
+$ i = 0
+$param_loop:
+$ param = f$element(i, ",", params)
+$ i = i + 1
+$ if param .eqs. "" then goto param_loop
+$ if param .eqs. "," then goto param_loop_end
+$ param_len = f$length(param)
+$ if f$locate("/", param) .lt. param_len
+$ then
+$ if testname .nes. ""
+$ then
+$ write sys$output "Only the last test name specified will be run!"
+$ endif
+$ testname = param
+$ goto param_loop
+$ endif
+$ lc_param = f$edit(param,"LOWERCASE") - "-"
+$ if f$locate(",''lc_param',", ignored_options) .lt. ignored_option_len
+$ then
+$ write sys$output "parameter ''param' is ignored on VMS for now."
+$ goto param_loop
+$ endif
+$ if f$locate(",''lc_param',", test_flags) .lt. test_flags_len
+$ then
+$ 'lc_param'_flag = "-" + lc_param
+$ goto param_loop
+$ endif
+$ write sys$output "parameter ''param' is not known to VMS."
+$ goto param_loop
+$!
+$param_loop_end:
+$!
+$no_gnv = 1
+$no_perl = 1
+$!
+$! Find GNV 2.1.3 + manditory updates
+$! If properly updated, the GNV$GNU logical name is present.
+$! Updated GNV utilities have a gnv$ prefix on them.
+$ gnv_root = f$trnlnm("GNV$GNU", "LNM$SYSTEM_TABLE")
+$ if gnv_root .nes. ""
+$ then
+$ no_gnv = 0
+$ ! Check for update ar utility.
+$ new_ar = "gnv$gnu:[usr.bin]gnv$ar.exe"
+$ if f$search(new_ar) .nes. ""
+$ then
+$ ! See if a new port of ar exists.
+$ ar :== $'new_ar'
+$ else
+$ ! Fall back to legacy GNV AR wrapper.
+$ old_ar = "gnv$gnu:[bin]ar.exe"
+$ if f$search(old_ar) .nes. ""
+$ then
+$ ar :== $'old_ar'
+$ else
+$ no_gnv = 1
+$ endif
+$ endif
+$ ! Check for updated bash
+$ if no_gnv .eq. 0
+$ then
+$ new_bash = "gnv$gnu:[bin]gnv$bash.exe"
+$ if f$search(new_bash) .nes. ""
+$ then
+$ bash :== $'new_bash'
+$ sh :== $'new_bash'
+$ else
+$ no_gnv = 1
+$ endif
+$ endif
+$ ! Check for updated coreutils
+$ if no_gnv .eq. 0
+$ then
+$ new_cat = "gnv$gnu:[bin]gnv$cat.exe"
+$ if f$search(new_cat) .nes. ""
+$ then
+$ cat :== $'new_cat'
+$ cp :== $gnv$gnu:[bin]gnv$cp.exe
+$ echo :== $gnv$gnu:[bin]gnv$echo.exe
+$ false :== $gnv$gnu:[bin]gnv$false.exe
+$ true :== $gnv$gnu:[bin]gnv$true.exe
+$ touch :== $gnv$gnu:[bin]gnv$touch.exe
+$ mkdir :== $gnv$gnu:[bin]gnv$mkdir.exe
+$ rm :== $gnv$gnu:[bin]gnv$rm.exe
+$ sleep :== $gnv$gnu:[bin]gnv$sleep.exe
+$ else
+$ no_gnv = 1
+$ endif
+$ endif
+$ ! Check for updated diff utility.
+$ if no_gnv .eq. 0
+$ then
+$ new_diff = "gnv$gnu:[usr.bin]gnv$diff.exe"
+$ if f$search(new_diff) .nes. ""
+$ then
+$ ! See if a new port of diff exists.
+$ diff :== $'new_diff'
+$ else
+$ ! Fall back to legacy GNV diff
+$ old_diff = "gnv$gnu:[bin]diff.exe"
+$ if f$search(old_diff) .nes. ""
+$ then
+$ diff :== $'old_diff'
+$ else
+$ no_gnv = 1
+$ endif
+$ endif
+$ endif
+$ endif
+$!
+$if no_gnv
+$then
+$ write sys$output "Could not find an up to date GNV installed!"
+$ help_flag = 1
+$endif
+$!
+$! Find perl 5.18.1 or later.
+$!
+$! look in perl_root:[000000]perl_setup.com
+$ perl_root = f$trnlnm("perl_root")
+$ ! This works with known perl installed from PCSI kits.
+$ if perl_root .nes. ""
+$ then
+$ perl_ver = f$element(1, ".", perl_root)
+$ if f$locate("-", perl_ver) .lt. f$length(perl_ver)
+$ then
+$ no_perl = 0
+$ endif
+$ endif
+$ if no_perl
+$ then
+$! look for sys$common:[perl-*]perl_setup.com
+$ perl_setup = f$search("sys$common:[perl-*]perl_setup.com")
+$ if perl_setup .eqs. ""
+$ then
+$ if gnv_root .nes. ""
+$ then
+$ gnv_device = f$parse(gnv_root,,,"DEVICE")
+$ perl_templ = "[vms$common.perl-*]perl_setup.com"
+$ perl_search = f$parse(perl_templ, gnv_device)
+$ perl_setup = f$search(perl_search)
+$ endif
+$ endif
+$ if perl_setup .nes. ""
+$ then
+$ @'perl_setup'
+$ no_perl = 0
+$ endif
+$ endif
+$!
+$ if no_perl
+$ then
+$ write sys$output "Could not find an up to date Perl installed!"
+$ help_flag = "-help"
+$ endif
+$!
+$!
+$ if help_flag .nes. ""
+$ then
+$ type sys$input
+$DECK
+This is a test script wrapper for the run_make_tests.pl script.
+
+This wrapper makes sure that the DCL symbols and logical names needed to
+run the perl script are in place.
+
+The test wrapper currently requires that the DCL symbols be global symbols.
+Those symbols will be left behind after the procedure is run.
+
+The PERL_ROOT will be set to a compatible perl if such a perl is found and
+is not the default PERL_ROOT:. This setting will persist after the test.
+
+This wrapper should be run with the default set to the base directory
+of the make source.
+
+The HELP parameter will bring up this text and then run the help script
+for the Perl wrapper. Not all options for the perl script have been
+implemented, such as valgrind or specifying the make path or source path.
+
+Running the wrapper script requires:
+ Perl 5.18 or later.
+ PCSI kits available from http://sourceforge.net/projects/vmsperlkit/files/
+
+ GNV 2.1.3 or later. GNV 3.0.1 has not tested with this script.
+ Bash 4.2.47 or later.
+ Coreutils 8.21 or later.
+ http://sourceforge.net/projects/gnv/files/
+ Read before installing:
+ http://sourceforge.net/p/gnv/wiki/InstallingGNVPackages/
+ As updates for other GNV components get posted, those updates should
+ be used.
+
+$EOD
+$ endif
+$!
+$ if no_gnv .or. no_perl then exit 44
+$!
+$!
+$ make := $bin:make.exe
+$ default = f$environment("DEFAULT")
+$ this = f$environment("PROCEDURE")
+$ on error then goto all_error
+$ set default 'f$parse(this,,,"DEVICE")''f$parse(this,,,"DIRECTORY")'
+$!
+$! Need to make sure that the config-flags.pm exists.
+$ if f$search("config-flags.pm") .eqs. ""
+$ then
+$ @config_flags_pm.com
+$ endif
+$ define/user bin 'default',gnv$gnu:[bin]
+$ define/user decc$filename_unix_noversion enable
+$ define/user decc$filename_unix_report enable
+$ define/user decc$readdir_dropdotnotype enable
+$ flags = ""
+$ if verbose_flag .nes. "" then flags = verbose_flag
+$ if detail_flag .nes. "" then flags = flags + " " + detail_flag
+$ if keep_flag .nes. "" then flags = flags + " " + keep_flag
+$ if usage_flag .nes. "" then flags = flags + " " + usage_flag
+$ if help_flag .nes. "" then flags = flags + " " + help_flag
+$ if debug_flag .nes. "" then flags = flags + " " + debug_flag
+$ flags = f$edit(flags, "TRIM, COMPRESS")
+$ if testname .nes. ""
+$ then
+$ perl run_make_tests.pl "''testname'" 'flags'
+$ else
+$ perl run_make_tests.pl 'flags'
+$ endif
+$all_error:
+$ set default 'default'
+$!
diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl
new file mode 100644
index 0000000..9468fab
--- /dev/null
+++ b/tests/run_make_tests.pl
@@ -0,0 +1,491 @@
+#!/usr/bin/env perl
+# -*-perl-*-
+
+# Test driver for the Make test suite
+
+# Usage: run_make_tests [testname]
+# [-debug]
+# [-help]
+# [-verbose]
+# [-keep]
+# [-make <make prog>]
+# (and others)
+
+# Copyright (C) 1992-2014 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+%FEATURES = ();
+
+$valgrind = 0; # invoke make with valgrind
+$valgrind_args = '';
+$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full --suppressions=guile.supp';
+$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
+$pure_log = undef;
+
+# The location of the GNU make source directory
+$srcdir = '';
+
+$command_string = '';
+
+$all_tests = 0;
+
+# rmdir broken in some Perls on VMS.
+if ($^O eq 'VMS')
+{
+ require VMS::Filespec;
+ VMS::Filespec->import();
+
+ sub vms_rmdir {
+ my $vms_file = vmspath($_[0]);
+ $vms_file = fileify($vms_file);
+ my $ret = unlink(vmsify($vms_file));
+ return $ret
+ };
+
+ *CORE::GLOBAL::rmdir = \&vms_rmdir;
+}
+
+require "test_driver.pl";
+require "config-flags.pm";
+
+# Some target systems might not have the POSIX module...
+$has_POSIX = eval { require "POSIX.pm" };
+
+#$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; };
+
+sub valid_option
+{
+ local($option) = @_;
+
+ if ($option =~ /^-make([-_]?path)?$/i) {
+ $make_path = shift @argv;
+ if (!-f $make_path) {
+ print "$option $make_path: Not found.\n";
+ exit 0;
+ }
+ return 1;
+ }
+
+ if ($option =~ /^-srcdir$/i) {
+ $srcdir = shift @argv;
+ if (! -f "$srcdir/gnumake.h") {
+ print "$option $srcdir: Not a valid GNU make source directory.\n";
+ exit 0;
+ }
+ return 1;
+ }
+
+ if ($option =~ /^-all([-_]?tests)?$/i) {
+ $all_tests = 1;
+ return 1;
+ }
+
+ if ($option =~ /^-(valgrind|memcheck)$/i) {
+ $valgrind = 1;
+ $valgrind_args = $memcheck_args;
+ return 1;
+ }
+
+ if ($option =~ /^-massif$/i) {
+ $valgrind = 1;
+ $valgrind_args = $massif_args;
+ return 1;
+ }
+
+# This doesn't work--it _should_! Someone badly needs to fix this.
+#
+# elsif ($option =~ /^-work([-_]?dir)?$/)
+# {
+# $workdir = shift @argv;
+# return 1;
+# }
+
+ return 0;
+}
+
+
+# This is an "all-in-one" function. Arguments are as follows:
+#
+# [0] (string): The makefile to be tested. undef means use the last one.
+# [1] (string): Arguments to pass to make.
+# [2] (string): Answer we should get back.
+# [3] (integer): Exit code we expect. A missing code means 0 (success)
+
+$old_makefile = undef;
+
+sub subst_make_string
+{
+ local $_ = shift;
+ $makefile and s/#MAKEFILE#/$makefile/g;
+ s/#MAKEPATH#/$mkpath/g;
+ s/#MAKE#/$make_name/g;
+ s/#PERL#/$perl_name/g;
+ s/#PWD#/$pwd/g;
+ return $_;
+}
+
+sub run_make_test
+{
+ local ($makestring, $options, $answer, $err_code, $timeout) = @_;
+
+ # If the user specified a makefile string, create a new makefile to contain
+ # it. If the first value is not defined, use the last one (if there is
+ # one).
+
+ if (! defined $makestring) {
+ defined $old_makefile
+ || die "run_make_test(undef) invoked before run_make_test('...')\n";
+ $makefile = $old_makefile;
+ } else {
+ if (! defined($makefile)) {
+ $makefile = &get_tmpfile();
+ }
+
+ # Make sure it ends in a newline and substitute any special tokens.
+ $makestring && $makestring !~ /\n$/s and $makestring .= "\n";
+ $makestring = subst_make_string($makestring);
+
+ # Populate the makefile!
+ open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
+ print MAKEFILE $makestring;
+ close(MAKEFILE) || die "Failed to write $makefile: $!\n";
+ }
+
+ # Do the same processing on $answer as we did on $makestring.
+ if (defined $answer) {
+ $answer && $answer !~ /\n$/s and $answer .= "\n";
+ $answer = subst_make_string($answer);
+ }
+
+ run_make_with_options($makefile, $options, &get_logfile(0),
+ $err_code, $timeout);
+ &compare_output($answer, &get_logfile(1));
+
+ $old_makefile = $makefile;
+ $makefile = undef;
+}
+
+# The old-fashioned way...
+sub run_make_with_options {
+ local ($filename,$options,$logname,$expected_code,$timeout) = @_;
+ local($code);
+ local($command) = $make_path;
+
+ $expected_code = 0 unless defined($expected_code);
+
+ # Reset to reflect this one test.
+ $test_passed = 1;
+
+ if ($filename) {
+ $command .= " -f $filename";
+ }
+
+ if ($options) {
+ if ($^O eq 'VMS') {
+ # Try to make sure arguments are properly quoted.
+ # This does not handle all cases.
+
+ # VMS uses double quotes instead of single quotes.
+ $options =~ s/\'/\"/g;
+
+ # If the leading quote is inside non-whitespace, then the
+ # quote must be doubled, because it will be enclosed in another
+ # set of quotes.
+ $options =~ s/(\S)(\".*\")/$1\"$2\"/g;
+
+ # Options must be quoted to preserve case if not already quoted.
+ $options =~ s/(\S+)/\"$1\"/g;
+
+ # Special fixup for embedded quotes.
+ $options =~ s/(\"\".+)\"(\s+)\"(.+\"\")/$1$2$3/g;
+
+ $options =~ s/(\A)(?:\"\")(.+)(?:\"\")/$1\"$2\"/g;
+
+ # Special fixup for misc/general4 test.
+ $options =~ s/""\@echo" "cc""/\@echo cc"/;
+ $options =~ s/"\@echo link"""/\@echo link"/;
+
+ # Remove shell escapes expected to be removed by bash
+ if ($options !~ /path=pre/) {
+ $options =~ s/\\//g;
+ }
+
+ # special fixup for options/eval
+ $options =~ s/"--eval=\$\(info" "eval/"--eval=\$\(info eval/;
+
+ print ("Options fixup = -$options-\n") if $debug;
+ }
+ $command .= " $options";
+ }
+
+ $command_string = "$command\n";
+
+ if ($valgrind) {
+ print VALGRIND "\n\nExecuting: $command\n";
+ }
+
+
+ {
+ my $old_timeout = $test_timeout;
+ $timeout and $test_timeout = $timeout;
+
+ # If valgrind is enabled, turn off the timeout check
+ $valgrind and $test_timeout = 0;
+
+ $code = &run_command_with_output($logname,$command);
+ $test_timeout = $old_timeout;
+ }
+
+ # Check to see if we have Purify errors. If so, keep the logfile.
+ # For this to work you need to build with the Purify flag -exit-status=yes
+
+ if ($pure_log && -f $pure_log) {
+ if ($code & 0x7000) {
+ $code &= ~0x7000;
+
+ # If we have a purify log, save it
+ $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : "");
+ print("Renaming purify log file to $tn\n") if $debug;
+ rename($pure_log, "$tn")
+ || die "Can't rename $log to $tn: $!\n";
+ ++$purify_errors;
+ } else {
+ unlink($pure_log);
+ }
+ }
+
+ if ($code != $expected_code) {
+ print "Error running $make_path (expected $expected_code; got $code): $command\n";
+ $test_passed = 0;
+ $runf = &get_runfile;
+ &create_file (&get_runfile, $command_string);
+ # If it's a SIGINT, stop here
+ if ($code & 127) {
+ print STDERR "\nCaught signal ".($code & 127)."!\n";
+ ($code & 127) == 2 and exit($code);
+ }
+ return 0;
+ }
+
+ if ($profile & $vos) {
+ system "add_profile $make_path";
+ }
+
+ return 1;
+}
+
+sub print_usage
+{
+ &print_standard_usage ("run_make_tests",
+ "[-make MAKE_PATHNAME] [-srcdir SRCDIR] [-memcheck] [-massif]",);
+}
+
+sub print_help
+{
+ &print_standard_help (
+ "-make",
+ "\tYou may specify the pathname of the copy of make to run.",
+ "-srcdir",
+ "\tSpecify the make source directory.",
+ "-valgrind",
+ "-memcheck",
+ "\tRun the test suite under valgrind's memcheck tool.",
+ "\tChange the default valgrind args with the VALGRIND_ARGS env var.",
+ "-massif",
+ "\tRun the test suite under valgrind's massif toool.",
+ "\tChange the default valgrind args with the VALGRIND_ARGS env var."
+ );
+}
+
+sub get_this_pwd {
+ $delete_command = 'rm -f';
+ if ($has_POSIX) {
+ $__pwd = POSIX::getcwd();
+ } elsif ($vos) {
+ $delete_command = "delete_file -no_ask";
+ $__pwd = `++(current_dir)`;
+ } else {
+ # No idea... just try using pwd as a last resort.
+ chop ($__pwd = `pwd`);
+ }
+
+ return $__pwd;
+}
+
+sub set_defaults
+{
+ # $profile = 1;
+ $testee = "GNU make";
+ $make_path = "make";
+ $tmpfilesuffix = "mk";
+ $pwd = &get_this_pwd;
+}
+
+sub set_more_defaults
+{
+ local($string);
+ local($index);
+
+ # find the type of the port. We do this up front to have a single
+ # point of change if it needs to be tweaked.
+ #
+ # This is probably not specific enough.
+ #
+ if ($osname =~ /Windows/i || $osname =~ /MINGW32/i || $osname =~ /CYGWIN_NT/i) {
+ $port_type = 'W32';
+ }
+ # Bleah, the osname is so variable on DOS. This kind of bites.
+ # Well, as far as I can tell if we check for some text at the
+ # beginning of the line with either no spaces or a single space, then
+ # a D, then either "OS", "os", or "ev" and a space. That should
+ # match and be pretty specific.
+ elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) {
+ $port_type = 'DOS';
+ }
+ # Check for OS/2
+ elsif ($osname =~ m%OS/2%) {
+ $port_type = 'OS/2';
+ }
+ # Everything else, right now, is UNIX. Note that we should integrate
+ # the VOS support into this as well and get rid of $vos; we'll do
+ # that next time.
+ else {
+ $port_type = 'UNIX';
+ }
+
+ # On DOS/Windows system the filesystem apparently can't track
+ # timestamps with second granularity (!!). Change the sleep time
+ # needed to force a file to be considered "old".
+ $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4;
+
+ print "Port type: $port_type\n" if $debug;
+ print "Make path: $make_path\n" if $debug;
+
+ # Find the full pathname of Make. For DOS systems this is more
+ # complicated, so we ask make itself.
+ if ($osname eq 'VMS') {
+ # On VMS pre-setup make to be found with simply 'make'.
+ $make_path = 'make';
+ } else {
+ my $mk = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`;
+ chop $mk;
+ $mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE):\n
+'echo \"all:;\@echo \\\$(MAKE)\" | $make_path -f-' failed!\n";
+ $make_path = $mk;
+ }
+ print "Make\t= '$make_path'\n" if $debug;
+
+ my $redir2 = '2> /dev/null';
+ $redir2 = '' if os_name eq 'VMS';
+ $string = `$make_path -v -f /dev/null $redir2`;
+
+ $string =~ /^(GNU Make [^,\n]*)/;
+ $testee_version = "$1\n";
+
+ my $redir = '2>&1';
+ $redir = '' if os_name eq 'VMS';
+ $string = `sh -c "$make_path -f /dev/null $redir"`;
+ if ($string =~ /(.*): \*\*\* No targets\. Stop\./) {
+ $make_name = $1;
+ }
+ else {
+ $make_path =~ /^(?:.*$pathsep)?(.+)$/;
+ $make_name = $1;
+ }
+
+ # prepend pwd if this is a relative path (ie, does not
+ # start with a slash, but contains one). Thanks for the
+ # clue, Roland.
+
+ if (index ($make_path, ":") != 1 && index ($make_path, "/") > 0)
+ {
+ $mkpath = "$pwd$pathsep$make_path";
+ }
+ else
+ {
+ $mkpath = $make_path;
+ }
+
+ # If srcdir wasn't provided on the command line, see if the
+ # location of the make program gives us a clue. Don't fail if not;
+ # we'll assume it's been installed into /usr/include or wherever.
+ if (! $srcdir) {
+ $make_path =~ /^(.*$pathsep)?/;
+ my $d = $1 || '../';
+ -f "${d}gnumake.h" and $srcdir = $d;
+ }
+
+ # Not with the make program, so see if we can get it out of the makefile
+ if (! $srcdir && open(MF, "< ../Makefile")) {
+ local $/ = undef;
+ $_ = <MF>;
+ close(MF);
+ /^abs_srcdir\s*=\s*(.*?)\s*$/m;
+ -f "$1/gnumake.h" and $srcdir = $1;
+ }
+
+ # Get Purify log info--if any.
+
+ if (exists $ENV{PURIFYOPTIONS}
+ && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) {
+ $pure_log = $1 || '';
+ $pure_log =~ s/%v/$make_name/;
+ $purify_errors = 0;
+ }
+
+ $string = `sh -c "$make_path -j 2 -f /dev/null $redir"`;
+ if ($string =~ /not supported/) {
+ $parallel_jobs = 0;
+ }
+ else {
+ $parallel_jobs = 1;
+ }
+
+ %FEATURES = map { $_ => 1 } split /\s+/, `sh -c "echo '\\\$(info \\\$(.FEATURES))' | $make_path -f- 2>/dev/null"`;
+
+ # Set up for valgrind, if requested.
+
+ if ($valgrind) {
+ my $args = $valgrind_args;
+ open(VALGRIND, "> valgrind.out")
+ || die "Cannot open valgrind.out: $!\n";
+ # -q --leak-check=yes
+ exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS};
+ $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $args $make_path";
+ # F_SETFD is 2
+ fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n";
+ system("echo Starting on `date` 1>&".fileno(VALGRIND));
+ print "Enabled valgrind support.\n";
+ }
+}
+
+sub setup_for_test
+{
+ $makefile = &get_tmpfile;
+ if (-f $makefile) {
+ unlink $makefile;
+ }
+
+ # Get rid of any Purify logs.
+ if ($pure_log) {
+ ($pure_testname = $testname) =~ tr,/,_,;
+ $pure_testname = "$pure_log.$pure_testname";
+ system("rm -f $pure_testname*");
+ print("Purify testfiles are: $pure_testname*\n") if $debug;
+ }
+}
+
+exit !&toplevel;
diff --git a/tests/scripts/features/archives b/tests/scripts/features/archives
new file mode 100644
index 0000000..b0acfec
--- /dev/null
+++ b/tests/scripts/features/archives
@@ -0,0 +1,97 @@
+# -*-mode: perl-*-
+
+$description = "Test GNU make's archive management features.";
+
+$details = "\
+This only works on systems that support it.";
+
+# If this instance of make doesn't support archives, skip it
+exists $FEATURES{archives} or return -1;
+
+# Create some .o files to work with
+utouch(-60, qw(a1.o a2.o a3.o));
+
+my $ar = $CONFIG_FLAGS{AR};
+
+# Some versions of ar print different things on creation. Find out.
+my $created = `$ar rv libxx.a a1.o 2>&1`;
+
+# Some versions of ar print different things on add. Find out.
+my $add = `$ar rv libxx.a a2.o 2>&1`;
+$add =~ s/a2\.o/#OBJECT#/g;
+
+# Some versions of ar print different things on replacement. Find out.
+my $repl = `$ar rv libxx.a a2.o 2>&1`;
+$repl =~ s/a2\.o/#OBJECT#/g;
+
+unlink('libxx.a');
+
+# Very simple
+run_make_test('all: libxx.a(a1.o)',
+ '', "$ar rv libxx.a a1.o\n$created");
+
+# Multiple .o's. Add a new one to the existing library
+($_ = $add) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a(a1.o a2.o)',
+ '', "$ar rv libxx.a a2.o\n$_");
+
+# Touch one of the .o's so it's rebuilt
+utouch(-40, 'a1.o');
+($_ = $repl) =~ s/#OBJECT#/a1.o/g;
+run_make_test(undef, '', "$ar rv libxx.a a1.o\n$_");
+
+# Use wildcards
+run_make_test('all: libxx.a(*.o)',
+ '', "#MAKE#: Nothing to be done for 'all'.\n");
+
+# Touch one of the .o's so it's rebuilt
+utouch(-30, 'a1.o');
+($_ = $repl) =~ s/#OBJECT#/a1.o/g;
+run_make_test(undef, '', "$ar rv libxx.a a1.o\n$_");
+
+# Use both wildcards and simple names
+utouch(-50, 'a2.o');
+($_ = $add) =~ s/#OBJECT#/a3.o/g;
+$_ .= "$ar rv libxx.a a2.o\n";
+($_ .= $repl) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a(a3.o *.o)', '',
+ "$ar rv libxx.a a3.o\n$_");
+
+# Check whitespace handling
+utouch(-40, 'a2.o');
+($_ = $repl) =~ s/#OBJECT#/a2.o/g;
+run_make_test('all: libxx.a( a3.o *.o )', '',
+ "$ar rv libxx.a a2.o\n$_");
+
+rmfiles(qw(a1.o a2.o a3.o libxx.a));
+
+# Check non-archive targets
+# See Savannah bug #37878
+run_make_test(q!
+all: foo(bar).baz
+foo(bar).baz: ; @echo '$@'
+!,
+ '', "foo(bar).baz\n");
+
+# Check renaming of archive targets.
+# See Savannah bug #38442
+
+mkdir('artest', 0777);
+touch('foo.vhd');
+
+run_make_test(q!
+DIR = artest
+vpath % $(DIR)
+default: lib(foo)
+(%): %.vhd ; @cd $(DIR) && touch $(*F) && $(AR) $(ARFLAGS) $@ $(*F) >/dev/null 2>&1 && rm $(*F)
+.PHONY: default
+!,
+ '', "");
+
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'default'.\n");
+
+unlink('foo.vhd');
+remove_directory_tree('artest');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/comments b/tests/scripts/features/comments
new file mode 100644
index 0000000..9257955
--- /dev/null
+++ b/tests/scripts/features/comments
@@ -0,0 +1,35 @@
+$description = "The following test creates a makefile to test comments\n"
+ ."and comment continuation to the next line using a \n"
+ ."backslash within makefiles.";
+
+$details = "To test comments within a makefile, a semi-colon was placed \n"
+ ."after a comment was started. This should not be reported as\n"
+ ."an error since it is within a comment. We then continue the \n"
+ ."comment to the next line using a backslash. To test whether\n"
+ ."the comment really continued, we place an echo command with some\n"
+ ."text on the line which should never execute since it should be \n"
+ ."within a comment\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<\EOF;
+# Test comment vs semicolon parsing and line continuation
+target: # this ; is just a comment \
+ @echo This is within a comment.
+ @echo There should be no errors for this makefile.
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "There should be no errors for this makefile.\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1))
diff --git a/tests/scripts/features/conditionals b/tests/scripts/features/conditionals
new file mode 100644
index 0000000..2ece60b
--- /dev/null
+++ b/tests/scripts/features/conditionals
@@ -0,0 +1,146 @@
+# -*-perl-*-
+$description = "Check GNU make conditionals.";
+
+$details = "Attempt various different flavors of GNU make conditionals.";
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = second
+
+all:
+ifeq ($(arg1),$(arg2))
+ @echo arg1 equals arg2
+else
+ @echo arg1 NOT equal arg2
+endif
+
+ifeq \'$(arg2)\' "$(arg5)"
+ @echo arg2 equals arg5
+else
+ @echo arg2 NOT equal arg5
+endif
+
+ifneq \'$(arg3)\' \'$(arg4)\'
+ @echo arg3 NOT equal arg4
+else
+ @echo arg3 equal arg4
+endif
+
+ifndef undefined
+ @echo variable is undefined
+else
+ @echo variable undefined is defined
+endif
+ifdef arg4
+ @echo arg4 is defined
+else
+ @echo arg4 is NOT defined
+endif',
+ '',
+ 'arg1 NOT equal arg2
+arg2 equals arg5
+arg3 NOT equal arg4
+variable is undefined
+arg4 is defined');
+
+
+# Test expansion of variables inside ifdef.
+
+run_make_test('
+foo = 1
+
+FOO = foo
+F = f
+
+DEF = no
+DEF2 = no
+
+ifdef $(FOO)
+DEF = yes
+endif
+
+ifdef $(F)oo
+DEF2 = yes
+endif
+
+
+DEF3 = no
+FUNC = $1
+ifdef $(call FUNC,DEF)3
+ DEF3 = yes
+endif
+
+all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)',
+ '',
+ 'DEF=yes DEF2=yes DEF3=yes');
+
+
+# Test all the different "else if..." constructs
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = fifth
+
+result =
+
+ifeq ($(arg1),$(arg2))
+ result += arg1 equals arg2
+else ifeq \'$(arg2)\' "$(arg5)"
+ result += arg2 equals arg5
+else ifneq \'$(arg3)\' \'$(arg3)\'
+ result += arg3 NOT equal arg4
+else ifndef arg5
+ result += variable is undefined
+else ifdef undefined
+ result += arg4 is defined
+else
+ result += success
+endif
+
+
+all: ; @echo $(result)',
+ '',
+ 'success');
+
+
+# Test some random "else if..." construct nesting
+
+run_make_test('
+arg1 = first
+arg2 = second
+arg3 = third
+arg4 = cc
+arg5 = second
+
+ifeq ($(arg1),$(arg2))
+ $(info failed 1)
+else ifeq \'$(arg2)\' "$(arg2)"
+ ifdef undefined
+ $(info failed 2)
+ else
+ $(info success)
+ endif
+else ifneq \'$(arg3)\' \'$(arg3)\'
+ $(info failed 3)
+else ifdef arg5
+ $(info failed 4)
+else ifdef undefined
+ $(info failed 5)
+else
+ $(info failed 6)
+endif
+
+.PHONY: all
+all: ; @:',
+ '',
+ 'success');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/default_names b/tests/scripts/features/default_names
new file mode 100644
index 0000000..2e83880
--- /dev/null
+++ b/tests/scripts/features/default_names
@@ -0,0 +1,44 @@
+# -*-perl-*-
+
+$description = "This script tests to make sure that Make looks for
+default makefiles in the correct order (GNUmakefile,makefile,Makefile)";
+
+# Create a makefile called "GNUmakefile"
+$makefile = "GNUmakefile";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "FIRST: ; \@echo It chose GNUmakefile\n";
+close(MAKEFILE);
+
+# Create another makefile called "makefile"
+open(MAKEFILE,"> makefile");
+print MAKEFILE "SECOND: ; \@echo It chose makefile\n";
+close(MAKEFILE);
+
+# DOS/WIN32/MacOSX platforms are case-insensitive / case-preserving, so
+# Makefile is the same file as makefile. Just test what we can here.
+
+my $case_sensitive = 0;
+if (! -f 'Makefile') {
+ # Create another makefile called "Makefile"
+ $case_sensitive = 1;
+ open(MAKEFILE,"> Makefile");
+ print MAKEFILE "THIRD: ; \@echo It chose Makefile\n";
+ close(MAKEFILE);
+}
+
+run_make_with_options("","",&get_logfile);
+compare_output("It chose GNUmakefile\n",&get_logfile(1));
+unlink($makefile);
+
+run_make_with_options("","",&get_logfile);
+compare_output("It chose makefile\n",&get_logfile(1));
+unlink("makefile");
+
+if ($case_sensitive) {
+ run_make_with_options("","",&get_logfile);
+ compare_output("It chose Makefile\n",&get_logfile(1));
+ unlink("Makefile");
+}
+
+1;
diff --git a/tests/scripts/features/double_colon b/tests/scripts/features/double_colon
new file mode 100644
index 0000000..1097775
--- /dev/null
+++ b/tests/scripts/features/double_colon
@@ -0,0 +1,164 @@
+# -*-perl-*-
+$description = "Test handling of double-colon rules.";
+
+$details = "\
+We test these features:
+
+ - Multiple commands for the same (double-colon) target
+ - Different prerequisites for targets: only out-of-date
+ ones are rebuilt.
+ - Double-colon targets that aren't the goal target.
+
+Then we do the same thing for parallel builds: double-colon
+targets should always be built serially.";
+
+# The Contents of the MAKEFILE ...
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+all: baz
+
+foo:: f1.h ; @echo foo FIRST
+foo:: f2.h ; @echo foo SECOND
+
+bar:: ; @echo aaa; sleep 1; echo aaa done
+bar:: ; @echo bbb
+
+baz:: ; @echo aaa
+baz:: ; @echo bbb
+
+biz:: ; @echo aaa
+biz:: two ; @echo bbb
+
+two: ; @echo two
+
+f1.h f2.h: ; @echo $@
+
+d :: ; @echo ok
+d :: d ; @echo oops
+
+EOF
+
+close(MAKEFILE);
+
+# TEST 0: A simple double-colon rule that isn't the goal target.
+
+&run_make_with_options($makefile, "all", &get_logfile, 0);
+$answer = "aaa\nbbb\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 1: As above, in parallel
+
+if ($parallel_jobs) {
+ &run_make_with_options($makefile, "-j10 all", &get_logfile, 0);
+ $answer = "aaa\nbbb\n";
+ &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 2: A simple double-colon rule that is the goal target
+
+&run_make_with_options($makefile, "bar", &get_logfile, 0);
+$answer = "aaa\naaa done\nbbb\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 3: As above, in parallel
+
+if ($parallel_jobs) {
+ &run_make_with_options($makefile, "-j10 bar", &get_logfile, 0);
+ $answer = "aaa\naaa done\nbbb\n";
+ &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 4: Each double-colon rule is supposed to be run individually
+
+&utouch(-5, 'f2.h');
+&touch('foo');
+
+&run_make_with_options($makefile, "foo", &get_logfile, 0);
+$answer = "f1.h\nfoo FIRST\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 5: Again, in parallel.
+
+if ($parallel_jobs) {
+ &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
+ $answer = "f1.h\nfoo FIRST\n";
+ &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 6: Each double-colon rule is supposed to be run individually
+
+&utouch(-5, 'f1.h');
+unlink('f2.h');
+&touch('foo');
+
+&run_make_with_options($makefile, "foo", &get_logfile, 0);
+$answer = "f2.h\nfoo SECOND\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 7: Again, in parallel.
+
+if ($parallel_jobs) {
+ &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
+ $answer = "f2.h\nfoo SECOND\n";
+ &compare_output($answer, &get_logfile(1));
+}
+
+# TEST 8: Test circular dependency check; PR/1671
+
+&run_make_with_options($makefile, "d", &get_logfile, 0);
+$answer = "ok\n$make_name: Circular d <- d dependency dropped.\noops\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 8: I don't grok why this is different than the above, but it is...
+#
+# Hmm... further testing indicates this might be timing-dependent?
+#
+#if ($parallel_jobs) {
+# &run_make_with_options($makefile, "-j10 biz", &get_logfile, 0);
+# $answer = "aaa\ntwo\nbbb\n";
+# &compare_output($answer, &get_logfile(1));
+#}
+
+unlink('foo','f1.h','f2.h');
+
+
+# TEST 9: make sure all rules in s double colon family get executed
+# (Savannah bug #14334).
+#
+
+&touch('one');
+&touch('two');
+
+run_make_test('
+.PHONY: all
+all: result
+
+result:: one
+ @echo $^ >>$@
+ @echo $^
+
+result:: two
+ @echo $^ >>$@
+ @echo $^
+
+',
+'',
+'one
+two');
+
+unlink('result','one','two');
+
+# TEST 10: check for proper backslash handling
+# Savannah bug #33399
+
+run_make_test('
+a\ xb :: ; @echo one
+a\ xb :: ; @echo two
+',
+ '', "one\ntwo\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/echoing b/tests/scripts/features/echoing
new file mode 100644
index 0000000..40debf5
--- /dev/null
+++ b/tests/scripts/features/echoing
@@ -0,0 +1,64 @@
+# -*-perl-*-
+$description = "The following test creates a makefile to test command
+echoing. It tests that when a command line starts with
+a '\@', the echoing of that line is suppressed. It also
+tests the -n option which tells make to ONLY echo the
+commands and no execution happens. In this case, even
+the commands with '\@' are printed. Lastly, it tests the
+-s flag which tells make to prevent all echoing, as if
+all commands started with a '\@'.";
+
+$details = "This test is similar to the 'clean' test except that a '\@' has
+been placed in front of the delete command line. Four tests
+are run here. First, make is run normally and the first echo
+command should be executed. In this case there is no '\@' so
+we should expect make to display the command AND display the
+echoed message. Secondly, make is run with the clean target,
+but since there is a '\@' at the beginning of the command, we
+expect no output; just the deletion of a file which we check
+for. Third, we give the clean target again except this time
+we give make the -n option. We now expect the command to be
+displayed but not to be executed. In this case we need only
+to check the output since an error message would be displayed
+if it actually tried to run the delete command again and the
+file didn't exist. Lastly, we run the first test again with
+the -s option and check that make did not echo the echo
+command before printing the message.\n";
+
+$example = "EXAMPLE_FILE";
+
+touch($example);
+
+# TEST #1
+# -------
+
+run_make_test("
+all:
+\techo This makefile did not clean the dir... good
+clean:
+\t\@$delete_command $example\n",
+ '', 'echo This makefile did not clean the dir... good
+This makefile did not clean the dir... good');
+
+# TEST #2
+# -------
+
+run_make_test(undef, 'clean', '');
+if (-f $example) {
+ $test_passed = 0;
+ unlink($example);
+}
+
+# TEST #3
+# -------
+
+run_make_test(undef, '-n clean', "$delete_command $example\n");
+
+
+# TEST #4
+# -------
+
+run_make_test(undef, '-s', "This makefile did not clean the dir... good\n");
+
+
+1;
diff --git a/tests/scripts/features/errors b/tests/scripts/features/errors
new file mode 100644
index 0000000..c0339cb
--- /dev/null
+++ b/tests/scripts/features/errors
@@ -0,0 +1,95 @@
+# -*-perl-*-
+
+$description = "The following tests the -i option and the '-' in front of \n"
+ ."commands to test that make ignores errors in these commands\n"
+ ."and continues processing.";
+
+$details = "This test runs two makes. The first runs on a target with a \n"
+ ."command that has a '-' in front of it (and a command that is \n"
+ ."intended to fail) and then a delete command after that is \n"
+ ."intended to succeed. If make ignores the failure of the first\n"
+ ."command as it is supposed to, then the second command should \n"
+ ."delete a file and this is what we check for. The second make\n"
+ ."that is run in this test is identical except that the make \n"
+ ."command is given with the -i option instead of the '-' in \n"
+ ."front of the command. They should run the same. ";
+
+if ($vos)
+{
+ $rm_command = "delete_file";
+}
+else
+{
+ $rm_command = "rm";
+}
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "clean:\n"
+ ."\t-$rm_command cleanit\n"
+ ."\t$rm_command foo\n"
+ ."clean2: \n"
+ ."\t$rm_command cleanit\n"
+ ."\t$rm_command foo\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("foo");
+
+unlink("cleanit");
+$cleanit_error = `sh -c "$rm_command cleanit 2>&1"`;
+chomp $cleanit_error;
+$delete_error_code = $? >> 8;
+
+# TEST #1
+# -------
+
+$answer = "$rm_command cleanit
+$cleanit_error
+$makefile:2: recipe for target 'clean' failed
+$make_name: [clean] Error $delete_error_code (ignored)
+$rm_command foo\n";
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# If make acted as planned, it should ignore the error from the first
+# command in the target and execute the second which deletes the file "foo"
+# This file, therefore, should not exist if the test PASSES.
+if (-f "foo") {
+ $test_passed = 0;
+}
+
+# The output for this on VOS is too hard to replicate, so we only check it
+# on unix.
+if (!$vos)
+{
+ &compare_output($answer,&get_logfile(1));
+}
+
+
+&touch("foo");
+
+# TEST #2
+# -------
+
+$answer = "$rm_command cleanit
+$cleanit_error
+$makefile:5: recipe for target 'clean2' failed
+$make_name: [clean2] Error $delete_error_code (ignored)
+$rm_command foo\n";
+
+&run_make_with_options($makefile,"clean2 -i",&get_logfile);
+
+if (-f "foo") {
+ $test_passed = 0;
+}
+
+if (!$vos) {
+ &compare_output($answer,&get_logfile(1));
+}
+
+1;
diff --git a/tests/scripts/features/escape b/tests/scripts/features/escape
new file mode 100644
index 0000000..bf069df
--- /dev/null
+++ b/tests/scripts/features/escape
@@ -0,0 +1,74 @@
+# -*-perl-*-
+$description = "Test various types of escaping in makefiles.";
+
+$details = "\
+Make sure that escaping of ':' works in target names.
+Make sure escaping of whitespace works in target names.
+Make sure that escaping of '#' works.
+Make sure that backslash before non-special characters are kept.";
+
+
+# TEST 1
+
+run_make_test('
+$(path)foo : ; @echo "touch ($@)"
+
+foo\ bar: ; @echo "touch ($@)"
+
+sharp: foo\#bar.ext
+foo\#bar.ext: ; @echo "foo#bar.ext = ($@)"',
+ '',
+ 'touch (foo)');
+
+# TEST 2: This one should fail, since the ":" is unquoted.
+
+run_make_test(undef,
+ 'path=pre:',
+ "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.",
+ 512);
+
+# TEST 3: This one should work, since we escape the ":".
+
+run_make_test(undef,
+ "'path=pre\\:'",
+ 'touch (pre:foo)');
+
+# TEST 4: This one should fail, since the escape char is escaped.
+
+run_make_test(undef,
+ "'path=pre\\\\:'",
+ "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.",
+ 512);
+
+# TEST 5: This one should work
+
+run_make_test(undef,
+ "'foo bar'",
+ 'touch (foo bar)');
+
+# TEST 6: Test escaped comments
+
+run_make_test(undef,
+ 'sharp',
+ 'foo#bar.ext = (foo#bar.ext)');
+
+# Test escaped colons in prerequisites
+# Quoting of backslashes in q!! is kind of messy.
+# Solaris sh does not properly handle backslashes even in '' so just
+# check the output make prints, not what the shell interprets.
+run_make_test(q!
+foo: foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar
+foo foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar: ; : '$@'
+!,
+ '', ": 'foo:bar'\n: 'foo\\:bar'\n: 'foo\\\\:bar'\n: 'foo'\n");
+
+# Test backslash before non-special chars: should be kept as-is
+
+run_make_test(q!
+all: ..\foo
+.DEFAULT: ; : '$@'
+!,
+ '', ": '..\\foo'\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/export b/tests/scripts/features/export
new file mode 100644
index 0000000..81bff0c
--- /dev/null
+++ b/tests/scripts/features/export
@@ -0,0 +1,186 @@
+# -*-perl-*-
+$description = "Check GNU make export/unexport commands.";
+
+$details = "";
+
+# The test driver cleans out our environment for us so we don't have to worry
+# about that here.
+
+&run_make_test('
+FOO = foo
+BAR = bar
+BOZ = boz
+
+export BAZ = baz
+export BOZ
+
+BITZ = bitz
+BOTZ = botz
+
+export BITZ BOTZ
+unexport BOTZ
+
+ifdef EXPORT_ALL
+export
+endif
+
+ifdef UNEXPORT_ALL
+unexport
+endif
+
+ifdef EXPORT_ALL_PSEUDO
+.EXPORT_ALL_VARIABLES:
+endif
+
+all:
+ @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)"
+ @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ"
+',
+ '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 1: make sure vars inherited from the parent are exported
+
+$extraENV{FOO} = 1;
+
+&run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 2: global export. Explicit unexport takes precedence.
+
+run_make_test(undef, "EXPORT_ALL=1" ,
+ "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 3: global unexport. Explicit export takes precedence.
+
+&run_make_test(undef, "UNEXPORT_ALL=1",
+ "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 4: both: in the above makefile the unexport comes last so that rules.
+
+&run_make_test(undef, "EXPORT_ALL=1 UNEXPORT_ALL=1",
+ "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 5: test the pseudo target.
+
+&run_make_test(undef, "EXPORT_ALL_PSEUDO=1",
+ "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
+FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n");
+
+# TEST 6: Test the expansion of variables inside export
+
+&run_make_test('
+foo = f-ok
+bar = b-ok
+
+FOO = foo
+F = f
+
+BAR = bar
+B = b
+
+export $(FOO)
+export $(B)ar
+
+all:
+ @echo foo=$(foo) bar=$(bar)
+ @echo foo=$$foo bar=$$bar
+',
+ "", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n");
+
+# TEST 7: Test the expansion of variables inside unexport
+
+&run_make_test('
+foo = f-ok
+bar = b-ok
+
+FOO = foo
+F = f
+
+BAR = bar
+B = b
+
+export foo bar
+
+unexport $(FOO)
+unexport $(B)ar
+
+all:
+ @echo foo=$(foo) bar=$(bar)
+ @echo foo=$$foo bar=$$bar
+',
+ '', "foo=f-ok bar=b-ok\nfoo= bar=\n");
+
+# TEST 7: Test exporting multiple variables on the same line
+
+&run_make_test('
+A = a
+B = b
+C = c
+D = d
+E = e
+F = f
+G = g
+H = h
+I = i
+J = j
+
+SOME = A B C
+
+export F G H I J
+
+export D E $(SOME)
+
+all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
+',
+ '', "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n");
+
+# TEST 8: Test unexporting multiple variables on the same line
+
+@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
+
+&run_make_test('
+A = a
+B = b
+C = c
+D = d
+E = e
+F = f
+G = g
+H = h
+I = i
+J = j
+
+SOME = A B C
+
+unexport F G H I J
+
+unexport D E $(SOME)
+
+all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J
+',
+ '', "A= B= C= D= E= F= G= H= I= J=\n");
+
+# TEST 9: Check setting a variable named "export"
+
+&run_make_test('
+export = 123
+export export
+export export = 456
+a: ; @echo "\$$(export)=$(export) / \$$export=$$export"
+',
+ '', "\$(export)=456 / \$export=456\n");
+
+# TEST 9: Check "export" as a target
+
+&run_make_test('
+a: export
+export: ; @echo "$@"
+',
+ '', "export\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/include b/tests/scripts/features/include
new file mode 100644
index 0000000..ee014bd
--- /dev/null
+++ b/tests/scripts/features/include
@@ -0,0 +1,179 @@
+# -*-mode: perl; rm-trailing-spaces: nil-*-
+
+$description = "Test various forms of the GNU make 'include' command.";
+
+$details = "\
+Test include, -include, sinclude and various regressions involving them.
+Test extra whitespace at the end of the include, multiple -includes and
+sincludes (should not give an error) and make sure that errors are reported
+for targets that were also -included.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The contents of the Makefile ...
+
+print MAKEFILE <<EOF;
+\#Extra space at the end of the following file name
+include $makefile2
+all: ; \@echo There should be no errors for this makefile.
+
+-include nonexistent.mk
+-include nonexistent.mk
+sinclude nonexistent.mk
+sinclude nonexistent-2.mk
+-include makeit.mk
+sinclude makeit.mk
+
+error: makeit.mk
+EOF
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE "ANOTHER: ; \@echo This is another included makefile\n";
+
+close(MAKEFILE);
+
+# Create the answer to what should be produced by this Makefile
+&run_make_with_options($makefile, "all", &get_logfile);
+$answer = "There should be no errors for this makefile.\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile, "ANOTHER", &get_logfile);
+$answer = "This is another included makefile\n";
+&compare_output($answer, &get_logfile(1));
+
+$makefile = undef;
+
+# Try to build the "error" target; this will fail since we don't know
+# how to create makeit.mk, but we should also get a message (even though
+# the -include suppressed it during the makefile read phase, we should
+# see one during the makefile run phase).
+
+run_make_test
+ ('
+-include foo.mk
+error: foo.mk ; @echo $@
+',
+ '',
+ "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n",
+ 512
+ );
+
+# Make sure that target-specific variables don't impact things. This could
+# happen because a file record is created when a target-specific variable is
+# set.
+
+run_make_test
+ ('
+bar.mk: foo := baz
+-include bar.mk
+hello: ; @echo hello
+',
+ '',
+ "hello\n"
+ );
+
+
+# Test inheritance of dontcare flag when rebuilding makefiles.
+#
+run_make_test('
+.PHONY: all
+all: ; @:
+
+-include foo
+
+foo: bar; @:
+', '', '');
+
+
+# Make sure that we don't die when the command fails but we dontcare.
+# (Savannah bug #13216).
+#
+run_make_test('
+.PHONY: all
+all:; @:
+
+-include foo
+
+foo: bar; @:
+
+bar:; @exit 1
+', '', '');
+
+# Check include, sinclude, -include with no filenames.
+# (Savannah bug #1761).
+
+run_make_test('
+.PHONY: all
+all:; @:
+include
+-include
+sinclude', '', '');
+
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (direct dependency case).
+#
+run_make_test('
+-include foo
+
+all: bar
+
+foo: baz
+bar: baz
+',
+'',
+"#MAKE#: *** No rule to make target 'baz', needed by 'bar'. Stop.\n",
+512);
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (indirect dependency case).
+#
+run_make_test('
+-include foo
+
+all: bar
+
+foo: baz
+bar: baz
+baz: end
+',
+'',
+"#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n",
+512);
+
+# Test that the diagnostics is issued even if the target has been
+# tried before with the dontcare flag (include/-include case).
+#
+run_make_test('
+include bar
+-include foo
+
+all:
+
+foo: baz
+bar: baz
+baz: end
+',
+'',
+"#MAKEFILE#:2: bar: No such file or directory
+#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n",
+512);
+
+if ($all_tests) {
+ # Test that include of a rebuild-able file doesn't show a warning
+ # Savannah bug #102
+ run_make_test(q!
+include foo
+foo: ; @echo foo = bar > $@
+!,
+ '', "#MAKE#: 'foo' is up to date.\n");
+ rmfiles('foo');
+}
+
+1;
diff --git a/tests/scripts/features/jobserver b/tests/scripts/features/jobserver
new file mode 100644
index 0000000..cedd4b3
--- /dev/null
+++ b/tests/scripts/features/jobserver
@@ -0,0 +1,61 @@
+# -*-perl-*-
+
+$description = "Test jobserver.";
+
+$details = "These tests are ones that specifically are different when the
+jobserver feature is available. Most -j tests are the same whether or not
+jobserver is available, and those appear in the 'parallelism' test suite.";
+
+exists $FEATURES{'jobserver'} or return -1;
+
+if (!$parallel_jobs) {
+ return -1;
+}
+
+# Don't put --jobserver-fds into a re-exec'd MAKEFLAGS.
+# We can't test this directly because there's no way a makefile can
+# show the value of MAKEFLAGS we were re-exec'd with. We can intuit it
+# by looking for "disabling jobserver mode" warnings; we should only
+# get one from the original invocation and none from the re-exec.
+# See Savannah bug #18124
+
+unlink('inc.mk');
+
+run_make_test(q!
+-include inc.mk
+recur:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @rm -f inc.mk
+ @$(MAKE) -j2 -f #MAKEFILE# all
+all:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @echo $@
+inc.mk:
+# @echo 'MAKEFLAGS = $(MAKEFLAGS)'
+ @echo 'FOO = bar' > $@
+!,
+ '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n");
+
+unlink('inc.mk');
+
+# Test recursion when make doesn't think it exists.
+# See Savannah bug #39934
+# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
+
+open(MAKEFILE,"> Makefile2");
+print MAKEFILE '
+vpath %.c ../
+foo:
+';
+close(MAKEFILE);
+
+run_make_test(q!
+default: ; @ #MAKEPATH# -f Makefile2
+!,
+ '-j2 --no-print-directory',
+"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
+#MAKE#[1]: Nothing to be done for 'foo'.");
+
+rmfiles('Makefile2');
+
+1;
diff --git a/tests/scripts/features/load b/tests/scripts/features/load
new file mode 100644
index 0000000..1f8cdc2
--- /dev/null
+++ b/tests/scripts/features/load
@@ -0,0 +1,110 @@
+# -*-perl-*-
+$description = "Test the load operator.";
+
+$details = "Test dynamic loading of modules.";
+
+# Don't do anything if this system doesn't support "load"
+exists $FEATURES{load} or return -1;
+
+# First build a shared object
+# Provide both a default and non-default load symbol
+
+unlink(qw(testload.c testload.so));
+
+open(my $F, '> testload.c') or die "open: testload.c: $!\n";
+print $F <<'EOF' ;
+#include <string.h>
+#include <stdio.h>
+
+#include "gnumake.h"
+
+int plugin_is_GPL_compatible;
+
+int
+testload_gmk_setup (gmk_floc *pos)
+{
+ (void)pos;
+ gmk_eval ("TESTLOAD = implicit", 0);
+ return 1;
+}
+
+int
+explicit_setup (gmk_floc *pos)
+{
+ (void)pos;
+ gmk_eval ("TESTLOAD = explicit", 0);
+ return 1;
+}
+EOF
+close($F) or die "close: testload.c: $!\n";
+
+# Make sure we can compile
+# CONFIG_FLAGS are loaded from config-flags.pm and set by configure
+
+my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testload.so testload.c";
+
+my $clog = `$sobuild 2>&1`;
+if ($? != 0) {
+ $verbose and print "Failed to build testload.so:\n$sobuild\n$_";
+ return -1;
+}
+
+# TEST 1
+run_make_test(q!
+PRE := $(.LOADED)
+load testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so implicit\n");
+
+# TEST 2
+# Load using an explicit function
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so explicit\n");
+
+# TEST 4
+# Check multiple loads
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so
+load testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+!,
+ '', "pre= post=testload.so implicit\n");
+
+# TEST 5
+# Check auto-rebuild of loaded file that's out of date
+utouch(-10, 'testload.so');
+touch('testload.c');
+
+run_make_test(q!
+PRE := $(.LOADED)
+load ./testload.so
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+testload.so: testload.c ; @echo "rebuilding $@"; !.$sobuild,
+ '', "rebuilding testload.so\npre= post=testload.so implicit\n");
+
+# TEST 5
+# Check auto-rebuild of loaded file when it doesn't exist
+unlink('testload.so');
+
+run_make_test(q!
+PRE := $(.LOADED)
+-load ./testload.so(explicit_setup)
+POST := $(.LOADED)
+all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD)
+%.so: %.c ; @echo "rebuilding $@"; !.$sobuild,
+ '', "rebuilding testload.so\npre= post=testload.so explicit\n");
+
+unlink(qw(testload.c testload.so)) unless $keep;
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/loadapi b/tests/scripts/features/loadapi
new file mode 100644
index 0000000..8c824c0
--- /dev/null
+++ b/tests/scripts/features/loadapi
@@ -0,0 +1,116 @@
+# -*-perl-*-
+$description = "Test the shared object load API.";
+
+$details = "Verify the different aspects of the shared object API.";
+
+# Don't do anything if this system doesn't support "load"
+exists $FEATURES{load} or return -1;
+
+# First build a shared object
+# Provide both a default and non-default load symbol
+
+unlink(qw(testapi.c testapi.so));
+
+open(my $F, '> testapi.c') or die "open: testapi.c: $!\n";
+print $F <<'EOF' ;
+#include <string.h>
+#include <stdio.h>
+
+#include "gnumake.h"
+
+int plugin_is_GPL_compatible;
+
+static char *
+test_eval (const char *buf)
+{
+ gmk_eval (buf, 0);
+ return NULL;
+}
+
+static char *
+test_expand (const char *val)
+{
+ return gmk_expand (val);
+}
+
+static char *
+test_noexpand (const char *val)
+{
+ char *str = gmk_alloc (strlen (val) + 1);
+ strcpy (str, val);
+ return str;
+}
+
+static char *
+func_test (const char *funcname, unsigned int argc, char **argv)
+{
+ char *mem;
+
+ if (strcmp (funcname, "test-expand") == 0)
+ return test_expand (argv[0]);
+
+ if (strcmp (funcname, "test-eval") == 0)
+ return test_eval (argv[0]);
+
+ if (strcmp (funcname, "test-noexpand") == 0)
+ return test_noexpand (argv[0]);
+
+ mem = gmk_alloc (sizeof ("unknown"));
+ strcpy (mem, "unknown");
+ return mem;
+}
+
+int
+testapi_gmk_setup ()
+{
+ gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT);
+ gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND);
+ gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT);
+ gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0);
+ return 1;
+}
+EOF
+close($F) or die "close: testapi.c: $!\n";
+
+my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testapi.so testapi.c";
+
+my $clog = `$sobuild 2>&1`;
+if ($? != 0) {
+ $verbose and print "Failed to build testapi.so:\n$sobuild\n$_";
+ return -1;
+}
+
+# TEST 1
+# Check the gmk_expand() function
+run_make_test(q!
+EXPAND = expansion
+all: ; @echo $(test-expand $$(EXPAND))
+load testapi.so
+!,
+ '', "expansion\n");
+
+# TEST 2
+# Check the eval operation. Prove that the argument is expanded only once
+run_make_test(q!
+load testapi.so
+TEST = bye
+ASSIGN = VAR = $(TEST) $(shell echo there)
+$(test-eval $(value ASSIGN))
+TEST = hi
+all:;@echo '$(VAR)'
+!,
+ '', "hi there\n");
+
+# TEST 2
+# Check the no-expand capability
+run_make_test(q!
+load testapi.so
+TEST = hi
+all:;@echo '$(test-noexpand $(TEST))'
+!,
+ '', "\$(TEST)\n");
+
+unlink(qw(testapi.c testapi.so)) unless $keep;
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/mult_rules b/tests/scripts/features/mult_rules
new file mode 100644
index 0000000..e706e17
--- /dev/null
+++ b/tests/scripts/features/mult_rules
@@ -0,0 +1,78 @@
+$description = "\
+The following test creates a makefile to test the presence
+of multiple rules for one target. One file can be the
+target of several rules if at most one rule has commands;
+the other rules can only have dependencies.";
+
+$details = "\
+The makefile created in this test contains two hardcoded rules
+for foo.o and bar.o. It then gives another multiple target rule
+with the same names as above but adding more dependencies.
+Additionally, another variable extradeps is listed as a
+dependency but is defined to be null. It can however be defined
+on the make command line as extradeps=extra.h which adds yet
+another dependency to the targets.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+objects = foo.o bar.o
+foo.o : defs.h
+bar.o : defs.h test.h
+extradeps =
+\$(objects) : config.h \$(extradeps)
+\t\@echo EXTRA EXTRA
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("defs.h","test.h","config.h");
+
+if ($vos)
+{
+ $error_code = 3307;
+}
+else
+{
+ $error_code = 512;
+}
+
+&run_make_with_options($makefile,
+ "extradeps=extra.h",
+ &get_logfile,
+ $error_code);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: *** No rule to make target 'extra.h', needed by 'foo.o'. Stop.\n";
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+
+&touch("extra.h");
+
+&run_make_with_options($makefile,
+ "extradeps=extra.h",
+ &get_logfile,
+ 0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "EXTRA EXTRA\n";
+
+&compare_output($answer,&get_logfile(1));
+
+unlink("defs.h","test.h","config.h","extra.h");
+
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/features/mult_targets b/tests/scripts/features/mult_targets
new file mode 100644
index 0000000..c8ff418
--- /dev/null
+++ b/tests/scripts/features/mult_targets
@@ -0,0 +1,46 @@
+$description = "The following test creates a makefile to test that a \n "
+ ."rule with multiple targets is equivalent to writing \n"
+ ."many rules, each with one target, and all identical aside\n"
+ ."from that.";
+
+$details = "A makefile is created with one rule and two targets. Make \n"
+ ."is called twice, once for each target, and the output which \n"
+ ."contains the target name with \$@ is looked at for the changes.\n"
+ ."This test also tests the substitute function by replacing \n"
+ ."the word output with nothing in the target name giving either\n"
+ ."an output of \"I am little\" or \"I am big\"";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "bigoutput littleoutput: test.h\n";
+print MAKEFILE "\t\@echo I am \$(subst output,,\$@)\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("test.h");
+
+&run_make_with_options($makefile,"bigoutput",&get_logfile);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = "I am big\n";
+
+&compare_output($answer,&get_logfile(1));
+
+&run_make_with_options($makefile,"littleoutput",&get_logfile);
+$answer = "I am little\n";
+&compare_output($answer,&get_logfile(1));
+
+unlink "test.h";
+
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/features/order_only b/tests/scripts/features/order_only
new file mode 100644
index 0000000..4ebdc2b
--- /dev/null
+++ b/tests/scripts/features/order_only
@@ -0,0 +1,118 @@
+# -*-perl-*-
+$description = "Test order-only prerequisites.";
+
+$details = "\
+Create makefiles with various combinations of normal and order-only
+prerequisites and ensure they behave properly. Test the \$| variable.";
+
+# TEST #0 -- Basics
+
+run_make_test('
+%r: | baz ; @echo $< $^ $|
+bar: foo
+foo:;@:
+baz:;@:',
+ '', "foo foo baz\n");
+
+# TEST #1 -- First try: the order-only prereqs need to be built.
+
+run_make_test(q!
+foo: bar | baz
+ @echo '$$^ = $^'
+ @echo '$$| = $|'
+ touch $@
+
+.PHONY: baz
+
+bar baz:
+ touch $@!,
+ '', "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n");
+
+
+# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo bar baz));
+
+# TEST #3 -- Make sure the order-only prereq was promoted to normal.
+
+run_make_test(q!
+foo: bar | baz
+ @echo '$$^ = $^'
+ @echo '$$| = $|'
+ touch $@
+
+foo: baz
+
+.PHONY: baz
+
+bar baz:
+ touch $@!,
+ '', "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
+
+
+# TEST #4 -- now we do it again
+
+run_make_test(undef, '', "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n");
+
+unlink(qw(foo bar baz));
+
+# Test empty normal prereqs
+
+# TEST #5 -- make sure the parser was correct.
+
+run_make_test(q!
+foo:| baz
+ @echo '$$^ = $^'
+ @echo '$$| = $|'
+ touch $@
+
+.PHONY: baz
+
+baz:
+ touch $@!,
+ '', "touch baz\n\$^ = \n\$| = baz\ntouch foo\n");
+
+# TEST #6 -- now we do it again: this time foo won't be built
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo baz));
+
+# Test order-only in pattern rules
+
+# TEST #7 -- make sure the parser was correct.
+
+run_make_test(q!
+%.w : %.x | baz
+ @echo '$$^ = $^'
+ @echo '$$| = $|'
+ touch $@
+
+all: foo.w
+
+.PHONY: baz
+foo.x baz:
+ touch $@!,
+ '',
+ "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n");
+
+# TEST #8 -- now we do it again: this time foo.w won't be built
+
+run_make_test(undef, '', "touch baz\n");
+
+unlink(qw(foo.w foo.x baz));
+
+# TEST #9 -- make sure that $< is set correctly in the face of order-only
+# prerequisites in pattern rules.
+
+run_make_test('
+%r: | baz ; @echo $< $^ $|
+bar: foo
+foo:;@:
+baz:;@:',
+ '', "foo foo baz\n");
+
+
+1;
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
new file mode 100644
index 0000000..a7534cb
--- /dev/null
+++ b/tests/scripts/features/output-sync
@@ -0,0 +1,341 @@
+# -*-perl-*-
+
+$description = "Test --output-sync (-O) option.";
+
+$details = "Test the synchronization of output from parallel jobs.";
+
+# If we don't have output sync support, never mind.
+exists $FEATURES{'output-sync'} or return -1;
+
+# Output sync can't be tested without parallelization
+$parallel_jobs or return -1;
+
+
+if ($vos) {
+ $sleep_command = "sleep -seconds";
+}
+else {
+ $sleep_command = "sleep";
+}
+
+# The following subdirectories with Makefiles are used in several
+# of the following tests. The model is:
+# foo/Makefile - has a "foo" target that waits for the bar target
+# bar/Makefile - has a "bar" target that runs immediately
+# - has a "baz" target that waits for the foo target
+#
+# So, you start the two sub-makes in parallel and first the "bar" target is
+# built, followed by "foo", followed by "baz". The trick is that first each
+# target prints a "start" statement, then waits (if appropriate), then prints
+# an end statement. Thus we can tell if the -O flag is working, since
+# otherwise these statements would be mixed together.
+
+@syncfiles = ();
+
+sub output_sync_clean {
+ rmfiles('foo/Makefile', 'bar/Makefile', @syncfiles);
+ rmdir('foo');
+ rmdir('bar');
+}
+
+# We synchronize the different jobs by having them wait for a sentinel file to
+# be created, instead of relying on a certain amount of time passing.
+# Unfortunately in this test we have to sleep after we see the sync file,
+# since we also want to make the obtaining of the write synchronization lock
+# reliable. If things are too fast, then sometimes a different job will steal
+# the output sync lock and the output is mis-ordered from what we expect.
+sub output_sync_wait {
+ return "while [ ! -f ../mksync.$_[0] ]; do :; done; rm -f ../mksync.$_[0].wait; $sleep_command 1";
+}
+sub output_sync_set {
+ return "date > ../mksync.$_[0]";
+}
+
+@syncfiles = qw(mksync.foo mksync.foo_start mksync.bar mksync.bar_start);
+
+output_sync_clean();
+mkdir('foo', 0777);
+mkdir('bar', 0777);
+
+$set_foo = output_sync_set('foo');
+$set_bar = output_sync_set('bar');
+$set_foo_start = output_sync_set('foo_start');
+$set_bar_start = output_sync_set('bar_start');
+
+$wait_foo = output_sync_wait('foo');
+$wait_bar = output_sync_wait('bar');
+$wait_foo_start = output_sync_set('foo_start');
+$wait_bar_start = output_sync_set('bar_start');
+
+open(MAKEFILE,"> foo/Makefile");
+print MAKEFILE <<EOF;
+all: foo
+
+foo: foo-base ; \@$set_foo
+
+foo-base:
+\t\@echo foo: start
+\t\@$wait_bar
+\t\@echo foo: end
+
+foo-job: foo-job-base ; \@$set_foo
+
+foo-job-base:
+\t\@$wait_bar_start
+\t\@echo foo: start
+\t\@$set_foo_start
+\t\@$wait_bar
+\t\@echo foo: end
+
+foo-fail:
+\t\@echo foo-fail: start
+\t\@$wait_bar
+\t\@echo foo-fail: end
+\t\@exit 1
+EOF
+close(MAKEFILE);
+
+open(MAKEFILE,"> bar/Makefile");
+print MAKEFILE <<EOF;
+all: bar baz
+
+bar: bar-base ; \@$set_bar
+bar-base:
+\t\@echo bar: start
+\t\@echo bar: end
+
+bar-job: bar-job-base ; \@$set_bar
+
+bar-job-base:
+\t\@echo bar: start
+\t\@$set_bar_start
+\t\@$wait_foo_start
+\t\@echo bar: end
+
+baz: baz-base
+baz-base:
+\t\@echo baz: start
+\t\@$wait_foo
+\t\@echo baz: end
+EOF
+close(MAKEFILE);
+
+# Test per-make synchronization.
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo
+
+make-bar: ; \$(MAKE) -C bar!,
+ '-j -Orecurse',
+"#MAKEPATH# -C foo
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: start
+foo: end
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKEPATH# -C bar
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+baz: start
+baz: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'\n", 0, 6);
+
+# Test per-target synchronization.
+# Note we have to sleep again here after starting the foo makefile before
+# starting the bar makefile, otherwise the "entering/leaving" messages for the
+# submakes might be ordered differently than we expect.
+
+unlink(@syncfiles);
+run_make_test(qq!
+x=1
+\$xMAKEFLAGS += --no-print-directory
+
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo
+
+make-bar: ; $sleep_command 1 ; \$(MAKE) -C bar!,
+ '-j --output-sync=target',
+"#MAKEPATH# -C foo
+$sleep_command 1 ; #MAKEPATH# -C bar
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: start
+foo: end
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+baz: start
+baz: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'\n", 0, 6);
+
+# Rerun but this time suppress the directory tracking
+unlink(@syncfiles);
+run_make_test(undef, '-j --output-sync=target x=',
+ "#MAKEPATH# -C foo
+$sleep_command 1 ; #MAKEPATH# -C bar
+bar: start
+bar: end
+foo: start
+foo: end
+baz: start
+baz: end\n", 0, 6);
+
+# Test that messages from make itself are enclosed with
+# "Entering/Leaving directory" messages.
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo-fail make-bar-bar
+
+make-foo-fail: ; \$(MAKE) -C foo foo-fail
+
+make-bar-bar: ; $sleep_command 1 ; \$(MAKE) -C bar bar!,
+ '-j -O',
+"#MAKEPATH# -C foo foo-fail
+$sleep_command 1 ; #MAKEPATH# -C bar bar
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo-fail: start
+foo-fail: end
+Makefile:20: recipe for target 'foo-fail' failed
+#MAKE#[1]: *** [foo-fail] Error 1
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKEFILE#:4: recipe for target 'make-foo-fail' failed
+#MAKE#: *** [make-foo-fail] Error 2\n",
+512);
+
+# Test the per-job synchronization.
+# For this we'll have bar-job:
+# print start, invoke bar-start, wait for foo-start, print end, print-bar-end
+# And foo-job:
+# wait for bar-start, print foo-start, wait for bar-end, print end
+
+unlink(@syncfiles);
+run_make_test(qq!
+all: make-foo make-bar
+
+make-foo: ; \$(MAKE) -C foo foo-job
+
+make-bar: ; $sleep_command 1 ; \$(MAKE) -C bar bar-job!,
+ '-j --output-sync=line',
+"#MAKEPATH# -C foo foo-job
+$sleep_command 1 ; #MAKEPATH# -C bar bar-job
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: start
+#MAKE#[1]: Leaving directory '#PWD#/foo'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: start
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/bar'
+bar: end
+#MAKE#[1]: Leaving directory '#PWD#/bar'
+#MAKE#[1]: Entering directory '#PWD#/foo'
+foo: end
+#MAKE#[1]: Leaving directory '#PWD#/foo'\n", 0, 6);
+
+
+# Remove temporary directories and contents.
+output_sync_clean();
+
+# Ensure recursion doesn't mis-order or double-print output
+run_make_test(qq!
+all:
+\t\@echo foo
+\t\@+echo bar
+!,
+ '-j -Oline', "foo\nbar\n");
+
+run_make_test(undef, '-j -Otarget', "foo\nbar\n");
+
+# Ensure when make writes out command it's not misordered
+run_make_test(qq!
+all:
+\t\@echo foobar
+\ttrue
+!,
+ '-j -Oline', "foobar\ntrue\n");
+
+run_make_test(undef, '-j -Otarget', "foobar\ntrue\n");
+
+# Ensure that shell functions inside recipes write stderr to the sync file
+run_make_test(q!
+all: ; @: $(shell echo foo 1>&2)
+!,
+ '-w -Oline', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+run_make_test(q!
+$(shell echo foo 1>&2)
+all: ; echo bar
+!,
+ '-s -w -Otarget', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n#MAKE#: Entering directory '#PWD#'\nbar\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Test recursion
+$m1 = get_tmpfile();
+$m2 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+all:; @:
+EOF
+close(M1);
+
+open(M2, "> $m2");
+print M2 <<'EOF';
+$(shell echo d2 stderr 1>&2)
+$(info d2 stdout)
+all:; @:
+# Force an ordering on the output
+$(shell sleep 1)
+EOF
+close(M2);
+
+run_make_test(qq!
+all: t1 t2
+t1: ; \@\$(MAKE) -f $m1
+t2: ; \@\$(MAKE) -f $m2
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nd2 stderr\nd2 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+rmfiles($m1, $m2);
+
+# Ensure that output generated while parsing makefiles is synced
+# when appropriate.
+$m1 = get_tmpfile();
+
+open(M1, "> $m1");
+print M1 <<'EOF';
+$(shell echo d1 stderr 1>&2)
+$(info d1 stdout)
+$(error d1 failed)
+all:; @:
+EOF
+close(M1);
+
+run_make_test(qq!
+all: t1
+t1: ; -\@\$(MAKE) -f $m1
+!,
+ "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n$m1:3: *** d1 failed. Stop.\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKEFILE#:3: recipe for target 't1' failed\n#MAKE#: [t1] Error 2 (ignored)\n");
+
+rmfiles($m1);
+
+# Test $(error ...) functions in recipes
+
+run_make_test(q!
+foo: $(OBJS) ; echo $(or $(filter %.o,$^),$(error fail))
+!,
+ '-O', "#MAKEFILE#:2: *** fail. Stop.\n", 512);
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/override b/tests/scripts/features/override
new file mode 100644
index 0000000..fff6c4e
--- /dev/null
+++ b/tests/scripts/features/override
@@ -0,0 +1,45 @@
+# -*-perl-*-
+
+$description = "Test the override directive on variable assignments.";
+
+$details = "";
+
+# TEST 0: Basic override
+
+run_make_test('
+X = start
+override recur = $(X)
+override simple := $(X)
+X = end
+all: ; @echo "$(recur) $(simple)"
+',
+ 'recur=I simple=J', "end start\n");
+
+# TEST 1: Override with append
+
+run_make_test('
+X += X1
+override X += X2
+override Y += Y1
+Y += Y2
+all: ; @echo "$(X) $(Y)"
+',
+ '', "X1 X2 Y1\n");
+
+# TEST 2: Override with append to the command line
+
+run_make_test(undef, 'X=C Y=C', "C X2 C Y1\n");
+
+# Test override of define/endef
+
+run_make_test('
+override define foo
+@echo First comes the definition.
+@echo Then comes the override.
+endef
+all: ; $(foo)
+',
+ 'foo=Hello', "First comes the definition.\nThen comes the override.\n");
+
+
+1;
diff --git a/tests/scripts/features/parallelism b/tests/scripts/features/parallelism
new file mode 100644
index 0000000..c702c26
--- /dev/null
+++ b/tests/scripts/features/parallelism
@@ -0,0 +1,216 @@
+# -*-perl-*-
+
+$description = "Test parallelism (-j) option.";
+
+
+$details = "This test creates a makefile with two double-colon default
+rules. The first rule has a series of sleep and echo commands
+intended to run in series. The second and third have just an
+echo statement. When make is called in this test, it is given
+the -j option with a value of 4. This tells make that it may
+start up to four jobs simultaneously. In this case, since the
+first command is a sleep command, the output of the second
+and third commands will appear before the first if indeed
+make is running all of these commands in parallel.";
+
+if (!$parallel_jobs) {
+ return -1;
+}
+
+if ($vos) {
+ $sleep_command = "sleep -seconds";
+}
+else {
+ $sleep_command = "sleep";
+}
+
+
+run_make_test("
+all : def_1 def_2 def_3
+def_1 : ; \@echo ONE; $sleep_command 3 ; echo TWO
+def_2 : ; \@$sleep_command 2 ; echo THREE
+def_3 : ; \@$sleep_command 1 ; echo FOUR",
+ '-j4', "ONE\nFOUR\nTHREE\nTWO");
+
+# Test parallelism with included files. Here we sleep/echo while
+# building the included files, to test that they are being built in
+# parallel.
+run_make_test("
+all: 1 2; \@echo success
+-include 1.inc 2.inc
+1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
+2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
+ "-j4",
+ "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7);
+
+rmfiles(qw(1.inc 2.inc));
+
+
+# Test parallelism with included files--this time recurse first and make
+# sure the jobserver works.
+run_make_test("
+recurse: ; \@\$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all
+all: 1 2; \@echo success
+
+INC = no
+ifeq (\$(INC),yes)
+-include 1.inc 2.inc
+endif
+
+1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@
+2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@",
+ "-j4",
+ "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7);
+
+rmfiles(qw(1.inc 2.inc));
+
+# Grant Taylor reports a problem where tokens can be lost (not written back
+# to the pipe when they should be): this happened when there is a $(shell ...)
+# function in an exported recursive variable. I added some code to check
+# for this situation and print a message if it occurred. This test used
+# to trigger this code when I added it but no longer does after the fix.
+# We have to increase the timeout from the default (5s) on this test.
+
+run_make_test("
+export HI = \$(shell \$(\$\@.CMD))
+first.CMD = echo hi
+second.CMD = $sleep_command 4; echo hi
+
+.PHONY: all first second
+all: first second
+
+first second: ; \@echo \$\@; $sleep_command 1; echo \$\@",
+ '-j2', "first\nfirst\nsecond\nsecond", 0, 7);
+
+# Michael Matz <matz@suse.de> reported a bug where if make is running in
+# parallel without -k and two jobs die in a row, but not too close to each
+# other, then make will quit without waiting for the rest of the jobs to die.
+
+run_make_test("
+.PHONY: all fail.1 fail.2 fail.3 ok
+all: fail.1 ok fail.2 fail.3
+
+fail.1 fail.2 fail.3:
+ \@$sleep_command \$(patsubst fail.%,%,\$\@)
+ \@echo Fail
+ \@exit 1
+
+ok:
+ \@$sleep_command 4
+ \@echo Ok done",
+ '-rR -j5', "Fail
+#MAKEFILE#:6: recipe for target 'fail.1' failed
+#MAKE#: *** [fail.1] Error 1
+#MAKE#: *** Waiting for unfinished jobs....
+Fail
+#MAKEFILE#:6: recipe for target 'fail.2' failed
+#MAKE#: *** [fail.2] Error 1
+Fail
+#MAKEFILE#:6: recipe for target 'fail.3' failed
+#MAKE#: *** [fail.3] Error 1
+Ok done",
+ 512);
+
+
+# Test for Savannah bug #15641.
+#
+run_make_test('
+.PHONY: all
+all:; @:
+
+-include foo.d
+
+foo.d: comp
+ @echo building $@
+
+comp: mod_a.o mod_b.o; @:
+
+mod_a.o mod_b.o:
+ @exit 1
+', '-j2', '');
+
+
+# TEST #9 -- Savannah bugs 3330 and 15919
+# In earlier versions of make this will either give the wrong answer, or hang.
+
+utouch(-10, 'target');
+run_make_test('target: intermed ; touch $@
+
+.INTERMEDIATE: intermed
+intermed: | phony ; touch $@
+
+.PHONY: phony
+phony: ; : phony', '-rR -j', ': phony');
+rmfiles('target');
+
+# TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec
+# See Savannah bug #33873
+
+$extraENV{MAKEFLAGS} = '-j4';
+
+run_make_test(q!
+things = thing1 thing2
+all: $(things)
+thing1:; @sleep 1; echo '$@ start'; sleep 2; echo '$@ end'
+thing2:; @echo '$@ start'; sleep 2; echo '$@ end'
+-include inc.mk
+inc.mk: ; @touch $@
+!,
+ '', "thing2 start\nthing1 start\nthing2 end\nthing1 end\n");
+
+delete $extraENV{MAKEFLAGS};
+rmfiles('inc.mk');
+
+# Ensure intermediate/secondary files are not pruned incorrectly.
+# See Savannah bug #30653
+
+utouch(-15, 'file2');
+utouch(-10, 'file4');
+utouch(-5, 'file1');
+
+run_make_test(q!
+.INTERMEDIATE: file3
+file4: file3 ; @mv -f $< $@
+file3: file2 ; touch $@
+file2: file1 ; @touch $@
+!,
+ '--no-print-directory -j2', "touch file3");
+
+rmfiles('file1', 'file2', 'file3', 'file4');
+
+# Make sure that all jobserver FDs are closed if we need to re-exec the
+# master copy.
+#
+# First, find the "default" file descriptors we normally use
+# Then make sure they're still used.
+#
+# Right now we don't have a way to run a makefile and capture the output
+# without checking it, so we can't really write this test.
+
+# run_make_test('
+# submake: ; @$(MAKE) --no-print-directory -f #MAKEFILE# fdprint 5>output
+
+# dependfile: ; @echo FOO=bar > $@
+
+# INCL := true
+
+# FOO=foo
+# ifeq ($(INCL),true)
+# -include dependfile
+# endif
+
+# fdprint: ; @echo $(filter --jobserver%,$(MAKEFLAGS))
+
+# recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# submake INCL=true',
+# '-j2 INCL=false fdprint',
+# 'bar');
+
+# rmfiles(qw(dependfile output));
+
+
+# # Do it again, this time where the include is done by the non-master make.
+# run_make_test(undef, '-j2 recurse INCL=false', 'bar');
+
+# rmfiles(qw(dependfile output));
+
+1;
diff --git a/tests/scripts/features/patspecific_vars b/tests/scripts/features/patspecific_vars
new file mode 100644
index 0000000..a530bba
--- /dev/null
+++ b/tests/scripts/features/patspecific_vars
@@ -0,0 +1,148 @@
+# -*-perl-*-
+$description = "Test pattern-specific variable settings.";
+
+$details = "\
+Create a makefile containing various flavors of pattern-specific variable
+settings, override and non-override, and using various variable expansion
+rules, semicolon interference, etc.";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+all: one.x two.x three.x
+FOO = foo
+BAR = bar
+BAZ = baz
+one.x: override FOO = one
+%.x: BAR = two
+t%.x: BAR = four
+thr% : override BAZ = three
+one.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ)
+four.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ)
+baz: ; @echo $@: $(FOO) $(BAR) $(BAZ)
+
+# test matching multiple patterns
+a%: AAA = aaa
+%b: BBB = ccc
+a%: BBB += ddd
+%b: AAA ?= xxx
+%b: AAA += bbb
+.PHONY: ab
+ab: ; @echo $(AAA); echo $(BBB)
+EOF
+
+close(MAKEFILE);
+
+
+# TEST #1 -- basics
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "one.x: one two baz\ntwo.x: foo four baz\nthree.x: foo four three\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2 -- try the override feature
+
+&run_make_with_options($makefile, "BAZ=five", &get_logfile);
+$answer = "one.x: one two five\ntwo.x: foo four five\nthree.x: foo four three\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3 -- make sure patterns are inherited properly
+
+&run_make_with_options($makefile, "four.x", &get_logfile);
+$answer = "baz: foo two baz\nfour.x: foo two baz\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #4 -- test multiple patterns matching the same target
+
+&run_make_with_options($makefile, "ab", &get_logfile);
+$answer = "aaa bbb\nccc ddd\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #5 -- test pattern-specific exported variables
+#
+run_make_test('
+/%: export foo := foo
+
+/bar:
+ @echo $(foo) $$foo
+', '', 'foo foo');
+
+
+# TEST #6 -- test expansion of pattern-specific simple variables
+#
+run_make_test('
+.PHONY: all
+
+all: inherit := good $$t
+all: bar baz
+
+b%: pattern := good $$t
+
+global := original $$t
+
+
+# normal target
+#
+ifdef rec
+bar: a = global: $(global) pattern: $(pattern) inherit: $(inherit)
+else
+bar: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
+endif
+
+bar: ; @echo \'normal: $a;\'
+
+
+# pattern target
+#
+ifdef rec
+%z: a = global: $(global) pattern: $(pattern) inherit: $(inherit)
+else
+%z: a := global: $(global) pattern: $(pattern) inherit: $(inherit)
+endif
+
+%z: ; @echo \'pattern: $a;\'
+
+
+global := new $$t
+',
+'',
+'normal: global: original $t pattern: inherit: ;
+pattern: global: original $t pattern: inherit: ;');
+
+
+# TEST #7 -- test expansion of pattern-specific recursive variables
+#
+run_make_test(undef, # reuse previous makefile
+'rec=1',
+'normal: global: new $t pattern: good $t inherit: good $t;
+pattern: global: new $t pattern: good $t inherit: good $t;');
+
+# TEST #8: override in pattern-specific variables
+
+run_make_test('
+a%: override FOO += f1
+a%: FOO += f2
+ab: ; @echo "$(FOO)"
+',
+ '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C f1\n");
+
+# TEST #9: Test shortest stem selection in pattern-specific variables.
+
+run_make_test('
+%-mt.x: x := two
+%.x: x := one
+
+all: foo.x foo-mt.x
+
+foo.x: ;@echo $x
+foo-mt.x: ;@echo $x
+',
+'',
+"one\ntwo");
+
+1;
diff --git a/tests/scripts/features/patternrules b/tests/scripts/features/patternrules
new file mode 100644
index 0000000..0ff49a7
--- /dev/null
+++ b/tests/scripts/features/patternrules
@@ -0,0 +1,225 @@
+# -*-perl-*-
+
+$description = "Test pattern rules.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+
+# TEST #0: Make sure that multiple patterns where the same target
+# can be built are searched even if the first one fails
+# to match properly.
+#
+
+run_make_test(q!
+.PHONY: all
+
+all: case.1 case.2 case.3
+
+# We can't have this, due to "Implicit Rule Search Algorithm" step 5c
+#xxx: void
+
+# 1 - existing file
+%.1: void
+ @exit 1
+%.1: #MAKEFILE#
+ @exit 0
+
+# 2 - phony
+%.2: void
+ @exit 1
+%.2: 2.phony
+ @exit 0
+.PHONY: 2.phony
+
+# 3 - implicit-phony
+%.3: void
+ @exit 1
+%.3: 3.implicit-phony
+ @exit 0
+
+3.implicit-phony:
+!, '', '');
+
+# TEST #1: make sure files that are built via implicit rules are marked
+# as targets (Savannah bug #12202).
+#
+run_make_test('
+TARGETS := foo foo.out
+
+.PHONY: all foo.in
+
+all: $(TARGETS)
+
+%: %.in
+ @echo $@
+
+%.out: %
+ @echo $@
+
+foo.in: ; @:
+
+',
+'',
+'foo
+foo.out');
+
+
+# TEST #2: make sure intermediate files that also happened to be
+# prerequisites are not removed (Savannah bug #12267).
+#
+run_make_test('
+$(dir)/foo.o:
+
+$(dir)/foo.y:
+ @echo $@
+
+%.c: %.y
+ touch $@
+
+%.o: %.c
+ @echo $@
+
+.PHONY: install
+install: $(dir)/foo.c
+
+',
+"dir=$dir",
+"$dir/foo.y
+touch $dir/foo.c
+$dir/foo.o");
+
+unlink("$dir/foo.c");
+
+
+# TEST #3: make sure precious flag is set properly for targets
+# that are built via implicit rules (Savannah bug #13218).
+#
+run_make_test('
+.DELETE_ON_ERROR:
+
+.PRECIOUS: %.bar
+
+%.bar:; @touch $@ && exit 1
+
+$(dir)/foo.bar:
+
+',
+"dir=$dir",
+"#MAKEFILE#:6: recipe for target '$dir/foo.bar' failed
+#MAKE#: *** [$dir/foo.bar] Error 1",
+512);
+
+unlink("$dir/foo.bar");
+
+
+# TEST #4: make sure targets of a matched implicit pattern rule are
+# never considered intermediate (Savannah bug #13022).
+#
+run_make_test('
+.PHONY: all
+all: foo.c foo.o
+
+%.h %.c: %.in
+ touch $*.h
+ touch $*.c
+
+%.o: %.c %.h
+ echo $+ >$@
+
+%.o: %.c
+ @echo wrong rule
+
+foo.in:
+ touch $@
+
+',
+'',
+'touch foo.in
+touch foo.h
+touch foo.c
+echo foo.c foo.h >foo.o');
+
+unlink('foo.in', 'foo.h', 'foo.c', 'foo.o');
+
+# TEST #5: make sure both prefix and suffix patterns work with multiple
+# target patterns (Savannah bug #26593).
+#
+run_make_test('
+all: foo.s1 foo.s2 p1.foo p2.foo
+
+p1.% p2.%: %.orig
+ @echo $@
+%.s1 %.s2: %.orig
+ @echo $@
+
+.PHONY: foo.orig
+',
+ '', "foo.s1\np1.foo\n");
+
+# TEST 6: Make sure that non-target files are still eligible to be created
+# as part of implicit rule chaining. Savannah bug #17752.
+
+run_make_test(q!
+BIN = xyz
+COPY = $(BIN).cp
+SRC = $(BIN).c
+allbroken: $(COPY) $(BIN) ; @echo ok
+$(SRC): ; @echo 'main(){}' > $@
+%.cp: % ; @cp $< $@
+% : %.c ; @cp $< $@
+clean: ; @rm -rf $(SRC) $(COPY) $(BIN)
+!,
+ '', "ok\n");
+
+unlink(qw(xyz xyz.cp xyz.c));
+
+# TEST 7: Make sure that all prereqs of all "also_make" targets get created
+# before any of the things that depend on any of them. Savannah bug #19108.
+
+run_make_test(q!
+final: x ; @echo $@
+x: x.t1 x.t2 ; @echo $@
+x.t2: dep
+dep: ; @echo $@
+%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2
+!,
+ '', "dep\nx.t1\nx.t2\nx\nfinal\n");
+
+
+# TEST 8: Verify we can remove pattern rules. Savannah bug #18622.
+
+my @f = (qw(foo.w foo.ch));
+touch(@f);
+
+run_make_test(q!
+CWEAVE := :
+
+# Disable builtin rules
+%.tex : %.w
+%.tex : %.w %.ch
+!,
+ 'foo.tex',
+ "#MAKE#: *** No rule to make target 'foo.tex'. Stop.", 512);
+
+unlink(@f);
+
+# TEST #9: Test shortest stem selection in pattern rules.
+
+run_make_test('
+%.x: ;@echo one
+%-mt.x: ;@echo two
+
+all: foo.x foo-mt.x
+',
+'',
+"one\ntwo");
+
+1;
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/quoting b/tests/scripts/features/quoting
new file mode 100644
index 0000000..916681c
--- /dev/null
+++ b/tests/scripts/features/quoting
@@ -0,0 +1,32 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test using \n" .
+ "quotes within makefiles.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOM';
+SHELL = /bin/sh
+TEXFONTS = NICEFONT
+DEFINES = -DDEFAULT_TFM_PATH=\".:$(TEXFONTS)\"
+test: ; @"echo" 'DEFINES = $(DEFINES)'
+EOM
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = 'DEFINES = -DDEFAULT_TFM_PATH=\".:NICEFONT\"' . "\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/features/recursion b/tests/scripts/features/recursion
new file mode 100644
index 0000000..fd5e351
--- /dev/null
+++ b/tests/scripts/features/recursion
@@ -0,0 +1,55 @@
+# -*-perl-*-
+$description = "Test recursion.";
+
+$details = "DETAILS";
+
+# Test some basic recursion.
+run_make_test('
+all:
+ $(MAKE) -f #MAKEFILE# foo
+foo:
+ @echo $(MAKE)
+ @echo MAKELEVEL = $(MAKELEVEL)
+ $(MAKE) -f #MAKEFILE# last
+last:
+ @echo $(MAKE)
+ @echo MAKELEVEL = $(MAKELEVEL)
+ @echo THE END
+',
+ ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')),
+ ($vos
+ ? "#MAKE#: Entering directory '#PWD#'
+make 'CFLAGS=-O' -f #MAKEFILE# foo
+make CFLAGS=-O
+MAKELEVEL = 0
+make 'CFLAGS=-O' -f #MAKEFILE# last
+make CFLAGS=-O
+MAKELEVEL = 0
+THE END
+#MAKE#: Leaving directory '#PWD#'"
+ : "#MAKE#: Entering directory '#PWD#'
+#MAKEPATH# -f #MAKEFILE# foo
+#MAKE#[1]: Entering directory '#PWD#'
+#MAKEPATH#
+MAKELEVEL = 1
+#MAKEPATH# -f #MAKEFILE# last
+#MAKE#[2]: Entering directory '#PWD#'
+#MAKEPATH#
+MAKELEVEL = 2
+THE END
+#MAKE#[2]: Leaving directory '#PWD#'
+#MAKE#[1]: Leaving directory '#PWD#'
+#MAKE#: Leaving directory '#PWD#'"));
+
+
+# Test command line overrides.
+run_make_test('
+recur: all ; @$(MAKE) --no-print-directory -f #MAKEFILE# a=AA all
+all: ; @echo "MAKEOVERRIDES = $(MAKEOVERRIDES)"
+',
+ 'a=ZZ',
+ 'MAKEOVERRIDES = a=ZZ
+MAKEOVERRIDES = a=AA
+');
+
+1;
diff --git a/tests/scripts/features/reinvoke b/tests/scripts/features/reinvoke
new file mode 100644
index 0000000..eb1a349
--- /dev/null
+++ b/tests/scripts/features/reinvoke
@@ -0,0 +1,80 @@
+# -*-mode: perl-*-
+
+$description = "Test GNU make's auto-reinvocation feature.";
+
+$details = "\
+If the makefile or one it includes can be rebuilt then it is, and make
+is reinvoked. We create a rule to rebuild the makefile from a temp
+file, then touch the temp file to make it newer than the makefile.";
+
+$omkfile = $makefile;
+
+&utouch(-600, 'incl.mk');
+# For some reason if we don't do this then the test fails for systems
+# with sub-second timestamps, maybe + NFS? Not sure.
+&utouch(-1, 'incl-1.mk');
+
+run_make_test('
+all: ; @echo running rules.
+
+#MAKEFILE# incl.mk: incl-1.mk
+ @echo rebuilding $@
+ @echo >> $@
+
+include incl.mk',
+ '', "rebuilding incl.mk\nrunning rules.\n");
+
+# Make sure updating the makefile itself also works
+
+&utouch(-600, $omkfile);
+
+run_make_test(undef, '', "rebuilding #MAKEFILE#\nrunning rules.\n");
+
+&rmfiles('incl.mk', 'incl-1.mk');
+
+
+# In this test we create an included file that's out-of-date, but then
+# the rule doesn't update it. Make shouldn't re-exec.
+
+&utouch(-600, 'b','a');
+#&utouch(-10, 'a');
+&touch('c');
+
+run_make_test('
+SHELL = /bin/sh
+
+all: ; @echo hello
+
+a : b ; echo >> $@
+
+b : c ; [ -f $@ ] || echo >> $@
+
+c: ; echo >> $@
+
+include $(F)',
+ 'F=a', "[ -f b ] || echo >> b\nhello\n");
+
+# Now try with the file we're not updating being the actual file we're
+# including: this and the previous one test different parts of the code.
+
+run_make_test(undef, 'F=b', "[ -f b ] || echo >> b\nhello\n")
+
+&rmfiles('a','b','c');
+
+# Ensure command line variables are preserved properly across re-exec
+# Tests for Savannah bug #30723
+
+run_make_test('
+ifdef RECURSE
+-include foo30723
+endif
+recurse: ; @$(MAKE) -f $(MAKEFILE_LIST) RECURSE=1 test
+test: ; @echo F.O=$(F.O)
+foo30723: ; @touch $@
+',
+ '--no-print-directory F.O=bar', "F.O=bar\n");
+
+unlink('foo30723');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/rule_glob b/tests/scripts/features/rule_glob
new file mode 100644
index 0000000..2d377e7
--- /dev/null
+++ b/tests/scripts/features/rule_glob
@@ -0,0 +1,37 @@
+# -*-perl-*-
+
+$description = "Test globbing in targets and prerequisites.";
+
+$details = "";
+
+touch(qw(a.one a.two a.three));
+
+# Test wildcards in regular targets and prerequisites
+run_make_test(q{
+.PHONY: all a.one a.two a.three
+all: a.one* a.t[a-z0-9]o a.th[!q]ee
+a.o[Nn][Ee] a.t*: ; @echo $@
+},
+ '', "a.one\na.two\na.three");
+
+# Test wildcards in pattern targets and prerequisites
+run_make_test(q{
+.PHONY: all
+all: a.four
+%.four : %.t* ; @echo $@: $(sort $^)
+},
+ '', "a.four: a.three a.two");
+
+# Test wildcards in second expansion targets and prerequisites
+run_make_test(q{
+.PHONY: all
+all: a.four
+.SECONDEXPANSION:
+%.four : $$(sort %.t*) ; @echo $@: $(sort $^)
+},
+ '', "a.four: a.three a.two");
+
+unlink(qw(a.one a.two a.three));
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit
new file mode 100644
index 0000000..790017a
--- /dev/null
+++ b/tests/scripts/features/se_explicit
@@ -0,0 +1,167 @@
+# -*-perl-*-
+$description = "Test second expansion in ordinary rules.";
+
+$details = "";
+
+# TEST #0: Test handing of '$' in prerequisites with and without second
+# expansion.
+
+# If we don't support archives then the prerequisite is different
+my $prereq = exists $FEATURES{'archives'} ? '$' : '$(PRE)';
+
+run_make_test(q!
+ifdef SE
+ .SECONDEXPANSION:
+endif
+foo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^'
+PRE = one two
+bar$$baz: $$(PRE)
+baraz: $$(PRE)
+PRE = three four
+.DEFAULT: ; @echo '$@'
+!,
+ '',
+ "$prereq\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz");
+
+run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz");
+
+# TEST #1: automatic variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+foo: bar baz
+
+foo: biz | buz
+
+foo: $$@.1 \
+ $$<.2 \
+ $$(addsuffix .3,$$^) \
+ $$(addsuffix .4,$$+) \
+ $$|.5 \
+ $$*.6
+
+!,
+'',
+'bar
+baz
+biz
+buz
+foo.1
+bar.2
+bar.3
+baz.3
+biz.3
+bar.4
+baz.4
+biz.4
+buz.5
+.6
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+foo.x: $$a $$b
+
+foo.x: a := bar
+
+%.x: b := baz
+!,
+'',
+'bar
+baz
+');
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+all: foo bar baz
+
+# Subtest #1
+foo: foo.1; @:
+foo: foo.2
+foo: foo.3
+
+# Subtest #2
+bar: bar.2
+bar: bar.1; @:
+bar: bar.3
+
+# Subtest #3
+baz: baz.1
+baz: baz.2
+baz: ; @:
+!,
+'',
+'foo.1
+foo.2
+foo.3
+bar.1
+bar.2
+bar.3
+baz.1
+baz.2
+');
+
+# TEST #4: eval in a context where there is no reading_file
+run_make_test(q!
+.SECONDEXPANSION:
+all : $$(eval $$(info test))
+!,
+ '', "test\n#MAKE#: Nothing to be done for 'all'.\n");
+
+# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new
+# target/prereq relationships.
+
+run_make_test(q!
+.SECONDEXPANSION:
+proj1.exe : proj1.o $$(eval $$(test))
+define test
+proj1.o : proj1.c
+proj1.c: proj1.h
+endef
+!,
+ '', "#MAKE#: *** prerequisites cannot be defined in recipes. Stop.\n", 512);
+
+
+# Automatic $$+ variable expansion issue. Savannah bug #25780
+run_make_test(q!
+all : foo foo
+.SECONDEXPANSION:
+all : $$+ ; @echo '$+'
+foo : ;
+!,
+ '', "foo foo foo foo\n");
+
+
+# Automatic $$+ variable expansion issue. Savannah bug #25780
+run_make_test(q!
+all : bar bar
+bar : ;
+q%x : ;
+.SECONDEXPANSION:
+a%l: q1x $$+ q2x ; @echo '$+'
+!,
+ '', "q1x bar bar q2x bar bar\n");
+
+
+# Allow patsubst shorthand in second expansion context.
+# Requires the colon to be quoted. Savannah bug #16545
+run_make_test(q!
+.PHONY: foo.bar
+.SECONDEXPANSION:
+foo: $$(@\\:%=%.bar); @echo '$^'
+!,
+ '', "foo.bar\n");
+
+1;
diff --git a/tests/scripts/features/se_implicit b/tests/scripts/features/se_implicit
new file mode 100644
index 0000000..ec09d8d
--- /dev/null
+++ b/tests/scripts/features/se_implicit
@@ -0,0 +1,260 @@
+# -*-perl-*-
+$description = "Test second expansion in ordinary rules.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+
+# Test #1: automatic variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+foo.a: bar baz
+
+foo.a: biz | buz
+
+foo.%: 1.$$@ \
+ 2.$$< \
+ $$(addprefix 3.,$$^) \
+ $$(addprefix 4.,$$+) \
+ 5.$$| \
+ 6.$$*
+ @:
+
+1.foo.a \
+2.bar \
+3.bar \
+3.baz \
+3.biz \
+4.bar \
+4.baz \
+4.biz \
+5.buz \
+6.a:
+ @echo '$@'
+
+!,
+'',
+'1.foo.a
+2.bar
+3.bar
+3.baz
+3.biz
+4.bar
+4.baz
+4.biz
+5.buz
+6.a
+bar
+baz
+biz
+buz
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+foo.x:
+
+foo.%: $$(%_a) $$(%_b) bar
+ @:
+
+foo.x: x_a := bar
+
+%.x: x_b := baz
+
+bar baz: ; @echo '$@'
+!,
+ '', "bar\nbaz\n");
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+all: foo bar baz
+
+
+# Subtest #1
+#
+%oo: %oo.1; @:
+
+foo: foo.2
+
+foo: foo.3
+
+foo.1: ; @echo '$@'
+
+
+# Subtest #2
+#
+bar: bar.2
+
+%ar: %ar.1; @:
+
+bar: bar.3
+
+bar.1: ; @echo '$@'
+
+
+# Subtest #3
+#
+baz: baz.1
+
+baz: baz.2
+
+%az: ; @:
+!,
+ '',
+'foo.1
+foo.2
+foo.3
+bar.1
+bar.2
+bar.3
+baz.1
+baz.2
+');
+
+
+# Test #4: stem splitting logic.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+$(dir)/tmp/bar.o:
+
+$(dir)/tmp/foo/bar.c: ; @echo '$@'
+$(dir)/tmp/bar/bar.c: ; @echo '$@'
+foo.h: ; @echo '$@'
+
+%.o: $$(addsuffix /%.c,foo bar) foo.h
+ @echo '$@: {$<} $^'
+!,
+ "dir=$dir", "$dir/tmp/foo/bar.c
+$dir/tmp/bar/bar.c
+foo.h
+$dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h
+");
+
+
+# Test #5: stem splitting logic and order-only prerequisites.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+$(dir)/tmp/foo.o: $(dir)/tmp/foo.c
+$(dir)/tmp/foo.c: ; @echo '$@'
+bar.h: ; @echo '$@'
+
+%.o: %.c|bar.h
+ @echo '$@: {$<} {$|} $^'
+
+!,
+ "dir=$dir", "$dir/tmp/foo.c
+bar.h
+$dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c
+");
+
+
+# Test #6: lack of implicit prerequisites.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+foo.o: foo.c
+foo.c: ; @echo '$@'
+
+%.o:
+ @echo '$@: {$<} $^'
+!,
+ '', "foo.c\nfoo.o: {foo.c} foo.c\n");
+
+
+# Test #7: Test stem from the middle of the name.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+foobarbaz:
+
+foo%baz: % $$*.1
+ @echo '$*'
+
+bar bar.1:
+ @echo '$@'
+!,
+ '', "bar\nbar.1\nbar\n");
+
+
+# Test #8: Make sure stem triple-expansion does not happen.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+foo$$bar:
+
+f%r: % $$*.1
+ @echo '$*'
+
+oo$$ba oo$$ba.1:
+ @echo '$@'
+!,
+ '', 'oo$ba
+oo$ba.1
+oo$ba
+');
+
+# Test #9: Check the value of $^
+run_make_test(q!
+.SECONDEXPANSION:
+
+%.so: | $$(extra) ; @echo $^
+
+foo.so: extra := foo.o
+foo.so:
+foo.o:
+!,
+ '', "\n");
+
+# Test #10: Test second expansion with second expansion prerequisites
+# Ensures pattern_search() recurses with SE prereqs.
+touch('a');
+run_make_test(q!
+.SECONDEXPANSION:
+sim_base_rgg := just_a_name
+sim_base_src := a
+sim_base_f := a a a
+sim_%.f: $${sim_$$*_f}
+ echo $@
+sim_%.src: $${sim_$$*_src}
+ echo $@
+sim_%: \
+ $$(if $$(sim_$$*_src),sim_%.src) \
+ $$(if $$(sim_$$*_f),sim_%.f) \
+ $$(if $$(sim_$$*_rgg),$$(sim_$$*_rgg).s)
+ echo $@
+!,
+ '-s sim_base', "#MAKE#: *** No rule to make target 'sim_base'. Stop.", 512);
+
+unlink('a');
+
+# Ensure that order-only tokens embedded in second expansions are parsed
+run_make_test(q!
+.SECONDEXPANSION:
+PREREQS=p1|p2
+P2=p2
+all : foo bar
+f%o: $$(PREREQS) ; @echo '$@' from '$^' and '$|'
+b%r: p1|$$(P2) ; @echo '$@' from '$^' and '$|'
+p% : ; : $@
+!,
+ "", ": p1\n: p2\nfoo from p1 and p2\nbar from p1 and p2\n");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/se_statpat b/tests/scripts/features/se_statpat
new file mode 100644
index 0000000..b1e59e1
--- /dev/null
+++ b/tests/scripts/features/se_statpat
@@ -0,0 +1,107 @@
+# -*-perl-*-
+$description = "Test second expansion in static pattern rules.";
+
+$details = "";
+
+# Test #1: automatic variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+foo.a foo.b: foo.%: bar.% baz.%
+foo.a foo.b: foo.%: biz.% | buz.%
+
+foo.a foo.b: foo.%: $$@.1 \
+ $$<.2 \
+ $$(addsuffix .3,$$^) \
+ $$(addsuffix .4,$$+) \
+ $$|.5 \
+ $$*.6
+!,
+ '', 'bar.a
+baz.a
+biz.a
+buz.a
+foo.a.1
+bar.a.2
+bar.a.3
+baz.a.3
+biz.a.3
+bar.a.4
+baz.a.4
+biz.a.4
+buz.a.5
+a.6
+');
+
+
+# Test #2: target/pattern -specific variables.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+foo.x foo.y: foo.%: $$(%_a) $$($$*_b)
+
+foo.x: x_a := bar
+
+%.x: x_b := baz
+!,
+ '', "bar\nbaz\n");
+
+
+# Test #3: order of prerequisites.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+.DEFAULT: ; @echo '$@'
+
+all: foo.a bar.a baz.a
+
+# Subtest #1
+foo.a foo.b: foo.%: foo.%.1; @:
+foo.a foo.b: foo.%: foo.%.2
+foo.a foo.b: foo.%: foo.%.3
+
+
+# Subtest #2
+bar.a bar.b: bar.%: bar.%.2
+bar.a bar.b: bar.%: bar.%.1; @:
+bar.a bar.b: bar.%: bar.%.3
+
+
+# Subtest #3
+baz.a baz.b: baz.%: baz.%.1
+baz.a baz.b: baz.%: baz.%.2
+baz.a baz.b: ; @:
+!,
+ '', 'foo.a.1
+foo.a.2
+foo.a.3
+bar.a.1
+bar.a.2
+bar.a.3
+baz.a.1
+baz.a.2
+');
+
+
+# Test #4: Make sure stem triple-expansion does not happen.
+#
+run_make_test(q!
+.SECONDEXPANSION:
+foo$$bar: f%r: % $$*.1
+ @echo '$*'
+
+oo$$ba oo$$ba.1:
+ @echo '$@'
+!,
+ '', 'oo$ba
+oo$ba.1
+oo$ba
+');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/shell_assignment b/tests/scripts/features/shell_assignment
new file mode 100644
index 0000000..686e4bd
--- /dev/null
+++ b/tests/scripts/features/shell_assignment
@@ -0,0 +1,65 @@
+# -*-perl-*-
+
+$description = "Test BSD-style shell assignments (VAR != VAL) for variables.";
+
+$details = "";
+
+# TEST 0: Basic shell assignment (!=).
+
+run_make_test('
+.POSIX:
+
+demo1!=printf \' 1 2 3\n4\n\n5 \n \n 6\n\n\n\n\'
+demo2 != printf \'7 8\n \'
+demo3 != printf \'$$(demo2)\'
+demo4 != printf \' 2 3 \n\'
+demo5 != printf \' 2 3 \n\n\'
+all: ; @echo "<$(demo1)> <$(demo2)> <$(demo3)> <$(demo4)> <${demo5}>"
+',
+ '', "< 1 2 3 4 5 6 > <7 8 > <7 8 > < 2 3 > < 2 3 >\n");
+
+# TEST 1: Handle '#' the same way as BSD make
+
+run_make_test('
+foo1!=echo bar#baz
+hash != printf \'\043\'
+foo2!= echo "bar$(hash)baz"
+
+all: ; @echo "<$(foo1)> <$(hash)> <$(foo2)>"
+',
+ '', "<bar> <#> <bar#baz>\n");
+
+# TEST 2: shell assignment variables (from !=) should be recursive.
+# Note that variables are re-evaluated later, so the shell can output
+# a value like $(XYZZY) as part of !=. The $(XYZZY) will be EVALUATED
+# when the value containing it is evaluated. On the negative side, this
+# means if you don't want this, you need to escape dollar signs as $$.
+# On the positive side, it means that shell programs can output macros
+# that are then evaluated as they are traditionally evaluated.. and that
+# you can use traditional macro evaluation semantics to implement !=.
+
+run_make_test('
+XYZZY = fiddle-dee-dee
+dollar = $$
+VAR3 != printf \'%s\' \'$(dollar)(XYZZY)\'
+
+all: ; @echo "<$(VAR3)>"
+',
+ '', "<fiddle-dee-dee>\n");
+
+
+# TEST 3: Overrides invoke shell anyway; they just don't store the result
+# in a way that is visible.
+
+run_make_test('
+
+override != echo abc > ,abc ; cat ,abc
+
+all: ; @echo "<$(override)>" ; cat ,abc
+',
+ 'override=xyz', "<xyz>\nabc\n");
+
+unlink(',abc');
+
+
+1;
diff --git a/tests/scripts/features/statipattrules b/tests/scripts/features/statipattrules
new file mode 100644
index 0000000..3f363de
--- /dev/null
+++ b/tests/scripts/features/statipattrules
@@ -0,0 +1,111 @@
+# -*-perl-*-
+$description = "Test handling of static pattern rules.";
+
+$details = "\
+The makefile created in this test has three targets. The
+filter command is used to get those target names ending in
+.o and statically creates a compile command with the target
+name and the target name with .c. It also does the same thing
+for another target filtered with .elc and creates a command
+to emacs a .el file";
+
+&touch('bar.c', 'lose.c');
+
+# TEST #0
+# -------
+
+run_make_test('
+files = foo.elc bar.o lose.o
+
+$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@
+
+$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<
+',
+ '',
+ 'CC -c bar.c -o bar.o');
+
+# TEST #1
+# -------
+
+run_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o');
+
+
+# TEST #2
+# -------
+&touch("foo.el");
+
+run_make_test(undef, 'foo.elc', 'emacs foo.el');
+
+# Clean up after the first tests.
+unlink('foo.el', 'bar.c', 'lose.c');
+
+
+# TEST #3 -- PR/1670: don't core dump on invalid static pattern rules
+# -------
+
+run_make_test('
+.DEFAULT: ; @echo $@
+foo: foo%: % %.x % % % y.% % ; @echo $@
+',
+ '', ".x\ny.\nfoo");
+
+
+# TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty
+# prerequisite list.
+run_make_test('
+foo.x bar.x: %.x : ; @echo $@
+
+',
+ '', 'foo.x');
+
+
+# TEST #5 -- bug #13881: double colon static pattern rule does not
+# substitute %.
+run_make_test('
+foo.bar:: %.bar: %.baz
+foo.baz: ;@:
+',
+ '', '');
+
+
+# TEST #6: make sure the second stem does not overwrite the first
+# perprerequisite's stem (Savannah bug #16053).
+#
+run_make_test('
+all.foo.bar: %.foo.bar: %.one
+
+all.foo.bar: %.bar: %.two
+
+all.foo.bar:
+ @echo $*
+ @echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all.foo.two');
+
+
+# TEST #7: make sure the second stem does not overwrite the first
+# perprerequisite's stem when second expansion is enabled
+# (Savannah bug #16053).
+#
+run_make_test('
+.SECONDEXPANSION:
+
+all.foo.bar: %.foo.bar: %.one $$*-one
+
+all.foo.bar: %.bar: %.two $$*-two
+
+all.foo.bar:
+ @echo $*
+ @echo $^
+
+.DEFAULT:;@:
+',
+'',
+'all.foo
+all.one all-one all.foo.two all.foo-two');
+
+1;
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
new file mode 100644
index 0000000..a9b8dbe
--- /dev/null
+++ b/tests/scripts/features/targetvars
@@ -0,0 +1,273 @@
+# -*-perl-*-
+$description = "Test target-specific variable settings.";
+
+$details = "\
+Create a makefile containing various flavors of target-specific variable
+values, override and non-override, and using various variable expansion
+rules, semicolon interference, etc.";
+
+run_make_test('
+SHELL = /bin/sh
+export FOO = foo
+export BAR = bar
+one: override FOO = one
+one two: ; @echo $(FOO) $(BAR)
+two: BAR = two
+three: ; BAR=1000
+ @echo $(FOO) $(BAR)
+# Some things that shouldn not be target vars
+funk : override
+funk : override adelic
+adelic override : ; echo $@
+# Test per-target recursive variables
+four:FOO=x
+four:VAR$(FOO)=ok
+four: ; @echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)"
+five:FOO=x
+five six : VAR$(FOO)=good
+five six: ;@echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)"
+# Test per-target variable inheritance
+seven: eight
+seven eight: ; @echo $@: $(FOO) $(BAR)
+seven: BAR = seven
+seven: FOO = seven
+eight: BAR = eight
+# Test the export keyword with per-target variables
+nine: ; @echo $(FOO) $(BAR) $$FOO $$BAR
+nine: FOO = wallace
+nine-a: export BAZ = baz
+nine-a: ; @echo $$BAZ
+# Test = escaping
+EQ = =
+ten: one$(EQ)two
+ten: one $(EQ) two
+ten one$(EQ)two $(EQ):;@echo $@
+.PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two
+# Test target-specific vars with pattern/suffix rules
+QVAR = qvar
+RVAR = =
+%.q : ; @echo $(QVAR) $(RVAR)
+foo.q : RVAR += rvar
+# Target-specific vars with multiple LHS pattern rules
+%.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR)
+foo.r : RVAR += rvar
+foo.t : TVAR := $(QVAR)
+',
+ "one two three", "one bar\nfoo two\nBAR=1000\nfoo bar\n");
+
+# TEST #2
+
+run_make_test(undef, "one two FOO=1 BAR=2", "one 2\n1 2\n");
+
+# TEST #3
+
+run_make_test(undef, "four", "x ok ok\n");
+
+# TEST #4
+
+run_make_test(undef, "seven", "eight: seven eight\nseven: seven seven\n");
+
+# TEST #5
+
+run_make_test(undef, "nine", "wallace bar wallace bar\n");
+
+# TEST #5-a
+
+run_make_test(undef, "nine-a", "baz\n");
+
+# TEST #6
+
+run_make_test(undef, "ten", "one=two\none bar\n=\nfoo two\nten\n");
+
+# TEST #6
+
+run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n");
+
+# TEST #7
+
+run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n");
+
+
+# TEST #8
+# For PR/1378: Target-specific vars don't inherit correctly
+
+run_make_test('
+foo: FOO = foo
+bar: BAR = bar
+foo: bar
+bar: baz
+baz: ; @echo $(FOO) $(BAR)
+', "", "foo bar\n");
+
+# TEST #9
+# For PR/1380: Using += assignment in target-specific variables sometimes fails
+# Also PR/1831
+
+run_make_test('
+.PHONY: all one
+all: FOO += baz
+all: one; @echo $(FOO)
+
+FOO = bar
+
+one: FOO += biz
+one: FOO += boz
+one: ; @echo $(FOO)
+',
+ '', "bar baz biz boz\nbar baz\n");
+
+# Test #10
+
+run_make_test(undef, 'one', "bar biz boz\n");
+
+# Test #11
+# PR/1709: Test semicolons in target-specific variable values
+
+run_make_test('
+foo : FOO = ; ok
+foo : ; @echo "$(FOO)"
+',
+ '', "; ok\n");
+
+# Test #12
+# PR/2020: More hassles with += target-specific vars. I _really_ think
+# I nailed it this time :-/.
+
+run_make_test('
+.PHONY: a
+
+BLAH := foo
+COMMAND = echo $(BLAH)
+
+a: ; @$(COMMAND)
+
+a: BLAH := bar
+a: COMMAND += snafu $(BLAH)
+',
+ '', "bar snafu bar\n");
+
+# Test #13
+# Test double-colon rules with target-specific variable values
+
+run_make_test('
+W = bad
+X = bad
+foo: W = ok
+foo:: ; @echo $(W) $(X) $(Y) $(Z)
+foo:: ; @echo $(W) $(X) $(Y) $(Z)
+foo: X = ok
+
+Y = foo
+bar: foo
+bar: Y = bar
+
+Z = nopat
+ifdef PATTERN
+ fo% : Z = pat
+endif
+',
+ 'foo', "ok ok foo nopat\nok ok foo nopat\n");
+
+# Test #14
+# Test double-colon rules with target-specific variable values and
+# inheritance
+
+run_make_test(undef, 'bar', "ok ok bar nopat\nok ok bar nopat\n");
+
+# Test #15
+# Test double-colon rules with pattern-specific variable values
+
+run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n");
+
+# Test #16
+# Test target-specific variables with very long command line
+# (> make default buffer length)
+
+run_make_test('
+base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
+
+deals_changed_since: ; @echo $(BUILD_OBJ)
+',
+ '', "no build information\n");
+
+# TEST #17
+
+# Test a merge of set_lists for files, where one list is much longer
+# than the other. See Savannah bug #15757.
+
+mkdir('t1', 0777);
+touch('t1/rules.mk');
+
+run_make_test('
+VPATH = t1
+include rules.mk
+.PHONY: all
+all: foo.x
+foo.x : rules.mk ; @echo MYVAR=$(MYVAR) FOOVAR=$(FOOVAR) ALLVAR=$(ALLVAR)
+all: ALLVAR = xxx
+foo.x: FOOVAR = bar
+rules.mk : MYVAR = foo
+.INTERMEDIATE: foo.x rules.mk
+',
+ '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx');
+
+rmfiles('t1/rules.mk');
+rmdir('t1');
+
+# TEST #18
+
+# Test appending to a simple variable containing a "$": avoid a
+# double-expansion. See Savannah bug #15913.
+
+run_make_test('
+VAR := $$FOO
+foo: VAR += BAR
+foo: ; @echo '."'".'$(VAR)'."'".'
+',
+ '', '$FOO BAR');
+
+# TEST #19: Override with append variables
+
+run_make_test('
+a: override FOO += f1
+a: FOO += f2
+a: ; @echo "$(FOO)"
+',
+ '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C f1\n");
+
+# TEST #19: Conditional variables with command-line settings
+
+run_make_test('
+a: FOO ?= f1
+a: ; @echo "$(FOO)"
+',
+ '', "f1\n");
+
+run_make_test(undef, 'FOO=C', "C\n");
+
+# TEST #20: Check for continuation after semicolons
+
+run_make_test(q!
+a: A = 'hello;\
+world'
+a: ; @echo $(A)
+!,
+ '', "hello; world\n");
+
+# TEST #19: Test define/endef variables as target-specific vars
+
+# run_make_test('
+# define b
+# @echo global
+# endef
+# a: define b
+# @echo local
+# endef
+
+# a: ; $(b)
+# ',
+# '', "local\n");
+
+1;
diff --git a/tests/scripts/features/utf8 b/tests/scripts/features/utf8
new file mode 100644
index 0000000..54bc471
--- /dev/null
+++ b/tests/scripts/features/utf8
@@ -0,0 +1,11 @@
+# -*-perl-*-
+
+$description = "Test support for UTF-8.";
+
+$details = "";
+
+# Verify that the UTF-8 BOM is ignored.
+run_make_test("\xEF\xBB\xBFall: ; \@echo \$\@\n", '', "all");
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/features/varnesting b/tests/scripts/features/varnesting
new file mode 100644
index 0000000..d8f3ffb
--- /dev/null
+++ b/tests/scripts/features/varnesting
@@ -0,0 +1,35 @@
+# -*-perl-*-
+$description = "Test recursive variables";
+
+$details = "";
+
+run_make_test('
+x = variable1
+variable2 := Hello
+y = $(subst 1,2,$(x))
+z = y
+a := $($($(z)))
+all:
+ @echo $(a)
+',
+ '', "Hello\n");
+
+# This tests resetting the value of a variable while expanding it.
+# You may only see problems with this if you're using valgrind or
+# some other memory checker that poisons freed memory.
+# See Savannah patch #7534
+
+run_make_test('
+VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
+wololo:
+ @$(VARIABLE)
+',
+ '', "hi\n");
+
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/features/vpath b/tests/scripts/features/vpath
new file mode 100644
index 0000000..ec24165
--- /dev/null
+++ b/tests/scripts/features/vpath
@@ -0,0 +1,81 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test the \n"
+ ."vpath directive which allows you to specify a search \n"
+ ."path for a particular class of filenames, those that\n"
+ ."match a particular pattern.";
+
+$details = "This tests the vpath directive by specifying search directories\n"
+ ."for one class of filenames with the form: vpath pattern directories"
+ ."\nIn this test, we specify the working directory for all files\n"
+ ."that end in c or h. We also test the variables $@ (which gives\n"
+ ."target name) and $^ (which is a list of all dependencies \n"
+ ."including the directories in which they were found). It also\n"
+ ."uses the function firstword used to extract just the first\n"
+ ."dependency from the entire list.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "vpath %.c foo\n";
+print MAKEFILE "vpath %.c $workdir\n";
+print MAKEFILE "vpath %.h $workdir\n";
+print MAKEFILE "objects = main.o kbd.o commands.o display.o insert.o\n";
+print MAKEFILE "edit: \$(objects)\n";
+print MAKEFILE "\t\@echo cc -o \$@ \$^\n";
+print MAKEFILE "main.o : main.c defs.h\n";
+print MAKEFILE "\t\@echo cc -c \$(firstword \$^)\n";
+print MAKEFILE "kbd.o : kbd.c defs.h command.h\n";
+print MAKEFILE "\t\@echo cc -c kbd.c\n";
+print MAKEFILE "commands.o : command.c defs.h command.h\n";
+print MAKEFILE "\t\@echo cc -c commands.c\n";
+print MAKEFILE "display.o : display.c defs.h buffer.h\n";
+print MAKEFILE "\t\@echo cc -c display.c\n";
+print MAKEFILE "insert.o : insert.c defs.h buffer.h\n";
+print MAKEFILE "\t\@echo cc -c insert.c\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+ "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+ "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
+ ."cc -c display.c\n"
+ ."cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o "
+ ."insert.o\n";
+
+if (&compare_output($answer,&get_logfile(1)))
+{
+ unlink @files_to_touch;
+}
+
+# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency
+# warnings due to change of struct file ptr. Savannah bug #13529.
+
+mkdir('vpath-d', 0777);
+
+run_make_test(q!
+vpath %.te vpath-d/
+.SECONDARY:
+default: vpath-d/a vpath-d/b
+vpath-d/a: fail.te
+vpath-d/b : fail.te
+vpath-d/fail.te:
+!,
+ '', "#MAKE#: Nothing to be done for 'default'.\n");
+
+rmdir('vpath-d');
+
+1;
diff --git a/tests/scripts/features/vpath2 b/tests/scripts/features/vpath2
new file mode 100644
index 0000000..7e970a7
--- /dev/null
+++ b/tests/scripts/features/vpath2
@@ -0,0 +1,45 @@
+$description = "This is part 2 in a series to test the vpath directive\n"
+ ."It tests the three forms of the directive:\n"
+ ." vpath pattern directive\n"
+ ." vpath pattern (clears path associated with pattern)\n"
+ ." vpath (clears all paths specified with vpath)\n";
+
+$details = "This test simply adds many search paths using various vpath\n"
+ ."directive forms and clears them afterwards. It has a simple\n"
+ ."rule to print a message at the end to confirm that the makefile\n"
+ ."ran with no errors.\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $workdir:$sourcedir\n";
+print MAKEFILE "vpath %.c foo\n";
+print MAKEFILE "vpath %.c $workdir\n";
+print MAKEFILE "vpath %.c $sourcedir\n";
+print MAKEFILE "vpath %.h $workdir\n";
+print MAKEFILE "vpath %.c\n";
+print MAKEFILE "vpath\n";
+print MAKEFILE "all:\n";
+print MAKEFILE "\t\@echo ALL IS WELL\n";
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "ALL IS WELL\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/features/vpath3 b/tests/scripts/features/vpath3
new file mode 100644
index 0000000..c6ede28
--- /dev/null
+++ b/tests/scripts/features/vpath3
@@ -0,0 +1,35 @@
+# -*-perl-*-
+
+$description = "Test the interaction of the -lfoo feature and vpath";
+$details = "";
+
+my @dirs_to_make = qw(a1 b1 a2 b2 b3);
+for my $d (@dirs_to_make) {
+ mkdir($d, 0777);
+}
+
+my @files_to_touch = ("a1${pathsep}lib1.a",
+ "a1${pathsep}libc.a",
+ "b1${pathsep}lib1.so",
+ "a2${pathsep}lib2.a",
+ "b2${pathsep}lib2.so",
+ "lib3.a",
+ "b3${pathsep}lib3.so");
+&touch(@files_to_touch);
+
+run_make_test('
+vpath %.h b3
+vpath %.a a1
+vpath %.so b1
+vpath % a2 b2
+vpath % b3
+all: -l1 -lc -l2 -l3; @echo $^
+',
+ '', "a1${pathsep}lib1.a a1${pathsep}libc.a a2${pathsep}lib2.a lib3.a\n");
+
+unlink(@files_to_touch);
+for my $d (@dirs_to_make) {
+ rmdir($d);
+}
+
+1;
diff --git a/tests/scripts/features/vpathgpath b/tests/scripts/features/vpathgpath
new file mode 100644
index 0000000..5e6217b
--- /dev/null
+++ b/tests/scripts/features/vpathgpath
@@ -0,0 +1,66 @@
+# -*-perl-*-
+$description = "Tests VPATH+/GPATH functionality.";
+
+$details = "";
+
+$VP = "$workdir$pathsep";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $VP\n";
+
+print MAKEFILE <<'EOMAKE';
+
+GPATH = $(VPATH)
+
+.SUFFIXES: .a .b .c .d
+.PHONY: general rename notarget intermediate
+
+%.a:
+%.b:
+%.c:
+%.d:
+
+%.a : %.b ; cat $^ > $@
+%.b : %.c ; cat $^ > $@
+%.c :: %.d ; cat $^ > $@
+
+# General testing info:
+
+general: foo.b
+foo.b: foo.c bar.c
+
+EOMAKE
+
+close(MAKEFILE);
+
+@touchedfiles = ();
+
+$off = -500;
+
+sub touchfiles {
+ foreach (@_) {
+ ($f = $_) =~ s,VP/,$VP,g;
+ &utouch($off, $f);
+ $off += 10;
+ push(@touchedfiles, $f);
+ }
+}
+
+# Run the general-case test
+
+&touchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d");
+
+&run_make_with_options($makefile,"general",&get_logfile());
+
+push(@touchedfiles, "bar.c");
+
+$answer = "$make_name: Nothing to be done for 'general'.\n";
+
+&compare_output($answer,&get_logfile(1));
+
+unlink(@touchedfiles) unless $keep;
+
+1;
diff --git a/tests/scripts/features/vpathplus b/tests/scripts/features/vpathplus
new file mode 100644
index 0000000..361788c
--- /dev/null
+++ b/tests/scripts/features/vpathplus
@@ -0,0 +1,129 @@
+# -*-perl-*-
+$description = "Tests the new VPATH+ functionality added in 3.76.";
+
+$details = "";
+
+$VP = "$workdir$pathsep";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "VPATH = $VP\n";
+
+print MAKEFILE <<'EOMAKE';
+
+SHELL = /bin/sh
+
+.SUFFIXES: .a .b .c .d
+.PHONY: general rename notarget intermediate
+
+%.a:
+%.b:
+%.c:
+%.d:
+
+%.a : %.b
+ cat $^ > $@
+%.b : %.c
+ cat $^ > $@ 2>/dev/null || exit 1
+%.c :: %.d
+ cat $^ > $@
+
+# General testing info:
+
+general: foo.b
+foo.b: foo.c bar.c
+
+# Rename testing info:
+
+rename: $(VPATH)/foo.c foo.d
+
+# Target not made testing info:
+
+notarget: notarget.b
+notarget.c: notarget.d
+ -@echo "not creating $@ from $^"
+
+# Intermediate files:
+
+intermediate: inter.a
+
+EOMAKE
+
+close(MAKEFILE);
+
+@touchedfiles = ();
+
+$off = -500;
+
+sub touchfiles {
+ foreach (@_) {
+ &utouch($off, $_);
+ $off += 10;
+ push(@touchedfiles, $_);
+ }
+}
+
+# Run the general-case test
+
+&touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d");
+
+&run_make_with_options($makefile,"general",&get_logfile);
+
+push(@touchedfiles, "bar.c");
+
+$answer = "cat bar.d > bar.c
+cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
+";
+&compare_output($answer,&get_logfile(1));
+
+# Test rules that don't make the target correctly
+
+&touchfiles("$VP/notarget.c", "notarget.b", "notarget.d");
+
+&run_make_with_options($makefile,"notarget",&get_logfile,512);
+
+$answer = "not creating notarget.c from notarget.d
+cat notarget.c > notarget.b 2>/dev/null || exit 1
+$makefile:16: recipe for target 'notarget.b' failed
+$make_name: *** [notarget.b] Error 1
+";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test intermediate file handling (part 1)
+
+&touchfiles("$VP/inter.d");
+
+&run_make_with_options($makefile,"intermediate",&get_logfile);
+
+push(@touchedfiles, "inter.a", "inter.b");
+
+$answer = "cat ${VP}inter.d > inter.c
+cat inter.c > inter.b 2>/dev/null || exit 1
+cat inter.b > inter.a
+rm inter.b inter.c
+";
+&compare_output($answer,&get_logfile(1));
+
+# Test intermediate file handling (part 2)
+
+&utouch(-20, "inter.a");
+&utouch(-10, "$VP/inter.b");
+&touch("$VP/inter.d");
+
+push(@touchedfiles, "$VP/inter.b", "$VP/inter.d");
+
+&run_make_with_options($makefile,"intermediate",&get_logfile);
+
+$answer = "cat ${VP}inter.d > inter.c
+cat inter.c > inter.b 2>/dev/null || exit 1
+cat inter.b > inter.a
+rm inter.c
+";
+&compare_output($answer,&get_logfile(1));
+
+unlink @touchedfiles unless $keep;
+
+1;
diff --git a/tests/scripts/functions/abspath b/tests/scripts/functions/abspath
new file mode 100644
index 0000000..84c30ab
--- /dev/null
+++ b/tests/scripts/functions/abspath
@@ -0,0 +1,81 @@
+# -*-perl-*-
+$description = "Test the abspath functions.";
+
+$details = "";
+
+run_make_test('
+ifneq ($(realpath $(abspath .)),$(CURDIR))
+ $(warning .: abs="$(abspath .)" real="$(realpath $(abspath .))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(realpath $(abspath ./)),$(CURDIR))
+ $(warning ./: abs="$(abspath ./)" real="$(realpath $(abspath ./))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(realpath $(abspath .///)),$(CURDIR))
+ $(warning .///: abs="$(abspath .///)" real="$(realpath $(abspath .///))" curdir="$(CURDIR)")
+endif
+
+ifneq ($(abspath /),/)
+ $(warning /: abspath="$(abspath /)")
+endif
+
+ifneq ($(abspath ///),/)
+ $(warning ///: abspath="$(abspath ///)")
+endif
+
+ifneq ($(abspath /.),/)
+ $(warning /.: abspath="$(abspath /.)")
+endif
+
+ifneq ($(abspath ///.),/)
+ $(warning ///.: abspath="$(abspath ///.)")
+endif
+
+ifneq ($(abspath /./),/)
+ $(warning /./: abspath="$(abspath /./)")
+endif
+
+ifneq ($(abspath /.///),/)
+ $(warning /.///: abspath="$(abspath /.///)")
+endif
+
+ifneq ($(abspath /..),/)
+ $(warning /..: abspath="$(abspath /..)")
+endif
+
+ifneq ($(abspath ///..),/)
+ $(warning ///..: abspath="$(abspath ///..)")
+endif
+
+ifneq ($(abspath /../),/)
+ $(warning /../: abspath="$(abspath /../)")
+endif
+
+ifneq ($(abspath /..///),/)
+ $(warning /..///: abspath="$(abspath /..///)")
+endif
+
+
+ifneq ($(abspath /foo/bar/..),/foo)
+ $(warning /foo/bar/..: abspath="$(abspath /foo/bar/..)")
+endif
+
+ifneq ($(abspath /foo/bar/../../../baz),/baz)
+ $(warning /foo/bar/../../../baz: abspath="$(abspath /foo/bar/../../../baz)")
+endif
+
+ifneq ($(abspath /foo/bar/../ /..),/foo /)
+ $(warning /foo/bar/../ /..: abspath="$(abspath /foo/bar/../ /..)")
+endif
+
+
+.PHONY: all
+all: ; @:
+',
+'',
+'');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/functions/addprefix b/tests/scripts/functions/addprefix
new file mode 100644
index 0000000..1845552
--- /dev/null
+++ b/tests/scripts/functions/addprefix
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the addprefix "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(addprefix src${pathsep},a.b.z.foo hacks) \n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep}a.b.z.foo src${pathsep}hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/addsuffix b/tests/scripts/functions/addsuffix
new file mode 100644
index 0000000..da4fbb7
--- /dev/null
+++ b/tests/scripts/functions/addsuffix
@@ -0,0 +1,36 @@
+# -*-perl-*-
+$description = "Test the addsuffix function.";
+
+$details = "";
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOMAKE;
+string := \$(addsuffix .c,src${pathsep}a.b.z.foo hacks)
+one: ; \@echo \$(string)
+
+two: ; \@echo \$(addsuffix foo,)
+EOMAKE
+
+close(MAKEFILE);
+
+
+# TEST 0
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "src${pathsep}a.b.z.foo.c hacks.c\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST 1
+
+&run_make_with_options($makefile, "two", &get_logfile);
+$answer = "\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/functions/andor b/tests/scripts/functions/andor
new file mode 100644
index 0000000..62e0c2e
--- /dev/null
+++ b/tests/scripts/functions/andor
@@ -0,0 +1,50 @@
+# -*-perl-*-
+$description = "Test the and & or functions.\n";
+
+$details = "Try various uses of and & or to ensure they all give the correct
+results.\n";
+
+# TEST #0
+# For $(and ...), it will either be empty or the last value
+run_make_test('
+NEQ = $(subst $1,,$2)
+f =
+t = true
+
+all:
+ @echo 1 $(and ,$t)
+ @echo 2 $(and $t)
+ @echo 3 $(and $t,)
+ @echo 4 $(and z,true,$f,false)
+ @echo 5 $(and $t,$f,$(info bad short-circuit))
+ @echo 6 $(and $(call NEQ,a,b),true)
+ @echo 7 $(and $(call NEQ,a,a),true)
+ @echo 8 $(and z,true,fal,se) hi
+ @echo 9 $(and ,true,fal,se)there
+ @echo 10 $(and $(e) ,$t)',
+ '',
+ "1\n2 true\n3\n4\n5\n6 true\n7\n8 se hi\n9 there\n10\n");
+
+# TEST #1
+# For $(or ...), it will either be empty or the first true value
+run_make_test('
+NEQ = $(subst $1,,$2)
+f =
+t = true
+
+all:
+ @echo 1 $(or , )
+ @echo 2 $(or $t)
+ @echo 3 $(or ,$t)
+ @echo 4 $(or z,true,$f,false)
+ @echo 5 $(or $t,$(info bad short-circuit))
+ @echo 6 $(or $(info short-circuit),$t)
+ @echo 7 $(or $(call NEQ,a,b),true)
+ @echo 8 $(or $(call NEQ,a,a),true)
+ @echo 9 $(or z,true,fal,se) hi
+ @echo 10 $(or ,true,fal,se)there
+ @echo 11 $(or $(e) ,$f)',
+ '',
+ "short-circuit\n1\n2 true\n3 true\n4 z\n5 true\n6 true\n7 b\n8 true\n9 z hi\n10 truethere\n11\n");
+
+1;
diff --git a/tests/scripts/functions/basename b/tests/scripts/functions/basename
new file mode 100644
index 0000000..08f2ea5
--- /dev/null
+++ b/tests/scripts/functions/basename
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the suffix "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(basename src${pathsep}a.b.z.foo.c src${pathsep}hacks src.bar${pathsep}a.b.z.foo.c src.bar${pathsep}hacks hacks) \n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep}a.b.z.foo src${pathsep}hacks src.bar${pathsep}a.b.z.foo src.bar${pathsep}hacks hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/call b/tests/scripts/functions/call
new file mode 100644
index 0000000..9db9da7
--- /dev/null
+++ b/tests/scripts/functions/call
@@ -0,0 +1,110 @@
+# -*-perl-*-
+$description = "Test the call function.\n";
+
+$details = "Try various uses of call and ensure they all give the correct
+results.\n";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+# Simple, just reverse two things
+#
+reverse = $2 $1
+
+# A complex 'map' function, using recursive 'call'.
+#
+map = $(foreach a,$2,$(call $1,$a))
+
+# Test using a builtin; this is silly as it's simpler to do without call
+#
+my-notdir = $(call notdir,$(1))
+
+# Test using non-expanded builtins
+#
+my-foreach = $(foreach $(1),$(2),$(3))
+my-if = $(if $(1),$(2),$(3))
+
+# Test recursive invocations of call with different arguments
+#
+one = $(1) $(2) $(3)
+two = $(call one,$(1),foo,$(2))
+
+# Test recursion on the user-defined function. As a special case make
+# won't error due to this.
+# Implement transitive closure using $(call ...)
+#
+DEP_foo = bar baz quux
+DEP_baz = quux blarp
+rest = $(wordlist 2,$(words ${1}),${1})
+tclose = $(if $1,$(firstword $1)\
+ $(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1))))
+
+all: ; @echo '$(call reverse,bar,foo)'; \
+ echo '$(call map,origin,MAKE reverse map)'; \
+ echo '$(call my-notdir,a/b c/d e/f)'; \
+ echo '$(call my-foreach)'; \
+ echo '$(call my-foreach,a,,,)'; \
+ echo '$(call my-if,a,b,c)'; \
+ echo '$(call two,bar,baz)'; \
+ echo '$(call tclose,foo)'
+
+
+
+EOMAKE
+
+# These won't work until/unless PR/1527 is resolved.
+# echo '$(call my-foreach,a,x y z,$(a)$(a))'; \
+# echo '$(call my-if,,$(warning don't print this),ok)'
+#
+# $answer = "xx yy zz\nok\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n";
+&compare_output($answer, &get_logfile(1));
+
+
+# TEST eclipsing of arguments when invoking sub-calls
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<'EOF';
+
+all = $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+level1 = $(call all,$1,$2,$3,$4,$5)
+level2 = $(call level1,$1,$2,$3)
+level3 = $(call level2,$1,$2,$3,$4,$5)
+
+all:
+ @echo $(call all,1,2,3,4,5,6,7,8,9,10,11)
+ @echo $(call level1,1,2,3,4,5,6,7,8)
+ @echo $(call level2,1,2,3,4,5,6,7,8)
+ @echo $(call level3,1,2,3,4,5,6,7,8)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "", &get_logfile);
+$answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n";
+&compare_output($answer,&get_logfile(1));
+
+# Ensure that variables are defined in global scope even in a $(call ...)
+
+delete $ENV{X123};
+
+run_make_test('
+tst = $(eval export X123)
+$(call tst)
+all: ; @echo "$${X123-not set}"
+',
+ '', "\n");
+
+1;
diff --git a/tests/scripts/functions/dir b/tests/scripts/functions/dir
new file mode 100644
index 0000000..f48fb8c
--- /dev/null
+++ b/tests/scripts/functions/dir
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the dir "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(dir src${pathsep}foo.c hacks) \n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "src${pathsep} .${pathsep}\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/error b/tests/scripts/functions/error
new file mode 100644
index 0000000..0d61177
--- /dev/null
+++ b/tests/scripts/functions/error
@@ -0,0 +1,73 @@
+# -*-Perl-*-
+
+$description = "\
+The following test creates a makefile to test the error function.";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE 'err = $(error Error found!)
+
+ifdef ERROR1
+$(error error is $(ERROR1))
+endif
+
+ifdef ERROR2
+$(error error is $(ERROR2))
+endif
+
+ifdef ERROR3
+all: some; @echo $(error error is $(ERROR3))
+endif
+
+ifdef ERROR4
+all: some; @echo error is $(ERROR4)
+ @echo $(error error is $(ERROR4))
+endif
+
+some: ; @echo Some stuff
+
+testvar: ; @: $(err)
+';
+
+close(MAKEFILE);
+
+# Test #1
+
+&run_make_with_options($makefile, "ERROR1=yes", &get_logfile, 512);
+$answer = "$makefile:4: *** error is yes. Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #2
+
+&run_make_with_options($makefile, "ERROR2=no", &get_logfile, 512);
+$answer = "$makefile:8: *** error is no. Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #3
+
+&run_make_with_options($makefile, "ERROR3=maybe", &get_logfile, 512);
+$answer = "Some stuff\n$makefile:12: *** error is maybe. Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #4
+
+&run_make_with_options($makefile, "ERROR4=definitely", &get_logfile, 512);
+$answer = "Some stuff\n$makefile:16: *** error is definitely. Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #5
+
+&run_make_with_options($makefile, "testvar", &get_logfile, 512);
+$answer = "$makefile:22: *** Error found!. Stop.\n";
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/eval b/tests/scripts/functions/eval
new file mode 100644
index 0000000..90513bd
--- /dev/null
+++ b/tests/scripts/functions/eval
@@ -0,0 +1,169 @@
+# -*-perl-*-
+
+$description = "Test the eval function.";
+
+$details = "This is a test of the eval function in GNU make.
+This function will evaluate inline makefile syntax and incorporate the
+results into its internal database.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+define Y
+ all:: ; @echo $AA
+ A = B
+endef
+
+X = $(eval $(value Y))
+
+$(eval $(shell echo A = A))
+$(eval $(Y))
+$(eval A = C)
+$(eval $(X))
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "AA\nBA\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test to make sure defining variables when we have extra scope pushed works
+# as expected.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<'EOF';
+VARS = A B
+
+VARSET = $(1) = $(2)
+
+$(foreach v,$(VARS),$(eval $(call VARSET,$v,$v)))
+
+all: ; @echo A = $(A) B = $(B)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "A = A B = B\n";
+
+&compare_output($answer,&get_logfile(1));
+
+# Test to make sure eval'ing inside conditionals works properly
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+
+print MAKEFILE <<'EOF';
+FOO = foo
+
+all:: ; @echo it
+
+define Y
+ all:: ; @echo worked
+endef
+
+ifdef BAR
+$(eval $(Y))
+endif
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "it\n";
+&compare_output($answer,&get_logfile(1));
+
+&run_make_with_options($makefile3, "BAR=1", &get_logfile);
+$answer = "it\nworked\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST very recursive invocation of eval
+
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile3");
+
+print MAKEFILE <<'EOF';
+..9 := 0 1 2 3 4 5 6 7 8 9
+rev=$(eval res:=)$(foreach word,$1,$(eval res:=${word} ${res}))${res}
+a:=$(call rev,${..9})
+all: ; @echo '[$(a)]'
+
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile3, "", &get_logfile);
+$answer = "[ 9 8 7 6 5 4 3 2 1 0 ]\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST eval with no filename context.
+# The trick here is that because EVAR is taken from the environment, it must
+# be evaluated before every command is invoked. Make sure that works, when
+# we have no file context for reading_file (bug # 6195)
+
+$makefile4 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile4");
+
+print MAKEFILE <<'EOF';
+EVAR = $(eval FOBAR = 1)
+all: ; @echo "OK"
+
+EOF
+
+close(MAKEFILE);
+
+$extraENV{EVAR} = '1';
+&run_make_with_options($makefile4, "", &get_logfile);
+$answer = "OK\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# Clean out previous information to allow new run_make_test() interface.
+# If we ever convert all the above to run_make_test() we can remove this line.
+$makefile = undef;
+
+# Test handling of backslashes in strings to be evaled.
+
+run_make_test('
+define FOO
+all: ; @echo hello \
+world
+endef
+$(eval $(FOO))
+', '', 'hello world');
+
+run_make_test('
+define FOO
+all: ; @echo '."'".'he\llo'."'".'
+ @echo world
+endef
+$(eval $(FOO))
+', '', 'he\llo
+world');
+
+
+# We don't allow new target/prerequisite relationships to be defined within a
+# command script, because these are evaluated after snap_deps() and that
+# causes lots of problems (like core dumps!)
+# See Savannah bug # 12124.
+
+run_make_test('deps: ; $(eval deps: foo)', '',
+ '#MAKEFILE#:1: *** prerequisites cannot be defined in recipes. Stop.',
+ 512);
+
+1;
diff --git a/tests/scripts/functions/file b/tests/scripts/functions/file
new file mode 100644
index 0000000..55eb58a
--- /dev/null
+++ b/tests/scripts/functions/file
@@ -0,0 +1,118 @@
+# -*-perl-*-
+
+$description = 'Test the $(file ...) function.';
+
+# Test > and >>
+run_make_test(q!
+define A
+a
+b
+endef
+B = c d
+$(file >file.out,$(A))
+$(foreach L,$(B),$(file >> file.out,$L))
+x:;@echo hi; cat file.out
+!,
+ '', "hi\na\nb\nc\nd");
+
+unlink('file.out');
+
+# Test >> to a non-existent file
+run_make_test(q!
+define A
+a
+b
+endef
+$(file >> file.out,$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Test > with no content
+run_make_test(q!
+$(file >4touch)
+.PHONY:x
+x:;@cat 4touch
+!,
+ '', '');
+
+# Test >> with no content
+run_make_test(q!
+$(file >>4touch)
+.PHONY:x
+x:;@cat 4touch
+!,
+ '', '');
+unlink('4touch');
+
+# Test > to a read-only file
+touch('file.out');
+chmod(0444, 'file.out');
+
+# Find the error that will be printed
+# This seems complicated, but we need the message from the C locale
+my $loc = undef;
+if ($has_POSIX) {
+ $loc = POSIX::setlocale(POSIX::LC_MESSAGES);
+ POSIX::setlocale(POSIX::LC_MESSAGES, 'C');
+}
+my $e;
+open(my $F, '>', 'file.out') and die "Opened read-only file!\n";
+$e = "$!";
+$loc and POSIX::setlocale(POSIX::LC_MESSAGES, $loc);
+
+run_make_test(q!
+define A
+a
+b
+endef
+$(file > file.out,$(A))
+x:;@cat file.out
+!,
+ '', "#MAKEFILE#:6: *** open: file.out: $e. Stop.",
+ 512);
+
+unlink('file.out');
+
+# Use variables for operator and filename
+run_make_test(q!
+define A
+a
+b
+endef
+OP = >
+FN = file.out
+$(file $(OP) $(FN),$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Don't add newlines if one already exists
+run_make_test(q!
+define A
+a
+b
+
+endef
+$(file >file.out,$(A))
+x:;@cat file.out
+!,
+ '', "a\nb");
+
+unlink('file.out');
+
+# Empty text
+run_make_test(q!
+$(file >file.out,)
+$(file >>file.out,)
+x:;@cat file.out
+!,
+ '', "\n\n");
+
+unlink('file.out');
+
+1;
diff --git a/tests/scripts/functions/filter-out b/tests/scripts/functions/filter-out
new file mode 100644
index 0000000..1fe4819
--- /dev/null
+++ b/tests/scripts/functions/filter-out
@@ -0,0 +1,42 @@
+# -*-perl-*-
+
+$description = "Test the filter and filter-out functions.";
+
+$details = "The makefile created in this test has two variables. The
+filter-out function is first used to discard names ending in
+.o with a single simple pattern. The second filter-out function
+augments the simple pattern with three literal names, which are
+also added to the text argument. This tests an internal hash table
+which is only used if there are multiple literals present in both
+the pattern and text arguments. The result of both filter-out
+functions is the same single .elc name.\n";
+
+# Basic test -- filter
+run_make_test(q!
+files1 := $(filter %.o, foo.elc bar.o lose.o)
+files2 := $(filter %.o foo.i, foo.i bar.i lose.i foo.elc bar.o lose.o)
+all: ; @echo '$(files1) $(files2)'
+!,
+ '', "bar.o lose.o foo.i bar.o lose.o\n");
+
+# Basic test -- filter-out
+run_make_test(q!
+files1 := $(filter-out %.o, foo.elc bar.o lose.o)
+files2 := $(filter-out foo.i bar.i lose.i %.o, foo.i bar.i lose.i foo.elc bar.o lose.o)
+all: ; @echo '$(files1) $(files2)'
+!,
+ '', "foo.elc foo.elc\n");
+
+# Escaped patterns
+run_make_test(q!all:;@echo '$(filter foo\%bar,foo%bar fooXbar)'!,
+ '', "foo%bar\n");
+
+run_make_test(q!all:;@echo '$(filter foo\%\%\\\\\%\%bar,foo%%\\%%bar fooX\\Ybar)'!,
+ '', "foo%%\\%%bar\n");
+
+run_make_test(q!
+X = $(filter foo\\\\\%bar,foo\%bar foo\Xbar)
+all:;@echo '$(X)'!,
+ '', "foo\\%bar\n");
+
+1;
diff --git a/tests/scripts/functions/findstring b/tests/scripts/functions/findstring
new file mode 100644
index 0000000..48abede
--- /dev/null
+++ b/tests/scripts/functions/findstring
@@ -0,0 +1,47 @@
+$description = "The following test creates a makefile to test the findstring "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(findstring port, reporter)\n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,
+ "",
+ &get_logfile,
+ 0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "port\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/flavor b/tests/scripts/functions/flavor
new file mode 100644
index 0000000..80d6be7
--- /dev/null
+++ b/tests/scripts/functions/flavor
@@ -0,0 +1,44 @@
+# -*-perl-*-
+$description = "Test the flavor function.";
+
+$details = "";
+
+
+# Test #1: Test general logic.
+#
+run_make_test('
+s := s
+r = r
+
+$(info u $(flavor u))
+$(info s $(flavor s))
+$(info r $(flavor r))
+
+ra += ra
+rc ?= rc
+
+$(info ra $(flavor ra))
+$(info rc $(flavor rc))
+
+s += s
+r += r
+
+$(info s $(flavor s))
+$(info r $(flavor r))
+
+
+.PHONY: all
+all:;@:
+',
+'',
+'u undefined
+s simple
+r recursive
+ra recursive
+rc recursive
+s simple
+r recursive');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/functions/foreach b/tests/scripts/functions/foreach
new file mode 100644
index 0000000..4d1a11d
--- /dev/null
+++ b/tests/scripts/functions/foreach
@@ -0,0 +1,77 @@
+# -*-perl-*-
+# $Id$
+
+$description = "Test the foreach function.";
+
+$details = "This is a test of the foreach function in gnu make.
+This function starts with a space separated list of
+names and a variable. Each name in the list is subsituted
+into the variable and the given text evaluated. The general
+form of the command is $(foreach var,$list,$text). Several
+types of foreach loops are tested\n";
+
+
+# TEST 0
+
+# Set an environment variable that we can test in the makefile.
+$extraENV{FOOFOO} = 'foo foo';
+
+run_make_test("space = ' '".'
+null :=
+auto_var = udef space CC null FOOFOO MAKE foo CFLAGS WHITE @ <
+foo = bletch null @ garf
+av = $(foreach var, $(auto_var), $(origin $(var)) )
+override WHITE := BLACK
+for_var = $(addsuffix .c,foo $(null) $(foo) $(space) $(av) )
+fe = $(foreach var2, $(for_var),$(subst .c,.o, $(var2) ) )
+all: auto for2
+auto : ; @echo $(av)
+for2: ; @echo $(fe)',
+ '-e WHITE=WHITE CFLAGS=',
+ "undefined file default file environment default file command line override automatic automatic
+foo.o bletch.o null.o @.o garf.o .o .o undefined.o file.o default.o file.o environment.o default.o file.o command.o line.o override.o automatic.o automatic.o");
+
+delete $extraENV{FOOFOO};
+
+# TEST 1: Test that foreach variables take precedence over global
+# variables in a global scope (like inside an eval). Tests bug #11913
+
+run_make_test('
+.PHONY: all target
+all: target
+
+x := BAD
+
+define mktarget
+target: x := $(x)
+target: ; @echo "$(x)"
+endef
+
+x := GLOBAL
+
+$(foreach x,FOREACH,$(eval $(value mktarget)))',
+ '',
+ 'FOREACH');
+
+
+# TEST 2: Check some error conditions.
+
+run_make_test('
+x = $(foreach )
+y = $x
+
+all: ; @echo $y',
+ '',
+ "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.",
+ 512);
+
+run_make_test('
+x = $(foreach )
+y := $x
+
+all: ; @echo $y',
+ '',
+ "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.",
+ 512);
+
+1;
diff --git a/tests/scripts/functions/guile b/tests/scripts/functions/guile
new file mode 100644
index 0000000..c63bec9
--- /dev/null
+++ b/tests/scripts/functions/guile
@@ -0,0 +1,99 @@
+# -*-perl-*-
+
+$description = 'Test the $(guile ...) function.';
+
+$details = 'This only works on systems that support it.';
+
+# If this instance of make doesn't support GNU Guile, skip it
+# This detects if guile is loaded using the "load" directive
+# $makefile = get_tmpfile();
+# open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n";
+# print MAKEFILE q!
+# -load guile
+# all: ; @echo $(filter guile,$(.LOADED))
+# !;
+# close(MAKEFILE) || die "Failed to write $makefile: $!\n";
+# $cmd = subst_make_string("#MAKEPATH# -f $makefile");
+# $log = get_logfile(0);
+# $code = run_command_with_output($log, $cmd);
+# read_file_into_string ($log) eq "guile\n" and $FEATURES{guile} = 1;
+
+# If we don't have Guile support, never mind.
+exists $FEATURES{guile} or return -1;
+
+# Verify simple data type conversions
+# Currently we don't support vectors:
+# echo '$(guile (vector 1 2 3))'; \
+run_make_test(q!
+x:;@echo '$(guile #f)'; \
+ echo '$(guile #t)'; \
+ echo '$(guile #\c)'; \
+ echo '$(guile 1234)'; \
+ echo '$(guile 'foo)'; \
+ echo '$(guile "bar")'; \
+ echo '$(guile (cons 'a 'b))'; \
+ echo '$(guile '(a b (c . d) 1 (2) 3))'
+!,
+ '', "\n#t\nc\n1234\nfoo\nbar\na b\na b c d 1 2 3");
+
+# Verify the gmk-expand function
+run_make_test(q!
+VAR = $(guile (gmk-expand "$(shell echo hi)"))
+x:;@echo '$(VAR)'
+!,
+ '', "hi");
+
+# Verify the gmk-eval function
+# Prove that the string is expanded only once (by eval)
+run_make_test(q!
+TEST = bye
+EVAL = VAR = $(TEST) $(shell echo there)
+$(guile (gmk-eval "$(value EVAL)"))
+TEST = hi
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Verify the gmk-eval function with a list
+run_make_test(q!
+$(guile (gmk-eval '(VAR = 1 (2) () 3)))
+x:;@echo '$(VAR)'
+!,
+ '', "1 2 3");
+
+# Verify the gmk-var function
+run_make_test(q!
+VALUE = hi $(shell echo there)
+VAR = $(guile (gmk-var "VALUE"))
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Verify the gmk-var function with a symbol
+run_make_test(q!
+VALUE = hi $(shell echo there)
+VAR = $(guile (gmk-var 'VALUE))
+x:;@echo '$(VAR)'
+!,
+ '', "hi there");
+
+# Write a Guile program using define and run it
+run_make_test(q!
+# Define the "fib" function in Guile
+define fib
+;; A procedure for counting the n:th Fibonacci number
+;; See SICP, p. 37
+(define (fib n)
+ (cond ((= n 0) 0)
+ ((= n 1) 1)
+ (else (+ (fib (- n 1))
+ (fib (- n 2))))))
+endef
+$(guile $(fib))
+
+# Now run it
+x:;@echo $(guile (fib $(FIB)))
+!,
+ 'FIB=10', "55");
+
+1;
diff --git a/tests/scripts/functions/if b/tests/scripts/functions/if
new file mode 100644
index 0000000..8604e4f
--- /dev/null
+++ b/tests/scripts/functions/if
@@ -0,0 +1,33 @@
+# -*-perl-*-
+$description = "Test the if function.\n";
+
+$details = "Try various uses of if and ensure they all give the correct
+results.\n";
+
+open(MAKEFILE, "> $makefile");
+
+print MAKEFILE <<EOMAKE;
+NEQ = \$(subst \$1,,\$2)
+e =
+
+all:
+\t\@echo 1 \$(if ,true,false)
+\t\@echo 2 \$(if ,true,)
+\t\@echo 3 \$(if ,true)
+\t\@echo 4 \$(if z,true,false)
+\t\@echo 5 \$(if z,true,\$(shell echo hi))
+\t\@echo 6 \$(if ,\$(shell echo hi),false)
+\t\@echo 7 \$(if \$(call NEQ,a,b),true,false)
+\t\@echo 8 \$(if \$(call NEQ,a,a),true,false)
+\t\@echo 9 \$(if z,true,fal,se) hi
+\t\@echo 10 \$(if ,true,fal,se)there
+\t\@echo 11 \$(if \$(e) ,true,false)
+EOMAKE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "1 false\n2\n3\n4 true\n5 true\n6 false\n7 true\n8 false\n9 true hi\n10 fal,sethere\n11 false\n";
+&compare_output($answer, &get_logfile(1));
+
+1;
diff --git a/tests/scripts/functions/join b/tests/scripts/functions/join
new file mode 100644
index 0000000..302c307
--- /dev/null
+++ b/tests/scripts/functions/join
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the join "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(join a b c,foo hacks .pl1) \n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "afoo bhacks c.pl1\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/notdir b/tests/scripts/functions/notdir
new file mode 100644
index 0000000..4ed8f9c
--- /dev/null
+++ b/tests/scripts/functions/notdir
@@ -0,0 +1,44 @@
+$description = "The following test creates a makefile to test the notdir "
+ ."function.";
+
+$details = "";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := \$(notdir ${pathsep}src${pathsep}foo.c hacks) \n"
+ ."all: \n"
+ ."\t\@echo \$(string) \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "foo.c hacks\n";
+
+# COMPARE RESULTS
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/origin b/tests/scripts/functions/origin
new file mode 100644
index 0000000..f7b7eb8
--- /dev/null
+++ b/tests/scripts/functions/origin
@@ -0,0 +1,51 @@
+# -*-perl-*-
+
+$description = "Test the origin function.";
+
+$details = "This is a test of the origin function in gnu make.
+This function will report on where a variable was
+defined per the following list:
+
+'undefined' never defined
+'default' default definition
+'environment' environment var without -e
+'environment override' environment var with -e
+'file' defined in makefile
+'command line' defined on the command line
+'override' defined by override in makefile
+'automatic' Automatic variable\n";
+
+# Set an environment variable
+$extraENV{MAKETEST} = 1;
+
+run_make_test('
+foo := bletch garf
+auto_var = undefined CC MAKETEST MAKE foo CFLAGS WHITE @
+av = $(foreach var, $(auto_var), $(origin $(var)) )
+override WHITE := BLACK
+all: auto
+ @echo $(origin undefined)
+ @echo $(origin CC)
+ @echo $(origin MAKETEST)
+ @echo $(origin MAKE)
+ @echo $(origin foo)
+ @echo $(origin CFLAGS)
+ @echo $(origin WHITE)
+ @echo $(origin @)
+auto :
+ @echo $(av)',
+ '-e WHITE=WHITE CFLAGS=',
+ 'undefined default environment default file command line override automatic
+undefined
+default
+environment
+default
+file
+command line
+override
+automatic');
+
+# Reset an environment variable
+delete $extraENV{MAKETEST};
+
+1;
diff --git a/tests/scripts/functions/realpath b/tests/scripts/functions/realpath
new file mode 100644
index 0000000..9b503b4
--- /dev/null
+++ b/tests/scripts/functions/realpath
@@ -0,0 +1,82 @@
+# -*-perl-*-
+$description = "Test the realpath functions.";
+
+$details = "";
+
+run_make_test('
+ifneq ($(realpath .),$(CURDIR))
+ $(error )
+endif
+
+ifneq ($(realpath ./),$(CURDIR))
+ $(error )
+endif
+
+ifneq ($(realpath .///),$(CURDIR))
+ $(error )
+endif
+
+ifneq ($(realpath /),/)
+ $(error )
+endif
+
+ifneq ($(realpath /.),/)
+ $(error )
+endif
+
+ifneq ($(realpath /./),/)
+ $(error )
+endif
+
+ifneq ($(realpath /.///),/)
+ $(error )
+endif
+
+ifneq ($(realpath /..),/)
+ $(error )
+endif
+
+ifneq ($(realpath /../),/)
+ $(error )
+endif
+
+ifneq ($(realpath /..///),/)
+ $(error )
+endif
+
+ifneq ($(realpath . /..),$(CURDIR) /)
+ $(error )
+endif
+
+.PHONY: all
+all: ; @:
+',
+ '',
+ '');
+
+# On Windows platforms, "//" means something special. So, don't do these
+# tests there.
+
+if ($port_type ne 'W32') {
+ run_make_test('
+ifneq ($(realpath ///),/)
+ $(error )
+endif
+
+ifneq ($(realpath ///.),/)
+ $(error )
+endif
+
+ifneq ($(realpath ///..),/)
+ $(error )
+endif
+
+.PHONY: all
+all: ; @:',
+ '',
+ '');
+}
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/functions/shell b/tests/scripts/functions/shell
new file mode 100644
index 0000000..723cd0e
--- /dev/null
+++ b/tests/scripts/functions/shell
@@ -0,0 +1,32 @@
+# -*-perl-*-
+
+$description = 'Test the $(shell ...) function.';
+
+$details = '';
+
+
+# Test shells inside rules.
+run_make_test('.PHONY: all
+all: ; @echo $(shell echo hi)
+','','hi');
+
+
+# Test unescaped comment characters in shells. Savannah bug #20513
+if ($all_tests) {
+ run_make_test(q!
+FOO := $(shell echo '#')
+foo: ; echo '$(FOO)'
+!,
+ '', "#\n");
+}
+
+# Test shells inside exported environment variables.
+# This is the test that fails if we try to put make exported variables into
+# the environment for a $(shell ...) call.
+run_make_test('
+export HI = $(shell echo hi)
+.PHONY: all
+all: ; @echo $$HI
+','','hi');
+
+1;
diff --git a/tests/scripts/functions/sort b/tests/scripts/functions/sort
new file mode 100644
index 0000000..b558910
--- /dev/null
+++ b/tests/scripts/functions/sort
@@ -0,0 +1,47 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to verify
+the ability of make to sort lists of object. Sort
+will also remove any duplicate entries. This will also
+be tested.";
+
+$details = "The make file is built with a list of object in a random order
+and includes some duplicates. Make should sort all of the elements
+remove all duplicates\n";
+
+run_make_test('
+foo := moon_light days
+foo1:= jazz
+bar := captured
+bar2 = boy end, has rise A midnight
+bar3:= $(foo)
+s1 := _by
+s2 := _and_a
+t1 := $(addsuffix $(s1), $(bar) )
+t2 := $(addsuffix $(s2), $(foo1) )
+t3 := $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2)
+t4 := $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3)
+t5 := $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4)
+t6 := $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5)
+t7 := $(t6) $(t6) $(t6)
+p1 := $(addprefix $(foo1), $(s2) )
+blank:=
+all:
+ @echo $(sort $(bar2) $(foo) $(addsuffix $(s1), $(bar) ) $(t2) $(bar2) $(bar3))
+ @echo $(sort $(blank) $(foo) $(bar2) $(t1) $(p1) )
+ @echo $(sort $(foo) $(bar2) $(t1) $(t4) $(t5) $(t7) $(t6) )
+',
+ '', 'A boy captured_by days end, has jazz_and_a midnight moon_light rise
+A boy captured_by days end, has jazz_and_a midnight moon_light rise
+A boy captured_by days end, has jazz_and_a midnight moon_light rise
+');
+
+
+# Test with non-space/tab whitespace. Note that you can't see the
+# original bug except using valgrind.
+
+run_make_test("FOO = a b\tc\rd\fe \f \f \f \f \ff
+all: ; \@echo \$(words \$(sort \$(FOO)))\n",
+ '', "5\n");
+
+1;
diff --git a/tests/scripts/functions/strip b/tests/scripts/functions/strip
new file mode 100644
index 0000000..8222433
--- /dev/null
+++ b/tests/scripts/functions/strip
@@ -0,0 +1,57 @@
+# -*-perl-*-
+$description = "The following test creates a makefile to verify
+the ability of make to strip white space from lists of object.\n";
+
+
+$details = "The make file is built with a list of objects that contain white space
+These are then run through the strip command to remove it. This is then
+verified by echoing the result.\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOMAKE';
+TEST1 := "Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING..."
+E :=
+TEST2 := $E try this and this $E
+
+define TEST3
+
+and these test out
+
+
+some
+blank lines
+
+
+
+endef
+
+.PHONY: all
+all:
+ @echo '$(strip $(TEST1) )'
+ @echo '$(strip $(TEST2) )'
+ @echo '$(strip $(TEST3) )'
+
+space: ; @echo '$(strip ) $(strip )'
+
+EOMAKE
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile);
+$answer = "\"Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING...\"
+try this and this
+and these test out some blank lines
+";
+&compare_output($answer,&get_logfile(1));
+
+
+&run_make_with_options($makefile,"space",&get_logfile);
+$answer = " \n";
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/functions/substitution b/tests/scripts/functions/substitution
new file mode 100644
index 0000000..0d2f6a2
--- /dev/null
+++ b/tests/scripts/functions/substitution
@@ -0,0 +1,38 @@
+# -*-perl-*-
+
+$description = "Test the subst and patsubst functions";
+
+$details = "";
+
+# Generic patsubst test: test both the function and variable form.
+
+run_make_test('
+foo := a.o b.o c.o
+bar := $(foo:.o=.c)
+bar2:= $(foo:%.o=%.c)
+bar3:= $(patsubst %.c,%.o,x.c.c bar.c)
+all:;@echo $(bar); echo $(bar2); echo $(bar3)',
+'',
+'a.c b.c c.c
+a.c b.c c.c
+x.c.o bar.o');
+
+# Patsubst without '%'--shouldn't match because the whole word has to match
+# in patsubst. Based on a bug report by Markus Mauhart <qwe123@chello.at>
+
+run_make_test('all:;@echo $(patsubst Foo,Repl,FooFoo)', '', 'FooFoo');
+
+# Variable subst where a pattern matches multiple times in a single word.
+# Based on a bug report by Markus Mauhart <qwe123@chello.at>
+
+run_make_test('
+A := fooBARfooBARfoo
+all:;@echo $(A:fooBARfoo=REPL)', '', 'fooBARREPL');
+
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/suffix b/tests/scripts/functions/suffix
new file mode 100644
index 0000000..0c4f919
--- /dev/null
+++ b/tests/scripts/functions/suffix
@@ -0,0 +1,57 @@
+$description = "The following test creates a makefile to test the suffix\n"
+ ."function. \n";
+
+$details = "The suffix function will return the string following the last _._\n"
+ ."the list provided. It will provide all of the unique suffixes found\n"
+ ."in the list. The long strings are sorted to remove duplicates.\n";
+
+# IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET
+# THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF
+# HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END.
+# EXAMPLE: $makefile2 = &get_tmpfile;
+
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "string := word.pl general_test2.pl1 FORCE.pl word.pl3 generic_test.perl /tmp.c/bar foo.baz/bar.c MAKEFILES_variable.c\n"
+ ."string2 := \$(string) \$(string) \$(string) \$(string) \$(string) \$(string) \$(string)\n"
+ ."string3 := \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2)\n"
+ ."string4 := \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3)\n"
+ ."all: \n"
+ ."\t\@echo \$(suffix \$(string)) \n"
+ ."\t\@echo \$(sort \$(suffix \$(string4))) \n"
+ ."\t\@echo \$(suffix \$(string) a.out) \n"
+ ."\t\@echo \$(sort \$(suffix \$(string3))) \n";
+
+
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+
+# COMPARE RESULTS
+$answer = ".pl .pl1 .pl .pl3 .perl .c .c\n"
+ .".c .perl .pl .pl1 .pl3\n"
+ .".pl .pl1 .pl .pl3 .perl .c .c .out\n"
+ .".c .perl .pl .pl1 .pl3\n";
+
+# In this call to compare output, you should use the call &get_logfile(1)
+# to send the name of the last logfile created. You may also use
+# the special call &get_logfile(1) which returns the same as &get_logfile(1).
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/value b/tests/scripts/functions/value
new file mode 100644
index 0000000..8e1a6f0
--- /dev/null
+++ b/tests/scripts/functions/value
@@ -0,0 +1,30 @@
+# -*-perl-*-
+
+$description = "Test the value function.";
+
+$details = "This is a test of the value function in GNU make.
+This function will evaluate to the value of the named variable with no
+further expansion performed on it.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+export FOO = foo
+
+recurse = FOO = $FOO
+static := FOO = $(value FOO)
+
+all: ; @echo $(recurse) $(value recurse) $(static) $(value static)
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "FOO = OO FOO = foo FOO = foo FOO = foo\n";
+
+
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/functions/warning b/tests/scripts/functions/warning
new file mode 100644
index 0000000..cd452d4
--- /dev/null
+++ b/tests/scripts/functions/warning
@@ -0,0 +1,65 @@
+# -*-Perl-*-
+
+$description = "\
+The following test creates a makefile to test the warning function.";
+
+$details = "";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+ifdef WARNING1
+$(warning warning is $(WARNING1))
+endif
+
+ifdef WARNING2
+$(warning warning is $(WARNING2))
+endif
+
+ifdef WARNING3
+all: some; @echo hi $(warning warning is $(WARNING3))
+endif
+
+ifdef WARNING4
+all: some; @echo hi
+ @echo there $(warning warning is $(WARNING4))
+endif
+
+some: ; @echo Some stuff
+
+EOF
+
+close(MAKEFILE);
+
+# Test #1
+
+&run_make_with_options($makefile, "WARNING1=yes", &get_logfile, 0);
+$answer = "$makefile:2: warning is yes\nSome stuff\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #2
+
+&run_make_with_options($makefile, "WARNING2=no", &get_logfile, 0);
+$answer = "$makefile:6: warning is no\nSome stuff\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #3
+
+&run_make_with_options($makefile, "WARNING3=maybe", &get_logfile, 0);
+$answer = "Some stuff\n$makefile:10: warning is maybe\nhi\n";
+&compare_output($answer,&get_logfile(1));
+
+# Test #4
+
+&run_make_with_options($makefile, "WARNING4=definitely", &get_logfile, 0);
+$answer = "Some stuff\n$makefile:14: warning is definitely\nhi\nthere\n";
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/functions/wildcard b/tests/scripts/functions/wildcard
new file mode 100644
index 0000000..bcd84ad
--- /dev/null
+++ b/tests/scripts/functions/wildcard
@@ -0,0 +1,103 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test wildcard
+expansions and the ability to put a command on the same
+line as the target name separated by a semi-colon.";
+
+$details = "\
+This test creates 4 files by the names of 1.example,
+two.example and 3.example. We execute three tests. The first
+executes the print1 target which tests the '*' wildcard by
+echoing all filenames by the name of '*.example'. The second
+test echo's all files which match '?.example' and
+[a-z0-9].example. Lastly we clean up all of the files using
+the '*' wildcard as in the first test";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOM;
+.PHONY: print1 print2 clean
+print1: ;\@echo \$(sort \$(wildcard example.*))
+print2:
+\t\@echo \$(sort \$(wildcard example.?))
+\t\@echo \$(sort \$(wildcard example.[a-z0-9]))
+\t\@echo \$(sort \$(wildcard example.[!A-Za-z_\\!]))
+clean:
+\t$delete_command \$(sort \$(wildcard example.*))
+EOM
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch("example.1");
+&touch("example.two");
+&touch("example.3");
+&touch("example.for");
+&touch("example._");
+
+# TEST #1
+# -------
+
+$answer = "example.1 example.3 example._ example.for example.two\n";
+
+&run_make_with_options($makefile,"print1",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+
+$answer = "example.1 example.3 example._\n"
+ ."example.1 example.3\n"
+ ."example.1 example.3\n";
+
+&run_make_with_options($makefile,"print2",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3
+# -------
+
+$answer = "$delete_command example.1 example.3 example._ example.for example.two";
+if ($vos)
+{
+ $answer .= " \n";
+}
+else
+{
+ $answer .= "\n";
+}
+
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+if ((-f "example.1")||(-f "example.two")||(-f "example.3")||(-f "example.for")) {
+ $test_passed = 0;
+}
+
+&compare_output($answer,&get_logfile(1));
+
+# TEST #4: Verify that failed wildcards don't return the pattern
+
+run_make_test(q!
+all: ; @echo $(wildcard xz--y*.7)
+!,
+ '', "\n");
+
+# TEST #5: wildcard used to verify file existence
+
+touch('xxx.yyy');
+
+run_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!,
+ '', "file=xxx.yyy\n");
+
+unlink('xxx.yyy');
+
+run_make_test(q!exists: ; @echo file=$(wildcard xxx.yyy)!,
+ '', "file=\n");
+
+1;
diff --git a/tests/scripts/functions/word b/tests/scripts/functions/word
new file mode 100644
index 0000000..4dcc940
--- /dev/null
+++ b/tests/scripts/functions/word
@@ -0,0 +1,167 @@
+# -*-perl-*-
+$description = "\
+Test the word, words, wordlist, firstword, and lastword functions.\n";
+
+$details = "\
+Produce a variable with a large number of words in it,
+determine the number of words, and then read each one back.\n";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<'EOF';
+string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
+string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
+string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
+string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
+all:
+ @echo $(words $(string))
+ @echo $(words $(string4))
+ @echo $(word 1, $(string))
+ @echo $(word 100, $(string))
+ @echo $(word 1, $(string))
+ @echo $(word 1000, $(string3))
+ @echo $(wordlist 3, 4, $(string))
+ @echo $(wordlist 4, 3, $(string))
+ @echo $(wordlist 1, 6, $(string))
+ @echo $(wordlist 5, 7, $(string))
+ @echo $(wordlist 100, 110, $(string))
+ @echo $(wordlist 7, 10, $(string2))
+EOF
+close(MAKEFILE);
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "6\n"
+ ."2058\n"
+ ."word.pl\n"
+ ."\n"
+ ."word.pl\n"
+ ."\n"
+ ."FORCE.pl word.pl\n"
+ ."\n"
+ ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
+ ."generic_test.perl MAKEFILES_variable.pl\n"
+ ."\n"
+ ."word.pl general_test2.pl FORCE.pl word.pl\n";
+&compare_output($answer, &get_logfile(1));
+
+
+# Test error conditions
+
+run_make_test('FOO = foo bar biz baz
+
+word-e1: ; @echo $(word ,$(FOO))
+word-e2: ; @echo $(word abc ,$(FOO))
+word-e3: ; @echo $(word 1a,$(FOO))
+
+wordlist-e1: ; @echo $(wordlist ,,$(FOO))
+wordlist-e2: ; @echo $(wordlist abc ,,$(FOO))
+wordlist-e3: ; @echo $(wordlist 1, 12a ,$(FOO))',
+ 'word-e1',
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'word-e2',
+ "#MAKEFILE#:4: *** non-numeric first argument to 'word' function: 'abc '. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'word-e3',
+ "#MAKEFILE#:5: *** non-numeric first argument to 'word' function: '1a'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e1',
+ "#MAKEFILE#:7: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e2',
+ "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' function: 'abc '. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e3',
+ "#MAKEFILE#:9: *** non-numeric second argument to 'wordlist' function: ' 12a '. Stop.",
+ 512);
+
+# Test error conditions again, but this time in a variable reference
+
+run_make_test('FOO = foo bar biz baz
+
+W = $(word $x,$(FOO))
+WL = $(wordlist $s,$e,$(FOO))
+
+word-e: ; @echo $(W)
+wordlist-e: ; @echo $(WL)',
+ 'word-e x=',
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'word-e x=abc',
+ "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: 'abc'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'word-e x=0',
+ "#MAKEFILE#:3: *** first argument to 'word' function must be greater than 0. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e s= e=',
+ "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: ''. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e s=abc e=',
+ "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: 'abc'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e s=4 e=12a',
+ "#MAKEFILE#:4: *** non-numeric second argument to 'wordlist' function: '12a'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'wordlist-e s=0 e=12',
+ "#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.",
+ 512);
+
+
+# TEST #8 -- test $(firstword )
+#
+run_make_test('
+void :=
+list := $(void) foo bar baz #
+
+a := $(word 1,$(list))
+b := $(firstword $(list))
+
+.PHONY: all
+
+all:
+ @test "$a" = "$b" && echo $a
+',
+'',
+'foo');
+
+
+# TEST #9 -- test $(lastword )
+#
+run_make_test('
+void :=
+list := $(void) foo bar baz #
+
+a := $(word $(words $(list)),$(list))
+b := $(lastword $(list))
+
+.PHONY: all
+
+all:
+ @test "$a" = "$b" && echo $a
+',
+'',
+'baz');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/misc/bs-nl b/tests/scripts/misc/bs-nl
new file mode 100644
index 0000000..4fc3f63
--- /dev/null
+++ b/tests/scripts/misc/bs-nl
@@ -0,0 +1,129 @@
+# -*-perl-*-
+$description = "Test backslash-newline handling.";
+
+$details = "";
+
+# TEST #1
+# -------
+
+# Backslash-newlines in recipes
+
+# These are basic backslash-newlines with no tricks
+run_make_test("fast:;\@echo fa\\\nst\n",
+ '', 'fast');
+
+run_make_test("slow:;\@: no-op; echo sl\\\now\n",
+ '', 'slow');
+
+run_make_test("dquote:;\@echo \"dqu\\\note\"\n",
+ '', 'dquote');
+
+run_make_test("squote:;\@echo 'squ\\\note'\n",
+ '', "squ\\\note");
+
+# Ensure that a leading prefix character is omitted
+run_make_test("fast:;\@echo fa\\\n\tst\n",
+ '', 'fast');
+
+run_make_test("slow:;\@: no-op; echo sl\\\n\tow\n",
+ '', 'slow');
+
+run_make_test("dquote:;\@echo \"dqu\\\n\tote\"\n",
+ '', 'dquote');
+
+run_make_test("squote:;\@echo 'squ\\\n\tote'\n",
+ '', "squ\\\note");
+
+# Ensure that ONLY the leading prefix character is omitted
+run_make_test("fast:;\@echo fa\\\n\t st\n",
+ '', 'fa st');
+
+run_make_test("slow:;\@: no-op; echo sl\\\n\t\tow\n",
+ '', "sl ow");
+
+run_make_test("dquote:;\@echo \"dqu\\\n\t ote\"\n",
+ '', 'dqu ote');
+
+run_make_test("squote:;\@echo 'squ\\\n\t\t ote'\n",
+ '', "squ\\\n\t ote");
+
+# Backslash-newlines in variable values
+
+# Simple
+run_make_test(q!
+var = he\
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Condense trailing space
+run_make_test(q!
+var = he \
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Remove leading space
+run_make_test(q!
+var = he\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Multiple bs/nl condensed
+run_make_test(q!
+var = he\
+\
+\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# POSIX: Preserve trailing space
+run_make_test(q!
+.POSIX:
+x = y
+var = he \
+llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# POSIX: One space per bs-nl
+run_make_test(q!
+.POSIX:
+x = y
+var = he\
+\
+\
+ llo
+var:;@echo '|$(var)|'!,
+ '', "|he llo|");
+
+# Savannah #39035: handle whitespace in call
+run_make_test(q!
+f = echo $(1)
+t:; @$(call f,"a \
+ b"); \
+ $(call f,"a \
+ b")
+!,
+ '', "a b\na b\n");
+
+# Savannah #38945: handle backslash CRLF
+# We need our own makefile so we can set binmode
+my $m1 = get_tmpfile();
+open(MAKEFILE, "> $m1");
+binmode(MAKEFILE);
+print MAKEFILE "FOO = foo \\\r\n";
+close(MAKEFILE);
+
+my $m2 = get_tmpfile();
+open(MAKEFILE, "> $m2");
+print MAKEFILE "include $m1\ndefine BAR\nall: ; \@echo \$(FOO) bar\nendef\n\$(eval \$(BAR))\n";
+close(MAKEFILE);
+
+run_make_with_options($m2, '', get_logfile());
+compare_output("foo bar\n", get_logfile(1));
+
+
+1;
diff --git a/tests/scripts/misc/close_stdout b/tests/scripts/misc/close_stdout
new file mode 100644
index 0000000..18606c3
--- /dev/null
+++ b/tests/scripts/misc/close_stdout
@@ -0,0 +1,9 @@
+# -*-perl-*-
+
+$description = "Make sure make exits with an error if stdout is full.";
+
+if (-e '/dev/full') {
+ run_make_test('', '-v > /dev/full', '/^#MAKE#: write error/', 256);
+}
+
+1;
diff --git a/tests/scripts/misc/fopen-fail b/tests/scripts/misc/fopen-fail
new file mode 100644
index 0000000..6580e51
--- /dev/null
+++ b/tests/scripts/misc/fopen-fail
@@ -0,0 +1,15 @@
+# -*-perl-*-
+
+$description = "Make sure make exits with an error if fopen fails.";
+
+# Recurse infinitely until we run out of open files, and ensure we
+# fail with a non-zero exit code. Don't bother to test the output
+# since it's hard to know what it will be, exactly.
+# See Savannah bug #27374.
+
+run_make_test(q!
+include $(lastword $(MAKEFILE_LIST))
+!,
+ '', undef, 512);
+
+1;
diff --git a/tests/scripts/misc/general1 b/tests/scripts/misc/general1
new file mode 100644
index 0000000..352fc6a
--- /dev/null
+++ b/tests/scripts/misc/general1
@@ -0,0 +1,51 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test the
+simple functionality of make. It mimics the
+rebuilding of a product with dependencies.
+It also tests the simple definition of VPATH.";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+edit: main.o kbd.o commands.o display.o \\
+ insert.o
+\t\@echo cc -o edit main.o kbd.o commands.o display.o \\
+ insert.o
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+insert.o : insert.c defs.h buffer.h
+\t\@echo cc -c insert.c
+EOF
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+ "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+ "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c\ncc -c kbd.c\ncc -c commands.c\ncc -c display.c
+cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o insert.o\n";
+
+# COMPARE RESULTS
+
+if (&compare_output($answer,&get_logfile(1))) {
+ unlink @files_to_touch;
+}
+
+1;
diff --git a/tests/scripts/misc/general2 b/tests/scripts/misc/general2
new file mode 100644
index 0000000..fb5c3aa
--- /dev/null
+++ b/tests/scripts/misc/general2
@@ -0,0 +1,50 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test the
+simple functionality of make. It is the same as
+general_test1 except that this one tests the
+definition of a variable to hold the object filenames.";
+
+open(MAKEFILE,"> $makefile");
+
+# The contents of the Makefile ...
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+objects = main.o kbd.o commands.o display.o insert.o
+edit: \$(objects)
+\t\@echo cc -o edit \$(objects)
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+insert.o : insert.c defs.h buffer.h
+\t\@echo cc -c insert.c
+EOF
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+ "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
+ "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c\ncc -c kbd.c\ncc -c commands.c\ncc -c display.c
+cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o insert.o\n";
+
+if (&compare_output($answer,&get_logfile(1))) {
+ unlink @files_to_touch;
+}
+
+1;
diff --git a/tests/scripts/misc/general3 b/tests/scripts/misc/general3
new file mode 100644
index 0000000..8ad0f8e
--- /dev/null
+++ b/tests/scripts/misc/general3
@@ -0,0 +1,313 @@
+# -*-perl-*-
+
+$description = "\
+This tests random features of the parser that need to be supported, and
+which have either broken at some point in the past or seem likely to
+break.";
+
+run_make_test("
+# We want to allow both empty commands _and_ commands that resolve to empty.
+EMPTY =
+
+.PHONY: all a1 a2 a3 a4
+all: a1 a2 a3 a4
+
+a1:;
+a2:
+\t
+a3:;\$(EMPTY)
+a4:
+\t\$(EMPTY)
+
+\# Non-empty lines that expand to nothing should also be ignored.
+STR = \# Some spaces
+TAB = \t \# A TAB and some spaces
+
+\$(STR)
+
+\$(STR) \$(TAB)",
+ '', "#MAKE#: Nothing to be done for 'all'.");
+
+# TEST 2
+
+# Make sure files without trailing newlines are handled properly.
+# Have to use the old style invocation to test this.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE "all:;\@echo FOO = \$(FOO)\nFOO = foo";
+close(MAKEFILE);
+
+&run_make_with_options($makefile2,"",&get_logfile);
+$answer = "FOO = foo\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST 3
+
+# Check semicolons in variable references
+
+run_make_test('
+$(if true,$(info true; true))
+all: ; @:
+',
+ '', 'true; true');
+
+# TEST 4
+
+# Check that backslashes in command scripts are handled according to POSIX.
+# Checks Savannah bug # 1332.
+
+# Test the fastpath / no quotes
+run_make_test('
+all:
+ @echo foo\
+bar
+ @echo foo\
+ bar
+ @echo foo\
+ bar
+ @echo foo\
+ bar
+ @echo foo \
+bar
+ @echo foo \
+ bar
+ @echo foo \
+ bar
+ @echo foo \
+ bar
+',
+ '', 'foobar
+foobar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar');
+
+# Test the fastpath / single quotes
+run_make_test("
+all:
+ \@echo 'foo\\
+bar'
+ \@echo 'foo\\
+ bar'
+ \@echo 'foo\\
+ bar'
+ \@echo 'foo\\
+ bar'
+ \@echo 'foo \\
+bar'
+ \@echo 'foo \\
+ bar'
+ \@echo 'foo \\
+ bar'
+ \@echo 'foo \\
+ bar'
+",
+ '', 'foo\
+bar
+foo\
+bar
+foo\
+ bar
+foo\
+ bar
+foo \
+bar
+foo \
+bar
+foo \
+ bar
+foo \
+ bar');
+
+# Test the fastpath / double quotes
+run_make_test('
+all:
+ @echo "foo\
+bar"
+ @echo "foo\
+ bar"
+ @echo "foo\
+ bar"
+ @echo "foo\
+ bar"
+ @echo "foo \
+bar"
+ @echo "foo \
+ bar"
+ @echo "foo \
+ bar"
+ @echo "foo \
+ bar"
+',
+ '', 'foobar
+foobar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar
+foo bar');
+
+# Test the slow path / no quotes
+run_make_test('
+all:
+ @echo hi; echo foo\
+bar
+ @echo hi; echo foo\
+ bar
+ @echo hi; echo foo\
+ bar
+ @echo hi; echo foo\
+ bar
+ @echo hi; echo foo \
+bar
+ @echo hi; echo foo \
+ bar
+ @echo hi; echo foo \
+ bar
+ @echo hi; echo foo \
+ bar
+',
+ '', 'hi
+foobar
+hi
+foobar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar');
+
+# Test the slow path / no quotes. This time we put the slow path
+# determination _after_ the backslash-newline handling.
+run_make_test('
+all:
+ @echo foo\
+bar; echo hi
+ @echo foo\
+ bar; echo hi
+ @echo foo\
+ bar; echo hi
+ @echo foo\
+ bar; echo hi
+ @echo foo \
+bar; echo hi
+ @echo foo \
+ bar; echo hi
+ @echo foo \
+ bar; echo hi
+ @echo foo \
+ bar; echo hi
+',
+ '', 'foobar
+hi
+foobar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi');
+
+# Test the slow path / single quotes
+run_make_test("
+all:
+ \@echo hi; echo 'foo\\
+bar'
+ \@echo hi; echo 'foo\\
+ bar'
+ \@echo hi; echo 'foo\\
+ bar'
+ \@echo hi; echo 'foo\\
+ bar'
+ \@echo hi; echo 'foo \\
+bar'
+ \@echo hi; echo 'foo \\
+ bar'
+ \@echo hi; echo 'foo \\
+ bar'
+ \@echo hi; echo 'foo \\
+ bar'
+",
+ '', 'hi
+foo\
+bar
+hi
+foo\
+bar
+hi
+foo\
+ bar
+hi
+foo\
+ bar
+hi
+foo \
+bar
+hi
+foo \
+bar
+hi
+foo \
+ bar
+hi
+foo \
+ bar');
+
+# Test the slow path / double quotes
+run_make_test('
+all:
+ @echo hi; echo "foo\
+bar"
+ @echo hi; echo "foo\
+ bar"
+ @echo hi; echo "foo\
+ bar"
+ @echo hi; echo "foo\
+ bar"
+ @echo hi; echo "foo \
+bar"
+ @echo hi; echo "foo \
+ bar"
+ @echo hi; echo "foo \
+ bar"
+ @echo hi; echo "foo \
+ bar"
+',
+ '', 'hi
+foobar
+hi
+foobar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar
+hi
+foo bar');
+
+1;
diff --git a/tests/scripts/misc/general4 b/tests/scripts/misc/general4
new file mode 100644
index 0000000..6d42a16
--- /dev/null
+++ b/tests/scripts/misc/general4
@@ -0,0 +1,82 @@
+# -*-perl-*-
+
+$description = "\
+This tests random features of make's algorithms, often somewhat obscure,
+which have either broken at some point in the past or seem likely to
+break.";
+
+run_make_test('
+# Make sure that subdirectories built as prerequisites are actually handled
+# properly.
+
+all: dir/subdir/file.a
+
+dir/subdir: ; @echo mkdir -p dir/subdir
+
+dir/subdir/file.b: dir/subdir ; @echo touch dir/subdir/file.b
+
+dir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@',
+ '', "mkdir -p dir/subdir\ntouch dir/subdir/file.b\ncp dir/subdir/file.b dir/subdir/file.a\n");
+
+# Test implicit rules
+
+&touch('foo.c');
+run_make_test('foo: foo.o',
+ 'CC="@echo cc" OUTPUT_OPTION=',
+ 'cc -c foo.c
+cc foo.o -o foo');
+unlink('foo.c');
+
+
+# Test implicit rules with '$' in the name (see se_implicit)
+
+run_make_test(q!
+%.foo : baz$$bar ; @echo 'done $<'
+%.foo : bar$$baz ; @echo 'done $<'
+test.foo:
+baz$$bar bar$$baz: ; @echo '$@'
+!,
+ '',
+ "baz\$bar\ndone baz\$bar");
+
+
+# Test implicit rules with '$' in the name (see se_implicit)
+# Use the '$' in the pattern.
+
+run_make_test(q!
+%.foo : %$$bar ; @echo 'done $<'
+test.foo:
+test$$bar: ; @echo '$@'
+!,
+ '',
+ "test\$bar\ndone test\$bar");
+
+# Make sure that subdirectories built as prerequisites are actually handled
+# properly... this time with '$'
+
+run_make_test(q!
+
+all: dir/subdir/file.$$a
+
+dir/subdir: ; @echo mkdir -p '$@'
+
+dir/subdir/file.$$b: dir/subdir ; @echo touch '$@'
+
+dir/subdir/%.$$a: dir/subdir/%.$$b ; @echo 'cp $< $@'
+!,
+ '', "mkdir -p dir/subdir\ntouch dir/subdir/file.\$b\ncp dir/subdir/file.\$b dir/subdir/file.\$a\n");
+
+# Test odd whitespace at the beginning of a line
+
+run_make_test("
+all:
+ \f
+
+ \\
+ \f \\
+ \013 \\
+all: ; \@echo hi
+",
+ '', "hi\n");
+
+1;
diff --git a/tests/scripts/misc/utf8 b/tests/scripts/misc/utf8
new file mode 100644
index 0000000..2adcd07
--- /dev/null
+++ b/tests/scripts/misc/utf8
@@ -0,0 +1,14 @@
+# -*-perl-*-
+$description = "Test utf8 handling.";
+
+$details = "";
+
+# Variable names containing UTF8 characters
+run_make_test("
+\xe2\x96\xaa := hello
+\$(info \$(\xe2\x96\xaa))
+all:
+",
+ '', "hello\n#MAKE#: Nothing to be done for 'all'.");
+
+1;
diff --git a/tests/scripts/options/dash-B b/tests/scripts/options/dash-B
new file mode 100644
index 0000000..9c708b7
--- /dev/null
+++ b/tests/scripts/options/dash-B
@@ -0,0 +1,85 @@
+# -*-perl-*-
+
+$description = "Test make -B (always remake) option.\n";
+
+$details = "\
+Construct a simple makefile that builds a target.
+Invoke make once, so it builds everything. Invoke it again and verify
+that nothing is built. Then invoke it with -B and verify that everything
+is built again.";
+
+&touch('bar.x');
+
+run_make_test('
+.SUFFIXES:
+
+.PHONY: all
+all: foo
+
+foo: bar.x
+ @echo cp $< $@
+ @echo "" > $@
+',
+ '', 'cp bar.x foo');
+
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'.");
+run_make_test(undef, '-B', 'cp bar.x foo');
+
+# Put the timestamp for foo into the future; it should still be remade.
+
+utouch(1000, 'foo');
+run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'.");
+run_make_test(undef, '-B', 'cp bar.x foo');
+
+# Clean up
+
+rmfiles('bar.x', 'foo');
+
+# Test -B with the re-exec feature: we don't want to re-exec forever
+# Savannah bug # 7566
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+',
+ '-B', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1');
+
+rmfiles('foo.x');
+
+# Test -B with the re-exec feature: we DO want -B in the "normal" part of the
+# makefile.
+
+&touch('blah.x');
+
+run_make_test('
+all: blah.x ; @echo $@
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+blah.x: ; @echo $@
+',
+ '-B', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1
+blah.x
+all');
+
+rmfiles('foo.x', 'blah.x');
+
+# Test that $? is set properly with -B; all prerequisites will be newer!
+
+utouch(-10, 'x.b');
+touch('x.a');
+
+run_make_test(q!
+x.a: x.b ; @echo $?
+!,
+ '-B', "x.b\n");
+
+unlink(qw(x.a x.b));
+
+1;
diff --git a/tests/scripts/options/dash-C b/tests/scripts/options/dash-C
new file mode 100644
index 0000000..42d0a8b
--- /dev/null
+++ b/tests/scripts/options/dash-C
@@ -0,0 +1,71 @@
+# -*-perl-*-
+
+$description = "Test the -C option to GNU make.";
+
+$details = "\
+This test is similar to the clean test except that this test creates the file
+to delete in the work directory instead of the current directory. Make is
+called from another directory using the -C workdir option so that it can both
+find the makefile and the file to delete in the work directory.";
+
+$example = $workdir . $pathsep . "EXAMPLE";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<EOF;
+all: ; \@echo This makefile did not clean the dir ... good
+clean: ; $delete_command EXAMPLE\$(ext)
+EOF
+close(MAKEFILE);
+
+# TEST #1
+# -------
+&touch($example);
+
+&run_make_with_options("${testname}.mk",
+ "-C $workdir clean",
+ &get_logfile);
+
+chdir $workdir;
+$wpath = &get_this_pwd;
+chdir $pwd;
+
+if (-f $example) {
+ $test_passed = 0;
+}
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: Entering directory '$wpath'\n"
+ . "$delete_command EXAMPLE\n"
+ . "$make_name: Leaving directory '$wpath'\n";
+
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #2
+# -------
+# Do it again with trailing "/"; this should work the same
+
+$example .= "slash";
+
+&touch($example);
+
+&run_make_with_options("${testname}.mk",
+ "-C $workdir/ clean ext=slash",
+ &get_logfile);
+
+chdir $workdir;
+$wpath = &get_this_pwd;
+chdir $pwd;
+
+if (-f $example) {
+ $test_passed = 0;
+}
+
+# Create the answer to what should be produced by this Makefile
+$answer = "$make_name: Entering directory '$wpath'\n"
+ . "$delete_command EXAMPLEslash\n"
+ . "$make_name: Leaving directory '$wpath'\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/options/dash-I b/tests/scripts/options/dash-I
new file mode 100644
index 0000000..d47a8d8
--- /dev/null
+++ b/tests/scripts/options/dash-I
@@ -0,0 +1,59 @@
+# -*-perl-*-
+
+$description ="The following test creates a makefile to test the -I option.";
+
+$details = "\
+This test tests the -I option by including a filename in
+another directory and giving make that directory name
+under -I in the command line. Without this option, the make
+would fail to find the included file. It also checks to make
+sure that the -I option gets passed to recursive makes.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+$mf2 = substr ($makefile2, index ($makefile2, $pathsep) + 1);
+print MAKEFILE <<EOF;
+include $mf2
+all:
+\t\@echo There should be no errors for this makefile.
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE <<EOF;
+ANOTHER:
+\t\@echo This is another included makefile
+recurse:
+\t\$(MAKE) ANOTHER -f $makefile
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,"-I $workdir all",&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "There should be no errors for this makefile.\n";
+&compare_output($answer,&get_logfile(1));
+
+
+$answer = "This is another included makefile\n";
+&run_make_with_options($makefile,"-I $workdir ANOTHER",&get_logfile);
+&compare_output($answer,&get_logfile(1));
+
+
+$answer = "$mkpath ANOTHER -f $makefile
+${make_name}[1]: Entering directory '$pwd'
+This is another included makefile
+${make_name}[1]: Leaving directory '$pwd'\n";
+
+&run_make_with_options($makefile,"-I $workdir recurse",&get_logfile);
+&compare_output($answer,&get_logfile(1));
diff --git a/tests/scripts/options/dash-W b/tests/scripts/options/dash-W
new file mode 100644
index 0000000..20b9f74
--- /dev/null
+++ b/tests/scripts/options/dash-W
@@ -0,0 +1,88 @@
+# -*-perl-*-
+
+$description = "Test make -W (what if) option.\n";
+
+# Basic build
+
+run_make_test('
+a.x: b.x
+a.x b.x: ; echo >> $@
+',
+ '', "echo >> b.x\necho >> a.x");
+
+# Run it again: nothing should happen
+
+run_make_test(undef, '', "#MAKE#: 'a.x' is up to date.");
+
+# Now run it with -W b.x: should rebuild a.x
+
+run_make_test(undef, '-W b.x', 'echo >> a.x');
+
+# Put the timestamp for a.x into the future; it should still be remade.
+
+utouch(1000, 'a.x');
+run_make_test(undef, '', "#MAKE#: 'a.x' is up to date.");
+run_make_test(undef, '-W b.x', 'echo >> a.x');
+
+# Clean up
+
+rmfiles('a.x', 'b.x');
+
+# Test -W with the re-exec feature: we don't want to re-exec forever
+# Savannah bug # 7566
+
+# First set it up with a normal build
+
+run_make_test('
+all: baz.x ; @:
+include foo.x
+foo.x: bar.x
+ @echo "\$$(info restarts=\$$(MAKE_RESTARTS))" > $@
+ @echo "touch $@"
+bar.x: ; echo >> $@
+baz.x: bar.x ; @echo "touch $@"
+',
+ '', '#MAKEFILE#:3: foo.x: No such file or directory
+echo >> bar.x
+touch foo.x
+restarts=1
+touch baz.x');
+
+# Now run with -W bar.x
+
+# Tweak foo.x's timestamp so the update will change it.
+&utouch(1000, 'foo.x');
+
+run_make_test(undef, '-W bar.x', "restarts=\ntouch foo.x\nrestarts=1\ntouch baz.x");
+
+rmfiles('foo.x', 'bar.x');
+
+# Test -W on vpath-found files: it should take effect.
+# Savannah bug # 15341
+
+mkdir('x-dir', 0777);
+utouch(-20, 'x-dir/x');
+touch('y');
+
+run_make_test('
+y: x ; @echo cp $< $@
+',
+ '-W x-dir/x VPATH=x-dir',
+ 'cp x-dir/x y');
+
+# Make sure ./ stripping doesn't interfere with the match.
+
+run_make_test('
+y: x ; @echo cp $< $@
+',
+ '-W ./x-dir/x VPATH=x-dir',
+ 'cp x-dir/x y');
+
+run_make_test(undef,
+ '-W x-dir/x VPATH=./x-dir',
+ 'cp ./x-dir/x y');
+
+unlink(qw(y x-dir/x));
+rmdir('x-dir');
+
+1;
diff --git a/tests/scripts/options/dash-e b/tests/scripts/options/dash-e
new file mode 100644
index 0000000..17c3fc8
--- /dev/null
+++ b/tests/scripts/options/dash-e
@@ -0,0 +1,24 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to ...";
+
+$details = "";
+
+$extraENV{GOOGLE} = 'boggle';
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+GOOGLE = bazzle
+all:; @echo "$(GOOGLE)"
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile, '-e' ,&get_logfile);
+
+$answer = "boggle\n";
+
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/options/dash-f b/tests/scripts/options/dash-f
new file mode 100644
index 0000000..3aa4746
--- /dev/null
+++ b/tests/scripts/options/dash-f
@@ -0,0 +1,85 @@
+$description = "The following test tests that if you specify greater \n"
+ ."than one '-f makefilename' on the command line, \n"
+ ."that make concatenates them. This test creates three \n"
+ ."makefiles and specifies all of them with the -f option \n"
+ ."on the command line. To make sure they were concatenated, \n"
+ ."we then call make with the rules from the concatenated \n"
+ ."makefiles one at a time. Finally, it calls all three \n"
+ ."rules in one call to make and checks that the output\n"
+ ."is in the correct order.";
+
+$makefile2 = &get_tmpfile;
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This is the output from the original makefile\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# Create a second makefile
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE "TWO: \n";
+print MAKEFILE "\t\@echo This is the output from makefile 2\n";
+close(MAKEFILE);
+
+# Create a third makefile
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE "THREE: \n";
+print MAKEFILE "\t\@echo This is the output from makefile 3\n";
+close(MAKEFILE);
+
+
+# Create the answer to what should be produced by this Makefile
+$answer = "This is the output from the original makefile\n";
+
+# Run make to catch the default rule
+&run_make_with_options($makefile,"-f $makefile2 -f $makefile3",&get_logfile,0);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# Run Make again with the rule from the second makefile: TWO
+$answer = "This is the output from makefile 2\n";
+
+&run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0);
+
+&compare_output($answer,&get_logfile(1));
+
+
+# Run Make again with the rule from the third makefile: THREE
+
+$answer = "This is the output from makefile 3\n";
+&run_make_with_options($makefile,
+ "-f $makefile2 -f $makefile3 THREE",
+ &get_logfile,
+ 0);
+&compare_output($answer,&get_logfile(1));
+
+
+# Run Make again with ALL three rules in the order 2 1 3 to make sure
+# that all rules are executed in the proper order
+
+$answer = "This is the output from makefile 2\n";
+$answer .= "This is the output from the original makefile\n";
+$answer .= "This is the output from makefile 3\n";
+&run_make_with_options($makefile,
+ "-f $makefile2 -f $makefile3 TWO all THREE",
+ &get_logfile,
+ 0);
+&compare_output($answer,&get_logfile(1));
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/options/dash-k b/tests/scripts/options/dash-k
new file mode 100644
index 0000000..e784e0d
--- /dev/null
+++ b/tests/scripts/options/dash-k
@@ -0,0 +1,115 @@
+# -*-perl-*-
+
+$description = "Test the make -k (don't stop on error) option.\n";
+
+$details = "\
+The makefile created in this test is a simulation of building
+a small product. However, the trick to this one is that one
+of the dependencies of the main target does not exist.
+Without the -k option, make would fail immediately and not
+build any part of the target. What we are looking for here,
+is that make builds the rest of the dependencies even though
+it knows that at the end it will fail to rebuild the main target.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+VPATH = $workdir
+edit: main.o kbd.o commands.o display.o
+\t\@echo cc -o edit main.o kbd.o commands.o display.o
+
+main.o : main.c defs.h
+\t\@echo cc -c main.c
+
+kbd.o : kbd.c defs.h command.h
+\t\@echo cc -c kbd.c
+
+commands.o : command.c defs.h command.h
+\t\@echo cc -c commands.c
+
+display.o : display.c defs.h buffer.h
+\t\@echo cc -c display.c
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
+ "$workdir${pathsep}command.h",
+ "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
+ "$workdir${pathsep}buffer.h",
+ "$workdir${pathsep}command.c");
+
+&touch(@files_to_touch);
+
+if ($vos) {
+ $error_code = 3307;
+}
+else {
+ $error_code = 512;
+}
+
+&run_make_with_options($makefile, "-k", &get_logfile, $error_code);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "cc -c main.c
+$make_name: *** No rule to make target 'kbd.c', needed by 'kbd.o'.
+cc -c commands.c
+cc -c display.c
+$make_name: Target 'edit' not remade because of errors.\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer, &get_logfile(1));
+
+unlink(@files_to_touch) unless $keep;
+
+
+# TEST 1: Make sure that top-level targets that depend on targets that
+# previously failed to build, aren't attempted. Regression for PR/1634.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+
+all: exe1 exe2; @echo making $@
+
+exe1 exe2: lib; @echo cp $^ $@
+
+lib: foo.o; @echo cp $^ $@
+
+foo.o: ; exit 1
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "-k", &get_logfile, $error_code);
+
+$answer = "exit 1
+$makefile2:9: recipe for target 'foo.o' failed
+$make_name: *** [foo.o] Error 1
+$make_name: Target 'all' not remade because of errors.\n";
+
+&compare_output($answer, &get_logfile(1));
+
+# TEST -- make sure we keep the error code if we can't create an included
+# makefile.
+
+run_make_test('all: ; @echo hi
+include ifile
+ifile: no-such-file; @false
+',
+ '-k',
+ "#MAKEFILE#:2: ifile: No such file or directory
+#MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'.
+#MAKE#: Failed to remake makefile 'ifile'.
+hi\n",
+ 512);
+
+1;
diff --git a/tests/scripts/options/dash-l b/tests/scripts/options/dash-l
new file mode 100644
index 0000000..0b0f196
--- /dev/null
+++ b/tests/scripts/options/dash-l
@@ -0,0 +1,56 @@
+# -*-perl-*-
+# Date: Tue, 11 Aug 1992 09:34:26 -0400
+# From: pds@lemming.webo.dg.com (Paul D. Smith)
+
+$description = "Test load balancing (-l) option.";
+
+$details = "\
+This test creates a makefile where all depends on three rules
+which contain the same body. Each rule checks for the existence
+of a temporary file; if it exists an error is generated. If it
+doesn't exist then it is created, the rule sleeps, then deletes
+the temp file again. Thus if any of the rules are run in
+parallel the test will fail. When make is called in this test,
+it is given the -l option with a value of 0.0001. This ensures
+that the load will be above this number and make will therefore
+decide that it cannot run more than one job even though -j 4 was
+also specified on the command line.";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<'EOF';
+SHELL = /bin/sh
+
+define test
+if [ ! -f test-file ]; then \
+ echo >> test-file; sleep 2; rm -f test-file; \
+else \
+ echo $@ FAILED; \
+fi
+endef
+
+all : ONE TWO THREE
+ONE : ; @$(test)
+TWO : ; @$(test)
+THREE : ; @$(test)
+EOF
+
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+$mkoptions = "-l 0.0001";
+$mkoptions .= " -j 4" if ($parallel_jobs);
+
+# We have to wait longer than the default (5s).
+&run_make_with_options($makefile, $mkoptions, &get_logfile, 0, 8);
+
+$slurp = &read_file_into_string (&get_logfile(1));
+if ($slurp !~ /cannot enforce load limit/) {
+ &compare_output("", &get_logfile(1));
+}
+
+1;
diff --git a/tests/scripts/options/dash-n b/tests/scripts/options/dash-n
new file mode 100644
index 0000000..dfed419
--- /dev/null
+++ b/tests/scripts/options/dash-n
@@ -0,0 +1,100 @@
+# -*-perl-*-
+$description = "Test the -n option.\n";
+
+$details = "Try various uses of -n and ensure they all give the correct results.\n";
+
+touch('orig');
+
+run_make_test(q!
+final: intermediate ; echo >> $@
+intermediate: orig ; echo >> $@
+!,
+ '', "echo >> intermediate\necho >> final\n");
+
+# TEST 1
+
+run_make_test(undef, '-Worig -n', "echo >> intermediate\necho >> final\n");
+
+rmfiles(qw(orig intermediate final));
+
+# We consider the actual updated timestamp of targets with all
+# recursive commands, even with -n. Switching this to the new model
+# is non-trivial because we use a trick below to change the log content
+# before we compare it ...
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+BAR = # nothing
+FOO = +$(BAR)
+a: b; echo > $@
+b: c; $(FOO)
+EOF
+
+close(MAKEFILE);
+
+&utouch(-20, 'b');
+&utouch(-10, 'a');
+&touch('c');
+
+# TEST 2
+
+&run_make_with_options($makefile2, "", &get_logfile);
+$answer = "$make_name: 'a' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 3
+
+&run_make_with_options($makefile2, "-n", &get_logfile);
+$answer = "$make_name: 'a' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST 4
+
+unlink(qw(a b));
+
+&run_make_with_options($makefile2, "-t -n", &get_logfile);
+
+open(DASH_N_LOG, ">>" . &get_logfile(1));
+print DASH_N_LOG "a exists but should not!\n" if -e 'a';
+print DASH_N_LOG "b exists but should not!\n" if -e 'b';
+close(DASH_N_LOG);
+
+&compare_output("touch b\ntouch a\n", &get_logfile(1));
+
+# CLEANUP
+
+unlink(qw(a b c));
+
+# Ensure -n continues to be included with recursive/re-execed make
+# See Savannah bug #38051
+
+$topmake = &get_tmpfile;
+$submake = &get_tmpfile;
+
+open(MAKEFILE, "> $topmake");
+print MAKEFILE <<"EOF";
+foo: ; \@\$(MAKE) -f "$submake" bar
+EOF
+close(MAKEFILE);
+
+
+# The bar target should print what would happen, but not actually run
+open(MAKEFILE, "> $submake");
+print MAKEFILE <<'EOF';
+inc: ; touch $@
+-include inc
+bar: ; @echo $(strip $(MAKEFLAGS))
+EOF
+close(MAKEFILE);
+
+&run_make_with_options($topmake, '-n --no-print-directory', &get_logfile);
+$answer = "$make_path -f \"$submake\" bar\ntouch inc\necho n --no-print-directory\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('inc');
+
+1;
diff --git a/tests/scripts/options/dash-q b/tests/scripts/options/dash-q
new file mode 100644
index 0000000..194588d
--- /dev/null
+++ b/tests/scripts/options/dash-q
@@ -0,0 +1,77 @@
+# -*-perl-*-
+$description = "Test the -q option.\n";
+
+$details = "Try various uses of -q and ensure they all give the correct results.\n";
+
+# TEST 0
+
+run_make_test(qq!
+one:
+two: ;
+three: ; :
+four: ; \$(.XY)
+five: ; \\
+ \$(.XY)
+six: ; \\
+ \$(.XY)
+\t\$(.XY)
+seven: ; \\
+ \$(.XY)
+\t: foo
+\t\$(.XY)
+!,
+ '-q one', '');
+
+# TEST 1
+
+run_make_test(undef, '-q two', '');
+
+# TEST 2
+
+run_make_test(undef, '-q three', '', 256);
+
+# TEST 3
+
+run_make_test(undef, '-q four', '');
+
+# TEST 4
+
+run_make_test(undef, '-q five', '');
+
+# TEST 5
+
+run_make_test(undef, '-q six', '');
+
+# TEST 6
+
+run_make_test(undef, '-q seven', '', 256);
+
+# TEST 7 : Savannah bug # 7144
+
+run_make_test('
+one:: ; @echo one
+one:: ; @echo two
+',
+ '-q', '', 256);
+
+# TEST 7 : Savannah bug # 42249
+# Make sure we exit with 1 even for prerequisite updates
+run_make_test('
+build-stamp: ; echo $@
+build-arch: build-stamp
+build-x: build-arch
+build-y: build-x
+',
+ '-q build-y', '', 256);
+
+# TEST 8
+# Make sure we exit with 2 on error even with -q
+run_make_test('
+build-stamp: ; echo $@
+build-arch: build-stamp-2
+build-x: build-arch
+build-y: build-x
+',
+ '-q build-y', "#MAKE#: *** No rule to make target 'build-stamp-2', needed by 'build-arch'. Stop.\n", 512);
+
+1;
diff --git a/tests/scripts/options/dash-t b/tests/scripts/options/dash-t
new file mode 100644
index 0000000..ec27d7a
--- /dev/null
+++ b/tests/scripts/options/dash-t
@@ -0,0 +1,58 @@
+# -*-perl-*-
+
+$description = "Test the -t option.\n";
+
+$details = "Look out for regressions of prior bugs related to -t.\n";
+# That means, nobody has even tried to make the tests below comprehensive
+
+# TEST 0
+# bug reported by Henning Makholm <henning@makholm.net> on 2001-11-03:
+# make 3.79.1 touches only interm-[ab] but reports final-[a] as
+# 'up to date' without touching them.
+# The 'obvious' fix didn't work for double-colon rules, so pay special
+# attention to them.
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE <<'EOMAKE';
+final-a: interm-a ; echo >> $@
+final-b: interm-b ; echo >> $@
+interm-a:: orig1-a ; echo >> $@
+interm-a:: orig2-a ; echo >> $@
+interm-b:: orig1-b ; echo >> $@
+interm-b:: orig2-b ; echo >> $@
+EOMAKE
+close(MAKEFILE);
+
+&utouch(-30, 'orig1-a','orig2-b');
+&utouch(-20, 'interm-a','interm-b');
+&utouch(-10, 'final-a','final-b');
+&touch('orig2-a','orig1-b');
+
+&run_make_with_options($makefile, "-t final-a final-b", &get_logfile);
+$answer = "touch interm-a\ntouch final-a\ntouch interm-b\ntouch final-b\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('orig1-a', 'orig2-a', 'interm-a', 'final-a');
+unlink('orig1-b', 'orig2-b', 'interm-b', 'final-b');
+
+# TEST 1
+# -t should not touch files with no commands.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE <<'EOMAKE';
+
+PHOOEY: xxx
+xxx: ; @:
+
+EOMAKE
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "-t", &get_logfile);
+$answer = "touch xxx\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('xxx');
+
+1;
diff --git a/tests/scripts/options/eval b/tests/scripts/options/eval
new file mode 100644
index 0000000..0f82409
--- /dev/null
+++ b/tests/scripts/options/eval
@@ -0,0 +1,29 @@
+# -*-perl-*-
+
+$description = "Test the --eval option.";
+
+$details = "Verify that --eval options take effect,
+and are passed to sub-makes.";
+
+# Verify that --eval is evaluated first
+run_make_test(q!
+BAR = bar
+all: ; @echo all
+recurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!,
+ '--eval=\$\(info\ eval\) FOO=\$\(BAR\)', "eval\nall");
+
+# Make sure that --eval is handled correctly during recursion
+run_make_test(undef, '--no-print-directory --eval=\$\(info\ eval\) recurse',
+ "eval\neval\nall\nrecurse");
+
+# Make sure that --eval is handled correctly during restarting
+run_make_test(q!
+all: ; @echo $@
+-include gen.mk
+gen.mk: ; @echo > $@
+!,
+ '--eval=\$\(info\ eval\)', "eval\neval\nall");
+
+unlink('gen.mk');
+
+1;
diff --git a/tests/scripts/options/general b/tests/scripts/options/general
new file mode 100644
index 0000000..d35bb35
--- /dev/null
+++ b/tests/scripts/options/general
@@ -0,0 +1,35 @@
+# -*-perl-*-
+$description = "Test generic option processing.\n";
+
+open(MAKEFILE, "> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "foo 1foo: ; \@echo \$\@\n";
+
+close(MAKEFILE);
+
+# TEST 0
+
+&run_make_with_options($makefile, "-j 1foo", &get_logfile);
+if (!$parallel_jobs) {
+ $answer = "$make_name: Parallel jobs (-j) are not supported on this platform.\n$make_name: Resetting to single job (-j1) mode.\n1foo\n";
+}
+else {
+ $answer = "1foo\n";
+}
+
+# TEST 1
+
+# This test prints the usage string; I don't really know a good way to
+# test it. I guess I could invoke make with a known-bad option to see
+# what the usage looks like, then compare it to what I get here... :(
+
+# If I were always on UNIX, I could invoke it with 2>/dev/null, then
+# just check the error code.
+
+&run_make_with_options($makefile, "-j1foo 2>/dev/null", &get_logfile, 512);
+$answer = "";
+&compare_output($answer, &get_logfile(1));
+
+1;
diff --git a/tests/scripts/options/print-directory b/tests/scripts/options/print-directory
new file mode 100644
index 0000000..a05bbee
--- /dev/null
+++ b/tests/scripts/options/print-directory
@@ -0,0 +1,33 @@
+# -*-perl-*-
+
+$description = "Test the -w option to GNU make.";
+
+# Simple test without -w
+run_make_test(q!
+all: ; @echo hi
+!,
+ "", "hi\n");
+
+# Simple test with -w
+run_make_test(undef, "-w",
+ "#MAKE#: Entering directory '#PWD#'\nhi\n#MAKE#: Leaving directory '#PWD#'\n");
+
+# Test makefile rebuild to ensure no enter/leave
+run_make_test(q!
+include foo
+all: ;@:
+foo: ; touch foo
+!,
+ "", "#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n");
+unlink('foo');
+
+# Test makefile rebuild with -w
+run_make_test(q!
+include foo
+all: ;@:
+foo: ; touch foo
+!,
+ "-w", "#MAKE#: Entering directory '#PWD#'\n#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n#MAKE#: Leaving directory '#PWD#'\n");
+unlink('foo');
+
+1;
diff --git a/tests/scripts/options/symlinks b/tests/scripts/options/symlinks
new file mode 100644
index 0000000..a1bfce0
--- /dev/null
+++ b/tests/scripts/options/symlinks
@@ -0,0 +1,68 @@
+# -*-perl-*-
+
+$description = "Test the -L option.";
+
+$details = "Verify that symlink handling with and without -L works properly.";
+
+# Only run these tests if the system sypports symlinks
+
+# Apparently the Windows port of Perl reports that it does support symlinks
+# (in that the symlink() function doesn't fail) but it really doesn't, so
+# check for it explicitly.
+
+if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) {
+ # This test is N/A
+ -1;
+} else {
+
+ # Set up a symlink sym -> dep
+ # We'll make both dep and targ older than sym
+ $pwd =~ m%/([^/]+)$%;
+ $dirnm = $1;
+ &utouch(-10, 'dep');
+ &utouch(-5, 'targ');
+ symlink("../$dirnm/dep", 'sym');
+
+ # Without -L, nothing should happen
+ # With -L, it should update targ
+ run_make_test('targ: sym ; @echo make $@ from $<', '',
+ "#MAKE#: 'targ' is up to date.");
+ run_make_test(undef, '-L', "make targ from sym");
+
+ # Now update dep; in all cases targ should be out of date.
+ &touch('dep');
+ run_make_test(undef, '', "make targ from sym");
+ run_make_test(undef, '-L', "make targ from sym");
+
+ # Now update targ; in all cases targ should be up to date.
+ &touch('targ');
+ run_make_test(undef, '', "#MAKE#: 'targ' is up to date.");
+ run_make_test(undef, '-L', "#MAKE#: 'targ' is up to date.");
+
+ # Add in a new link between sym and dep. Be sure it's newer than targ.
+ sleep(1);
+ rename('dep', 'dep1');
+ symlink('dep1', 'dep');
+
+ # Without -L, nothing should happen
+ # With -L, it should update targ
+ run_make_test(undef, '', "#MAKE#: 'targ' is up to date.");
+ run_make_test(undef, '-L', "make targ from sym");
+
+ rmfiles('targ', 'dep', 'sym', 'dep1');
+
+ # Check handling when symlinks point to non-existent files. Without -L we
+ # should get an error: with -L we should use the timestamp of the symlink.
+
+ symlink("../$dirname/dep", 'sym');
+ run_make_test('targ: sym ; @echo make $@ from $<', '',
+ "#MAKE#: *** No rule to make target 'sym', needed by 'targ'. Stop.", 512);
+
+ run_make_test('targ: sym ; @echo make $@ from $<', '-L',
+ 'make targ from sym');
+
+
+ rmfiles('targ', 'sym');
+
+ 1;
+}
diff --git a/tests/scripts/options/warn-undefined-variables b/tests/scripts/options/warn-undefined-variables
new file mode 100644
index 0000000..ce15507
--- /dev/null
+++ b/tests/scripts/options/warn-undefined-variables
@@ -0,0 +1,25 @@
+# -*-perl-*-
+
+$description = "Test the --warn-undefined-variables option.";
+
+$details = "Verify that warnings are printed for referencing undefined variables.";
+
+# Without --warn-undefined-variables, nothing should happen
+run_make_test('
+EMPTY =
+EREF = $(EMPTY)
+UREF = $(UNDEFINED)
+
+SEREF := $(EREF)
+SUREF := $(UREF)
+
+all: ; @echo ref $(EREF) $(UREF)',
+ '', 'ref');
+
+# With --warn-undefined-variables, it should warn me
+run_make_test(undef, '--warn-undefined-variables',
+ "#MAKEFILE#:7: warning: undefined variable 'UNDEFINED'
+#MAKEFILE#:9: warning: undefined variable 'UNDEFINED'
+ref");
+
+1;
diff --git a/tests/scripts/targets/DEFAULT b/tests/scripts/targets/DEFAULT
new file mode 100644
index 0000000..f3d5148
--- /dev/null
+++ b/tests/scripts/targets/DEFAULT
@@ -0,0 +1,53 @@
+$description = "The following test creates a makefile to override part\n"
+ ."of one Makefile with Another Makefile with the .DEFAULT\n"
+ ."rule.";
+
+$details = "This tests the use of the .DEFAULT special target to say that \n"
+ ."to remake any target that cannot be made fram the information\n"
+ ."in the containing makefile, make should look in another makefile\n"
+ ."This test gives this makefile the target bar which is not \n"
+ ."defined here but passes the target bar on to another makefile\n"
+ ."which does have the target bar defined.\n";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "foo:\n";
+print MAKEFILE "\t\@echo Executing rule FOO\n\n";
+print MAKEFILE ".DEFAULT:\n";
+print MAKEFILE "\t\@\$(MAKE) -f $makefile2 \$\@ \n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+
+print MAKEFILE "bar:\n";
+print MAKEFILE "\t\@echo Executing rule BAR\n\n";
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile,'bar',&get_logfile);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "${make_name}[1]: Entering directory '$pwd'\n"
+ . "Executing rule BAR\n"
+ . "${make_name}[1]: Leaving directory '$pwd'\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/targets/FORCE b/tests/scripts/targets/FORCE
new file mode 100644
index 0000000..eb8f251
--- /dev/null
+++ b/tests/scripts/targets/FORCE
@@ -0,0 +1,40 @@
+# -*-perl-*-
+
+$description = "The following tests rules without Commands or Dependencies.";
+
+$details = "If the rule ...\n";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".IGNORE :\n";
+print MAKEFILE "clean: FORCE\n";
+print MAKEFILE "\t$delete_command clean\n";
+print MAKEFILE "FORCE:\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+
+# Create a file named "clean". This is the same name as the target clean
+# and tricks the target into thinking that it is up to date. (Unless you
+# use the .PHONY target.
+&touch("clean");
+
+$answer = "$delete_command clean\n";
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/targets/INTERMEDIATE b/tests/scripts/targets/INTERMEDIATE
new file mode 100644
index 0000000..2b3021b
--- /dev/null
+++ b/tests/scripts/targets/INTERMEDIATE
@@ -0,0 +1,108 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .INTERMEDIATE target.";
+
+$details = "\
+Test the behavior of the .INTERMEDIATE special target.
+Create a makefile where a file would not normally be considered
+intermediate, then specify it as .INTERMEDIATE. Build and ensure it's
+deleted properly. Rebuild to ensure that it's not created if it doesn't
+exist but doesn't need to be built. Change the original and ensure
+that the intermediate file and the ultimate target are both rebuilt, and
+that the intermediate file is again deleted.
+
+Try this with implicit rules and explicit rules: both should work.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+.INTERMEDIATE: foo.e bar.e
+
+# Implicit rule test
+%.d : %.e ; cp $< $@
+%.e : %.f ; cp $< $@
+
+foo.d: foo.e
+
+# Explicit rule test
+foo.c: foo.e bar.e; cat $^ > $@
+EOF
+
+close(MAKEFILE);
+
+# TEST #0
+
+&utouch(-20, 'foo.f', 'bar.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #1
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "$make_name: 'foo.d' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2
+
+&utouch(-10, 'foo.d');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #3
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #4
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "$make_name: 'foo.c' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #5
+
+&utouch(-10, 'foo.c');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #6 -- added for PR/1669: don't remove files mentioned on the cmd line.
+
+&run_make_with_options($makefile,'foo.e',&get_logfile);
+$answer = "cp foo.f foo.e\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo.f', 'foo.e', 'foo.d', 'foo.c', 'bar.f', 'bar.e', 'bar.d', 'bar.c');
+
+# TEST #7 -- added for PR/1423
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+all: foo
+foo.a: ; touch $@
+%: %.a ; touch $@
+.INTERMEDIATE: foo.a
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, '-R', &get_logfile);
+$answer = "touch foo.a\ntouch foo\nrm foo.a\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo');
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/targets/ONESHELL b/tests/scripts/targets/ONESHELL
new file mode 100644
index 0000000..87713da
--- /dev/null
+++ b/tests/scripts/targets/ONESHELL
@@ -0,0 +1,88 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .ONESHELL target.";
+
+$details = "";
+
+# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
+# separate arguments.
+my $t = `/bin/sh -e -c true 2>/dev/null`;
+my $multi_ok = $? == 0;
+
+# Simple
+
+run_make_test(q!
+.ONESHELL:
+all:
+ a=$$$$
+ [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+
+# Simple but use multi-word SHELLFLAGS
+
+if ($multi_ok) {
+ run_make_test(q!
+.ONESHELL:
+.SHELLFLAGS = -e -c
+all:
+ a=$$$$
+ [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+}
+
+# Again, but this time with inner prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+ a=$$$$
+ @-+ [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', 'a=$$
+[ 0"$a" -eq "$$" ] || echo fail
+');
+
+# This time with outer prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+ @a=$$$$
+ [ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', '');
+
+
+# This time with outer and inner prefix chars
+
+run_make_test(q!
+.ONESHELL:
+all:
+ @a=$$$$
+ -@ +[ 0"$$a" -eq "$$$$" ] || echo fail
+!,
+ '', '');
+
+
+# Now try using a different interpreter
+
+run_make_test(q!
+.RECIPEPREFIX = >
+.ONESHELL:
+SHELL = #PERL#
+.SHELLFLAGS = -e
+all:
+> @$$a=5
+> +7;
+> @y=qw(a b c);
+>print "a = $$a, y = (@y)\n";
+!,
+ '', "a = 12, y = (a b c)\n");
+
+1;
diff --git a/tests/scripts/targets/PHONY b/tests/scripts/targets/PHONY
new file mode 100644
index 0000000..c8e2110
--- /dev/null
+++ b/tests/scripts/targets/PHONY
@@ -0,0 +1,54 @@
+# -*-perl-*-
+
+$description = "The following tests the use of a PHONY target. It makes\n"
+ ."sure that the rules under a target get executed even if\n"
+ ."a filename of the same name of the target exists in the\n"
+ ."directory.\n";
+
+$details = "This makefile in this test declares the target clean to be a \n"
+ ."PHONY target. We then create a file named \"clean\" in the \n"
+ ."directory. Although this file exists, the rule under the target\n"
+ ."clean should still execute because of it's phony status.";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".PHONY : clean \n";
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This makefile did not clean the dir ... good\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command $example clean\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+# Create a file named "clean". This is the same name as the target clean
+# and tricks the target into thinking that it is up to date. (Unless you
+# use the .PHONY target.
+&touch("clean");
+
+$answer = "$delete_command $example clean\n";
+&run_make_with_options($makefile,"clean",&get_logfile);
+
+if (-f $example) {
+ $test_passed = 0;
+}
+
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/targets/POSIX b/tests/scripts/targets/POSIX
new file mode 100644
index 0000000..a24e3bc
--- /dev/null
+++ b/tests/scripts/targets/POSIX
@@ -0,0 +1,57 @@
+# -*-perl-*-
+
+$description = "Test the behaviour of the .POSIX target.";
+
+$details = "";
+
+
+# Ensure turning on .POSIX enables the -e flag for the shell
+# We can't assume the exit value of "false" because on different systems it's
+# different.
+
+my $script = 'false; true';
+my $flags = '-ec';
+my $out = `/bin/sh $flags '$script' 2>&1`;
+my $err = $? >> 8;
+run_make_test(qq!
+.POSIX:
+all: ; \@$script
+!,
+ '', "#MAKEFILE#:3: recipe for target 'all' failed
+#MAKE#: *** [all] Error $err\n", 512);
+
+# User settings must override .POSIX
+$flags = '-xc';
+$out = `/bin/sh $flags '$script' 2>&1`;
+run_make_test(qq!
+.SHELLFLAGS = $flags
+.POSIX:
+all: ; \@$script
+!,
+ '', $out);
+
+# Test the default value of various POSIX-specific variables
+my %POSIX = (AR => 'ar', ARFLAGS => '-rv',
+ YACC => 'yacc', YFLAGS => '',
+ LEX => 'lex', LFLAGS => '',
+ LDFLAGS => '',
+ CC => 'c99', CFLAGS => '-O',
+ FC => 'fort77', FFLAGS => '-O 1',
+ GET => 'get', GFLAGS => '',
+ SCCSFLAGS => '', SCCSGETFLAGS => '-s');
+my $make = join('', map { "\t\@echo '$_=\$($_)'\n" } sort keys %POSIX);
+my $r = join('', map { "$_=$POSIX{$_}\n"} sort keys %POSIX);
+run_make_test(qq!
+.POSIX:
+all:
+$make
+!,
+ '', $r);
+
+# Make sure that local settings take precedence
+%extraENV = map { $_ => "xx-$_" } keys %POSIX;
+$r = join('', map { "$_=xx-$_\n"} sort keys %POSIX);
+run_make_test(undef, '', $r);
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/targets/SECONDARY b/tests/scripts/targets/SECONDARY
new file mode 100644
index 0000000..447c275
--- /dev/null
+++ b/tests/scripts/targets/SECONDARY
@@ -0,0 +1,190 @@
+#! -*-perl-*-
+
+$description = "Test the behaviour of the .SECONDARY target.";
+
+$details = "\
+Test the behavior of the .SECONDARY special target.
+Create a makefile where a file would not normally be considered
+intermediate, then specify it as .SECONDARY. Build and note that it's
+not automatically deleted. Delete the file. Rebuild to ensure that
+it's not created if it doesn't exist but doesn't need to be built.
+Change the original and ensure that the secondary file and the ultimate
+target are both rebuilt, and that the secondary file is not deleted.
+
+Try this with implicit rules and explicit rules: both should work.\n";
+
+open(MAKEFILE,"> $makefile");
+
+print MAKEFILE <<'EOF';
+
+.SECONDARY: foo.e
+
+# Implicit rule test
+%.d : %.e ; cp $< $@
+%.e : %.f ; cp $< $@
+
+foo.d: foo.e
+
+# Explicit rule test
+foo.c: foo.e ; cp $< $@
+EOF
+
+close(MAKEFILE);
+
+# TEST #1
+
+&utouch(-20, 'foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2
+
+unlink('foo.e');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "$make_name: 'foo.d' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #3
+
+&utouch(-10, 'foo.d');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.d',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.d\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #4
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.e foo.c\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #5
+
+unlink('foo.e');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "$make_name: 'foo.c' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #6
+
+&utouch(-10, 'foo.c');
+&touch('foo.f');
+
+&run_make_with_options($makefile,'foo.c',&get_logfile);
+$answer = "cp foo.f foo.e\ncp foo.e foo.c\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('foo.f', 'foo.e', 'foo.d', 'foo.c');
+
+# TEST #7 -- test the "global" .SECONDARY, with no targets.
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+
+print MAKEFILE <<'EOF';
+.SECONDARY:
+
+final: intermediate
+intermediate: source
+
+final intermediate source:
+ echo $< > $@
+EOF
+
+close(MAKEFILE);
+
+&utouch(-10, 'source');
+touch('final');
+
+&run_make_with_options($makefile2, '', &get_logfile);
+$answer = "$make_name: 'final' is up to date.\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink('source', 'final', 'intermediate');
+
+
+# TEST #8 -- test the "global" .SECONDARY, with .PHONY.
+
+touch('version2');
+run_make_test('
+.PHONY: version
+.SECONDARY:
+version2: version ; @echo GOOD
+all: version2',
+ 'all', 'GOOD');
+
+unlink('version2');
+
+# TEST #9 -- Savannah bug #15919
+# The original fix for this bug caused a new bug, shown here.
+
+touch(qw(1.a 2.a));
+
+run_make_test('
+%.c : %.b ; cp $< $@
+%.b : %.a ; cp $< $@
+all : 1.c 2.c
+2.a: 1.c', '-rR -j',
+'cp 1.a 1.b
+cp 1.b 1.c
+cp 2.a 2.b
+cp 2.b 2.c
+rm 1.b 2.b');
+
+unlink(qw(1.a 2.a 1.c 2.c));
+
+# TEST #10 -- Savannah bug #15919
+touch('test.0');
+run_make_test('
+.SECONDARY : test.1 test.2 test.3
+
+test : test.4
+
+%.4 : %.int %.3 ; touch $@
+
+%.int : %.3 %.2 ; touch $@
+
+%.3 : | %.2 ; touch $@
+
+%.2 : %.1 ; touch $@
+
+%.1 : %.0 ; touch $@', '-rR -j 2',
+'touch test.1
+touch test.2
+touch test.3
+touch test.int
+touch test.4
+rm test.int');
+
+# After a touch of test.0 it should give the same output, except we don't need
+# to rebuild test.3 (order-only)
+sleep(1);
+touch('test.0');
+run_make_test(undef, '-rR -j 2',
+'touch test.1
+touch test.2
+touch test.int
+touch test.4
+rm test.int');
+
+# With both test.0 and test.3 updated it should still build everything except
+# test.3
+sleep(1);
+touch('test.0', 'test.3');
+run_make_test(undef, '-rR -j 2',
+'touch test.1
+touch test.2
+touch test.int
+touch test.4
+rm test.int');
+
+unlink(qw(test.0 test.1 test.2 test.3 test.4));
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/targets/SILENT b/tests/scripts/targets/SILENT
new file mode 100644
index 0000000..4bb0a0f
--- /dev/null
+++ b/tests/scripts/targets/SILENT
@@ -0,0 +1,42 @@
+# -*-perl-*-
+
+$description = "The following tests the special target .SILENT. By simply\n"
+ ."mentioning this as a target, it tells make not to print\n"
+ ."commands before executing them.";
+
+$details = "This test is the same as the clean test except that it should\n"
+ ."not echo its command before deleting the specified file.\n";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE ".SILENT : clean\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command EXAMPLE_FILE\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+$answer = "";
+&run_make_with_options($makefile,"clean",&get_logfile,0);
+if (-f $example) {
+ $test_passed = 0;
+}
+&compare_output($answer,&get_logfile(1));
+
+1;
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/targets/clean b/tests/scripts/targets/clean
new file mode 100644
index 0000000..b32c976
--- /dev/null
+++ b/tests/scripts/targets/clean
@@ -0,0 +1,50 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to delete a \n"
+ ."file in the directory. It tests to see if make will \n"
+ ."NOT execute the command unless the rule is given in \n"
+ ."the make command line.";
+
+$example = "EXAMPLE_FILE";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE "all: \n";
+print MAKEFILE "\t\@echo This makefile did not clean the dir... good\n";
+print MAKEFILE "clean: \n";
+print MAKEFILE "\t$delete_command EXAMPLE_FILE\n";
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+&touch($example);
+
+
+&run_make_with_options($makefile,"",&get_logfile,0);
+
+# Create the answer to what should be produced by this Makefile
+$answer = "This makefile did not clean the dir... good\n";
+
+&compare_output($answer,&get_logfile(1)) || &error ("abort");
+
+
+$answer = "$delete_command $example\n";
+&run_make_with_options($makefile,"clean",&get_logfile,0);
+if (-f $example) {
+ $test_passed = 0;
+}
+&compare_output($answer,&get_logfile(1)) || &error ("abort");
+
+1;
+
+
+
+
+
+
+
+
+
diff --git a/tests/scripts/test_template b/tests/scripts/test_template
new file mode 100644
index 0000000..3fd3f95
--- /dev/null
+++ b/tests/scripts/test_template
@@ -0,0 +1,29 @@
+# -*-perl-*-
+
+$description = "<FILL IN SHORT DESCRIPTION HERE>";
+$details = "<FILL IN DETAILS OF HOW YOU TEST WHAT YOU SAY YOU ARE TESTING>";
+
+# Run a make test. See the documentation of run_make_test() in
+# run_make_tests.pl, but briefly the first argument is a string with the
+# contents of a makefile to be tested, the second is a string containing the
+# arguments to be passed to the make invocation, the third is a string
+# containing the expected output. The fourth is the expected exit code for
+# make. If not specified, it's assumed that the make program should succeed
+# (exit with 0).
+
+run_make_test('Your test makefile goes here',
+ 'Arguments to pass to make go here',
+ 'Expected output from the invocation goes here');
+
+# There are various special tokens, options, etc. See the full documentation
+# in run_make_tests.pl.
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/variables/CURDIR b/tests/scripts/variables/CURDIR
new file mode 100644
index 0000000..ee7cacb
--- /dev/null
+++ b/tests/scripts/variables/CURDIR
@@ -0,0 +1,20 @@
+# -*-perl-*-
+
+$description = "This tests the CURDIR varaible.";
+
+$details = "Echo CURDIR both with and without -C. Also ensure overrides work.";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "all: ; \@echo \$(CURDIR)\n";
+close(MAKEFILE);
+
+
+# TEST #1
+# -------
+
+&run_make_with_options($makefile,"",&get_logfile);
+$answer = "$pwd\n";
+&compare_output($answer,&get_logfile(1));
+
+
+1;
diff --git a/tests/scripts/variables/DEFAULT_GOAL b/tests/scripts/variables/DEFAULT_GOAL
new file mode 100644
index 0000000..8188ce7
--- /dev/null
+++ b/tests/scripts/variables/DEFAULT_GOAL
@@ -0,0 +1,87 @@
+# -*-perl-*-
+$description = "Test the .DEFAULT_GOAL special variable.";
+
+$details = "";
+
+
+# Test #1: basic logic.
+#
+run_make_test('
+# Basics.
+#
+foo: ; @:
+
+ifneq ($(.DEFAULT_GOAL),foo)
+$(error )
+endif
+
+# Reset to empty.
+#
+.DEFAULT_GOAL :=
+
+bar: ; @:
+
+ifneq ($(.DEFAULT_GOAL),bar)
+$(error )
+endif
+
+# Change to a different goal.
+#
+
+.DEFAULT_GOAL := baz
+
+baz: ; @echo $@
+',
+'',
+'baz');
+
+
+# Test #2: unknown goal.
+#
+run_make_test('
+.DEFAULT_GOAL = foo
+',
+'',
+"#MAKE#: *** No rule to make target 'foo'. Stop.",
+512);
+
+
+# Test #3: more than one goal.
+#
+run_make_test('
+.DEFAULT_GOAL := foo bar
+',
+'',
+'#MAKE#: *** .DEFAULT_GOAL contains more than one target. Stop.',
+512);
+
+
+# Test #4: Savannah bug #12226.
+#
+run_make_test('
+define rule
+foo: ; @echo $$@
+endef
+
+define make-rule
+$(eval $(rule))
+endef
+
+$(call make-rule)
+
+',
+'',
+'foo');
+
+# TEST #5: .DEFAULT_GOAL containing just whitespace (Savannah bug #25697)
+
+run_make_test('
+N =
+.DEFAULT_GOAL = $N $N # Just whitespace
+
+foo: ; @echo "boo"
+',
+ '', "#MAKE#: *** No targets. Stop.\n", 512);
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/variables/GNUMAKEFLAGS b/tests/scripts/variables/GNUMAKEFLAGS
new file mode 100644
index 0000000..6e50794
--- /dev/null
+++ b/tests/scripts/variables/GNUMAKEFLAGS
@@ -0,0 +1,42 @@
+# -*-perl-*-
+
+$description = "Test proper behavior of GNUMAKEFLAGS";
+
+# Accept flags from GNUMAKEFLAGS as well as MAKEFLAGS
+# Results always go in MAKEFLAGS
+
+$extraENV{'GNUMAKEFLAGS'} = '-e -r -R';
+
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '', 'erR');
+
+# Long arguments mean everything is prefixed with "-"
+
+$extraENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace';
+
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '', "#MAKEFILE#:2: target 'all' does not exist
+echo erR --trace --no-print-directory
+erR --trace --no-print-directory");
+
+# Verify that re-exec / recursion doesn't duplicate flags from GNUMAKEFLAGS
+
+unlink('x.mk');
+
+$extraENV{GNUMAKEFLAGS} = '-Itst/bad';
+
+run_make_test(q!
+recurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all
+all: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS
+-include x.mk
+x.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@
+!,
+ "", "x.mk\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = w -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+unlink('x.mk');
+
+1;
diff --git a/tests/scripts/variables/INCLUDE_DIRS b/tests/scripts/variables/INCLUDE_DIRS
new file mode 100644
index 0000000..c9662e9
--- /dev/null
+++ b/tests/scripts/variables/INCLUDE_DIRS
@@ -0,0 +1,46 @@
+# -*-perl-*-
+$description = "Test the .INCLUDE_DIRS special variable.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+# Test #1: The content of .INCLUDE_DIRS depends on the platform for which
+# make was built. What we know for sure is that it shouldn't be
+# empty.
+#
+run_make_test('
+ifeq ($(.INCLUDE_DIRS),)
+$(warning .INCLUDE_DIRS is empty)
+endif
+
+.PHONY: all
+all:;@:
+',
+'',
+'');
+
+
+# Test #2: Make sure -I paths end up in .INCLUDE_DIRS.
+#
+run_make_test('
+ifeq ($(dir),)
+$(warning dir is empty)
+endif
+
+ifeq ($(filter $(dir),$(.INCLUDE_DIRS)),)
+$(warning .INCLUDE_DIRS does not contain $(dir))
+endif
+
+.PHONY: all
+all:;@:
+',
+"-I$dir dir=$dir",
+'');
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
diff --git a/tests/scripts/variables/LIBPATTERNS b/tests/scripts/variables/LIBPATTERNS
new file mode 100644
index 0000000..9182954
--- /dev/null
+++ b/tests/scripts/variables/LIBPATTERNS
@@ -0,0 +1,38 @@
+# -*-perl-*-
+
+$description = "Test .LIBPATTERNS special variable.";
+
+$details = "";
+
+# TEST 0: basics
+
+touch('mtest_foo.a');
+
+run_make_test('
+.LIBPATTERNS = mtest_%.a
+all: -lfoo ; @echo "build $@ from $<"
+',
+ '', "build all from mtest_foo.a\n");
+
+# TEST 1: Handle elements that are not patterns.
+
+run_make_test('
+.LIBPATTERNS = mtest_foo.a mtest_%.a
+all: -lfoo ; @echo "build $@ from $<"
+',
+ '', "#MAKE#: .LIBPATTERNS element 'mtest_foo.a' is not a pattern
+build all from mtest_foo.a\n");
+
+# TEST 2: target-specific override
+
+# Uncomment this when we add support, see Savannah bug #25703
+# run_make_test('
+# .LIBPATTERNS = mbad_%.a
+# all: .LIBPATTERNS += mtest_%.a
+# all: -lfoo ; @echo "build $@ from $<"
+# ',
+# '', "build all from mtest_foo.a\n");
+
+unlink('mtest_foo.a');
+
+1;
diff --git a/tests/scripts/variables/MAKE b/tests/scripts/variables/MAKE
new file mode 100644
index 0000000..dc62160
--- /dev/null
+++ b/tests/scripts/variables/MAKE
@@ -0,0 +1,24 @@
+# -*-perl-*-
+
+$description = "Test proper behavior of the MAKE variable";
+
+$details = "DETAILS";
+
+run_make_test(q!
+TMP := $(MAKE)
+MAKE := $(subst X=$(X),,$(MAKE))
+all:
+ @echo $(TMP)
+ $(MAKE) -f #MAKEFILE# foo
+
+foo:
+ @echo $(MAKE)
+!,
+ '',
+ "#MAKEPATH#\n#MAKEPATH# -f #MAKEFILE# foo\n"
+ . "#MAKE#[1]: Entering directory '#PWD#'\n"
+ . "#MAKEPATH#\n#MAKE#[1]: Leaving directory '#PWD#'\n");
+
+rmfiles("foo");
+
+1;
diff --git a/tests/scripts/variables/MAKECMDGOALS b/tests/scripts/variables/MAKECMDGOALS
new file mode 100644
index 0000000..879283b
--- /dev/null
+++ b/tests/scripts/variables/MAKECMDGOALS
@@ -0,0 +1,52 @@
+# -*-perl-*-
+
+$description = "Test the MAKECMDGOALS variable.";
+
+$details = "\
+We construct a makefile with various targets, all of which print out
+\$(MAKECMDGOALS), then call it different ways.";
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE "\
+.DEFAULT all:
+ \@echo \$(MAKECMDGOALS)
+";
+close(MAKEFILE);
+
+# TEST #1
+
+&run_make_with_options($makefile,
+ "",
+ &get_logfile,
+ 0);
+$answer = "\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST #2
+
+&run_make_with_options($makefile,
+ "all",
+ &get_logfile,
+ 0);
+$answer = "all\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# TEST #3
+
+&run_make_with_options($makefile,
+ "foo bar baz yaz",
+ &get_logfile,
+ 0);
+$answer = "foo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\n";
+&compare_output($answer,&get_logfile(1));
+
+
+# This tells the test driver that the perl test script executed properly.
+1;
+
+
+
+
+
+
diff --git a/tests/scripts/variables/MAKEFILES b/tests/scripts/variables/MAKEFILES
new file mode 100644
index 0000000..b23da8e
--- /dev/null
+++ b/tests/scripts/variables/MAKEFILES
@@ -0,0 +1,53 @@
+# -*-perl-*-
+
+$description = "Test the MAKEFILES variable.";
+
+$makefile2 = &get_tmpfile;
+$makefile3 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE 'all: ; @echo DEFAULT RULE: M2=$(M2) M3=$(M3)', "\n";
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE <<EOF;
+M2 = m2
+NDEF: ; \@echo RULE FROM MAKEFILE 2
+EOF
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile3");
+print MAKEFILE <<EOF;
+M3 = m3
+NDEF3: ; \@echo RULE FROM MAKEFILE 3
+EOF
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile, "MAKEFILES='$makefile2 $makefile3'",
+ &get_logfile);
+$answer = "DEFAULT RULE: M2=m2 M3=m3\n";
+&compare_output($answer,&get_logfile(1));
+
+# TEST 2: Verify that included makefiles don't set the default goal.
+# See Savannah bug #13401.
+
+create_file('xx-inc.mk', '
+include_goal: ; @echo $@
+include xx-ind.mk
+');
+
+create_file('xx-ind.mk', '
+indirect_goal: ; @echo $@
+');
+
+run_make_test(q!
+top: ; @echo $@
+!,
+ 'MAKEFILES=xx-inc.mk', "top\n");
+
+unlink(qw(xx-inc.mk xx-ind.mk));
+
+1;
diff --git a/tests/scripts/variables/MAKEFLAGS b/tests/scripts/variables/MAKEFLAGS
new file mode 100644
index 0000000..8a5d0f6
--- /dev/null
+++ b/tests/scripts/variables/MAKEFLAGS
@@ -0,0 +1,41 @@
+# -*-perl-*-
+
+$description = "Test proper behavior of MAKEFLAGS";
+
+$details = "DETAILS";
+
+# Normal flags aren't prefixed with "-"
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '-e -r -R', 'erR');
+
+# Long arguments mean everything is prefixed with "-"
+run_make_test(q!
+all: ; @echo $(MAKEFLAGS)
+!,
+ '--no-print-directory -e -r -R --trace', "#MAKEFILE#:2: target 'all' does not exist
+echo erR --trace --no-print-directory
+erR --trace --no-print-directory");
+
+
+# Recursive invocations of make should accumulate MAKEFLAGS values.
+# Savannah bug #2216
+run_make_test(q!
+MSG = Fails
+all:
+ @echo '$@: MAKEFLAGS=$(MAKEFLAGS)'
+ @MSG=Works $(MAKE) -e -f #MAKEFILE# jump
+jump:
+ @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
+ @$(MAKE) -f #MAKEFILE# print
+print:
+ @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)'
+.PHONY: all jump print
+!,
+ '--no-print-directory',
+ 'all: MAKEFLAGS= --no-print-directory
+jump Works: MAKEFLAGS=e --no-print-directory
+print Works: MAKEFLAGS=e --no-print-directory');
+
+1;
diff --git a/tests/scripts/variables/MAKELEVEL b/tests/scripts/variables/MAKELEVEL
new file mode 100644
index 0000000..96a4e74
--- /dev/null
+++ b/tests/scripts/variables/MAKELEVEL
@@ -0,0 +1,33 @@
+# -*-perl-*-
+
+$description = "The following test creates a makefile to test
+makelevels in Make. It prints \$(MAKELEVEL) and then
+prints the environment variable MAKELEVEL";
+
+open(MAKEFILE,"> $makefile");
+
+# The Contents of the MAKEFILE ...
+
+print MAKEFILE <<EOF;
+all:
+\t\@echo MAKELEVEL is \$(MAKELEVEL)
+\techo \$\$MAKELEVEL
+EOF
+
+# END of Contents of MAKEFILE
+
+close(MAKEFILE);
+
+# RUN MAKE
+
+&run_make_with_options($makefile,"",&get_logfile);
+
+# SET ANSWER
+
+$answer = "MAKELEVEL is 0\necho \$MAKELEVEL\n1\n";
+
+# COMPARE RESULTS
+
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/variables/MAKE_RESTARTS b/tests/scripts/variables/MAKE_RESTARTS
new file mode 100644
index 0000000..ef8e368
--- /dev/null
+++ b/tests/scripts/variables/MAKE_RESTARTS
@@ -0,0 +1,62 @@
+# -*-perl-*-
+
+$description = "Test the MAKE_RESTARTS variable.";
+
+# Test basic capability
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @touch $@
+',
+ '', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1');
+
+rmfiles('foo.x');
+
+# Test multiple restarts
+
+run_make_test('
+all: ; @:
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @echo "include bar.x" > $@
+bar.x: ; @touch $@
+',
+ '', 'MAKE_RESTARTS=
+#MAKEFILE#:4: foo.x: No such file or directory
+MAKE_RESTARTS=1
+foo.x:1: bar.x: No such file or directory
+MAKE_RESTARTS=2');
+
+rmfiles('foo.x', 'bar.x');
+
+# Test multiple restarts and make sure the variable is cleaned up
+
+run_make_test('
+recurse:
+ @echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS
+ @$(MAKE) -f #MAKEFILE# all
+all:
+ @echo all MAKE_RESTARTS=$$MAKE_RESTARTS
+$(info MAKE_RESTARTS=$(MAKE_RESTARTS))
+include foo.x
+foo.x: ; @echo "include bar.x" > $@
+bar.x: ; @touch $@
+',
+ '', "MAKE_RESTARTS=
+#MAKEFILE#:8: foo.x: No such file or directory
+MAKE_RESTARTS=1
+foo.x:1: bar.x: No such file or directory
+MAKE_RESTARTS=2
+recurse MAKE_RESTARTS=
+#MAKE#[1]: Entering directory '#PWD#'
+MAKE_RESTARTS=
+all MAKE_RESTARTS=
+#MAKE#[1]: Leaving directory '#PWD#'");
+
+rmfiles('foo.x', 'bar.x');
+
+1;
diff --git a/tests/scripts/variables/MFILE_LIST b/tests/scripts/variables/MFILE_LIST
new file mode 100644
index 0000000..076e42d
--- /dev/null
+++ b/tests/scripts/variables/MFILE_LIST
@@ -0,0 +1,30 @@
+# -*-perl-*-
+
+$description = "Test the MAKEFILE_LIST variable.";
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE,"> $makefile");
+print MAKEFILE <<EOF;
+m1 := \$(MAKEFILE_LIST)
+include $makefile2
+m3 := \$(MAKEFILE_LIST)
+
+all:
+\t\@echo \$(m1)
+\t\@echo \$(m2)
+\t\@echo \$(m3)
+EOF
+close(MAKEFILE);
+
+
+open(MAKEFILE,"> $makefile2");
+print MAKEFILE "m2 := \$(MAKEFILE_LIST)\n";
+close(MAKEFILE);
+
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "$makefile\n$makefile $makefile2\n$makefile $makefile2\n";
+&compare_output($answer,&get_logfile(1));
+
+1;
diff --git a/tests/scripts/variables/SHELL b/tests/scripts/variables/SHELL
new file mode 100644
index 0000000..1d01ba3
--- /dev/null
+++ b/tests/scripts/variables/SHELL
@@ -0,0 +1,103 @@
+# -*-perl-*-
+
+$description = "Test proper handling of SHELL.";
+
+# Find the default value when SHELL is not set. On UNIX it will be /bin/sh,
+# but on other platforms who knows?
+resetENV();
+delete $ENV{SHELL};
+$mshell = `echo 'all:;\@echo \$(SHELL)' | $make_path -f-`;
+chop $mshell;
+
+# According to POSIX, the value of SHELL in the environment has no impact on
+# the value in the makefile.
+# Note %extraENV takes precedence over the default value for the shell.
+
+$extraENV{SHELL} = '/dev/null';
+run_make_test('all:;@echo "$(SHELL)"', '', $mshell);
+
+# According to POSIX, any value of SHELL set in the makefile should _NOT_ be
+# exported to the subshell! I wanted to set SHELL to be $^X (perl) in the
+# makefile, but make runs $(SHELL) -c 'commandline' and that doesn't work at
+# all when $(SHELL) is perl :-/. So, we just add an extra initial /./ which
+# works well on UNIX and seems to work OK on at least some non-UNIX systems.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell $mshell");
+
+# As a GNU make extension, if make's SHELL variable is explicitly exported,
+# then we really _DO_ export it.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("export SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell /./$mshell");
+
+
+# Test out setting of SHELL, both exported and not, as a target-specific
+# variable.
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("all: SHELL := /./$mshell\n".'
+all:;@echo "$(SHELL) $$SHELL"
+', '', "/./$mshell $mshell");
+
+$extraENV{SHELL} = $mshell;
+
+run_make_test("
+SHELL := /././$mshell
+one: two
+two: export SHELL := /./$mshell\n".'
+one two:;@echo "$@: $(SHELL) $$SHELL"
+', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n");
+
+# Test .SHELLFLAGS
+
+# We don't know the output here: on Solaris for example, every line printed
+# by the shell in -x mode has a trailing space (!!)
+my $script = 'true; true';
+my $flags = '-xc';
+my $out = `/bin/sh $flags '$script' 2>&1`;
+
+run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+ '', $out);
+
+# Do it again but add spaces to SHELLFLAGS
+
+# Some shells (*shakes fist at Solaris*) cannot handle multiple flags in
+# separate arguments.
+my $t = `/bin/sh -e -c true 2>/dev/null`;
+my $multi_ok = $? == 0;
+
+if ($multi_ok) {
+ $flags = '-x -c';
+ run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+ '', $out);
+}
+
+# We can't just use "false" because on different systems it provides a
+# different exit code--once again Solaris: false exits with 255 not 1
+$script = 'true; false; true';
+$flags = '-xec';
+$out = `/bin/sh $flags '$script' 2>&1`;
+my $err = $? >> 8;
+
+run_make_test(qq!
+.SHELLFLAGS = $flags
+all: ; \@$script
+!,
+ '', "$out#MAKEFILE#:3: recipe for target 'all' failed
+#MAKE#: *** [all] Error $err\n", 512);
+
+1;
diff --git a/tests/scripts/variables/automatic b/tests/scripts/variables/automatic
new file mode 100644
index 0000000..33c482d
--- /dev/null
+++ b/tests/scripts/variables/automatic
@@ -0,0 +1,122 @@
+# -*-perl-*-
+
+$description = "Test automatic variable setting.";
+
+$details = "";
+
+use Cwd;
+
+$dir = cwd;
+$dir =~ s,.*/([^/]+)$,../$1,;
+
+open(MAKEFILE, "> $makefile");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SUFFIXES:
+.SUFFIXES: .x .y .z
+$(dir)/foo.x : baz.z $(dir)/bar.y baz.z
+ @echo '$$@ = $@, $$(@D) = $(@D), $$(@F) = $(@F)'
+ @echo '$$* = $*, $$(*D) = $(*D), $$(*F) = $(*F)'
+ @echo '$$< = $<, $$(<D) = $(<D), $$(<F) = $(<F)'
+ @echo '$$^ = $^, $$(^D) = $(^D), $$(^F) = $(^F)'
+ @echo '$$+ = $+, $$(+D) = $(+D), $$(+F) = $(+F)'
+ @echo '$$? = $?, $$(?D) = $(?D), $$(?F) = $(?F)'
+ touch $@
+
+$(dir)/bar.y baz.z : ; touch $@
+EOF
+close(MAKEFILE);
+
+# TEST #0 -- simple test
+# -------
+
+# Touch these into the past
+&utouch(-10, qw(foo.x baz.z));
+
+&run_make_with_options($makefile, "", &get_logfile);
+$answer = "touch $dir/bar.y
+\$\@ = $dir/foo.x, \$(\@D) = $dir, \$(\@F) = foo.x
+\$* = $dir/foo, \$(*D) = $dir, \$(*F) = foo
+\$< = baz.z, \$(<D) = ., \$(<F) = baz.z
+\$^ = baz.z $dir/bar.y, \$(^D) = . $dir, \$(^F) = baz.z bar.y
+\$+ = baz.z $dir/bar.y baz.z, \$(+D) = . $dir ., \$(+F) = baz.z bar.y baz.z
+\$? = $dir/bar.y, \$(?D) = $dir, \$(?F) = bar.y
+touch $dir/foo.x\n";
+&compare_output($answer, &get_logfile(1));
+
+unlink(qw(foo.x bar.y baz.z));
+
+# TEST #1 -- test the SysV emulation of $$@ etc.
+# -------
+
+$makefile2 = &get_tmpfile;
+
+open(MAKEFILE, "> $makefile2");
+print MAKEFILE "dir = $dir\n";
+print MAKEFILE <<'EOF';
+.SECONDEXPANSION:
+.SUFFIXES:
+.DEFAULT: ; @echo '$@'
+
+$(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x
+
+$(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).%
+
+$(dir)/biz: $$(@).x $${@}.x $${@D}.x $${@F}.x
+EOF
+
+close(MAKEFILE);
+
+&run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile);
+$answer = ".x\n$dir/foo.x\nx\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile);
+$answer = ".x\n$dir/x.z.x\nx\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\y\n\$@.y\n$dir.y\ny.z.y\n";
+&compare_output($answer, &get_logfile(1));
+
+&run_make_with_options($makefile2, "$dir/biz", &get_logfile);
+$answer = "$dir/biz.x\n$dir.x\nbiz.x\n";
+&compare_output($answer, &get_logfile(1));
+
+# TEST #2 -- test for Savannah bug #12320.
+#
+run_make_test('
+.SUFFIXES: .b .src
+
+mbr.b: mbr.src
+ @echo $*
+
+mbr.src: ; @:',
+ '',
+ 'mbr');
+
+# TEST #3 -- test for Savannah bug #8154
+# Make sure that nonexistent prerequisites are listed in $?, since they are
+# considered reasons for the target to be rebuilt.
+#
+# See also Savannah bugs #16002 and #16051.
+
+touch('foo');
+
+run_make_test('
+foo: bar ; @echo "\$$? = $?"
+bar: ;',
+ '',
+ '$? = bar');
+
+unlink('foo');
+
+# TEST #4: ensure prereq ordering is correct when the commmand target has none
+# See Savannah bug #21198
+
+run_make_test('
+all : A B
+all : ; @echo $@ -- $^ -- $<
+all : C D
+all : E F
+A B C D E F G H : ; @:
+',
+ '', "all -- A B C D E F -- A\n");
+
+1;
diff --git a/tests/scripts/variables/define b/tests/scripts/variables/define
new file mode 100644
index 0000000..7324cbc
--- /dev/null
+++ b/tests/scripts/variables/define
@@ -0,0 +1,282 @@
+# -*-perl-*-
+
+$description = "Test define/endef variable assignments.";
+
+$details = "";
+
+# TEST 0: old-style basic define/endef
+
+run_make_test('
+define multi
+@echo hi
+echo there
+endef
+
+all: ; $(multi)
+',
+ '', "hi\necho there\nthere\n");
+
+# TEST 1: Various new-style define/endef
+
+run_make_test('
+FOO = foo
+
+define multi =
+echo hi
+@echo $(FOO)
+endef # this is the end
+
+define simple :=
+@echo $(FOO)
+endef
+
+define posix ::=
+@echo $(FOO)
+endef
+
+append = @echo a
+
+define append +=
+
+@echo b
+endef
+
+define cond ?= # this is a conditional
+@echo first
+endef
+
+define cond ?=
+@echo second
+endef
+
+FOO = there
+
+all: ; $(multi)
+ $(simple)
+ $(posix)
+ $(append)
+ $(cond)
+',
+ '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
+
+# TEST 1a: Various new-style define/endef, with no spaces
+
+run_make_test('
+FOO = foo
+
+define multi=
+echo hi
+@echo $(FOO)
+endef # this is the end
+
+define simple:=
+@echo $(FOO)
+endef
+
+define posix::=
+@echo $(FOO)
+endef
+
+append = @echo a
+
+define append+=
+
+@echo b
+endef
+
+define cond?= # this is a conditional
+@echo first
+endef
+
+define cond?=
+@echo second
+endef
+
+FOO = there
+
+all: ; $(multi)
+ $(simple)
+ $(posix)
+ $(append)
+ $(cond)
+',
+ '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n");
+
+# TEST 2: define in true section of conditional (containing conditional)
+
+run_make_test('
+FOO = foo
+NAME = def
+def =
+ifdef BOGUS
+ define $(subst e,e,$(NAME)) =
+ ifeq (1,1)
+ FOO = bar
+ endif
+ endef
+endif
+
+$(eval $(def))
+all: ; @echo $(FOO)
+',
+ 'BOGUS=1', "bar\n");
+
+# TEST 3: define in false section of conditional (containing conditional)
+
+run_make_test(undef, '', "foo\n");
+
+# TEST 4: nested define (supported?)
+
+run_make_test('
+define outer
+ define inner
+ A = B
+ endef
+endef
+
+$(eval $(outer))
+
+outer: ; @echo $(inner)
+',
+ '', "A = B\n");
+
+# TEST 5: NEGATIVE: Missing variable name
+
+run_make_test('
+NAME =
+define $(NAME) =
+ouch
+endef
+all: ; @echo ouch
+',
+ '', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512);
+
+# TEST 6: NEGATIVE: extra text after define
+
+run_make_test('
+NAME =
+define NAME = $(NAME)
+ouch
+endef
+all: ; @echo ok
+',
+ '', "#MAKEFILE#:3: extraneous text after 'define' directive\nok\n");
+
+# TEST 7: NEGATIVE: extra text after endef
+
+run_make_test('
+NAME =
+define NAME =
+ouch
+endef $(NAME)
+all: ; @echo ok
+',
+ '', "#MAKEFILE#:5: extraneous text after 'endef' directive\nok\n");
+
+# TEST 8: NEGATIVE: missing endef
+
+run_make_test('
+NAME =
+all: ; @echo ok
+define NAME =
+ouch
+endef$(NAME)
+',
+ '', "#MAKEFILE#:4: *** missing 'endef', unterminated 'define'. Stop.\n", 512);
+
+# -------------------------
+# Make sure that prefix characters apply properly to define/endef values.
+#
+# There's a bit of oddness here if you try to use a variable to hold the
+# prefix character for a define. Even though something like this:
+#
+# define foo
+# echo bar
+# endef
+#
+# all: ; $(V)$(foo)
+#
+# (where V=@) can be seen by the user to be obviously different than this:
+#
+# define foo
+# $(V)echo bar
+# endef
+#
+# all: ; $(foo)
+#
+# and the user thinks it should behave the same as when the "@" is literal
+# instead of in a variable, that can't happen because by the time make
+# expands the variables for the command line and sees it begins with a "@" it
+# can't know anymore whether the prefix character came before the variable
+# reference or was included in the first line of the variable reference.
+
+# TEST #5
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; @$(FOO)
+', '', 'hello
+world');
+
+# TEST #6
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #7
+# -------
+
+run_make_test('
+define FOO
+$(V1)echo hello
+$(V2)echo world
+endef
+all: ; $(FOO)
+', 'V1=@', 'hello
+echo world
+world');
+
+# TEST #8
+# -------
+
+run_make_test(undef, 'V2=@', 'echo hello
+hello
+world');
+
+# TEST #9
+# -------
+
+run_make_test(undef, 'V1=@ V2=@', 'hello
+world');
+
+# TEST #10
+# -------
+# Test the basics; a "@" internally to the variable applies to only one line.
+# A "@" before the variable applies to the entire variable.
+
+run_make_test('
+define FOO
+@echo hello
+echo world
+endef
+define BAR
+echo hello
+echo world
+endef
+
+all: foo bar
+foo: ; $(FOO)
+bar: ; @$(BAR)
+', '', 'hello
+echo world
+world
+hello
+world
+');
+
+1;
diff --git a/tests/scripts/variables/flavors b/tests/scripts/variables/flavors
new file mode 100644
index 0000000..ba133ea
--- /dev/null
+++ b/tests/scripts/variables/flavors
@@ -0,0 +1,96 @@
+# -*-perl-*-
+
+$description = "Test various flavors of make variable setting.";
+
+$details = "";
+
+# TEST 0: Recursive
+
+run_make_test('
+ugh = Goodbye
+foo = $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Hello\n");
+
+# TEST 1: Simple
+
+run_make_test('
+bar = Goodbye
+foo := $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye\n");
+
+# TEST 2: Append to recursive
+
+run_make_test('
+foo = Hello
+ugh = Goodbye
+foo += $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Hello Hello\n");
+
+# TEST 3: Append to simple
+
+run_make_test('
+foo := Hello
+ugh = Goodbye
+bar = ${ugh}
+foo += $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Hello Goodbye\n");
+
+# TEST 4: Conditional pre-set
+
+run_make_test('
+foo = Hello
+ugh = Goodbye
+bar = ${ugh}
+foo ?= $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Hello\n");
+
+# TEST 5: Conditional unset
+
+run_make_test('
+ugh = Goodbye
+bar = ${ugh}
+foo ?= $(bar)
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Hello\n");
+
+# TEST 6: Simple using POSIX syntax
+run_make_test('
+bar = Goodbye
+foo ::= $(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye\n");
+
+# TEST 7: POSIX syntax no spaces
+run_make_test('
+bar = Goodbye
+foo::=$(bar)
+bar = ${ugh}
+ugh = Hello
+all: ; @echo $(foo)
+',
+ '', "Goodbye\n");
+
+1;
diff --git a/tests/scripts/variables/negative b/tests/scripts/variables/negative
new file mode 100644
index 0000000..16a72b8
--- /dev/null
+++ b/tests/scripts/variables/negative
@@ -0,0 +1,46 @@
+# -*-perl-*-
+
+$description = "Run some negative tests (things that should fail).";
+
+# TEST #0
+# Check that non-terminated variable references are detected (and
+# reported using the best filename/lineno info
+run_make_test('
+foo = bar
+x = $(foo
+y = $x
+
+all: ; @echo $y
+',
+ '', '#MAKEFILE#:3: *** unterminated variable reference. Stop.',
+ 512);
+
+# TEST #1
+# Bogus variable value passed on the command line.
+run_make_test(undef,
+ 'x=\$\(other',
+ '#MAKEFILE#:4: *** unterminated variable reference. Stop.',
+ 512);
+
+# TEST #2
+# Again, but this time while reading the makefile.
+run_make_test('
+foo = bar
+x = $(foo
+y = $x
+
+z := $y
+
+all: ; @echo $y
+',
+ '', '#MAKEFILE#:3: *** unterminated variable reference. Stop.',
+ 512);
+
+# TEST #3
+# Bogus variable value passed on the command line.
+run_make_test(undef,
+ 'x=\$\(other',
+ '#MAKEFILE#:4: *** unterminated variable reference. Stop.',
+ 512);
+
+1;
diff --git a/tests/scripts/variables/private b/tests/scripts/variables/private
new file mode 100644
index 0000000..8967ffb
--- /dev/null
+++ b/tests/scripts/variables/private
@@ -0,0 +1,122 @@
+# -*-perl-*-
+
+$description = "Test 'private' variables.";
+
+$details = "";
+
+# 1: Simple verification that private variables are not inherited
+&run_make_test('
+a:
+F = g
+a: F = a
+b: private F = b
+
+a b c: ; @echo $@: F=$(F)
+a: b
+b: c
+',
+ '', "c: F=a\nb: F=b\na: F=a\n");
+
+# 2: Again, but this time we start with "b" so "a"'s variable is not in scope
+&run_make_test(undef, 'b', "c: F=g\nb: F=b\n");
+
+# 3: Verification with pattern-specific variables
+&run_make_test('
+t.a:
+
+F1 = g
+F2 = g
+%.a: private F1 = a
+%.a: F2 = a
+
+t.a t.b: ; @echo $@: F1=$(F1) / F2=$(F2)
+t.a: t.b
+',
+ '', "t.b: F1=g / F2=a\nt.a: F1=a / F2=a\n");
+
+# 4: Test private global variables
+&run_make_test('
+a:
+private F = g
+G := $(F)
+a:
+b: F = b
+
+a b: ; @echo $@: F=$(F) / G=$(G)
+a: b
+',
+ '', "b: F=b / G=g\na: F= / G=g\n");
+
+# 5: Multiple conditions on the same variable. Test export.
+delete $ENV{'_X'};
+&run_make_test('
+_X = x
+a: export override private _X = a
+a: ; @echo _X=$(_X) / _X=$$_X
+',
+ '', "_X=a / _X=a");
+
+# 6: Test override.
+&run_make_test(undef, '_X=c', "_X=a / _X=a\n");
+
+# 7: Ensure keywords still work as targets
+&run_make_test('
+a: export override private foo bar
+foo bar export override private: ; @echo $@
+',
+ '', "export\noverride\nprivate\nfoo\nbar\n");
+
+# 8: Ensure keywords still work as variables
+&run_make_test('
+private = g
+a: private = a
+a: b
+a b: ; @echo $@=$(private)
+',
+ '', "b=a\na=a\n");
+
+# 9: make sure private suppresses inheritance
+run_make_test(q!
+DEFS = FOO
+all: bar1
+bar1: private DEFS += 1
+bar3: private DEFS += 3
+bar1: bar2
+bar2: bar3
+bar1 bar2 bar3: ; @echo '$@: $(DEFS)'
+!,
+ '', "bar3: FOO 3\nbar2: FOO\nbar1: FOO 1\n");
+
+# 10: Test append with pattern-specific variables and private
+
+run_make_test(q!
+IA = global
+PA = global
+PS = global
+S = global
+PS = global
+SV = global
+b%: IA += b%
+b%: private PA += b%
+b%: private PS = b%
+bar: all
+bar: IA += bar
+bar: private PA += bar
+bar: private PS = bar
+a%: IA += a%
+a%: private PA += a%
+a%: private PS = a%
+all: IA += all
+all: private PA += all
+all: private PS = all
+
+bar all: ; @echo '$@: IA=$(IA)'; echo '$@: PA=$(PA)'; echo '$@: PS=$(PS)'
+!,
+ '', "all: IA=global b% bar a% all
+all: PA=global a% all
+all: PS=all
+bar: IA=global b% bar
+bar: PA=global b% bar
+bar: PS=bar\n");
+
+1;
diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special
new file mode 100644
index 0000000..a5ab93a
--- /dev/null
+++ b/tests/scripts/variables/special
@@ -0,0 +1,141 @@
+# -*-perl-*-
+
+$description = "Test special GNU make variables.";
+
+$details = "";
+
+&run_make_test('
+
+X1 := $(sort $(filter FOO BAR,$(.VARIABLES)))
+
+FOO := foo
+
+X2 := $(sort $(filter FOO BAR,$(.VARIABLES)))
+
+BAR := bar
+
+all:
+ @echo X1 = $(X1)
+ @echo X2 = $(X2)
+ @echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES)))
+',
+ '', "X1 =\nX2 = FOO\nLAST = BAR FOO\n");
+
+
+
+# $makefile2 = &get_tmpfile;
+# open(MAKEFILE, "> $makefile2");
+
+# print MAKEFILE <<'EOF';
+
+# X1 := $(sort $(.TARGETS))
+
+# all: foo
+# @echo X1 = $(X1)
+# @echo X2 = $(X2)
+# @echo LAST = $(sort $(.TARGETS))
+
+# X2 := $(sort $(.TARGETS))
+
+# foo:
+
+# EOF
+
+# close(MAKEFILE);
+
+# # TEST #2
+# # -------
+
+# &run_make_with_options($makefile2, "", &get_logfile);
+# $answer = "X1 =\nX2 = all\nLAST = all foo\n";
+# &compare_output($answer, &get_logfile(1));
+
+# Test the .RECIPEPREFIX variable
+&run_make_test('
+define foo
+: foo-one\
+foo-two
+: foo-three
+ : foo-four
+endef
+
+orig: ; : orig-one
+ : orig-two \
+orig-three \
+ orig-four \
+ orig-five \\\\
+ : orig-six
+ $(foo)
+
+.RECIPEPREFIX = >
+test: ; : test-one
+>: test-two \
+test-three \
+>test-four \
+> test-five \\\\
+>: test-six
+>$(foo)
+
+.RECIPEPREFIX =
+reset: ; : reset-one
+ : reset-two \
+reset-three \
+ reset-four \
+ reset-five \\\\
+ : reset-six
+ $(foo)
+',
+ 'orig test reset',
+ ': orig-one
+: orig-two \
+orig-three \
+orig-four \
+ orig-five \\\\
+: orig-six
+: foo-one foo-two
+: foo-three
+: foo-four
+: test-one
+: test-two \
+test-three \
+test-four \
+ test-five \\\\
+: test-six
+: foo-one foo-two
+: foo-three
+: foo-four
+: reset-one
+: reset-two \
+reset-three \
+reset-four \
+ reset-five \\\\
+: reset-six
+: foo-one foo-two
+: foo-three
+: foo-four');
+
+# Test that the "did you mean TAB" message is printed properly
+
+run_make_test(q!
+$x.
+!,
+ '', '#MAKEFILE#:2: *** missing separator. Stop.', 512);
+
+run_make_test(q!
+foo:
+ bar
+!,
+ '', '#MAKEFILE#:3: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.', 512);
+
+run_make_test(q!
+.RECIPEPREFIX = :
+foo:
+ bar
+!,
+ '', '#MAKEFILE#:4: *** missing separator. Stop.', 512);
+
+1;
+
+### Local Variables:
+### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action))
+### End:
diff --git a/tests/scripts/variables/undefine b/tests/scripts/variables/undefine
new file mode 100644
index 0000000..38707b8
--- /dev/null
+++ b/tests/scripts/variables/undefine
@@ -0,0 +1,73 @@
+# -*-perl-*-
+
+$description = "Test variable undefine.";
+
+$details = "";
+
+# TEST 0: basic undefine functionality
+
+run_make_test('
+a = a
+b := b
+define c
+c
+endef
+
+$(info $(flavor a) $(flavor b) $(flavor c))
+
+n := b
+
+undefine a
+undefine $n
+undefine c
+
+$(info $(flavor a) $(flavor b) $(flavor c))
+
+
+all: ;@:
+',
+'', "recursive simple recursive\nundefined undefined undefined");
+
+
+# TEST 1: override
+
+run_make_test('
+undefine a
+override undefine b
+
+$(info $(flavor a) $(flavor b))
+
+
+all: ;@:
+',
+'a=a b=b', "recursive undefined");
+
+1;
+
+# TEST 2: undefine in eval (make sure we undefine from the global var set)
+
+run_make_test('
+define undef
+$(eval undefine $$1)
+endef
+
+a := a
+$(call undef,a)
+$(info $(flavor a))
+
+
+all: ;@:
+',
+'', "undefined");
+
+
+# TEST 3: Missing variable name
+
+run_make_test('
+a =
+undefine $a
+all: ;@echo ouch
+',
+'', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512);
+
+1;
diff --git a/tests/test_driver.pl b/tests/test_driver.pl
new file mode 100644
index 0000000..91141eb
--- /dev/null
+++ b/tests/test_driver.pl
@@ -0,0 +1,1474 @@
+#!/usr/bin/perl
+# -*-perl-*-
+#
+# Modification history:
+# Written 91-12-02 through 92-01-01 by Stephen McGee.
+# Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize.
+#
+# Copyright (C) 1991-2014 Free Software Foundation, Inc.
+# This file is part of GNU Make.
+#
+# GNU Make is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3 of the License, or (at your option) any later
+# version.
+#
+# GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# Test driver routines used by a number of test suites, including
+# those for SCS, make, roll_dir, and scan_deps (?).
+#
+# this routine controls the whole mess; each test suite sets up a few
+# variables and then calls &toplevel, which does all the real work.
+
+# $Id$
+
+
+# The number of test categories we've run
+$categories_run = 0;
+# The number of test categroies that have passed
+$categories_passed = 0;
+# The total number of individual tests that have been run
+$total_tests_run = 0;
+# The total number of individual tests that have passed
+$total_tests_passed = 0;
+# The number of tests in this category that have been run
+$tests_run = 0;
+# The number of tests in this category that have passed
+$tests_passed = 0;
+
+
+# Yeesh. This whole test environment is such a hack!
+$test_passed = 1;
+
+# Timeout in seconds. If the test takes longer than this we'll fail it.
+$test_timeout = 5;
+$test_timeout = 10 if $^O eq 'VMS';
+
+# Path to Perl
+$perl_name = $^X;
+
+# %makeENV is the cleaned-out environment.
+%makeENV = ();
+
+# %extraENV are any extra environment variables the tests might want to set.
+# These are RESET AFTER EVERY TEST!
+%extraENV = ();
+
+sub vms_get_process_logicals {
+ # Sorry for the long note here, but to keep this test running on
+ # VMS, it is needed to be understood.
+ #
+ # Perl on VMS by default maps the %ENV array to the system wide logical
+ # name table.
+ #
+ # This is a very large dynamically changing table.
+ # On Linux, this would be the equivalent of a table that contained
+ # every mount point, temporary pipe, and symbolic link on every
+ # file system. You normally do not have permission to clear or replace it,
+ # and if you did, the results would be catastrophic.
+ #
+ # On VMS, added/changed %ENV items show up in the process logical
+ # name table. So to track changes, a copy of it needs to be captured.
+
+ my $raw_output = `show log/process/access_mode=supervisor`;
+ my @raw_output_lines = split('\n',$raw_output);
+ my %log_hash;
+ foreach my $line (@raw_output_lines) {
+ if ($line =~ /^\s+"([A-Za-z\$_]+)"\s+=\s+"(.+)"$/) {
+ $log_hash{$1} = $2;
+ }
+ }
+ return \%log_hash
+}
+
+# %origENV is the caller's original environment
+if ($^O ne 'VMS') {
+ %origENV = %ENV;
+} else {
+ my $proc_env = vms_get_process_logicals;
+ %origENV = %{$proc_env};
+}
+
+sub resetENV
+{
+ # We used to say "%ENV = ();" but this doesn't work in Perl 5.000
+ # through Perl 5.004. It was fixed in Perl 5.004_01, but we don't
+ # want to require that here, so just delete each one individually.
+
+ if ($^O ne 'VMS') {
+ foreach $v (keys %ENV) {
+ delete $ENV{$v};
+ }
+
+ %ENV = %makeENV;
+ } else {
+ my $proc_env = vms_get_process_logicals();
+ my %delta = %{$proc_env};
+ foreach my $v (keys %delta) {
+ if (exists $origENV{$v}) {
+ if ($origENV{$v} ne $delta{$v}) {
+ $ENV{$v} = $origENV{$v};
+ }
+ } else {
+ delete $ENV{$v};
+ }
+ }
+ }
+
+ foreach $v (keys %extraENV) {
+ $ENV{$v} = $extraENV{$v};
+ delete $extraENV{$v};
+ }
+}
+
+sub toplevel
+{
+ # Pull in benign variables from the user's environment
+
+ foreach (# UNIX-specific things
+ 'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH',
+ 'LD_LIBRARY_PATH',
+ # Purify things
+ 'PURIFYOPTIONS',
+ # Windows NT-specific stuff
+ 'Path', 'SystemRoot',
+ # DJGPP-specific stuff
+ 'DJDIR', 'DJGPP', 'SHELL', 'COMSPEC', 'HOSTNAME', 'LFN',
+ 'FNCASE', '387', 'EMU387', 'GROUP'
+ ) {
+ $makeENV{$_} = $ENV{$_} if $ENV{$_};
+ }
+
+ # Make sure our compares are not foiled by locale differences
+
+ $makeENV{LC_ALL} = 'C';
+
+ # Replace the environment with the new one
+ #
+ %origENV = %ENV unless $^O eq 'VMS';
+
+ resetENV();
+
+ $| = 1; # unbuffered output
+
+ $debug = 0; # debug flag
+ $profile = 0; # profiling flag
+ $verbose = 0; # verbose mode flag
+ $detail = 0; # detailed verbosity
+ $keep = 0; # keep temp files around
+ $workdir = "work"; # The directory where the test will start running
+ $scriptdir = "scripts"; # The directory where we find the test scripts
+ $tmpfilesuffix = "t"; # the suffix used on tmpfiles
+ $default_output_stack_level = 0; # used by attach_default_output, etc.
+ $default_input_stack_level = 0; # used by attach_default_input, etc.
+ $cwd = "."; # don't we wish we knew
+ $cwdslash = ""; # $cwd . $pathsep, but "" rather than "./"
+
+ &get_osname; # sets $osname, $vos, $pathsep, and $short_filenames
+
+ &set_defaults; # suite-defined
+
+ &parse_command_line (@ARGV);
+
+ print "OS name = '$osname'\n" if $debug;
+
+ $workpath = "$cwdslash$workdir";
+ $scriptpath = "$cwdslash$scriptdir";
+
+ &set_more_defaults; # suite-defined
+
+ &print_banner;
+
+ if ($osname eq 'VMS' && $cwdslash eq "")
+ {
+ # Porting this script to VMS revealed a small bug in opendir() not
+ # handling search lists correctly when the directory only exists in
+ # one of the logical_devices. Need to find the first directory in
+ # the search list, as that is where things will be written to.
+ my @dirs = split("/", $pwd);
+
+ my $logical_device = $ENV{$dirs[1]};
+ if ($logical_device =~ /([A-Za-z0-9_]+):(:?.+:)+/)
+ {
+ # A search list was found. Grab the first logical device
+ # and use it instead of the search list.
+ $dirs[1]=$1;
+ my $lcl_pwd = join('/', @dirs);
+ $workpath = $lcl_pwd . '/' . $workdir
+ }
+ }
+
+ if (-d $workpath)
+ {
+ print "Clearing $workpath...\n";
+ &remove_directory_tree("$workpath/")
+ || &error ("Couldn't wipe out $workpath\n");
+ }
+ else
+ {
+ mkdir ($workpath, 0777) || &error ("Couldn't mkdir $workpath: $!\n");
+ }
+
+ if (!-d $scriptpath)
+ {
+ &error ("Failed to find $scriptpath containing perl test scripts.\n");
+ }
+
+ if (@TESTS)
+ {
+ print "Making work dirs...\n";
+ foreach $test (@TESTS)
+ {
+ if ($test =~ /^([^\/]+)\//)
+ {
+ $dir = $1;
+ push (@rmdirs, $dir);
+ -d "$workpath/$dir"
+ || mkdir ("$workpath/$dir", 0777)
+ || &error ("Couldn't mkdir $workpath/$dir: $!\n");
+ }
+ }
+ }
+ else
+ {
+ print "Finding tests...\n";
+ opendir (SCRIPTDIR, $scriptpath)
+ || &error ("Couldn't opendir $scriptpath: $!\n");
+ @dirs = grep (!/^(\..*|CVS|RCS)$/, readdir (SCRIPTDIR) );
+ closedir (SCRIPTDIR);
+ foreach $dir (@dirs)
+ {
+ next if ($dir =~ /^(\..*|CVS|RCS)$/ || ! -d "$scriptpath/$dir");
+ push (@rmdirs, $dir);
+ # VMS can have overlayed file systems, so directories may repeat.
+ next if -d "$workpath/$dir";
+ mkdir ("$workpath/$dir", 0777)
+ || &error ("Couldn't mkdir $workpath/$dir: $!\n");
+ opendir (SCRIPTDIR, "$scriptpath/$dir")
+ || &error ("Couldn't opendir $scriptpath/$dir: $!\n");
+ @files = grep (!/^(\..*|CVS|RCS|.*~)$/, readdir (SCRIPTDIR) );
+ closedir (SCRIPTDIR);
+ foreach $test (@files)
+ {
+ -d $test and next;
+ push (@TESTS, "$dir/$test");
+ }
+ }
+ }
+
+ if (@TESTS == 0)
+ {
+ &error ("\nNo tests in $scriptpath, and none were specified.\n");
+ }
+
+ print "\n";
+
+ run_all_tests();
+
+ foreach $dir (@rmdirs)
+ {
+ rmdir ("$workpath/$dir");
+ }
+
+ $| = 1;
+
+ $categories_failed = $categories_run - $categories_passed;
+ $total_tests_failed = $total_tests_run - $total_tests_passed;
+
+ if ($total_tests_failed)
+ {
+ print "\n$total_tests_failed Test";
+ print "s" unless $total_tests_failed == 1;
+ print " in $categories_failed Categor";
+ print ($categories_failed == 1 ? "y" : "ies");
+ print " Failed (See .$diffext* files in $workdir dir for details) :-(\n\n";
+ return 0;
+ }
+ else
+ {
+ print "\n$total_tests_passed Test";
+ print "s" unless $total_tests_passed == 1;
+ print " in $categories_passed Categor";
+ print ($categories_passed == 1 ? "y" : "ies");
+ print " Complete ... No Failures :-)\n\n";
+ return 1;
+ }
+}
+
+sub get_osname
+{
+ # Set up an initial value. In perl5 we can do it the easy way.
+ $osname = defined($^O) ? $^O : '';
+
+ if ($osname eq 'VMS')
+ {
+ $vos = 0;
+ $pathsep = "/";
+ return;
+ }
+
+ # Find a path to Perl
+
+ # See if the filesystem supports long file names with multiple
+ # dots. DOS doesn't.
+ $short_filenames = 0;
+ (open (TOUCHFD, "> fancy.file.name") && close (TOUCHFD))
+ || ($short_filenames = 1);
+ unlink ("fancy.file.name") || ($short_filenames = 1);
+
+ if (! $short_filenames) {
+ # Thanks go to meyering@cs.utexas.edu (Jim Meyering) for suggesting a
+ # better way of doing this. (We used to test for existence of a /mnt
+ # dir, but that apparently fails on an SGI Indigo (whatever that is).)
+ # Because perl on VOS translates /'s to >'s, we need to test for
+ # VOSness rather than testing for Unixness (ie, try > instead of /).
+
+ mkdir (".ostest", 0777) || &error ("Couldn't create .ostest: $!\n", 1);
+ open (TOUCHFD, "> .ostest>ick") && close (TOUCHFD);
+ chdir (".ostest") || &error ("Couldn't chdir to .ostest: $!\n", 1);
+ }
+
+ if (! $short_filenames && -f "ick")
+ {
+ $osname = "vos";
+ $vos = 1;
+ $pathsep = ">";
+ }
+ else
+ {
+ # the following is regrettably knarly, but it seems to be the only way
+ # to not get ugly error messages if uname can't be found.
+ # Hmmm, BSD/OS 2.0's uname -a is excessively verbose. Let's try it
+ # with switches first.
+ eval "chop (\$osname = `sh -c 'uname -nmsr 2>&1'`)";
+ if ($osname =~ /not found/i)
+ {
+ $osname = "(something posixy with no uname)";
+ }
+ elsif ($@ ne "" || $?)
+ {
+ eval "chop (\$osname = `sh -c 'uname -a 2>&1'`)";
+ if ($@ ne "" || $?)
+ {
+ $osname = "(something posixy)";
+ }
+ }
+ $vos = 0;
+ $pathsep = "/";
+ }
+
+ if (! $short_filenames) {
+ chdir ("..") || &error ("Couldn't chdir to ..: $!\n", 1);
+ unlink (".ostest>ick");
+ rmdir (".ostest") || &error ("Couldn't rmdir .ostest: $!\n", 1);
+ }
+}
+
+sub parse_command_line
+{
+ @argv = @_;
+
+ # use @ARGV if no args were passed in
+
+ if (@argv == 0)
+ {
+ @argv = @ARGV;
+ }
+
+ # look at each option; if we don't recognize it, maybe the suite-specific
+ # command line parsing code will...
+
+ while (@argv)
+ {
+ $option = shift @argv;
+ if ($option =~ /^-debug$/i)
+ {
+ print "\nDEBUG ON\n";
+ $debug = 1;
+ }
+ elsif ($option =~ /^-usage$/i)
+ {
+ &print_usage;
+ exit 0;
+ }
+ elsif ($option =~ /^-(h|help)$/i)
+ {
+ &print_help;
+ exit 0;
+ }
+ elsif ($option =~ /^-profile$/i)
+ {
+ $profile = 1;
+ }
+ elsif ($option =~ /^-verbose$/i)
+ {
+ $verbose = 1;
+ }
+ elsif ($option =~ /^-detail$/i)
+ {
+ $detail = 1;
+ $verbose = 1;
+ }
+ elsif ($option =~ /^-keep$/i)
+ {
+ $keep = 1;
+ }
+ elsif (&valid_option($option))
+ {
+ # The suite-defined subroutine takes care of the option
+ }
+ elsif ($option =~ /^-/)
+ {
+ print "Invalid option: $option\n";
+ &print_usage;
+ exit 0;
+ }
+ else # must be the name of a test
+ {
+ $option =~ s/\.pl$//;
+ push(@TESTS,$option);
+ }
+ }
+}
+
+sub max
+{
+ local($num) = shift @_;
+ local($newnum);
+
+ while (@_)
+ {
+ $newnum = shift @_;
+ if ($newnum > $num)
+ {
+ $num = $newnum;
+ }
+ }
+
+ return $num;
+}
+
+sub print_centered
+{
+ local($width, $string) = @_;
+ local($pad);
+
+ if (length ($string))
+ {
+ $pad = " " x ( ($width - length ($string) + 1) / 2);
+ print "$pad$string";
+ }
+}
+
+sub print_banner
+{
+ local($info);
+ local($line);
+ local($len);
+
+ $info = "Running tests for $testee on $osname\n"; # $testee is suite-defined
+ $len = &max (length ($line), length ($testee_version),
+ length ($banner_info), 73) + 5;
+ $line = ("-" x $len) . "\n";
+ if ($len < 78)
+ {
+ $len = 78;
+ }
+
+ &print_centered ($len, $line);
+ &print_centered ($len, $info);
+ &print_centered ($len, $testee_version); # suite-defined
+ &print_centered ($len, $banner_info); # suite-defined
+ &print_centered ($len, $line);
+ print "\n";
+}
+
+sub run_all_tests
+{
+ $categories_run = 0;
+
+ $lasttest = '';
+ foreach $testname (sort @TESTS) {
+ # Skip duplicates on VMS caused by logical name search lists.
+ next if $testname eq $lasttest;
+ $lasttest = $testname;
+ $suite_passed = 1; # reset by test on failure
+ $num_of_logfiles = 0;
+ $num_of_tmpfiles = 0;
+ $description = "";
+ $details = "";
+ $old_makefile = undef;
+ $testname =~ s/^$scriptpath$pathsep//;
+ $perl_testname = "$scriptpath$pathsep$testname";
+ $testname =~ s/(\.pl|\.perl)$//;
+ $testpath = "$workpath$pathsep$testname";
+ # Leave enough space in the extensions to append a number, even
+ # though it needs to fit into 8+3 limits.
+ if ($short_filenames) {
+ $logext = 'l';
+ $diffext = 'd';
+ $baseext = 'b';
+ $runext = 'r';
+ $extext = '';
+ } else {
+ $logext = 'log';
+ $diffext = 'diff';
+ $baseext = 'base';
+ $runext = 'run';
+ $extext = '.';
+ }
+ $extext = '_' if $^O eq 'VMS';
+ $log_filename = "$testpath.$logext";
+ $diff_filename = "$testpath.$diffext";
+ $base_filename = "$testpath.$baseext";
+ $run_filename = "$testpath.$runext";
+ $tmp_filename = "$testpath.$tmpfilesuffix";
+
+ setup_for_test();
+
+ $output = "........................................................ ";
+
+ substr($output,0,length($testname)) = "$testname ";
+
+ print $output;
+
+ $tests_run = 0;
+ $tests_passed = 0;
+
+ # Run the test!
+ $code = do $perl_testname;
+
+ ++$categories_run;
+ $total_tests_run += $tests_run;
+ $total_tests_passed += $tests_passed;
+
+ # How did it go?
+ if (!defined($code)) {
+ # Failed to parse or called die
+ if (length ($@)) {
+ warn "\n*** Test died ($testname): $@\n";
+ } else {
+ warn "\n*** Couldn't parse $perl_testname\n";
+ }
+ $status = "FAILED ($tests_passed/$tests_run passed)";
+ }
+
+ elsif ($code == -1) {
+ # Skipped... not supported
+ $status = "N/A";
+ --$categories_run;
+ }
+
+ elsif ($code != 1) {
+ # Bad result... this shouldn't really happen. Usually means that
+ # the suite forgot to end with "1;".
+ warn "\n*** Test returned $code\n";
+ $status = "FAILED ($tests_passed/$tests_run passed)";
+ }
+
+ elsif ($tests_run == 0) {
+ # Nothing was done!!
+ $status = "FAILED (no tests found!)";
+ }
+
+ elsif ($tests_run > $tests_passed) {
+ # Lose!
+ $status = "FAILED ($tests_passed/$tests_run passed)";
+ }
+
+ else {
+ # Win!
+ ++$categories_passed;
+ $status = "ok ($tests_passed passed)";
+
+ # Clean up
+ for ($i = $num_of_tmpfiles; $i; $i--) {
+ rmfiles($tmp_filename . num_suffix($i));
+ }
+ for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--) {
+ rmfiles($log_filename . num_suffix($i));
+ rmfiles($base_filename . num_suffix($i));
+ }
+ }
+
+ # If the verbose option has been specified, then a short description
+ # of each test is printed before displaying the results of each test
+ # describing WHAT is being tested.
+
+ if ($verbose) {
+ if ($detail) {
+ print "\nWHAT IS BEING TESTED\n";
+ print "--------------------";
+ }
+ print "\n\n$description\n\n";
+ }
+
+ # If the detail option has been specified, then the details of HOW
+ # the test is testing what it says it is testing in the verbose output
+ # will be displayed here before the results of the test are displayed.
+
+ if ($detail) {
+ print "\nHOW IT IS TESTED\n";
+ print "----------------";
+ print "\n\n$details\n\n";
+ }
+
+ print "$status\n";
+ }
+}
+
+# If the keep flag is not set, this subroutine deletes all filenames that
+# are sent to it.
+
+sub rmfiles
+{
+ local(@files) = @_;
+
+ if (!$keep)
+ {
+ return (unlink @files);
+ }
+
+ return 1;
+}
+
+sub print_standard_usage
+{
+ local($plname,@moreusage) = @_;
+ local($line);
+
+ print "usage:\t$plname [testname] [-verbose] [-detail] [-keep]\n";
+ print "\t\t\t[-profile] [-usage] [-help] [-debug]\n";
+ foreach (@moreusage) {
+ print "\t\t\t$_\n";
+ }
+}
+
+sub print_standard_help
+{
+ local(@morehelp) = @_;
+ local($line);
+ local($tline);
+ local($t) = " ";
+
+ $line = "Test Driver For $testee";
+ print "$line\n";
+ $line = "=" x length ($line);
+ print "$line\n";
+
+ &print_usage;
+
+ print "\ntestname\n"
+ . "${t}You may, if you wish, run only ONE test if you know the name\n"
+ . "${t}of that test and specify this name anywhere on the command\n"
+ . "${t}line. Otherwise ALL existing tests in the scripts directory\n"
+ . "${t}will be run.\n"
+ . "-verbose\n"
+ . "${t}If this option is given, a description of every test is\n"
+ . "${t}displayed before the test is run. (Not all tests may have\n"
+ . "${t}descriptions at this time)\n"
+ . "-detail\n"
+ . "${t}If this option is given, a detailed description of every\n"
+ . "${t}test is displayed before the test is run. (Not all tests\n"
+ . "${t}have descriptions at this time)\n"
+ . "-profile\n"
+ . "${t}If this option is given, then the profile file\n"
+ . "${t}is added to other profiles every time $testee is run.\n"
+ . "${t}This option only works on VOS at this time.\n"
+ . "-keep\n"
+ . "${t}You may give this option if you DO NOT want ANY\n"
+ . "${t}of the files generated by the tests to be deleted. \n"
+ . "${t}Without this option, all files generated by the test will\n"
+ . "${t}be deleted IF THE TEST PASSES.\n"
+ . "-debug\n"
+ . "${t}Use this option if you would like to see all of the system\n"
+ . "${t}calls issued and their return status while running the tests\n"
+ . "${t}This can be helpful if you're having a problem adding a test\n"
+ . "${t}to the suite, or if the test fails!\n";
+
+ foreach $line (@morehelp)
+ {
+ $tline = $line;
+ if (substr ($tline, 0, 1) eq "\t")
+ {
+ substr ($tline, 0, 1) = $t;
+ }
+ print "$tline\n";
+ }
+}
+
+#######################################################################
+########### Generic Test Driver Subroutines ###########
+#######################################################################
+
+sub get_caller
+{
+ local($depth);
+ local($package);
+ local($filename);
+ local($linenum);
+
+ $depth = defined ($_[0]) ? $_[0] : 1;
+ ($package, $filename, $linenum) = caller ($depth + 1);
+ return "$filename: $linenum";
+}
+
+sub error
+{
+ local($message) = $_[0];
+ local($caller) = &get_caller (1);
+
+ if (defined ($_[1]))
+ {
+ $caller = &get_caller ($_[1] + 1) . " -> $caller";
+ }
+
+ die "$caller: $message";
+}
+
+sub compare_output
+{
+ local($answer,$logfile) = @_;
+ local($slurp, $answer_matched) = ('', 0);
+
+ ++$tests_run;
+
+ if (! defined $answer) {
+ print "Ignoring output ........ " if $debug;
+ $answer_matched = 1;
+ } else {
+ print "Comparing Output ........ " if $debug;
+
+ $slurp = &read_file_into_string ($logfile);
+
+ # For make, get rid of any time skew error before comparing--too bad this
+ # has to go into the "generic" driver code :-/
+ $slurp =~ s/^.*modification time .*in the future.*\n//gm;
+ $slurp =~ s/^.*Clock skew detected.*\n//gm;
+
+ if ($slurp eq $answer) {
+ $answer_matched = 1;
+ } else {
+ # See if it is a slash or CRLF problem
+ local ($answer_mod, $slurp_mod) = ($answer, $slurp);
+
+ $answer_mod =~ tr,\\,/,;
+ $answer_mod =~ s,\r\n,\n,gs;
+
+ $slurp_mod =~ tr,\\,/,;
+ $slurp_mod =~ s,\r\n,\n,gs;
+
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ if ($^O eq 'VMS') {
+
+ # VMS has extra blank lines in output sometimes.
+ # Ticket #41760
+ if (!$answer_matched) {
+ $slurp_mod =~ s/\n\n+/\n/gm;
+ $slurp_mod =~ s/\A\n+//g;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS adding a "Waiting for unfinished jobs..."
+ # Remove it for now to see what else is going on.
+ if (!$answer_matched) {
+ $slurp_mod =~ s/^.+\*\*\* Waiting for unfinished jobs.+$//m;
+ $slurp_mod =~ s/\n\n/\n/gm;
+ $slurp_mod =~ s/^\n+//gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS wants target device to exist or generates an error,
+ # Some test tagets look like VMS devices and trip this.
+ if (!$answer_matched) {
+ $slurp_mod =~ s/^.+\: no such device or address.*$//gim;
+ $slurp_mod =~ s/\n\n/\n/gm;
+ $slurp_mod =~ s/^\n+//gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS error message has a different case
+ if (!$answer_matched) {
+ $slurp_mod =~ s/no such file /No such file /gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS is putting comas instead of spaces in output
+ if (!$answer_matched) {
+ $slurp_mod =~ s/,/ /gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS Is sometimes adding extra leading spaces to output?
+ if (!$answer_matched) {
+ my $slurp_mod = $slurp_mod;
+ $slurp_mod =~ s/^ +//gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS port not handling POSIX encoded child status
+ # Translate error case it for now.
+ if (!$answer_matched) {
+ $slurp_mod =~ s/0x1035a00a/1/gim;
+ $answer_matched = 1 if $slurp_mod =~ /\Q$answer_mod\E/i;
+
+ }
+ if (!$answer_matched) {
+ $slurp_mod =~ s/0x1035a012/2/gim;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # Tests are using a UNIX null command, temp hack
+ # until this can be handled by the VMS port.
+ # ticket # 41761
+ if (!$answer_matched) {
+ $slurp_mod =~ s/^.+DCL-W-NOCOMD.*$//gim;
+ $slurp_mod =~ s/\n\n+/\n/gm;
+ $slurp_mod =~ s/^\n+//gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+ # Tests are using exit 0;
+ # this generates a warning that should stop the make, but does not
+ if (!$answer_matched) {
+ $slurp_mod =~ s/^.+NONAME-W-NOMSG.*$//gim;
+ $slurp_mod =~ s/\n\n+/\n/gm;
+ $slurp_mod =~ s/^\n+//gm;
+ $answer_matched = ($slurp_mod eq $answer_mod);
+ }
+
+ # VMS is sometimes adding single quotes to output?
+ if (!$answer_matched) {
+ my $noq_slurp_mod = $slurp_mod;
+ $noq_slurp_mod =~ s/\'//gm;
+ $answer_matched = ($noq_slurp_mod eq $answer_mod);
+
+ # And missing an extra space in output
+ if (!$answer_matched) {
+ $noq_answer_mod = $answer_mod;
+ $noq_answer_mod =~ s/\h\h+/ /gm;
+ $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
+ }
+
+ # VMS adding ; to end of some lines.
+ if (!$answer_matched) {
+ $noq_slurp_mod =~ s/;\n/\n/gm;
+ $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
+ }
+
+ # VMS adding trailing space to end of some quoted lines.
+ if (!$answer_matched) {
+ $noq_slurp_mod =~ s/\h+\n/\n/gm;
+ $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
+ }
+
+ # And VMS missing leading blank line
+ if (!$answer_matched) {
+ $noq_answer_mod =~ s/\A\n//g;
+ $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
+ }
+
+ # Unix double quotes showing up as single quotes on VMS.
+ if (!$answer_matched) {
+ $noq_answer_mod =~ s/\"//g;
+ $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
+ }
+ }
+ }
+
+ # If it still doesn't match, see if the answer might be a regex.
+ if (!$answer_matched && $answer =~ m,^/(.+)/$,) {
+ $answer_matched = ($slurp =~ /$1/);
+ if (!$answer_matched && $answer_mod =~ m,^/(.+)/$,) {
+ $answer_matched = ($slurp_mod =~ /$1/);
+ }
+ }
+ }
+ }
+
+ if ($answer_matched && $test_passed)
+ {
+ print "ok\n" if $debug;
+ ++$tests_passed;
+ return 1;
+ }
+
+ if (! $answer_matched) {
+ print "DIFFERENT OUTPUT\n" if $debug;
+
+ &create_file (&get_basefile, $answer);
+ &create_file (&get_runfile, $command_string);
+
+ print "\nCreating Difference File ...\n" if $debug;
+
+ # Create the difference file
+
+ local($command) = "diff -c " . &get_basefile . " " . $logfile;
+ &run_command_with_output(&get_difffile,$command);
+ }
+
+ return 0;
+}
+
+sub read_file_into_string
+{
+ local($filename) = @_;
+ local($oldslash) = $/;
+
+ undef $/;
+
+ open (RFISFILE, $filename) || return "";
+ local ($slurp) = <RFISFILE>;
+ close (RFISFILE);
+
+ $/ = $oldslash;
+
+ return $slurp;
+}
+
+my @OUTSTACK = ();
+my @ERRSTACK = ();
+
+sub attach_default_output
+{
+ local ($filename) = @_;
+ local ($code);
+
+ if ($vos)
+ {
+ $code = system "++attach_default_output_hack $filename";
+ $code == -2 || &error ("adoh death\n", 1);
+ return 1;
+ }
+
+ my $dup = undef;
+ open($dup, '>&', STDOUT) or error("ado: $! duping STDOUT\n", 1);
+ push @OUTSTACK, $dup;
+
+ $dup = undef;
+ open($dup, '>&', STDERR) or error("ado: $! duping STDERR\n", 1);
+ push @ERRSTACK, $dup;
+
+ open(STDOUT, '>', $filename) or error("ado: $filename: $!\n", 1);
+ open(STDERR, ">&STDOUT") or error("ado: $filename: $!\n", 1);
+}
+
+# close the current stdout/stderr, and restore the previous ones from
+# the "stack."
+
+sub detach_default_output
+{
+ local ($code);
+
+ if ($vos)
+ {
+ $code = system "++detach_default_output_hack";
+ $code == -2 || &error ("ddoh death\n", 1);
+ return 1;
+ }
+
+ @OUTSTACK or error("default output stack has flown under!\n", 1);
+
+ close(STDOUT);
+ close(STDERR) unless $^O eq 'VMS';
+
+
+ open (STDOUT, '>&', pop @OUTSTACK) or error("ddo: $! duping STDOUT\n", 1);
+ open (STDERR, '>&', pop @ERRSTACK) or error("ddo: $! duping STDERR\n", 1);
+}
+
+# This runs a command without any debugging info.
+sub _run_command
+{
+ my $code;
+
+ # We reset this before every invocation. On Windows I think there is only
+ # one environment, not one per process, so I think that variables set in
+ # test scripts might leak into subsequent tests if this isn't reset--???
+ resetENV();
+
+ eval {
+ if ($^O eq 'VMS') {
+ local $SIG{ALRM} = sub {
+ my $e = $ERRSTACK[0];
+ print $e "\nTest timed out after $test_timeout seconds\n";
+ die "timeout\n"; };
+# alarm $test_timeout;
+ system(@_);
+ my $severity = ${^CHILD_ERROR_NATIVE} & 7;
+ $code = 0;
+ if (($severity & 1) == 0) {
+ $code = 512;
+ }
+
+ # Get the vms status.
+ my $vms_code = ${^CHILD_ERROR_NATIVE};
+
+ # Remove the print status bit
+ $vms_code &= ~0x10000000;
+
+ # Posix code translation.
+ if (($vms_code & 0xFFFFF000) == 0x35a000) {
+ $code = (($vms_code & 0xFFF) >> 3) * 256;
+ }
+ } else {
+ my $pid = fork();
+ if (! $pid) {
+ exec(@_) or die "Cannot execute $_[0]\n";
+ }
+ local $SIG{ALRM} = sub { my $e = $ERRSTACK[0]; print $e "\nTest timed out after $test_timeout seconds\n"; die "timeout\n"; };
+ alarm $test_timeout;
+ waitpid($pid, 0) > 0 or die "No such pid: $pid\n";
+ $code = $?;
+ }
+ alarm 0;
+ };
+ if ($@) {
+ # The eval failed. If it wasn't SIGALRM then die.
+ $@ eq "timeout\n" or die "Command failed: $@";
+
+ # Timed out. Resend the alarm to our process group to kill the children.
+ $SIG{ALRM} = 'IGNORE';
+ kill -14, $$;
+ $code = 14;
+ }
+
+ return $code;
+}
+
+# run one command (passed as a list of arg 0 - n), returning 0 on success
+# and nonzero on failure.
+
+sub run_command
+{
+ print "\nrun_command: @_\n" if $debug;
+ my $code = _run_command(@_);
+ print "run_command returned $code.\n" if $debug;
+ print "vms status = ${^CHILD_ERROR_NATIVE}\n" if $debug and $^O eq 'VMS';
+ return $code;
+}
+
+# run one command (passed as a list of arg 0 - n, with arg 0 being the
+# second arg to this routine), returning 0 on success and non-zero on failure.
+# The first arg to this routine is a filename to connect to the stdout
+# & stderr of the child process.
+
+sub run_command_with_output
+{
+ my $filename = shift;
+
+ print "\nrun_command_with_output($filename,$runname): @_\n" if $debug;
+ &attach_default_output ($filename);
+ my $code = eval { _run_command(@_) };
+ my $err = $@;
+ &detach_default_output;
+
+ $err and die $err;
+
+ print "run_command_with_output returned $code.\n" if $debug;
+ print "vms status = ${^CHILD_ERROR_NATIVE}\n" if $debug and $^O eq 'VMS';
+ return $code;
+}
+
+# performs the equivalent of an "rm -rf" on the first argument. Like
+# rm, if the path ends in /, leaves the (now empty) directory; otherwise
+# deletes it, too.
+
+sub remove_directory_tree
+{
+ local ($targetdir) = @_;
+ local ($nuketop) = 1;
+ local ($ch);
+
+ $ch = substr ($targetdir, length ($targetdir) - 1);
+ if ($ch eq "/" || $ch eq $pathsep)
+ {
+ $targetdir = substr ($targetdir, 0, length ($targetdir) - 1);
+ $nuketop = 0;
+ }
+
+ if (! -e $targetdir)
+ {
+ return 1;
+ }
+
+ &remove_directory_tree_inner ("RDT00", $targetdir) || return 0;
+ if ($nuketop)
+ {
+ rmdir $targetdir || return 0;
+ }
+
+ return 1;
+}
+
+sub remove_directory_tree_inner
+{
+ local ($dirhandle, $targetdir) = @_;
+ local ($object);
+ local ($subdirhandle);
+
+ opendir ($dirhandle, $targetdir) || return 0;
+ $subdirhandle = $dirhandle;
+ $subdirhandle++;
+ while ($object = readdir ($dirhandle))
+ {
+ if ($object =~ /^(\.\.?|CVS|RCS)$/)
+ {
+ next;
+ }
+
+ $object = "$targetdir$pathsep$object";
+ lstat ($object);
+
+ if (-d _ && &remove_directory_tree_inner ($subdirhandle, $object))
+ {
+ rmdir $object || return 0;
+ }
+ else
+ {
+ if ($^O ne 'VMS')
+ {
+ unlink $object || return 0;
+ }
+ else
+ {
+ # VMS can have multiple versions of a file.
+ 1 while unlink $object;
+ }
+ }
+ }
+ closedir ($dirhandle);
+ return 1;
+}
+
+# We used to use this behavior for this function:
+#
+#sub touch
+#{
+# local (@filenames) = @_;
+# local ($now) = time;
+# local ($file);
+#
+# foreach $file (@filenames)
+# {
+# utime ($now, $now, $file)
+# || (open (TOUCHFD, ">> $file") && close (TOUCHFD))
+# || &error ("Couldn't touch $file: $!\n", 1);
+# }
+# return 1;
+#}
+#
+# But this behaves badly on networked filesystems where the time is
+# skewed, because it sets the time of the file based on the _local_
+# host. Normally when you modify a file, it's the _remote_ host that
+# determines the modtime, based on _its_ clock. So, instead, now we open
+# the file and write something into it to force the remote host to set
+# the modtime correctly according to its clock.
+#
+
+sub touch
+{
+ local ($file);
+
+ foreach $file (@_) {
+ (open(T, ">> $file") && print(T "\n") && close(T))
+ || &error("Couldn't touch $file: $!\n", 1);
+ }
+}
+
+# Touch with a time offset. To DTRT, call touch() then use stat() to get the
+# access/mod time for each file and apply the offset.
+
+sub utouch
+{
+ local ($off) = shift;
+ local ($file);
+
+ &touch(@_);
+
+ local (@s) = stat($_[0]);
+
+ utime($s[8]+$off, $s[9]+$off, @_);
+}
+
+# open a file, write some stuff to it, and close it.
+
+sub create_file
+{
+ local ($filename, @lines) = @_;
+
+ open (CF, "> $filename") || &error ("Couldn't open $filename: $!\n", 1);
+ foreach $line (@lines)
+ {
+ print CF $line;
+ }
+ close (CF);
+}
+
+# create a directory tree described by an associative array, wherein each
+# key is a relative pathname (using slashes) and its associated value is
+# one of:
+# DIR indicates a directory
+# FILE:contents indicates a file, which should contain contents +\n
+# LINK:target indicates a symlink, pointing to $basedir/target
+# The first argument is the dir under which the structure will be created
+# (the dir will be made and/or cleaned if necessary); the second argument
+# is the associative array.
+
+sub create_dir_tree
+{
+ local ($basedir, %dirtree) = @_;
+ local ($path);
+
+ &remove_directory_tree ("$basedir");
+ mkdir ($basedir, 0777) || &error ("Couldn't mkdir $basedir: $!\n", 1);
+
+ foreach $path (sort keys (%dirtree))
+ {
+ if ($dirtree {$path} =~ /^DIR$/)
+ {
+ mkdir ("$basedir/$path", 0777)
+ || &error ("Couldn't mkdir $basedir/$path: $!\n", 1);
+ }
+ elsif ($dirtree {$path} =~ /^FILE:(.*)$/)
+ {
+ &create_file ("$basedir/$path", $1 . "\n");
+ }
+ elsif ($dirtree {$path} =~ /^LINK:(.*)$/)
+ {
+ symlink ("$basedir/$1", "$basedir/$path")
+ || &error ("Couldn't symlink $basedir/$path -> $basedir/$1: $!\n", 1);
+ }
+ else
+ {
+ &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1);
+ }
+ }
+ if ($just_setup_tree)
+ {
+ die "Tree is setup...\n";
+ }
+}
+
+# compare a directory tree with an associative array in the format used
+# by create_dir_tree, above.
+# The first argument is the dir under which the structure should be found;
+# the second argument is the associative array.
+
+sub compare_dir_tree
+{
+ local ($basedir, %dirtree) = @_;
+ local ($path);
+ local ($i);
+ local ($bogus) = 0;
+ local ($contents);
+ local ($target);
+ local ($fulltarget);
+ local ($found);
+ local (@files);
+ local (@allfiles);
+
+ opendir (DIR, $basedir) || &error ("Couldn't open $basedir: $!\n", 1);
+ @allfiles = grep (!/^(\.\.?|CVS|RCS)$/, readdir (DIR) );
+ closedir (DIR);
+ if ($debug)
+ {
+ print "dirtree: (%dirtree)\n$basedir: (@allfiles)\n";
+ }
+
+ foreach $path (sort keys (%dirtree))
+ {
+ if ($debug)
+ {
+ print "Checking $path ($dirtree{$path}).\n";
+ }
+
+ $found = 0;
+ foreach $i (0 .. $#allfiles)
+ {
+ if ($allfiles[$i] eq $path)
+ {
+ splice (@allfiles, $i, 1); # delete it
+ if ($debug)
+ {
+ print " Zapped $path; files now (@allfiles).\n";
+ }
+ lstat ("$basedir/$path");
+ $found = 1;
+ last;
+ }
+ }
+
+ if (!$found)
+ {
+ print "compare_dir_tree: $path does not exist.\n";
+ $bogus = 1;
+ next;
+ }
+
+ if ($dirtree {$path} =~ /^DIR$/)
+ {
+ if (-d _ && opendir (DIR, "$basedir/$path") )
+ {
+ @files = readdir (DIR);
+ closedir (DIR);
+ @files = grep (!/^(\.\.?|CVS|RCS)$/ && ($_ = "$path/$_"), @files);
+ push (@allfiles, @files);
+ if ($debug)
+ {
+ print " Read in $path; new files (@files).\n";
+ }
+ }
+ else
+ {
+ print "compare_dir_tree: $path is not a dir.\n";
+ $bogus = 1;
+ }
+ }
+ elsif ($dirtree {$path} =~ /^FILE:(.*)$/)
+ {
+ if (-l _ || !-f _)
+ {
+ print "compare_dir_tree: $path is not a file.\n";
+ $bogus = 1;
+ next;
+ }
+
+ if ($1 ne "*")
+ {
+ $contents = &read_file_into_string ("$basedir/$path");
+ if ($contents ne "$1\n")
+ {
+ print "compare_dir_tree: $path contains wrong stuff."
+ . " Is:\n$contentsShould be:\n$1\n";
+ $bogus = 1;
+ }
+ }
+ }
+ elsif ($dirtree {$path} =~ /^LINK:(.*)$/)
+ {
+ $target = $1;
+ if (!-l _)
+ {
+ print "compare_dir_tree: $path is not a link.\n";
+ $bogus = 1;
+ next;
+ }
+
+ $contents = readlink ("$basedir/$path");
+ $contents =~ tr/>/\//;
+ $fulltarget = "$basedir/$target";
+ $fulltarget =~ tr/>/\//;
+ if (!($contents =~ /$fulltarget$/))
+ {
+ if ($debug)
+ {
+ $target = $fulltarget;
+ }
+ print "compare_dir_tree: $path should be link to $target, "
+ . "not $contents.\n";
+ $bogus = 1;
+ }
+ }
+ else
+ {
+ &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1);
+ }
+ }
+
+ if ($debug)
+ {
+ print "leftovers: (@allfiles).\n";
+ }
+
+ foreach $file (@allfiles)
+ {
+ print "compare_dir_tree: $file should not exist.\n";
+ $bogus = 1;
+ }
+
+ return !$bogus;
+}
+
+# this subroutine generates the numeric suffix used to keep tmp filenames,
+# log filenames, etc., unique. If the number passed in is 1, then a null
+# string is returned; otherwise, we return ".n", where n + 1 is the number
+# we were given.
+
+sub num_suffix
+{
+ local($num) = @_;
+
+ if (--$num > 0) {
+ return "$extext$num";
+ }
+
+ return "";
+}
+
+# This subroutine returns a log filename with a number appended to
+# the end corresponding to how many logfiles have been created in the
+# current running test. An optional parameter may be passed (0 or 1).
+# If a 1 is passed, then it does NOT increment the logfile counter
+# and returns the name of the latest logfile. If either no parameter
+# is passed at all or a 0 is passed, then the logfile counter is
+# incremented and the new name is returned.
+
+sub get_logfile
+{
+ local($no_increment) = @_;
+
+ $num_of_logfiles += !$no_increment;
+
+ return ($log_filename . &num_suffix ($num_of_logfiles));
+}
+
+# This subroutine returns a base (answer) filename with a number
+# appended to the end corresponding to how many logfiles (and thus
+# base files) have been created in the current running test.
+# NO PARAMETERS ARE PASSED TO THIS SUBROUTINE.
+
+sub get_basefile
+{
+ return ($base_filename . &num_suffix ($num_of_logfiles));
+}
+
+# This subroutine returns a difference filename with a number appended
+# to the end corresponding to how many logfiles (and thus diff files)
+# have been created in the current running test.
+
+sub get_difffile
+{
+ return ($diff_filename . &num_suffix ($num_of_logfiles));
+}
+
+# This subroutine returns a command filename with a number appended
+# to the end corresponding to how many logfiles (and thus command files)
+# have been created in the current running test.
+
+sub get_runfile
+{
+ return ($run_filename . &num_suffix ($num_of_logfiles));
+}
+
+# just like logfile, only a generic tmp filename for use by the test.
+# they are automatically cleaned up unless -keep was used, or the test fails.
+# Pass an argument of 1 to return the same filename as the previous call.
+
+sub get_tmpfile
+{
+ local($no_increment) = @_;
+
+ $num_of_tmpfiles += !$no_increment;
+
+ return ($tmp_filename . &num_suffix ($num_of_tmpfiles));
+}
+
+1;