diff --git a/ChangeLog b/ChangeLog index 331d02ed..f3fdffa9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 1999-07-21 Paul D. Smith + * Version 3.77.90 released. + + * Makefile.am (AUTOMAKE_OPTIONS): Require automake 1.4. + + * default.c (default_suffix_rules): Rearrange the default command + lines to conform to POSIX rules (put the filename argument $< + _after_ the OUTPUT_OPTION, not before it). + * various: Changed !strncmp() calls to strneq() macros. * misc.c (sindex): Make slightly more efficient. @@ -18,9 +26,8 @@ (define_automatic_variables): Ditto. * vpath.c (construct_vpath_list): Ditto. - * misc.c (xrealloc): If PTR is NULL, call malloc to conform to - the standard--some older versions of realloc are non-standard so - make xrealloc DTRT. + * misc.c (xrealloc): Some reallocs are non-standard: work around + them in xrealloc by calling malloc if PTR is NULL. * main.c (main): Call xrealloc() directly instead of testing for NULL. @@ -28,8 +35,8 @@ non-standard versions of free() don't like it. * configure.in (--enable-dmalloc): Install some support for using - dmalloc (http://www.dmalloc.com) with make. Use --enable-dmalloc - with configure. + dmalloc (http://www.dmalloc.com/) with make. Use --enable-dmalloc + with configure to enable it. 1999-07-20 Paul D. Smith @@ -189,7 +196,8 @@ suggested by Howard Chu . * configure.in (job-server): New disable option for job server - support--it's enabled by default. + support--it's enabled by default. If it works well this will go + away. * NEWS: Summarize the new feature. @@ -233,6 +241,29 @@ kept although it's not needed or used unless you don't have waitpid() or wait3(). +1999-04-10 Paul D. Smith + + * main.c (main): Reset the considered bit on all the makefiles if + something failed to update; we need to examine them again if they + appear as normal targets in order to get the proper error message. + +1999-04-09 Paul D. Smith + + Performance enhancement from Tim Magill . + + * remake.c (update_file): If you have large numbers of + dependencies and you run in parallel, make can spend considerable + time each pass through the graph looking at branches it has + already seen. Since we only reap_children() when starting a pass, + not in the middle, if a branch has been seen already in that pass + nothing interesting can happen until the next pass. So, we toggle + a bit saying whether we've seen this target in this pass or not. + (update_goal_chain): Initially set the global considered toggle to + 1, since all targets initialize their boolean to 0. At the end of + each pass, toggle the global considered variable. * filedef.h + (struct file): Per-file considered toggle bit. * file.c: New + global toggle variable considered. + 1999-04-03 Paul D. Smith * remake.c (f_mtime): If: a) we found a file and b) we didn't @@ -541,6 +572,9 @@ * config.h.W32: Ditto. * configh.dos: Ditto. + * dir.c (find_directory) [WINDOWS32]: Windows stat() fails if + directory names end with `\' so strip it. + 1998-08-17 Paul D. Smith * make.texinfo: Added copyright year to the printed copy. Removed diff --git a/Makefile.am b/Makefile.am index b5d22c67..bf490405 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ # This is a -*-Makefile-*-, or close enough -AUTOMAKE_OPTIONS = 1.3 +AUTOMAKE_OPTIONS = 1.4 bin_PROGRAMS = make diff --git a/configure.in b/configure.in index f62c192c..82bb5028 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ 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. -AM_INIT_AUTOMAKE(make, 3.77.xx) +AM_INIT_AUTOMAKE(make, 3.77.90) AM_CONFIG_HEADER(config.h) dnl Regular configure stuff diff --git a/default.c b/default.c index 16811443..79f313ea 100644 --- a/default.c +++ b/default.c @@ -183,21 +183,21 @@ static char *default_suffix_rules[] = ".S.o", "$(COMPILE.S) -o $@ $<", ".c.o", - "$(COMPILE.c) $< $(OUTPUT_OPTION)", + "$(COMPILE.c) $(OUTPUT_OPTION) $<", ".cc.o", - "$(COMPILE.cc) $< $(OUTPUT_OPTION)", + "$(COMPILE.cc) $(OUTPUT_OPTION) $<", ".C.o", - "$(COMPILE.C) $< $(OUTPUT_OPTION)", + "$(COMPILE.C) $(OUTPUT_OPTION) $<", ".cpp.o", - "$(COMPILE.cpp) $< $(OUTPUT_OPTION)", + "$(COMPILE.cpp) $(OUTPUT_OPTION) $<", ".f.o", - "$(COMPILE.f) $< $(OUTPUT_OPTION)", + "$(COMPILE.f) $(OUTPUT_OPTION) $<", ".p.o", - "$(COMPILE.p) $< $(OUTPUT_OPTION)", + "$(COMPILE.p) $(OUTPUT_OPTION) $<", ".F.o", - "$(COMPILE.F) $< $(OUTPUT_OPTION)", + "$(COMPILE.F) $(OUTPUT_OPTION) $<", ".r.o", - "$(COMPILE.r) $< $(OUTPUT_OPTION)", + "$(COMPILE.r) $(OUTPUT_OPTION) $<", ".mod.o", "$(COMPILE.mod) -o $@ $<", @@ -222,9 +222,9 @@ static char *default_suffix_rules[] = "@$(RM) $@ \n $(LEX.l) $< > $@", ".F.f", - "$(PREPROCESS.F) $< $(OUTPUT_OPTION)", + "$(PREPROCESS.F) $(OUTPUT_OPTION) $<", ".r.f", - "$(PREPROCESS.r) $< $(OUTPUT_OPTION)", + "$(PREPROCESS.r) $(OUTPUT_OPTION) $<", /* This might actually make lex.yy.c if there's no %R% directive in $*.l, but in that case why were you diff --git a/dir.c b/dir.c index fc0b6f5d..0d0f0783 100644 --- a/dir.c +++ b/dir.c @@ -332,6 +332,13 @@ find_directory (name) #ifdef VMS if (vmsstat_dir (name, &st) < 0) #else + +#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 { diff --git a/file.c b/file.c index 2a9a7912..65f3e2d3 100644 --- a/file.c +++ b/file.c @@ -38,6 +38,9 @@ static struct file *files[FILE_BUCKETS]; unsigned int num_intermediates = 0; +/* Current value for pruning the scan of the goal chain (toggle 0/1). */ + +unsigned int considered = 0; /* Access the hash table of all file records. lookup_file given a name, return the struct file * for that name, diff --git a/filedef.h b/filedef.h index c96c2e35..425bb048 100644 --- a/filedef.h +++ b/filedef.h @@ -92,12 +92,18 @@ struct file unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */ unsigned int pat_searched:1;/* Nonzero if we already searched for pattern-specific variables. */ + unsigned int considered:1; /* equal to `considered' if file has been + considered on current scan of goal chain */ }; /* 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; diff --git a/glob/ChangeLog b/glob/ChangeLog index b7e85ad0..6fa43650 100644 --- a/glob/ChangeLog +++ b/glob/ChangeLog @@ -1,3 +1,14 @@ +1999-07-21 Paul D. Smith + + * glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version + from GLIBC. + + * fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI. + (__strchrnul): This won't exist outside GLIBC, so create one. + + * glob.c: Move getlogin{,_r} prototypes below glob.h to get __P() + macro. + 1998-08-05 Paul D. Smith * configure.in: Remove; configuration for glob is handled by the diff --git a/glob/Makefile.am b/glob/Makefile.am index 964ac194..e6359b46 100644 --- a/glob/Makefile.am +++ b/glob/Makefile.am @@ -1,6 +1,6 @@ # -*-Makefile-*-, or close enough -AUTOMAKE_OPTIONS = 1.3 foreign +AUTOMAKE_OPTIONS = 1.4 foreign noinst_LIBRARIES = libglob.a diff --git a/glob/fnmatch.c b/glob/fnmatch.c index 2d6f6afb..4ad86ff8 100644 --- a/glob/fnmatch.c +++ b/glob/fnmatch.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU C Library. This library is free software; you can redistribute it and/or @@ -29,7 +29,7 @@ #include #include -#if HAVE_STRING_H +#if HAVE_STRING_H || defined _LIBC # include #else # include @@ -127,16 +127,35 @@ extern char *getenv (); extern int errno; # endif +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (s, c) + register const char *s; + int c; +{ + c = (unsigned char)c; + while (*s && *s != c) + ++s; + return (char *)s; +} +# endif + /* Match STRING against the filename pattern PATTERN, returning zero if it matches, nonzero if not. */ -int -fnmatch (pattern, string, flags) +static int +#ifdef _LIBC +internal_function +#endif +internal_fnmatch (pattern, string, no_leading_period, flags) const char *pattern; const char *string; + int no_leading_period; int flags; { register const char *p = pattern, *n = string; - register char c; + register unsigned char c; /* Note that this evaluates C many times. */ # ifdef _LIBC @@ -154,10 +173,11 @@ fnmatch (pattern, string, flags) case '?': if (*n == '\0') return FNM_NOMATCH; - else if ((flags & FNM_FILE_NAME) && *n == '/') + else if (*n == '/' && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; - else if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + else if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; break; @@ -170,18 +190,19 @@ fnmatch (pattern, string, flags) return FNM_NOMATCH; c = FOLD (c); } - if (FOLD (*n) != c) + if (FOLD ((unsigned char) *n) != c) return FNM_NOMATCH; break; case '*': - if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) { - if ((flags & FNM_FILE_NAME) && *n == '/') + if (*n == '/' && (flags & FNM_FILE_NAME)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else if (c == '?') @@ -199,17 +220,65 @@ fnmatch (pattern, string, flags) } if (c == '\0') - return 0; + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this does mean it cannot match. */ + return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL + ? FNM_NOMATCH : 0); + else + { + const char *endp; - { - char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - c1 = FOLD (c1); - for (--p; *n != '\0'; ++n) - if ((c == '[' || FOLD (*n) == c1) && - fnmatch (p, n, flags & ~FNM_PERIOD) == 0) - return 0; - return FNM_NOMATCH; - } + endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); + + if (c == '[') + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + for (--p; n < endp; ++n) + if (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) + == 0) + return 0; + } + else if (c == '/' && (flags & FNM_FILE_NAME)) + { + while (*n != '\0' && *n != '/') + ++n; + if (*n == '/' + && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, + flags) == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n) + if (FOLD ((unsigned char) *n) == c + && (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; case '[': { @@ -224,8 +293,10 @@ fnmatch (pattern, string, flags) if (*n == '\0') return FNM_NOMATCH; - if (*n == '.' && (flags & FNM_PERIOD) && - (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + if (*n == '.' && no_leading_period && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))) return FNM_NOMATCH; if (*n == '/' && (flags & FNM_FILE_NAME)) @@ -239,13 +310,14 @@ fnmatch (pattern, string, flags) c = *p++; for (;;) { - int fn = FOLD (*n); + unsigned char fn = FOLD ((unsigned char) *n); if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; - c = FOLD (*p++); + c = FOLD ((unsigned char) *p); + ++p; if (c == fn) goto matched; @@ -258,6 +330,7 @@ fnmatch (pattern, string, flags) # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wctype_t wt; # endif + const char *startp = p; for (;;) { @@ -272,7 +345,15 @@ fnmatch (pattern, string, flags) p += 2; break; } - str[c1++] = 'c'; + if (c < 'a' || c >= 'z') + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = '['; + goto normal_bracket; + } + str[c1++] = c; } str[c1] = '\0'; @@ -282,47 +363,52 @@ fnmatch (pattern, string, flags) /* Invalid character class name. */ return FNM_NOMATCH; - if (__iswctype (__btowc (*n), wt)) + if (__iswctype (__btowc ((unsigned char) *n), wt)) goto matched; # else - if ((STREQ (str, "alnum") && ISALNUM (*n)) - || (STREQ (str, "alpha") && ISALPHA (*n)) - || (STREQ (str, "blank") && ISBLANK (*n)) - || (STREQ (str, "cntrl") && ISCNTRL (*n)) - || (STREQ (str, "digit") && ISDIGIT (*n)) - || (STREQ (str, "graph") && ISGRAPH (*n)) - || (STREQ (str, "lower") && ISLOWER (*n)) - || (STREQ (str, "print") && ISPRINT (*n)) - || (STREQ (str, "punct") && ISPUNCT (*n)) - || (STREQ (str, "space") && ISSPACE (*n)) - || (STREQ (str, "upper") && ISUPPER (*n)) - || (STREQ (str, "xdigit") && ISXDIGIT (*n))) + if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) + || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) + || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) + || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) + || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) + || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) + || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) + || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) + || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) + || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) + || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) + || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) goto matched; # endif } else if (c == '\0') /* [ (unterminated) loses. */ return FNM_NOMATCH; - else if (FOLD (c) == fn) - goto matched; - - cold = c; - c = *p++; - - if (c == '-' && *p != ']') + else { - /* It is a range. */ - char cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return FNM_NOMATCH; - - if (cold <= fn && fn <= FOLD (cend)) + normal_bracket: + if (FOLD (c) == fn) goto matched; + cold = c; c = *p++; + + if (c == '-' && *p != ']') + { + /* It is a range. */ + unsigned char cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + + if (cold <= fn && fn <= FOLD (cend)) + goto matched; + + c = *p++; + } } + if (c == ']') break; } @@ -363,7 +449,7 @@ fnmatch (pattern, string, flags) break; default: - if (c != FOLD (*n)) + if (c != FOLD ((unsigned char) *n)) return FNM_NOMATCH; } @@ -382,4 +468,14 @@ fnmatch (pattern, string, flags) # undef FOLD } + +int +fnmatch (pattern, string, flags) + const char *pattern; + const char *string; + int flags; +{ + return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); +} + #endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/glob/fnmatch.h b/glob/fnmatch.h index 4d1eb3e2..cc3ec379 100644 --- a/glob/fnmatch.h +++ b/glob/fnmatch.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -24,8 +24,10 @@ extern "C" { #endif #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 -# undef __P -# define __P(protos) protos +# if !defined __GLIBC__ || !defined __P +# undef __P +# define __P(protos) protos +# endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () @@ -66,13 +68,13 @@ extern "C" { `fnmatch'. Since this is not the case here it will never be returned but the conformance test suites still require the symbol to be defined. */ -#if (_XOPEN_SOURCE - 0) == 500 +#ifdef _XOPEN_SOURCE # define FNM_NOSYS (-1) #endif -/* Match STRING against the filename pattern PATTERN, +/* Match NAME against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ -extern int fnmatch __P ((__const char *__pattern, __const char *__string, +extern int fnmatch __P ((__const char *__pattern, __const char *__name, int __flags)); #ifdef __cplusplus diff --git a/glob/glob.c b/glob/glob.c index eab79194..1ab5d8b6 100644 --- a/glob/glob.c +++ b/glob/glob.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc. +/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -177,10 +177,10 @@ extern void bcopy (); #if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 # define HAVE_MEMPCPY 1 +# undef mempcpy # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif - #ifndef __GNU_LIBRARY__ # ifdef __GNUC__ __inline @@ -240,11 +240,17 @@ extern char *alloca (); #endif #ifdef _LIBC +# undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) # define closedir(dir) __closedir (dir) # define opendir(name) __opendir (name) # define readdir(str) __readdir (str) +# define getpwnam_r(name, bufp, buf, len, res) \ + __getpwnam_r (name, bufp, buf, len, res) +# ifndef __stat +# define __stat(fname, buf) __xstat (_STAT_VER, fname, buf) +# endif #endif #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) @@ -274,6 +280,12 @@ extern char *alloca (); # undef GLOB_PERIOD #endif #include + +#ifdef HAVE_GETLOGIN_R +extern int getlogin_r __P ((char *, size_t)); +#else +extern char *getlogin __P ((void)); +#endif static #if __GNUC__ - 0 >= 2 @@ -282,7 +294,7 @@ inline const char *next_brace_sub __P ((const char *begin)); static int glob_in_dir __P ((const char *pattern, const char *directory, int flags, - int (*errfunc) __P ((const char *, int)), + int (*errfunc) (const char *, int), glob_t *pglob)); static int prefix_array __P ((const char *prefix, char **array, size_t n)); static int collated_compare __P ((const __ptr_t, const __ptr_t)); @@ -349,7 +361,7 @@ glob (pattern, flags, errfunc, pglob) glob_t *pglob; { const char *filename; - char *dirname; + const char *dirname; size_t dirlen; int status; int oldcount; @@ -501,39 +513,40 @@ glob (pattern, flags, errfunc, pglob) { /* This can mean two things: a simple name or "~name". The later case is nothing but a notation for a directory. */ - if ((flags & GLOB_TILDE) && pattern[0] == '~') + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { - dirname = (char *) pattern; + dirname = pattern; dirlen = strlen (pattern); - /* Set FILENAME to NULL as a special flag. This is ugly but - other solutions would require much more code. We test for - this special case below. */ - filename = NULL; + /* Set FILENAME to NULL as a special flag. This is ugly but + other solutions would require much more code. We test for + this special case below. */ + filename = NULL; } else { - filename = pattern; + filename = pattern; #ifdef _AMIGA - dirname = (char *) ""; + dirname = ""; #else - dirname = (char *) "."; + dirname = "."; #endif - dirlen = 0; - } + dirlen = 0; + } } else if (filename == pattern) { /* "/pattern". */ - dirname = (char *) "/"; + dirname = "/"; dirlen = 1; ++filename; } else { + char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 - if ((*filename == ':') + if (*filename == ':' || (filename > pattern + 1 && filename[-1] == ':')) { char *drive_spec; @@ -555,30 +568,31 @@ glob (pattern, flags, errfunc, pglob) from "d:/", since "d:" and "d:/" are not the same.*/ } #endif - dirname = (char *) __alloca (dirlen + 1); + newp = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY - *((char *) mempcpy (dirname, pattern, dirlen)) = '\0'; + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; #else - memcpy (dirname, pattern, dirlen); - dirname[dirlen] = '\0'; + memcpy (newp, pattern, dirlen); + newp[dirlen] = '\0'; #endif + dirname = newp; ++filename; if (filename[0] == '\0' #if defined __MSDOS__ || defined WINDOWS32 - && dirname[dirlen-1] != ':' - && (dirlen < 3 || dirname[dirlen-2] != ':' - || dirname[dirlen-1] != '/') + && dirname[dirlen - 1] != ':' + && (dirlen < 3 || dirname[dirlen - 2] != ':' + || dirname[dirlen - 1] != '/') #endif - && dirlen > 1) - /* "pattern/". Expand "pattern", appending slashes. */ - { - int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); - if (val == 0) - pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) - | (flags & GLOB_MARK)); - return val; - } + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); + return val; + } } if (!(flags & GLOB_APPEND)) @@ -590,12 +604,12 @@ glob (pattern, flags, errfunc, pglob) oldcount = pglob->gl_pathc; #ifndef VMS - if ((flags & GLOB_TILDE) && dirname[0] == '~') + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') { if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ - char *home_dir = getenv ("HOME"); + const char *home_dir = getenv ("HOME"); # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; @@ -607,45 +621,61 @@ glob (pattern, flags, errfunc, pglob) if (home_dir == NULL || home_dir[0] == '\0') { int success; -# if defined HAVE_GETLOGIN_R || defined _LIBC - extern int getlogin_r __P ((char *, size_t)); - size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; char *name; +# if defined HAVE_GETLOGIN_R || defined _LIBC + size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; if (buflen == 0) /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ - buflen = 16; + buflen = 20; name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else - extern char *getlogin __P ((void)); - char *name; - success = (name = getlogin ()) != NULL; # endif if (success) { + struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; - struct passwd pwbuf, *p; + struct passwd pwbuf; + int save = errno; + if (pwbuflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. + Try a moderate value. */ + pwbuflen = 1024; pwtmpbuf = (char *) __alloca (pwbuflen); - success = (__getpwnam_r (name, &pwbuf, pwtmpbuf, - pwbuflen, &p) >= 0); + while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) + != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + pwbuflen *= 2; + pwtmpbuf = (char *) __alloca (pwbuflen); + __set_errno (save); + } # else - struct passwd *p = getpwnam (name); - success = p != NULL; + p = getpwnam (name); # endif - if (success) + if (p != NULL) home_dir = p->pw_dir; } } if (home_dir == NULL || home_dir[0] == '\0') - home_dir = (char *) "~"; /* No luck. */ + { + if (flags & GLOB_TILDE_CHECK) + return GLOB_NOMATCH; + else + home_dir = "~"; /* No luck. */ + } # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ @@ -670,40 +700,58 @@ glob (pattern, flags, errfunc, pglob) else { char *end_name = strchr (dirname, '/'); - char *user_name; - char *home_dir; + const char *user_name; + const char *home_dir; if (end_name == NULL) user_name = dirname + 1; else { - user_name = (char *) __alloca (end_name - dirname); + char *newp; + newp = (char *) __alloca (end_name - dirname); # ifdef HAVE_MEMPCPY - *((char *) mempcpy (user_name, dirname + 1, end_name - dirname)) + *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; # else - memcpy (user_name, dirname + 1, end_name - dirname); - user_name[end_name - dirname - 1] = '\0'; + memcpy (newp, dirname + 1, end_name - dirname); + newp[end_name - dirname - 1] = '\0'; # endif + user_name = newp; } /* Look up specific user's home directory. */ { + struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); - char *pwtmpbuf = (char *) __alloca (buflen); - struct passwd pwbuf, *p; - if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0) - home_dir = p->pw_dir; - else - home_dir = NULL; + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + + if (buflen == -1) + /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a + moderate value. */ + buflen = 1024; + pwtmpbuf = (char *) __alloca (buflen); + + while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + buflen *= 2; + pwtmpbuf = __alloca (buflen); + __set_errno (save); + } # else - struct passwd *p = getpwnam (user_name); + p = getpwnam (user_name); +# endif if (p != NULL) home_dir = p->pw_dir; else home_dir = NULL; -# endif } /* If we found a home directory use this. */ if (home_dir != NULL) @@ -722,6 +770,11 @@ glob (pattern, flags, errfunc, pglob) # endif dirname = newp; } + else + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the + home directory. */ + return GLOB_NOMATCH; } # endif /* Not Amiga && not WINDOWS32. */ } @@ -850,78 +903,80 @@ glob (pattern, flags, errfunc, pglob) flag was set we must return the list consisting of the disrectory names followed by the filename. */ if (pglob->gl_pathc == oldcount) - /* No matches. */ - if (flags & GLOB_NOCHECK) - { - size_t filename_len = strlen (filename) + 1; - char **new_pathv; - struct stat st; + { + /* No matches. */ + if (flags & GLOB_NOCHECK) + { + size_t filename_len = strlen (filename) + 1; + char **new_pathv; + struct stat st; - /* This is an pessimistic guess about the size. */ - pglob->gl_pathv - = (char **) realloc (pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - dirs.gl_pathc + 1) * - sizeof (char *)); - if (pglob->gl_pathv == NULL) - { - globfree (&dirs); - return GLOB_NOSPACE; - } + /* This is an pessimistic guess about the size. */ + pglob->gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + + ((flags & GLOB_DOOFFS) ? + pglob->gl_offs : 0) + + dirs.gl_pathc + 1) * + sizeof (char *)); + if (pglob->gl_pathv == NULL) + { + globfree (&dirs); + return GLOB_NOSPACE; + } - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; + if (flags & GLOB_DOOFFS) + while (pglob->gl_pathc < pglob->gl_offs) + pglob->gl_pathv[pglob->gl_pathc++] = NULL; - for (i = 0; i < dirs.gl_pathc; ++i) - { - const char *dir = dirs.gl_pathv[i]; - size_t dir_len = strlen (dir); + for (i = 0; i < dirs.gl_pathc; ++i) + { + const char *dir = dirs.gl_pathv[i]; + size_t dir_len = strlen (dir); - /* First check whether this really is a directory. */ - if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 - || !S_ISDIR (st.st_mode)) - /* No directory, ignore this entry. */ - continue; + /* First check whether this really is a directory. */ + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 + || !S_ISDIR (st.st_mode)) + /* No directory, ignore this entry. */ + continue; - pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 - + filename_len); - if (pglob->gl_pathv[pglob->gl_pathc] == NULL) - { - globfree (&dirs); - globfree (pglob); - return GLOB_NOSPACE; - } + pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 + + filename_len); + if (pglob->gl_pathv[pglob->gl_pathc] == NULL) + { + globfree (&dirs); + globfree (pglob); + return GLOB_NOSPACE; + } #ifdef HAVE_MEMPCPY - mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], - dir, dir_len), - "/", 1), - filename, filename_len); + mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], + dir, dir_len), + "/", 1), + filename, filename_len); #else - memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); - pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; - memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], - filename, filename_len); + memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); + pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; + memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], + filename, filename_len); #endif - ++pglob->gl_pathc; - } + ++pglob->gl_pathc; + } - pglob->gl_pathv[pglob->gl_pathc] = NULL; - pglob->gl_flags = flags; + pglob->gl_pathv[pglob->gl_pathc] = NULL; + pglob->gl_flags = flags; - /* Now we know how large the gl_pathv vector must be. */ - new_pathv = (char **) realloc (pglob->gl_pathv, - ((pglob->gl_pathc + 1) - * sizeof (char *))); - if (new_pathv != NULL) - pglob->gl_pathv = new_pathv; - } - else - return GLOB_NOMATCH; + /* Now we know how large the gl_pathv vector must be. */ + new_pathv = (char **) realloc (pglob->gl_pathv, + ((pglob->gl_pathc + 1) + * sizeof (char *))); + if (new_pathv != NULL) + pglob->gl_pathv = new_pathv; + } + else + return GLOB_NOMATCH; + } globfree (&dirs); } @@ -1092,6 +1147,8 @@ prefix_array (dirname, array, n) } +/* We must not compile this function twice. */ +#if !defined _LIBC || !defined NO_GLOB_PATTERN_P /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ int @@ -1126,8 +1183,9 @@ __glob_pattern_p (pattern, quote) return 0; } -#ifdef _LIBC +# ifdef _LIBC weak_alias (__glob_pattern_p, glob_pattern_p) +# endif #endif @@ -1213,8 +1271,9 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) : (__ptr_t) opendir (directory)); if (stream == NULL) { - if ((errfunc != NULL && (*errfunc) (directory, errno)) - || (flags & GLOB_ERR)) + if (errno != ENOTDIR + && ((errfunc != NULL && (*errfunc) (directory, errno)) + || (flags & GLOB_ERR))) return GLOB_ABORTED; nfound = 0; meta = 0; @@ -1317,10 +1376,12 @@ glob_in_dir (pattern, directory, flags, errfunc, pglob) save = errno; if (stream != NULL) - if (flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir) (stream); - else - closedir ((DIR *) stream); + { + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir ((DIR *) stream); + } __set_errno (save); return nfound == 0 ? GLOB_NOMATCH : 0; diff --git a/glob/glob.h b/glob/glob.h index a546c865..6a3ab181 100644 --- a/glob/glob.h +++ b/glob/glob.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -24,21 +24,42 @@ extern "C" { #undef __ptr_t #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 -# undef __P -# define __P(protos) protos -# define __ptr_t void * -# if !defined __GNUC__ || __GNUC__ < 2 -# undef __const -# define __const const +# if !defined __GLIBC__ || !defined __P +# undef __P +# undef __PMT +# define __P(protos) protos +# define __PMT(protos) protos +# if !defined __GNUC__ || __GNUC__ < 2 +# undef __const +# define __const const +# endif # endif +# define __ptr_t void * #else /* Not C++ or ANSI C. */ # undef __P +# undef __PMT # define __P(protos) () +# define __PMT(protos) () # undef __const # define __const # define __ptr_t char * #endif /* C++ or ANSI C. */ +/* We need `size_t' for the following definitions. */ +#ifndef __size_t +# if defined __GNUC__ && __GNUC__ >= 2 +typedef __SIZE_TYPE__ __size_t; +# else +/* This is a guess. */ +typedef unsigned long int __size_t; +# endif +#else +/* The GNU CC stddef.h version defines __size_t as empty. We need a real + definition. */ +# undef __size_t +# define __size_t size_t +#endif + /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ @@ -57,10 +78,12 @@ extern "C" { # define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ # define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ # define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ +# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error + if the user name is not available. */ # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ - GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR) + GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) #else # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ @@ -71,41 +94,52 @@ extern "C" { #define GLOB_NOSPACE 1 /* Ran out of memory. */ #define GLOB_ABORTED 2 /* Read error. */ #define GLOB_NOMATCH 3 /* No matches found. */ - +#define GLOB_NOSYS 4 /* Not implemented. */ #ifdef _GNU_SOURCE /* Previous versions of this file defined GLOB_ABEND instead of GLOB_ABORTED. Provide a compatibility definition here. */ # define GLOB_ABEND GLOB_ABORTED #endif -/* This value is returned if the implementation does not support - `glob'. Since this is not the case here it will never be - returned but the conformance test suites still require the symbol - to be defined. */ -#if (_XOPEN_SOURCE - 0) == 500 -# define GLOB_NOSYS (-1) -#endif - /* Structure describing a globbing run. */ #if !defined _AMIGA && !defined VMS /* Buggy compiler. */ struct stat; #endif typedef struct { - int gl_pathc; /* Count of paths matched by the pattern. */ + __size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ - int gl_offs; /* Slots to reserve in `gl_pathv'. */ + __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ - void (*gl_closedir) __P ((void *)); - struct dirent *(*gl_readdir) __P ((void *)); - __ptr_t (*gl_opendir) __P ((__const char *)); - int (*gl_lstat) __P ((__const char *, struct stat *)); - int (*gl_stat) __P ((__const char *, struct stat *)); + void (*gl_closedir) __PMT ((void *)); + struct dirent *(*gl_readdir) __PMT ((void *)); + __ptr_t (*gl_opendir) __PMT ((__const char *)); + int (*gl_lstat) __PMT ((__const char *, struct stat *)); + int (*gl_stat) __PMT ((__const char *, struct stat *)); } glob_t; +#ifdef _LARGEFILE64_SOURCE +struct stat64; +typedef struct + { + __size_t gl_pathc; + char **gl_pathv; + __size_t gl_offs; + int gl_flags; + + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) __PMT ((void *)); + struct dirent64 *(*gl_readdir) __PMT ((void *)); + __ptr_t (*gl_opendir) __PMT ((__const char *)); + int (*gl_lstat) __PMT ((__const char *, struct stat64 *)); + int (*gl_stat) __PMT ((__const char *, struct stat64 *)); + } glob64_t; +#endif + /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, @@ -114,12 +148,33 @@ typedef struct `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ +#if _FILE_OFFSET_BITS != 64 extern int glob __P ((__const char *__pattern, int __flags, - int (*__errfunc) __P ((__const char *, int)), + int (*__errfunc) (__const char *, int), glob_t *__pglob)); /* Free storage allocated in PGLOB by a previous `glob' call. */ extern void globfree __P ((glob_t *__pglob)); +#else +# if __GNUC__ >= 2 +extern int glob __P ((__const char *__pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__pglob)) __asm__ ("glob64"); + +extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64"); +# else +# define glob glob64 +# define globfree globfree64 +# endif +#endif + +#ifdef _LARGEFILE64_SOURCE +extern int glob64 __P ((__const char *__pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob64_t *__pglob)); + +extern void globfree64 __P ((glob64_t *__pglob)); +#endif #ifdef _GNU_SOURCE @@ -128,7 +183,6 @@ extern void globfree __P ((glob_t *__pglob)); This function is not part of the interface specified by POSIX.2 but several programs want to use it. */ -extern int __glob_pattern_p __P ((__const char *__pattern, int __quote)); extern int glob_pattern_p __P ((__const char *__pattern, int __quote)); #endif diff --git a/main.c b/main.c index f9ba4f4f..1950956b 100644 --- a/main.c +++ b/main.c @@ -1465,45 +1465,51 @@ int main (int argc, char ** argv) struct dep *d; for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next) - if (d->file->updated) - { - /* This makefile was updated. */ - if (d->file->update_status == 0) - { - /* It was successfully updated. */ - any_remade |= (file_mtime_no_search (d->file) - != makefile_mtimes[i]); - } - else if (! (d->changed & RM_DONTCARE)) - { - FILE_TIMESTAMP mtime; - /* The update failed and this makefile was not - from the MAKEFILES variable, so we care. */ - error (NILF, "Failed to remake makefile `%s'.", - d->file->name); - mtime = file_mtime_no_search (d->file); - any_remade |= (mtime != (FILE_TIMESTAMP) -1 - && mtime != makefile_mtimes[i]); - } - } - else - /* This makefile was not found at all. */ - if (! (d->changed & RM_DONTCARE)) + { + /* Reset the considered flag; we may need to look at the file + again to print an error. */ + d->file->considered = 0; + + if (d->file->updated) { - /* This is a makefile we care about. See how much. */ - if (d->changed & RM_INCLUDED) - /* An included makefile. We don't need - to die, but we do want to complain. */ - error (NILF, "Included makefile `%s' was not found.", - dep_name (d)); - else + /* This makefile was updated. */ + if (d->file->update_status == 0) { - /* A normal makefile. We must die later. */ - error (NILF, "Makefile `%s' was not found", - dep_name (d)); - any_failed = 1; + /* It was successfully updated. */ + any_remade |= (file_mtime_no_search (d->file) + != makefile_mtimes[i]); + } + else if (! (d->changed & RM_DONTCARE)) + { + FILE_TIMESTAMP mtime; + /* The update failed and this makefile was not + from the MAKEFILES variable, so we care. */ + error (NILF, "Failed to remake makefile `%s'.", + d->file->name); + mtime = file_mtime_no_search (d->file); + any_remade |= (mtime != (FILE_TIMESTAMP) -1 + && mtime != makefile_mtimes[i]); } } + else + /* This makefile was not found at all. */ + if (! (d->changed & RM_DONTCARE)) + { + /* This is a makefile we care about. See how much. */ + if (d->changed & RM_INCLUDED) + /* An included makefile. We don't need + to die, but we do want to complain. */ + error (NILF, "Included makefile `%s' was not found.", + dep_name (d)); + else + { + /* A normal makefile. We must die later. */ + error (NILF, "Makefile `%s' was not found", + dep_name (d)); + any_failed = 1; + } + } + } /* Reset this to empty so we get the right error message below. */ read_makefiles = 0; diff --git a/remake.c b/remake.c index 75af6586..90de313c 100644 --- a/remake.c +++ b/remake.c @@ -106,6 +106,9 @@ update_goal_chain (goals, makefiles) job_slots = 1; #endif + /* All files start with the considered bit 0, so the global value is 1. */ + considered = 1; + /* Update all the goals until they are all finished. */ while (goals != 0) @@ -247,6 +250,11 @@ update_goal_chain (goals, makefiles) g = g->next; } } + + /* If we reached the end of the dependency graph toggle the considered + flag for the next pass. */ + if (g == 0) + considered = !considered; } if (makefiles) @@ -312,6 +320,17 @@ update_file (file, depth) register int status = 0; register struct file *f; + /* Prune the dependency graph: if we've already been here on _this_ pass + through the dependency graph, we don't have to go any further. We won't + reap_children until we start the next pass, so no state change is + possible below here until then. */ + if (file->considered == considered) + { + DEBUGPR ("Pruning file `%s'.\n"); + return 0; + } + file->considered = considered; + for (f = file->double_colon ? file->double_colon : file; f != 0; f = f->prev) { status |= update_file_1 (f, depth);