Compare commits

...

76 Commits

Author SHA1 Message Date
Paul Smith
d1d9c0274b Update version info. 2002-10-04 03:17:56 +00:00
Paul Smith
ee9584dc8d Don't put .cvsignore files in the distributed tar file. 2002-10-04 02:28:59 +00:00
Paul Smith
9dc79463a9 Fix K&R-isms found on SunOS 4.1.4 builds. 2002-10-04 02:12:52 +00:00
Paul Smith
1d3dfeb74b Some updates for automake 1.7 and prep for releasing 3.80. 2002-10-03 05:46:12 +00:00
Paul Smith
2de1b62112 Add VMS updates from Martin Zinser. 2002-10-01 15:32:14 +00:00
Paul Smith
ae003efd61 Fix a bug handling target/prerequisite names containing comment
characters.
2002-09-23 22:16:40 +00:00
Paul Smith
ebd05dbeb3 Fix a bug exporting/unexporting multiple variables in one command.
Update the text about reporting bugs.
2002-09-18 20:51:58 +00:00
Paul Smith
76652d5d02 Add some indexing to the manual.
Fix a few simple casting warnings, etc.
2002-09-18 04:35:52 +00:00
Paul Smith
dac7b49de4 Fix bug #940 (from the Savannah bug tracker): make sure that target-
specific variables work correctly in conjunction with double-colon
targets.
2002-09-17 21:52:45 +00:00
Paul Smith
d7ebcadadb Fixups for the release. One bug fix, some automake complaint fixes,
and a function return type fix for older systems.
2002-09-12 22:15:58 +00:00
Paul Smith
4a11acf047 Fix HAVE_BROKEN_RESTART logic.
Fix hash.h typos (only noticed when using Windows).
Update .cvsignore files.
2002-09-11 16:55:44 +00:00
Paul Smith
5df75e7265 Fix regex matching for modification time warnings.
The ones we had were weird, and failed for multiple warnings in a
single file.
2002-09-10 22:39:18 +00:00
Paul Smith
bc91c0b23f A few test bug fixes:
* Never use "touch" in make rules; it breaks on most sub-second
    supporting systems.  Use echo "" > $@ instead.
  * Forgot to close test makefiles before using them!

All the above worked fine on Linux but failed miserably on Solaris.
2002-09-10 22:23:20 +00:00
Paul Smith
5297a83b27 Have the test driver check for the new format of the time skew error
messages.
2002-09-10 20:59:03 +00:00
Paul Smith
7ea029a07c Add support for broken SA_RESTART on PTX.
Fix bug #103: allow ifdef, export, and unexport to expand their arguments.
2002-09-10 07:27:28 +00:00
Paul Smith
9b41488ad1 Whoops; configure wasn't looking for memmove. 2002-09-09 21:20:41 +00:00
Paul Smith
988deb489b Fix for complex situations where directories are declared as prerequisites.
Info on this fix from barkalow@reputation.com: thanks!

Some updates/cleanups of some of the tests; added a forgotten -t test, etc.
2002-09-04 07:26:19 +00:00
Paul Smith
d2429d7508 Update some NEWS and README nits, and add new gettext macros to config's
Makefile.am.
2002-09-03 21:43:04 +00:00
Paul Smith
299c72e6ed Update to a new version of automake and gettext.
Invent a new macro HAVE_DOS_PATHS and change various instances of:
  #if defined(WINDOWS) || defined(__MSDOS__)
to use the new macro instead.  This should help make the OS/2 port
cleaner, as well.
Invent a cvs-clean maintainer target that tries to get the workspace
back to the state it was in after a CVS checkout.
New language.
2002-08-10 01:27:16 +00:00
Paul Smith
ee3a4f9dd6 Change the version.
Update to require new gettext.
Change hash.c to by K&R.
Redo some strings to make i18n simpler.
2002-08-08 05:39:17 +00:00
Paul Smith
f2ceb0d68a Incorporate some VMS fixes.
Add -B option docs.
Add .VARIABLES variable.
Add a few new tests.
Add a new translation: Swedish
2002-08-08 00:11:19 +00:00
Paul Smith
bccb277dda New variables, .VARIABLES and .TARGETS. 2002-08-01 13:16:57 +00:00
Paul Smith
a56563badd Make sure templates are built. 2002-07-14 02:57:04 +00:00
Paul Smith
21cf8c6444 Install Greg McGary's patches to port the id-utils hashing functions to
GNU make.  Also he provides some other performance fixups after doing
some profiling of make on large makefiles.

Modify the test suite to allow the use of Valgrind to find memory problems.
2002-07-11 06:38:57 +00:00
Paul Smith
4d72c4c11e Implement SysV-style $$@ support. I looked at E.Parmelan's patch but
decided to implement this a different way, and didn't use it.
2002-07-10 12:59:07 +00:00
Paul Smith
6c9a393f95 Documentation and tests for order-only prerequisites.
Add a new test suite for automatic variables.
2002-07-09 06:35:56 +00:00
Paul Smith
724925be2b Various cleanups reported by people using the alpha release.
Incorporate "order-only" prerequisites patch.  Wrote a test for it.
The test shows what might be a bug in the code; I need to look at it
more closely (anyway it doesn't behave as I expected).  Also I haven't
done the docs yet.
2002-07-08 13:05:02 +00:00
Paul Smith
2f20fc1cc7 Remove .po files; we'll retrieve them directly from the translation site. 2002-07-08 03:25:34 +00:00
Paul Smith
8572d6adf0 Major updates in preparation for 3.80.
New version of the manual, put into the doc subdir.
Enhancements: $(eval ...) and $(value ...) functions, various bug
fixes, etc.  See the ChangeLog.
More to come.
2002-07-08 02:26:47 +00:00
Paul Smith
4a07398023 Update the README template. 2002-05-29 22:24:09 +00:00
Paul Smith
99e01f61fd Install newest German translation. 2002-05-13 14:40:16 +00:00
Paul Smith
9052b52dfc Fix Debian bug #144306: pass target-specific variables into the environment
properly.

Fix configure: allow cross-compilation; fix getloadavg (still needs _lots_
of work!)

Let $(call ...) functions to be self-referencing.  Lets us do transitive
closures, for example.
2002-05-10 03:15:07 +00:00
Paul Smith
5dedf7be63 Remove our local copy so we can use the standard version. 2002-04-24 21:52:21 +00:00
Paul Smith
2276c37ae7 Add back initial "\" which was accidentally removed a year ago! :-/. 2002-04-24 21:36:38 +00:00
Paul Smith
306462f0bd Updates for new tools. Everything works now building on Linux,
including creating make packages.  I'll try some other systems tomorrow.
Also added a new translation: Croatian.  Thanks!
2002-04-22 04:35:19 +00:00
Paul Smith
3a8a7a5d00 Updates and fixes for CVS builds.
Created a README.cvs describing the procedure.
2002-04-22 02:11:31 +00:00
Paul Smith
7ed1a08985 Update GNU make to use Autoconf 2.53, Automake 1.6.1, Gettext 0.11.1.
We're using Gettext's "external" feature to avoid including the intl
code in the GNU make distribution.
2002-04-21 23:57:24 +00:00
Paul Smith
cae1db6ecd Installed a new translation for Hebrew. 2002-04-20 19:35:15 +00:00
Paul Smith
dad29566b3 Updates to translaations.
Fix an assert() in an obscure use of -q
Handling of double-colon timestamp updates was broken in a bizarre way.
Store arguments to $(call ...) functions in simple variables, not recursive
variables.
2002-04-20 19:25:54 +00:00
Paul Smith
d242ee9053 Install updated translations. 2002-03-12 01:36:17 +00:00
Paul Smith
1d9d40a209 Install a new Japanese translation. 2001-12-04 18:47:02 +00:00
Paul Smith
c0312423d9 Update copyright info. 2001-11-18 18:38:02 +00:00
Paul Smith
9302338304 Installed the da.po (Danish) translation file.
Fixed some translation string issues.
2001-08-19 04:55:51 +00:00
Paul Smith
74f08c639d Installed a new French translation (resolves Debian Bug #106720) 2001-08-03 19:02:51 +00:00
Paul Smith
635a784ebf New/updated translations; minor update to the index of the manual. 2001-07-05 00:35:03 +00:00
Paul Smith
4c28600a50 New translation. 2001-06-01 03:57:19 +00:00
Paul Smith
ce2c6eadf1 Fix for EINTR problems when using jobserver.
New translation files.
Fix for @+ inside define macros being applied too widely.
Various other bug fixes.
2001-06-01 03:56:50 +00:00
Paul Smith
5d582d4ba0 Some VMS fixes sent by John Fowler.
Fix: make flags on some lines of define/endef don't affect other lines
2001-05-21 06:16:00 +00:00
Paul Smith
8f2b1e2c7c Some bug fixes and document updates. 2001-01-21 06:49:11 +00:00
Paul Smith
e5324a8c6a * Fix FAT handling on Windows to match the DJGPP port's FAT handling.
* Fix a potential hole in readline if lines end in ^M (CRLF).
2000-11-17 06:59:08 +00:00
Paul Smith
d5a04ee984 * Various bug fixes.
* New Galician translation.
2000-10-05 16:27:06 +00:00
Paul Smith
50ba270762 * Rework phrasing to allow for better translations.
# New Japanese translation file.
2000-09-21 04:14:38 +00:00
Paul Smith
8ddf04c627 Fix PR/1831. See the ChangeLog. 2000-08-21 06:18:35 +00:00
Paul Smith
1a82956eae * Various fixes; see the ChangeLog. 2000-07-30 18:26:42 +00:00
Paul Smith
3c132f10f3 * Minor code cleanups
* Fix for PR/1811, from Paul Eggert.
2000-07-07 17:34:56 +00:00
Paul Smith
88187d9f4b * Fix PR/1791. 2000-06-23 19:43:11 +00:00
Paul Smith
775b644765 * Released 3.79.1 2000-06-23 18:55:43 +00:00
Paul Smith
fcbfe98cbe * Fix -q so it works more correctly.
* Don't print "nothing to do" messages for ":" commands
* Update the version to 3.79.1
2000-06-23 15:55:46 +00:00
Paul Smith
cbe92a2241 * Fix PR/1709. 2000-06-22 00:45:34 +00:00
Paul Smith
d5f7eb2897 * A couple of nits. 2000-06-20 21:32:40 +00:00
Paul Smith
3e6f48b444 * More updates and fixes. 2000-06-20 05:48:40 +00:00
Paul Smith
0d70d05458 * Various fixes for problems in the 3.79.0.1 pretest. 2000-06-19 21:22:44 +00:00
Paul Smith
f04e78f11b * Typo. 2000-06-14 22:29:48 +00:00
Paul Smith
c392c19335 * More fixes for configuring gettext correctly. 2000-06-14 22:29:30 +00:00
Paul Smith
4972b017b6 * Some timestamp fixes from Paul Eggert.
* Fix compilation on Linux; use libintl.h and not gettext.h when using
  the system gettext.
2000-06-13 05:22:52 +00:00
Paul Smith
4a5550c822 * Lots of bug fixes and cleanup; new i18n files, etc. 2000-06-07 05:43:37 +00:00
Paul Smith
e5c40f6e5a New translation files. 2000-06-01 14:37:58 +00:00
Paul Smith
5ed9fb46b2 * Various bug fixes. 2000-04-22 02:11:17 +00:00
Paul Smith
f9c91ec34d * Some final cleanups, and release 3.79. 2000-04-05 16:02:55 +00:00
Paul Smith
f3a974bf32 * Fix bug handling archive members: convert timestamp to nsec properly
on those systems that support it.
2000-04-03 05:58:41 +00:00
Paul Smith
c67266ceac * New config.sub and config.guess
* Update version number for release
* Fixes to the build.sh to handle i18n/gettext
* Make dash-n more robust.
2000-03-29 03:23:18 +00:00
Paul Smith
4145bcbcda * Handle case of empty static pattern rule prerequisites.
* Fix linenumbers in error messages for rule definitions.
2000-03-27 20:53:50 +00:00
Paul Smith
c637af71d9 * A large number of fixes/enhancements. See the ChangeLog.
* Added a new version of the German translation file.
2000-03-27 06:54:37 +00:00
Paul Smith
a81013175c * Ignore attempt to change a file into itself.
* Define COFLAGS to avoid unknown variable warning.
* Fix some usec problems on UnixWare.
* Don't remove .INTERMEDIATE targets specified on the command line.
2000-03-26 06:56:54 +00:00
Paul Smith
75f879f37f * Fix backslash-escape in targets.
* Release 3.78.91.
2000-02-09 19:57:15 +00:00
Paul Smith
e68a27ec7b * Fix some warnings in gettext.c and function.c
* Don't try to execute tests which are actually directories.
2000-02-09 07:02:18 +00:00
121 changed files with 15690 additions and 34131 deletions

View File

@@ -1,6 +1,6 @@
*.gz *.Z *.tar *.tgz
=*
TODO COPYING*
TODO COPYING* ABOUT-NLS
make-3* make-test*
*.info *.info-*
stamp-*
@@ -12,7 +12,8 @@ makebook*
*.cp *.cps *.fn *.fns *.vr *.vrs *.tp *.tps *.ky *.kys *.pg *.pgs
README README.DOS README.W32
aclocal.m4 config.h.in config.h config.status config.cache configure
aclocal.m4 autom4te.cache
config.h.in config.h config.status config.cache configure
Makefile.in Makefile
build.sh.in build.sh
SMakefile NMakefile Makefile.DOS

226
ABOUT-NLS
View File

@@ -1,226 +0,0 @@
Notes on the Free Translation Project
*************************************
Free software is going international! The Free Translation Project
is a way to get maintainers of free software, translators, and users all
together, so that will gradually become able to speak many languages.
A few packages already provide translations for their messages.
If you found this `ABOUT-NLS' file inside a distribution, you may
assume that the distributed package does use GNU `gettext' internally,
itself available at your nearest GNU archive site. But you do *not*
need to install GNU `gettext' prior to configuring, installing or using
this package with messages translated.
Installers will find here some useful hints. These notes also
explain how users should proceed for getting the programs to use the
available translations. They tell how people wanting to contribute and
work at translations should contact the appropriate team.
When reporting bugs in the `intl/' directory or bugs which may be
related to internationalization, you should tell about the version of
`gettext' which is used. The information can be found in the
`intl/VERSION' file, in internationalized packages.
One advise in advance
=====================
If you want to exploit the full power of internationalization, you
should configure it using
./configure --with-included-gettext
to force usage of internationalizing routines provided within this
package, despite the existence of internationalizing capabilities in the
operating system where this package is being installed. So far, only
the `gettext' implementation in the GNU C library version 2 provides as
many features (such as locale alias or message inheritance) as the
implementation here. It is also not possible to offer this additional
functionality on top of a `catgets' implementation. Future versions of
GNU `gettext' will very likely convey even more functionality. So it
might be a good idea to change to GNU `gettext' as soon as possible.
So you need not provide this option if you are using GNU libc 2 or
you have installed a recent copy of the GNU gettext package with the
included `libintl'.
INSTALL Matters
===============
Some packages are "localizable" when properly installed; the
programs they contain can be made to speak your own native language.
Most such packages use GNU `gettext'. Other packages have their own
ways to internationalization, predating GNU `gettext'.
By default, this package will be installed to allow translation of
messages. It will automatically detect whether the system provides
usable `catgets' (if using this is selected by the installer) or
`gettext' functions. If neither is available, the GNU `gettext' own
library will be used. This library is wholly contained within this
package, usually in the `intl/' subdirectory, so prior installation of
the GNU `gettext' package is *not* required. Installers may use
special options at configuration time for changing the default
behaviour. The commands:
./configure --with-included-gettext
./configure --with-catgets
./configure --disable-nls
will respectively bypass any pre-existing `catgets' or `gettext' to use
the internationalizing routines provided within this package, enable
the use of the `catgets' functions (if found on the locale system), or
else, *totally* disable translation of messages.
When you already have GNU `gettext' installed on your system and run
configure without an option for your new package, `configure' will
probably detect the previously built and installed `libintl.a' file and
will decide to use this. This might be not what is desirable. You
should use the more recent version of the GNU `gettext' library. I.e.
if the file `intl/VERSION' shows that the library which comes with this
package is more recent, you should use
./configure --with-included-gettext
to prevent auto-detection.
By default the configuration process will not test for the `catgets'
function and therefore they will not be used. The reasons are already
given above: the emulation on top of `catgets' cannot provide all the
extensions provided by the GNU `gettext' library. If you nevertheless
want to use the `catgets' functions use
./configure --with-catgets
to enable the test for `catgets' (this causes no harm if `catgets' is
not available on your system). If you really select this option we
would like to hear about the reasons because we cannot think of any
good one ourself.
Internationalized packages have usually many `po/LL.po' files, where
LL gives an ISO 639 two-letter code identifying the language. Unless
translations have been forbidden at `configure' time by using the
`--disable-nls' switch, all available translations are installed
together with the package. However, the environment variable `LINGUAS'
may be set, prior to configuration, to limit the installed set.
`LINGUAS' should then contain a space separated list of two-letter
codes, stating which languages are allowed.
Using This Package
==================
As a user, if your language has been installed for this package, you
only have to set the `LANG' environment variable to the appropriate
ISO 639 `LL' two-letter code prior to using the programs in the
package. For example, let's suppose that you speak German. At the
shell prompt, merely execute `setenv LANG de' (in `csh'),
`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
can be done from your `.login' or `.profile' file, once and for all.
An operating system might already offer message localization for
many of its programs, while other programs have been installed locally
with the full capabilities of GNU `gettext'. Just using `gettext'
extended syntax for `LANG' would break proper localization of already
available operating system programs. In this case, users should set
both `LANGUAGE' and `LANG' variables in their environment, as programs
using GNU `gettext' give preference to `LANGUAGE'. For example, some
Swedish users would rather read translations in German than English for
when Swedish is not available. This is easily accomplished by setting
`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
Translating Teams
=================
For the Free Translation Project to be a success, we need interested
people who like their own language and write it well, and who are also
able to synergize with other translators speaking the same language.
Each translation team has its own mailing list, courtesy of Linux
International. You may reach your translation team at the address
`LL@li.org', replacing LL by the two-letter ISO 639 code for your
language. Language codes are *not* the same as the country codes given
in ISO 3166. The following translation teams exist, as of December
1997:
Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
`hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
`pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
Swedish `sv', and Turkish `tr'.
For example, you may reach the Chinese translation team by writing to
`zh@li.org'.
If you'd like to volunteer to *work* at translating messages, you
should become a member of the translating team for your own language.
The subscribing address is *not* the same as the list itself, it has
`-request' appended. For example, speakers of Swedish can send a
message to `sv-request@li.org', having this message body:
subscribe
Keep in mind that team members are expected to participate
*actively* in translations, or at solving translational difficulties,
rather than merely lurking around. If your team does not exist yet and
you want to start one, or if you are unsure about what to do or how to
get started, please write to `translation@iro.umontreal.ca' to reach the
coordinator for all translator teams.
The English team is special. It works at improving and uniformizing
the terminology in use. Proven linguistic skill are praised more than
programming skill, here.
Available Packages
==================
Languages are not equally supported in all packages. The following
matrix shows the current state of internationalization, as of December
1997. The matrix shows, in regard of each package, for which languages
PO files have been submitted to translation coordination.
Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
.----------------------------------------------------.
bash | [] [] [] | 3
bison | [] [] [] | 3
clisp | [] [] [] [] | 4
cpio | [] [] [] [] [] [] | 6
diffutils | [] [] [] [] [] | 5
enscript | [] [] [] [] [] [] | 6
fileutils | [] [] [] [] [] [] [] [] [] [] | 10
findutils | [] [] [] [] [] [] [] [] [] | 9
flex | [] [] [] [] | 4
gcal | [] [] [] [] [] | 5
gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
grep | [] [] [] [] [] [] [] [] [] [] | 10
hello | [] [] [] [] [] [] [] [] [] [] [] | 11
id-utils | [] [] [] | 3
indent | [] [] [] [] [] | 5
libc | [] [] [] [] [] [] [] | 7
m4 | [] [] [] [] [] [] | 6
make | [] [] [] [] [] [] | 6
music | [] [] | 2
ptx | [] [] [] [] [] [] [] [] | 8
recode | [] [] [] [] [] [] [] [] [] | 9
sh-utils | [] [] [] [] [] [] [] [] | 8
sharutils | [] [] [] [] [] [] | 6
tar | [] [] [] [] [] [] [] [] [] [] [] | 11
texinfo | [] [] [] | 3
textutils | [] [] [] [] [] [] [] [] [] | 9
wdiff | [] [] [] [] [] [] [] [] | 8
`----------------------------------------------------'
17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
Some counters in the preceding matrix are higher than the number of
visible blocks let us expect. This is because a few extra PO files are
used for implementing regional variants of languages, or language
dialects.
For a PO file in the matrix above to be effective, the package to
which it applies should also have been internationalized and
distributed as such by its maintainer. There might be an observable
lag between the mere existence a PO file and its wide availability in a
distribution.
If December 1997 seems to be old, you may fetch a more recent copy
of this `ABOUT-NLS' file on most GNU archive sites.

View File

@@ -47,6 +47,7 @@ Other contributors:
Jim Kelton <jim_kelton@tivoli.com>
David Lubbren <uhay@rz.uni-karlsruhe.de>
Tim Magill <tim.magill@telops.gte.com>
Greg McGary <greg@mcgary.org>
Han-Wen Nienhuys <hanwen@cs.uu.nl>
Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Carl Staelin (Princeton University)

6860
ChangeLog

File diff suppressed because it is too large Load Diff

6648
ChangeLog.2 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
# -*-Makefile-*- template for DJGPP
# Makefile.in generated automatically by automake 1.2 from Makefile.am
# Copyright (C) 1994, 1995-1998, 1999 Free Software Foundation, Inc.
# Copyright (C) 1994, 1995-1998, 1999, 2002 Free Software Foundation, Inc.
# This Makefile.DOS is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
@@ -15,26 +15,25 @@ VPATH = $(srcdir)
prefix = /dev/env/DJDIR
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
datadir = ${prefix}/share
libdir = ${prefix}/lib
infodir = ${prefix}/info
# DJGPP doesn't have separate man tree, use info instead.
mandir = ${prefix}/info
includedir = ${prefix}/include
bindir = /bin
datadir = /share
libdir = /lib
infodir = /info
mandir = /man
includedir = /include
oldincludedir = c:/djgpp/include
DESTDIR =
DESTDIR = /dev/env/DJDIR
pkgdatadir = $(datadir)/make
pkglibdir = $(libdir)/make
pkgincludedir = $(includedir)/make
localedir = $(prefix)/share/locale
localedir = $(datadir)/locale
INSTALL = ${bindir}/ginstall -c
INSTALL_PROGRAM = ${bindir}/ginstall -c
INSTALL_DATA = ${bindir}/ginstall -c -m 644
INSTALL_SCRIPT = ${bindir}/ginstall -c
INSTALL = ${exec_prefix}/bin/ginstall -c
INSTALL_PROGRAM = ${exec_prefix}/bin/ginstall -c
INSTALL_DATA = ${exec_prefix}/bin/ginstall -c -m 644
INSTALL_SCRIPT = ${exec_prefix}/bin/ginstall -c
transform = s,x,x,
# This will fail even if they don't have a Unix-like shell (stock DOS
@@ -48,11 +47,15 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
EXEEXT = .exe
OBJEXT = o
AR = ar
AWK = gawk
CC = gcc
CPP = gcc -E
LIBOBJS =
MAKEINFO = ${bindir}/makeinfo
MAKEINFO = ${exec_prefix}/bin/makeinfo
PACKAGE = make
PERL = perl
RANLIB = ranlib
@@ -61,7 +64,7 @@ VERSION = %VERSION%
AUTOMAKE_OPTIONS = 1.2
bin_PROGRAMS = %PROGRAMS%
bin_PROGRAMS = %PROGRAMS%$(EXEEXT)
make_SOURCES = %SOURCES%
# This should include the glob/ prefix
@@ -78,7 +81,7 @@ BUILT_SOURCES = README build.sh-in
EXTRA_DIST = $(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c make-stds.texi texinfo.tex SCOPTIONS SMakefile Makefile.ami README.Amiga config.ami amiga.c amiga.h NMakefile README.DOS configh.dos configure.bat makefile.com README.W32 build_w32.bat config.h-W32 subproc.bat make.lnk config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c vmsify.c
SUBDIRS = glob
mkinstalldirs = ${bindir}/gmkdir -p
mkinstalldirs = ${exec_prefix}/bin/gmkdir -p
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = build.sh
PROGRAMS = $(bin_PROGRAMS)
@@ -100,7 +103,7 @@ CFLAGS = -O2 -g
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
TEXI2DVI = texi2dvi
TEXINFO_TEX = $(srcdir)/texinfo.tex
TEXINFO_TEX = $(srcdir)/config/texinfo.tex
INFO_DEPS = make.info
DVIS = make.dvi
TEXINFOS = make.texinfo
@@ -108,8 +111,7 @@ man1dir = $(mandir)/man1
MANS = $(man_MANS)
NROFF = nroff
DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh.in config.h.in configure configure.in getloadavg.c gettext.c install-sh missing mkinstalldirs stamp-h.in texinfo.tex
DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh-in config.h-in configure configure.in getloadavg.c
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@@ -122,7 +124,7 @@ HEADERS = $(wildcard $(srcdir)/*.h)
default: all
.SUFFIXES:
.SUFFIXES: .S .c .dvi .info .o .ps .s .texi .texinfo .txi
.SUFFIXES: .c .dvi .info .o .obj .ps .texinfo .tex
mostlyclean-hdr:
@@ -154,17 +156,11 @@ uninstall-binPROGRAMS:
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
mostlyclean-compile:
-rm -f *.o *.exe make.new core
-rm -f *.$(OBJEXT) *$(EXEEXT) make.new core
clean-compile:
@@ -173,7 +169,7 @@ distclean-compile:
maintainer-clean-compile:
make: $(make_OBJECTS) $(make_DEPENDENCIES)
make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES)
@command.com /c if exist make del make
@command.com /c if exist make.exe del make.exe
$(LINK) $(make_LDFLAGS) $(make_OBJECTS) $(make_LDADD) $(LIBS)
@@ -184,29 +180,19 @@ make.dvi: make.texinfo
DVIPS = dvips
.texi.info:
$(MAKEINFO) $(srcdir)/$< -o ./$@
.texi.dvi:
TEXINPUTS="$(srcdir);$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
.texi:
$(MAKEINFO) $(srcdir)/$< -o ./$@
.texinfo.info:
$(MAKEINFO) $(srcdir)/$< -o ./$@
@command.com /c if exist make.info* del make.info*
@command.com /c if exist make.i* del make.i*
$(MAKEINFO) -I$(srcdir) $< -o ./$@
.texinfo:
$(MAKEINFO) $(srcdir)/$< -o ./$@
@command.com /c if exist make.info* del make.info*
@command.com /c if exist make.i* del make.i*
$(MAKEINFO) -I$(srcdir) $< -o ./$@
.texinfo.dvi:
TEXINPUTS="$(srcdir);$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
.txi.info:
$(MAKEINFO) $(srcdir)/$< -o ./$@
.txi.dvi:
TEXINPUTS="$(srcdir);$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
.dvi.ps:
$(DVIPS) $< -o $@
@@ -543,3 +529,40 @@ check-regression:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# --------------- DEPENDENCIES
ar.o: ar.c make.h config.h gettext.h filedef.h dep.h glob/fnmatch.h
arscan.o: arscan.c make.h config.h gettext.h
commands.o: commands.c make.h config.h gettext.h dep.h filedef.h \
variable.h job.h commands.h
default.o: default.c make.h config.h gettext.h rule.h dep.h filedef.h \
job.h commands.h variable.h
dir.o: dir.c make.h config.h gettext.h glob/glob.h
expand.o: expand.c make.h config.h gettext.h filedef.h job.h commands.h \
variable.h rule.h
file.o: file.c make.h config.h gettext.h dep.h filedef.h job.h \
commands.h variable.h debug.h
function.o: function.c make.h config.h gettext.h filedef.h variable.h \
dep.h job.h commands.h debug.h
getopt.o: getopt.c config.h gettext.h getopt.h
getopt1.o: getopt1.c config.h getopt.h
implicit.o: implicit.c make.h config.h gettext.h rule.h dep.h filedef.h \
debug.h
job.o: job.c make.h config.h gettext.h job.h debug.h filedef.h \
commands.h variable.h
main.o: main.c make.h config.h gettext.h dep.h filedef.h variable.h \
job.h commands.h rule.h debug.h getopt.h
misc.o: misc.c make.h config.h gettext.h dep.h debug.h
read.o: read.c make.h config.h gettext.h glob/glob.h dep.h filedef.h \
job.h commands.h variable.h rule.h debug.h
remake.o: remake.c make.h config.h gettext.h filedef.h job.h commands.h \
dep.h variable.h debug.h
remote-stub.o: remote-stub.c make.h config.h gettext.h filedef.h job.h \
commands.h
rule.o: rule.c make.h config.h gettext.h dep.h filedef.h job.h \
commands.h variable.h rule.h
signame.o: signame.c make.h config.h gettext.h
variable.o: variable.c make.h config.h gettext.h dep.h filedef.h job.h \
commands.h variable.h rule.h
version.o: version.c config.h
vpath.o: vpath.c make.h config.h gettext.h filedef.h variable.h

View File

@@ -1,62 +1,64 @@
# This is a -*-Makefile-*-, or close enough
AUTOMAKE_OPTIONS = 1.4
AUTOMAKE_OPTIONS = 1.7 dist-bzip2 check-news
ACLOCAL_AMFLAGS = -I config
SUBDIRS = $(GLOBDIR) i18n
SUBDIRS = glob config po doc
bin_PROGRAMS = make
# These source files also have gettext references
SRCS = ar.c arscan.c commands.c dir.c expand.c file.c function.c \
getopt.c implicit.c job.c main.c misc.c read.c remake.c \
rule.c signame.c variable.c vpath.c
if USE_CUSTOMS
remote = remote-cstms.c
else
remote = remote-stub.c
endif
make_SOURCES = $(SRCS) default.c remote-$(REMOTE).c version.c \
getopt1.c
make_SOURCES = ar.c arscan.c commands.c default.c dir.c expand.c file.c \
function.c getopt.c getopt1.c implicit.c job.c main.c \
misc.c read.c remake.c $(remote) rule.c signame.c \
variable.c version.c vpath.c hash.c
EXTRA_make_SOURCES = remote-stub.c remote-cstms.c
noinst_HEADERS = commands.h dep.h filedef.h job.h make.h rule.h variable.h \
debug.h signame.h getopt.h gettext.h
debug.h getopt.h gettext.h hash.h
make_LDADD = $(LIBOBJS) @ALLOCA@ $(GLOBLIB)
make_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@
man_MANS = make.1
info_TEXINFOS = make.texinfo
DEFS = -DALIASPATH=\"$(aliaspath)\" -DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@
DEFS = -DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@
INCLUDES = -I. -I$(srcdir) $(GLOBINC)
AM_CPPFLAGS = $(GLOBINC)
EXTRA_DIST = README build.sh.in $(man_MANS) README.customs remote-cstms.c\
make-stds.texi SCOPTIONS SMakefile\
# Extra stuff to include in the distribution.
# Note we need all the glob stuff here, rather than in glob/Makefile.am,
# because often that directory isn't built on the systems used by the
# maintainers.
EXTRA_DIST = README build.sh.in $(man_MANS)\
README.customs\
SCOPTIONS SMakefile\
README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h\
README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\
README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat\
readme.vms makefile.vms makefile.com config.h-vms vmsdir.h\
vmsfunctions.c vmsify.c\
gettext.c\
glob/COPYING.LIB glob/ChangeLog glob/Makefile.am\
glob/Makefile.ami glob/Makefile.in glob/SCOPTIONS\
glob/SMakefile glob/configure.bat glob/fnmatch.c\
glob/fnmatch.h glob/glob.c glob/glob.h
MOSTLYCLEANFILES = loadavg.c
CLEANFILES = loadavg
readme.vms makefile.vms makefile.com config.h-vms \
vmsdir.h vmsfunctions.c vmsify.c
MAKE_HOST = @MAKE_HOST@
# Forward targets
html:
cd doc && $(MAKE) $(AM_MAKEFLAGS) $@
.PHONY: html
# --------------- Internationalization Section
POTFILES = $(SRCS) remote-cstms.c vmsfunctions.c
localedir = $(prefix)/share/locale
aliaspath = $(localedir):.
all-local: $(srcdir)/stamp-pot
$(srcdir)/stamp-pot: $(POTFILES)
@echo "$(POTFILES)" > $@
localedir = $(datadir)/locale
# --------------- Local INSTALL Section
@@ -93,7 +95,7 @@ install-exec-local:
#
dist-hook:
(cd $(srcdir); \
sub=`find w32 tests -follow \( -name CVS -prune -o -name work -prune \) -o \( -name \*.orig -o -name \*.rej -o -name \*~ -prune \) -o -type f -print`; \
sub=`find w32 tests -follow \( -name CVS -prune -o -name .cvsignore -o -name work -prune \) -o \( -name \*.orig -o -name \*.rej -o -name \*~ -prune \) -o -type f -print`; \
tar chf - $$sub) \
| (cd $(distdir); tar xfBp -)
@@ -111,25 +113,21 @@ check-local: check-regression check-loadavg
.PHONY: check-loadavg check-regression
# > check-loadavg
#
loadavg: loadavg.c config.h
@rm -f loadavg
$(LINK) -DTEST $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(make_LDFLAGS) loadavg.c $(LIBS)
# We copy getloadavg.c into a different file rather than compiling it
# directly because some compilers clobber getloadavg.o in the process.
#
loadavg.c: getloadavg.c
ln $(srcdir)/getloadavg.c loadavg.c || \
cp $(srcdir)/getloadavg.c loadavg.c
check-loadavg: loadavg
@echo The system uptime program believes the load average to be:
-uptime
@echo The GNU load average checking code believes:
@echo The GNU load average checking code thinks:
-./loadavg
# The loadavg function is invoked during "make check" to test getloadavg.
noinst_PROGRAMS = loadavg
loadavg_SOURCES = loadavg.c
loadavg_CFLAGS = -DTEST
loadavg_LDADD = @GETLOADAVG_LIBS@
loadavg.c: $(srcdir)/getloadavg.c
cp $(srcdir)/getloadavg.c loadavg.c
# > check-regression
#
# Look for the make test suite, and run it if found and we can find perl.
@@ -159,12 +157,6 @@ check-regression:
fi
# --------------- Local CLEAN section
maintainer-clean-local:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
# --------------- Maintainer's Section
@MAINT_MAKEFILE@

108
NEWS
View File

@@ -1,8 +1,8 @@
GNU make NEWS -*-indented-text-*-
History of user-visible changes.
25 Jan 2000
03 October 2002
Copyright (C) 1992,93,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
Copyright (C) 2002 Free Software Foundation, Inc.
See the end for copying conditions.
All changes mentioned here are more fully described in the GNU make
@@ -12,6 +12,92 @@ Please send GNU make bug reports to <bug-make@gnu.org>.
See the README file and the GNU make manual for details on sending bug
reports.
Version 3.80
* A new feature exists: order-only prerequisites. These prerequisites
affect the order in which targets are built, but they do not impact
the rebuild/no-rebuild decision of their dependents. That is to say,
they allow you to require target B be built before target A, without
requiring that target A will always be rebuilt if target B is updated.
Patch for this feature provided by Greg McGary <greg@mcgary.org>.
* For compatibility with SysV make, GNU make now supports the peculiar
syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule.
This syntax is only valid within explicit and static pattern rules: it
cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan
<egp@free.fr> provided a patch implementing this feature; however, I
decided to implement it in a different way.
* The argument to the "ifdef" conditional is now expanded before it's
tested, so it can be a constructed variable name.
Similarly, the arguments to "export" (when not used in a variable
definition context) and "unexport" are also now expanded.
* A new function is defined: $(value ...). The argument to this
function is the _name_ of a variable. The result of the function is
the value of the variable, without having been expanded.
* A new function is defined: $(eval ...). The arguments to this
function should expand to makefile commands, which will then be
evaluated as if they had appeared in the makefile. In combination
with define/endef multiline variable definitions this is an extremely
powerful capability. The $(value ...) function is also sometimes
useful here.
* A new built-in variable is defined, $(MAKEFILE_LIST). It contains a
list of each makefile GNU make has read, or started to read, in the
order in which they were encountered. So, the last filename in the
list when a makefile is just being read (before any includes) is the
name of the current makefile.
* A new built-in variable is defined: $(.VARIABLES). When it is
expanded it returns a complete list of variable names defined by all
makefiles at that moment.
* A new command-line option is defined, -B or --always-make. If
specified GNU make will consider all targets out-of-date even if they
would otherwise not be.
* The arguments to $(call ...) functions were being stored in $1, $2,
etc. as recursive variables, even though they are fully expanded
before assignment. This means that escaped dollar signs ($$ etc.)
were not behaving properly. Now the arguments are stored as simple
variables. This may mean that if you added extra escaping to your
$(call ...) function arguments you will need to undo it now.
* The variable invoked by $(call ...) can now be recursive: unlike other
variables it can reference itself and this will not produce an error
when it is used as the first argument to $(call ...) (but only then).
* New pseudo-target .LOW_RESOLUTION_TIME, superseding the configure
option --disable-nsec-timestamps. You might need this if your build
process depends on tools like "cp -p" preserving time stamps, since
"cp -p" (right now) doesn't preserve the subsecond portion of a time
stamp.
* Updated translations for French, Galician, German, Japanese, Korean,
and Russian. New translations for Croatian, Danish, Hebrew, and
Turkish.
* Updated internationalization support to Gettext 0.11.5.
GNU make now uses Gettext's "external" feature, and does not include
any internationalization code itself. Configure will search your
system for an existing implementation of GNU Gettext (only GNU Gettext
is acceptable) and use it if it exists. If not, NLS will be disabled.
See ABOUT-NLS for more information.
* Updated to autoconf 2.54 and automake 1.7. Users should not be impacted.
Version 3.79.1
* .SECONDARY with no prerequisites now prevents any target from being
removed because make thinks it's an intermediate file, not just those
listed in the makefile.
* New configure option --disable-nsec-timestamps, but this was
superseded in later versions by the .LOW_RESOLUTION_TIME pseudo-target.
Version 3.79
* GNU make optionally supports internationalization and locales via the
@@ -32,27 +118,25 @@ Version 3.79
explicitly within a make rule you may need to re-examine your use for
correctness given this change.
* A new psuedo-target .NOTPARALLEL is available. If defined, the
* A new pseudo-target .NOTPARALLEL is available. If defined, the
current makefile is run serially regardless of the value of -j.
However, submakes are still eligible for parallel execution.
* The $(call ...) function doesn't expand its arguments automatically
anymore. This allows you to put builtin functions like "if" and
"foreach", which also have special expansion rules, in a $(call ...)
function and have it work properly. This was suggested by Damien
GIBOU <damien.gibou@st.com>.
* The --debug option has changed: it now allows optional flags
controlling the amount and type of debugging output. By default only
a minimal amount information is generated, displaying the names of
"normal" targets (not makefiles) were deemed out of date and in need
of being rebuilt.
"normal" targets (not makefiles) that were deemed out of date and in
need of being rebuilt.
Note that the -d option behaves as before: it takes no arguments and
all debugging information is generated.
* The `-p' (print database) output now includes filename and linenumber
information for variable definitions, to help debugging.
information for variable definitions, to aid debugging.
* The wordlist function no longer reverses its arguments if the "start"
value is greater than the "end" value. If that's true, nothing is
returned.
* Hartmut Becker provided many updates for the VMS port of GNU make.
See the readme.vms file for more details.

View File

@@ -34,11 +34,22 @@ New (since 3.74) DOS-specific features:
environment (requires Perl and auxiliary tools; see below).
To build:
To install a binary distribution:
Simply unzip the makNNNb.zip file (where NNN is the version number)
preserving the directory structure (-d switch if you use PKUNZIP).
If you are installing Make on Windows 9X or Windows 2000, use an
unzip program that supports long filenames in zip files. After
unzipping, make sure the directory with make.exe is on your PATH,
and that's all you need to use Make.
To build from sources:
1. Unzip the archive, preserving the directory structure (-d switch
if you use PKUNZIP). If you build Make on Windows 95, use an
unzip program that supports long filenames in zip files.
if you use PKUNZIP). If you build Make on Windows 9X or Windows
2000, use an unzip program that supports long filenames in zip
files.
If you are unpacking an official GNU source distribution, use
either DJTAR (which is part of the DJGPP development
@@ -84,6 +95,15 @@ To build:
will also need GNU Fileutils and GNU Sed for this (they should
be available from the DJGPP sites).
By default, GNU make will install into your DJGPP installation
area. If you wish to use a different directory, override the
DESTDIR variable when invoking "make install", like this:
make install DESTDIR=c:/other/dir
This causes the make executable to be placed in c:/other/dir/bin,
the man pages in c:/other/dir/man, etc.
Without a Unix-style shell, you will have to install programs
and the docs manually. Copy make.exe to a directory on your
PATH, make.i* info files to your Info directory, and update the

141
README.cvs Normal file
View File

@@ -0,0 +1,141 @@
-*-text-*-
Obtaining CVS Code
------------------
This seems redundant, since if you're reading this you most likely have
already performed this step; however, for completeness, you can obtain
the GNU make source code via anonymous CVS from the FSF's Savannah
project <http://savannah.gnu.org/projects/make/>:
$ cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/make co make
You might want to use the "-z3" option to get compression, and you most
certainly will want the -P option to avoid unneeded directories
cluttering up your source. Personally I add these (as well as -dP for
update) to my ~/.cvsrc file.
If you have an older version of CVS, you might have to login first.
There is no password; just hit the ENTER key if you are asked for one.
Building From CVS
-----------------
To build GNU make from CVS, you will need Autoconf 2.53 (or better),
Automake 1.6.3 (or better), and Gettext 0.11.5 (or better), and any
tools that those utilities require (GNU m4, Perl, etc.). You will also
need a copy of wget.
After checking out the code, you will need to perform these steps to get
to the point where you can run "make".
1) $ autopoint
This will instantiate various m4 macros files, etc. in the config
and po directories.
2) $ aclocal -I config
Generate the proper aclocal.m4 file.
3) $ autoheader
Generate a "config.h.in" file from the contents of configure.in,
etc.
4) $ automake --add-missing
Add (symlink) missing files into the distribution, and generate
Makefile.in's from Makefile.am's.
You will see these perhaps unexpected messages (among others which
you should be expecting :)); just ignore them--I know what I'm doing
:).
Makefile.am: required file `./README' not found
configure.in:xxx: required file `./build.sh.in' not found
Makefile.am:xxx: automatically discovered file `getloadavg.c' should not be explicitly mentioned
5) $ autoconf
Generate a "configure" script from configure.in and acinclude.m4.
6) $ ./configure
Generate a Makefile
7) $ make update
Use wget to retrieve various other files that GNU make relies on,
but does not keep in its own source tree.
At this point you have successfully brought your CVS copy of the GNU
make source directory up to the point where it can be treated
more-or-less like the official package you would get from ftp.gnu.org.
That is, you can just run:
$ make && make check && make install
to build and install GNU make.
Creating a Package
------------------
Once you have performed the above steps (including the configuration and
build) you can create a GNU make package. This is very simple, just
run:
$ make dist-gzip
and, if you like:
$ make dist-bzip2
Even better, you should run this:
$ make distcheck
Which will build both .gz and .bz2 package files, then unpack them into
a temporary location, try to build them, and repack them, verifying that
everything works, you get the same results, _and_ no extraneous files
are left over after the "distclean" rule--whew!! Now, _that_ is why
converting to Automake is worth the trouble! A big "huzzah!" to Tom
T. and the AutoToolers!
That's it, you're done!
Appendix A - For The Brave
--------------------------
For those of you who trust me implicitly, or are just brave (or
foolhardy), here is a canned sequence of commands to build a GNU make
distribution package from a virgin CVS source checkout (assuming all the
prerequisites are available of course).
This list is eminently suitable for a quick swipe o' the mouse and a
swift click o' mouse-2 into an xterm. Go for it!
autopoint
aclocal -I config
autoheader
automake --add-missing
autoconf
./configure
make update
make
make check
make distcheck

View File

@@ -19,6 +19,21 @@ Some systems' Make programs are broken and cannot process the Makefile for
GNU Make. If you get errors from your system's Make when building GNU
Make, try using `build.sh' instead.
GNU Make is free software. See the file COPYING for copying conditions.
Downloading
-----------
GNU Make can be obtained in many different ways. See a description here:
http://www.gnu.org/software/software.html
Documentation
-------------
GNU make is fully documented in the GNU Make manual, which is contained
in this distribution as the file make.texinfo. You can also find
on-line and preformatted (PostScript and DVI) versions at the FSF's web
@@ -28,12 +43,35 @@ site. There is information there about ordering hardcopy documentation.
http://www.gnu.org/doc/doc.html
http://www.gnu.org/manual/manual.html
You can also find the latest versions of GNU Make from there.
You can send GNU make bug reports to bug-make@gnu.org. Please see the
Development
-----------
GNU Make development is hosted by Savannah, the FSF's online development
management tool. Savannah is here:
http://savannah.gnu.org
And the GNU Make development page is here:
http://savannah.gnu.org/projects/make/
You can find most information concerning the development of GNU Make at
this site.
Bug Reporting
-------------
You can send GNU make bug reports to <bug-make@gnu.org>. Please see the
section of the GNU make manual entitled `Problems and Bugs' for
information on submitting useful and complete bug reports.
You can also use the online bug tracking system in the Savannah GNU Make
project to submit new problem reports or search for existing ones:
http://savannah.gnu.org/bugs/?group_id=71
If you need help using GNU make, try these forums:
help-make@gnu.org
@@ -41,24 +79,33 @@ If you need help using GNU make, try these forums:
news:gnu.utils.help
news:gnu.utils.bug
Also:
http://savannah.gnu.org/support/?group_id=71
- See README.customs for details on integrating GNU make with the
Customs distributed build environment from the Pmake distribution.
You may also find interesting patches to GNU Make available here:
- See README.W32 for details about GNU Make on Windows NT, 95, or 98.
http://savannah.gnu.org/patch/?group_id=71
- See README.Amiga for details about GNU Make on AmigaDOS.
- See README.DOS for compilation instructions on MS-DOS and MS-Windows
using DJGPP tools.
A precompiled binary of the MSDOS port of GNU Make is available as part
of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more
information.
Note these patches are provided by our users as a service and we make no
statements regarding their correctness. Please contact the authors
directly if you have a problem or suggestion for a patch available on
this page.
GNU Make is free software. See the file COPYING for copying conditions.
CVS Access
----------
The GNU make source repository is available via anonymous CVS from the
GNU Subversions CVS server; look here for details:
http://savannah.gnu.org/cvs/?group_id=71
Please note: you won't be able to build GNU make from CVS without
installing appropriate maintainer's tools, such as GNU m4, automake,
autoconf, Perl, GNU make, and GCC. See the README.cvs file for hints on
how to build GNU make once these tools are available. We make no
guarantees about the contents or quality of the latest code in the CVS
repository: it is not unheard of for code that is known to be broken to
be checked in. Use at your own risk.
System-specific Notes
@@ -79,3 +126,39 @@ files (LFS) in configure for those operating systems that provide it.
Please report any bugs that you find in this area. If you run into
difficulties, then as a workaround you should be able to disable LFS by
adding the `--disable-largefile' option to the `configure' script.
On systems that support micro- and nano-second timestamp values and
where stat(2) provides this information, GNU make will use it when
comparing timestamps to get the most accurate possible result. However,
note that many current implementations of tools that *set* timestamps do
not preserve micro- or nano-second granularity. This means that "cp -p"
and other similar tools (tar, etc.) may not exactly duplicate timestamps
with micro- and nano-second granularity on some systems. If your build
system contains rules that depend on proper behavior of tools like "cp
-p", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to
force make to treat them properly. See the manual for details.
Ports
-----
- See README.customs for details on integrating GNU make with the
Customs distributed build environment from the Pmake distribution.
- See readme.vms for details about GNU Make on OpenVMS.
- See README.Amiga for details about GNU Make on AmigaDOS.
- See README.W32 for details about GNU Make on Windows NT, 95, or 98.
- See README.DOS for compilation instructions on MS-DOS and MS-Windows
using DJGPP tools.
A precompiled binary of the MSDOS port of GNU Make is available as part
of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more
information.
Please note there are two _separate_ ports of GNU make for Microsoft
systems: a native Windows tool built with (for example) MSVC or Cygwin,
and a DOS-based tool built with DJGPP. Please be sure you are looking
at the right README!

View File

@@ -28,13 +28,14 @@ priority on my list of things I don't have time to do right now is
fixing up the GNU make test suite. Most importantly it needs to be made
"parallelizable", so more than one regression can run at the same time
(essentially, make the "work" directory local). Also, the CWD during
the test should be in the work directory; right now sometimes tests leak
files into the main directory which causes subsequent tests to fail
(some tests may need to be tweaked). Beyond that, any cleanup done to
make writing, reading, or handling tests simpler would be great! Please
feel free to make whatever changes you like to the current tests, given
some high-level goals, and that you'll port the current tests to
whatever you do :).
the test should be in the work directory or, better, a test-specific
temporary directory so each test gets a new directory; right now
sometimes tests leak files into the main directory which causes
subsequent tests to fail (some tests may need to be tweaked). Beyond
that, any cleanup done to make writing, reading, or handling tests
simpler would be great! Please feel free to make whatever changes you
like to the current tests, given some high-level goals, and that you'll
port the current tests to whatever you do :).
The Rest of the List
@@ -46,9 +47,9 @@ The Rest of the List
2) Option to check more than timestamps to determine if targets have
changed. This is also a very big one. It's _close_ to my plate :),
and I have very definite ideas about how I want it done. Please
pick something else unless you must have this feature. If you try
it, please work _extremely_ closely with me on it.
and I have very definite ideas about how I would like it done.
Please pick something else unless you must have this feature. If
you try it, please work _extremely_ closely with me on it.
2a) Possibly a special case of this is the .KEEP_STATE feature of Sun's
make. Some great folks at W U. in Canada did an implementation of
@@ -95,7 +96,7 @@ The Rest of the List
doing until #1 is done.
9) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY
psuedo-targets have different capabilities. For example, .PRECIOUS
pseudo-targets have different capabilities. For example, .PRECIOUS
can take a "%", the others can't. Etc. These should all work the
same, insofar as that makes sense.
@@ -105,15 +106,35 @@ The Rest of the List
very important for parallel builds: sometimes you need some stuff
done first but you don't want to rebuild everything because of it.
11) Improved debugging/logging/etc. capabilities. This area is in
desparate need of work; the current -d, -s, etc. options are simply
insufficient. We need different levels of output: some that are
much less verbose. E.g., maybe just print one line about why make
decides to rebuild each target. Also, we could use something like
the -E option for preprocessors; this would print out makefiles
after resolving all includes, immediate variable reverences, etc.
Also, a way to turn on and off obeying the "@" token for scripts
that's independent of -n (so we could have them in effect for -n,
and have them not in effect without -n).
11) Improved debugging/logging/etc. capabilities. Part of this is done:
I introduced a number of debugging enhancements. Tim Magill is (I
think) looking into options to control output more selectively.
One thing I want to do in debugging is add a flag to allow debugging
of variables as they're expanded (!). This would be incredibly
verbose, but could be invaluable when nothing else seems to work and
you just can't figure it out. The way variables are expanded now
means this isn't 100% trivial, but it probably won't be hard.
Maybe other things. Contact me about the user interface.
12) Integration of Guile as an embedded scripting language. This means:
allowing Guile functions to be declared in makefiles somehow, then
providing a syntax for invoking them. At least one formulation of
that would have the function resolve to a string which would be
substituted in the makefile, kind of like $(shell ...) does now, but
using the embedded interpreter so there's no process forked of
course. Obviously this is an optional add-on feature.
It could be more advanced than that, even, who knows? Maybe make
could provide Guile functions that allow Guile scripts more direct
access to internal make structures, somehow. This kind of thing
needs a lot of thought.
Also there's always the flip side: in some very fundamental ways
make isn't the best choice right now for a complex build tool. It's
great for simple-to-medium tasks, but there are already other tools
available for the really tough situations. Ask yourself,
realistically, how much work is worthwhile to add to make, given the
fundamentals you can't really overcome without significantly
affecting backward compatibility--and then why not use another tool
in the first place?
Something to think about.

View File

@@ -1,60 +0,0 @@
/* Name of this package (needed by automake) */
#undef PACKAGE
/* Version of this package (needed by automake) */
#undef VERSION
/* Define to 1 if NLS is requested. */
#undef ENABLE_NLS
/* Define as 1 if you have dcgettext. */
#undef HAVE_DCGETTEXT
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
#undef HAVE_GETTEXT
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to the installation directory for locales. */
#undef LOCALEDIR
/* Define as 1 if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define to the name of the SCCS `get' command. */
#undef SCCS_GET
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
#undef SCCS_GET_MINUS_G
/* Define this to enable job server support in GNU make. */
#undef MAKE_JOBSERVER
/* Define to be the nanoseconds member of struct stat's st_mtim,
if it exists. */
#undef ST_MTIM_NSEC
/* Define this if the C library defines the variable `sys_siglist'. */
#undef HAVE_SYS_SIGLIST
/* Define this if the C library defines the variable `_sys_siglist'. */
#undef HAVE__SYS_SIGLIST
/* Define this if you have the `union wait' type in <sys/wait.h>. */
#undef HAVE_UNION_WAIT
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#undef uintmax_t
/* These are for AC_FUNC_SELECT */
/* Define if the system doesn't provide fd_set. */
#undef fd_set
/* Define the type of the first arg to select(). */
#undef fd_set_size_t
/* Define this if select() args need to be cast away from fd_set (HP-UX). */
#undef SELECT_FD_SET_CAST

View File

@@ -66,7 +66,7 @@ dnl set to 'no').
AC_DEFUN([CF_RECHECK_FUNC],[
AC_CHECK_LIB($2,$1,[
CF_UPPER(cf_tr_func,$1)
AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func)
AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1])
ac_cv_func_$1=yes
$3="-l$2 [$]$3"],[
ac_cv_func_$1=unknown
@@ -84,173 +84,12 @@ $1=`echo $2 | tr '[a-z]' '[A-Z]'`
changequote([,])dnl
])dnl
dnl ---------------------------------------------------------------------------
dnl Got this from the GNU tar 1.13.11 distribution
dnl by Paul Eggert <eggert@twinsun.com>
dnl ---------------------------------------------------------------------------
dnl By default, many hosts won't let programs access large files;
dnl one must use special compiler options to get large-file access to work.
dnl For more details about this brain damage please see:
dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
dnl Written by Paul Eggert <eggert@twinsun.com>.
dnl Internal subroutine of AC_SYS_LARGEFILE.
dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
AC_DEFUN(AC_SYS_LARGEFILE_FLAGS,
[AC_CACHE_CHECK([for $1 value to request large file support],
ac_cv_sys_largefile_$1,
[if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
then
ac_cv_sys_largefile_$1=`cat conftest.1`
else
ac_cv_sys_largefile_$1=no
ifelse($1, CFLAGS,
[case "$host_os" in
# HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
changequote(, )dnl
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
changequote([, ])dnl
if test "$GCC" = yes; then
ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__
fi
;;
# IRIX 6.2 and later require cc -n32.
changequote(, )dnl
irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
changequote([, ])dnl
if test "$GCC" != yes; then
ac_cv_sys_largefile_CFLAGS=-n32
fi
esac
if test "$ac_cv_sys_largefile_CFLAGS" != no; then
ac_save_CC="$CC"
CC="$CC $ac_cv_sys_largefile_CFLAGS"
AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
CC="$ac_save_CC"
fi])
fi
rm -f conftest*])])
dnl Internal subroutine of AC_SYS_LARGEFILE.
dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
AC_DEFUN(AC_SYS_LARGEFILE_SPACE_APPEND,
[case $2 in
no) ;;
?*)
case "[$]$1" in
'') $1=$2 ;;
*) $1=[$]$1' '$2 ;;
esac ;;
esac])
dnl Internal subroutine of AC_SYS_LARGEFILE.
dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE,
[AC_CACHE_CHECK([for $1], $2,
[$2=no
changequote(, )dnl
$4
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
case "$ac_flag" in
-D$1)
$2=1 ;;
-D$1=*)
$2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
esac
done
changequote([, ])dnl
])
if test "[$]$2" != no; then
AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
fi])
AC_DEFUN(AC_SYS_LARGEFILE,
[AC_REQUIRE([AC_CANONICAL_HOST])
AC_ARG_ENABLE(largefile,
[ --disable-largefile omit support for large files])
if test "$enable_largefile" != no; then
AC_CHECK_TOOL(GETCONF, getconf)
AC_SYS_LARGEFILE_FLAGS(CFLAGS)
AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
AC_SYS_LARGEFILE_FLAGS(LIBS)
for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
case "$ac_flag" in
no) ;;
-D_FILE_OFFSET_BITS=*) ;;
-D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
-D_LARGE_FILES | -D_LARGE_FILES=*) ;;
-D?* | -I?*)
AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
*)
AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
esac
done
AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
ac_cv_sys_file_offset_bits,
[Number of bits in a file offset, on hosts where this is settable.],
[case "$host_os" in
# HP-UX 10.20 and later
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
ac_cv_sys_file_offset_bits=64 ;;
esac])
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
ac_cv_sys_largefile_source,
[Define to make fseeko etc. visible, on some hosts.],
[case "$host_os" in
# HP-UX 10.20 and later
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
ac_cv_sys_largefile_source=1 ;;
esac])
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
ac_cv_sys_large_files,
[Define for large files, on AIX-style hosts.],
[case "$host_os" in
# AIX 4.2 and later
aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
ac_cv_sys_large_files=1 ;;
esac])
fi
])
dnl ---------------------------------------------------------------------------
dnl From Paul Eggert <eggert@twinsun.com>
dnl Define HAVE_INTTYPES_H if <inttypes.h> exists,
dnl doesn't clash with <sys/types.h>, and declares uintmax_t.
AC_DEFUN(jm_AC_HEADER_INTTYPES_H,
[
if test x = y; then
dnl This code is deliberately never run via ./configure.
dnl FIXME: this is a gross hack to make autoheader put an entry
dnl for `HAVE_INTTYPES_H' in config.h.in.
AC_CHECK_FUNCS(INTTYPES_H)
fi
AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h,
[AC_TRY_COMPILE(
[#include <sys/types.h>
#include <inttypes.h>],
[uintmax_t i = (uintmax_t) -1;],
jm_ac_cv_header_inttypes_h=yes,
jm_ac_cv_header_inttypes_h=no)])
if test $jm_ac_cv_header_inttypes_h = yes; then
ac_kludge=HAVE_INTTYPES_H
AC_DEFINE_UNQUOTED($ac_kludge)
fi
])
dnl ---------------------------------------------------------------------------
dnl From Paul Eggert <eggert@twinsun.com>
AC_DEFUN(AC_STRUCT_ST_MTIM_NSEC,
[AC_CACHE_CHECK([for nanoseconds member of struct stat.st_mtim],
[AC_CACHE_CHECK([for nanoseconds field of struct stat.st_mtim],
ac_cv_struct_st_mtim_nsec,
[ac_save_CPPFLAGS="$CPPFLAGS"
ac_cv_struct_st_mtim_nsec=no
@@ -268,307 +107,58 @@ AC_DEFUN(AC_STRUCT_ST_MTIM_NSEC,
CPPFLAGS="$ac_save_CPPFLAGS"])
if test $ac_cv_struct_st_mtim_nsec != no; then
AC_DEFINE_UNQUOTED(ST_MTIM_NSEC, $ac_cv_struct_st_mtim_nsec)
AC_DEFINE_UNQUOTED(ST_MTIM_NSEC, $ac_cv_struct_st_mtim_nsec, [Define if 'struct stat' contains a nanoseconds field])
fi
]
)
dnl ---------------------------------------------------------------------------
dnl From Paul Eggert <eggert@twinsun.com>
dnl Define uintmax_t to `unsigned long' or `unsigned long long'
dnl if <inttypes.h> does not exist.
AC_DEFUN(jm_AC_TYPE_UINTMAX_T,
[
AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
if test $jm_ac_cv_header_inttypes_h = no; then
AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long,
[AC_TRY_LINK([unsigned long long ull = 1; int i = 63;],
[unsigned long long ullmax = (unsigned long long) -1;
return ull << i | ull >> i | ullmax / ull | ullmax % ull;],
ac_cv_type_unsigned_long_long=yes,
ac_cv_type_unsigned_long_long=no)])
if test $ac_cv_type_unsigned_long_long = yes; then
AC_DEFINE(uintmax_t, unsigned long long)
else
AC_DEFINE(uintmax_t, unsigned long)
fi
fi
])
dnl ---------------------------------------------------------------------------
dnl From Steve Robbins <steve@nyongwa.montreal.qc.ca>
dnl This will be in the next version of autoconf; take this out then!
dnl From a proposed change made on the autoconf list on 2 Feb 1999
dnl http://sourceware.cygnus.com/ml/autoconf/1999-02/msg00001.html
dnl Patch for AIX 3.2 by Lars Hecking <lhecking@nmrc.ucc.ie> on 17 May 1999
AC_DEFUN(AC_FUNC_SELECT,
[AC_CHECK_FUNCS(select)
if test "$ac_cv_func_select" = yes; then
AC_CHECK_HEADERS(unistd.h sys/types.h sys/time.h sys/select.h sys/socket.h)
AC_MSG_CHECKING([argument types of select()])
AC_CACHE_VAL(ac_cv_type_fd_set_size_t,dnl
[AC_CACHE_VAL(ac_cv_type_fd_set,dnl
[for ac_cv_type_fd_set in 'fd_set' 'int' 'void'; do
for ac_cv_type_fd_set_size_t in 'int' 'size_t' 'unsigned long' 'unsigned'; do
for ac_type_timeval in 'struct timeval' 'const struct timeval'; do
AC_TRY_COMPILE(dnl
[#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif],
[#ifdef __STDC__
extern select ($ac_cv_type_fd_set_size_t,
$ac_cv_type_fd_set *, $ac_cv_type_fd_set *, $ac_cv_type_fd_set *,
$ac_type_timeval *);
#else
extern select ();
$ac_cv_type_fd_set_size_t s;
$ac_cv_type_fd_set *p;
$ac_type_timeval *t;
#endif],
[ac_found=yes ; break 3],ac_found=no)
done
done
done
])dnl AC_CACHE_VAL
])dnl AC_CACHE_VAL
if test "$ac_found" = no; then
AC_MSG_ERROR([can't determine argument types])
fi
AC_MSG_RESULT([select($ac_cv_type_fd_set_size_t,$ac_cv_type_fd_set *,...)])
AC_DEFINE_UNQUOTED(fd_set_size_t, $ac_cv_type_fd_set_size_t)
ac_cast=
if test "$ac_cv_type_fd_set" != fd_set; then
# Arguments 2-4 are not fd_set. Some weirdo systems use fd_set type for
# FD_SET macros, but insist that you cast the argument to select. I don't
# understand why that might be, but it means we cannot define fd_set.
AC_EGREP_CPP(dnl
changequote(<<,>>)dnl
<<(^|[^a-zA-Z_0-9])fd_set[^a-zA-Z_0-9]>>dnl
changequote([,]),dnl
[#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif],dnl
# We found fd_set type in a header, need special cast
ac_cast="($ac_cv_type_fd_set *)",dnl
# No fd_set type; it is safe to define it
AC_DEFINE_UNQUOTED(fd_set,$ac_cv_type_fd_set))
fi
AC_DEFINE_UNQUOTED(SELECT_FD_SET_CAST,$ac_cast)
# make_FUNC_SETVBUF_REVERSED
# ------------------------
AC_DEFUN([make_FUNC_SETVBUF_REVERSED],
[AC_REQUIRE([AC_C_PROTOTYPES])dnl
AC_CACHE_CHECK(whether setvbuf arguments are reversed,
ac_cv_func_setvbuf_reversed,
[ac_cv_func_setvbuf_reversed=no
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdio.h>
# if PROTOTYPES
int (setvbuf) (FILE *, int, char *, size_t);
# endif]],
[[char buf; return setvbuf (stdout, _IOLBF, &buf, 1);]])],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdio.h>
# if PROTOTYPES
int (setvbuf) (FILE *, int, char *, size_t);
# endif]],
[[char buf; return setvbuf (stdout, &buf, _IOLBF, 1);]])],
[# It compiles and links either way, so it must not be declared
# with a prototype and most likely this is a K&R C compiler.
# Try running it.
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdio.h>]],
[[/* This call has the arguments reversed.
A reversed system may check and see that the address of buf
is not _IOLBF, _IONBF, or _IOFBF, and return nonzero. */
char buf;
if (setvbuf (stdout, _IOLBF, &buf, 1) != 0)
exit (1);
putchar ('\r');
exit (0); /* Non-reversed systems SEGV here. */]])],
ac_cv_func_setvbuf_reversed=yes,
rm -f core core.* *.core,
[[: # Assume setvbuf is not reversed when cross-compiling.]])]
ac_cv_func_setvbuf_reversed=yes)])])
if test $ac_cv_func_setvbuf_reversed = yes; then
AC_DEFINE(SETVBUF_REVERSED, 1,
[Define to 1 if the `setvbuf' function takes the buffering type as
its second argument and the buffer pointer as the third, as on
System V before release 3.])
fi
])
# The following is taken from automake 1.4,
# except that it prefers the compiler option -Ae to "-Aa -D_HPUX_SOURCE"
# because only the former supports 64-bit integral types on HP-UX 10.20.
## ----------------------------------------- ##
## ANSIfy the C compiler whenever possible. ##
## From Franc,ois Pinard ##
## ----------------------------------------- ##
# serial 2
# @defmac AC_PROG_CC_STDC
# @maindex PROG_CC_STDC
# @ovindex CC
# If the C compiler in not in ANSI C mode by default, try to add an option
# to output variable @code{CC} to make it so. This macro tries various
# options that select ANSI C on some system or another. It considers the
# compiler to be in ANSI C mode if it handles function prototypes correctly.
#
# If you use this macro, you should check after calling it whether the C
# compiler has been set to accept ANSI C; if not, the shell variable
# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
# code in ANSI C, you can make an un-ANSIfied copy of it by using the
# program @code{ansi2knr}, which comes with Ghostscript.
# @end defmac
AC_DEFUN(AM_PROG_CC_STDC,
[AC_REQUIRE([AC_PROG_CC])
AC_BEFORE([$0], [AC_C_INLINE])
AC_BEFORE([$0], [AC_C_CONST])
dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
dnl a magic option to avoid problems with ANSI preprocessor commands
dnl like #elif.
dnl FIXME: can't do this because then AC_AIX won't work due to a
dnl circular dependency.
dnl AC_BEFORE([$0], [AC_PROG_CPP])
AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
AC_CACHE_VAL(am_cv_prog_cc_stdc,
[am_cv_prog_cc_stdc=no
ac_save_CC="$CC"
# Don't try gcc -ansi; that turns off useful extensions and
# breaks some systems' header files.
# AIX -qlanglvl=ansi
# Ultrix and OSF/1 -std1
# HP-UX -Aa -D_HPUX_SOURCE
# SVR4 -Xc -D__EXTENSIONS__
for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
AC_TRY_COMPILE(
[#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
char **p;
int i;
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
], [
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
],
[am_cv_prog_cc_stdc="$ac_arg"; break])
done
CC="$ac_save_CC"
])
if test -z "$am_cv_prog_cc_stdc"; then
AC_MSG_RESULT([none needed])
else
AC_MSG_RESULT($am_cv_prog_cc_stdc)
fi
case "x$am_cv_prog_cc_stdc" in
x|xno) ;;
*) CC="$CC $am_cv_prog_cc_stdc" ;;
esac
])
dnl ---------------------------------------------------------------------------
dnl Enable internationalization support for GNU make.
dnl Obtained from the libit 0.7 distribution
dnl
AC_DEFUN(fp_WITH_GETTEXT, [
AC_MSG_CHECKING(whether NLS is wanted)
AC_ARG_ENABLE(nls,
[ --disable-nls disallow Native Language Support],
enable_nls=$enableval, enable_nls=yes)
AC_MSG_RESULT($enable_nls)
use_nls=$enable_nls
AM_CONDITIONAL(USE_NLS, test $use_nls = yes)
if test $enable_nls = yes; then
AC_DEFINE(ENABLE_NLS)
AC_ARG_WITH(catgets,
[ --with-catgets say that catgets is not supported],
[AC_MSG_WARN([catgets not supported, --with-catgets ignored])])
AC_CHECK_FUNCS(gettext)
AC_CHECK_LIB(intl, gettext, :)
if test $ac_cv_lib_intl_gettext$ac_cv_func_gettext != nono; then
AC_MSG_CHECKING(whether the included gettext is preferred)
AC_ARG_WITH(included-gettext,
[ --without-included-gettext avoid our provided version of gettext],
with_included_gettext=$withval, with_included_gettext=yes)
AC_MSG_RESULT($with_included_gettext)
if test $with_included_gettext$ac_cv_func_gettext = nono; then
LIBS="$LIBS -lintl"
fi
else
with_included_gettext=yes
fi
if test $with_included_gettext = yes; then
LIBOBJS="$LIBOBJS gettext.o"
AC_DEFINE(HAVE_GETTEXT)
AC_DEFINE(HAVE_DCGETTEXT)
else
AC_CHECK_HEADERS(libintl.h)
AC_CHECK_FUNCS(dcgettext gettext)
fi
AC_CHECK_HEADERS(locale.h)
AC_CHECK_FUNCS(getcwd setlocale stpcpy)
AM_LC_MESSAGES
if test -z "$ALL_LINGUAS"; then
AC_MSG_WARN(This package does not install translations yet.)
else
ac_items="$ALL_LINGUAS"
for ac_item in $ac_items; do
ALL_POFILES="$ALL_POFILES $ac_item.po"
ALL_MOFILES="$ALL_MOFILES $ac_item.mo"
done
fi
AC_SUBST(ALL_LINGUAS)
AC_SUBST(ALL_POFILES)
AC_SUBST(ALL_MOFILES)
AC_MSG_CHECKING(which translations to install)
if test -z "$LINGUAS"; then
ac_print="$ALL_LINGUAS"
MOFILES="$ALL_MOFILES"
else
ac_items="$LINGUAS"
for ac_item in $ac_items; do
case "$ALL_LINGUAS" in
*$ac_item*)
ac_print="$ac_print $ac_item"
MOFILES="$MOFILES $ac_item.mo"
;;
esac
done
fi
AC_SUBST(MOFILES)
if test -z "$ac_print"; then
AC_MSG_RESULT(none)
else
AC_MSG_RESULT($ac_print)
fi
if test "x$prefix" = xNONE; then
AC_DEFINE_UNQUOTED(LOCALEDIR, "$ac_default_prefix/share/locale")
else
AC_DEFINE_UNQUOTED(LOCALEDIR, "$prefix/share/locale")
fi
fi])
])# make_FUNC_SETVBUF_REVERSED

12
ar.c
View File

@@ -1,5 +1,6 @@
/* Interface to `ar' archives for GNU Make.
Copyright (C) 1988,89,90,91,92,93,97 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1997,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -41,9 +42,14 @@ int
ar_name (name)
char *name;
{
char *p = strchr (name, '('), *end = name + strlen (name) - 1;
char *p = strchr (name, '(');
char *end;
if (p == 0 || p == name || *end != ')')
if (p == 0 || p == name)
return 0;
end = p + strlen (p) - 1;
if (*end != ')')
return 0;
if (p[1] == '(' && end[-1] == ')')

View File

@@ -66,7 +66,7 @@ VMS_get_member_info (module, rfa)
status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc,
&bufdesc.dsc$w_length, 0);
if (! status)
if (! (status & 1))
{
error (NILF, _("lbr$set_module failed to extract module info, status = %d"),
status);
@@ -79,7 +79,11 @@ VMS_get_member_info (module, rfa)
mhd = (struct mhddef *) filename;
#ifdef __DECC
val = decc$fix_time (&mhd->mhd$l_datim);
/* John Fowler <jfowler@nyx.net> writes this is needed in his environment,
* but that decc$fix_time() isn't documented to work this way. Let me
* know if this causes problems in other VMS environments.
*/
val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
#endif
for (i = 0; i < module->dsc$w_length; i++)
@@ -150,7 +154,7 @@ ar_scan (archive, function, arg)
status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
if (! status)
if (! (status & 1))
{
error (NILF, _("lbr$ini_control failed with status = %d"),status);
return -2;
@@ -161,7 +165,7 @@ ar_scan (archive, function, arg)
status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
if (! status)
if (! (status & 1))
{
error (NILF, _("unable to open library `%s' to lookup member `%s'"),
archive, (char *)arg);
@@ -232,7 +236,25 @@ ar_scan (archive, function, arg)
#endif
#ifndef WINDOWS32
# include <ar.h>
# ifndef __BEOS__
# include <ar.h>
# else
/* BeOS 5 doesn't have <ar.h> but has archives in the same format
* as many other Unices. This was taken from GNU binutils for BeOS.
*/
# define ARMAG "!<arch>\n" /* String that begins an archive file. */
# define SARMAG 8 /* Size of that string. */
# define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
struct ar_hdr
{
char ar_name[16]; /* Member file name, sometimes / terminated. */
char ar_date[12]; /* File date, decimal seconds since Epoch. */
char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
char ar_mode[8]; /* File mode, in ASCII octal. */
char ar_size[10]; /* File size, in ASCII decimal. */
char ar_fmag[2]; /* Always contains ARFMAG. */
};
# endif
#else
/* These should allow us to read Windows (VC++) libraries (according to Frank
* Libbrecht <frankl@abzx.belgium.hp.com>)
@@ -775,8 +797,8 @@ ar_member_touch (arname, memname)
if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
goto lose;
/* The file's mtime is the time we we want. */
while (fstat (fd, &statbuf) < 0 && EINTR_SET)
;
if (fstat (fd, &statbuf) < 0)
goto lose;
#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
/* Advance member's time to that time */
for (i = 0; i < sizeof ar_hdr.ar_date; i++)

View File

@@ -27,7 +27,6 @@ CC='@CC@'
CFLAGS='@CFLAGS@'
CPPFLAGS='@CPPFLAGS@'
LDFLAGS='@LDFLAGS@'
defines='@DEFS@ -DLIBDIR="${libdir}" -DINCLUDEDIR="${includedir}"'
ALLOCA='@ALLOCA@'
LOADLIBES='@LIBS@'
extras='@LIBOBJS@'
@@ -37,12 +36,17 @@ GLOBLIB='@GLOBLIB@'
# Common prefix for machine-independent installed files.
prefix='@prefix@'
# Common prefix for machine-dependent installed files.
exec_prefix='@exec_prefix@'
exec_prefix=`eval echo @exec_prefix@`
# Directory to find libraries in for `-lXXX'.
libdir=${exec_prefix}/lib
# Directory to search by default for included makefiles.
includedir=${prefix}/include
localedir=${prefix}/share/locale
aliaspath=${localedir}:.
defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@'
# Exit as soon as any command fails.
set -e
@@ -51,13 +55,14 @@ objs="%objs% remote-${REMOTE}.o ${extras} ${ALLOCA}"
if [ x"$GLOBLIB" != x ]; then
objs="$objs %globobjs%"
globinc=-I${srcdir}/glob
fi
# Compile the source files into those objects.
for file in `echo ${objs} | sed 's/\.o/.c/g'`; do
echo compiling ${file}...
$CC $defines $CPPFLAGS $CFLAGS \
-c -I. -I${srcdir} ${srcdir}/$file
-c -I. -I${srcdir} ${globinc} ${srcdir}/$file
done
# The object files were actually all put in the current directory.

View File

@@ -1,4 +1,5 @@
set make=gnumake
+if not exist config.h copy config.h.W32 config.h
cd w32\subproc
echo "Creating the subproc library"
%ComSpec% /c build.bat

View File

@@ -24,6 +24,12 @@ Boston, MA 02111-1307, USA. */
#include "job.h"
#include "commands.h"
#if VMS
# define FILE_LIST_SEPARATOR ','
#else
# define FILE_LIST_SEPARATOR ' '
#endif
extern int remote_kill PARAMS ((int id, int sig));
#ifndef HAVE_UNISTD_H
@@ -36,7 +42,6 @@ static void
set_file_variables (file)
register struct file *file;
{
register char *p;
char *at, *percent, *star, *less;
#ifndef NO_ARCHIVES
@@ -46,6 +51,8 @@ set_file_variables (file)
if (ar_name (file->name))
{
unsigned int len;
char *p;
p = strchr (file->name, '(');
at = (char *) alloca (p - file->name + 1);
bcopy (file->name, at, p - file->name);
@@ -117,15 +124,17 @@ set_file_variables (file)
DEFINE_VARIABLE ("@", 1, at);
DEFINE_VARIABLE ("%", 1, percent);
/* Compute the values for $^, $+, and $?. */
/* Compute the values for $^, $+, $?, and $|. */
{
register unsigned int qmark_len, plus_len;
unsigned int qmark_len, plus_len, bar_len;
char *caret_value, *plus_value;
register char *cp;
char *cp;
char *qmark_value;
register char *qp;
register struct dep *d;
char *bar_value;
char *qp;
char *bp;
struct dep *d;
unsigned int len;
/* Compute first the value for $+, which is supposed to contain
@@ -133,36 +142,35 @@ set_file_variables (file)
plus_len = 0;
for (d = file->deps; d != 0; d = d->next)
plus_len += strlen (dep_name (d)) + 1;
if (! d->ignore_mtime)
plus_len += strlen (dep_name (d)) + 1;
if (plus_len == 0)
plus_len++;
len = plus_len == 0 ? 1 : plus_len;
cp = plus_value = (char *) alloca (len);
cp = plus_value = (char *) alloca (plus_len);
qmark_len = plus_len; /* Will be this or less. */
qmark_len = plus_len + 1; /* Will be this or less. */
for (d = file->deps; d != 0; d = d->next)
{
char *c = dep_name (d);
if (! d->ignore_mtime)
{
char *c = dep_name (d);
#ifndef NO_ARCHIVES
if (ar_name (c))
{
c = strchr (c, '(') + 1;
len = strlen (c) - 1;
}
else
if (ar_name (c))
{
c = strchr (c, '(') + 1;
len = strlen (c) - 1;
}
else
#endif
len = strlen (c);
len = strlen (c);
bcopy (c, cp, len);
cp += len;
#if VMS
*cp++ = ',';
#else
*cp++ = ' ';
#endif
if (! d->changed)
qmark_len -= len + 1; /* Don't space in $? for this one. */
}
bcopy (c, cp, len);
cp += len;
*cp++ = FILE_LIST_SEPARATOR;
if (! d->changed)
qmark_len -= len + 1; /* Don't space in $? for this one. */
}
/* Kill the last space and define the variable. */
@@ -175,11 +183,18 @@ set_file_variables (file)
uniquize_deps (file->deps);
/* Compute the values for $^ and $?. */
bar_len = 0;
for (d = file->deps; d != 0; d = d->next)
if (d->ignore_mtime)
bar_len += strlen (dep_name (d)) + 1;
if (bar_len == 0)
bar_len++;
/* Compute the values for $^, $?, and $|. */
cp = caret_value = plus_value; /* Reuse the buffer; it's big enough. */
len = qmark_len == 0 ? 1 : qmark_len;
qp = qmark_value = (char *) alloca (len);
qp = qmark_value = (char *) alloca (qmark_len);
bp = bar_value = (char *) alloca (bar_len);
for (d = file->deps; d != 0; d = d->next)
{
@@ -195,23 +210,24 @@ set_file_variables (file)
#endif
len = strlen (c);
bcopy (c, cp, len);
cp += len;
#if VMS
*cp++ = ',';
#else
*cp++ = ' ';
#endif
if (d->changed)
{
bcopy (c, qp, len);
qp += len;
#if VMS
*qp++ = ',';
#else
*qp++ = ' ';
#endif
if (d->ignore_mtime)
{
bcopy (c, bp, len);
bp += len;
*bp++ = FILE_LIST_SEPARATOR;
}
else
{
bcopy (c, cp, len);
cp += len;
*cp++ = FILE_LIST_SEPARATOR;
if (d->changed)
{
bcopy (c, qp, len);
qp += len;
*qp++ = FILE_LIST_SEPARATOR;
}
}
}
/* Kill the last spaces and define the variables. */
@@ -221,13 +237,16 @@ set_file_variables (file)
qp[qp > qmark_value ? -1 : 0] = '\0';
DEFINE_VARIABLE ("?", 1, qmark_value);
bp[bp > bar_value ? -1 : 0] = '\0';
DEFINE_VARIABLE ("|", 1, bar_value);
}
#undef DEFINE_VARIABLE
}
/* Chop CMDS up into individual command lines if necessary.
Also set the `lines_flag' and `any_recurse' members. */
Also set the `lines_flags' and `any_recurse' members. */
void
chop_commands (cmds)
@@ -300,7 +319,7 @@ chop_commands (cmds)
int flags = 0;
for (p = lines[idx];
isblank (*p) || *p == '-' || *p == '@' || *p == '+';
isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+';
++p)
switch (*p)
{
@@ -477,7 +496,10 @@ delete_target (file, on_behalf_of)
#ifndef NO_ARCHIVES
if (ar_name (file->name))
{
if (ar_member_date (file->name) != FILE_TIMESTAMP_S (file->last_mtime))
time_t file_date = (file->last_mtime == NONEXISTENT_MTIME
? (time_t) -1
: (time_t) FILE_TIMESTAMP_S (file->last_mtime));
if (ar_member_date (file->name) != file_date)
{
if (on_behalf_of)
error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"),
@@ -492,7 +514,7 @@ delete_target (file, on_behalf_of)
if (stat (file->name, &st) == 0
&& S_ISREG (st.st_mode)
&& FILE_TIMESTAMP_STAT_MODTIME (st) != file->last_mtime)
&& FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime)
{
if (on_behalf_of)
error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name);

View File

@@ -26,6 +26,10 @@
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long
/* Define to `int' if <sys/types.h> doesn't define. */
#define gid_t int

1088
config.guess vendored

File diff suppressed because it is too large Load Diff

View File

@@ -9,13 +9,6 @@
/* #undef _ALL_SOURCE */
#endif
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* maybe this should be placed into make.h */
#if defined(__VAX) && defined(__DECC)
#define alloca(n) __ALLOCA(n)
#endif
/* Define to 1 if NLS is requested. */
/* #undef ENABLE_NLS */
@@ -50,6 +43,10 @@
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef gid_t */
@@ -341,6 +338,9 @@
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* Use high resolution file timestamps if nonzero. */
#define FILE_TIMESTAMP_HI_RES 0
/* Define for case insensitve filenames */
#define HAVE_CASE_INSENSITIVE_FS 1
@@ -392,5 +392,12 @@
#define PARAMS(protos) ()
#endif /* C++ or ANSI C. */
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* maybe this should be placed into make.h */
#if defined(__VAX) && defined(__DECC)
#define alloca(n) __ALLOCA(n)
#endif
/* Build host information. */
#define MAKE_HOST "VMS"

View File

@@ -26,6 +26,10 @@
/* Define if the `getloadavg' function needs to be run setuid or setgid. */
/* #undef GETLOADAVG_PRIVILEGED */
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
#define gid_t int
@@ -188,6 +192,21 @@
#undef SCCS_GET
#define SCCS_GET "echo no sccs get"
/* Define to 1 if NLS is requested. */
/* #undef ENABLE_NLS */
/* Define as 1 if you have dcgettext. */
/* #undef HAVE_DCGETTEXT */
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
/* #undef HAVE_GETTEXT */
/* Define if your locale.h file contains LC_MESSAGES. */
/* #undef HAVE_LC_MESSAGES */
/* Define to the installation directory for locales. */
#define LOCALEDIR ""
/* Define this if the SCCS `get' command understands the `-G<file>' option. */
/* #undef SCCS_GET_MINUS_G */
@@ -332,9 +351,15 @@
/* Define if you have the sun library (-lsun). */
/* #undef HAVE_LIBSUN */
/* Use high resolution file timestamps if nonzero. */
#define FILE_TIMESTAMP_HI_RES 0
/* Build host information. */
#define MAKE_HOST "Windows32"
/* Grok DOS paths (drive specs and backslash path element separators) */
#define HAVE_DOS_PATHS
/*
* Refer to README.W32 for info on the following settings
*/

1220
config.sub vendored

File diff suppressed because it is too large Load Diff

4
config/.cvsignore Normal file
View File

@@ -0,0 +1,4 @@
*.m4
config.*
Makefile Makefile.in

14
config/ChangeLog Normal file
View File

@@ -0,0 +1,14 @@
2002-04-21 gettextize <bug-gnu-gettext@gnu.org>
* codeset.m4: New file, from gettext-0.11.1.
* gettext.m4: New file, from gettext-0.11.1.
* glibc21.m4: New file, from gettext-0.11.1.
* iconv.m4: New file, from gettext-0.11.1.
* isc-posix.m4: New file, from gettext-0.11.1.
* lcmessage.m4: New file, from gettext-0.11.1.
* lib-ld.m4: New file, from gettext-0.11.1.
* lib-link.m4: New file, from gettext-0.11.1.
* lib-prefix.m4: New file, from gettext-0.11.1.
* progtest.m4: New file, from gettext-0.11.1.
* Makefile.am: New file.

4
config/Makefile.am Normal file
View File

@@ -0,0 +1,4 @@
EXTRA_DIST = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 \
intdiv0.m4 inttypes-pri.m4 inttypes.m4 inttypes_h.m4 \
isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 \
progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4

View File

@@ -1,52 +1,94 @@
/* Many things are defined already by a system header. */
#include <sys/config.h>
/* Name of this package (needed by automake) */
#define PACKAGE "%PACKAGE%"
/* Version of this package (needed by automake) */
#define VERSION "%VERSION%"
#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1
/* Define if `sys_siglist' is declared by <signal.h>. */
# define SYS_SIGLIST_DECLARED 1
/* Define this if the C library defines the variable `_sys_siglist'. */
# define HAVE_SYS_SIGLIST 1
#else
/* Define NSIG. */
# define NSIG SIGMAX
#endif
/* Define if you have sigsetmask. */
#define HAVE_SIGSETMASK 1
/* Define if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define if you have the memmove function. */
#define HAVE_MEMMOVE 1
#define SCCS_GET "get"
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long long
/* Define the type of the first arg to select(). */
#define fd_set_size_t int
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the vprintf library function. */
#undef HAVE_VPRINTF
#define HAVE_VPRINTF 1
/* Build host information. */
#define MAKE_HOST "i386-pc-msdosdjgpp"
/* Many things are defined already by a system header. */
#include <sys/config.h>
#if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1
/* Define if `sys_siglist' is declared by <signal.h>. */
# define SYS_SIGLIST_DECLARED 1
/* Define this if the C library defines the variable `_sys_siglist'. */
# define HAVE_SYS_SIGLIST 1
#else
/* Define NSIG. */
# define NSIG SIGMAX
#endif
/* Use high resolution file timestamps if nonzero. */
#define FILE_TIMESTAMP_HI_RES 0
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have the fdopen function. */
#define HAVE_FDOPEN 1
/* Define to 1 if you have the `getgroups' function. */
#define HAVE_GETGROUPS 1
/* Define if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define if you have the mkstemp function. */
#define HAVE_MKSTEMP 1
/* Define to 1 if you have the `mktemp' function. */
#define HAVE_MKTEMP 1
/* Define to 1 if you have the `setlinebuf' function. */
#define HAVE_SETLINEBUF 1
/* Define to 1 if you have the `setvbuf' function. */
#define HAVE_SETVBUF 1
#define SCCS_GET "get"
/* Define to `unsigned long' or `unsigned long long'
if <inttypes.h> doesn't define. */
#define uintmax_t unsigned long long
/* Define the type of the first arg to select(). */
#define fd_set_size_t int
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the vprintf library function. */
#undef HAVE_VPRINTF
#define HAVE_VPRINTF 1
/* Name of the package */
#define PACKAGE "%PACKAGE%"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "bug-%PACKAGE%@gnu.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "GNU %PACKAGE%"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "GNU %PACKAGE% %VERSION%"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "%PACKAGE%"
/* Define to the version of this package. */
#define PACKAGE_VERSION "%VERSION%"
/* Define to 1 if the C compiler supports function prototypes. */
#define PROTOTYPES 1
/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
#define SYS_SIGLIST_DECLARED 1
/* Version number of package */
#define VERSION "%VERSION%"
/* Build host information. */
#define MAKE_HOST "i386-pc-msdosdjgpp"
/* Grok DOS paths (drive specs and backslash path element separators) */
#define HAVE_DOS_PATHS

View File

@@ -1,81 +1,159 @@
dnl Process this file with autoconf to produce a configure script.
AC_REVISION([$Id$])
AC_PREREQ(2.13)dnl dnl Minimum Autoconf version required.
AC_INIT(vpath.c)dnl dnl A distinctive file to look for in srcdir.
# Process this file with autoconf to produce a configure script.
AM_INIT_AUTOMAKE(make, 3.78.91)
AM_CONFIG_HEADER(config.h)
AC_INIT(GNU make,3.80,bug-make@gnu.org)
dnl Regular configure stuff
AC_PREREQ(2.54)
AC_CANONICAL_HOST
AC_REVISION([[$Id$]])
# Autoconf setup
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(vpath.c)
AC_CONFIG_HEADERS(config.h)
# Automake setup
AM_INIT_AUTOMAKE
AC_PROG_MAKE_SET
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_CHECK_PROG(AR, ar, ar, ar)
AC_PROG_RANLIB
AC_PROG_CPP dnl Later checks need this.
AC_PROG_CPP
AC_CHECK_PROG(AR, ar, ar, ar)
# Perl is needed for the test suite (only)
AC_CHECK_PROG(PERL, perl, perl, perl)
# Specialized system macros
AC_CANONICAL_HOST
AC_AIX
AC_ISC_POSIX
AC_MINIX
AC_CHECK_PROG(PERL, perl, perl, perl) dnl Needed for the test suite (only)
# Enable gettext, in "external" mode.
dnl This test must come as early as possible after the compiler configuration
dnl tests, because the choice of the file model can (in principle) affect
dnl whether functions and headers are available, whether they work, etc.
AM_GNU_GETTEXT_VERSION(0.11.5)
AM_GNU_GETTEXT([external])
# This test must come as early as possible after the compiler configuration
# tests, because the choice of the file model can (in principle) affect
# whether functions and headers are available, whether they work, etc.
AC_SYS_LARGEFILE
# Checks for libraries.
AC_SEARCH_LIBS(getpwnam, [sun])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_DIRENT
AC_TYPE_UID_T dnl Also does gid_t.
AC_TYPE_PID_T
AC_TYPE_SIGNAL
AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/param.h fcntl.h string.h \
memory.h sys/timeb.h)
AC_PROG_CC_C_O
AM_PROG_CC_STDC
AC_C_CONST dnl getopt needs this.
AC_C_INLINE dnl gettext needs this.
AC_HEADER_STAT
AC_HEADER_TIME
AC_CHECK_HEADERS(stdlib.h locale.h unistd.h limits.h fcntl.h string.h \
memory.h sys/param.h sys/time.h sys/timeb.h)
AM_PROG_CC_C_O
AM_PROG_CC_STDC
AC_C_CONST
AC_TYPE_SIGNAL
AC_TYPE_UID_T
AC_TYPE_PID_T
# Find some definition for uintmax_t
AC_CHECK_TYPE(uintmax_t,,[
uintmax_t="unsigned long"
AC_CHECK_TYPE(unsigned long long,[uintmax_t="unsigned long long"])
AC_DEFINE_UNQUOTED(uintmax_t,$uintmax_t,[Define uintmax_t if not defined in <stdint.h> or <inttypes.h>.])])
# Find out whether our struct stat returns nanosecond resolution timestamps.
AC_STRUCT_ST_MTIM_NSEC
jm_AC_TYPE_UINTMAX_T
AC_SUBST(LIBOBJS)
AC_DEFUN(AC_CHECK_SYMBOL, [dnl
AC_MSG_CHECKING(for $1)
AC_CACHE_VAL(ac_cv_check_symbol_$1, [dnl
AC_TRY_LINK(, [extern char *sys_siglist[]; puts(*sys_siglist);],
ac_cv_check_symbol_$1=yes, ac_cv_check_symbol_$1=no)])
if test "$ac_cv_check_symbol_$1" = yes; then
changequote(,)dnl
ac_tr_symbol=`echo $1 | tr '[a-z]' '[A-Z]'`
changequote([,])dnl
AC_DEFINE_UNQUOTED(HAVE_${ac_tr_symbol})
AC_MSG_CHECKING([whether to use high resolution file timestamps])
AC_CACHE_VAL(make_cv_file_timestamp_hi_res, [
make_cv_file_timestamp_hi_res=no
if test "$ac_cv_struct_st_mtim_nsec" != no; then
AC_TRY_COMPILE([
# if HAVE_INTTYPES_H
# include <inttypes.h>
# endif],
[char a[0x7fffffff < (uintmax_t) -1 >> 30 ? 1 : -1];],
make_cv_file_timestamp_hi_res=yes)
fi])
AC_MSG_RESULT($make_cv_file_timestamp_hi_res)
if test "$make_cv_file_timestamp_hi_res" = yes; then
val=1
else
val=0
fi
AC_MSG_RESULT($ac_cv_check_symbol_$1)])dnl
AC_DEFINE_UNQUOTED(FILE_TIMESTAMP_HI_RES, $val,
[Use high resolution file timestamps if nonzero.])
# clock_gettime is in -lposix4 in Solaris 2.6.
AC_CHECK_LIB(posix4, clock_gettime)
if test "$make_cv_file_timestamp_hi_res" = yes; then
# Solaris 2.5.1 needs -lposix4 to get the clock_gettime function.
# Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
AC_SEARCH_LIBS(clock_gettime, [rt posix4])
if test "$ac_cv_search_clock_gettime" != no; then
AC_DEFINE(HAVE_CLOCK_GETTIME, 1,
[Define if you have the clock_gettime function.])
fi
fi
# See if we have a standard version of gettimeofday(). Since actual
# implementations can differ, just make sure we have the most common
# one.
AC_CACHE_CHECK([for standard gettimeofday], ac_cv_func_gettimeofday,
[ac_cv_func_gettimeofday=no
AC_TRY_RUN([#include <sys/time.h>
int main ()
{
struct timeval t; t.tv_sec = -1; t.tv_usec = -1;
exit (gettimeofday (&t, 0) != 0
|| t.tv_sec < 0 || t.tv_usec < 0);
}],
ac_cv_func_gettimeofday=yes,
ac_cv_func_gettimeofday=no,
ac_cv_func_gettimeofday="no (cross-compiling)")])
if test "$ac_cv_func_gettimeofday" = yes; then
AC_DEFINE(HAVE_GETTIMEOFDAY, 1,
[Define if you have a standard gettimeofday function])
fi
AC_CHECK_FUNCS( memcpy memmove strchr strdup mkstemp mktemp fdopen \
bsd_signal dup2 getcwd sigsetmask sigaction getgroups \
seteuid setegid setlinebuf setreuid setregid setvbuf pipe \
strerror strsignal)
make_FUNC_SETVBUF_REVERSED
# strcoll() is used by the GNU glob library
AC_FUNC_STRCOLL
AC_CHECK_FUNCS(memmove strchr memcpy strdup psignal mktemp pstat_getdynamic \
clock_gettime dup2 getcwd sigsetmask sigaction getgroups \
setlinebuf seteuid setegid setreuid setregid pipe \
strerror strsignal)
AC_CHECK_SYMBOL(sys_siglist)
AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_FUNC_VPRINTF
AC_FUNC_STRCOLL
AC_FUNC_CLOSEDIR_VOID
AC_FUNC_SETVBUF_REVERSED
AC_FUNC_SELECT
AC_CHECK_LIB(kstat, kstat_open) dnl _Must_ come before AC_FUNC_GETLOADAVG.
AC_FUNC_GETLOADAVG
# AC_FUNC_GETLOADAVG is documented to set the NLIST_STRUCT value, but it
# doesn't. So, we will.
if test "$ac_cv_header_nlist_h" = yes; then
AC_TRY_COMPILE([#include <nlist.h>],
[struct nlist nl;
nl.n_name = "string";
return 0;],
make_cv_nlist_struct=yes,
make_cv_nlist_struct=no)
if test "$make_cv_nlist_struct" = yes; then
AC_DEFINE(NLIST_STRUCT, 1,
[Define if struct nlist.n_name is a pointer rather than an array.])
fi
fi
AC_DECL_SYS_SIGLIST
# Check out the wait reality.
AC_CHECK_HEADERS(sys/wait.h)
AC_CHECK_FUNCS(waitpid wait3)
@@ -101,46 +179,41 @@ pid = waitpid (-1, &status, 0);
],
[make_cv_union_wait=yes], [make_cv_union_wait=no])])
if test "$make_cv_union_wait" = yes; then
AC_DEFINE(HAVE_UNION_WAIT)
AC_DEFINE(HAVE_UNION_WAIT, 1, [Define this if you have the \`union wait' type in <sys/wait.h>.])
fi
AC_MSG_RESULT($make_cv_union_wait)
AC_DECL_SYS_SIGLIST
dnl Handle internationalization
# See if the user wants to use pmake's "customs" distributed build capability
ALL_LINGUAS="de es fr ko nl pl ru"
fp_WITH_GETTEXT
# The presence of the following is not meant to imply
# that make necessarily works on those systems.
AC_CHECK_LIB(sun, getpwnam)
AC_SUBST(REMOTE) REMOTE=stub
make_try_customs=no
use_customs=false
AC_ARG_WITH(customs,
[ --with-customs=DIR Enable remote jobs via Customs--see README.customs],
[case "$withval" in
n|no) ;;
*) make_cppflags="$CPPFLAGS"
case "$withval" in
y|ye|yes) ;;
*) CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs"
make_ldflags="$LDFLAGS -L$with_customs/lib" ;;
esac
CF_NETLIBS
AC_CHECK_HEADER(customs.h,
REMOTE=cstms
LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags",
with_customs=no
CPPFLAGS="$make_cppflags" make_badcust=yes)
;;
esac])
AC_HELP_STRING([--with-customs=DIR],
[enable remote jobs via Customs--see README.customs]),
[case $withval in
n|no) : ;;
*) make_cppflags="$CPPFLAGS"
case $withval in
y|ye|yes) : ;;
*) CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs"
make_ldflags="$LDFLAGS -L$with_customs/lib" ;;
esac
CF_NETLIBS
AC_CHECK_HEADER(customs.h,
[use_customs=true
LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags"],
[with_customs=no
CPPFLAGS="$make_cppflags" make_badcust=yes])
;;
esac])
# Tell automake about this, so it can include the right .c files.
AM_CONDITIONAL(USE_CUSTOMS, test "$use_customs" = true)
dnl See if we can handle the job server feature, and if the user wants it.
# See if we can handle the job server feature, and if the user wants it.
AC_ARG_ENABLE(job-server,
[ --disable-job-server Disallow recursive make communication during -jN],
AC_HELP_STRING([--disable-job-server],
[disallow recursive make communication during -jN]),
[make_cv_job_server="$enableval" user_job_server="$enableval"],
[make_cv_job_server="yes"])
@@ -149,22 +222,23 @@ case "$ac_cv_func_waitpid/$ac_cv_func_wait3" in
no/no) has_wait_nohang=no ;;
esac
case "$ac_cv_func_pipe/$ac_cv_func_sigaction/$has_wait_nohang/$make_cv_job_server" in
yes/yes/yes/yes) AC_DEFINE(MAKE_JOBSERVER) ;;
AC_CACHE_CHECK(for SA_RESTART, make_cv_sa_restart, [
AC_TRY_COMPILE([#include <signal.h>],
[return SA_RESTART;],
make_cv_sa_restart=yes,
make_cv_sa_restart=no)])
if test "$make_cv_sa_restart" != no; then
AC_DEFINE(HAVE_SA_RESTART, 1,
[Define if <signal.h> defines the SA_RESTART constant.])
fi
case "$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/$make_cv_job_server" in
yes/yes/yes/yes/yes)
AC_DEFINE(MAKE_JOBSERVER, 1,
[Define this to enable job server support in GNU make.]);;
esac
dnl Allow building with dmalloc
AC_ARG_ENABLE(dmalloc,
[ --enable-dmalloc Enable support for the dmalloc debugging library],
[make_cv_dmalloc="$enableval"],
[make_cv_dmalloc="no"])
case "$make_cv_dmalloc" in
yes) AC_CHECK_HEADERS(dmalloc.h)
AC_CHECK_LIB(dmalloc, dmalloc_shutdown)
CPPFLAGS="$CPPFLAGS -DDMALLOC_FUNC_CHECK" ;;
esac
# Find the SCCS commands, so we can include them in our default rules.
AC_CACHE_CHECK(for location of SCCS get command, make_cv_path_sccs_get, [
if test -f /usr/sccs/get; then
@@ -172,7 +246,7 @@ if test -f /usr/sccs/get; then
else
make_cv_path_sccs_get=get
fi])
AC_DEFINE_UNQUOTED(SCCS_GET,["$make_cv_path_sccs_get"])
AC_DEFINE_UNQUOTED(SCCS_GET, ["$make_cv_path_sccs_get"], [Define to the name of the SCCS 'get' command.])
ac_clean_files="$ac_clean_files s.conftest conftoast" # Remove these later.
if ( /usr/sccs/admin -n s.conftest || admin -n s.conftest ) >/dev/null 2>&1 &&
@@ -186,54 +260,71 @@ if ( /usr/sccs/admin -n s.conftest || admin -n s.conftest ) >/dev/null 2>&1 &&
make_cv_sys_get_minus_G=no
fi])
case "$make_cv_sys_get_minus_G" in
yes) AC_DEFINE(SCCS_GET_MINUS_G);;
yes) AC_DEFINE(SCCS_GET_MINUS_G, 1,
[Define this if the SCCS 'get' command understands the '-G<file>' option.]);;
esac
fi
rm -f s.conftest conftoast
# Check the system to see if it provides GNU glob. If not, use our
# local version.
AC_MSG_CHECKING(if system libc has GNU glob)
AC_CACHE_VAL(make_cv_sys_gnu_glob, [
AC_TRY_CPP([
AC_EGREP_CPP(gnu glob,[
#include <features.h>
#include <glob.h>
#include <fnmatch.h>
#define GLOB_INTERFACE_VERSION 1
#if defined _LIBC || !defined __GNU_LIBRARY__ || __GNU_LIBRARY__ <= 1
# error no gnu glob
#else
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
# include <gnu-versions.h>
# if _GNU_GLOB_INTERFACE_VERSION != GLOB_INTERFACE_VERSION
# error no gnu glob
# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
gnu glob
# endif
#endif
], make_cv_sys_gnu_glob=yes, make_cv_sys_gnu_glob=no)])
case "$make_cv_sys_gnu_glob" in
yes) AC_MSG_RESULT(yes) ;;
no) AC_MSG_RESULT([no; using local copy])
AC_SUBST(GLOBDIR) GLOBDIR=glob
AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob'
AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a
;;
], [AC_MSG_RESULT(yes)
make_cv_sys_gnu_glob=yes], [AC_MSG_RESULT([no; using local copy])
AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob'
AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a
make_cv_sys_gnu_glob=no])])
# Tell automake about this, so it can build the right .c files.
AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no)
# PTX systems have a broken implementation of SA_RESTART. I know of
# no way to test for this behavior, so I'll just test for PTX
case "$host" in
i386-sequent-sysv4)
AC_DEFINE(HAVE_BROKEN_RESTART, 1, [This system has SA_RESTART, but it doesn't work properly.])
echo ""
echo "WARNING: The SA_RESTART sigaction() flag does not work on PTX."
echo " This causes 'make -j' to fail at random times."
echo " I am installing a workaround, which is mostly but not 100%"
echo " effective. If you see random failures during 'make -j'"
echo " you should either contact the bug list, or not use -j."
echo "" ;;
esac
# Let the makefile know what our build host is
AC_DEFINE_UNQUOTED(MAKE_HOST,"$host",[Build host information.])
MAKE_HOST="$host"
AC_SUBST(MAKE_HOST)
# Include the Maintainer's Makefile section, if it's here.
MAINT_MAKEFILE=/dev/null
if test -r "$srcdir/maintMakefile"; then
MAINT_MAKEFILE="$srcdir/maintMakefile"
fi
AC_SUBST_FILE(MAINT_MAKEFILE)
AC_OUTPUT(build.sh Makefile glob/Makefile i18n/Makefile)
# Allow building with dmalloc
AM_WITH_DMALLOC
dnl If we don't yet have build.sh.in, build.sh is a bogus 0-length file
dnl so remove it.
dnl Can't do this because then remote builds with build.sh don't work.
dnl test -f build.sh.in || rm -f build.sh
# Sanity check and inform the user of what we found
case "$make_badcust" in
yes) echo
@@ -248,7 +339,7 @@ case "$with_customs" in
:
else
echo
echo "WARNING: \`$with_customs/lib' does not appear to contain the"
echo "WARNING: '$with_customs/lib' does not appear to contain the"
echo " Customs library. You must build and install Customs"
echo " before compiling GNU make."
echo
@@ -274,6 +365,23 @@ case "$make_cv_job_server/$user_job_server" in
echo ;;
esac
# Specify what files are to be created.
# We only generate the build.sh if we have a build.sh.in; we won't have
# one before we've created a distribution.
AC_CONFIG_FILES(Makefile glob/Makefile po/Makefile.in config/Makefile doc/Makefile)
if test -f $srcdir/build.sh.in; then
AC_CONFIG_FILES(build.sh)
fi
# OK, do it!
AC_OUTPUT
dnl Local Variables:
dnl comment-start: "dnl "
dnl comment-end: ""

View File

@@ -396,10 +396,10 @@ static char *default_variables[] =
/* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist,
and to the empty string if $@ does exist. */
"CHECKOUT,v",
"+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)",
"CHECKOUT,v", "+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)",
"CO", "co",
"COFLAGS", "",
"CPP", "$(CC) -E",
#ifdef CRAY
"CF77PPFLAGS", "-P",

4
dep.h
View File

@@ -38,7 +38,8 @@ struct dep
struct dep *next;
char *name;
struct file *file;
int changed;
unsigned int changed : 8;
unsigned int ignore_mtime : 1;
};
@@ -72,5 +73,6 @@ extern char *dep_name ();
extern struct dep *copy_dep_chain PARAMS ((struct dep *d));
extern struct dep *read_all_makefiles PARAMS ((char **makefiles));
extern int eval_buffer PARAMS ((char *buffer));
extern int update_goal_chain PARAMS ((struct dep *goals, int makefiles));
extern void uniquize_deps PARAMS ((struct dep *));

646
dir.c
View File

@@ -1,5 +1,6 @@
/* Directory hashing for GNU Make.
Copyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -18,6 +19,7 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "make.h"
#include "hash.h"
#ifdef HAVE_DIRENT_H
# include <dirent.h>
@@ -159,7 +161,8 @@ vms_hash (name)
while (*name)
{
h = (h << 4) + (isupper (*name) ? tolower (*name) : *name);
unsigned char uc = *name;
h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
name++;
g = h & 0xf0000000;
if (g)
@@ -216,8 +219,6 @@ vmsstat_dir (name, st)
struct directory_contents
{
struct directory_contents *next;
dev_t dev; /* Device and inode numbers of this dir. */
#ifdef WINDOWS32
/*
@@ -229,6 +230,7 @@ struct directory_contents
* way to emulate inode.
*/
char *path_key;
int ctime;
int mtime; /* controls check for stale directory cache */
int fs_flags; /* FS_FAT, FS_NTFS, ... */
#define FS_FAT 0x1
@@ -241,17 +243,99 @@ struct directory_contents
ino_t ino;
#endif
#endif /* WINDOWS32 */
struct dirfile **files; /* Files in this directory. */
struct hash_table dirfiles; /* Files in this directory. */
DIR *dirstream; /* Stream reading this directory. */
};
static unsigned long
directory_contents_hash_1 (key_0)
const void *key_0;
{
struct directory_contents const *key = (struct directory_contents const *) key_0;
unsigned long hash;
#ifdef WINDOWS32
ISTRING_HASH_1 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
^ ((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
+ (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
# endif
#endif /* WINDOWS32 */
return hash;
}
static unsigned long
directory_contents_hash_2 (key_0)
const void *key_0;
{
struct directory_contents const *key = (struct directory_contents const *) key_0;
unsigned long hash;
#ifdef WINDOWS32
ISTRING_HASH_2 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
^ ~((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
+ (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
# endif
#endif /* WINDOWS32 */
return hash;
}
static int
directory_contents_hash_cmp (xv, yv)
const void *xv;
const void *yv;
{
struct directory_contents const *x = (struct directory_contents const *) xv;
struct directory_contents const *y = (struct directory_contents const *) yv;
int result;
#ifdef WINDOWS32
ISTRING_COMPARE (x->path_key, y->path_key, result);
if (result)
return result;
result = x->ctime - y->ctime;
if (result)
return result;
#else
# ifdef VMS
result = x->ino[0] - y->ino[0];
if (result)
return result;
result = x->ino[1] - y->ino[1];
if (result)
return result;
result = x->ino[2] - y->ino[2];
if (result)
return result;
# else
result = x->ino - y->ino;
if (result)
return result;
# endif
#endif /* WINDOWS32 */
return x->dev - y->dev;
}
/* Table of directory contents hashed by device and inode number. */
static struct directory_contents *directories_contents[DIRECTORY_BUCKETS];
static struct hash_table directory_contents;
struct directory
{
struct directory *next;
char *name; /* Name of the directory. */
/* The directory's contents. This data may be shared by several
@@ -260,9 +344,31 @@ struct directory
struct directory_contents *contents;
};
/* Table of directories hashed by name. */
static struct directory *directories[DIRECTORY_BUCKETS];
static unsigned long
directory_hash_1 (key)
const void *key;
{
return_ISTRING_HASH_1 (((struct directory const *) key)->name);
}
static unsigned long
directory_hash_2 (key)
const void *key;
{
return_ISTRING_HASH_2 (((struct directory const *) key)->name);
}
static int
directory_hash_cmp (x, y)
const void *x;
const void *y;
{
return_ISTRING_COMPARE (((struct directory const *) x)->name,
((struct directory const *) y)->name);
}
/* Table of directories hashed by name. */
static struct hash_table directories;
/* Never have more than this many directories open at once. */
@@ -275,11 +381,38 @@ static unsigned int open_directories = 0;
struct dirfile
{
struct dirfile *next;
char *name; /* Name of the file. */
char impossible; /* This file is impossible. */
short length;
short impossible; /* This file is impossible. */
};
static unsigned long
dirfile_hash_1 (key)
const void *key;
{
return_ISTRING_HASH_1 (((struct dirfile const *) key)->name);
}
static unsigned long
dirfile_hash_2 (key)
const void *key;
{
return_ISTRING_HASH_2 (((struct dirfile const *) key)->name);
}
static int
dirfile_hash_cmp (xv, yv)
const void *xv;
const void *yv;
{
struct dirfile const *x = ((struct dirfile const *) xv);
struct dirfile const *y = ((struct dirfile const *) yv);
int result = x->length - y->length;
if (result)
return result;
return_ISTRING_COMPARE (x->name, y->name);
}
#ifndef DIRFILE_BUCKETS
#define DIRFILE_BUCKETS 107
#endif
@@ -293,9 +426,11 @@ static struct directory *
find_directory (name)
register char *name;
{
register unsigned int hash = 0;
register char *p;
register struct directory *dir;
register struct directory **dir_slot;
struct directory dir_key;
int r;
#ifdef WINDOWS32
char* w32_path;
char fs_label[BUFSIZ];
@@ -311,41 +446,45 @@ find_directory (name)
name = vmsify (name,1);
#endif
for (p = name; *p != '\0'; ++p)
HASHI (hash, *p);
hash %= DIRECTORY_BUCKETS;
dir_key.name = name;
dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
dir = *dir_slot;
for (dir = directories[hash]; dir != 0; dir = dir->next)
if (strieq (dir->name, name))
break;
if (dir == 0)
if (HASH_VACANT (dir))
{
struct stat st;
/* The directory was not found. Create a new entry for it. */
p = name + strlen (name);
dir = (struct directory *) xmalloc (sizeof (struct directory));
dir->next = directories[hash];
directories[hash] = dir;
dir->name = savestring (name, p - name);
hash_insert_at (&directories, dir, dir_slot);
/* The directory is not in the name hash table.
Find its device and inode numbers, and look it up by them. */
#ifdef VMS
if (vmsstat_dir (name, &st) < 0)
#else
# ifdef WINDOWS32
#ifdef WINDOWS32
/* Remove any trailing '\'. Windows32 stat fails even on valid
directories if they end in '\'. */
if (p[-1] == '\\')
p[-1] = '\0';
# endif
if (stat (name, &st) < 0)
#endif
{
#ifdef VMS
r = vmsstat_dir (name, &st);
#else
r = stat (name, &st);
#endif
#ifdef WINDOWS32
/* Put back the trailing '\'. If we don't, we're permanently
truncating the value! */
if (p[-1] == '\0')
p[-1] = '\\';
#endif
if (r < 0)
{
/* Couldn't stat the directory. Mark this by
setting the `contents' member to a nil pointer. */
dir->contents = 0;
@@ -355,39 +494,26 @@ find_directory (name)
/* Search the contents hash table; device and inode are the key. */
struct directory_contents *dc;
struct directory_contents **dc_slot;
struct directory_contents dc_key;
dc_key.dev = st.st_dev;
#ifdef WINDOWS32
w32_path = w32ify(name, 1);
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ctime;
dc_key.path_key = w32_path = w32ify (name, 1);
dc_key.ctime = st.st_ctime;
#else
# ifdef VMS
hash = (((unsigned int) st.st_dev << 16)
| ((unsigned int) st.st_ino[0]
+ (unsigned int) st.st_ino[1]
+ (unsigned int) st.st_ino[2]));
dc_key.ino[0] = st.st_ino[0];
dc_key.ino[1] = st.st_ino[1];
dc_key.ino[2] = st.st_ino[2];
# else
hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino;
dc_key.ino = st.st_ino;
# endif
#endif
hash %= DIRECTORY_BUCKETS;
dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
dc = *dc_slot;
for (dc = directories_contents[hash]; dc != 0; dc = dc->next)
#ifdef WINDOWS32
if (strieq(dc->path_key, w32_path))
#else
if (dc->dev == st.st_dev
# ifdef VMS
&& dc->ino[0] == st.st_ino[0]
&& dc->ino[1] == st.st_ino[1]
&& dc->ino[2] == st.st_ino[2]
# else
&& dc->ino == st.st_ino
# endif
)
#endif /* WINDOWS32 */
break;
if (dc == 0)
if (HASH_VACANT (dc))
{
/* Nope; this really is a directory we haven't seen before. */
@@ -397,7 +523,8 @@ find_directory (name)
/* Enter it in the contents hash table. */
dc->dev = st.st_dev;
#ifdef WINDOWS32
dc->path_key = xstrdup(w32_path);
dc->path_key = xstrdup (w32_path);
dc->ctime = st.st_ctime;
dc->mtime = st.st_mtime;
/*
@@ -426,22 +553,16 @@ find_directory (name)
dc->ino = st.st_ino;
# endif
#endif /* WINDOWS32 */
dc->next = directories_contents[hash];
directories_contents[hash] = dc;
hash_insert_at (&directory_contents, dc, dc_slot);
dc->dirstream = opendir (name);
if (dc->dirstream == 0)
/* Couldn't open the directory. Mark this by
setting the `files' member to a nil pointer. */
dc->files = 0;
dc->dirfiles.ht_vec = 0;
else
{
/* Allocate an array of buckets for files and zero it. */
dc->files = (struct dirfile **)
xmalloc (sizeof (struct dirfile *) * DIRFILE_BUCKETS);
bzero ((char *) dc->files,
sizeof (struct dirfile *) * DIRFILE_BUCKETS);
hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
/* Keep track of how many directories are open. */
++open_directories;
if (open_directories == MAX_OPEN_DIRECTORIES)
@@ -467,16 +588,15 @@ dir_contents_file_exists_p (dir, filename)
register struct directory_contents *dir;
register char *filename;
{
register unsigned int hash;
register char *p;
register struct dirfile *df;
register struct dirent *d;
unsigned int hash;
struct dirfile *df;
struct dirent *d;
#ifdef WINDOWS32
struct stat st;
int rehash = 0;
#endif
if (dir == 0 || dir->files == 0)
if (dir == 0 || dir->dirfiles.ht_vec == 0)
{
/* The directory could not be stat'd or opened. */
return 0;
@@ -496,24 +616,19 @@ dir_contents_file_exists_p (dir, filename)
hash = 0;
if (filename != 0)
{
struct dirfile dirfile_key;
if (*filename == '\0')
{
/* Checking if the directory exists. */
/* Checking if the directory exists. */
return 1;
}
for (p = filename; *p != '\0'; ++p)
HASH (hash, *p);
hash %= DIRFILE_BUCKETS;
/* Search the list of hashed files. */
for (df = dir->files[hash]; df != 0; df = df->next)
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
df = (struct dirfile *) hash_find_item (&dir->dirfiles, &dirfile_key);
if (df)
{
if (strieq (df->name, filename))
{
return !df->impossible;
}
return !df->impossible;
}
}
@@ -528,33 +643,34 @@ dir_contents_file_exists_p (dir, filename)
* filesystems force a rehash always as mtime does not change
* on directories (ugh!).
*/
if (dir->path_key &&
(dir->fs_flags & FS_FAT ||
(stat(dir->path_key, &st) == 0 &&
st.st_mtime > dir->mtime))) {
if (dir->path_key
&& (dir->fs_flags & FS_FAT
|| (stat(dir->path_key, &st) == 0
&& st.st_mtime > dir->mtime)))
{
/* reset date stamp to show most recent re-process */
dir->mtime = st.st_mtime;
/* reset date stamp to show most recent re-process */
dir->mtime = st.st_mtime;
/* make sure directory can still be opened */
dir->dirstream = opendir(dir->path_key);
/* make sure directory can still be opened */
dir->dirstream = opendir(dir->path_key);
if (dir->dirstream)
rehash = 1;
else
return 0; /* couldn't re-read - fail */
} else
if (dir->dirstream)
rehash = 1;
else
return 0; /* couldn't re-read - fail */
}
else
#endif
/* The directory has been all read in. */
return 0;
/* The directory has been all read in. */
return 0;
}
while ((d = readdir (dir->dirstream)) != 0)
{
/* Enter the file in the hash table. */
register unsigned int newhash = 0;
unsigned int len;
register unsigned int i;
struct dirfile dirfile_key;
struct dirfile **dirfile_slot;
#if defined(VMS) && defined(HAVE_DIRENT_H)
/* In VMS we get file versions too, which have to be stripped off */
@@ -568,39 +684,25 @@ dir_contents_file_exists_p (dir, filename)
continue;
len = NAMLEN (d);
for (i = 0; i < len; ++i)
HASHI (newhash, d->d_name[i]);
newhash %= DIRFILE_BUCKETS;
dirfile_key.name = d->d_name;
dirfile_key.length = len;
dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
#ifdef WINDOWS32
/*
* If re-reading a directory, check that this file isn't already
* in the cache.
*/
if (rehash) {
for (df = dir->files[newhash]; df != 0; df = df->next)
if (streq(df->name, d->d_name))
break;
} else
df = 0;
/*
* If re-reading a directory, don't cache files that have
* already been discovered.
*/
if (!df) {
#endif
df = (struct dirfile *) xmalloc (sizeof (struct dirfile));
df->next = dir->files[newhash];
dir->files[newhash] = df;
df->name = savestring (d->d_name, len);
df->impossible = 0;
#ifdef WINDOWS32
}
if (! rehash || HASH_VACANT (*dirfile_slot))
#endif
{
df = (struct dirfile *) xmalloc (sizeof (struct dirfile));
df->name = savestring (d->d_name, len);
df->length = len;
df->impossible = 0;
hash_insert_at (&dir->dirfiles, df, dirfile_slot);
}
/* Check if the name matches the one we're searching for. */
if (filename != 0
&& newhash == hash && strieq (d->d_name, filename))
if (filename != 0 && strieq (d->d_name, filename))
{
return 1;
}
@@ -654,7 +756,7 @@ file_exists_p (name)
return dir_file_exists_p ("[]", name);
#else /* !VMS */
dirend = strrchr (name, '/');
#if defined (WINDOWS32) || defined (__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
char *bslash = strrchr(name, '\\');
@@ -664,7 +766,7 @@ file_exists_p (name)
if (!dirend && name[0] && name[1] == ':')
dirend = name + 1;
}
#endif /* WINDOWS32 || __MSDOS__ */
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifndef _AMIGA
return dir_file_exists_p (".", name);
@@ -678,7 +780,7 @@ file_exists_p (name)
dirname = "/";
else
{
#if defined (WINDOWS32) || defined (__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < name + 3 && name[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
@@ -701,7 +803,6 @@ file_impossible (filename)
{
char *dirend;
register char *p = filename;
register unsigned int hash;
register struct directory *dir;
register struct dirfile *new;
@@ -714,7 +815,7 @@ file_impossible (filename)
dir = find_directory ("[]");
#else
dirend = strrchr (p, '/');
#if defined (WINDOWS32) || defined (__MSDOS__)
# ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
char *bslash = strrchr(p, '\\');
@@ -724,13 +825,13 @@ file_impossible (filename)
if (!dirend && p[0] && p[1] == ':')
dirend = p + 1;
}
#endif /* WINDOWS32 or __MSDOS__ */
# endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifdef _AMIGA
# ifdef _AMIGA
dir = find_directory ("");
#else /* !VMS && !AMIGA */
# else /* !VMS && !AMIGA */
dir = find_directory (".");
#endif /* AMIGA */
# endif /* AMIGA */
#endif /* VMS */
else
{
@@ -740,7 +841,7 @@ file_impossible (filename)
dirname = "/";
else
{
#if defined (WINDOWS32) || defined (__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < p + 3 && p[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
@@ -754,48 +855,28 @@ file_impossible (filename)
filename = p = slash + 1;
}
for (hash = 0; *p != '\0'; ++p)
HASHI (hash, *p);
hash %= DIRFILE_BUCKETS;
if (dir->contents == 0)
{
/* The directory could not be stat'd. We allocate a contents
structure for it, but leave it out of the contents hash table. */
dir->contents = (struct directory_contents *)
xmalloc (sizeof (struct directory_contents));
#ifdef WINDOWS32
dir->contents->path_key = NULL;
dir->contents->mtime = 0;
#else /* WINDOWS32 */
#ifdef VMS
dir->contents->dev = 0;
dir->contents->ino[0] = dir->contents->ino[1] =
dir->contents->ino[2] = 0;
#else
dir->contents->dev = dir->contents->ino = 0;
#endif
#endif /* WINDOWS32 */
dir->contents->files = 0;
dir->contents->dirstream = 0;
bzero ((char *) dir->contents, sizeof (struct directory_contents));
}
if (dir->contents->files == 0)
if (dir->contents->dirfiles.ht_vec == 0)
{
/* The directory was not opened; we must allocate the hash buckets. */
dir->contents->files = (struct dirfile **)
xmalloc (sizeof (struct dirfile) * DIRFILE_BUCKETS);
bzero ((char *) dir->contents->files,
sizeof (struct dirfile) * DIRFILE_BUCKETS);
hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
}
/* Make a new entry and put it in the table. */
new = (struct dirfile *) xmalloc (sizeof (struct dirfile));
new->next = dir->contents->files[hash];
dir->contents->files[hash] = new;
new->name = xstrdup (filename);
new->length = strlen (filename);
new->impossible = 1;
hash_insert (&dir->contents->dirfiles, new);
}
/* Return nonzero if FILENAME has been marked impossible. */
@@ -806,9 +887,9 @@ file_impossible_p (filename)
{
char *dirend;
register char *p = filename;
register unsigned int hash;
register struct directory_contents *dir;
register struct dirfile *next;
register struct dirfile *dirfile;
struct dirfile dirfile_key;
#ifdef VMS
dirend = strrchr (filename, ']');
@@ -816,7 +897,7 @@ file_impossible_p (filename)
dir = find_directory ("[]")->contents;
#else
dirend = strrchr (filename, '/');
#if defined (WINDOWS32) || defined (__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
char *bslash = strrchr(filename, '\\');
@@ -826,7 +907,7 @@ file_impossible_p (filename)
if (!dirend && filename[0] && filename[1] == ':')
dirend = filename + 1;
}
#endif /* WINDOWS32 || __MSDOS__ */
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifdef _AMIGA
dir = find_directory ("")->contents;
@@ -842,7 +923,7 @@ file_impossible_p (filename)
dirname = "/";
else
{
#if defined (WINDOWS32) || defined (__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < filename + 3 && filename[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
@@ -856,27 +937,25 @@ file_impossible_p (filename)
p = filename = slash + 1;
}
if (dir == 0 || dir->files == 0)
if (dir == 0 || dir->dirfiles.ht_vec == 0)
/* There are no files entered for this directory. */
return 0;
#ifdef __MSDOS__
p = filename = dosify (p);
filename = dosify (p);
#endif
#ifdef HAVE_CASE_INSENSITIVE_FS
p = filename = downcase (p);
filename = downcase (p);
#endif
#ifdef VMS
p = filename = vmsify (p, 1);
filename = vmsify (p, 1);
#endif
for (hash = 0; *p != '\0'; ++p)
HASH (hash, *p);
hash %= DIRFILE_BUCKETS;
for (next = dir->files[hash]; next != 0; next = next->next)
if (strieq (filename, next->name))
return next->impossible;
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
dirfile = (struct dirfile *) hash_find_item (&dir->dirfiles, &dirfile_key);
if (dirfile)
return dirfile->impossible;
return 0;
}
@@ -896,78 +975,96 @@ dir_name (dir)
void
print_dir_data_base ()
{
register unsigned int i, dirs, files, impossible;
register struct directory *dir;
register unsigned int files;
register unsigned int impossible;
register struct directory **dir_slot;
register struct directory **dir_end;
puts (_("\n# Directories\n"));
dirs = files = impossible = 0;
for (i = 0; i < DIRECTORY_BUCKETS; ++i)
for (dir = directories[i]; dir != 0; dir = dir->next)
{
++dirs;
if (dir->contents == 0)
printf (_("# %s: could not be stat'd.\n"), dir->name);
else if (dir->contents->files == 0)
files = impossible = 0;
dir_slot = (struct directory **) directories.ht_vec;
dir_end = dir_slot + directories.ht_size;
for ( ; dir_slot < dir_end; dir_slot++)
{
register struct directory *dir = *dir_slot;
if (! HASH_VACANT (dir))
{
if (dir->contents == 0)
printf (_("# %s: could not be stat'd.\n"), dir->name);
else if (dir->contents->dirfiles.ht_vec == 0)
{
#ifdef WINDOWS32
printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
dir->name, dir->contents->path_key,dir->contents->mtime);
printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
dir->name, dir->contents->path_key,dir->contents->mtime);
#else /* WINDOWS32 */
#ifdef VMS
printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
dir->name, (long int) dir->contents->dev,
(long int) dir->contents->ino);
printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
dir->name, (long int) dir->contents->dev,
(long int) dir->contents->ino);
#endif
#endif /* WINDOWS32 */
else
{
register unsigned int f = 0, im = 0;
register unsigned int j;
register struct dirfile *df;
for (j = 0; j < DIRFILE_BUCKETS; ++j)
for (df = dir->contents->files[j]; df != 0; df = df->next)
if (df->impossible)
++im;
else
++f;
}
else
{
register unsigned int f = 0;
register unsigned int im = 0;
register struct dirfile **files_slot;
register struct dirfile **files_end;
files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
files_end = files_slot + dir->contents->dirfiles.ht_size;
for ( ; files_slot < files_end; files_slot++)
{
register struct dirfile *df = *files_slot;
if (! HASH_VACANT (df))
{
if (df->impossible)
++im;
else
++f;
}
}
#ifdef WINDOWS32
printf (_("# %s (key %s, mtime %d): "),
dir->name, dir->contents->path_key, dir->contents->mtime);
printf (_("# %s (key %s, mtime %d): "),
dir->name, dir->contents->path_key, dir->contents->mtime);
#else /* WINDOWS32 */
#ifdef VMS
printf (_("# %s (device %d, inode [%d,%d,%d]): "),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
printf (_("# %s (device %d, inode [%d,%d,%d]): "),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf (_("# %s (device %ld, inode %ld): "),
dir->name,
(long)dir->contents->dev, (long)dir->contents->ino);
printf (_("# %s (device %ld, inode %ld): "),
dir->name,
(long)dir->contents->dev, (long)dir->contents->ino);
#endif
#endif /* WINDOWS32 */
if (f == 0)
fputs (_("No"), stdout);
else
printf ("%u", f);
fputs (_(" files, "), stdout);
if (im == 0)
fputs (_("no"), stdout);
else
printf ("%u", im);
fputs (_(" impossibilities"), stdout);
if (dir->contents->dirstream == 0)
puts (".");
else
puts (_(" so far."));
files += f;
impossible += im;
}
}
if (f == 0)
fputs (_("No"), stdout);
else
printf ("%u", f);
fputs (_(" files, "), stdout);
if (im == 0)
fputs (_("no"), stdout);
else
printf ("%u", im);
fputs (_(" impossibilities"), stdout);
if (dir->contents->dirstream == 0)
puts (".");
else
puts (_(" so far."));
files += f;
impossible += im;
}
}
}
fputs ("\n# ", stdout);
if (files == 0)
@@ -979,7 +1076,7 @@ print_dir_data_base ()
fputs (_("no"), stdout);
else
printf ("%u", impossible);
printf (_(" impossibilities in %u directories.\n"), dirs);
printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill);
}
/* Hooks for globbing. */
@@ -991,9 +1088,7 @@ print_dir_data_base ()
struct dirstream
{
struct directory_contents *contents; /* The directory being read. */
unsigned int bucket; /* Current hash bucket. */
struct dirfile *elt; /* Current elt in bucket. */
struct dirfile **dirfile_slot; /* Current slot in table. */
};
/* Forward declarations. */
@@ -1007,9 +1102,9 @@ open_dirstream (directory)
struct dirstream *new;
struct directory *dir = find_directory ((char *)directory);
if (dir->contents == 0 || dir->contents->files == 0)
if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0)
/* DIR->contents is nil if the directory could not be stat'd.
DIR->contents->files is nil if it could not be opened. */
DIR->contents->dirfiles is nil if it could not be opened. */
return 0;
/* Read all the contents of the directory now. There is no benefit
@@ -1019,8 +1114,7 @@ open_dirstream (directory)
new = (struct dirstream *) xmalloc (sizeof (struct dirstream));
new->contents = dir->contents;
new->bucket = 0;
new->elt = new->contents->files[0];
new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;
return (__ptr_t) new;
}
@@ -1030,45 +1124,40 @@ read_dirstream (stream)
__ptr_t stream;
{
struct dirstream *const ds = (struct dirstream *) stream;
register struct dirfile *df;
struct directory_contents *dc = ds->contents;
struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;
static char *buf;
static unsigned int bufsz;
while (ds->bucket < DIRFILE_BUCKETS)
while (ds->dirfile_slot < dirfile_end)
{
while ((df = ds->elt) != 0)
register struct dirfile *df = *ds->dirfile_slot++;
if (! HASH_VACANT (df) && !df->impossible)
{
ds->elt = df->next;
if (!df->impossible)
/* The glob interface wants a `struct dirent',
so mock one up. */
struct dirent *d;
unsigned int len = df->length + 1;
if (sizeof *d - sizeof d->d_name + len > bufsz)
{
/* The glob interface wants a `struct dirent',
so mock one up. */
struct dirent *d;
unsigned int len = strlen (df->name) + 1;
if (buf != 0)
free (buf);
bufsz *= 2;
if (sizeof *d - sizeof d->d_name + len > bufsz)
{
if (buf != 0)
free (buf);
bufsz *= 2;
if (sizeof *d - sizeof d->d_name + len > bufsz)
bufsz = sizeof *d - sizeof d->d_name + len;
buf = xmalloc (bufsz);
}
d = (struct dirent *) buf;
FAKE_DIR_ENTRY (d);
bufsz = sizeof *d - sizeof d->d_name + len;
buf = xmalloc (bufsz);
}
d = (struct dirent *) buf;
FAKE_DIR_ENTRY (d);
#ifdef _DIRENT_HAVE_D_NAMLEN
d->d_namlen = len - 1;
d->d_namlen = len - 1;
#endif
#ifdef _DIRENT_HAVE_D_TYPE
d->d_type = DT_UNKNOWN;
d->d_type = DT_UNKNOWN;
#endif
memcpy (d->d_name, df->name, len);
return d;
}
memcpy (d->d_name, df->name, len);
return d;
}
if (++ds->bucket == DIRFILE_BUCKETS)
break;
ds->elt = ds->contents->files[ds->bucket];
}
return 0;
@@ -1112,3 +1201,12 @@ dir_setup_glob (gl)
/* We don't bother setting gl_lstat, since glob never calls it.
The slot is only there for compatibility with 4.4 BSD. */
}
void
hash_init_directories ()
{
hash_init (&directories, DIRECTORY_BUCKETS,
directory_hash_1, directory_hash_2, directory_hash_cmp);
hash_init (&directory_contents, DIRECTORY_BUCKETS,
directory_contents_hash_1, directory_contents_hash_2, directory_contents_hash_cmp);
}

7
doc/.cvsignore Normal file
View File

@@ -0,0 +1,7 @@
Makefile Makefile.in
fdl.texi make-stds.texi texinfo.tex
make.info*
make*.html
make.aux make.cp make.cps make.fn make.fns make.ky
make.pg make.toc make.tp make.vr make.log
make.dvi make.ps make.pdf

23
doc/Makefile.am Normal file
View File

@@ -0,0 +1,23 @@
## Process this file with automake to create Makefile.in.
## Makefile for GNU make documentation.
## Copyright 2002 Free Software Foundation, Inc.
TEXI2HTML = texi2html
TEXI2HTML_FLAGS = -split_chapter
info_TEXINFOS = make.texi
make_TEXINFOS = fdl.texi make-stds.texi
CLEANFILES = make*.html
## ----------------------------- ##
## Other documentation formats. ##
## ----------------------------- ##
html: make_1.html
make_1.html: $(info_TEXINFOS) $(make_TEXINFOS)
$(TEXI2HTML) $(TEXI2HTML_FLAGS) $(srcdir)/make.texi
.PHONY: html

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,42 @@
@echo Building Make for MSDOS
@rem Echo ON so they will see what is going on.
@echo on
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g commands.c -o commands.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g job.c -o job.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g variable.c -o variable.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g expand.c -o expand.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g function.c -o function.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g vpath.c -o vpath.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g version.c -o version.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g ar.c -o ar.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g arscan.c -o arscan.o
@echo Building Make for MSDOS
@rem Echo ON so they will see what is going on.
@echo on
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g commands.c -o commands.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g job.c -o job.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g variable.c -o variable.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g expand.c -o expand.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g function.c -o function.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g vpath.c -o vpath.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g version.c -o version.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g ar.c -o ar.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g arscan.c -o arscan.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g signame.c -o signame.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g remote-stub.c -o remote-stub.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt.c -o getopt.o
gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt1.c -o getopt1.o
@cd glob
@if exist libglob.a del libglob.a
gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g glob.c -o glob.o
gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g fnmatch.c -o fnmatch.o
ar rv libglob.a glob.o fnmatch.o
@echo off
cd ..
echo commands.o > respf.$$$
for %%f in (job dir file misc main read remake rule implicit default variable) do echo %%f.o >> respf.$$$
for %%f in (expand function vpath version ar arscan signame remote-stub getopt getopt1) do echo %%f.o >> respf.$$$
echo glob/libglob.a >> respf.$$$
@echo Linking...
@echo on
gcc -o make.new @respf.$$$
@if exist make.exe echo Make.exe is now built!
@if not exist make.exe echo Make.exe build failed...
@if exist make.exe del respf.$$$

153
expand.c
View File

@@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "make.h"
#include <assert.h>
#include "make.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
@@ -91,47 +92,45 @@ initialize_variable_output ()
/* Recursively expand V. The returned string is malloc'd. */
static char *allocated_variable_append PARAMS ((struct variable *v,
struct variable_set_list *l));
static char *allocated_variable_append PARAMS ((const struct variable *v));
char *
recursively_expand_setlist (v, list)
register struct variable *v;
struct variable_set_list *list;
recursively_expand_for_file (v, file)
struct variable *v;
struct file *file;
{
char *value;
struct variable_set_list *save = 0;
if (v->expanding)
/* Expanding V causes infinite recursion. Lose. */
fatal (reading_file,
_("Recursive variable `%s' references itself (eventually)"),
v->name);
{
if (!v->exp_count)
/* Expanding V causes infinite recursion. Lose. */
fatal (reading_file,
_("Recursive variable `%s' references itself (eventually)"),
v->name);
--v->exp_count;
}
if (file)
{
save = current_variable_set_list;
current_variable_set_list = file->variables;
}
v->expanding = 1;
if (v->append)
value = allocated_variable_append (v, list);
value = allocated_variable_append (v);
else
value = allocated_variable_expand (v->value);
v->expanding = 0;
if (file)
current_variable_set_list = save;
return value;
}
/* Warn that NAME is an undefined variable. */
#ifdef __GNUC__
__inline
#endif
static void
warn_undefined (name, length)
char *name;
unsigned int length;
{
if (warn_undefined_variables_flag)
error (reading_file,
_("warning: undefined variable `%.*s'"), (int)length, name);
}
/* Expand a simple reference to variable NAME, which is LENGTH chars long. */
#ifdef __GNUC__
@@ -144,10 +143,9 @@ reference_variable (o, name, length)
unsigned int length;
{
register struct variable *v;
struct variable_set_list *setlist;
char *value;
v = lookup_variable_setlist (name, length, &setlist);
v = lookup_variable (name, length);
if (v == 0)
warn_undefined (name, length);
@@ -155,7 +153,7 @@ reference_variable (o, name, length)
if (v == 0 || *v->value == '\0')
return o;
value = (v->recursive ? recursively_expand_setlist (v, setlist) : v->value);
value = (v->recursive ? recursively_expand (v) : v->value);
o = variable_buffer_output (o, value, strlen (value));
@@ -282,7 +280,7 @@ variable_expand_string (line, string, length)
Is the resultant text a substitution reference? */
colon = lindex (beg, end, ':');
if (colon != 0)
if (colon)
{
/* This looks like a substitution reference: $(FOO:A=B). */
char *subst_beg, *subst_end, *replace_beg, *replace_end;
@@ -370,7 +368,7 @@ variable_expand_string (line, string, length)
break;
default:
if (isblank (p[-1]))
if (isblank ((unsigned char)p[-1]))
break;
/* A $ followed by a random char is a variable reference:
@@ -429,6 +427,9 @@ expand_argument (str, end)
{
char *tmp;
if (str == end)
return xstrdup("");
if (!end || *end == '\0')
tmp = str;
else
@@ -468,56 +469,72 @@ variable_expand_for_file (line, file)
return result;
}
/* Like allocated_variable_expand, but we first expand this variable in the
context of the next variable set, then we append the expanded value. */
/* Like allocated_variable_expand, but for += target-specific variables.
First recursively construct the variable value from its appended parts in
any upper variable sets. Then expand the resulting value. */
static char *
allocated_variable_append (v, list)
struct variable *v;
struct variable_set_list *list;
variable_append (name, length, set)
const char *name;
unsigned int length;
const struct variable_set_list *set;
{
struct variable_set_list *save;
int len = strlen (v->name);
char *var = alloca (len + 4);
char *value;
const struct variable *v;
char *buf = 0;
/* If there's nothing left to check, return the empty buffer. */
if (!set)
return initialize_variable_output ();
/* Try to find the variable in this variable set. */
v = lookup_variable_in_set (name, length, set->set);
/* If there isn't one, look to see if there's one in a set above us. */
if (!v)
return variable_append (name, length, set->next);
/* If this variable type is append, first get any upper values.
If not, initialize the buffer. */
if (v->append)
buf = variable_append (name, length, set->next);
else
buf = initialize_variable_output ();
/* Append this value to the buffer, and return it.
If we already have a value, first add a space. */
if (buf > variable_buffer)
buf = variable_buffer_output (buf, " ", 1);
return variable_buffer_output (buf, v->value, strlen (v->value));
}
static char *
allocated_variable_append (v)
const struct variable *v;
{
char *val, *retval;
/* Construct the appended variable value. */
char *obuf = variable_buffer;
unsigned int olen = variable_buffer_length;
variable_buffer = 0;
if (!list)
list = current_variable_set_list;
assert(list->next != 0);
save = current_variable_set_list;
current_variable_set_list = list->next;
var[0] = '$';
var[1] = '(';
strcpy (&var[2], v->name);
var[len+2] = ')';
var[len+3] = '\0';
value = variable_expand_for_file (var, 0);
current_variable_set_list = save;
value += strlen (value);
value = variable_buffer_output (value, " ", 1);
value = variable_expand_string (value, v->value, (long)-1);
value = variable_buffer;
#if 0
/* Waste a little memory and save time. */
value = xrealloc (value, strlen (value))
#endif
val = variable_append (v->name, strlen (v->name), current_variable_set_list);
variable_buffer_output (val, "", 1);
val = variable_buffer;
variable_buffer = obuf;
variable_buffer_length = olen;
return value;
/* Now expand it and return that. */
retval = allocated_variable_expand (val);
free (val);
return retval;
}
/* Like variable_expand_for_file, but the returned string is malloc'd.

686
file.c
View File

@@ -1,5 +1,6 @@
/* Target file hash table management for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,95,96,97 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -17,30 +18,51 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "make.h"
#include <assert.h>
#include "make.h"
#include "dep.h"
#include "filedef.h"
#include "job.h"
#include "commands.h"
#include "variable.h"
#include "debug.h"
#include "hash.h"
/* Hash table of files the makefile knows how to make. */
static unsigned long
file_hash_1 (key)
const void *key;
{
return_ISTRING_HASH_1 (((struct file const *) key)->hname);
}
static unsigned long
file_hash_2 (key)
const void *key;
{
return_ISTRING_HASH_2 (((struct file const *) key)->hname);
}
static int
file_hash_cmp (x, y)
const void *x;
const void *y;
{
return_ISTRING_COMPARE (((struct file const *) x)->hname,
((struct file const *) y)->hname);
}
#ifndef FILE_BUCKETS
#define FILE_BUCKETS 1007
#endif
static struct file *files[FILE_BUCKETS];
static struct hash_table files;
/* Number of files with the `intermediate' flag set. */
unsigned int num_intermediates = 0;
/* Current value for pruning the scan of the goal chain (toggle 0/1). */
unsigned int considered = 0;
/* Whether or not .SECONDARY with no prerequisites was given. */
static int all_secondary = 0;
/* Access the hash table of all file records.
lookup_file given a name, return the struct file * for that name,
@@ -52,25 +74,26 @@ lookup_file (name)
char *name;
{
register struct file *f;
register char *n;
register unsigned int hashval;
struct file file_key;
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
register char *lname, *ln;
#endif
if (*name == '\0')
abort ();
assert (*name != '\0');
/* This is also done in parse_file_seq, so this is redundant
for names read from makefiles. It is here for names passed
on the command line. */
#ifdef VMS
# ifndef WANT_CASE_SENSITIVE_TARGETS
lname = (char *)malloc(strlen(name) + 1);
for (n=name, ln=lname; *n != '\0'; ++n, ++ln)
*ln = isupper((unsigned char)*n) ? tolower((unsigned char)*n) : *n;
*ln = '\0';
name = lname;
{
register char *n;
lname = (char *) malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
*ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;
*ln = '\0';
name = lname;
}
# endif
while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
@@ -96,66 +119,51 @@ lookup_file (name)
#endif /* AMIGA */
#endif /* VMS */
hashval = 0;
for (n = name; *n != '\0'; ++n)
HASHI (hashval, *n);
hashval %= FILE_BUCKETS;
for (f = files[hashval]; f != 0; f = f->next)
{
if (strieq (f->hname, name))
{
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return f;
}
}
file_key.hname = name;
f = (struct file *) hash_find_item (&files, &file_key);
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free (lname);
#endif
return 0;
return f;
}
struct file *
enter_file (name)
char *name;
{
register struct file *f, *new;
register char *n;
register unsigned int hashval;
register struct file *f;
register struct file *new;
register struct file **file_slot;
struct file file_key;
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
char *lname, *ln;
#endif
if (*name == '\0')
abort ();
assert (*name != '\0');
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
lname = (char *)malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
{
if (isupper((unsigned char)*n))
*ln = tolower((unsigned char)*n);
else
*ln = *n;
}
*ln = 0;
/* Creates a possible leak, old value of name is unreachable, but I
currently don't know how to fix it. */
name = lname;
{
register char *n;
lname = (char *) malloc (strlen (name) + 1);
for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
{
if (isupper ((unsigned char)*n))
*ln = tolower ((unsigned char)*n);
else
*ln = *n;
}
*ln = 0;
/* Creates a possible leak, old value of name is unreachable, but I
currently don't know how to fix it. */
name = lname;
}
#endif
hashval = 0;
for (n = name; *n != '\0'; ++n)
HASHI (hashval, *n);
hashval %= FILE_BUCKETS;
for (f = files[hashval]; f != 0; f = f->next)
if (strieq (f->hname, name))
break;
if (f != 0 && !f->double_colon)
file_key.hname = name;
file_slot = (struct file **) hash_find_slot (&files, &file_key);
f = *file_slot;
if (! HASH_VACANT (f) && !f->double_colon)
{
#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
free(lname);
@@ -168,12 +176,8 @@ enter_file (name)
new->name = new->hname = name;
new->update_status = -1;
if (f == 0)
{
/* This is a completely new file. */
new->next = files[hashval];
files[hashval] = new;
}
if (HASH_VACANT (f))
hash_insert_at (&files, new, file_slot);
else
{
/* There is already a double-colon entry for this file. */
@@ -186,178 +190,129 @@ enter_file (name)
return new;
}
/* Rehash FILE to NAME. This is not as simple as resetting
the `hname' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
rehash_file (file, name)
register struct file *file;
char *name;
{
char *oldname = file->hname;
register unsigned int oldhash;
register char *n;
while (file->renamed != 0)
file = file->renamed;
/* Find the hash values of the old and new names. */
oldhash = 0;
for (n = oldname; *n != '\0'; ++n)
HASHI (oldhash, *n);
file_hash_enter (file, name, oldhash, file->name);
}
/* Rename FILE to NAME. This is not as simple as resetting
the `name' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
rename_file (file, name)
register struct file *file;
char *name;
rename_file (from_file, to_hname)
register struct file *from_file;
char *to_hname;
{
rehash_file(file, name);
while (file)
rehash_file (from_file, to_hname);
while (from_file)
{
file->name = file->hname;
file = file->prev;
from_file->name = from_file->hname;
from_file = from_file->prev;
}
}
/* Rehash FILE to NAME. This is not as simple as resetting
the `hname' member, since it must be put in a new hash bucket,
and possibly merged with an existing file called NAME. */
void
file_hash_enter (file, name, oldhash, oldname)
register struct file *file;
char *name;
unsigned int oldhash;
char *oldname;
rehash_file (from_file, to_hname)
register struct file *from_file;
char *to_hname;
{
unsigned int oldbucket = oldhash % FILE_BUCKETS;
register unsigned int newhash, newbucket;
struct file *oldfile;
register char *n;
register struct file *f;
struct file file_key;
struct file **file_slot;
struct file *to_file;
struct file *deleted_file;
struct file *f;
newhash = 0;
for (n = name; *n != '\0'; ++n)
HASHI (newhash, *n);
newbucket = newhash % FILE_BUCKETS;
file_key.hname = to_hname;
if (0 == file_hash_cmp (from_file, &file_key))
return;
/* Look for an existing file under the new name. */
file_key.hname = from_file->hname;
while (from_file->renamed != 0)
from_file = from_file->renamed;
if (file_hash_cmp (from_file, &file_key))
/* hname changed unexpectedly */
abort ();
for (oldfile = files[newbucket]; oldfile != 0; oldfile = oldfile->next)
if (strieq (oldfile->hname, name))
break;
deleted_file = hash_delete (&files, from_file);
if (deleted_file != from_file)
/* from_file isn't the one stored in files */
abort ();
/* If the old file is the same as the new file, something's wrong. */
assert (oldfile != file);
file_key.hname = to_hname;
file_slot = (struct file **) hash_find_slot (&files, &file_key);
to_file = *file_slot;
if (oldhash != 0 && (newbucket != oldbucket || oldfile != 0))
{
/* Remove FILE from its hash bucket. */
from_file->hname = to_hname;
for (f = from_file->double_colon; f != 0; f = f->prev)
f->hname = to_hname;
struct file *lastf = 0;
for (f = files[oldbucket]; f != file; f = f->next)
lastf = f;
if (lastf == 0)
files[oldbucket] = f->next;
else
lastf->next = f->next;
}
/* Give FILE its new name. */
file->hname = name;
for (f = file->double_colon; f != 0; f = f->prev)
f->hname = name;
if (oldfile == 0)
{
/* There is no existing file with the new name. */
if (newbucket != oldbucket)
{
/* Put FILE in its new hash bucket. */
file->next = files[newbucket];
files[newbucket] = file;
}
}
if (HASH_VACANT (to_file))
hash_insert_at (&files, from_file, file_slot);
else
{
/* There is an existing file with the new name.
We must merge FILE into the existing file. */
/* TO_FILE already exists under TO_HNAME.
We must retain TO_FILE and merge FROM_FILE into it. */
register struct dep *d;
if (file->cmds != 0)
if (from_file->cmds != 0)
{
if (oldfile->cmds == 0)
oldfile->cmds = file->cmds;
else if (file->cmds != oldfile->cmds)
if (to_file->cmds == 0)
to_file->cmds = from_file->cmds;
else if (from_file->cmds != to_file->cmds)
{
/* We have two sets of commands. We will go with the
one given in the rule explicitly mentioning this name,
but give a message to let the user know what's going on. */
if (oldfile->cmds->fileinfo.filenm != 0)
error (&file->cmds->fileinfo,
_("Commands were specified for \
file `%s' at %s:%lu,"),
oldname, oldfile->cmds->fileinfo.filenm,
oldfile->cmds->fileinfo.lineno);
if (to_file->cmds->fileinfo.filenm != 0)
error (&from_file->cmds->fileinfo,
_("Commands were specified for file `%s' at %s:%lu,"),
from_file->name, to_file->cmds->fileinfo.filenm,
to_file->cmds->fileinfo.lineno);
else
error (&file->cmds->fileinfo,
_("Commands for file `%s' were found by \
implicit rule search,"),
oldname);
error (&file->cmds->fileinfo,
_("but `%s' is now considered the same file \
as `%s'."),
oldname, name);
error (&file->cmds->fileinfo,
_("Commands for `%s' will be ignored \
in favor of those for `%s'."),
name, oldname);
error (&from_file->cmds->fileinfo,
_("Commands for file `%s' were found by implicit rule search,"),
from_file->name);
error (&from_file->cmds->fileinfo,
_("but `%s' is now considered the same file as `%s'."),
from_file->name, to_hname);
error (&from_file->cmds->fileinfo,
_("Commands for `%s' will be ignored in favor of those for `%s'."),
to_hname, from_file->name);
}
}
/* Merge the dependencies of the two files. */
d = oldfile->deps;
if (d == 0)
oldfile->deps = file->deps;
if (to_file->deps == 0)
to_file->deps = from_file->deps;
else
{
while (d->next != 0)
d = d->next;
d->next = file->deps;
register struct dep *deps = to_file->deps;
while (deps->next != 0)
deps = deps->next;
deps->next = from_file->deps;
}
merge_variable_set_lists (&oldfile->variables, file->variables);
merge_variable_set_lists (&to_file->variables, from_file->variables);
if (oldfile->double_colon && file->is_target && !file->double_colon)
if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
oldname, name);
if (!oldfile->double_colon && file->double_colon)
from_file->name, to_hname);
if (!to_file->double_colon && from_file->double_colon)
{
if (oldfile->is_target)
if (to_file->is_target)
fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
oldname, name);
from_file->name, to_hname);
else
oldfile->double_colon = file->double_colon;
to_file->double_colon = from_file->double_colon;
}
if (file->last_mtime > oldfile->last_mtime)
if (from_file->last_mtime > to_file->last_mtime)
/* %%% Kludge so -W wins on a file that gets vpathized. */
oldfile->last_mtime = file->last_mtime;
to_file->last_mtime = from_file->last_mtime;
oldfile->mtime_before_update = file->mtime_before_update;
to_file->mtime_before_update = from_file->mtime_before_update;
#define MERGE(field) oldfile->field |= file->field
#define MERGE(field) to_file->field |= from_file->field
MERGE (precious);
MERGE (tried_implicit);
MERGE (updating);
@@ -368,7 +323,7 @@ in favor of those for `%s'."),
MERGE (ignore_vpath);
#undef MERGE
file->renamed = oldfile;
from_file->renamed = to_file;
}
}
@@ -381,54 +336,65 @@ void
remove_intermediates (sig)
int sig;
{
register int i;
register struct file *f;
char doneany;
register struct file **file_slot;
register struct file **file_end;
int doneany = 0;
if (question_flag || touch_flag)
/* If there's no way we will ever remove anything anyway, punt early. */
if (question_flag || touch_flag || all_secondary)
return;
if (sig && just_print_flag)
return;
doneany = 0;
for (i = 0; i < FILE_BUCKETS; ++i)
for (f = files[i]; f != 0; f = f->next)
if (f->intermediate && (f->dontcare || !f->precious)
&& !f->secondary)
{
int status;
if (f->update_status == -1)
/* If nothing would have created this file yet,
don't print an "rm" command for it. */
continue;
else if (just_print_flag)
status = 0;
else
{
status = unlink (f->name);
if (status < 0 && errno == ENOENT)
continue;
}
if (!f->dontcare)
{
if (sig)
error (NILF, _("*** Deleting intermediate file `%s'"), f->name);
else if (!silent_flag)
{
if (! doneany)
{
fputs ("rm ", stdout);
doneany = 1;
}
else
putchar (' ');
fputs (f->name, stdout);
fflush (stdout);
}
if (status < 0)
perror_with_name ("unlink: ", f->name);
}
}
file_slot = (struct file **) files.ht_vec;
file_end = file_slot + files.ht_size;
for ( ; file_slot < file_end; file_slot++)
if (! HASH_VACANT (*file_slot))
{
register struct file *f = *file_slot;
if (f->intermediate && (f->dontcare || !f->precious)
&& !f->secondary && !f->cmd_target)
{
int status;
if (f->update_status == -1)
/* If nothing would have created this file yet,
don't print an "rm" command for it. */
continue;
if (just_print_flag)
status = 0;
else
{
status = unlink (f->name);
if (status < 0 && errno == ENOENT)
continue;
}
if (!f->dontcare)
{
if (sig)
error (NILF, _("*** Deleting intermediate file `%s'"), f->name);
else
{
if (! doneany)
DB (DB_BASIC, (_("Removing intermediate files...\n")));
if (!silent_flag)
{
if (! doneany)
{
fputs ("rm ", stdout);
doneany = 1;
}
else
putchar (' ');
fputs (f->name, stdout);
fflush (stdout);
}
}
if (status < 0)
perror_with_name ("unlink: ", f->name);
}
}
}
if (doneany && !sig)
{
@@ -446,38 +412,51 @@ remove_intermediates (sig)
void
snap_deps ()
{
register struct file *f, *f2;
register struct file *f;
register struct file *f2;
register struct dep *d;
register int i;
register struct file **file_slot_0;
register struct file **file_slot;
register struct file **file_end;
/* Enter each dependency name as a file. */
for (i = 0; i < FILE_BUCKETS; ++i)
for (f = files[i]; f != 0; f = f->next)
for (f2 = f; f2 != 0; f2 = f2->prev)
for (d = f2->deps; d != 0; d = d->next)
if (d->name != 0)
{
d->file = lookup_file (d->name);
if (d->file == 0)
d->file = enter_file (d->name);
else
free (d->name);
d->name = 0;
}
/* We must use hash_dump (), because within this loop
we might add new files to the table, possibly causing
an in-situ table expansion. */
file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
file_end = file_slot_0 + files.ht_fill;
for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
for (f2 = *file_slot; f2 != 0; f2 = f2->prev)
for (d = f2->deps; d != 0; d = d->next)
if (d->name != 0)
{
d->file = lookup_file (d->name);
if (d->file == 0)
d->file = enter_file (d->name);
else
free (d->name);
d->name = 0;
}
free (file_slot_0);
for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
f2->precious = 1;
for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
f2->low_resolution_time = 1;
for (f = lookup_file (".PHONY"); f != 0; f = f->prev)
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
{
/* Mark this file as phony and nonexistent. */
f2->phony = 1;
f2->last_mtime = (FILE_TIMESTAMP) -1;
f2->mtime_before_update = (FILE_TIMESTAMP) -1;
f2->last_mtime = NONEXISTENT_MTIME;
f2->mtime_before_update = NONEXISTENT_MTIME;
}
for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
@@ -500,19 +479,12 @@ snap_deps ()
but unlike real intermediate files,
these are not deleted after make finishes. */
if (f->deps)
{
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
f2->intermediate = f2->secondary = 1;
}
for (d = f->deps; d != 0; d = d->next)
for (f2 = d->file; f2 != 0; f2 = f2->prev)
f2->intermediate = f2->secondary = 1;
/* .SECONDARY with no deps listed marks *all* files that way. */
else
{
int i;
for (i = 0; i < FILE_BUCKETS; i++)
for (f2 = files[i]; f2; f2= f2->next)
f2->intermediate = f2->secondary = 1;
}
all_secondary = 1;
}
f = lookup_file (".EXPORT_ALL_VARIABLES");
@@ -565,19 +537,82 @@ set_command_state (file, state)
d->file->command_state = state;
}
/* Get and print file timestamps. */
/* Convert an external file timestamp to internal form. */
FILE_TIMESTAMP
file_timestamp_now ()
file_timestamp_cons (fname, s, ns)
char const *fname;
time_t s;
int ns;
{
#if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
struct timespec timespec;
if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
return FILE_TIMESTAMP_FROM_S_AND_NS (timespec.tv_sec, timespec.tv_nsec);
int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);
FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;
FILE_TIMESTAMP ts = product + offset;
if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)
&& product <= ts && ts <= ORDINARY_MTIME_MAX))
{
char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
file_timestamp_sprintf (buf, ts);
error (NILF, _("%s: Timestamp out of range; substituting %s"),
fname ? fname : _("Current time"), buf);
}
return ts;
}
/* Return the current time as a file timestamp, setting *RESOLUTION to
its resolution. */
FILE_TIMESTAMP
file_timestamp_now (resolution)
int *resolution;
{
int r;
time_t s;
int ns;
/* Don't bother with high-resolution clocks if file timestamps have
only one-second resolution. The code below should work, but it's
not worth the hassle of debugging it on hosts where it fails. */
#if FILE_TIMESTAMP_HI_RES
# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
{
struct timespec timespec;
if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
{
r = 1;
s = timespec.tv_sec;
ns = timespec.tv_nsec;
goto got_time;
}
}
# endif
# if HAVE_GETTIMEOFDAY
{
struct timeval timeval;
if (gettimeofday (&timeval, 0) == 0)
{
r = 1000;
s = timeval.tv_sec;
ns = timeval.tv_usec * 1000;
goto got_time;
}
}
# endif
#endif
return FILE_TIMESTAMP_FROM_S_AND_NS (time ((time_t *) 0), 0);
r = 1000000000;
s = time ((time_t *) 0);
ns = 0;
got_time:
*resolution = r;
return file_timestamp_cons (0, s, ns);
}
/* Place into the buffer P a printable representation of the file
timestamp TS. */
void
file_timestamp_sprintf (p, ts)
char *p;
@@ -601,7 +636,7 @@ file_timestamp_sprintf (p, ts)
applies only to local times, whereas this timestamp might come
from a remote filesystem. So removing trailing zeros is the
best guess that we can do. */
sprintf (p, ".%09ld", (long) FILE_TIMESTAMP_NS (ts));
sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
p += strlen (p) - 1;
while (*p == '0')
p--;
@@ -616,15 +651,30 @@ static void
print_file (f)
struct file *f;
{
register struct dep *d;
struct dep *d;
struct dep *ood = 0;
putchar ('\n');
if (!f->is_target)
puts (_("# Not a target:"));
printf ("%s:%s", f->name, f->double_colon ? ":" : "");
/* Print all normal dependencies; note any order-only deps. */
for (d = f->deps; d != 0; d = d->next)
printf (" %s", dep_name (d));
if (! d->ignore_mtime)
printf (" %s", dep_name (d));
else if (! ood)
ood = d;
/* Print order-only deps, if we have any. */
if (ood)
{
printf (" | %s", dep_name (ood));
for (d = ood->next; d != 0; d = d->next)
if (d->ignore_mtime)
printf (" %s", dep_name (d));
}
putchar ('\n');
if (f->precious)
@@ -649,10 +699,12 @@ print_file (f)
printf (" %s", dep_name (d));
putchar ('\n');
}
if (f->last_mtime == 0)
if (f->last_mtime == UNKNOWN_MTIME)
puts (_("# Modification time never checked."));
else if (f->last_mtime == (FILE_TIMESTAMP) -1)
else if (f->last_mtime == NONEXISTENT_MTIME)
puts (_("# File does not exist."));
else if (f->last_mtime == OLD_MTIME)
puts (_("# File is very old."));
else
{
char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
@@ -709,41 +761,67 @@ print_file (f)
void
print_file_data_base ()
{
register unsigned int i, nfiles, per_bucket;
register struct file *file;
puts (_("\n# Files"));
per_bucket = nfiles = 0;
for (i = 0; i < FILE_BUCKETS; ++i)
hash_map (&files, print_file);
fputs (_("\n# files hash-table stats:\n# "), stdout);
hash_print_stats (&files, stdout);
}
#define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500)
char *
build_target_list (value)
char *value;
{
static unsigned long last_targ_count = 0;
if (files.ht_fill != last_targ_count)
{
register unsigned int this_bucket = 0;
unsigned long max = EXPANSION_INCREMENT (strlen (value));
unsigned long len;
char *p;
struct file **fp = (struct file **) files.ht_vec;
struct file **end = &fp[files.ht_size];
for (file = files[i]; file != 0; file = file->next)
{
register struct file *f;
/* Make sure we have at least MAX bytes in the allocated buffer. */
value = xrealloc (value, max);
++this_bucket;
p = value;
len = 0;
for (; fp < end; ++fp)
if (!HASH_VACANT (*fp) && (*fp)->is_target)
{
struct file *f = *fp;
int l = strlen (f->name);
for (f = file; f != 0; f = f->prev)
print_file (f);
}
len += l + 1;
if (len > max)
{
unsigned long off = p - value;
nfiles += this_bucket;
if (this_bucket > per_bucket)
per_bucket = this_bucket;
max += EXPANSION_INCREMENT (l + 1);
value = xrealloc (value, max);
p = &value[off];
}
bcopy (f->name, p, l);
p += l;
*(p++) = ' ';
}
*(p-1) = '\0';
last_targ_count = files.ht_fill;
}
if (nfiles == 0)
puts (_("\n# No files."));
else
{
printf (_("\n# %u files in %u hash buckets.\n"), nfiles, FILE_BUCKETS);
#ifndef NO_FLOAT
printf (_("# average %.3f files per bucket, max %u files in one bucket.\n"),
((double) nfiles) / ((double) FILE_BUCKETS), per_bucket);
#endif
}
return value;
}
void
init_hash_files ()
{
hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
}
/* EOF */

View File

@@ -1,5 +1,6 @@
/* Definition of target file data structures for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,97 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -22,13 +23,14 @@ Boston, MA 02111-1307, USA. */
that the makefile says how to make.
All of these are chained together through `next'. */
#include "hash.h"
struct file
{
struct file *next;
char *name;
char *hname; /* Hashed filename */
char *vpath; /* VPATH/vpath pathname */
struct dep *deps;
struct dep *deps; /* all dependencies, including duplicates */
struct commands *cmds; /* Commands to execute for this target. */
int command_flags; /* Flags OR'd in for cmds; see commands.h. */
char *stem; /* Implicit stem, if an implicit
@@ -72,6 +74,8 @@ struct file
} command_state ENUM_BITFIELD (2);
unsigned int precious:1; /* Non-0 means don't delete file on quit */
unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp
has only one-second resolution. */
unsigned int tried_implicit:1; /* Nonzero if have searched
for implicit rule for making
this file; don't search again. */
@@ -94,13 +98,6 @@ struct file
considered on current scan of goal chain */
};
/* Number of intermediate files entered. */
extern unsigned int num_intermediates;
/* Current value for pruning the scan of the goal chain (toggle 0/1). */
extern unsigned int considered;
extern struct file *default_goal_file, *suffix_file, *default_file;
@@ -111,35 +108,31 @@ extern void remove_intermediates PARAMS ((int sig));
extern void snap_deps PARAMS ((void));
extern void rename_file PARAMS ((struct file *file, char *name));
extern void rehash_file PARAMS ((struct file *file, char *name));
extern void file_hash_enter PARAMS ((struct file *file, char *name,
unsigned int oldhash, char *oldname));
extern void set_command_state PARAMS ((struct file *file, int state));
extern void notice_finished_file PARAMS ((struct file *file));
extern void init_hash_files PARAMS ((void));
extern char *build_target_list PARAMS ((char *old_list));
#if ST_MTIM_NSEC
# define FILE_TIMESTAMP_STAT_MODTIME(st) \
FILE_TIMESTAMP_FROM_S_AND_NS ((st).st_mtim.tv_sec, \
(st).st_mtim.ST_MTIM_NSEC)
# define FILE_TIMESTAMPS_PER_S \
MIN ((FILE_TIMESTAMP) 1000000000, \
(INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
/ INTEGER_TYPE_MAXIMUM (time_t)))
#if FILE_TIMESTAMP_HI_RES
# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
file_timestamp_cons (fname, (st).st_mtime, (st).st_mtim.ST_MTIM_NSEC)
#else
# define FILE_TIMESTAMP_STAT_MODTIME(st) ((st).st_mtime)
# define FILE_TIMESTAMPS_PER_S 1
# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \
file_timestamp_cons (fname, (st).st_mtime, 0)
#endif
#define FILE_TIMESTAMP_FROM_S_AND_NS(s, ns) \
((s) * FILE_TIMESTAMPS_PER_S \
+ (ns) * FILE_TIMESTAMPS_PER_S / 1000000000)
#define FILE_TIMESTAMP_DIV(a, b) ((a)/(b) - ((a)%(b) < 0))
#define FILE_TIMESTAMP_MOD(a, b) ((a)%(b) + ((a)%(b) < 0) * (b))
#define FILE_TIMESTAMP_S(ts) FILE_TIMESTAMP_DIV ((ts), FILE_TIMESTAMPS_PER_S)
#define FILE_TIMESTAMP_NS(ts) \
(((FILE_TIMESTAMP_MOD ((ts), FILE_TIMESTAMPS_PER_S) * 1000000000) \
+ (FILE_TIMESTAMPS_PER_S - 1)) \
/ FILE_TIMESTAMPS_PER_S)
/* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution.
(Multiply by 2**30 instead of by 10**9 to save time at the cost of
slightly decreasing the number of available timestamps.) With
64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04
UTC, but by then uintmax_t should be larger than 64 bits. */
#define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1)
#define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0)
#define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \
>> FILE_TIMESTAMP_LO_BITS)
#define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \
& ((1 << FILE_TIMESTAMP_LO_BITS) - 1)))
/* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN"
representing a file timestamp. The upper bound is not necessarily 19,
@@ -159,35 +152,48 @@ extern void notice_finished_file PARAMS ((struct file *file));
* 302 / 1000) \
+ 1 + 1 + 4 + 25)
extern FILE_TIMESTAMP file_timestamp_now PARAMS ((void));
extern FILE_TIMESTAMP file_timestamp_cons PARAMS ((char const *,
time_t, int));
extern FILE_TIMESTAMP file_timestamp_now PARAMS ((int *));
extern void file_timestamp_sprintf PARAMS ((char *p, FILE_TIMESTAMP ts));
/* Return the mtime of file F (a struct file *), caching it.
The value is -1 if the file does not exist. */
The value is NONEXISTENT_MTIME if the file does not exist. */
#define file_mtime(f) file_mtime_1 ((f), 1)
/* Return the mtime of file F (a struct file *), caching it.
Don't search using vpath for the file--if it doesn't actually exist,
we don't find it.
The value is -1 if the file does not exist. */
The value is NONEXISTENT_MTIME if the file does not exist. */
#define file_mtime_no_search(f) file_mtime_1 ((f), 0)
extern FILE_TIMESTAMP f_mtime PARAMS ((struct file *file, int search));
#define file_mtime_1(f, v) \
((f)->last_mtime ? (f)->last_mtime : f_mtime ((f), v))
((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime)
/* Special timestamp values. */
/* The file's timestamp is not yet known. */
#define UNKNOWN_MTIME 0
/* The file does not exist. */
#define NONEXISTENT_MTIME 1
/* The file does not exist, and we assume that it is older than any
actual file. */
#define OLD_MTIME 2
/* The smallest and largest ordinary timestamps. */
#define ORDINARY_MTIME_MIN (OLD_MTIME + 1)
#define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \
<< FILE_TIMESTAMP_LO_BITS) \
+ ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1)
/* Modtime value to use for `infinitely new'. We used to get the current time
from the system and use that whenever we wanted `new'. But that causes
trouble when the machine running make and the machine holding a file have
different ideas about what time it is; and can also lose for `force'
targets, which need to be considered newer than anything that depends on
them, even if said dependents' modtimes are in the future.
If FILE_TIMESTAMP is unsigned, its maximum value is the same as
((FILE_TIMESTAMP) -1), so use one less than that, because -1 is
used for non-existing files. */
#define NEW_MTIME \
(INTEGER_TYPE_SIGNED (FILE_TIMESTAMP) \
? INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) \
: (INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) - 1))
them, even if said dependents' modtimes are in the future. */
#define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP)
#define check_renamed(file) \
while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */

View File

@@ -1,5 +1,5 @@
/* Builtin function expansion for GNU Make.
Copyright (C) 1988,1989,1991-1997,1999 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1991-1997, 1999, 2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -37,8 +37,39 @@ struct function_table_entry
unsigned char minimum_args;
unsigned char maximum_args;
char expand_args;
char *(*func_ptr) PARAMS((char *output, char **argv, const char*funcname));
char *(*func_ptr) PARAMS ((char *output, char **argv, const char *fname));
};
static unsigned long
function_table_entry_hash_1 (keyv)
const void *keyv;
{
struct function_table_entry const *key = (struct function_table_entry const *) keyv;
return_STRING_N_HASH_1 (key->name, key->len);
}
static unsigned long
function_table_entry_hash_2 (keyv)
const void *keyv;
{
struct function_table_entry const *key = (struct function_table_entry const *) keyv;
return_STRING_N_HASH_2 (key->name, key->len);
}
static int
function_table_entry_hash_cmp (xv, yv)
const void *xv;
const void *yv;
{
struct function_table_entry const *x = (struct function_table_entry const *) xv;
struct function_table_entry const *y = (struct function_table_entry const *) yv;
int result = x->len - y->len;
if (result)
return result;
return_STRING_N_COMPARE (x->name, y->name, x->len);
}
static struct hash_table function_table;
/* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing
@@ -92,10 +123,10 @@ subst_expand (o, text, subst, replace, slen, rlen, by_word, suffix_only)
/* If we're substituting only by fully matched words,
or only at the ends of words, check that this case qualifies. */
if ((by_word
&& ((p > t && !isblank (p[-1]))
|| (p[slen] != '\0' && !isblank (p[slen]))))
&& ((p > t && !isblank ((unsigned char)p[-1]))
|| (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
|| (suffix_only
&& (p[slen] != '\0' && !isblank (p[slen]))))
&& (p[slen] != '\0' && !isblank ((unsigned char)p[slen]))))
/* Struck out. Output the rest of the string that is
no longer to be replaced. */
o = variable_buffer_output (o, subst, slen);
@@ -128,7 +159,7 @@ patsubst_expand (o, text, pattern, replace, pattern_percent, replace_percent)
unsigned int pattern_prepercent_len, pattern_postpercent_len;
unsigned int replace_prepercent_len, replace_postpercent_len = 0;
char *t;
int len;
unsigned int len;
int doneany = 0;
/* We call find_percent on REPLACE before checking PATTERN so that REPLACE
@@ -221,25 +252,25 @@ patsubst_expand (o, text, pattern, replace, pattern_percent, replace_percent)
}
/* Look up a function by name.
The table is currently small enough that it's not really worthwhile to use
a fancier lookup algorithm. If it gets larger, maybe...
*/
/* Look up a function by name. */
static const struct function_table_entry *
lookup_function (table, s)
const struct function_table_entry *table;
lookup_function (s)
const char *s;
{
int len = strlen(s);
const char *e = s;
for (; table->name != NULL; ++table)
if (table->len <= len
&& (isblank (s[table->len]) || s[table->len] == '\0')
&& strneq (s, table->name, table->len))
return table;
while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
e++;
if (*e == '\0' || isblank ((unsigned char) *e))
{
struct function_table_entry function_table_entry_key;
function_table_entry_key.name = s;
function_table_entry_key.len = e - s;
return NULL;
return hash_find_item (&function_table, &function_table_entry_key);
}
return 0;
}
@@ -386,7 +417,7 @@ func_patsubst (o, argv, funcname)
static char *
func_join(o, argv, funcname)
func_join (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -429,7 +460,7 @@ func_join(o, argv, funcname)
static char *
func_origin(o, argv, funcname)
func_origin (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -472,18 +503,18 @@ func_origin(o, argv, funcname)
}
#ifdef VMS
#define IS_PATHSEP(c) ((c) == ']')
# define IS_PATHSEP(c) ((c) == ']')
#else
#if defined(__MSDOS__) || defined(WINDOWS32)
#define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
#else
#define IS_PATHSEP(c) ((c) == '/')
#endif
# ifdef HAVE_DOS_PATHS
# define IS_PATHSEP(c) ((c) == '/' || (c) == '\\')
# else
# define IS_PATHSEP(c) ((c) == '/')
# endif
#endif
static char *
func_notdir_suffix(o, argv, funcname)
func_notdir_suffix (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -492,9 +523,9 @@ func_notdir_suffix(o, argv, funcname)
char *list_iterator = argv[0];
char *p2 =0;
int doneany =0;
int len=0;
unsigned int len=0;
int is_suffix = streq(funcname, "suffix");
int is_suffix = streq (funcname, "suffix");
int is_notdir = !is_suffix;
while ((p2 = find_next_token (&list_iterator, &len)) != 0)
{
@@ -516,9 +547,9 @@ func_notdir_suffix(o, argv, funcname)
continue;
o = variable_buffer_output (o, p, len - (p - p2));
}
#if defined(WINDOWS32) || defined(__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* Handle the case of "d:foo/bar". */
else if (streq(funcname, "notdir") && p2[0] && p2[1] == ':')
else if (streq (funcname, "notdir") && p2[0] && p2[1] == ':')
{
p = p2 + 2;
o = variable_buffer_output (o, p, len - (p - p2));
@@ -544,7 +575,7 @@ func_notdir_suffix(o, argv, funcname)
static char *
func_basename_dir(o, argv, funcname)
func_basename_dir (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -555,7 +586,7 @@ func_basename_dir(o, argv, funcname)
int doneany=0;
unsigned int len=0;
char *p=0;
int is_basename= streq(funcname, "basename");
int is_basename= streq (funcname, "basename");
int is_dir= !is_basename;
while ((p2 = find_next_token (&p3, &len)) != 0)
@@ -563,7 +594,7 @@ func_basename_dir(o, argv, funcname)
p = p2 + len;
while (p >= p2 && (!is_basename || *p != '.'))
{
if (IS_PATHSEP(*p))
if (IS_PATHSEP (*p))
break;
--p;
}
@@ -572,7 +603,7 @@ func_basename_dir(o, argv, funcname)
o = variable_buffer_output (o, p2, ++p - p2);
else if (p >= p2 && (*p == '.'))
o = variable_buffer_output (o, p2, p - p2);
#if defined(WINDOWS32) || defined(__MSDOS__)
#ifdef HAVE_DOS_PATHS
/* Handle the "d:foobar" case */
else if (p2[0] && p2[1] == ':' && is_dir)
o = variable_buffer_output (o, p2, 2);
@@ -603,7 +634,7 @@ func_basename_dir(o, argv, funcname)
}
static char *
func_addsuffix_addprefix(o, argv, funcname)
func_addsuffix_addprefix (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -636,7 +667,7 @@ func_addsuffix_addprefix(o, argv, funcname)
}
static char *
func_subst(o, argv, funcname)
func_subst (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -649,7 +680,7 @@ func_subst(o, argv, funcname)
static char *
func_firstword(o, argv, funcname)
func_firstword (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -666,7 +697,7 @@ func_firstword(o, argv, funcname)
static char *
func_words(o, argv, funcname)
func_words (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -724,7 +755,7 @@ check_numeric (s, message)
static char *
func_word(o, argv, funcname)
func_word (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -738,7 +769,7 @@ func_word(o, argv, funcname)
i = atoi (argv[0]);
if (i == 0)
fatal (reading_file, _("the `word' function takes a positive index argument"));
fatal (reading_file, _("first argument to `word' function must be greater than 0"));
end_p = argv[1];
@@ -758,45 +789,42 @@ func_wordlist (o, argv, funcname)
char **argv;
const char *funcname;
{
int i=0;
int j=0;
int start, count;
/* Check the first argument. */
/* Check the arguments. */
check_numeric (argv[0],
_("non-numeric first argument to `wordlist' function"));
i =atoi(argv[0]);
check_numeric (argv[1],
_("non-numeric second argument to `wordlist' function"));
j = atoi(argv[1]);
start = atoi (argv[0]);
count = atoi (argv[1]) - start + 1;
if (count > 0)
{
char *p;
char *end_p = argv[2];
{
char *p;
char *end_p = argv[2];
/* Find the beginning of the "start"th word. */
while (((p = find_next_token (&end_p, 0)) != 0) && --start)
;
int start = (i < j) ? i : j;
int count = j -i ;
if (count < 0)
count = - count;
count ++;
if (p)
{
/* Find the end of the "count"th word from start. */
while (--count && (find_next_token (&end_p, 0) != 0))
;
/* Return the stuff in the middle. */
o = variable_buffer_output (o, p, end_p - p);
}
}
while (((p = find_next_token (&end_p, 0)) != 0) && --start)
{}
if (p)
{
while (--count && (find_next_token (&end_p, 0) != 0))
{}
o = variable_buffer_output (o, p, end_p - p);
}
}
return o;
}
static char*
func_findstring(o, argv, funcname)
func_findstring (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -865,64 +893,154 @@ func_foreach (o, argv, funcname)
struct a_word
{
struct a_word *next;
struct a_word *chain;
char *str;
int length;
int matched;
};
static unsigned long
a_word_hash_1 (key)
const void *key;
{
return_STRING_HASH_1 (((struct a_word const *) key)->str);
}
static unsigned long
a_word_hash_2 (key)
const void *key;
{
return_STRING_HASH_2 (((struct a_word const *) key)->str);
}
static int
a_word_hash_cmp (x, y)
const void *x;
const void *y;
{
int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length;
if (result)
return result;
return_STRING_COMPARE (((struct a_word const *) x)->str,
((struct a_word const *) y)->str);
}
struct a_pattern
{
struct a_pattern *next;
char *str;
char *percent;
int length;
int save_c;
};
static char *
func_filter_filterout (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
{
struct a_word *wordhead = 0;
struct a_word *wordtail = 0;
struct a_word *wordhead;
struct a_word **wordtail;
struct a_word *wp;
struct a_pattern *pathead;
struct a_pattern **pattail;
struct a_pattern *pp;
struct hash_table a_word_table;
int is_filter = streq (funcname, "filter");
char *patterns = argv[0];
char *pat_iterator = argv[0];
char *word_iterator = argv[1];
int literals = 0;
int words = 0;
int hashing = 0;
char *p;
unsigned int len;
/* Chop ARGV[1] up into words and then run each pattern through. */
/* Chop ARGV[0] up into patterns to match against the words. */
pattail = &pathead;
while ((p = find_next_token (&pat_iterator, &len)) != 0)
{
struct a_pattern *pat = (struct a_pattern *) alloca (sizeof (struct a_pattern));
*pattail = pat;
pattail = &pat->next;
if (*pat_iterator != '\0')
++pat_iterator;
pat->str = p;
pat->length = len;
pat->save_c = p[len];
p[len] = '\0';
pat->percent = find_percent (p);
if (pat->percent == 0)
literals++;
}
*pattail = 0;
/* Chop ARGV[1] up into words to match against the patterns. */
wordtail = &wordhead;
while ((p = find_next_token (&word_iterator, &len)) != 0)
{
struct a_word *w = (struct a_word *)alloca(sizeof(struct a_word));
if (wordhead == 0)
wordhead = w;
else
wordtail->next = w;
wordtail = w;
struct a_word *word = (struct a_word *) alloca (sizeof (struct a_word));
*wordtail = word;
wordtail = &word->next;
if (*word_iterator != '\0')
++word_iterator;
p[len] = '\0';
w->str = p;
w->matched = 0;
word->str = p;
word->length = len;
word->matched = 0;
word->chain = 0;
words++;
}
*wordtail = 0;
/* Only use a hash table if arg list lengths justifies the cost. */
hashing = (literals >= 2 && (literals * words) >= 10);
if (hashing)
{
hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2, a_word_hash_cmp);
for (wp = wordhead; wp != 0; wp = wp->next)
{
struct a_word *owp = hash_insert (&a_word_table, wp);
if (owp)
wp->chain = owp;
}
}
if (wordhead != 0)
if (words)
{
char *pat_iterator = patterns;
int doneany = 0;
struct a_word *wp;
wordtail->next = 0;
/* Run each pattern through the words, killing words. */
while ((p = find_next_token (&pat_iterator, &len)) != 0)
for (pp = pathead; pp != 0; pp = pp->next)
{
char *percent;
char save = p[len];
p[len] = '\0';
percent = find_percent (p);
for (wp = wordhead; wp != 0; wp = wp->next)
wp->matched |= (percent == 0 ? streq (p, wp->str)
: pattern_matches (p, percent, wp->str));
p[len] = save;
if (pp->percent)
for (wp = wordhead; wp != 0; wp = wp->next)
wp->matched |= pattern_matches (pp->str, pp->percent, wp->str);
else if (hashing)
{
struct a_word a_word_key;
a_word_key.str = pp->str;
a_word_key.length = pp->length;
wp = (struct a_word *) hash_find_item (&a_word_table, &a_word_key);
while (wp)
{
wp->matched |= 1;
wp = wp->chain;
}
}
else
for (wp = wordhead; wp != 0; wp = wp->next)
wp->matched |= (wp->length == pp->length
&& strneq (pp->str, wp->str, wp->length));
}
/* Output the words that matched (or didn't, for filter-out). */
@@ -939,12 +1057,18 @@ func_filter_filterout (o, argv, funcname)
--o;
}
for (pp = pathead; pp != 0; pp = pp->next)
pp->str[pp->length] = pp->save_c;
if (hashing)
hash_free (&a_word_table, 0);
return o;
}
static char *
func_strip(o, argv, funcname)
func_strip (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -992,18 +1116,18 @@ func_error (o, argv, funcname)
another special case where function arguments aren't broken up,
just create a format string that puts them back together. */
for (len=0, argvp=argv; *argvp != 0; ++argvp)
len += strlen(*argvp) + 2;
len += strlen (*argvp) + 2;
p = msg = alloca (len + 1);
p = msg = (char *) alloca (len + 1);
for (argvp=argv; argvp[1] != 0; ++argvp)
{
strcpy(p, *argvp);
p += strlen(*argvp);
strcpy (p, *argvp);
p += strlen (*argvp);
*(p++) = ',';
*(p++) = ' ';
}
strcpy(p, *argvp);
strcpy (p, *argvp);
if (*funcname == 'e')
fatal (reading_file, "%s", msg);
@@ -1128,7 +1252,7 @@ func_if (o, argv, funcname)
}
static char *
func_wildcard(o, argv, funcname)
func_wildcard (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
@@ -1143,6 +1267,42 @@ func_wildcard(o, argv, funcname)
return o;
}
/*
$(eval <makefile string>)
Always resolves to the empty string.
Treat the arguments as a segment of makefile, and parse them.
*/
static char *
func_eval (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
{
eval_buffer (argv[0]);
return o;
}
static char *
func_value (o, argv, funcname)
char *o;
char **argv;
const char *funcname;
{
/* Look up the variable. */
struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
/* Copy its value into the output buffer without expanding it. */
if (v)
o = variable_buffer_output (o, v->value, strlen(v->value));
return o;
}
/*
\r is replaced on UNIX as well. Is this desirable?
*/
@@ -1197,11 +1357,11 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp)
HANDLE hProcess;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (DuplicateHandle(GetCurrentProcess(),
if (DuplicateHandle (GetCurrentProcess(),
GetStdHandle(STD_INPUT_HANDLE),
GetCurrentProcess(),
&hIn,
@@ -1277,7 +1437,7 @@ msdos_openpipe (int* pipedes, int *pidp, char *text)
extern int dos_command_running, dos_status;
/* Make sure not to bother processing an empty line. */
while (isblank (*text))
while (isblank ((unsigned char)*text))
++text;
if (*text == '\0')
return 0;
@@ -1371,7 +1531,7 @@ func_shell (o, argv, funcname)
/* For error messages. */
if (reading_file != 0)
{
error_prefix = (char *) alloca (strlen(reading_file->filenm)+11+4);
error_prefix = (char *) alloca (strlen (reading_file->filenm)+11+4);
sprintf (error_prefix,
"%s:%lu: ", reading_file->filenm, reading_file->lineno);
}
@@ -1438,8 +1598,7 @@ func_shell (o, argv, funcname)
buffer = (char *) xmalloc (maxlen + 1);
/* Read from the pipe until it gets EOF. */
i = 0;
do
for (i = 0; ; i += cc)
{
if (i == maxlen)
{
@@ -1447,12 +1606,11 @@ func_shell (o, argv, funcname)
buffer = (char *) xrealloc (buffer, maxlen + 1);
}
errno = 0;
cc = read (pipedes[0], &buffer[i], maxlen - i);
if (cc > 0)
i += cc;
if (cc <= 0)
break;
}
while (cc > 0 || EINTR_SET);
buffer[i] = '\0';
/* Close the read side of the pipe. */
#ifdef __MSDOS__
@@ -1470,8 +1628,8 @@ func_shell (o, argv, funcname)
if (batch_filename) {
DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
batch_filename));
remove(batch_filename);
free(batch_filename);
remove (batch_filename);
free (batch_filename);
}
shell_function_pid = 0;
@@ -1536,7 +1694,10 @@ func_shell (char *o, char **argv, const char *funcname)
if (command_argv == 0)
return o;
/* Note the mktemp() is a security hole, but this only runs on Amiga.
Ideally we would use main.c:open_tmpfile(), but this uses a special
Open(), not fopen(), and I'm not familiar enough with the code to mess
with it. */
strcpy (tmp_output, "t:MakeshXXXXXXXX");
mktemp (tmp_output);
child_stdout = Open (tmp_output, MODE_NEWFILE);
@@ -1620,8 +1781,6 @@ func_not (char* o, char **argv, char *funcname)
#endif
#define STRING_SIZE_TUPLE(_s) (_s), (sizeof(_s)-1)
/* Lookup table for builtin functions.
This doesn't have to be sorted; we use a straight lookup. We might gain
@@ -1634,47 +1793,50 @@ func_not (char* o, char **argv, char *funcname)
EXPAND_ARGS means that all arguments should be expanded before invocation.
Functions that do namespace tricks (foreach) don't automatically expand. */
static char *func_call PARAMS((char *o, char **argv, const char *funcname));
static char *func_call PARAMS ((char *o, char **argv, const char *funcname));
static struct function_table_entry function_table[] =
static struct function_table_entry function_table_init[] =
{
/* Name/size */ /* MIN MAX EXP? Function */
{ STRING_SIZE_TUPLE("addprefix"), 2, 2, 1, func_addsuffix_addprefix},
{ STRING_SIZE_TUPLE("addsuffix"), 2, 2, 1, func_addsuffix_addprefix},
{ STRING_SIZE_TUPLE("basename"), 1, 1, 1, func_basename_dir},
{ STRING_SIZE_TUPLE("dir"), 1, 1, 1, func_basename_dir},
{ STRING_SIZE_TUPLE("notdir"), 1, 1, 1, func_notdir_suffix},
{ STRING_SIZE_TUPLE("basename"), 0, 1, 1, func_basename_dir},
{ STRING_SIZE_TUPLE("dir"), 0, 1, 1, func_basename_dir},
{ STRING_SIZE_TUPLE("notdir"), 0, 1, 1, func_notdir_suffix},
{ STRING_SIZE_TUPLE("subst"), 3, 3, 1, func_subst},
{ STRING_SIZE_TUPLE("suffix"), 1, 1, 1, func_notdir_suffix},
{ STRING_SIZE_TUPLE("suffix"), 0, 1, 1, func_notdir_suffix},
{ STRING_SIZE_TUPLE("filter"), 2, 2, 1, func_filter_filterout},
{ STRING_SIZE_TUPLE("filter-out"), 2, 2, 1, func_filter_filterout},
{ STRING_SIZE_TUPLE("findstring"), 2, 2, 1, func_findstring},
{ STRING_SIZE_TUPLE("firstword"), 1, 1, 1, func_firstword},
{ STRING_SIZE_TUPLE("firstword"), 0, 1, 1, func_firstword},
{ STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join},
{ STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst},
{ STRING_SIZE_TUPLE("shell"), 1, 1, 1, func_shell},
{ STRING_SIZE_TUPLE("sort"), 1, 1, 1, func_sort},
{ STRING_SIZE_TUPLE("strip"), 1, 1, 1, func_strip},
{ STRING_SIZE_TUPLE("wildcard"), 1, 1, 1, func_wildcard},
{ STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell},
{ STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
{ STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip},
{ STRING_SIZE_TUPLE("wildcard"), 0, 1, 1, func_wildcard},
{ STRING_SIZE_TUPLE("word"), 2, 2, 1, func_word},
{ STRING_SIZE_TUPLE("wordlist"), 3, 3, 1, func_wordlist},
{ STRING_SIZE_TUPLE("words"), 1, 1, 1, func_words},
{ STRING_SIZE_TUPLE("origin"), 1, 1, 1, func_origin},
{ STRING_SIZE_TUPLE("words"), 0, 1, 1, func_words},
{ STRING_SIZE_TUPLE("origin"), 0, 1, 1, func_origin},
{ STRING_SIZE_TUPLE("foreach"), 3, 3, 0, func_foreach},
{ STRING_SIZE_TUPLE("call"), 1, 0, 0, func_call},
{ STRING_SIZE_TUPLE("error"), 1, 1, 1, func_error},
{ STRING_SIZE_TUPLE("warning"), 1, 1, 1, func_error},
{ STRING_SIZE_TUPLE("call"), 1, 0, 1, func_call},
{ STRING_SIZE_TUPLE("error"), 0, 1, 1, func_error},
{ STRING_SIZE_TUPLE("warning"), 0, 1, 1, func_error},
{ STRING_SIZE_TUPLE("if"), 2, 3, 0, func_if},
{ STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value},
{ STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval},
#ifdef EXPERIMENTAL
{ STRING_SIZE_TUPLE("eq"), 2, 2, 1, func_eq},
{ STRING_SIZE_TUPLE("not"), 1, 1, 1, func_not},
{ STRING_SIZE_TUPLE("not"), 0, 1, 1, func_not},
#endif
{ 0 }
};
#define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry))
/* These must come after the definition of function_table[]. */
/* These must come after the definition of function_table. */
static char *
expand_builtin_function (o, argc, argv, entry_p)
@@ -1683,11 +1845,18 @@ expand_builtin_function (o, argc, argv, entry_p)
char **argv;
struct function_table_entry *entry_p;
{
if (argc < entry_p->minimum_args)
if (argc < (int)entry_p->minimum_args)
fatal (reading_file,
_("Insufficient number of arguments (%d) to function `%s'"),
argc, entry_p->name);
/* I suppose technically some function could do something with no
arguments, but so far none do, so just test it for all functions here
rather than in each one. We can change it later if necessary. */
if (!argc)
return o;
if (!entry_p->func_ptr)
fatal (reading_file, _("Unimplemented on this platform: function `%s'"),
entry_p->name);
@@ -1717,7 +1886,7 @@ handle_function (op, stringp)
beg = *stringp + 1;
entry_p = lookup_function (function_table, beg);
entry_p = lookup_function (beg);
if (!entry_p)
return 0;
@@ -1748,7 +1917,7 @@ handle_function (op, stringp)
*stringp = end;
/* Get some memory to store the arg pointers. */
argvp = argv = (char **) alloca (sizeof(char *) * (nargs + 2));
argvp = argv = (char **) alloca (sizeof (char *) * (nargs + 2));
/* Chop the string into arguments, then a nul. As soon as we hit
MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the
@@ -1769,9 +1938,7 @@ handle_function (op, stringp)
end = beg + len;
}
p = beg;
nargs = 0;
for (p=beg, nargs=0; p < end; ++argvp)
for (p=beg, nargs=0; p <= end; ++argvp)
{
char *next;
@@ -1819,67 +1986,53 @@ func_call (o, argv, funcname)
{
char *fname;
char *cp;
int flen;
char *body;
int flen;
int i;
const struct function_table_entry *entry_p;
fname = expand_argument (argv[0], NULL);
struct variable *v;
/* There is no way to define a variable with a space in the name, so strip
leading and trailing whitespace as a favor to the user. */
cp = fname;
while (*cp != '\0' && isspace ((unsigned char)*cp))
++cp;
argv[0] = cp;
fname = argv[0];
while (*fname != '\0' && isspace ((unsigned char)*fname))
++fname;
cp += strlen(cp) - 1;
while (cp > argv[0] && isspace ((unsigned char)*cp))
cp = fname + strlen (fname) - 1;
while (cp > fname && isspace ((unsigned char)*cp))
--cp;
cp[1] = '\0';
/* Calling nothing is a no-op */
if (*argv[0] == '\0')
{
free (fname);
return o;
}
if (*fname == '\0')
return o;
/* Are we invoking a builtin function? */
entry_p = lookup_function (function_table, argv[0]);
entry_p = lookup_function (fname);
if (entry_p)
{
char **av;
free (fname);
/* How many arguments do we have? */
for (i=0; argv[i+1]; ++i)
;
/* If we need to expand arguments, do it now. */
if (entry_p->expand_args)
for (av=argv+1; *av; ++av)
*av = expand_argument (*av, NULL);
o = expand_builtin_function (o, i, argv+1, entry_p);
/* What we expanded we must free... */
if (entry_p->expand_args)
for (av=argv+1; *av; ++av)
free (*av);
return o;
return expand_builtin_function (o, i, argv+1, entry_p);
}
/* Not a builtin, so the first argument is the name of a variable to be
expanded and interpreted as a function. Create the variable
reference. */
flen = strlen (argv[0]);
expanded and interpreted as a function. Find it. */
flen = strlen (fname);
body = alloca (flen + 4);
v = lookup_variable (fname, flen);
if (v == 0)
warn_undefined (fname, flen);
if (v == 0 || *v->value == '\0')
return o;
body = (char *) alloca (flen + 4);
body[0] = '$';
body[1] = '(';
memcpy (body + 2, fname, flen);
@@ -1895,16 +2048,29 @@ func_call (o, argv, funcname)
char num[11];
sprintf (num, "%d", i);
define_variable (num, strlen (num), *argv, o_automatic, 1);
define_variable (num, strlen (num), *argv, o_automatic, 0);
}
/* Expand the body in the context of the arguments, adding the result to
the variable buffer. */
v->exp_count = EXP_COUNT_MAX;
o = variable_expand_string (o, body, flen+3);
v->exp_count = 0;
pop_variable_scope ();
free (fname);
return o + strlen(o);
return o + strlen (o);
}
void
hash_init_function_table ()
{
hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2,
function_table_entry_hash_1, function_table_entry_hash_2,
function_table_entry_hash_cmp);
hash_load (&function_table, function_table_init,
FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
}

View File

@@ -40,7 +40,7 @@
NLIST_STRUCT Include nlist.h, not a.out.h, and
the nlist n_name element is a pointer,
not an array.
NLIST_NAME_UNION struct nlist has an n_un member, not n_name.
HAVE_STRUCT_NLIST_N_UN_N_NAME struct nlist has an n_un member, not n_name.
LINUX_LDAV_FILE [__linux__]: File containing load averages.
Specific system predefines this file uses, aside from setting
@@ -99,6 +99,13 @@
extern int errno;
#endif
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#if !HAVE_SETLOCALE
# define setlocale(Category, Locale) /* empty */
#endif
#ifndef HAVE_GETLOADAVG
@@ -192,6 +199,10 @@ extern int errno;
# define tek4300 /* Define by emacs, but not by other users. */
# endif
/* AC_FUNC_GETLOADAVG thinks QNX is SVR4, but it isn't. */
# if defined(__QNX__)
# undef SVR4
# endif
/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */
# ifndef LOAD_AVE_TYPE
@@ -309,67 +320,6 @@ extern int errno;
# define LDAV_CVT(n) (((double) (n)) / FSCALE)
# endif
/* VAX C can't handle multi-line #ifs, or lines longer that 256 characters. */
# ifndef NLIST_STRUCT
# ifdef MORE_BSD
# define NLIST_STRUCT
# endif
# ifdef sun
# define NLIST_STRUCT
# endif
# ifdef decstation
# define NLIST_STRUCT
# endif
# ifdef hpux
# define NLIST_STRUCT
# endif
# if defined (_SEQUENT_) || defined (sequent)
# define NLIST_STRUCT
# endif
# ifdef sgi
# define NLIST_STRUCT
# endif
# ifdef SVR4
# define NLIST_STRUCT
# endif
# ifdef sony_news
# define NLIST_STRUCT
# endif
# ifdef OSF_ALPHA
# define NLIST_STRUCT
# endif
# if defined (ardent) && defined (titan)
# define NLIST_STRUCT
# endif
# ifdef tek4300
# define NLIST_STRUCT
# endif
# ifdef butterfly
# define NLIST_STRUCT
# endif
# if defined(alliant) && defined(i860) /* Alliant FX/2800 */
# define NLIST_STRUCT
# endif
# ifdef _AIX
# define NLIST_STRUCT
# endif
# endif /* defined (NLIST_STRUCT) */
# if defined(sgi) || (defined(mips) && !defined(BSD))
# define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
@@ -413,11 +363,11 @@ extern int errno;
# ifndef VMS
# ifndef __linux__
# ifndef NLIST_STRUCT
# include <a.out.h>
# else /* NLIST_STRUCT */
# ifdef HAVE_NLIST_H
# include <nlist.h>
# endif /* NLIST_STRUCT */
# else
# include <a.out.h>
# endif
# ifdef SUNOS_5
# include <fcntl.h>
@@ -646,8 +596,11 @@ getloadavg (loadavg, nelem)
if (count <= 0)
return -1;
/* The following sscanf must use the C locale. */
setlocale (LC_NUMERIC, "C");
count = sscanf (ldavgbuf, "%lf %lf %lf",
&load_ave[0], &load_ave[1], &load_ave[2]);
setlocale (LC_NUMERIC, "");
if (count < 1)
return -1;
@@ -923,13 +876,13 @@ getloadavg (loadavg, nelem)
strcpy (nl[0].n_name, LDAV_SYMBOL);
strcpy (nl[1].n_name, "");
# else /* NLIST_STRUCT */
# ifdef NLIST_NAME_UNION
# ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
nl[0].n_un.n_name = LDAV_SYMBOL;
nl[1].n_un.n_name = 0;
# else /* not NLIST_NAME_UNION */
# else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
nl[0].n_name = LDAV_SYMBOL;
nl[1].n_name = 0;
# endif /* not NLIST_NAME_UNION */
# endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
# endif /* NLIST_STRUCT */
# ifndef SUNOS_5
@@ -1038,6 +991,8 @@ getloadavg (loadavg, nelem)
#endif /* ! HAVE_GETLOADAVG */
#ifdef TEST
#include "make.h"
int
main (argc, argv)
int argc;

2605
gettext.c

File diff suppressed because it is too large Load Diff

202
gettext.h
View File

@@ -1,177 +1,59 @@
/* Begin of libgettext.h */
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
/* Message catalogs for internationalization.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published
by the Free Software Foundation; either version 2, 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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
/* Because on some systems (e.g. Solaris) we sometimes have to include
the systems libintl.h as well as this file we have more complex
include protection above. But the systems header might perhaps also
define _LIBINTL_H and therefore we have to protect the definition here. */
#if !defined _LIBINTL_H || !defined _LIBGETTEXT_H
#ifndef _LIBINTL_H
# define _LIBINTL_H 1
#endif
#define _LIBGETTEXT_H 1
/* We define an additional symbol to signal that we use the GNU
implementation of gettext. */
#define __USE_GNU_GETTEXT 1
#include <sys/types.h>
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PARAMS
# if __STDC__ || defined __cplusplus
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#ifndef NULL
# if !defined __cplusplus || defined __GNUC__
# define NULL ((void *) 0)
# else
# define NULL (0)
# endif
#endif
#if !HAVE_LC_MESSAGES
/* This value determines the behaviour of the gettext() and dgettext()
function. But some system does not have this defined. Define it
to a default value. */
# define LC_MESSAGES (-1)
#endif
/* Declarations for gettext-using-catgets interface. Derived from
Jim Meyering's libintl.h. */
struct _msg_ent
{
const char *_msg;
int _msg_number;
};
#if HAVE_CATGETS
/* These two variables are defined in the automatically by po-to-tbl.sed
generated file `cat-id-tbl.c'. */
extern const struct _msg_ent _msg_tbl[];
extern int _msg_tbl_length;
#endif
/* For automatical extraction of messages sometimes no real
translation is needed. Instead the string itself is the result. */
#define gettext_noop(Str) (Str)
/* Look up MSGID in the current default message catalog for the current
LC_MESSAGES locale. If not found, returns MSGID itself (the default
text). */
extern char *gettext PARAMS ((const char *__msgid));
/* static char *gettext__ PARAMS ((const char *__msgid)); */
/* Look up MSGID in the DOMAINNAME message catalog for the current
LC_MESSAGES locale. */
extern char *dgettext PARAMS ((const char *__domainname, const char *__msgid));
/* static char *dgettext__ PARAMS ((const char *__domainname,
const char *__msgid)); */
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
extern char *dcgettext PARAMS ((const char *__domainname, const char *__msgid,
int __category));
extern char *dcgettext__ PARAMS ((const char *__domainname,
const char *__msgid, int __category));
/* Set the current default message catalog to DOMAINNAME.
If DOMAINNAME is null, return the current default.
If DOMAINNAME is "", reset to the default of "messages". */
extern char *textdomain PARAMS ((const char *__domainname));
/* static char *textdomain__ PARAMS ((const char *__domainname)); */
/* Specify that the DOMAINNAME message catalog will be found
in DIRNAME rather than in the system locale data base. */
extern char *bindtextdomain PARAMS ((const char *__domainname,
const char *__dirname));
/* static char *bindtextdomain__ PARAMS ((const char *__domainname,
const char *__dirname)); */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS
/* Solaris 2.3 has the gettext function but dcgettext is missing.
So we omit this optimization for Solaris 2.3. BTW, Solaris 2.4
has dcgettext. */
# if !HAVE_CATGETS && (!HAVE_GETTEXT || HAVE_DCGETTEXT)
# define gettext(Msgid) \
dgettext (NULL, Msgid)
# define dgettext(Domainname, Msgid) \
dcgettext (Domainname, Msgid, LC_MESSAGES)
# if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7
/* This global variable is defined in loadmsgcat.c. We need a sign,
whether a new catalog was loaded, which can be associated with all
translations. */
extern int _nl_msg_cat_cntr;
# define dcgettext(Domainname, Msgid, Category) \
(__extension__ \
({ \
char *__result; \
if (__builtin_constant_p (Msgid)) \
{ \
static char *__translation__; \
static int __catalog_counter__; \
if (! __translation__ || __catalog_counter__ != _nl_msg_cat_cntr) \
{ \
__translation__ = \
dcgettext__ (Domainname, Msgid, Category); \
__catalog_counter__ = _nl_msg_cat_cntr; \
} \
__result = __translation__; \
} \
else \
__result = dcgettext__ (Domainname, Msgid, Category); \
__result; \
}))
# endif
# endif
/* Get declarations of GNU message catalog functions. */
# include <libintl.h>
#else
# define gettext(Msgid) (Msgid)
# define dgettext(Domainname, Msgid) (Msgid)
# define dcgettext(Domainname, Msgid, Category) (Msgid)
# define textdomain(Domainname) ((char *) Domainname)
# define bindtextdomain(Domainname, Dirname) ((char *) Dirname)
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
#endif
#ifdef __cplusplus
}
#endif
/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
The argument, String, should be a literal string. Concatenated strings
and other string expressions won't work.
The macro's expansion is not parenthesized, so that it is suitable as
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
#endif
/* End of libgettext.h */
#endif /* _LIBGETTEXT_H */

View File

@@ -1 +1,2 @@
.deps Makefile.in
Makefile Makefile.in
.deps

View File

@@ -1,3 +1,9 @@
2002-04-22 Paul D. Smith <psmith@gnu.org>
* Makefile.am: Use automake 1.6.
Use new automake condition USE_LOCAL_GLOB to decide whether or not
to build the local GNU glob library or use the system one.
1999-09-12 Paul D. Smith <psmith@gnu.org>
* fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC

View File

@@ -1,10 +1,14 @@
# -*-Makefile-*-, or close enough
AUTOMAKE_OPTIONS = 1.4 foreign
AUTOMAKE_OPTIONS = 1.7 foreign
noinst_LIBRARIES = libglob.a
# Only build the library when the system doesn't already have GNU glob.
if USE_LOCAL_GLOB
noinst_LIBRARIES = libglob.a
endif
libglob_a_SOURCES = glob.c glob.h fnmatch.c fnmatch.h
EXTRA_DIST = COPYING.LIB Makefile.ami SCOPTIONS SMakefile \
configure.bat

View File

@@ -1,396 +0,0 @@
@setfilename gpl.info
@unnumbered GNU GENERAL PUBLIC LICENSE
@center Version 2, June 1991
@display
Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@end display
@unnumberedsec Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software---to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
@iftex
@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@end iftex
@ifinfo
@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@end ifinfo
@enumerate
@item
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The ``Program'', below,
refers to any such program or work, and a ``work based on the Program''
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term ``modification''.) Each licensee is addressed as ``you''.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
@item
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
@item
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
@enumerate a
@item
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
@item
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
@item
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
@end enumerate
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
@item
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
@enumerate a
@item
Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
@item
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
@item
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
@end enumerate
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
@item
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
@item
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
@item
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
@item
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
@item
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
@item
The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and ``any
later version'', you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
@item
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
@iftex
@heading NO WARRANTY
@end iftex
@ifinfo
@center NO WARRANTY
@end ifinfo
@item
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
@item
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
@end enumerate
@iftex
@heading END OF TERMS AND CONDITIONS
@end iftex
@ifinfo
@center END OF TERMS AND CONDITIONS
@end ifinfo
@page
@unnumberedsec How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the ``copyright'' line and a pointer to where the full notice is found.
@smallexample
@var{one line to give the program's name and an idea of what it does.}
Copyright (C) 19@var{yy} @var{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 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
@end smallexample
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
@smallexample
Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
@end smallexample
The hypothetical commands @samp{show w} and @samp{show c} should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than @samp{show w} and
@samp{show c}; they could even be mouse-clicks or menu items---whatever
suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a ``copyright disclaimer'' for the program, if
necessary. Here is a sample; alter the names:
@smallexample
@group
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
@var{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
@end group
@end smallexample
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

369
hash.c Normal file
View File

@@ -0,0 +1,369 @@
/* hash.c -- hash table maintenance
Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "make.h"
#include "hash.h"
#define CALLOC(t, n) ((t *) calloc (sizeof (t), (n)))
#define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))
#define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n)))
#define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n)))
static void hash_rehash __P((struct hash_table* ht));
static unsigned long round_up_2 __P((unsigned long rough));
/* Implement double hashing with open addressing. The table size is
always a power of two. The secondary (`increment') hash function
is forced to return an odd-value, in order to be relatively prime
to the table size. This guarantees that the increment can
potentially hit every slot in the table during collision
resolution. */
void *hash_deleted_item = &hash_deleted_item;
/* Force the table size to be a power of two, possibly rounding up the
given size. */
void
hash_init (ht, size, hash_1, hash_2, hash_cmp)
struct hash_table* ht;
unsigned long size;
hash_func_t hash_1;
hash_func_t hash_2;
hash_cmp_func_t hash_cmp;
{
ht->ht_size = round_up_2 (size);
ht->ht_empty_slots = ht->ht_size;
ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size);
if (ht->ht_vec == 0)
{
fprintf (stderr, _("can't allocate %ld bytes for hash table: memory exhausted"),
ht->ht_size * sizeof(struct token *));
exit (1);
}
ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */
ht->ht_fill = 0;
ht->ht_collisions = 0;
ht->ht_lookups = 0;
ht->ht_rehashes = 0;
ht->ht_hash_1 = hash_1;
ht->ht_hash_2 = hash_2;
ht->ht_compare = hash_cmp;
}
/* Load an array of items into `ht'. */
void
hash_load (ht, item_table, cardinality, size)
struct hash_table* ht;
void *item_table;
unsigned long cardinality;
unsigned long size;
{
char *items = (char *) item_table;
while (cardinality--)
{
hash_insert (ht, items);
items += size;
}
}
/* Returns the address of the table slot matching `key'. If `key' is
not found, return the address of an empty slot suitable for
inserting `key'. The caller is responsible for incrementing
ht_fill on insertion. */
void **
hash_find_slot (ht, key)
struct hash_table* ht;
void const *key;
{
void **slot;
void **deleted_slot = 0;
unsigned int hash_2 = 0;
unsigned int hash_1 = (*ht->ht_hash_1) (key);
ht->ht_lookups++;
for (;;)
{
hash_1 &= (ht->ht_size - 1);
slot = &ht->ht_vec[hash_1];
if (*slot == 0)
return (deleted_slot ? deleted_slot : slot);
if (*slot == hash_deleted_item)
{
if (deleted_slot == 0)
deleted_slot = slot;
}
else
{
if (key == *slot)
return slot;
if ((*ht->ht_compare) (key, *slot) == 0)
return slot;
ht->ht_collisions++;
}
if (!hash_2)
hash_2 = (*ht->ht_hash_2) (key) | 1;
hash_1 += hash_2;
}
}
void *
hash_find_item (ht, key)
struct hash_table* ht;
void const *key;
{
void **slot = hash_find_slot (ht, key);
return ((HASH_VACANT (*slot)) ? 0 : *slot);
}
void *
hash_insert (ht, item)
struct hash_table* ht;
void *item;
{
void **slot = hash_find_slot (ht, item);
void *old_item = slot ? *slot : 0;
hash_insert_at (ht, item, slot);
return ((HASH_VACANT (old_item)) ? 0 : old_item);
}
void *
hash_insert_at (ht, item, slot)
struct hash_table* ht;
void *item;
void const *slot;
{
void *old_item = *(void **) slot;
if (HASH_VACANT (old_item))
{
ht->ht_fill++;
if (old_item == 0)
ht->ht_empty_slots--;
old_item = item;
}
*(void const **) slot = item;
if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity)
{
hash_rehash (ht);
return (void *) hash_find_slot (ht, item);
}
else
return (void *) slot;
}
void *
hash_delete (ht, item)
struct hash_table* ht;
void const *item;
{
void **slot = hash_find_slot (ht, item);
return hash_delete_at (ht, slot);
}
void *
hash_delete_at (ht, slot)
struct hash_table* ht;
void const *slot;
{
void *item = *(void **) slot;
if (!HASH_VACANT (item))
{
*(void const **) slot = hash_deleted_item;
ht->ht_fill--;
return item;
}
else
return 0;
}
void
hash_free_items (ht)
struct hash_table* ht;
{
void **vec = ht->ht_vec;
void **end = &vec[ht->ht_size];
for (; vec < end; vec++)
{
void *item = *vec;
if (!HASH_VACANT (item))
free (item);
*vec = 0;
}
ht->ht_fill = 0;
ht->ht_empty_slots = ht->ht_size;
}
void
hash_delete_items (ht)
struct hash_table* ht;
{
void **vec = ht->ht_vec;
void **end = &vec[ht->ht_size];
for (; vec < end; vec++)
*vec = 0;
ht->ht_fill = 0;
ht->ht_collisions = 0;
ht->ht_lookups = 0;
ht->ht_rehashes = 0;
ht->ht_empty_slots = ht->ht_size;
}
void
hash_free (ht, free_items)
struct hash_table* ht;
int free_items;
{
if (free_items)
hash_free_items (ht);
else
{
ht->ht_fill = 0;
ht->ht_empty_slots = ht->ht_size;
}
free (ht->ht_vec);
ht->ht_vec = 0;
ht->ht_capacity = 0;
}
void
hash_map (ht, map)
struct hash_table *ht;
hash_map_func_t map;
{
void **slot;
void **end = &ht->ht_vec[ht->ht_size];
for (slot = ht->ht_vec; slot < end; slot++)
{
if (!HASH_VACANT (*slot))
(*map) (*slot);
}
}
void
hash_map_arg (ht, map, arg)
struct hash_table *ht;
hash_map_arg_func_t map;
void *arg;
{
void **slot;
void **end = &ht->ht_vec[ht->ht_size];
for (slot = ht->ht_vec; slot < end; slot++)
{
if (!HASH_VACANT (*slot))
(*map) (*slot, arg);
}
}
/* Double the size of the hash table in the event of overflow... */
static void
hash_rehash (ht)
struct hash_table* ht;
{
unsigned long old_ht_size = ht->ht_size;
void **old_vec = ht->ht_vec;
void **ovp;
if (ht->ht_fill >= ht->ht_capacity)
{
ht->ht_size *= 2;
ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4);
}
ht->ht_rehashes++;
ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size);
for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++)
{
if (! HASH_VACANT (*ovp))
{
void **slot = hash_find_slot (ht, *ovp);
*slot = *ovp;
}
}
ht->ht_empty_slots = ht->ht_size - ht->ht_fill;
free (old_vec);
}
void
hash_print_stats (ht, out_FILE)
struct hash_table *ht;
FILE *out_FILE;
{
/* GKM FIXME: honor NO_FLOAT */
fprintf (out_FILE, _("Load=%ld/%ld=%.0f%%, "), ht->ht_fill, ht->ht_size,
100.0 * (double) ht->ht_fill / (double) ht->ht_size);
fprintf (out_FILE, _("Rehash=%d, "), ht->ht_rehashes);
fprintf (out_FILE, _("Collisions=%ld/%ld=%.0f%%"), ht->ht_collisions, ht->ht_lookups,
(ht->ht_lookups
? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups)
: 0));
}
/* Dump all items into a NULL-terminated vector. Use the
user-supplied vector, or malloc one. */
void **
hash_dump (ht, vector_0, compare)
struct hash_table *ht;
void **vector_0;
qsort_cmp_t compare;
{
void **vector;
void **slot;
void **end = &ht->ht_vec[ht->ht_size];
if (vector_0 == 0)
vector_0 = MALLOC (void *, ht->ht_fill + 1);
vector = vector_0;
for (slot = ht->ht_vec; slot < end; slot++)
if (!HASH_VACANT (*slot))
*vector++ = *slot;
*vector = 0;
if (compare)
qsort (vector_0, ht->ht_fill, sizeof (void *), compare);
return vector_0;
}
/* Round a given number up to the nearest power of 2. */
static unsigned long
round_up_2 (n)
unsigned long n;
{
n |= (n >> 1);
n |= (n >> 2);
n |= (n >> 4);
n |= (n >> 8);
n |= (n >> 16);
#if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295
/* We only need this on systems where unsigned long is >32 bits. */
n |= (n >> 32);
#endif
return n + 1;
}

233
hash.h Normal file
View File

@@ -0,0 +1,233 @@
/* hash.h -- decls for hash table
Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef _hash_h_
#define _hash_h_
#include <stdio.h>
#include <ctype.h>
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
# if !defined __GLIBC__ || !defined __P
# undef __P
# define __P(protos) protos
# endif
#else /* Not C++ or ANSI C. */
# undef __P
# define __P(protos) ()
/* We can get away without defining `const' here only because in this file
it is used only inside the prototype for `fnmatch', which is elided in
non-ANSI C where `const' is problematical. */
#endif /* C++ or ANSI C. */
typedef unsigned long (*hash_func_t) __P((void const *key));
typedef int (*hash_cmp_func_t) __P((void const *x, void const *y));
typedef void (*hash_map_func_t) __P((void const *item));
typedef void (*hash_map_arg_func_t) __P((void const *item, void *arg));
struct hash_table
{
void **ht_vec;
unsigned long ht_size; /* total number of slots (power of 2) */
unsigned long ht_capacity; /* usable slots, limited by loading-factor */
unsigned long ht_fill; /* items in table */
unsigned long ht_empty_slots; /* empty slots not including deleted slots */
unsigned long ht_collisions; /* # of failed calls to comparison function */
unsigned long ht_lookups; /* # of queries */
unsigned int ht_rehashes; /* # of times we've expanded table */
hash_func_t ht_hash_1; /* primary hash function */
hash_func_t ht_hash_2; /* secondary hash function */
hash_cmp_func_t ht_compare; /* comparison function */
};
typedef int (*qsort_cmp_t) __P((void const *, void const *));
void hash_init __P((struct hash_table *ht, unsigned long size,
hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp));
void hash_load __P((struct hash_table *ht, void *item_table,
unsigned long cardinality, unsigned long size));
void **hash_find_slot __P((struct hash_table *ht, void const *key));
void *hash_find_item __P((struct hash_table *ht, void const *key));
void *hash_insert __P((struct hash_table *ht, void *item));
void *hash_insert_at __P((struct hash_table *ht, void *item, void const *slot));
void *hash_delete __P((struct hash_table *ht, void const *item));
void *hash_delete_at __P((struct hash_table *ht, void const *slot));
void hash_delete_items __P((struct hash_table *ht));
void hash_free_items __P((struct hash_table *ht));
void hash_free __P((struct hash_table *ht, int free_items));
void hash_map __P((struct hash_table *ht, hash_map_func_t map));
void hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg));
void hash_print_stats __P((struct hash_table *ht, FILE *out_FILE));
void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare));
extern void *hash_deleted_item;
#define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item)
/* hash and comparison macros for case-sensitive string keys. */
#define STRING_HASH_1(KEY, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
while (*++_key_) \
(RESULT) += (*_key_ << (_key_[1] & 0xf)); \
} while (0)
#define return_STRING_HASH_1(KEY) do { \
unsigned long _result_ = 0; \
STRING_HASH_1 ((KEY), _result_); \
return _result_; \
} while (0)
#define STRING_HASH_2(KEY, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
while (*++_key_) \
(RESULT) += (*_key_ << (_key_[1] & 0x7)); \
} while (0)
#define return_STRING_HASH_2(KEY) do { \
unsigned long _result_ = 0; \
STRING_HASH_2 ((KEY), _result_); \
return _result_; \
} while (0)
#define STRING_COMPARE(X, Y, RESULT) do { \
RESULT = strcmp ((X), (Y)); \
} while (0)
#define return_STRING_COMPARE(X, Y) do { \
return strcmp ((X), (Y)); \
} while (0)
#define STRING_N_HASH_1(KEY, N, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
int _n_ = (N); \
if (_n_) \
while (--_n_ && *++_key_) \
(RESULT) += (*_key_ << (_key_[1] & 0xf)); \
(RESULT) += *++_key_; \
} while (0)
#define return_STRING_N_HASH_1(KEY, N) do { \
unsigned long _result_ = 0; \
STRING_N_HASH_1 ((KEY), (N), _result_); \
return _result_; \
} while (0)
#define STRING_N_HASH_2(KEY, N, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
int _n_ = (N); \
if (_n_) \
while (--_n_ && *++_key_) \
(RESULT) += (*_key_ << (_key_[1] & 0x7)); \
(RESULT) += *++_key_; \
} while (0)
#define return_STRING_N_HASH_2(KEY, N) do { \
unsigned long _result_ = 0; \
STRING_N_HASH_2 ((KEY), (N), _result_); \
return _result_; \
} while (0)
#define STRING_N_COMPARE(X, Y, N, RESULT) do { \
RESULT = strncmp ((X), (Y), (N)); \
} while (0)
#define return_STRING_N_COMPARE(X, Y, N) do { \
return strncmp ((X), (Y), (N)); \
} while (0)
#ifdef HAVE_CASE_INSENSITIVE_FS
/* hash and comparison macros for case-insensitive string _key_s. */
#define ISTRING_HASH_1(KEY, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
while (*++_key_) \
(RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \
} while (0)
#define return_ISTRING_HASH_1(KEY) do { \
unsigned long _result_ = 0; \
ISTRING_HASH_1 ((KEY), _result_); \
return _result_; \
} while (0)
#define ISTRING_HASH_2(KEY, RESULT) do { \
unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \
while (*++_key_) \
(RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \
} while (0)
#define return_ISTRING_HASH_2(KEY) do { \
unsigned long _result_ = 0; \
ISTRING_HASH_2 ((KEY), _result_); \
return _result_; \
} while (0)
#define ISTRING_COMPARE(X, Y, RESULT) do { \
RESULT = strcmpi ((X), (Y)); \
} while (0)
#define return_ISTRING_COMPARE(X, Y) do { \
return strcmpi ((X), (Y)); \
} while (0)
#else
#define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT))
#define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY)
#define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT))
#define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY)
#define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT))
#define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y))
#endif
/* hash and comparison macros for integer _key_s. */
#define INTEGER_HASH_1(KEY, RESULT) do { \
(RESULT) += ((unsigned long)(KEY)); \
} while (0)
#define return_INTEGER_HASH_1(KEY) do { \
unsigned long _result_ = 0; \
INTEGER_HASH_1 ((KEY), _result_); \
return _result_; \
} while (0)
#define INTEGER_HASH_2(KEY, RESULT) do { \
(RESULT) += ~((unsigned long)(KEY)); \
} while (0)
#define return_INTEGER_HASH_2(KEY) do { \
unsigned long _result_ = 0; \
INTEGER_HASH_2 ((KEY), _result_); \
return _result_; \
} while (0)
#define INTEGER_COMPARE(X, Y, RESULT) do { \
(RESULT) = X - Y; \
} while (0)
#define return_INTEGER_COMPARE(X, Y) do { \
int _result_; \
INTEGER_COMPARE (X, Y, _result_); \
return _result_; \
} while (0)
/* hash and comparison macros for address keys. */
#define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT))
#define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT))
#define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT))
#define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3)
#define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3)
#define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y))
#endif /* not _hash_h_ */

View File

@@ -1,3 +0,0 @@
*.mo *.pot
Makefile.in Makefile

View File

@@ -1,75 +0,0 @@
# Makefile for PO directories.
# François Pinard <pinard@iro.umontreal.ca>, 1998.
AUTOMAKE_OPTIONS = gnits
localedir = $(prefix)/share/locale
ALL_POFILES = @ALL_POFILES@
ALL_MOFILES = @ALL_MOFILES@
MOFILES = @MOFILES@
EXTRA_DIST = $(PACKAGE).pot $(ALL_POFILES) $(ALL_MOFILES)
MSGFMT = msgfmt
MSGMERGE = msgmerge
XGETTEXT = xgettext
SUFFIXES = .po .pox .mo
.po.pox:
$(MAKE) $(PACKAGE).pot
$(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
.po.mo:
file=$(srcdir)/`echo $* | sed 's,.*/,,'`.mo \
&& rm -f $$file && $(MSGFMT) -o $$file $<
all: $(ALL_MOFILES)
install-data-local: $(MOFILES)
if USE_NLS
files='$(MOFILES)'; \
for file in $$files; do \
base=`basename $$file`; \
langdir=$(DESTDIR)$(localedir)/`echo $$base | sed 's/\.mo$$//'`/LC_MESSAGES; \
$(mkinstalldirs) $$langdir; \
echo " $(INSTALL_DATA) $(srcdir)/$$file $$langdir/$(PACKAGE).mo"; \
$(INSTALL_DATA) $(srcdir)/$$file $$langdir/$(PACKAGE).mo; \
done
endif
uninstall-local:
if USE_NLS
files='$(MOFILES)'; \
for file in $$files; do \
base=`basename $$file`; \
langdir=$(DESTDIR)$(localedir)/`echo $$base | sed 's/\.mo$$//'`/LC_MESSAGES; \
rm -f $$langdir/$(PACKAGE).mo; \
done
endif
MAINTAINER_CLEAN = $(PACKAGE).pot $(MOFILES)
$(srcdir)/$(PACKAGE).pot: $(top_srcdir)/stamp-pot
$(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
--add-comments --keyword=_ --keyword=N_ `cat $(top_srcdir)/stamp-pot`
test ! -f $(PACKAGE).po || ( rm -f $@ && mv $(PACKAGE).po $@ )
update-po: Makefile
$(MAKE) $(PACKAGE).pot
files='$(ALL_MOFILES)'; \
for file in $$files; do \
base=`basename $$file`; \
lang=`echo $$base | sed 's/\.mo$$//'`; \
mv $(srcdir)/$$lang.po $(srcdir)/$$lang.old.po; \
echo "$$lang:"; \
cd $(srcdir) \
&& if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
rm -f $$lang.old.po; \
else \
echo "msgmerge for $$file failed!"; \
rm -f $$lang.po; \
mv $$lang.old.po $$lang.po; \
fi; \
done

1772
i18n/de.po

File diff suppressed because it is too large Load Diff

1932
i18n/es.po

File diff suppressed because it is too large Load Diff

1445
i18n/fr.po

File diff suppressed because it is too large Load Diff

1445
i18n/ko.po

File diff suppressed because it is too large Load Diff

1441
i18n/nl.po

File diff suppressed because it is too large Load Diff

1467
i18n/pl.po

File diff suppressed because it is too large Load Diff

1424
i18n/ru.po

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* Implicit rule searching for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,97 Free Software Foundation, Inc.
Copyright (C) 1988,89,90,91,92,93,94,97,2000 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -100,7 +100,7 @@ pattern_search (file, archive, depth, recursions)
/* List of dependencies found recursively. */
struct file **intermediate_files
= (struct file **) alloca (max_pattern_deps * sizeof (struct file *));
= (struct file **) xmalloc (max_pattern_deps * sizeof (struct file *));
/* List of the patterns used to find intermediate files. */
char **intermediate_patterns
@@ -117,11 +117,12 @@ pattern_search (file, archive, depth, recursions)
/* The start and length of the stem of FILENAME for the current rule. */
register char *stem = 0;
register unsigned int stemlen = 0;
register unsigned int fullstemlen = 0;
/* Buffer in which we store all the rules that are possibly applicable. */
struct rule **tryrules
= (struct rule **) alloca (num_pattern_rules * max_pattern_targets
* sizeof (struct rule *));
= (struct rule **) xmalloc (num_pattern_rules * max_pattern_targets
* sizeof (struct rule *));
/* Number of valid elements in TRYRULES. */
unsigned int nrules;
@@ -167,7 +168,7 @@ pattern_search (file, archive, depth, recursions)
lastslash = strrchr (filename, ':');
#else
lastslash = strrchr (filename, '/');
#if defined(__MSDOS__) || defined(WINDOWS32)
#ifdef HAVE_DOS_PATHS
/* Handle backslashes (possibly mixed with forward slashes)
and the case of "d:file". */
{
@@ -398,8 +399,8 @@ pattern_search (file, archive, depth, recursions)
directory (the one gotten by prepending FILENAME's directory),
so it might actually exist. */
if ((!dep->changed || check_lastslash)
&& (lookup_file (p) != 0 || file_exists_p (p)))
if (lookup_file (p) != 0
|| ((!dep->changed || check_lastslash) && file_exists_p (p)))
{
found_files[deps_found++] = xstrdup (p);
continue;
@@ -494,7 +495,7 @@ pattern_search (file, archive, depth, recursions)
/* RULE is nil if the loop went all the way
through the list and everything failed. */
if (rule == 0)
return 0;
goto done;
foundrule = i;
@@ -542,10 +543,10 @@ pattern_search (file, archive, depth, recursions)
dep->name = 0;
dep->file->tried_implicit |= dep->changed;
}
num_intermediates++;
}
dep = (struct dep *) xmalloc (sizeof (struct dep));
dep->ignore_mtime = 0;
s = found_files[deps_found];
if (recursions == 0)
{
@@ -582,18 +583,23 @@ pattern_search (file, archive, depth, recursions)
}
if (!checked_lastslash[foundrule])
/* Always allocate new storage, since STEM might be
on the stack for an intermediate file. */
file->stem = savestring (stem, stemlen);
{
/* Always allocate new storage, since STEM might be
on the stack for an intermediate file. */
file->stem = savestring (stem, stemlen);
fullstemlen = stemlen;
}
else
{
int dirlen = (lastslash + 1) - filename;
/* We want to prepend the directory from
the original FILENAME onto the stem. */
file->stem = (char *) xmalloc (((lastslash + 1) - filename)
+ stemlen + 1);
bcopy (filename, file->stem, (lastslash + 1) - filename);
bcopy (stem, file->stem + ((lastslash + 1) - filename), stemlen);
file->stem[((lastslash + 1) - filename) + stemlen] = '\0';
fullstemlen = dirlen + stemlen;
file->stem = (char *) xmalloc (fullstemlen + 1);
bcopy (filename, file->stem, dirlen);
bcopy (stem, file->stem + dirlen, stemlen);
file->stem[fullstemlen] = '\0';
}
file->cmds = rule->cmds;
@@ -606,12 +612,14 @@ pattern_search (file, archive, depth, recursions)
if (i != matches[foundrule])
{
struct dep *new = (struct dep *) xmalloc (sizeof (struct dep));
new->name = p = (char *) xmalloc (rule->lens[i] + stemlen + 1);
/* GKM FIMXE: handle '|' here too */
new->ignore_mtime = 0;
new->name = p = (char *) xmalloc (rule->lens[i] + fullstemlen + 1);
bcopy (rule->targets[i], p,
rule->suffixes[i] - rule->targets[i] - 1);
p += rule->suffixes[i] - rule->targets[i] - 1;
bcopy (stem, p, stemlen);
p += stemlen;
bcopy (file->stem, p, fullstemlen);
p += fullstemlen;
bcopy (rule->suffixes[i], p,
rule->lens[i] - (rule->suffixes[i] - rule->targets[i]) + 1);
new->file = enter_file (new->name);
@@ -619,6 +627,9 @@ pattern_search (file, archive, depth, recursions)
file->also_make = new;
}
done:
free (intermediate_files);
free (tryrules);
return 1;
return rule != 0;
}

243
job.c
View File

@@ -17,9 +17,10 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "make.h"
#include <assert.h>
#include "make.h"
#include "job.h"
#include "debug.h"
#include "filedef.h"
@@ -74,7 +75,6 @@ static int amiga_batch_file;
#endif /* Amiga. */
#ifdef VMS
# include <time.h>
# ifndef __GNUC__
# include <processes.h>
# endif
@@ -295,10 +295,10 @@ vms_redirect (desc, fname, ibuf)
extern char *vmsify ();
ibuf++;
while (isspace (*ibuf))
while (isspace ((unsigned char)*ibuf))
ibuf++;
fptr = ibuf;
while (*ibuf && !isspace (*ibuf))
while (*ibuf && !isspace ((unsigned char)*ibuf))
ibuf++;
*ibuf = 0;
if (strcmp (fptr, "/dev/null") != 0)
@@ -436,8 +436,8 @@ reap_children (block, err)
we'll keep reaping children. */
while ((children != 0 || shell_function_pid != 0) &&
(block || REAP_MORE))
while ((children != 0 || shell_function_pid != 0)
&& (block || REAP_MORE))
{
int remote = 0;
register int pid;
@@ -500,9 +500,6 @@ reap_children (block, err)
{
/* A remote status command failed miserably. Punt. */
remote_status_lose:
if (EINTR_SET)
continue;
pfatal_with_name ("remote_status");
}
else
@@ -511,7 +508,6 @@ reap_children (block, err)
#if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32)
if (any_local)
{
local_wait:
#ifdef VMS
vmsWaitForChildren (&status);
pid = c->pid;
@@ -529,10 +525,6 @@ reap_children (block, err)
if (pid < 0)
{
/* EINTR? Try again. */
if (EINTR_SET)
goto local_wait;
/* The wait*() failed miserably. Punt. */
pfatal_with_name ("wait");
}
@@ -737,7 +729,7 @@ reap_children (block, err)
update_status to its also_make files. */
notice_finished_file (c->file);
DB (DB_JOBS, (_("Removing child 0x%08lx PID %ld %s from chain.\n"),
DB (DB_JOBS, (_("Removing child 0x%08lx PID %ld%s from chain.\n"),
(unsigned long int) c, (long) c->pid,
c->remote ? _(" (remote)") : ""));
@@ -792,9 +784,8 @@ free_child (child)
/* Write a job token back to the pipe. */
while (write (job_fds[1], &token, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("write jobserver"));
if (write (job_fds[1], &token, 1) != 1)
pfatal_with_name (_("write jobserver"));
DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"),
(unsigned long int) child, child->file->name));
@@ -848,6 +839,26 @@ unblock_sigs ()
}
#endif
#ifdef MAKE_JOBSERVER
/* Set the child handler action flags to FLAGS. */
static void
set_child_handler_action_flags (flags)
int flags;
{
struct sigaction sa;
bzero ((char *) &sa, sizeof sa);
sa.sa_handler = child_handler;
sa.sa_flags = flags;
#if defined SIGCHLD
sigaction (SIGCHLD, &sa, NULL);
#endif
#if defined SIGCLD && SIGCLD != SIGCHLD
sigaction (SIGCLD, &sa, NULL);
#endif
}
#endif
/* Start a job to run the commands specified in CHILD.
CHILD is updated to reflect the commands and ID of the child process.
@@ -890,27 +901,19 @@ start_job_command (child)
flags |= COMMANDS_RECURSE;
else if (*p == '-')
child->noerror = 1;
else if (!isblank (*p))
else if (!isblank ((unsigned char)*p))
break;
++p;
}
/* Update the file's command flags with any new ones we found. */
child->file->cmds->lines_flags[child->command_line - 1] |= flags;
/* If -q was given, just say that updating `failed'. The exit status of
1 tells the user that -q is saying `something to do'; the exit status
for a random error is 2. */
if (question_flag && !(flags & COMMANDS_RECURSE))
{
child->file->update_status = 1;
notice_finished_file (child->file);
return;
}
/* There may be some preceding whitespace left if there
was nothing but a backslash on the first line. */
p = next_token (p);
/* Update the file's command flags with any new ones we found. We only
keep the COMMANDS_RECURSE setting. Even this isn't 100% correct; we are
now marking more commands recursive than should be in the case of
multiline define/endef scripts where only one line is marked "+". In
order to really fix this, we'll have to keep a lines_flags for every
actual line, after expansion. */
child->file->cmds->lines_flags[child->command_line - 1]
|= flags & COMMANDS_RECURSE;
/* Figure out an argument list from this command line. */
@@ -930,13 +933,31 @@ start_job_command (child)
}
}
/* If -q was given, say that updating `failed' if there was any text on the
command line, or `succeeded' otherwise. The exit status of 1 tells the
user that -q is saying `something to do'; the exit status for a random
error is 2. */
if (argv != 0 && question_flag && !(flags & COMMANDS_RECURSE))
{
#ifndef VMS
free (argv[0]);
free ((char *) argv);
#endif
child->file->update_status = 1;
notice_finished_file (child->file);
return;
}
if (touch_flag && !(flags & COMMANDS_RECURSE))
{
/* Go on to the next command. It might be the recursive one.
We construct ARGV only to find the end of the command line. */
#ifndef VMS
free (argv[0]);
free ((char *) argv);
if (argv)
{
free (argv[0]);
free ((char *) argv);
}
#endif
argv = 0;
}
@@ -968,8 +989,20 @@ start_job_command (child)
message (0, (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag))
? "%s" : (char *) 0, p);
/* Tell update_goal_chain that a command has been started on behalf of
this target. It is important that this happens here and not in
reap_children (where we used to do it), because reap_children might be
reaping children from a different target. We want this increment to
guaranteedly indicate that a command was started for the dependency
chain (i.e., update_file recursion chain) we are processing. */
++commands_started;
/* Optimize an empty command. People use this for timestamp rules,
so avoid forking a useless shell. */
so avoid forking a useless shell. Do this after we increment
commands_started so make still treats this special case as if it
performed some action (makes a difference as to what messages are
printed, etc. */
#if !defined(VMS) && !defined(_AMIGA)
if (
@@ -989,15 +1022,6 @@ start_job_command (child)
}
#endif /* !VMS && !_AMIGA */
/* Tell update_goal_chain that a command has been started on behalf of
this target. It is important that this happens here and not in
reap_children (where we used to do it), because reap_children might be
reaping children from a different target. We want this increment to
guaranteedly indicate that a command was started for the dependency
chain (i.e., update_file recursion chain) we are processing. */
++commands_started;
/* If -n was given, recurse to get the next line in the sequence. */
if (just_print_flag && !(flags & COMMANDS_RECURSE))
@@ -1411,7 +1435,8 @@ new_job (file)
/* Discard any preceding whitespace that has
already been written to the output. */
while (out > ref && isblank (out[-1]))
while (out > ref
&& isblank ((unsigned char)out[-1]))
--out;
/* Replace it all with a single space. */
@@ -1475,34 +1500,73 @@ new_job (file)
while (1)
{
char token;
int got_token;
int saved_errno;
DB (DB_JOBS, ("Need a job token; we %shave children\n",
children ? "" : "don't "));
/* If we don't already have a job started, use our "free" token. */
if (!children)
break;
/* Read a token. As long as there's no token available we'll block.
If we get a SIGCHLD we'll return with EINTR. If one happened
before we got here we'll return immediately with EBADF because
the signal handler closes the dup'd file descriptor. */
We enable interruptible system calls before the read(2) so that if
we get a SIGCHLD while we're waiting, we'll return with EINTR and
we can process the death(s) and return tokens to the free pool.
if (read (job_rfd, &token, 1) == 1)
Once we return from the read, we immediately reinstate restartable
system calls. This allows us to not worry about checking for
EINTR on all the other system calls in the program.
There is one other twist: there is a span between the time
reap_children() does its last check for dead children and the time
the read(2) call is entered, below, where if a child dies we won't
notice. This is extremely serious as it could cause us to
deadlock, given the right set of events.
To avoid this, we do the following: before we reap_children(), we
dup(2) the read FD on the jobserver pipe. The read(2) call below
uses that new FD. In the signal handler, we close that FD. That
way, if a child dies during the section mentioned above, the
read(2) will be invoked with an invalid FD and will return
immediately with EBADF. */
/* Make sure we have a dup'd FD. */
if (job_rfd < 0)
{
DB (DB_JOBS, ("Duplicate the job FD\n"));
job_rfd = dup (job_fds[0]);
}
/* Reap anything that's currently waiting. */
reap_children (0, 0);
/* If our "free" token has become available, use it. */
if (!children)
break;
/* Set interruptible system calls, and read() for a job token. */
set_child_handler_action_flags (0);
got_token = read (job_rfd, &token, 1);
saved_errno = errno;
set_child_handler_action_flags (SA_RESTART);
/* If we got one, we're done here. */
if (got_token == 1)
{
DB (DB_JOBS, (_("Obtained token for child 0x%08lx (%s).\n"),
(unsigned long int) c, c->file->name));
break;
}
/* If the error _wasn't_ expected (EINTR or EBADF), punt. Otherwise,
go back and reap_children(), and try again. */
errno = saved_errno;
if (errno != EINTR && errno != EBADF)
pfatal_with_name (_("read jobs pipe"));
/* Re-dup the read side of the pipe, so the signal handler can
notify us if we miss a child. */
if (job_rfd < 0)
job_rfd = dup (job_fds[0]);
/* Something's done. We don't want to block for a whole child,
just reap whatever's there. */
reap_children (0, 0);
if (errno == EBADF)
DB (DB_JOBS, ("Read returned EBADF.\n"));
}
#endif
@@ -1572,6 +1636,8 @@ load_too_high ()
}
user_access ();
DB (DB_JOBS, ("Current system load = %f (max requested = %f)\n",
load, max_load_average));
return load >= max_load_average;
#endif
}
@@ -1795,7 +1861,7 @@ child_execute_job (argv, child)
int status;
char *cmd = alloca (strlen (argv) + 512), *p, *q;
char ifile[256], ofile[256], efile[256];
char comname[50];
char *comname = 0;
char procname[100];
/* Parse IO redirection. */
@@ -1806,7 +1872,7 @@ child_execute_job (argv, child)
DB (DB_JOBS, ("child_execute_job (%s)\n", argv));
while (isspace (*argv))
while (isspace ((unsigned char)*argv))
argv++;
if (*argv == 0)
@@ -1831,9 +1897,9 @@ child_execute_job (argv, child)
p++;
if (*p == '\n')
p++;
if (isspace (*p))
if (isspace ((unsigned char)*p))
{
do { p++; } while (isspace (*p));
do { p++; } while (isspace ((unsigned char)*p));
p--;
}
*q = *p;
@@ -1944,8 +2010,6 @@ child_execute_job (argv, child)
is desired. Forcing commands with newlines into DCLs allows to
store search lists on user mode logicals. */
comname[0] = '\0';
if (strlen (cmd) > MAXCMDLEN
|| (have_redirection != 0)
|| (have_newline != 0))
@@ -1962,12 +2026,9 @@ child_execute_job (argv, child)
return 0;
}
strcpy (comname, "sys$scratch:CMDXXXXXX.COM");
(void) mktemp (comname);
outfile = fopen (comname, "w");
outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM");
if (outfile == 0)
pfatal_with_name (comname);
pfatal_with_name (_("fopen (temporary file)"));
if (ifile[0])
{
@@ -1998,11 +2059,11 @@ child_execute_job (argv, child)
case '\n':
/* At a newline, skip any whitespace around a leading $
from the command and issue exactly one $ into the DCL. */
while (isspace (*p))
while (isspace ((unsigned char)*p))
p++;
if (*p == '$')
p++;
while (isspace (*p))
while (isspace ((unsigned char)*p))
p++;
fwrite (p, 1, q - p, outfile);
fputc ('$', outfile);
@@ -2150,7 +2211,7 @@ child_execute_job (argv, child)
fflush (stdout);
}
if (comname[0] && !ISDB (DB_JOBS))
if (comname && !ISDB (DB_JOBS))
unlink (comname);
return (status & 1);
@@ -2402,9 +2463,9 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls",
"copy", "ctty", "date", "del", "dir", "echo",
"erase", "exit", "for", "goto", "if", "if", "md",
"mkdir", "path", "pause", "prompt", "rem", "ren",
"rename", "set", "shift", "time", "type",
"ver", "verify", "vol", ":", 0 };
"mkdir", "path", "pause", "prompt", "rd", "rem",
"ren", "rename", "rmdir", "set", "shift", "time",
"type", "ver", "verify", "vol", ":", 0 };
static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^";
static char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login",
"logout", "set", "umask", "wait", "while", "for",
@@ -2417,8 +2478,8 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
0 };
char* sh_chars;
char** sh_cmds;
#else /* WINDOWS32 */
static char sh_chars[] = "#;\"*?[]&|<>(){}$`^";
#else /* must be UNIX-ish */
static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~";
static char *sh_cmds[] = { "cd", "eval", "exec", "exit", "login",
"logout", "set", "umask", "wait", "while", "for",
"case", "if", ":", ".", "break", "continue",
@@ -2449,7 +2510,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
*restp = NULL;
/* Make sure not to bother processing an empty line. */
while (isblank (*line))
while (isblank ((unsigned char)*line))
++line;
if (*line == '\0')
return 0;
@@ -2465,10 +2526,10 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
slow_flag = strcmp((s1 ? s1 : ""), (s2 ? s2 : ""));
if (s1);
free(s1);
if (s2);
free(s2);
if (s1)
free (s1);
if (s2)
free (s2);
}
if (slow_flag)
goto slow;
@@ -2606,7 +2667,7 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
}
else if (p[1] != '\0')
{
#if defined(__MSDOS__) || defined(WINDOWS32)
#ifdef HAVE_DOS_PATHS
/* Only remove backslashes before characters special
to Unixy shells. All other backslashes are copied
verbatim, since they are probably DOS-style
@@ -2630,8 +2691,8 @@ construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr)
&& (strchr (sh_chars_sh, p[1]) == 0))
/* back up one notch, to copy the backslash */
--p;
#endif /* HAVE_DOS_PATHS */
#endif /* __MSDOS__ || WINDOWS32 */
/* Copy and skip the following char. */
*ap++ = *++p;
}
@@ -2967,12 +3028,12 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
for (;;)
{
while ((*cptr != 0)
&& (isspace (*cptr)))
&& (isspace ((unsigned char)*cptr)))
cptr++;
if (*cptr == 0)
break;
while ((*cptr != 0)
&& (!isspace(*cptr)))
&& (!isspace((unsigned char)*cptr)))
cptr++;
argc++;
}
@@ -2986,14 +3047,14 @@ construct_command_argv (line, restp, file, batch_filename_ptr)
for (;;)
{
while ((*cptr != 0)
&& (isspace (*cptr)))
&& (isspace ((unsigned char)*cptr)))
cptr++;
if (*cptr == 0)
break;
DB (DB_JOBS, ("argv[%d] = [%s]\n", argc, cptr));
argv[argc++] = cptr;
while ((*cptr != 0)
&& (!isspace(*cptr)))
&& (!isspace((unsigned char)*cptr)))
cptr++;
if (*cptr != 0)
*cptr++ = 0;

653
main.c
View File

@@ -1,5 +1,6 @@
/* Argument parsing and main program of GNU Make.
Copyright (C) 1988,89,90,91,94,95,96,97,98,99 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -68,7 +69,6 @@ extern void exit PARAMS ((int)) __attribute__ ((noreturn));
# endif
extern double atof ();
#endif
extern char *mktemp ();
static void print_data_base PARAMS ((void));
static void print_version PARAMS ((void));
@@ -76,6 +76,8 @@ static void decode_switches PARAMS ((int argc, char **argv, int env));
static void decode_env_switches PARAMS ((char *envar, unsigned int len));
static void define_makeflags PARAMS ((int all, int makefile));
static char *quote_for_env PARAMS ((char *out, char *in));
static void initialize_global_hash_tables PARAMS ((void));
/* The structure that describes an accepted command switch. */
@@ -103,9 +105,6 @@ struct command_switch
char *default_value;/* Pointer to default value. */
char *long_name; /* Long option name. */
char *argdesc; /* Descriptive word for argument. */
char *description; /* Description for usage message. */
/* 0 means internal; don't display help. */
};
/* True if C is a switch value that corresponds to a short option. */
@@ -250,113 +249,142 @@ static int print_usage_flag = 0;
for each reference to an undefined variable. */
int warn_undefined_variables_flag;
/* If nonzero, always build all targets, regardless of whether
they appear out of date or not. */
int always_make_flag = 0;
/* The usage output. We write it this way to make life easier for the
translators, especially those trying to translate to right-to-left
languages like Hebrew. */
static const char *const usage[] =
{
N_("Options:\n"),
N_("\
-b, -m Ignored for compatibility.\n"),
N_("\
-B, --always-make Unconditionally make all targets.\n"),
N_("\
-C DIRECTORY, --directory=DIRECTORY\n\
Change to DIRECTORY before doing anything.\n"),
N_("\
-d Print lots of debugging information.\n"),
N_("\
--debug[=FLAGS] Print various types of debugging information.\n"),
N_("\
-e, --environment-overrides\n\
Environment variables override makefiles.\n"),
N_("\
-f FILE, --file=FILE, --makefile=FILE\n\
Read FILE as a makefile.\n"),
N_("\
-h, --help Print this message and exit.\n"),
N_("\
-i, --ignore-errors Ignore errors from commands.\n"),
N_("\
-I DIRECTORY, --include-dir=DIRECTORY\n\
Search DIRECTORY for included makefiles.\n"),
N_("\
-j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n"),
N_("\
-k, --keep-going Keep going when some targets can't be made.\n"),
N_("\
-l [N], --load-average[=N], --max-load[=N]\n\
Don't start multiple jobs unless load is below N.\n"),
N_("\
-n, --just-print, --dry-run, --recon\n\
Don't actually run any commands; just print them.\n"),
N_("\
-o FILE, --old-file=FILE, --assume-old=FILE\n\
Consider FILE to be very old and don't remake it.\n"),
N_("\
-p, --print-data-base Print make's internal database.\n"),
N_("\
-q, --question Run no commands; exit status says if up to date.\n"),
N_("\
-r, --no-builtin-rules Disable the built-in implicit rules.\n"),
N_("\
-R, --no-builtin-variables Disable the built-in variable settings.\n"),
N_("\
-s, --silent, --quiet Don't echo commands.\n"),
N_("\
-S, --no-keep-going, --stop\n\
Turns off -k.\n"),
N_("\
-t, --touch Touch targets instead of remaking them.\n"),
N_("\
-v, --version Print the version number of make and exit.\n"),
N_("\
-w, --print-directory Print the current directory.\n"),
N_("\
--no-print-directory Turn off -w, even if it was turned on implicitly.\n"),
N_("\
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\n\
Consider FILE to be infinitely new.\n"),
N_("\
--warn-undefined-variables Warn when an undefined variable is referenced.\n"),
NULL
};
/* The table of command switches. */
static const struct command_switch switches[] =
{
{ 'b', ignore, 0, 0, 0, 0, 0, 0,
0, 0,
N_("Ignored for compatibility") },
{ 'C', string, (char *) &directories, 0, 0, 0, 0, 0,
"directory", N_("DIRECTORY"),
N_("Change to DIRECTORY before doing anything") },
{ 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0,
0, 0,
N_("Print lots of debugging information") },
{ CHAR_MAX+1, string, (char *) &db_flags, 1, 1, 0,
"basic", 0,
"debug", N_("FLAGS"),
N_("Print various types of debugging information") },
{ 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'B', flag, (char *) &always_make_flag, 1, 1, 0, 0, 0, "always-make" },
{ 'C', string, (char *) &directories, 0, 0, 0, 0, 0, "directory" },
{ 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0, 0 },
{ CHAR_MAX+1, string, (char *) &db_flags, 1, 1, 0, "basic", 0, "debug" },
#ifdef WINDOWS32
{ 'D', flag, (char *) &suspend_flag, 1, 1, 0, 0, 0,
"suspend-for-debug", 0,
N_("Suspend process to allow a debugger to attach") },
{ 'D', flag, (char *) &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" },
#endif
{ 'e', flag, (char *) &env_overrides, 1, 1, 0, 0, 0,
"environment-overrides", 0,
N_("Environment variables override makefiles") },
{ 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0,
"file", N_("FILE"),
N_("Read FILE as a makefile") },
{ 'h', flag, (char *) &print_usage_flag, 0, 0, 0, 0, 0,
"help", 0,
N_("Print this message and exit") },
"environment-overrides", },
{ 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0, "file" },
{ 'h', flag, (char *) &print_usage_flag, 0, 0, 0, 0, 0, "help" },
{ 'i', flag, (char *) &ignore_errors_flag, 1, 1, 0, 0, 0,
"ignore-errors", 0,
N_("Ignore errors from commands") },
"ignore-errors" },
{ 'I', string, (char *) &include_directories, 1, 1, 0, 0, 0,
"include-dir", N_("DIRECTORY"),
N_("Search DIRECTORY for included makefiles") },
{ 'j',
positive_int, (char *) &job_slots, 1, 1, 0,
(char *) &inf_jobs, (char *) &default_job_slots,
"jobs", "N",
N_("Allow N jobs at once; infinite jobs with no arg") },
"include-dir" },
{ 'j', positive_int, (char *) &job_slots, 1, 1, 0, (char *) &inf_jobs,
(char *) &default_job_slots, "jobs" },
{ CHAR_MAX+2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0,
"jobserver-fds", 0,
0 },
{ 'k', flag, (char *) &keep_going_flag, 1, 1, 0,
0, (char *) &default_keep_going_flag,
"keep-going", 0,
N_("Keep going when some targets can't be made") },
"jobserver-fds" },
{ 'k', flag, (char *) &keep_going_flag, 1, 1, 0, 0,
(char *) &default_keep_going_flag, "keep-going" },
#ifndef NO_FLOAT
{ 'l', floating, (char *) &max_load_average, 1, 1, 0,
(char *) &default_load_average, (char *) &default_load_average,
"load-average", "N",
N_("Don't start multiple jobs unless load is below N") },
"load-average" },
#else
{ 'l', positive_int, (char *) &max_load_average, 1, 1, 0,
(char *) &default_load_average, (char *) &default_load_average,
"load-average", "N",
N_("Don't start multiple jobs unless load is below N") },
"load-average" },
#endif
{ 'm', ignore, 0, 0, 0, 0, 0, 0,
0, 0,
"-b" },
{ 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0,
"just-print", 0,
N_("Don't actually run any commands; just print them") },
{ 'o', string, (char *) &old_files, 0, 0, 0, 0, 0,
"old-file", N_("FILE"),
N_("Consider FILE to be very old and don't remake it") },
{ 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
{ 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
{ 'o', string, (char *) &old_files, 0, 0, 0, 0, 0, "old-file" },
{ 'p', flag, (char *) &print_data_base_flag, 1, 1, 0, 0, 0,
"print-data-base", 0,
N_("Print make's internal database") },
{ 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0,
"question", 0,
N_("Run no commands; exit status says if up to date") },
"print-data-base" },
{ 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0, "question" },
{ 'r', flag, (char *) &no_builtin_rules_flag, 1, 1, 0, 0, 0,
"no-builtin-rules", 0,
N_("Disable the built-in implicit rules") },
"no-builtin-rules" },
{ 'R', flag, (char *) &no_builtin_variables_flag, 1, 1, 0, 0, 0,
"no-builtin-variables", 0,
N_("Disable the built-in variable settings") },
{ 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0,
"silent", 0,
N_("Don't echo commands") },
{ 'S', flag_off, (char *) &keep_going_flag, 1, 1, 0,
0, (char *) &default_keep_going_flag,
"no-keep-going", 0,
N_("Turns off -k") },
{ 't', flag, (char *) &touch_flag, 1, 1, 1, 0, 0,
"touch", 0,
N_("Touch targets instead of remaking them") },
{ 'v', flag, (char *) &print_version_flag, 1, 1, 0, 0, 0,
"version", 0,
N_("Print the version number of make and exit") },
"no-builtin-variables" },
{ 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0, "silent" },
{ 'S', flag_off, (char *) &keep_going_flag, 1, 1, 0, 0,
(char *) &default_keep_going_flag, "no-keep-going" },
{ 't', flag, (char *) &touch_flag, 1, 1, 1, 0, 0, "touch" },
{ 'v', flag, (char *) &print_version_flag, 1, 1, 0, 0, 0, "version" },
{ 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0,
"print-directory", 0,
N_("Print the current directory") },
"print-directory" },
{ CHAR_MAX+3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
"no-print-directory", 0,
N_("Turn off -w, even if it was turned on implicitly") },
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0,
"what-if", N_("FILE"),
N_("Consider FILE to be infinitely new") },
"no-print-directory" },
{ 'W', string, (char *) &new_files, 0, 0, 0, 0, 0, "what-if" },
{ CHAR_MAX+4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
"warn-undefined-variables", 0,
N_("Warn when an undefined variable is referenced") },
"warn-undefined-variables" },
{ '\0', }
};
@@ -375,12 +403,6 @@ static struct option long_option_aliases[] =
{ "makefile", required_argument, 0, 'f' },
};
/* The usage message prints the descriptions of options starting in
this column. Make sure it leaves enough room for the longest
description to fit in less than 80 characters. */
#define DESCRIPTION_COLUMN 30
/* List of goal targets. */
static struct dep *goals, *lastgoal;
@@ -444,11 +466,43 @@ int clock_skew_detected;
#ifdef POSIX
sigset_t fatal_signal_set;
#else
#ifdef HAVE_SIGSETMASK
# ifdef HAVE_SIGSETMASK
int fatal_signal_mask;
# endif
#endif
#if !defined HAVE_BSD_SIGNAL && !defined bsd_signal
# if !defined HAVE_SIGACTION
# define bsd_signal signal
# else
typedef RETSIGTYPE (*bsd_signal_ret_t) ();
static bsd_signal_ret_t
bsd_signal (sig, func)
int sig;
bsd_signal_ret_t func;
{
struct sigaction act, oact;
act.sa_handler = func;
act.sa_flags = SA_RESTART;
sigemptyset (&act.sa_mask);
sigaddset (&act.sa_mask, sig);
if (sigaction (sig, &act, &oact) != 0)
return SIG_ERR;
return oact.sa_handler;
}
# endif
#endif
static void
initialize_global_hash_tables ()
{
init_hash_global_variable_set ();
init_hash_files ();
hash_init_directories ();
hash_init_function_table ();
}
static struct file *
enter_command_line_file (name)
char *name;
@@ -728,6 +782,51 @@ msdos_return_to_initial_directory ()
}
#endif
extern char *mktemp ();
extern int mkstemp ();
FILE *
open_tmpfile(name, template)
char **name;
const char *template;
{
int fd;
#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
# define TEMPLATE_LEN strlen (template)
#else
# define TEMPLATE_LEN L_tmpnam
#endif
*name = xmalloc (TEMPLATE_LEN + 1);
strcpy (*name, template);
#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
/* It's safest to use mkstemp(), if we can. */
fd = mkstemp (*name);
if (fd == -1)
return 0;
return fdopen (fd, "w");
#else
# ifdef HAVE_MKTEMP
(void) mktemp (*name);
# else
(void) tmpnam (*name);
# endif
# ifdef HAVE_FDOPEN
/* Can't use mkstemp(), but guard against a race condition. */
fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1)
return 0;
return fdopen (fd, "w");
# else
/* Not secure, but what can we do? */
return fopen (*name, "w");
# endif
#endif
}
#ifndef _AMIGA
int
main (argc, argv, envp)
@@ -775,13 +874,6 @@ int main (int argc, char ** argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#if !defined (HAVE_STRSIGNAL) && !defined (HAVE_SYS_SIGLIST)
{
extern void signame_init ();
signame_init ();
}
#endif
#ifdef POSIX
sigemptyset (&fatal_signal_set);
#define ADD_SIG(sig) sigaddset (&fatal_signal_set, sig)
@@ -795,8 +887,8 @@ int main (int argc, char ** argv)
#endif
#define FATAL_SIG(sig) \
if (signal ((sig), fatal_error_signal) == SIG_IGN) \
(void) signal ((sig), SIG_IGN); \
if (bsd_signal (sig, fatal_error_signal) == SIG_IGN) \
bsd_signal (sig, SIG_IGN); \
else \
ADD_SIG (sig);
@@ -809,6 +901,13 @@ int main (int argc, char ** argv)
FATAL_SIG (SIGINT);
FATAL_SIG (SIGTERM);
#ifdef __MSDOS__
/* Windows 9X delivers FP exceptions in child programs to their
parent! We don't want Make to die when a child divides by zero,
so we work around that lossage by catching SIGFPE. */
FATAL_SIG (SIGFPE);
#endif
#ifdef SIGDANGER
FATAL_SIG (SIGDANGER);
#endif
@@ -828,24 +927,24 @@ int main (int argc, char ** argv)
#ifdef HAVE_WAIT_NOHANG
# if defined SIGCHLD
(void) signal (SIGCHLD, SIG_DFL);
(void) bsd_signal (SIGCHLD, SIG_DFL);
# endif
# if defined SIGCLD && SIGCLD != SIGCHLD
(void) signal (SIGCLD, SIG_DFL);
(void) bsd_signal (SIGCLD, SIG_DFL);
# endif
#endif
/* Make sure stdout is line-buffered. */
#ifdef HAVE_SETLINEBUF
setlinebuf (stdout);
#else
#ifndef SETVBUF_REVERSED
setvbuf (stdout, (char *) 0, _IOLBF, BUFSIZ);
#else /* setvbuf not reversed. */
/* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
#ifdef HAVE_SETVBUF
# ifdef SETVBUF_REVERSED
setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
#endif /* setvbuf reversed. */
# else /* setvbuf not reversed. */
/* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
setvbuf (stdout, (char *) 0, _IOLBF, BUFSIZ);
# endif /* setvbuf reversed. */
#elif HAVE_SETLINEBUF
setlinebuf (stdout);
#endif /* setlinebuf missing. */
/* Figure out where this program lives. */
@@ -884,6 +983,8 @@ int main (int argc, char ** argv)
/* Set up to access user data (files). */
user_access ();
initialize_global_hash_tables ();
/* Figure out where we are. */
#ifdef WINDOWS32
@@ -907,6 +1008,10 @@ int main (int argc, char ** argv)
atexit (msdos_return_to_initial_directory);
#endif
/* Initialize the special variables. */
define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1;
/* define_variable (".TARGETS", 8, "", o_default, 0); */
/* Read in variables from the environment. It is important that this be
done before $(MAKE) is figured out so its definitions will not be
from the environment. */
@@ -1150,8 +1255,8 @@ int main (int argc, char ** argv)
#endif /* WINDOWS32 */
/* Figure out the level of recursion. */
{
struct variable *v = lookup_variable ("MAKELEVEL", 9);
if (v != 0 && *v->value != '\0' && *v->value != '-')
struct variable *v = lookup_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH);
if (v != 0 && v->value[0] != '\0' && v->value[0] != '-')
makelevel = (unsigned int) atoi (v->value);
else
makelevel = 0;
@@ -1211,25 +1316,47 @@ int main (int argc, char ** argv)
and thus re-read the makefiles, we read standard input
into a temporary file and read from that. */
FILE *outfile;
/* Make a unique filename. */
#ifdef HAVE_MKTEMP
#ifdef VMS
static char name[] = "sys$scratch:GmXXXXXX";
#else
static char name[] = "/tmp/GmXXXXXX";
#endif
(void) mktemp (name);
#else
static char name[L_tmpnam];
(void) tmpnam (name);
#endif
char *template, *tmpdir;
if (stdin_nm)
fatal (NILF, _("Makefile from standard input specified twice."));
outfile = fopen (name, "w");
#ifdef VMS
# define DEFAULT_TMPDIR "sys$scratch:"
#else
# ifdef P_tmpdir
# define DEFAULT_TMPDIR P_tmpdir
# else
# define DEFAULT_TMPDIR "/tmp"
# endif
#endif
#define DEFAULT_TMPFILE "GmXXXXXX"
if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0')
#if defined __MSDOS__ || defined(WINDOWS32)
/* These are also used commonly on these platforms. */
&& ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0')
&& ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0')
#endif
)
tmpdir = DEFAULT_TMPDIR;
template = (char *) alloca (strlen (tmpdir)
+ sizeof (DEFAULT_TMPFILE) + 1);
strcpy (template, tmpdir);
#ifdef HAVE_DOS_PATHS
if (strchr ("/\\", template[strlen (template) - 1]) == NULL)
strcat (template, "/");
#else
# ifndef VMS
if (template[strlen (template) - 1] != '/')
strcat (template, "/");
# endif /* !VMS */
#endif /* !HAVE_DOS_PATHS */
strcat (template, DEFAULT_TMPFILE);
outfile = open_tmpfile (&stdin_nm, template);
if (outfile == 0)
pfatal_with_name (_("fopen (temporary file)"));
while (!feof (stdin))
@@ -1243,16 +1370,9 @@ int main (int argc, char ** argv)
/* Replace the name that read_all_makefiles will
see with the name of the temporary file. */
{
char *temp;
/* SGI compiler requires alloca's result be assigned simply. */
temp = (char *) alloca (sizeof (name));
bcopy (name, temp, sizeof (name));
makefiles->list[i] = temp;
}
makefiles->list[i] = xstrdup (stdin_nm);
/* Make sure the temporary file will not be remade. */
stdin_nm = savestring (name, sizeof (name) -1);
f = enter_file (stdin_nm);
f->updated = 1;
f->update_status = 0;
@@ -1279,34 +1399,18 @@ int main (int argc, char ** argv)
If none of these are true, we don't need a signal handler at all. */
{
extern RETSIGTYPE child_handler PARAMS ((int sig));
# if defined HAVE_SIGACTION
struct sigaction sa;
bzero ((char *)&sa, sizeof (struct sigaction));
sa.sa_handler = child_handler;
# if defined SA_INTERRUPT
/* This is supposed to be the default, but what the heck... */
sa.sa_flags = SA_INTERRUPT;
# endif
# define HANDLESIG(s) sigaction (s, &sa, NULL)
# else
# define HANDLESIG(s) signal (s, child_handler)
# endif
/* OK, now actually install the handlers. */
# if defined SIGCHLD
(void) HANDLESIG (SIGCHLD);
bsd_signal (SIGCHLD, child_handler);
# endif
# if defined SIGCLD && SIGCLD != SIGCHLD
(void) HANDLESIG (SIGCLD);
bsd_signal (SIGCLD, child_handler);
# endif
}
#endif
/* Let the user send us SIGUSR1 to toggle the -d flag during the run. */
#ifdef SIGUSR1
(void) signal (SIGUSR1, debug_signal_handler);
bsd_signal (SIGUSR1, debug_signal_handler);
#endif
/* Define the initial list of suffixes for old-style rules. */
@@ -1461,9 +1565,8 @@ int main (int argc, char ** argv)
want job_slots to be 0 to indicate we're using the jobserver. */
while (--job_slots)
while (write (job_fds[1], &c, 1) != 1)
if (!EINTR_SET)
pfatal_with_name (_("init jobserver pipe"));
if (write (job_fds[1], &c, 1) != 1)
pfatal_with_name (_("init jobserver pipe"));
/* Fill in the jobserver_fds struct for our children. */
@@ -1509,7 +1612,7 @@ int main (int argc, char ** argv)
build_vpath_lists ();
/* Mark files given with -o flags as very old (00:00:01.00 Jan 1, 1970)
/* Mark files given with -o flags as very old
and as having been updated already, and files given with -W flags as
brand new (time-stamp as far as possible into the future). */
@@ -1517,7 +1620,7 @@ int main (int argc, char ** argv)
for (p = old_files->list; *p != 0; ++p)
{
f = enter_command_line_file (*p);
f->last_mtime = f->mtime_before_update = (FILE_TIMESTAMP) 1;
f->last_mtime = f->mtime_before_update = OLD_MTIME;
f->updated = 1;
f->update_status = 0;
f->command_state = cs_finished;
@@ -1607,10 +1710,11 @@ int main (int argc, char ** argv)
switch (update_goal_chain (read_makefiles, 1))
{
case 1:
default:
#define BOGUS_UPDATE_STATUS 0
assert (BOGUS_UPDATE_STATUS);
break;
/* The only way this can happen is if the user specified -q and asked
* for one of the makefiles to be remade as a target on the command
* line. Since we're not actually updating anything with -q we can
* treat this as "did nothing".
*/
case -1:
/* Did nothing. */
@@ -1650,7 +1754,7 @@ int main (int argc, char ** argv)
error (NILF, _("Failed to remake makefile `%s'."),
d->file->name);
mtime = file_mtime_no_search (d->file);
any_remade |= (mtime != (FILE_TIMESTAMP) -1
any_remade |= (mtime != NONEXISTENT_MTIME
&& mtime != makefile_mtimes[i]);
}
}
@@ -1741,7 +1845,8 @@ int main (int argc, char ** argv)
#ifndef _AMIGA
for (p = environ; *p != 0; ++p)
if (strneq (*p, "MAKELEVEL=", 10))
if ((*p)[MAKELEVEL_LENGTH] == '='
&& strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH))
{
/* The SGI compiler apparently can't understand
the concept of storing the result of a function
@@ -1749,7 +1854,7 @@ int main (int argc, char ** argv)
char *sgi_loses;
sgi_loses = (char *) alloca (40);
*p = sgi_loses;
sprintf (*p, "MAKELEVEL=%u", makelevel);
sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel);
break;
}
#else /* AMIGA */
@@ -1757,12 +1862,12 @@ int main (int argc, char ** argv)
char buffer[256];
int len;
len = GetVar ("MAKELEVEL", buffer, sizeof (buffer), GVF_GLOBAL_ONLY);
len = GetVar (MAKELEVEL_NAME, buffer, sizeof (buffer), GVF_GLOBAL_ONLY);
if (len != -1)
{
sprintf (buffer, "%u", makelevel);
SetVar ("MAKELEVEL", buffer, -1, GVF_GLOBAL_ONLY);
SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
}
}
#endif
@@ -1790,6 +1895,11 @@ int main (int argc, char ** argv)
exit (0);
#endif
/* NOTREACHED */
default:
#define BOGUS_UPDATE_STATUS 0
assert (BOGUS_UPDATE_STATUS);
break;
}
db_level = orig_db_level;
@@ -1814,6 +1924,7 @@ int main (int argc, char ** argv)
goals = (struct dep *) xmalloc (sizeof (struct dep));
goals->next = 0;
goals->name = 0;
goals->ignore_mtime = 0;
goals->file = default_goal_file;
}
}
@@ -1838,16 +1949,16 @@ int main (int argc, char ** argv)
/* Nothing happened. */
case 0:
/* Updated successfully. */
status = EXIT_SUCCESS;
status = MAKE_SUCCESS;
break;
case 1:
/* We are under -q and would run some commands. */
status = MAKE_TROUBLE;
break;
case 2:
/* Updating failed. POSIX.2 specifies exit status >1 for this;
but in VMS, there is only success and failure. */
status = EXIT_FAILURE ? 2 : EXIT_FAILURE;
break;
case 1:
/* We are under -q and would run some commands. */
status = EXIT_FAILURE;
status = MAKE_FAILURE;
break;
default:
abort ();
@@ -1971,6 +2082,7 @@ handle_non_switch_argument (arg, env)
}
lastgoal->name = 0;
lastgoal->file = f;
lastgoal->ignore_mtime = 0;
{
/* Add this target name to the MAKECMDGOALS variable. */
@@ -2003,7 +2115,8 @@ static void
print_usage (bad)
int bad;
{
register const struct command_switch *cs;
extern char *make_host;
const char *const *cpp;
FILE *usageto;
if (print_version_flag)
@@ -2013,88 +2126,16 @@ print_usage (bad)
fprintf (usageto, _("Usage: %s [options] [target] ...\n"), program);
fputs (_("Options:\n"), usageto);
for (cs = switches; cs->c != '\0'; ++cs)
{
char buf[1024], shortarg[50], longarg[50], *p;
for (cpp = usage; *cpp; ++cpp)
fputs (_(*cpp), usageto);
if (!cs->description || cs->description[0] == '-')
continue;
if (!remote_description || *remote_description == '\0')
fprintf (usageto, _("\nThis program built for %s\n"), make_host);
else
fprintf (usageto, _("\nThis program built for %s (%s)\n"),
make_host, remote_description);
switch (long_options[cs - switches].has_arg)
{
case no_argument:
shortarg[0] = longarg[0] = '\0';
break;
case required_argument:
sprintf (longarg, "=%s", gettext (cs->argdesc));
sprintf (shortarg, " %s", gettext (cs->argdesc));
break;
case optional_argument:
sprintf (longarg, "[=%s]", gettext (cs->argdesc));
sprintf (shortarg, " [%s]", gettext (cs->argdesc));
break;
}
p = buf;
if (short_option (cs->c))
{
sprintf (buf, " -%c%s", cs->c, shortarg);
p += strlen (p);
}
if (cs->long_name != 0)
{
unsigned int i;
sprintf (p, "%s--%s%s",
!short_option (cs->c) ? " " : ", ",
cs->long_name, longarg);
p += strlen (p);
for (i = 0; i < (sizeof (long_option_aliases) /
sizeof (long_option_aliases[0]));
++i)
if (long_option_aliases[i].val == cs->c)
{
sprintf (p, ", --%s%s",
long_option_aliases[i].name, longarg);
p += strlen (p);
}
}
{
const struct command_switch *ncs = cs;
while ((++ncs)->c != '\0')
if (ncs->description
&& ncs->description[0] == '-'
&& ncs->description[1] == cs->c)
{
/* This is another switch that does the same
one as the one we are processing. We want
to list them all together on one line. */
sprintf (p, ", -%c%s", ncs->c, shortarg);
p += strlen (p);
if (ncs->long_name != 0)
{
sprintf (p, ", --%s%s", ncs->long_name, longarg);
p += strlen (p);
}
}
}
if (p - buf > DESCRIPTION_COLUMN - 2)
/* The list of option names is too long to fit on the same
line with the description, leaving at least two spaces.
Print it on its own line instead. */
{
fprintf (usageto, "%s\n", buf);
buf[0] = '\0';
}
fprintf (usageto, "%*s%s.\n",
- DESCRIPTION_COLUMN,
buf, gettext (cs->description));
}
fprintf (usageto, _("\nReport bugs to <bug-make@gnu.org>.\n"));
fprintf (usageto, _("Report bugs to <bug-make@gnu.org>\n"));
}
/* Decode switches from ARGC and ARGV.
@@ -2190,9 +2231,16 @@ decode_switches (argc, argv, env)
break;
case positive_int:
if (optarg == 0 && argc > optind
&& ISDIGIT (argv[optind][0]))
optarg = argv[optind++];
/* See if we have an option argument; if we do require that
it's all digits, not something like "10foo". */
if (optarg == 0 && argc > optind)
{
const char *cp;
for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp)
;
if (cp[0] == '\0')
optarg = argv[optind++];
}
if (!doit)
break;
@@ -2200,11 +2248,16 @@ decode_switches (argc, argv, env)
if (optarg != 0)
{
int i = atoi (optarg);
if (i < 1)
const char *cp;
/* Yes, I realize we're repeating this in some cases. */
for (cp = optarg; ISDIGIT (cp[0]); ++cp)
;
if (i < 1 || cp[0] != '\0')
{
if (doit)
error (NILF, _("the `-%c' option requires a positive integral argument"),
cs->c);
error (NILF, _("the `-%c' option requires a positive integral argument"),
cs->c);
bad = 1;
}
else
@@ -2296,14 +2349,14 @@ decode_env_switches (envar, len)
{
if (*value == '\\' && value[1] != '\0')
++value; /* Skip the backslash. */
else if (isblank (*value))
else if (isblank ((unsigned char)*value))
{
/* End of the word. */
*p++ = '\0';
argv[++argc] = p;
do
++value;
while (isblank (*value));
while (isblank ((unsigned char)*value));
continue;
}
*p++ = *value++;
@@ -2336,7 +2389,7 @@ quote_for_env (out, in)
{
if (*in == '$')
*out++ = '$';
else if (isblank (*in) || *in == '\\')
else if (isblank ((unsigned char)*in) || *in == '\\')
*out++ = '\\';
*out++ = *in++;
}
@@ -2614,7 +2667,6 @@ define_makeflags (all, makefile)
static void
print_version ()
{
extern char *make_host;
static int printed_version = 0;
char *precede = print_data_base_flag ? "# " : "";
@@ -2623,20 +2675,19 @@ print_version ()
/* Do it only once. */
return;
printf ("%sGNU Make version %s", precede, version_string);
if (remote_description != 0 && *remote_description != '\0')
printf ("-%s", remote_description);
/* Print this untranslated. The coding standards recommend translating the
(C) to the copyright symbol, but this string is going to change every
year, and none of the rest of it should be translated (including the
word "Copyright", so it hardly seems worth it. */
printf (_(", by Richard Stallman and Roland McGrath.\n\
%sBuilt for %s\n\
%sCopyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99\n\
%s\tFree Software Foundation, Inc.\n\
%sThis is free software; see the source for copying conditions.\n\
printf ("%sGNU Make %s\n\
%sCopyright (C) 2002 Free Software Foundation, Inc.\n",
precede, version_string, precede);
printf (_("%sThis is free software; see the source for copying conditions.\n\
%sThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
%sPARTICULAR PURPOSE.\n\n\
%sReport bugs to <bug-make@gnu.org>.\n\n"),
precede, make_host,
precede, precede, precede, precede, precede, precede);
%sPARTICULAR PURPOSE.\n"),
precede, precede, precede);
printed_version = 1;
@@ -2683,7 +2734,7 @@ die (status)
print_version ();
/* Wait for children to die. */
for (err = status != 0; job_slots_used > 0; err = 0)
for (err = (status != 0); job_slots_used > 0; err = 0)
reap_children (1, err);
/* Let the remote job module clean up its state. */
@@ -2717,7 +2768,6 @@ log_working_directory (entering)
int entering;
{
static int entered = 0;
char *msg = entering ? _("Entering") : _("Leaving");
/* Print nothing without the flag. Don't print the entering message
again if we already have. Don't print the leaving message if we
@@ -2730,13 +2780,34 @@ log_working_directory (entering)
if (print_data_base_flag)
fputs ("# ", stdout);
if (makelevel == 0)
printf ("%s: %s ", program, msg);
else
printf ("%s[%u]: %s ", program, makelevel, msg);
/* Use entire sentences to give the translators a fighting chance. */
if (starting_directory == 0)
puts (_("an unknown directory"));
if (makelevel == 0)
if (starting_directory == 0)
if (entering)
printf (_("%s: Entering an unknown directory"), program);
else
printf (_("%s: Leaving an unknown directory"), program);
else
if (entering)
printf (_("%s: Entering directory `%s'\n"),
program, starting_directory);
else
printf (_("%s: Leaving directory `%s'\n"),
program, starting_directory);
else
printf (_("directory `%s'\n"), starting_directory);
if (starting_directory == 0)
if (entering)
printf (_("%s[%u]: Entering an unknown directory"),
program, makelevel);
else
printf (_("%s[%u]: Leaving an unknown directory"),
program, makelevel);
else
if (entering)
printf (_("%s[%u]: Entering directory `%s'\n"),
program, makelevel, starting_directory);
else
printf (_("%s[%u]: Leaving directory `%s'\n"),
program, makelevel, starting_directory);
}

View File

@@ -12,6 +12,8 @@ TEMPLATES = README README.DOS README.W32 \
config.ami configh.dos config.h.W32 config.h-vms
MTEMPLATES = Makefile.DOS SMakefile
all-am: $(TEMPLATES) $(MTEMPLATES) build.sh.in
# We need this to ensure that README and build.sh.in are created on time to
# avoid errors by automake.
#
@@ -57,35 +59,169 @@ build.sh.in: build.template Makefile
$< > $@
chmod a-w+x $@
# Use automake to build a dependency list file, for "foreign" makefiles like
# Makefile.DOS.
#
.dep_segment: Makefile.am maintMakefile $(DEP_FILES)
$(AUTOMAKE) --generate-deps --build-dir=. --srcdir-name=.
# We clean everything here. The GNU standards for makefile conventions say
# you shouldn't remove configure, etc., but this makefile is only available
# in a full development distribution, so they'll only be removed then.
# Automake used to have a --generate-deps flag, but it's gone now, so we have
# to do it ourselves.
#
# And _I_ want them to be removed ;)
.dep_segment: Makefile.am maintMakefile $(DEP_FILES)
cat $(DEP_FILES) \
| sed -e '/^[^:]*\.[ch] *:/d' \
-e 's, /usr/[^ ]*,,g' \
-e 's, $(srcdir)/, ,g' \
-e '/^ \\$$/d' \
> $@
# Get rid of everything "else".
#
maintFILES = configure aclocal.m4 config.h.in Makefile.in stamp-h.in
MAINTAINERCLEANFILES = $(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \
CVS-CLEAN-FILES += $(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \
missing build.sh.in .dep_segment
# Put the alpha distribution files up for anonymous FTP.
#
ALPHA := ~ftp/gnu
TARFILE := $(distdir).tar.gz
# This rule tries to clean the tree right down to how it looks when you do a
# virgin CVS checkout.
.PHONY: alpha
alpha: $(ALPHA) $(TARFILE)
@rm -f $(ALPHA)/$(TARFILE)
cp -p $(TARFILE) $(ALPHA)
.PHONY: cvs-clean
cvs-clean: maintainer-clean
-rm -f *~
-rm -f config/*~ config/Makefile.in config/[a-z]*
-rm -f po/*~ po/Makefile.in.in po/Rules-quot po/[a-z]*
-rm -f doc/*~ doc/Makefile.in doc/fdl.texi doc/make-stds.texi \
doc/texinfo.tex
-rm -f glob/*~ glob/Makefile.in
-rm -f ABOUT-NLS $(CVS-CLEAN-FILES)
# This is needed because normal builds with GCC don't compile alloca.c, so
# alloca.P doesn't get built :-/.
# ----------------------------------------------------------------------
#
.deps/alloca.P: alloca.c
$(COMPILE) -M -o $@ $<
# The sections below were stolen from the Makefile.maint used by fileutils,
# sh-utils, textutils, CPPI, Bison, and Autoconf.
## ---------------- ##
## Updating files. ##
## ---------------- ##
WGET = wget --passive-ftp --non-verbose
ftp-gnu = ftp://ftp.gnu.org/gnu
move_if_change = if test -r $(target) && cmp -s $(target).t $(target); then \
echo $(target) is unchanged; rm -f $(target).t; \
else \
mv $(target).t $(target); \
fi
# ------------------- #
# Updating PO files. #
# ------------------- #
po_repo = http://www.iro.umontreal.ca/contrib/po/maint/$(PACKAGE)
.PHONY: do-po-update po-update
do-po-update:
tmppo=/tmp/$(PACKAGE)-$(VERSION)-po &&\
rm -rf $$tmppo && \
mkdir $$tmppo && \
(cd $$tmppo && $(WGET) -r -l1 -nd --no-parent -A '*.po' $(po_repo)) &&\
cp $$tmppo/*.po po
cd po && $(MAKE) update-po
$(MAKE) po-check
po-update:
if test -d "po"; then \
$(MAKE) do-po-update; \
fi
# -------------------------- #
# Updating GNU build tools. #
# -------------------------- #
# The following pseudo table associates a local directory and a URL
# with each of the files that belongs to some other package and is
# regularly updated from the specified URL.
# $(srcdir)/src/ansi2knr.c
wget_files ?= $(srcdir)/config/config.guess $(srcdir)/config/config.sub \
$(srcdir)/doc/texinfo.tex $(srcdir)/doc/make-stds.texi \
$(srcdir)/doc/fdl.texi
wget-targets = $(patsubst %, get-%, $(wget_files))
config.guess-url_prefix = $(ftp-gnu)/config/
config.sub-url_prefix = $(ftp-gnu)/config/
ansi2knr.c-url_prefix = ftp://ftp.cs.wisc.edu/ghost/
texinfo.tex-url_prefix = $(ftp-gnu)/texinfo/
standards.texi-url_prefix = $(ftp-gnu)/GNUinfo/
make-stds.texi-url_prefix = $(ftp-gnu)/GNUinfo/
fdl.texi-url_prefix = $(ftp-gnu)/GNUinfo/
target = $(patsubst get-%,%,$@)
url = $($(notdir $(target))-url_prefix)$(notdir $(target))
.PHONY: $(wget-targets)
$(wget-targets):
@echo $(WGET) $(url) -O $(target) \
&& $(WGET) $(url) -O $(target).t \
&& $(move_if_change)
.PHONY: wget-update
wget-update: $(wget-targets)
# Updating tools via CVS.
cvs_files ?= depcomp missing
cvs-targets = $(patsubst %, get-%, $(cvs_files))
automake_repo = :pserver:anoncvs@anoncvs.cygnus.com:/cvs/automake
.PHONY: $(cvs-targets)
$(cvs-targets):
$(CVS) -d $(automake_repo) co -p automake/lib/$(notdir $(target)) \
>$(target).t \
&& $(move_if_change)
.PHONY: cvs-update
cvs-update: $(cvs-targets)
# --------------------- #
# Updating everything. #
# --------------------- #
.PHONY: update
update: wget-update po-update
# cvs-update
## --------------- ##
## Sanity checks. ##
## --------------- ##
# Checks that don't require cvs. Run `changelog-check' last as
# previous test may reveal problems requiring new ChangeLog entries.
local-check: po-check changelog-check
# copyright-check writable-files
changelog-check:
if head ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \
:; \
else \
echo "$(VERSION) not in ChangeLog" 1>&2; \
exit 1; \
fi
# Verify that all source files using _() are listed in po/POTFILES.in.
po-check:
if test -f po/POTFILES.in; then \
grep -E -v '^(#|$$)' po/POTFILES.in | sort > $@-1; \
grep -E -l '\b_\(' *.c | sort > $@-2; \
diff -u $@-1 $@-2 || exit 1; \
rm -f $@-1 $@-2; \
fi

View File

@@ -1,916 +0,0 @@
@comment This file is included by both standards.texi and make.texinfo.
@comment It was broken out of standards.texi on 1/6/93 by roland.
@node Makefile Conventions
@chapter Makefile Conventions
@comment standards.texi does not print an index, but make.texinfo does.
@cindex makefile, conventions for
@cindex conventions for makefiles
@cindex standards for makefiles
This
@ifinfo
node
@end ifinfo
@iftex
@ifset CODESTD
section
@end ifset
@ifclear CODESTD
chapter
@end ifclear
@end iftex
describes conventions for writing the Makefiles for GNU programs.
Using Automake will help you write a Makefile that follows these
conventions.
@menu
* Makefile Basics:: General Conventions for Makefiles
* Utilities in Makefiles:: Utilities in Makefiles
* Command Variables:: Variables for Specifying Commands
* Directory Variables:: Variables for Installation Directories
* Standard Targets:: Standard Targets for Users
* Install Command Categories:: Three categories of commands in the `install'
rule: normal, pre-install and post-install.
@end menu
@node Makefile Basics
@section General Conventions for Makefiles
Every Makefile should contain this line:
@example
SHELL = /bin/sh
@end example
@noindent
to avoid trouble on systems where the @code{SHELL} variable might be
inherited from the environment. (This is never a problem with GNU
@code{make}.)
Different @code{make} programs have incompatible suffix lists and
implicit rules, and this sometimes creates confusion or misbehavior. So
it is a good idea to set the suffix list explicitly using only the
suffixes you need in the particular Makefile, like this:
@example
.SUFFIXES:
.SUFFIXES: .c .o
@end example
@noindent
The first line clears out the suffix list, the second introduces all
suffixes which may be subject to implicit rules in this Makefile.
Don't assume that @file{.} is in the path for command execution. When
you need to run programs that are a part of your package during the
make, please make sure that it uses @file{./} if the program is built as
part of the make or @file{$(srcdir)/} if the file is an unchanging part
of the source code. Without one of these prefixes, the current search
path is used.
The distinction between @file{./} (the @dfn{build directory}) and
@file{$(srcdir)/} (the @dfn{source directory}) is important because
users can build in a separate directory using the @samp{--srcdir} option
to @file{configure}. A rule of the form:
@smallexample
foo.1 : foo.man sedscript
sed -e sedscript foo.man > foo.1
@end smallexample
@noindent
will fail when the build directory is not the source directory, because
@file{foo.man} and @file{sedscript} are in the the source directory.
When using GNU @code{make}, relying on @samp{VPATH} to find the source
file will work in the case where there is a single dependency file,
since the @code{make} automatic variable @samp{$<} will represent the
source file wherever it is. (Many versions of @code{make} set @samp{$<}
only in implicit rules.) A Makefile target like
@smallexample
foo.o : bar.c
$(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o
@end smallexample
@noindent
should instead be written as
@smallexample
foo.o : bar.c
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@@
@end smallexample
@noindent
in order to allow @samp{VPATH} to work correctly. When the target has
multiple dependencies, using an explicit @samp{$(srcdir)} is the easiest
way to make the rule work well. For example, the target above for
@file{foo.1} is best written as:
@smallexample
foo.1 : foo.man sedscript
sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@@
@end smallexample
GNU distributions usually contain some files which are not source
files---for example, Info files, and the output from Autoconf, Automake,
Bison or Flex. Since these files normally appear in the source
directory, they should always appear in the source directory, not in the
build directory. So Makefile rules to update them should put the
updated files in the source directory.
However, if a file does not appear in the distribution, then the
Makefile should not put it in the source directory, because building a
program in ordinary circumstances should not modify the source directory
in any way.
Try to make the build and installation targets, at least (and all their
subtargets) work correctly with a parallel @code{make}.
@node Utilities in Makefiles
@section Utilities in Makefiles
Write the Makefile commands (and any shell scripts, such as
@code{configure}) to run in @code{sh}, not in @code{csh}. Don't use any
special features of @code{ksh} or @code{bash}.
The @code{configure} script and the Makefile rules for building and
installation should not use any utilities directly except these:
@c dd find
@c gunzip gzip md5sum
@c mkfifo mknod tee uname
@example
cat cmp cp diff echo egrep expr false grep install-info
ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true
@end example
The compression program @code{gzip} can be used in the @code{dist} rule.
Stick to the generally supported options for these programs. For
example, don't use @samp{mkdir -p}, convenient as it may be, because
most systems don't support it.
It is a good idea to avoid creating symbolic links in makefiles, since a
few systems don't support them.
The Makefile rules for building and installation can also use compilers
and related programs, but should do so via @code{make} variables so that the
user can substitute alternatives. Here are some of the programs we
mean:
@example
ar bison cc flex install ld ldconfig lex
make makeinfo ranlib texi2dvi yacc
@end example
Use the following @code{make} variables to run those programs:
@example
$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX)
$(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)
@end example
When you use @code{ranlib} or @code{ldconfig}, you should make sure
nothing bad happens if the system does not have the program in question.
Arrange to ignore an error from that command, and print a message before
the command to tell the user that failure of this command does not mean
a problem. (The Autoconf @samp{AC_PROG_RANLIB} macro can help with
this.)
If you use symbolic links, you should implement a fallback for systems
that don't have symbolic links.
Additional utilities that can be used via Make variables are:
@example
chgrp chmod chown mknod
@end example
It is ok to use other utilities in Makefile portions (or scripts)
intended only for particular systems where you know those utilities
exist.
@node Command Variables
@section Variables for Specifying Commands
Makefiles should provide variables for overriding certain commands, options,
and so on.
In particular, you should run most utility programs via variables.
Thus, if you use Bison, have a variable named @code{BISON} whose default
value is set with @samp{BISON = bison}, and refer to it with
@code{$(BISON)} whenever you need to use Bison.
File management utilities such as @code{ln}, @code{rm}, @code{mv}, and
so on, need not be referred to through variables in this way, since users
don't need to replace them with other programs.
Each program-name variable should come with an options variable that is
used to supply options to the program. Append @samp{FLAGS} to the
program-name variable name to get the options variable name---for
example, @code{BISONFLAGS}. (The names @code{CFLAGS} for the C
compiler, @code{YFLAGS} for yacc, and @code{LFLAGS} for lex, are
exceptions to this rule, but we keep them because they are standard.)
Use @code{CPPFLAGS} in any compilation command that runs the
preprocessor, and use @code{LDFLAGS} in any compilation command that
does linking as well as in any direct use of @code{ld}.
If there are C compiler options that @emph{must} be used for proper
compilation of certain files, do not include them in @code{CFLAGS}.
Users expect to be able to specify @code{CFLAGS} freely themselves.
Instead, arrange to pass the necessary options to the C compiler
independently of @code{CFLAGS}, by writing them explicitly in the
compilation commands or by defining an implicit rule, like this:
@smallexample
CFLAGS = -g
ALL_CFLAGS = -I. $(CFLAGS)
.c.o:
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
@end smallexample
Do include the @samp{-g} option in @code{CFLAGS}, because that is not
@emph{required} for proper compilation. You can consider it a default
that is only recommended. If the package is set up so that it is
compiled with GCC by default, then you might as well include @samp{-O}
in the default value of @code{CFLAGS} as well.
Put @code{CFLAGS} last in the compilation command, after other variables
containing compiler options, so the user can use @code{CFLAGS} to
override the others.
@code{CFLAGS} should be used in every invocation of the C compiler,
both those which do compilation and those which do linking.
Every Makefile should define the variable @code{INSTALL}, which is the
basic command for installing a file into the system.
Every Makefile should also define the variables @code{INSTALL_PROGRAM}
and @code{INSTALL_DATA}. (The default for each of these should be
@code{$(INSTALL)}.) Then it should use those variables as the commands
for actual installation, for executables and nonexecutables
respectively. Use these variables as follows:
@example
$(INSTALL_PROGRAM) foo $(bindir)/foo
$(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a
@end example
Optionally, you may prepend the value of @code{DESTDIR} to the target
filename. Doing this allows the installer to create a snapshot of the
installation to be copied onto the real target filesystem later. Do not
set the value of @code{DESTDIR} in your Makefile, and do not include it
in any installed files. With support for @code{DESTDIR}, the above
examples become:
@example
$(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo
$(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a
@end example
@noindent
Always use a file name, not a directory name, as the second argument of
the installation commands. Use a separate command for each file to be
installed.
@node Directory Variables
@section Variables for Installation Directories
Installation directories should always be named by variables, so it is
easy to install in a nonstandard place. The standard names for these
variables are described below. They are based on a standard filesystem
layout; variants of it are used in SVR4, 4.4BSD, Linux, Ultrix v4, and
other modern operating systems.
These two variables set the root for the installation. All the other
installation directories should be subdirectories of one of these two,
and nothing should be directly installed into these two directories.
@table @samp
@item prefix
A prefix used in constructing the default values of the variables listed
below. The default value of @code{prefix} should be @file{/usr/local}.
When building the complete GNU system, the prefix will be empty and
@file{/usr} will be a symbolic link to @file{/}.
(If you are using Autoconf, write it as @samp{@@prefix@@}.)
Running @samp{make install} with a different value of @code{prefix}
from the one used to build the program should @var{not} recompile
the program.
@item exec_prefix
A prefix used in constructing the default values of some of the
variables listed below. The default value of @code{exec_prefix} should
be @code{$(prefix)}.
(If you are using Autoconf, write it as @samp{@@exec_prefix@@}.)
Generally, @code{$(exec_prefix)} is used for directories that contain
machine-specific files (such as executables and subroutine libraries),
while @code{$(prefix)} is used directly for other directories.
Running @samp{make install} with a different value of @code{exec_prefix}
from the one used to build the program should @var{not} recompile the
program.
@end table
Executable programs are installed in one of the following directories.
@table @samp
@item bindir
The directory for installing executable programs that users can run.
This should normally be @file{/usr/local/bin}, but write it as
@file{$(exec_prefix)/bin}.
(If you are using Autoconf, write it as @samp{@@bindir@@}.)
@item sbindir
The directory for installing executable programs that can be run from
the shell, but are only generally useful to system administrators. This
should normally be @file{/usr/local/sbin}, but write it as
@file{$(exec_prefix)/sbin}.
(If you are using Autoconf, write it as @samp{@@sbindir@@}.)
@item libexecdir
@comment This paragraph adjusted to avoid overfull hbox --roland 5jul94
The directory for installing executable programs to be run by other
programs rather than by users. This directory should normally be
@file{/usr/local/libexec}, but write it as @file{$(exec_prefix)/libexec}.
(If you are using Autoconf, write it as @samp{@@libexecdir@@}.)
@end table
Data files used by the program during its execution are divided into
categories in two ways.
@itemize @bullet
@item
Some files are normally modified by programs; others are never normally
modified (though users may edit some of these).
@item
Some files are architecture-independent and can be shared by all
machines at a site; some are architecture-dependent and can be shared
only by machines of the same kind and operating system; others may never
be shared between two machines.
@end itemize
This makes for six different possibilities. However, we want to
discourage the use of architecture-dependent files, aside from object
files and libraries. It is much cleaner to make other data files
architecture-independent, and it is generally not hard.
Therefore, here are the variables Makefiles should use to specify
directories:
@table @samp
@item datadir
The directory for installing read-only architecture independent data
files. This should normally be @file{/usr/local/share}, but write it as
@file{$(prefix)/share}.
(If you are using Autoconf, write it as @samp{@@datadir@@}.)
As a special exception, see @file{$(infodir)}
and @file{$(includedir)} below.
@item sysconfdir
The directory for installing read-only data files that pertain to a
single machine--that is to say, files for configuring a host. Mailer
and network configuration files, @file{/etc/passwd}, and so forth belong
here. All the files in this directory should be ordinary ASCII text
files. This directory should normally be @file{/usr/local/etc}, but
write it as @file{$(prefix)/etc}.
(If you are using Autoconf, write it as @samp{@@sysconfdir@@}.)
Do not install executables here in this directory (they probably belong
in @file{$(libexecdir)} or @file{$(sbindir)}). Also do not install
files that are modified in the normal course of their use (programs
whose purpose is to change the configuration of the system excluded).
Those probably belong in @file{$(localstatedir)}.
@item sharedstatedir
The directory for installing architecture-independent data files which
the programs modify while they run. This should normally be
@file{/usr/local/com}, but write it as @file{$(prefix)/com}.
(If you are using Autoconf, write it as @samp{@@sharedstatedir@@}.)
@item localstatedir
The directory for installing data files which the programs modify while
they run, and that pertain to one specific machine. Users should never
need to modify files in this directory to configure the package's
operation; put such configuration information in separate files that go
in @file{$(datadir)} or @file{$(sysconfdir)}. @file{$(localstatedir)}
should normally be @file{/usr/local/var}, but write it as
@file{$(prefix)/var}.
(If you are using Autoconf, write it as @samp{@@localstatedir@@}.)
@item libdir
The directory for object files and libraries of object code. Do not
install executables here, they probably ought to go in @file{$(libexecdir)}
instead. The value of @code{libdir} should normally be
@file{/usr/local/lib}, but write it as @file{$(exec_prefix)/lib}.
(If you are using Autoconf, write it as @samp{@@libdir@@}.)
@item infodir
The directory for installing the Info files for this package. By
default, it should be @file{/usr/local/info}, but it should be written
as @file{$(prefix)/info}.
(If you are using Autoconf, write it as @samp{@@infodir@@}.)
@item lispdir
The directory for installing any Emacs Lisp files in this package. By
default, it should be @file{/usr/local/share/emacs/site-lisp}, but it
should be written as @file{$(prefix)/share/emacs/site-lisp}.
If you are using Autoconf, write the default as @samp{@@lispdir@@}.
In order to make @samp{@@lispdir@@} work, you need the following lines
in your @file{configure.in} file:
@example
lispdir='$@{datadir@}/emacs/site-lisp'
AC_SUBST(lispdir)
@end example
@item includedir
@c rewritten to avoid overfull hbox --roland
The directory for installing header files to be included by user
programs with the C @samp{#include} preprocessor directive. This
should normally be @file{/usr/local/include}, but write it as
@file{$(prefix)/include}.
(If you are using Autoconf, write it as @samp{@@includedir@@}.)
Most compilers other than GCC do not look for header files in directory
@file{/usr/local/include}. So installing the header files this way is
only useful with GCC. Sometimes this is not a problem because some
libraries are only really intended to work with GCC. But some libraries
are intended to work with other compilers. They should install their
header files in two places, one specified by @code{includedir} and one
specified by @code{oldincludedir}.
@item oldincludedir
The directory for installing @samp{#include} header files for use with
compilers other than GCC. This should normally be @file{/usr/include}.
(If you are using Autoconf, you can write it as @samp{@@oldincludedir@@}.)
The Makefile commands should check whether the value of
@code{oldincludedir} is empty. If it is, they should not try to use
it; they should cancel the second installation of the header files.
A package should not replace an existing header in this directory unless
the header came from the same package. Thus, if your Foo package
provides a header file @file{foo.h}, then it should install the header
file in the @code{oldincludedir} directory if either (1) there is no
@file{foo.h} there or (2) the @file{foo.h} that exists came from the Foo
package.
To tell whether @file{foo.h} came from the Foo package, put a magic
string in the file---part of a comment---and @code{grep} for that string.
@end table
Unix-style man pages are installed in one of the following:
@table @samp
@item mandir
The top-level directory for installing the man pages (if any) for this
package. It will normally be @file{/usr/local/man}, but you should
write it as @file{$(prefix)/man}.
(If you are using Autoconf, write it as @samp{@@mandir@@}.)
@item man1dir
The directory for installing section 1 man pages. Write it as
@file{$(mandir)/man1}.
@item man2dir
The directory for installing section 2 man pages. Write it as
@file{$(mandir)/man2}
@item @dots{}
@strong{Don't make the primary documentation for any GNU software be a
man page. Write a manual in Texinfo instead. Man pages are just for
the sake of people running GNU software on Unix, which is a secondary
application only.}
@item manext
The file name extension for the installed man page. This should contain
a period followed by the appropriate digit; it should normally be @samp{.1}.
@item man1ext
The file name extension for installed section 1 man pages.
@item man2ext
The file name extension for installed section 2 man pages.
@item @dots{}
Use these names instead of @samp{manext} if the package needs to install man
pages in more than one section of the manual.
@end table
And finally, you should set the following variable:
@table @samp
@item srcdir
The directory for the sources being compiled. The value of this
variable is normally inserted by the @code{configure} shell script.
(If you are using Autconf, use @samp{srcdir = @@srcdir@@}.)
@end table
For example:
@smallexample
@c I have changed some of the comments here slightly to fix an overfull
@c hbox, so the make manual can format correctly. --roland
# Common prefix for installation directories.
# NOTE: This directory must exist when you start the install.
prefix = /usr/local
exec_prefix = $(prefix)
# Where to put the executable for the command `gcc'.
bindir = $(exec_prefix)/bin
# Where to put the directories used by the compiler.
libexecdir = $(exec_prefix)/libexec
# Where to put the Info files.
infodir = $(prefix)/info
@end smallexample
If your program installs a large number of files into one of the
standard user-specified directories, it might be useful to group them
into a subdirectory particular to that program. If you do this, you
should write the @code{install} rule to create these subdirectories.
Do not expect the user to include the subdirectory name in the value of
any of the variables listed above. The idea of having a uniform set of
variable names for installation directories is to enable the user to
specify the exact same values for several different GNU packages. In
order for this to be useful, all the packages must be designed so that
they will work sensibly when the user does so.
@node Standard Targets
@section Standard Targets for Users
All GNU programs should have the following targets in their Makefiles:
@table @samp
@item all
Compile the entire program. This should be the default target. This
target need not rebuild any documentation files; Info files should
normally be included in the distribution, and DVI files should be made
only when explicitly asked for.
By default, the Make rules should compile and link with @samp{-g}, so
that executable programs have debugging symbols. Users who don't mind
being helpless can strip the executables later if they wish.
@item install
Compile the program and copy the executables, libraries, and so on to
the file names where they should reside for actual use. If there is a
simple test to verify that a program is properly installed, this target
should run that test.
Do not strip executables when installing them. Devil-may-care users can
use the @code{install-strip} target to do that.
If possible, write the @code{install} target rule so that it does not
modify anything in the directory where the program was built, provided
@samp{make all} has just been done. This is convenient for building the
program under one user name and installing it under another.
The commands should create all the directories in which files are to be
installed, if they don't already exist. This includes the directories
specified as the values of the variables @code{prefix} and
@code{exec_prefix}, as well as all subdirectories that are needed.
One way to do this is by means of an @code{installdirs} target
as described below.
Use @samp{-} before any command for installing a man page, so that
@code{make} will ignore any errors. This is in case there are systems
that don't have the Unix man page documentation system installed.
The way to install Info files is to copy them into @file{$(infodir)}
with @code{$(INSTALL_DATA)} (@pxref{Command Variables}), and then run
the @code{install-info} program if it is present. @code{install-info}
is a program that edits the Info @file{dir} file to add or update the
menu entry for the given Info file; it is part of the Texinfo package.
Here is a sample rule to install an Info file:
@comment This example has been carefully formatted for the Make manual.
@comment Please do not reformat it without talking to roland@gnu.ai.mit.edu.
@smallexample
$(DESTDIR)$(infodir)/foo.info: foo.info
$(POST_INSTALL)
# There may be a newer info file in . than in srcdir.
-if test -f foo.info; then d=.; \
else d=$(srcdir); fi; \
$(INSTALL_DATA) $$d/foo.info $(DESTDIR)$@@; \
# Run install-info only if it exists.
# Use `if' instead of just prepending `-' to the
# line so we notice real errors from install-info.
# We use `$(SHELL) -c' because some shells do not
# fail gracefully when there is an unknown command.
if $(SHELL) -c 'install-info --version' \
>/dev/null 2>&1; then \
install-info --dir-file=$(DESTDIR)$(infodir)/dir \
$(DESTDIR)$(infodir)/foo.info; \
else true; fi
@end smallexample
When writing the @code{install} target, you must classify all the
commands into three categories: normal ones, @dfn{pre-installation}
commands and @dfn{post-installation} commands. @xref{Install Command
Categories}.
@item uninstall
Delete all the installed files---the copies that the @samp{install}
target creates.
This rule should not modify the directories where compilation is done,
only the directories where files are installed.
The uninstallation commands are divided into three categories, just like
the installation commands. @xref{Install Command Categories}.
@item install-strip
Like @code{install}, but strip the executable files while installing
them. In many cases, the definition of this target can be very simple:
@smallexample
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
install
@end smallexample
Normally we do not recommend stripping an executable unless you are sure
the program has no bugs. However, it can be reasonable to install a
stripped executable for actual execution while saving the unstripped
executable elsewhere in case there is a bug.
@comment The gratuitous blank line here is to make the table look better
@comment in the printed Make manual. Please leave it in.
@item clean
Delete all files from the current directory that are normally created by
building the program. Don't delete the files that record the
configuration. Also preserve files that could be made by building, but
normally aren't because the distribution comes with them.
Delete @file{.dvi} files here if they are not part of the distribution.
@item distclean
Delete all files from the current directory that are created by
configuring or building the program. If you have unpacked the source
and built the program without creating any other files, @samp{make
distclean} should leave only the files that were in the distribution.
@item mostlyclean
Like @samp{clean}, but may refrain from deleting a few files that people
normally don't want to recompile. For example, the @samp{mostlyclean}
target for GCC does not delete @file{libgcc.a}, because recompiling it
is rarely necessary and takes a lot of time.
@item maintainer-clean
Delete almost everything from the current directory that can be
reconstructed with this Makefile. This typically includes everything
deleted by @code{distclean}, plus more: C source files produced by
Bison, tags tables, Info files, and so on.
The reason we say ``almost everything'' is that running the command
@samp{make maintainer-clean} should not delete @file{configure} even if
@file{configure} can be remade using a rule in the Makefile. More generally,
@samp{make maintainer-clean} should not delete anything that needs to
exist in order to run @file{configure} and then begin to build the
program. This is the only exception; @code{maintainer-clean} should
delete everything else that can be rebuilt.
The @samp{maintainer-clean} target is intended to be used by a maintainer of
the package, not by ordinary users. You may need special tools to
reconstruct some of the files that @samp{make maintainer-clean} deletes.
Since these files are normally included in the distribution, we don't
take care to make them easy to reconstruct. If you find you need to
unpack the full distribution again, don't blame us.
To help make users aware of this, the commands for the special
@code{maintainer-clean} target should start with these two:
@smallexample
@@echo 'This command is intended for maintainers to use; it'
@@echo 'deletes files that may need special tools to rebuild.'
@end smallexample
@item TAGS
Update a tags table for this program.
@c ADR: how?
@item info
Generate any Info files needed. The best way to write the rules is as
follows:
@smallexample
info: foo.info
foo.info: foo.texi chap1.texi chap2.texi
$(MAKEINFO) $(srcdir)/foo.texi
@end smallexample
@noindent
You must define the variable @code{MAKEINFO} in the Makefile. It should
run the @code{makeinfo} program, which is part of the Texinfo
distribution.
Normally a GNU distribution comes with Info files, and that means the
Info files are present in the source directory. Therefore, the Make
rule for an info file should update it in the source directory. When
users build the package, ordinarily Make will not update the Info files
because they will already be up to date.
@item dvi
Generate DVI files for all Texinfo documentation.
For example:
@smallexample
dvi: foo.dvi
foo.dvi: foo.texi chap1.texi chap2.texi
$(TEXI2DVI) $(srcdir)/foo.texi
@end smallexample
@noindent
You must define the variable @code{TEXI2DVI} in the Makefile. It should
run the program @code{texi2dvi}, which is part of the Texinfo
distribution.@footnote{@code{texi2dvi} uses @TeX{} to do the real work
of formatting. @TeX{} is not distributed with Texinfo.} Alternatively,
write just the dependencies, and allow GNU @code{make} to provide the command.
@item dist
Create a distribution tar file for this program. The tar file should be
set up so that the file names in the tar file start with a subdirectory
name which is the name of the package it is a distribution for. This
name can include the version number.
For example, the distribution tar file of GCC version 1.40 unpacks into
a subdirectory named @file{gcc-1.40}.
The easiest way to do this is to create a subdirectory appropriately
named, use @code{ln} or @code{cp} to install the proper files in it, and
then @code{tar} that subdirectory.
Compress the tar file file with @code{gzip}. For example, the actual
distribution file for GCC version 1.40 is called @file{gcc-1.40.tar.gz}.
The @code{dist} target should explicitly depend on all non-source files
that are in the distribution, to make sure they are up to date in the
distribution.
@ifset CODESTD
@xref{Releases, , Making Releases}.
@end ifset
@ifclear CODESTD
@xref{Releases, , Making Releases, standards, GNU Coding Standards}.
@end ifclear
@item check
Perform self-tests (if any). The user must build the program before
running the tests, but need not install the program; you should write
the self-tests so that they work when the program is built but not
installed.
@end table
The following targets are suggested as conventional names, for programs
in which they are useful.
@table @code
@item installcheck
Perform installation tests (if any). The user must build and install
the program before running the tests. You should not assume that
@file{$(bindir)} is in the search path.
@item installdirs
It's useful to add a target named @samp{installdirs} to create the
directories where files are installed, and their parent directories.
There is a script called @file{mkinstalldirs} which is convenient for
this; you can find it in the Texinfo package.
@c It's in /gd/gnu/lib/mkinstalldirs.
You can use a rule like this:
@comment This has been carefully formatted to look decent in the Make manual.
@comment Please be sure not to make it extend any further to the right.--roland
@smallexample
# Make sure all installation directories (e.g. $(bindir))
# actually exist by making them if necessary.
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(bindir) $(datadir) \
$(libdir) $(infodir) \
$(mandir)
@end smallexample
This rule should not modify the directories where compilation is done.
It should do nothing but create installation directories.
@end table
@node Install Command Categories
@section Install Command Categories
@cindex pre-installation commands
@cindex post-installation commands
When writing the @code{install} target, you must classify all the
commands into three categories: normal ones, @dfn{pre-installation}
commands and @dfn{post-installation} commands.
Normal commands move files into their proper places, and set their
modes. They may not alter any files except the ones that come entirely
from the package they belong to.
Pre-installation and post-installation commands may alter other files;
in particular, they can edit global configuration files or data bases.
Pre-installation commands are typically executed before the normal
commands, and post-installation commands are typically run after the
normal commands.
The most common use for a post-installation command is to run
@code{install-info}. This cannot be done with a normal command, since
it alters a file (the Info directory) which does not come entirely and
solely from the package being installed. It is a post-installation
command because it needs to be done after the normal command which
installs the package's Info files.
Most programs don't need any pre-installation commands, but we have the
feature just in case it is needed.
To classify the commands in the @code{install} rule into these three
categories, insert @dfn{category lines} among them. A category line
specifies the category for the commands that follow.
A category line consists of a tab and a reference to a special Make
variable, plus an optional comment at the end. There are three
variables you can use, one for each category; the variable name
specifies the category. Category lines are no-ops in ordinary execution
because these three Make variables are normally undefined (and you
@emph{should not} define them in the makefile).
Here are the three possible category lines, each with a comment that
explains what it means:
@smallexample
$(PRE_INSTALL) # @r{Pre-install commands follow.}
$(POST_INSTALL) # @r{Post-install commands follow.}
$(NORMAL_INSTALL) # @r{Normal commands follow.}
@end smallexample
If you don't use a category line at the beginning of the @code{install}
rule, all the commands are classified as normal until the first category
line. If you don't use any category lines, all the commands are
classified as normal.
These are the category lines for @code{uninstall}:
@smallexample
$(PRE_UNINSTALL) # @r{Pre-uninstall commands follow.}
$(POST_UNINSTALL) # @r{Post-uninstall commands follow.}
$(NORMAL_UNINSTALL) # @r{Normal commands follow.}
@end smallexample
Typically, a pre-uninstall command would be used for deleting entries
from the Info directory.
If the @code{install} or @code{uninstall} target has any dependencies
which act as subroutines of installation, then you should start
@emph{each} dependency's commands with a category line, and start the
main target's commands with a category line also. This way, you can
ensure that each command is placed in the right category regardless of
which of the dependencies actually run.
Pre-installation and post-installation commands should not run any
programs except for these:
@example
[ basename bash cat chgrp chmod chown cmp cp dd diff echo
egrep expand expr false fgrep find getopt grep gunzip gzip
hostname install install-info kill ldconfig ln ls md5sum
mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee
test touch true uname xargs yes
@end example
@cindex binary packages
The reason for distinguishing the commands in this way is for the sake
of making binary packages. Typically a binary package contains all the
executables and other files that need to be installed, and has its own
method of installing them---so it does not need to run the normal
installation commands. But installing the binary package does need to
execute the pre-installation and post-installation commands.
Programs to build binary packages work by extracting the
pre-installation and post-installation commands. Here is one way of
extracting the pre-installation commands:
@smallexample
make -n install -o all \
PRE_INSTALL=pre-install \
POST_INSTALL=post-install \
NORMAL_INSTALL=normal-install \
| gawk -f pre-install.awk
@end smallexample
@noindent
where the file @file{pre-install.awk} could contain this:
@smallexample
$0 ~ /^\t[ \t]*(normal_install|post_install)[ \t]*$/ @{on = 0@}
on @{print $0@}
$0 ~ /^\t[ \t]*pre_install[ \t]*$/ @{on = 1@}
@end smallexample
The resulting file of pre-installation commands is executed as a shell
script as part of installing the binary package.

187
make.h
View File

@@ -1,5 +1,6 @@
/* Miscellaneous global declarations and portability cruft for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,95,96,97,99 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -17,11 +18,6 @@ along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* AIX requires this to be the first thing in the file. */
#if defined (_AIX) && !defined (__GNUC__)
#pragma alloca
#endif
/* We use <config.h> instead of "config.h" so that a compilation
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
(which it would do because make.h was found in $srcdir). */
@@ -29,6 +25,21 @@ Boston, MA 02111-1307, USA. */
#undef HAVE_CONFIG_H
#define HAVE_CONFIG_H 1
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
/* Use prototypes if available. */
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
@@ -39,14 +50,10 @@ Boston, MA 02111-1307, USA. */
# define PARAMS(protos) ()
#endif /* C++ or ANSI C. */
/* Specify we want GNU source code. This must be defined before any
system headers are included. */
#include "gettext.h"
#define _(Text) gettext (Text)
#define N_(Text) gettext_noop (Text)
#if !HAVE_SETLOCALE
# define setlocale(Category, Locale) /* empty */
#endif
#define _GNU_SOURCE 1
#ifdef CRAY
@@ -60,7 +67,6 @@ Boston, MA 02111-1307, USA. */
# define __NO_STRING_INLINES
#endif
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
@@ -72,21 +78,24 @@ Boston, MA 02111-1307, USA. */
<sys/timeb.h>? If any does not, configure should check for it. */
# include <sys/timeb.h>
#endif
#include <time.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <errno.h>
#ifndef errno
extern int errno;
#endif
/* A shortcut for EINTR checking. Note you should be careful when negating
this! That might not mean what you want if EINTR is not available. */
#ifdef EINTR
# define EINTR_SET (errno == EINTR)
#else
# define EINTR_SET (0)
#endif
#ifndef isblank
# define isblank(c) ((c) == ' ' || (c) == '\t')
#endif
@@ -117,6 +126,10 @@ extern int errno;
# define sigmask(sig) (1 << ((sig) - 1))
#endif
#ifndef HAVE_SA_RESTART
# define SA_RESTART 0
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
@@ -181,6 +194,8 @@ extern unsigned int get_path_max PARAMS ((void));
# include <unixlib.h>
# include <unixio.h>
# include <perror.h>
/* Needed to use alloca on VMS. */
# include <builtins.h>
#endif
#ifndef __attribute__
@@ -223,6 +238,14 @@ extern void exit PARAMS ((int)) __attribute__ ((noreturn));
#endif /* Standard headers. */
/* These should be in stdlib.h. Make sure we have them. */
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 0
#endif
#ifdef ANSI_STRING
# ifndef bcmp
@@ -262,26 +285,13 @@ extern void bcopy PARAMS ((const char *b1, char *b2, int));
extern char *strerror PARAMS ((int errnum));
#endif
#ifdef __GNUC__
# undef alloca
# define alloca(n) __builtin_alloca (n)
#else /* Not GCC. */
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else /* Not HAVE_ALLOCA_H. */
# ifndef _AIX
extern char *alloca ();
# endif /* Not AIX. */
# endif /* HAVE_ALLOCA_H. */
#endif /* GCC. */
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#define FILE_TIMESTAMP uintmax_t
#if ST_MTIM_NSEC
# if HAVE_INTTYPES_H
# include <inttypes.h>
# endif
# define FILE_TIMESTAMP uintmax_t
#else
# define FILE_TIMESTAMP time_t
#if !defined(HAVE_STRSIGNAL)
extern char *strsignal PARAMS ((int signum));
#endif
/* ISDIGIT offers the following features:
@@ -289,10 +299,10 @@ extern char *alloca ();
- It's guaranteed to evaluate its argument exactly once.
NOTE! Make relies on this behavior, don't change it!
- It's typically faster.
Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
only '0' through '9' are digits. Prefer ISDIGIT to isdigit() unless
it's important to use the locale's definition of `digit' even when the
host does not conform to Posix. */
host does not conform to POSIX. */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#ifndef iAPX286
@@ -318,22 +328,28 @@ extern char *alloca ();
extern int strcmpi (const char *,const char *);
#endif
/* Add to VAR the hashing value of C, one character in a name. */
#define HASH(var, c) \
((var += (c)), (var = ((var) << 7) + ((var) >> 20)))
#ifdef HAVE_CASE_INSENSITIVE_FS /* Fold filenames */
# define HASHI(var, c) \
((var += tolower((unsigned char)(c))), (var = ((var) << 7) + ((var) >> 20)))
#else
# define HASHI(var, c) HASH(var,c)
#endif
#if defined(__GNUC__) || defined(ENUM_BITFIELDS)
# define ENUM_BITFIELD(bits) :bits
#else
# define ENUM_BITFIELD(bits)
#endif
/* Handle gettext and locales. */
#if HAVE_LOCALE_H
# include <locale.h>
#else
# define setlocale(category, locale)
#endif
#include <gettext.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) gettext_noop (msgid)
#define S_(msg1,msg2,num) ngettext (msg1,msg2,num)
/* Handle other OSs. */
#if defined(__MSDOS__) || defined(WINDOWS32)
# define PATH_SEPARATOR_CHAR ';'
#else
@@ -370,6 +386,8 @@ struct floc
};
#define NILF ((struct floc *)0)
#define STRING_SIZE_TUPLE(_s) (_s), (sizeof (_s)-1)
/* Fancy processing for variadic functions in both ANSI and pre-ANSI
compilers. */
@@ -388,15 +406,15 @@ extern void fatal ();
extern void die PARAMS ((int)) __attribute__ ((noreturn));
extern void log_working_directory PARAMS ((int));
extern void pfatal_with_name PARAMS ((char *)) __attribute__ ((noreturn));
extern void perror_with_name PARAMS ((char *, char *));
extern void pfatal_with_name PARAMS ((const char *)) __attribute__ ((noreturn));
extern void perror_with_name PARAMS ((const char *, const char *));
extern char *savestring PARAMS ((const char *, unsigned int));
extern char *concat PARAMS ((char *, char *, char *));
extern char *concat PARAMS ((const char *, const char *, const char *));
extern char *xmalloc PARAMS ((unsigned int));
extern char *xrealloc PARAMS ((char *, unsigned int));
extern char *xstrdup PARAMS ((const char *));
extern char *find_next_token PARAMS ((char **, unsigned int *));
extern char *next_token PARAMS ((char *));
extern char *next_token PARAMS ((const char *));
extern char *end_of_token PARAMS ((char *));
extern void collapse_continuations PARAMS ((char *));
extern void remove_comments PARAMS((char *));
@@ -405,8 +423,9 @@ extern char *sindex PARAMS ((const char *, unsigned int, \
extern char *lindex PARAMS ((const char *, const char *, int));
extern int alpha_compare PARAMS ((const void *, const void *));
extern void print_spaces PARAMS ((unsigned int));
extern char *find_char_unquote PARAMS ((char *, char *, int));
extern char *find_char_unquote PARAMS ((char *, int, int, int));
extern char *find_percent PARAMS ((char *));
extern FILE *open_tmpfile PARAMS ((char **, const char *));
#ifndef NO_ARCHIVES
extern int ar_name PARAMS ((char *));
@@ -420,6 +439,7 @@ extern int file_exists_p PARAMS ((char *));
extern int file_impossible_p PARAMS ((char *));
extern void file_impossible PARAMS ((char *));
extern char *dir_name PARAMS ((char *));
extern void hash_init_directories PARAMS ((void));
extern void define_default_variables PARAMS ((void));
extern void set_default_suffixes PARAMS ((void));
@@ -467,7 +487,7 @@ extern const struct floc *reading_file;
extern char **environ;
extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag;
extern int print_data_base_flag, question_flag, touch_flag;
extern int print_data_base_flag, question_flag, touch_flag, always_make_flag;
extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
extern int print_version_flag, print_directory_flag;
extern int warn_undefined_variables_flag, posix_pedantic, not_parallel;
@@ -503,25 +523,13 @@ extern int handling_fatal_signal;
#endif
#ifdef VMS
# ifndef EXIT_FAILURE
# define EXIT_FAILURE 3
# endif
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 1
# endif
# ifndef EXIT_TROUBLE
# define EXIT_TROUBLE 2
# endif
# define MAKE_SUCCESS 1
# define MAKE_TROUBLE 2
# define MAKE_FAILURE 3
#else
# ifndef EXIT_FAILURE
# define EXIT_FAILURE 2
# endif
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
# endif
# ifndef EXIT_TROUBLE
# define EXIT_TROUBLE 1
# endif
# define MAKE_SUCCESS 0
# define MAKE_TROUBLE 1
# define MAKE_FAILURE 2
#endif
/* Set up heap debugging library dmalloc. */
@@ -529,3 +537,26 @@ extern int handling_fatal_signal;
#ifdef HAVE_DMALLOC_H
#include <dmalloc.h>
#endif
/* If we have broken SA_RESTART support, then wrap stat() and readdir() with
versions that handle EINTR. Note that there are still plenty of system
calls that can fail with EINTR but this, reportedly, gets the vast
majority of failure cases. If you still experience failures you'll need
to either get a system where SA_RESTART works, or you need to avoid -j. */
#ifdef HAVE_BROKEN_RESTART
/* Here we make an assumption that a system with a broken SA_RESTART has
dirent.h. Right now the only system I know of in this category is PTX, and
it does have dirent.h.
*/
#include <dirent.h>
#define stat(_f,_b) atomic_stat ((_f), (_b))
#define readdir(_d) atomic_readdir (_d)
extern int atomic_stat PARAMS ((const char *file, struct stat *buf));
extern struct dirent *atomic_readdir PARAMS ((DIR *dir));
#endif

View File

@@ -4,9 +4,11 @@ $!
$! P1 is non-empty if you want to link with the VAXCRTL library instead
$! of the shareable executable
$! P2 = DEBUG will build an image with debug information
$! P3 = WALL will enable all warning messages (some are suppressed since
$! one macro intentionally causes an error condition)
$!
$! In case of problems with the install you might contact me at
$! zinser@decus.decus.de (preferred) or martin_zinser@exchange.de
$! zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com
$
$! hb
$! But don't ask Martin Zinser about the lines, I added/changed.
@@ -15,6 +17,14 @@ $ on error then $ goto cleanup
$! in case somebody set up her/his own symbol for cc
$ set symbol/scope=(nolocal,noglobal)
$!
$! Just some general constants...
$!
$ true = 1
$ false = 0
$ tmpnam = "temp_" + f$getjpi("","pid")
$ tt = tmpnam + ".txt"
$ tc = tmpnam + ".c"
$!
$! Look for the compiler used
$!
$ lval = ""
@@ -49,7 +59,17 @@ $ lopt = "/debug"
$ else
$ lopt = ""
$ endif
$ filelist = "alloca ar arscan commands default dir expand file function implicit job main misc read remake remote-stub rule signame variable version vmsfunctions vmsify vpath [.glob]glob [.glob]fnmatch getopt1 getopt"
$!
$! Do we want to see all warnings
$!
$ if (p3.nes."WALL")
$ then
$ gosub check_cc_qual
$ endif
$ filelist = "alloca ar arscan commands default dir expand file function " + -
"hash implicit job main misc read remake remote-stub rule " + -
"signame variable version vmsfunctions vmsify vpath " + -
"[.glob]glob [.glob]fnmatch getopt1 getopt"
$ copy config.h-vms config.h
$ n=0
$ open/write optf make.opt
@@ -75,11 +95,44 @@ $ if f$trnlnm("OPTF").nes."" then $ close optf
$ if f$search("make.opt").nes."" then $ del make.opt;*
$ exit
$!
$!------------------------------------------------------------------------------
$!
$! Check if this is a define relating to the properties of the C/C++
$! compiler
$!
$CHECK_CC_QUAL:
$ open/write tmpc 'tc
$ ccqual = "/warn=(disable=questcompare)"
$ write tmpc "#include <stdio.h>"
$ write tmpc "unsigned int i = 1;"
$ write tmpc "int main(){"
$ write tmpc "if (i < 0){printf(""Mission impossible\n"");}}"
$ close tmpc
$ gosub cc_qual_check
$ return
$!
$!------------------------------------------------------------------------------
$!
$! Check for properties of C/C++ compiler
$!
$CC_QUAL_CHECK:
$ cc_qual = false
$ set message/nofac/noident/nosever/notext
$ cc 'ccqual' 'tmpnam'
$ if $status then cc_qual = true
$ set message/fac/ident/sever/text
$ delete/nolog 'tmpnam'.*;*
$ if cc_qual then ccopt = ccopt + ccqual
$ return
$!------------------------------------------------------------------------------
$!
$ compileit : subroutine
$ ploc = f$locate("]",p1)
$ filnam = p1
$ if ploc .lt. f$length(p1) then filnam=f$extract(ploc+1,100,p1)
$ write optf "''filnam'"
$ cc'ccopt'/include=([],[.glob])/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") 'p1'
$ cc'ccopt'/include=([],[.glob]) -
/define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") -
'p1'
$ exit
$ endsubroutine : compileit

View File

@@ -4,6 +4,7 @@
# VMS extensions from GNU Make 3.60 imported by
# Klaus Kämpf (kkaempf@rmi.de)
# Modified for version 3.78.1 by Hartmut.Becker@compaq.com.
# Modified for version 3.80 by zinser@decus.de
#
# 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
@@ -86,11 +87,11 @@ mandir = []
# Number to put on the man page filename.
manext = 1
objs = commands.obj,job.obj,dir.obj,file.obj,misc.obj,\
objs = commands.obj,job.obj,dir.obj,file.obj,misc.obj,hash.obj,\
main.obj,read.obj,remake.obj,rule.obj,implicit.obj,\
default.obj,variable.obj,expand.obj,function.obj,\
vpath.obj,version.obj$(ARCHIVES)$(ALLOCA)$(extras)$(getopt)$(glob)
srcs = commands.c job.c dir.c file.c misc.c \
srcs = commands.c job.c dir.c file.c misc.c hash.c\
main.c read.c remake.c rule.c implicit.c \
default.c variable.c expand.c function.c \
vpath.c version.c vmsfunctions.c vmsify.c $(ARCHIVES_SRC) $(ALLOCASRC) \
@@ -119,6 +120,7 @@ job.obj: job.c make.h commands.h job.h filedef.h variable.h
dir.obj: dir.c make.h
file.obj: file.c make.h commands.h dep.h filedef.h variable.h
misc.obj: misc.c make.h dep.h
hash.obj: hash.c make.h hash.h
main.obj: main.c make.h commands.h dep.h filedef.h variable.h job.h
read.obj: read.c make.h commands.h dep.h filedef.h variable.h
remake.obj: remake.c make.h commands.h job.h dep.h filedef.h

84
misc.c
View File

@@ -1,5 +1,6 @@
/* Miscellaneous generic support functions for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,95,97 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -49,6 +50,7 @@ Boston, MA 02111-1307, USA. */
# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
# define VA_START(args, lastarg)
# define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist)
# define VA_END(args)
#endif
@@ -120,7 +122,7 @@ collapse_continuations (line)
if (backslash)
{
in = next_token (in);
while (out > line && isblank (out[-1]))
while (out > line && isblank ((unsigned char)out[-1]))
--out;
*out++ = ' ';
}
@@ -161,7 +163,7 @@ remove_comments (line)
{
char *comment;
comment = find_char_unquote (line, "#", 0);
comment = find_char_unquote (line, '#', 0, 0);
if (comment != 0)
/* Cut off the line at the #. */
@@ -172,7 +174,7 @@ remove_comments (line)
void
print_spaces (n)
register unsigned int n;
unsigned int n;
{
while (n-- > 0)
putchar (' ');
@@ -184,10 +186,10 @@ print_spaces (n)
char *
concat (s1, s2, s3)
register char *s1, *s2, *s3;
const char *s1, *s2, *s3;
{
register unsigned int len1, len2, len3;
register char *result;
unsigned int len1, len2, len3;
char *result;
len1 = *s1 != '\0' ? strlen (s1) : 0;
len2 = *s2 != '\0' ? strlen (s2) : 0;
@@ -335,18 +337,18 @@ strerror (errnum)
void
perror_with_name (str, name)
char *str, *name;
const char *str, *name;
{
error (NILF, "%s%s: %s", str, name, strerror (errno));
error (NILF, _("%s%s: %s"), str, name, strerror (errno));
}
/* Print an error message from errno and exit. */
void
pfatal_with_name (name)
char *name;
const char *name;
{
fatal (NILF, "%s: %s", name, strerror (errno));
fatal (NILF, _("%s: %s"), name, strerror (errno));
/* NOTREACHED */
}
@@ -478,7 +480,7 @@ char *
end_of_token (s)
char *s;
{
while (*s != '\0' && !isblank (*s))
while (*s != '\0' && !isblank ((unsigned char)*s))
++s;
return s;
}
@@ -495,7 +497,8 @@ end_of_token_w32 (s, stopchar)
register char *p = s;
register int backslash = 0;
while (*p != '\0' && *p != stopchar && (backslash || !isblank (*p)))
while (*p != '\0' && *p != stopchar
&& (backslash || !isblank ((unsigned char)*p)))
{
if (*p++ == '\\')
{
@@ -518,13 +521,11 @@ end_of_token_w32 (s, stopchar)
char *
next_token (s)
char *s;
const char *s;
{
register char *p = s;
while (isblank (*p))
++p;
return p;
while (isblank ((unsigned char)*s))
++s;
return (char *)s;
}
/* Find the next token in PTR; return the address of it, and store the
@@ -650,7 +651,7 @@ log_access (flavor)
but we write this one to stderr because it might be
run in a child fork whose stdout is piped. */
fprintf (stderr, _("%s access: user %lu (real %lu), group %lu (real %lu)\n"),
fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"),
flavor, (unsigned long) geteuid (), (unsigned long) getuid (),
(unsigned long) getegid (), (unsigned long) getgid ());
fflush (stderr);
@@ -671,7 +672,7 @@ init_access ()
if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1)
pfatal_with_name ("get{e}[gu]id");
log_access (_("Initialized"));
log_access (_("Initialized access"));
current_access = make;
#endif
@@ -750,7 +751,7 @@ user_access ()
current_access = user;
log_access ("User");
log_access (_("User access"));
#endif /* GETLOADAVG_PRIVILEGED */
}
@@ -798,7 +799,7 @@ make_access ()
current_access = make;
log_access ("Make");
log_access (_("Make access"));
#endif /* GETLOADAVG_PRIVILEGED */
}
@@ -832,7 +833,7 @@ child_access ()
pfatal_with_name ("child_access: setregid");
#endif
log_access ("Child");
log_access (_("Child access"));
#endif /* GETLOADAVG_PRIVILEGED */
}
@@ -855,3 +856,38 @@ get_path_max ()
return value;
}
#endif
#ifdef HAVE_BROKEN_RESTART
#undef stat
#undef readdir
int
atomic_stat(file, buf)
const char *file;
struct stat *buf;
{
int r;
while ((r = stat (file, buf)) < 0)
if (errno != EINTR)
break;
return r;
}
struct dirent *
atomic_readdir(dir)
DIR *dir;
{
struct dirent *r;
while ((r = readdir (dir)) == NULL)
if (errno != EINTR)
break;
return r;
}
#endif /* HAVE_BROKEN_RESTART */

6
po/.cvsignore Normal file
View File

@@ -0,0 +1,6 @@
*.gmo *.mo *.pot *.po
Makefile Makefile.in Makefile.in.in
Rules-quot
*.sed *.sin *.header
POTFILES

17
po/ChangeLog Normal file
View File

@@ -0,0 +1,17 @@
2002-08-08 Paul D. Smith <psmith@gnu.org>
* LINGUAS: Add a new translation for Chinese (simplified) (zh_CN).
2002-08-02 Paul D. Smith <psmith@gnu.org>
* LINGUAS: Add a new translation for Swedish (sv).
2002-04-21 Paul D. Smith <psmith@gnu.org>
* LINGUAS, hr.po: Added new translation: Croatian.
* da.po, de.po, es.po, fr.po, gl.po, he.po, ja.po, ko.po, nl.po,
pl.po, pt_BR.po, ru.po, tr.po: Moved from i18n to here.
* .cvsignore: Moved from i18n to here.
* POTFILES.in, LINGUAS, Makevars: Created.

5
po/LINGUAS Normal file
View File

@@ -0,0 +1,5 @@
# Set of available languages: 16 languages
da de es fr gl he hr ja ko nl pl pt_BR sv ru tr zh_CN
# Can't seem to get en@quot and en@boldquot to build properly?

25
po/Makevars Normal file
View File

@@ -0,0 +1,25 @@
# Makefile variables for PO directory in any package using GNU gettext.
# Usually the message domain is the same as the package name.
DOMAIN = $(PACKAGE)
# These two variables depend on the location of this directory.
subdir = po
top_builddir = ..
# These options get passed to xgettext.
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
# This is the copyright holder that gets inserted into the header of the
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
# package. (Note that the msgstr strings, extracted from the package's
# sources, belong to the copyright holder of the package.) Translators are
# expected to transfer the copyright for their translations to this person
# or entity, or to disclaim their copyright. The empty string stands for
# the public domain; in this case the translators are expected to disclaim
# their copyright.
COPYRIGHT_HOLDER = Free Software Foundation, Inc.
# This is the list of locale categories, beyond LC_MESSAGES, for which the
# message catalogs shall be used. It is usually empty.
EXTRA_LOCALE_CATEGORIES =

24
po/POTFILES.in Normal file
View File

@@ -0,0 +1,24 @@
# List of source files containing translatable strings.
# Copyright (C) 2002 Free Software Foundation, Inc.
ar.c
arscan.c
commands.c
dir.c
expand.c
file.c
function.c
getopt.c
hash.c
implicit.c
job.c
main.c
misc.c
read.c
remake.c
remote-cstms.c
rule.c
signame.c
variable.c
vmsfunctions.c
vpath.c

1710
read.c

File diff suppressed because it is too large Load Diff

247
remake.c
View File

@@ -1,5 +1,6 @@
/* Basic dependency engine for GNU Make.
Copyright (C) 1988,89,90,91,92,93,94,95,96,97,99 Free Software Foundation, Inc.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
2002 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
@@ -43,9 +44,24 @@ Boston, MA 02111-1307, USA. */
extern int try_implicit_rule PARAMS ((struct file *file, unsigned int depth));
/* The test for circular dependencies is based on the 'updating' bit in
`struct file'. However, double colon targets have seperate `struct
file's; make sure we always use the base of the double colon chain. */
#define start_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\
->updating = 1)
#define finish_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\
->updating = 0)
#define is_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\
->updating)
/* Incremented when a command is started (under -n, when one would be). */
unsigned int commands_started = 0;
/* Current value for pruning the scan of the goal chain (toggle 0/1). */
static unsigned int considered;
static int update_file PARAMS ((struct file *file, unsigned int depth));
static int update_file_1 PARAMS ((struct file *file, unsigned int depth));
static int check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr));
@@ -62,9 +78,6 @@ static int library_search PARAMS ((char **lib, FILE_TIMESTAMP *mtime_ptr));
should only make one goal at a time and return as soon as one goal whose
`changed' member is nonzero is successfully made. */
/* We need to know this "lower down" for correct error handling. */
static int updating_makefiles = 0;
int
update_goal_chain (goals, makefiles)
register struct dep *goals;
@@ -74,8 +87,6 @@ update_goal_chain (goals, makefiles)
unsigned int j = job_slots;
int status = -1;
updating_makefiles = makefiles;
#define MTIME(file) (makefiles ? file_mtime_no_search (file) \
: file_mtime (file))
@@ -287,7 +298,7 @@ update_file (file, depth)
if (f->considered == considered)
{
DBF (DB_VERBOSE, _("Pruning file `%s'.\n"));
return 0;
return f->command_state == cs_finished ? f->update_status : 0;
}
/* This loop runs until we start commands for a double colon rule, or until
@@ -373,7 +384,7 @@ update_file_1 (file, depth)
++depth;
/* Notice recursive update of the same file. */
file->updating = 1;
start_updating (file);
/* Looking at the file's modtime beforehand allows the possibility
that its name may be changed by a VPATH search, and thus it may
@@ -383,9 +394,19 @@ update_file_1 (file, depth)
this_mtime = file_mtime (file);
check_renamed (file);
noexist = this_mtime == (FILE_TIMESTAMP) -1;
noexist = this_mtime == NONEXISTENT_MTIME;
if (noexist)
DBF (DB_BASIC, _("File `%s' does not exist.\n"));
else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX
&& file->low_resolution_time)
{
/* Avoid spurious rebuilds due to low resolution time stamps. */
int ns = FILE_TIMESTAMP_NS (this_mtime);
if (ns != 0)
error (NILF, _("*** Warning: .LOW_RESOLUTION_TIME file `%s' has a high resolution time stamp"),
file->name);
this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns;
}
must_make = noexist;
@@ -415,13 +436,14 @@ update_file_1 (file, depth)
while (d != 0)
{
FILE_TIMESTAMP mtime;
int maybe_make;
check_renamed (d->file);
mtime = file_mtime (d->file);
check_renamed (d->file);
if (d->file->updating)
if (is_updating (d->file))
{
error (NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
@@ -437,7 +459,11 @@ update_file_1 (file, depth)
}
d->file->parent = file;
dep_status |= check_dep (d->file, depth, this_mtime, &must_make);
maybe_make = must_make;
dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make);
if (! d->ignore_mtime)
must_make = maybe_make;
check_renamed (d->file);
{
@@ -466,7 +492,7 @@ update_file_1 (file, depth)
/* Now we know whether this target needs updating.
If it does, update all the intermediate files we depend on. */
if (must_make)
if (must_make || always_make_flag)
{
for (d = file->deps; d != 0; d = d->next)
if (d->file->intermediate)
@@ -499,7 +525,7 @@ update_file_1 (file, depth)
}
}
file->updating = 0;
finish_updating (file);
DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n"));
@@ -518,7 +544,7 @@ update_file_1 (file, depth)
file->update_status = dep_status;
notice_finished_file (file);
depth--;
--depth;
DBF (DB_VERBOSE, _("Giving up on target file `%s'.\n"));
@@ -541,7 +567,7 @@ update_file_1 (file, depth)
file's bookkeeping (updated, but not_started is bogus state). */
set_command_state (file, cs_not_started);
/* Now record which dependencies are more
/* Now record which prerequisites are more
recent than this file, so we can define $?. */
deps_changed = 0;
@@ -550,17 +576,21 @@ update_file_1 (file, depth)
FILE_TIMESTAMP d_mtime = file_mtime (d->file);
check_renamed (d->file);
#if 1 /* %%% In version 4, remove this code completely to
if (! d->ignore_mtime)
{
#if 1
/* %%% In version 4, remove this code completely to
implement not remaking deps if their deps are newer
than their parents. */
if (d_mtime == (FILE_TIMESTAMP) -1 && !d->file->intermediate)
/* We must remake if this dep does not
exist and is not intermediate. */
must_make = 1;
if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate)
/* We must remake if this dep does not
exist and is not intermediate. */
must_make = 1;
#endif
/* Set DEPS_CHANGED if this dep actually changed. */
deps_changed |= d->changed;
/* Set DEPS_CHANGED if this dep actually changed. */
deps_changed |= d->changed;
}
/* Set D->changed if either this dep actually changed,
or its dependent, FILE, is older or does not exist. */
@@ -570,7 +600,12 @@ update_file_1 (file, depth)
{
const char *fmt = 0;
if (d_mtime == (FILE_TIMESTAMP) -1)
if (d->ignore_mtime)
{
if (ISDB (DB_VERBOSE))
fmt = _("Prerequisite `%s' is order-only for target `%s'.\n");
}
else if (d_mtime == NONEXISTENT_MTIME)
{
if (ISDB (DB_BASIC))
fmt = _("Prerequisite `%s' of target `%s' does not exist.\n");
@@ -601,12 +636,18 @@ update_file_1 (file, depth)
DBF (DB_BASIC,
_("Target `%s' is double-colon and has no prerequisites.\n"));
}
else if (!noexist && file->is_target && !deps_changed && file->cmds == 0)
else if (!noexist && file->is_target && !deps_changed && file->cmds == 0
&& !always_make_flag)
{
must_make = 0;
DBF (DB_VERBOSE,
_("No commands for `%s' and no prerequisites actually changed.\n"));
}
else if (!must_make && file->cmds != 0 && always_make_flag)
{
must_make = 1;
DBF (DB_VERBOSE, _("Making `%s' due to always-make flag.\n"));
}
if (!must_make)
{
@@ -686,6 +727,7 @@ notice_finished_file (file)
{
struct dep *d;
int ran = file->command_state == cs_running;
int touched = 0;
file->command_state = cs_finished;
file->updated = 1;
@@ -714,24 +756,36 @@ notice_finished_file (file)
if (file->phony)
file->update_status = 0;
else
/* Should set file's modification date and do nothing else. */
file->update_status = touch_file (file);
{
/* Should set file's modification date and do nothing else. */
file->update_status = touch_file (file);
/* Pretend we ran a real touch command, to suppress the
"`foo' is up to date" message. */
commands_started++;
/* Request for the timestamp to be updated (and distributed
to the double-colon entries). Simply setting ran=1 would
almost have done the trick, but messes up with the also_make
updating logic below. */
touched = 1;
}
}
}
if (file->mtime_before_update == 0)
if (file->mtime_before_update == UNKNOWN_MTIME)
file->mtime_before_update = file->last_mtime;
if (ran && !file->phony)
if ((ran && !file->phony) || touched)
{
struct file *f;
int i = 0;
/* If -n or -q and all the commands are recursive, we ran them so
/* If -n, -t, or -q and all the commands are recursive, we ran them so
really check the target's mtime again. Otherwise, assume the target
would have been updated. */
if (question_flag || just_print_flag)
if (question_flag || just_print_flag || touch_flag)
{
for (i = file->cmds->ncommand_lines; i > 0; --i)
if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE))
@@ -743,11 +797,11 @@ notice_finished_file (file)
else if (file->is_target && file->cmds == 0)
i = 1;
file->last_mtime = i == 0 ? 0 : NEW_MTIME;
file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME;
/* Propagate the change of modification time to all the double-colon
entries for this file. */
for (f = file->double_colon; f != 0; f = f->next)
for (f = file->double_colon; f != 0; f = f->prev)
f->last_mtime = file->last_mtime;
}
@@ -789,11 +843,11 @@ check_dep (file, depth, this_mtime, must_make_ptr)
FILE_TIMESTAMP this_mtime;
int *must_make_ptr;
{
register struct dep *d;
struct dep *d;
int dep_status = 0;
++depth;
file->updating = 1;
start_updating (file);
if (!file->intermediate)
/* If this is a non-intermediate file, update it and record
@@ -804,7 +858,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
check_renamed (file);
mtime = file_mtime (file);
check_renamed (file);
if (mtime == (FILE_TIMESTAMP) -1 || mtime > this_mtime)
if (mtime == NONEXISTENT_MTIME || mtime > this_mtime)
*must_make_ptr = 1;
}
else
@@ -832,20 +886,22 @@ check_dep (file, depth, this_mtime, must_make_ptr)
check_renamed (file);
mtime = file_mtime (file);
check_renamed (file);
if (mtime != (FILE_TIMESTAMP) -1 && mtime > this_mtime)
if (mtime != NONEXISTENT_MTIME && mtime > this_mtime)
*must_make_ptr = 1;
/* Otherwise, update all non-intermediate files we depend on,
if necessary, and see whether any of them is more
recent than the file on whose behalf we are checking. */
else
{
register struct dep *lastd;
struct dep *lastd;
lastd = 0;
d = file->deps;
while (d != 0)
{
if (d->file->updating)
int maybe_make;
if (is_updating (d->file))
{
error (NILF, _("Circular %s <- %s dependency dropped."),
file->name, d->file->name);
@@ -865,8 +921,11 @@ check_dep (file, depth, this_mtime, must_make_ptr)
}
d->file->parent = file;
maybe_make = *must_make_ptr;
dep_status |= check_dep (d->file, depth, this_mtime,
must_make_ptr);
&maybe_make);
if (! d->ignore_mtime)
*must_make_ptr = maybe_make;
check_renamed (d->file);
if (dep_status != 0 && !keep_going_flag)
break;
@@ -884,7 +943,7 @@ check_dep (file, depth, this_mtime, must_make_ptr)
}
}
file->updating = 0;
finish_updating (file);
return dep_status;
}
@@ -913,13 +972,8 @@ touch_file (file)
{
struct stat statbuf;
char buf;
int status;
do
status = fstat (fd, &statbuf);
while (status < 0 && EINTR_SET);
if (status < 0)
if (fstat (fd, &statbuf) < 0)
TOUCH_ERROR ("touch: fstat: ");
/* Rewrite character 0 same as it already is. */
if (read (fd, &buf, 1) < 0)
@@ -1032,6 +1086,7 @@ f_mtime (file, search)
char *arname, *memname;
struct file *arfile;
int arname_used = 0;
time_t member_date;
/* Find the archive's name. */
ar_parse_name (file->name, &arname, &memname);
@@ -1086,18 +1141,23 @@ f_mtime (file, search)
free (arname);
free (memname);
if (mtime == (FILE_TIMESTAMP) -1)
/* The archive doesn't exist, so it's members don't exist either. */
return (FILE_TIMESTAMP) -1;
file->low_resolution_time = 1;
mtime = ar_member_date (file->hname);
if (mtime == NONEXISTENT_MTIME)
/* The archive doesn't exist, so its members don't exist either. */
return NONEXISTENT_MTIME;
member_date = ar_member_date (file->hname);
mtime = (member_date == (time_t) -1
? NONEXISTENT_MTIME
: file_timestamp_cons (file->hname, member_date, 0));
}
else
#endif
{
mtime = name_mtime (file->name);
if (mtime == (FILE_TIMESTAMP) -1 && search && !file->ignore_vpath)
if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
{
/* If name_mtime failed, search VPATH. */
char *name = file->name;
@@ -1106,8 +1166,8 @@ f_mtime (file, search)
|| (name[0] == '-' && name[1] == 'l'
&& library_search (&name, &mtime)))
{
if (mtime != 0)
/* vpath_search and library_search store zero in MTIME
if (mtime != UNKNOWN_MTIME)
/* vpath_search and library_search store UNKNOWN_MTIME
if they didn't need to do a stat call for their work. */
file->last_mtime = mtime;
@@ -1135,41 +1195,47 @@ f_mtime (file, search)
We only need to do this once, for now. */
static FILE_TIMESTAMP now = 0;
if (!clock_skew_detected
&& mtime != (FILE_TIMESTAMP)-1 && mtime > now
&& !file->updated)
&& mtime != NONEXISTENT_MTIME
&& !file->updated)
{
/* This file's time appears to be in the future.
Update our concept of the present, and compare again. */
static FILE_TIMESTAMP adjusted_now;
now = file_timestamp_now ();
FILE_TIMESTAMP adjusted_mtime = mtime;
#ifdef WINDOWS32
/*
* FAT filesystems round time to nearest even second(!). Just
* allow for any file (NTFS or FAT) to perhaps suffer from this
* braindamage.
*/
if (mtime > now && (((mtime % 2) == 0) && ((mtime-1) > now)))
#else
#ifdef __MSDOS__
/* Scrupulous testing indicates that some Windows
filesystems can set file times up to 3 sec into the future! */
if (mtime > now + 3)
#else
if (mtime > now)
#if defined(WINDOWS32) || defined(__MSDOS__)
/* Experimentation has shown that FAT filesystems can set file times
up to 3 seconds into the future! Play it safe. */
#define FAT_ADJ_OFFSET (FILE_TIMESTAMP) 3
FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
adjusted_mtime -= adjustment;
#endif
#endif
{
char mtimebuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
char nowbuf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
file_timestamp_sprintf (mtimebuf, mtime);
file_timestamp_sprintf (nowbuf, now);
error (NILF, _("*** Warning: File `%s' has modification time in the future (%s > %s)"),
file->name, mtimebuf, nowbuf);
clock_skew_detected = 1;
/* If the file's time appears to be in the future, update our
concept of the present and try once more. */
if (adjusted_now < adjusted_mtime)
{
int resolution;
FILE_TIMESTAMP now = file_timestamp_now (&resolution);
adjusted_now = now + (resolution - 1);
if (adjusted_now < adjusted_mtime)
{
#ifdef NO_FLOAT
error (NILF, _("Warning: File `%s' has modification time in the future"),
file->name);
#else
double from_now =
(FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
+ ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
/ 1e9));
error (NILF, _("Warning: File `%s' has modification time %.2g s in the future"),
file->name, from_now);
#endif
clock_skew_detected = 1;
}
}
}
}
@@ -1185,7 +1251,8 @@ f_mtime (file, search)
been built by us but was found now, it existed before make
started. So, turn off the intermediate bit so make doesn't
delete it, since it didn't create it. */
if (mtime != (FILE_TIMESTAMP)-1 && file->command_state == cs_not_started
if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started
&& file->command_state == cs_not_started
&& !file->tried_implicit && file->intermediate)
file->intermediate = 0;
@@ -1206,10 +1273,14 @@ name_mtime (name)
{
struct stat st;
if (stat (name, &st) < 0)
return (FILE_TIMESTAMP) -1;
if (stat (name, &st) != 0)
{
if (errno != ENOENT && errno != ENOTDIR)
perror_with_name ("stat:", name);
return NONEXISTENT_MTIME;
}
return FILE_TIMESTAMP_STAT_MODTIME (st);
return FILE_TIMESTAMP_STAT_MODTIME (name, st);
}
@@ -1295,7 +1366,7 @@ library_search (lib, mtime_ptr)
/* Look first for `libNAME.a' in the current directory. */
mtime = name_mtime (libbuf);
if (mtime != (FILE_TIMESTAMP) -1)
if (mtime != NONEXISTENT_MTIME)
{
*lib = xstrdup (libbuf);
if (mtime_ptr != 0)
@@ -1335,7 +1406,7 @@ library_search (lib, mtime_ptr)
{
sprintf (buf, "%s/%s", *dp, libbuf);
mtime = name_mtime (buf);
if (mtime != (FILE_TIMESTAMP) -1)
if (mtime != NONEXISTENT_MTIME)
{
*lib = xstrdup (buf);
if (mtime_ptr != 0)

View File

@@ -83,7 +83,7 @@ start_remote_job_p (first_p)
Customs requires a privileged source port be used. */
make_access ();
if (ISDB (DB_EXTRA))
if (ISDB (DB_JOBS))
Rpc_Debug(1);
/* Ping the daemon once to see if it is there. */
@@ -124,8 +124,8 @@ start_remote_job_p (first_p)
status = Customs_Host (EXPORT_SAME, &permit);
if (status != RPC_SUCCESS)
{
DB (DB_EXTRA, (_("Customs won't export: %s\n"),
Rpc_ErrorMessage (status)));
DB (DB_JOBS, (_("Customs won't export: %s\n"),
Rpc_ErrorMessage (status)));
return 0;
}

3
rule.c
View File

@@ -230,6 +230,7 @@ convert_suffix_rule (target, source, cmds)
deps = (struct dep *) xmalloc (sizeof (struct dep));
deps->next = 0;
deps->name = depname;
deps->ignore_mtime = 0;
}
create_pattern_rule (names, percents, 0, deps, cmds, 0);
@@ -653,7 +654,7 @@ print_rule_data_base ()
register unsigned int rules, terminal;
register struct rule *r;
puts ("\n# Implicit Rules");
puts (_("\n# Implicit Rules"));
rules = terminal = 0;
for (r = pattern_rules; r != 0; r = r->next)

138
signame.c
View File

@@ -1,26 +1,33 @@
/* Convert between signal names and numbers.
Copyright (C) 1990,92,93,95,96,99 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Copyright (C) 1990,92,93,95,96,99, 2002 Free Software Foundation, Inc.
This file was part of the GNU C Library, but is now part of GNU make.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
GNU Make is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
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 Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
You should have received a copy of the GNU General Public License
along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* In the GNU make version, all the headers we need are provided by make.h. */
#include "make.h"
/* If the system provides strsignal, we don't need it. */
#if !defined(HAVE_STRSIGNAL)
/* If the system provides sys_siglist, we'll use that.
Otherwise create our own.
*/
#if !defined(SYS_SIGLIST_DECLARED)
/* Some systems do not define NSIG in <signal.h>. */
#ifndef NSIG
@@ -31,27 +38,12 @@
#endif
#endif
#if !__STDC__
#define const
#endif
#include "signame.h"
#ifndef HAVE_SYS_SIGLIST
/* There is too much variation in Sys V signal numbers and names, so
we must initialize them at runtime. */
static const char *undoc;
const char *sys_siglist[NSIG];
#else /* HAVE_SYS_SIGLIST. */
#ifndef SYS_SIGLIST_DECLARED
extern char *sys_siglist[];
#endif /* Not SYS_SIGLIST_DECLARED. */
#endif /* Not HAVE_SYS_SIGLIST. */
static const char *sys_siglist[NSIG];
/* Table of abbreviations for signals. Note: A given number can
appear more than once with different abbreviations. */
@@ -62,7 +54,9 @@ typedef struct
int number;
const char *abbrev;
} num_abbrev;
static num_abbrev sig_table[SIG_TABLE_SIZE];
/* Number of elements of sig_table used. */
static int sig_table_nelts = 0;
@@ -74,14 +68,13 @@ init_sig (number, abbrev, name)
const char *abbrev;
const char *name;
{
#ifndef HAVE_SYS_SIGLIST
/* If this value is ever greater than NSIG it seems like it'd be a bug in
the system headers, but... better safe than sorry. We know, for
example, that this isn't always true on VMS. */
if (number >= 0 && number < NSIG)
sys_siglist[number] = name;
#endif
if (sig_table_nelts < SIG_TABLE_SIZE)
{
sig_table[sig_table_nelts].number = number;
@@ -89,19 +82,16 @@ init_sig (number, abbrev, name)
}
}
void
static int
signame_init ()
{
#ifndef HAVE_SYS_SIGLIST
int i;
char *u = _("unknown signal");
undoc = xstrdup(u);
undoc = xstrdup (_("unknown signal"));
/* Initialize signal names. */
for (i = 0; i < NSIG; i++)
sys_siglist[i] = undoc;
#endif /* !HAVE_SYS_SIGLIST */
/* Initialize signal names. */
#if defined (SIGHUP)
@@ -235,66 +225,12 @@ signame_init ()
#if defined (SIGNOFP)
init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available"));
#endif
return 1;
}
/* Return the abbreviation for signal NUMBER. */
#endif /* SYS_SIGLIST_DECLARED */
char *
sig_abbrev (number)
int number;
{
int i;
if (sig_table_nelts == 0)
signame_init ();
for (i = 0; i < sig_table_nelts; i++)
if (sig_table[i].number == number)
return (char *)sig_table[i].abbrev;
return NULL;
}
/* Return the signal number for an ABBREV, or -1 if there is no
signal by that name. */
int
sig_number (abbrev)
const char *abbrev;
{
int i;
if (sig_table_nelts == 0)
signame_init ();
/* Skip over "SIG" if present. */
if (abbrev[0] == 'S' && abbrev[1] == 'I' && abbrev[2] == 'G')
abbrev += 3;
for (i = 0; i < sig_table_nelts; i++)
if (abbrev[0] == sig_table[i].abbrev[0]
&& strcmp (abbrev, sig_table[i].abbrev) == 0)
return sig_table[i].number;
return -1;
}
#ifndef HAVE_PSIGNAL
/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
a colon, and followed by a newline. */
void
psignal (signal, message)
int signal;
const char *message;
{
if (signal <= 0 || signal >= NSIG)
fprintf (stderr, "%s: unknown signal", message);
else
fprintf (stderr, "%s: %s\n", message, sys_siglist[signal]);
}
#endif
#ifndef HAVE_STRSIGNAL
/* Return the string associated with the signal number. */
char *
strsignal (signal)
@@ -302,10 +238,18 @@ strsignal (signal)
{
static char buf[] = "Signal 12345678901234567890";
#if !defined(SYS_SIGLIST_DECLARED)
static char sig_initted = 0;
if (!sig_initted)
sig_initted = signame_init ();
#endif
if (signal > 0 || signal < NSIG)
return (char *) sys_siglist[signal];
sprintf (buf, "Signal %d", signal);
return buf;
}
#endif
#endif /* HAVE_STRSIGNAL */

View File

@@ -1,67 +0,0 @@
/* Convert between signal names and numbers.
Copyright (C) 1990, 1992, 1993, 1995, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#if defined (__STDC__) && __STDC__
/* Initialize `sys_siglist'. */
void signame_init (void);
/* Return the abbreviation (e.g. ABRT, FPE, etc.) for signal NUMBER.
Do not return this as a const char *. The caller might want to
assign it to a char *. */
char *sig_abbrev (int number);
/* Return the signal number for an ABBREV, or -1 if there is no
signal by that name. */
int sig_number (const char *abbrev);
/* Avoid conflicts with a system header file that might define these three. */
#ifndef HAVE_PSIGNAL
/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
a colon, and followed by a newline. */
void psignal (int signal, const char *message);
#endif
#ifndef HAVE_STRSIGNAL
/* Return the name of SIGNAL. */
char *strsignal (int signal);
#endif
#if !defined (HAVE_SYS_SIGLIST)
/* Names for signals from 0 to NSIG-1. */
extern const char *sys_siglist[];
#endif
#else
void signame_init ();
char *sig_abbrev ();
int sig_number ();
#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_PSIGNAL)
void psignal ();
#endif
#ifndef HAVE_STRSIGNAL
char *strsignal ();
#endif
#if !defined (HAVE_SYS_SIGLIST)
extern char *sys_siglist[];
#endif
#endif

1
tests/.cvsignore Normal file
View File

@@ -0,0 +1 @@
work

View File

@@ -1,11 +1,206 @@
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
<http://developer.kde.org/~sewardj/>. 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 PR/1407.
* 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 porting order, etc. is predictable.
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
@@ -17,6 +212,11 @@
* 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
@@ -27,7 +227,7 @@
* 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 infinitely looping.
invoke foreach from it without looping forever.
1999-12-15 Paul D. Smith <psmith@gnu.org>

View File

@@ -11,11 +11,16 @@
# [-make <make prog>]
# (and others)
$valgrind = 0; # invoke make with valgrind
require "test_driver.pl";
#$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; };
sub valid_option
{
local($option) = @_;
if ($option =~ /^-make([-_]?path)?$/)
{
$make_path = shift @argv;
@@ -27,6 +32,11 @@ sub valid_option
return 1;
}
if ($option =~ /^-valgrind$/i) {
$valgrind = 1;
return 1;
}
# This doesn't work--it _should_! Someone needs to fix this badly.
#
# elsif ($option =~ /^-work([-_]?dir)?$/)
@@ -56,6 +66,10 @@ sub run_make_with_options
$command .= " $options";
}
if ($valgrind) {
print VALGRIND "\n\nExecuting: $command\n";
}
$code = &run_command_with_output($logname,$command);
# Check to see if we have Purify errors. If so, keep the logfile.
@@ -81,6 +95,11 @@ sub run_make_with_options
{
print "Error running $make_path ($code): $command\n";
$test_passed = 0;
# If it's a SIGINT, stop here
if ($code & 127) {
print STDERR "\nCaught signal ".($code & 127)."!\n";
exit($code);
}
return 0;
}
@@ -215,6 +234,21 @@ sub set_more_defaults
else {
$parallel_jobs = 1;
}
# Set up for valgrind, if requested.
if ($valgrind) {
# use POSIX qw(:fcntl_h);
# require Fcntl;
open(VALGRIND, "> valgrind.out")
|| die "Cannot open valgrind.out: $!\n";
# -q --leak-check=yes
$make_path = "valgrind --num-callers=15 --logfile-fd=".fileno(VALGRIND)." $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

View File

@@ -51,7 +51,6 @@ close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile,0);
# Create the answer to what should be produced by this Makefile
$answer = "arg1 NOT equal arg2
arg2 equals arg5
arg3 NOT equal arg4
@@ -59,9 +58,43 @@ variable is undefined
arg4 is defined
";
# COMPARE RESULTS
&compare_output($answer,&get_logfile(1));
# Test expansion of variables inside ifdef.
$makefile2 = &get_tmpfile;
open(MAKEFILE, "> $makefile2");
print MAKEFILE <<'EOF';
foo = 1
FOO = foo
F = f
DEF = no
DEF2 = no
ifdef $(FOO)
DEF = yes
endif
ifdef $(F)oo
DEF2 = yes
endif
all:; @echo DEF=$(DEF) DEF2=$(DEF2)
EOF
close(MAKEFILE)
&run_make_with_options($makefile2,"",&get_logfile,0);
$answer = "DEF=yes DEF2=yes\n";
&compare_output($answer,&get_logfile(1));
# This tells the test driver that the perl test script executed properly.
1;

View File

@@ -36,6 +36,9 @@ two: ; @echo two
f1.h f2.h: ; @echo $@
d :: ; @echo ok
d :: d ; @echo oops
EOF
close(MAKEFILE);
@@ -48,9 +51,11 @@ $answer = "aaa\nbbb\n";
# TEST 1: As above, in parallel
&run_make_with_options($makefile, "-j10 all", &get_logfile, 0);
$answer = "aaa\nbbb\n";
&compare_output($answer, &get_logfile(1));
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
@@ -60,13 +65,15 @@ $answer = "aaa\naaa done\nbbb\n";
# TEST 3: As above, in parallel
&run_make_with_options($makefile, "-j10 bar", &get_logfile, 0);
$answer = "aaa\naaa done\nbbb\n";
&compare_output($answer, &get_logfile(1));
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
&touch('f2.h');
&utouch(-5, 'f2.h');
&touch('foo');
&run_make_with_options($makefile, "foo", &get_logfile, 0);
@@ -75,13 +82,15 @@ $answer = "f1.h\nfoo FIRST\n";
# TEST 5: Again, in parallel.
&run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
$answer = "f1.h\nfoo FIRST\n";
&compare_output($answer, &get_logfile(1));
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
&touch('f1.h');
&utouch(-5, 'f1.h');
unlink('f2.h');
&touch('foo');
@@ -91,17 +100,27 @@ $answer = "f2.h\nfoo SECOND\n";
# TEST 7: Again, in parallel.
&run_make_with_options($makefile, "-j10 foo", &get_logfile, 0);
$answer = "f2.h\nfoo SECOND\n";
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?
#
#&run_make_with_options($makefile, "-j10 biz", &get_logfile, 0);
#$answer = "aaa\ntwo\nbbb\n";
#&compare_output($answer, &get_logfile(1));
#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');

View File

@@ -1,11 +1,21 @@
# -*-perl-*-
$description = "Test various types of escaping in makefiles.";
$details = "Make sure that escaping of `:' works in target names.";
$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.";
open(MAKEFILE,"> $makefile");
print MAKEFILE '$(path)foo : ; @echo cp $^ $@
';
print MAKEFILE <<'EOF';
$(path)foo : ; @echo cp $^ $@
foo\ bar: ; @echo 'touch "$@"'
sharp: foo\#bar.ext
foo\#bar.ext: ; @echo foo\#bar.ext = '$@'
EOF
close(MAKEFILE);
@@ -34,5 +44,17 @@ $answer = "cp p:foo\n";
$answer = "$makefile:1: *** target pattern contains no `%'. Stop.\n";
&compare_output($answer,&get_logfile(1));
# TEST 5: This one should work
&run_make_with_options($makefile, "'foo bar'", &get_logfile, 0);
$answer = "touch \"foo bar\"\n";
&compare_output($answer,&get_logfile(1));
# TEST 6: Test escaped comments
&run_make_with_options($makefile, "sharp", &get_logfile, 0);
$answer = "foo#bar.ext = foo#bar.ext\n";
&compare_output($answer,&get_logfile(1));
# This tells the test driver that the perl test script executed properly.
1;

View File

@@ -0,0 +1,250 @@
# -*-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.
open(MAKEFILE,"> $makefile");
# The Contents of the MAKEFILE ...
print MAKEFILE <<'EOMAKE';
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"
EOMAKE
close(MAKEFILE);
# TEST 0: basics
&run_make_with_options($makefile,"",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
# TEST 1: make sure vars inherited from the parent are exported
$ENV{FOO} = 1;
&run_make_with_options($makefile,"",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
delete $ENV{FOO};
# TEST 2: global export. Explicit unexport takes precedence.
&run_make_with_options($makefile,"EXPORT_ALL=1",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
# TEST 3: global unexport. Explicit export takes precedence.
&run_make_with_options($makefile,"UNEXPORT_ALL=1",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
# TEST 4: both: in the above makefile the unexport comes last so that rules.
&run_make_with_options($makefile,"EXPORT_ALL=1 UNEXPORT_ALL=1",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
# TEST 5: test the pseudo target.
&run_make_with_options($makefile,"EXPORT_ALL_PSEUDO=1",&get_logfile,0);
$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz
FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n";
&compare_output($answer,&get_logfile(1));
# TEST 6: Test the expansion of variables inside export
$makefile2 = &get_tmpfile;
open(MAKEFILE, "> $makefile2");
print MAKEFILE <<'EOF';
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
EOF
close(MAKEFILE);
&run_make_with_options($makefile2,"",&get_logfile,0);
$answer = "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n";
&compare_output($answer,&get_logfile(1));
# TEST 7: Test the expansion of variables inside unexport
$makefile3 = &get_tmpfile;
open(MAKEFILE, "> $makefile3");
print MAKEFILE <<'EOF';
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
EOF
close(MAKEFILE);
&run_make_with_options($makefile3,"",&get_logfile,0);
$answer = "foo=f-ok bar=b-ok\nfoo= bar=\n";
&compare_output($answer,&get_logfile(1));
# TEST 7: Test exporting multiple variables on the same line
$makefile4 = &get_tmpfile;
open(MAKEFILE, "> $makefile4");
print MAKEFILE <<'EOF';
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
EOF
close(MAKEFILE);
&run_make_with_options($makefile4,"",&get_logfile,0);
$answer = "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n";
&compare_output($answer,&get_logfile(1));
# TEST 8: Test unexporting multiple variables on the same line
$makefile5 = &get_tmpfile;
open(MAKEFILE, "> $makefile5");
print MAKEFILE <<'EOF';
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
EOF
close(MAKEFILE);
@ENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10);
&run_make_with_options($makefile5,"",&get_logfile,0);
$answer = "A= B= C= D= E= F= G= H= I= J=\n";
&compare_output($answer,&get_logfile(1));
delete @ENV{qw(A B C D E F G H I J)};
# This tells the test driver that the perl test script executed properly.
1;

View File

@@ -0,0 +1,112 @@
# -*-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.";
open(MAKEFILE,"> $makefile");
print MAKEFILE <<'EOF';
foo: bar | baz
@echo '$$^ = $^'
@echo '$$| = $|'
touch $@
.PHONY: baz
bar baz:
touch $@
EOF
close(MAKEFILE);
# TEST #1 -- just the syntax
&run_make_with_options($makefile, "", &get_logfile);
$answer = "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n";
&compare_output($answer,&get_logfile(1));
# TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated
&run_make_with_options($makefile, "", &get_logfile);
$answer = "touch baz\n";
&compare_output($answer,&get_logfile(1));
unlink(qw(foo bar baz));
# Test prereqs that are both order and non-order
$makefile2 = &get_tmpfile;
open(MAKEFILE,"> $makefile2");
print MAKEFILE <<'EOF';
foo: bar | baz
@echo '$$^ = $^'
@echo '$$| = $|'
touch $@
foo: baz
.PHONY: baz
bar baz:
touch $@
EOF
close(MAKEFILE);
# TEST #3 -- Make sure the order-only prereq was promoted to normal.
&run_make_with_options($makefile2, "", &get_logfile);
$answer = "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
&compare_output($answer,&get_logfile(1));
# TEST #4 -- now we do it again
&run_make_with_options($makefile2, "", &get_logfile);
$answer = "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n";
&compare_output($answer,&get_logfile(1));
unlink(qw(foo bar baz));
# Test empty normal prereqs
$makefile3 = &get_tmpfile;
open(MAKEFILE,"> $makefile3");
print MAKEFILE <<'EOF';
foo:| baz
@echo '$$^ = $^'
@echo '$$| = $|'
touch $@
.PHONY: baz
baz:
touch $@
EOF
close(MAKEFILE);
# TEST #5 -- make sure the parser was correct.
&run_make_with_options($makefile3, "", &get_logfile);
$answer = "touch baz\n\$^ = \n\$| = baz\ntouch foo\n";
&compare_output($answer,&get_logfile(1));
# TEST #6 -- now we do it again: this time foo won't be built
&run_make_with_options($makefile3, "", &get_logfile);
$answer = "touch baz\n";
&compare_output($answer,&get_logfile(1));
unlink(qw(foo baz));
1;

View File

@@ -26,13 +26,8 @@ EOM
close(MAKEFILE);
&touch($makefile2);
# Sleep 2 seconds for DOS/Windows FAT volumes which have 2-second
# granularity of file times.
sleep(2);
&touch("$makefile_orig");
&utouch(-10, $makefile, $makefile2);
&touch($makefile_orig);
&run_make_with_options($makefile, "", &get_logfile, 0);
@@ -65,8 +60,8 @@ EOM
close(MAKEFILE);
&touch('a','b');
sleep(2);
&utouch(-20, 'b','a');
#&utouch(-10, 'a');
&touch('c');
# First try with the file that's not updated "once removed" from the

View File

@@ -1,66 +1,67 @@
$description = "The following test creates a makefile to test static \n"
."pattern rules. Static pattern rules are rules which \n"
."specify multiple targets and construct the dependency \n"
."names for each target based on the target name. ";
# -*-perl-*-
$description = "Test handling of static pattern rules.";
$details = "The makefile created in this test has three targets. The \n"
."filter command is used to get those target names ending in \n"
.".o and statically creates a compile command with the target\n"
."name and the target name with .c. It also does the same thing\n"
."for another target filtered with .elc and creates a command\n"
."to emacs a .el file";
$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";
open(MAKEFILE,"> $makefile");
print MAKEFILE <<'EOF';
files = foo.elc bar.o lose.o
# The Contents of the MAKEFILE ...
print MAKEFILE "files = foo.elc bar.o lose.o \n\n"
."\$(filter %.o,\$(files)): %.o: %.c\n"
."\t\@echo CC -c \$(CFLAGS) \$< -o \$@ \n"
."\$(filter %.elc,\$(files)): %.elc: %.el \n"
."\t\@echo emacs \$< \n";
# END of Contents of MAKEFILE
$(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $<
EOF
close(MAKEFILE);
&touch("bar.c","lose.c");
&touch('bar.c', 'lose.c');
# TEST #1
# -------
&run_make_with_options($makefile,
"",
&get_logfile,
0);
# Create the answer to what should be produced by this Makefile
&run_make_with_options($makefile, '', &get_logfile);
$answer = "CC -c bar.c -o bar.o\n";
&compare_output($answer,&get_logfile(1));
&compare_output($answer, &get_logfile(1));
# TEST #2
# -------
&run_make_with_options($makefile,"lose.o",&get_logfile);
&run_make_with_options($makefile, 'lose.o', &get_logfile);
$answer = "CC -c lose.c -o lose.o\n";
&compare_output($answer,&get_logfile(1));
&compare_output($answer, &get_logfile(1));
# TEST #3
# -------
&touch("foo.el");
&run_make_with_options($makefile,"foo.elc",&get_logfile);
&run_make_with_options($makefile, 'foo.elc', &get_logfile);
$answer = "emacs foo.el\n";
&compare_output($answer,&get_logfile(1));
&compare_output($answer, &get_logfile(1));
unlink('foo.el', 'bar.c', 'lose.c');
# TEST #4 -- PR/1670: don't core dump on invalid static pattern rules
# -------
$makefile2 = &get_tmpfile;
open(MAKEFILE, "> $makefile2");
print MAKEFILE "foo: foo%: % ; \@echo $@\n";
close(MAKEFILE);
&run_make_with_options($makefile2, '', &get_logfile, 512);
$answer = "$makefile2:1: *** target `foo' leaves prerequisite pattern empty. Stop.\n";
&compare_output($answer, &get_logfile(1));
unlink("foo.el","bar.c","lose.c");
1;

View File

@@ -126,6 +126,7 @@ $answer = "foo bar\n";
# TEST #9
# For PR/1380: Using += assignment in target-specific variables sometimes fails
# Also PR/1831
$makefile3 = &get_tmpfile;
@@ -138,16 +139,104 @@ all: one; @echo $(FOO)
FOO = bar
one: FOO += biz
one: FOO += boz
one: ; @echo $(FOO)
EOF
close(MAKEFILE);
&run_make_with_options("$makefile3", "", &get_logfile);
$answer = "bar baz biz\nbar baz\n";
$answer = "bar baz biz boz\nbar baz\n";
&compare_output($answer, &get_logfile(1));
# Test #10
&run_make_with_options("$makefile3", "one", &get_logfile);
$answer = "bar biz\n";
$answer = "bar biz boz\n";
&compare_output($answer, &get_logfile(1));
# Test #11
# PR/1709: Test semicolons in target-specific variable values
$makefile4 = &get_tmpfile;
open(MAKEFILE, "> $makefile4");
print MAKEFILE <<'EOF';
foo : FOO = ; ok
foo : ; @echo '$(FOO)'
EOF
close(MAKEFILE);
&run_make_with_options("$makefile4", "", &get_logfile);
$answer = "; ok\n";
&compare_output($answer, &get_logfile(1));
# Test #12
# PR/2020: More hassles with += target-specific vars. I _really_ think
# I nailed it this time :-/.
$makefile5 = &get_tmpfile;
open(MAKEFILE, "> $makefile5");
print MAKEFILE <<'EOF';
.PHONY: a
BLAH := foo
COMMAND = echo $(BLAH)
a: ; @$(COMMAND)
a: BLAH := bar
a: COMMAND += snafu $(BLAH)
EOF
close(MAKEFILE);
&run_make_with_options("$makefile5", "", &get_logfile);
$answer = "bar snafu bar\n";
&compare_output($answer, &get_logfile(1));
# Test #13
# Test double-colon rules with target-specific variable values
$makefile6 = &get_tmpfile;
open(MAKEFILE, "> $makefile6");
print MAKEFILE <<'EOF';
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
EOF
close(MAKEFILE);
&run_make_with_options("$makefile6", "foo", &get_logfile);
$answer = "ok ok foo nopat\nok ok foo nopat\n";
&compare_output($answer, &get_logfile(1));
# Test #14
# Test double-colon rules with target-specific variable values and
# inheritance
&run_make_with_options("$makefile6", "bar", &get_logfile);
$answer = "ok ok bar nopat\nok ok bar nopat\n";
&compare_output($answer, &get_logfile(1));
# Test #15
# Test double-colon rules with pattern-specific variable values
&run_make_with_options("$makefile6", "foo PATTERN=yes", &get_logfile);
$answer = "ok ok foo pat\nok ok foo pat\n";
&compare_output($answer, &get_logfile(1));

View File

@@ -38,12 +38,14 @@ close(MAKEFILE);
@touchedfiles = ();
$off = -500;
sub touchfiles {
foreach (@_) {
($f = $_) =~ s,VP/,$VP,g;
&touch($f);
&utouch($off, $f);
$off += 10;
push(@touchedfiles, $f);
sleep(1);
}
}

View File

@@ -55,18 +55,19 @@ close(MAKEFILE);
@touchedfiles = ();
$off = -500;
sub touchfiles {
foreach (@_) {
sleep($wtime);
($f = $_) =~ s,VP/,$VP,g;
&touch($f);
push(@touchedfiles, $f);
&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");
&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);
@@ -79,7 +80,7 @@ cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1
# Test rules that don't make the target correctly
&touchfiles("VP/notarget.c", "notarget.b", "notarget.d");
&touchfiles("$VP/notarget.c", "notarget.b", "notarget.d");
&run_make_with_options($makefile,"notarget",&get_logfile,512);
@@ -92,7 +93,7 @@ $make_name: *** [notarget.b] Error 1
# Test intermediate file handling (part 1)
&touchfiles("VP/inter.d");
&touchfiles("$VP/inter.d");
&run_make_with_options($makefile,"intermediate",&get_logfile);
@@ -107,7 +108,11 @@ rm inter.b inter.c
# Test intermediate file handling (part 2)
&touchfiles("VP/inter.b", "VP/inter.d");
&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);

View File

@@ -1,44 +1,36 @@
$description = "The following test creates a makefile to test the addsuffix "
."function.";
# -*-perl-*-
$description = "Test the addsuffix 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 := \$(addsuffix .c,src${pathsep}a.b.z.foo hacks) \n"
."all: \n"
."\t\@echo \$(string) \n";
print MAKEFILE <<EOMAKE;
string := \$(addsuffix .c,src${pathsep}a.b.z.foo hacks)
one: ; \@echo \$(string)
# END of Contents of MAKEFILE
two: ; \@echo \$(addsuffix foo,)
EOMAKE
close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile,0);
# Create the answer to what should be produced by this Makefile
# TEST 0
&run_make_with_options($makefile, "", &get_logfile);
$answer = "src${pathsep}a.b.z.foo.c hacks.c\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));
# 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;

View File

@@ -26,23 +26,47 @@ my-notdir = $(call notdir,$(1))
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-foreach,a,x y z,$(a)$(a))'; \
echo '$(call my-if,a,b,c)'; \
echo '$(call my-if,,$(warning don't print this),ok)'
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\nxx yy zz\nb\nok\n";
$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));
1;

View File

@@ -0,0 +1,60 @@
# -*-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));
1;

View File

@@ -1,35 +1,28 @@
$description = "The following test creates a makefile to test static \n"
."pattern rules. Static pattern rules are rules which \n"
."specify multiple targets and construct the dependency \n"
."names for each target based on the target name. ";
# -*-perl-*-
$details = "The makefile created in this test has three targets. The \n"
."filter command is used to get those target names ending in \n"
.".o and statically creates a compile command with the target\n"
."name and the target name with .c. It also does the same thing\n"
."for another target filtered with .elc and creates a command\n"
."to emacs a .el file";
$description = "Test the filter-out function.";
$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";
open(MAKEFILE,"> $makefile");
# The Contents of the MAKEFILE ...
print MAKEFILE "files := \$(filter-out %.o, foo.elc bar.o lose.o) \n"
."all: \n"
."\t\@echo \$(files) \n";
# END of Contents of MAKEFILE
print MAKEFILE <<'EOF';
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)
EOF
close(MAKEFILE);
&run_make_with_options($makefile,
"",
&get_logfile,
0);
# Create the answer to what should be produced by this Makefile
$answer = "foo.elc\n";
&run_make_with_options($makefile, "", &get_logfile, 0);
$answer = "foo.elc foo.elc\n";
&compare_output($answer,&get_logfile(1));
1;

View File

@@ -34,6 +34,8 @@ all:
@echo '$(strip $(TEST2) )'
@echo '$(strip $(TEST3) )'
space: ; @echo '$(strip ) $(strip )'
EOMAKE
# END of Contents of MAKEFILE
@@ -41,13 +43,15 @@ EOMAKE
close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile);
# Create the answer to what should be produced by this Makefile
$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;

View File

@@ -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;

View File

@@ -1,16 +1,17 @@
# -*-perl-*-
$description = "The following test creates a makefile to test wildcard\n"
."expansions and the ability to put a command on the same\n"
."line as the target name separated by a semi-colon.";
$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, \n"
."two.example and 3.example. We execute three tests. The first\n"
."executes the print1 target which tests the '*' wildcard by \n"
."echoing all filenames by the name of '*.example'. The second\n"
."test echo's all files which match '?.example' and \n"
."[a-z0-9].example. Lastly we clean up all of the files using\n"
."the '*' wildcard as in the first test";
$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";
if ($vos)
{
@@ -27,6 +28,7 @@ open(MAKEFILE,"> $makefile");
# The Contents of the MAKEFILE ...
print MAKEFILE <<EOM;
.PHONY: print1 print2 clean
print1: ;\@echo \$(wildcard example.*)
print2:
\t\@echo \$(wildcard example.?)

View File

@@ -1,33 +1,33 @@
$description = "The following test creates a makefile to test the word, words,\n"
."and wordlist functions.\n";
# -*-perl-*-
$description = "Test the word, words, and wordlist functions.\n";
$details = "The word function will return the number of words in a variable or\n"
."the word specified. The test will produce a variable with a large\n"
."number of words in it, determine the number of word and then read\n"
."each one back.\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");
# The Contents of the MAKEFILE ...
print MAKEFILE "string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl \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 \$(words \$(string)) \n"
."\t\@echo \$(words \$(string4)) \n"
."\t\@echo \$(word 1, \$(string)) \n"
."\t\@echo \$(word 100, \$(string)) \n"
."\t\@echo \$(word 1, \$(string)) \n"
."\t\@echo \$(word 1000, \$(string3)) \n"
."\t\@echo \$(wordlist 3, 4, \$(string)) \n"
."\t\@echo \$(wordlist 4, 3, \$(string)) \n"
."\t\@echo \$(wordlist 1, 6, \$(string)) \n"
."\t\@echo \$(wordlist 7, 5, \$(string)) \n"
."\t\@echo \$(wordlist 100, 110, \$(string)) \n"
."\t\@echo \$(wordlist 7, 10, \$(string2)) \n"
;
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
@@ -35,7 +35,7 @@ print MAKEFILE "string := word.pl general_test2.pl FORCE.pl word.pl generic_t
close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile,0);
&run_make_with_options($makefile, "", &get_logfile);
# Create the answer to what should be produced by this Makefile
@@ -47,7 +47,7 @@ $answer = "6\n"
."word.pl\n"
."\n"
."FORCE.pl word.pl\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"
@@ -58,13 +58,7 @@ $answer = "6\n"
# 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));
&compare_output($answer, &get_logfile(1));
# This tells the test driver that the perl test script executed properly.
1;

View File

@@ -5,12 +5,14 @@ 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.";
$makefile2 = &get_tmpfile;
open(MAKEFILE,"> $makefile");
# The contents of the Makefile ...
print MAKEFILE <<EOF;
\# We want to allow both empty commands _and_ commands that resolve to empty.
# We want to allow both empty commands _and_ commands that resolve to empty.
EMPTY =
.PHONY: all a1 a2 a3 a4
@@ -36,10 +38,21 @@ EOF
close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile);
# Create the answer to what should be produced by this Makefile
$answer = "$make_name: Nothing to be done for `all'.\n";
&compare_output($answer,&get_logfile(1));
# TEST 2
# Make sure files without trailing newlines are handled properly.
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));
1;

Some files were not shown because too many files have changed in this diff Show More