make/dir.c

1229 lines
30 KiB
C
Raw Normal View History

1991-10-19 03:26:24 +08:00
/* Directory hashing for GNU Make.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
2010-07-13 09:20:10 +08:00
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010 Free Software Foundation, Inc.
1991-10-19 03:26:24 +08:00
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
1991-10-19 03:26:24 +08:00
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.
1991-10-19 03:26:24 +08:00
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
1991-10-19 03:26:24 +08:00
#include "make.h"
#include "hash.h"
1991-10-19 03:26:24 +08:00
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
2000-01-22 13:43:03 +08:00
# ifdef VMS
/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */
const char *vmsify (const char *name, int type);
2000-01-22 13:43:03 +08:00
# endif
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
# ifdef HAVE_VMSDIR_H
# include "vmsdir.h"
# endif /* HAVE_VMSDIR_H */
#endif
/* In GNU systems, <dirent.h> defines this macro for us. */
#ifdef _D_NAMLEN
2000-01-22 13:43:03 +08:00
# undef NAMLEN
# define NAMLEN(d) _D_NAMLEN(d)
#endif
1991-10-19 03:26:24 +08:00
2000-01-22 13:43:03 +08:00
#if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
1991-10-19 03:26:24 +08:00
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
2000-01-22 13:43:03 +08:00
# define REAL_DIR_ENTRY(dp) 1
# define FAKE_DIR_ENTRY(dp)
1991-10-19 03:26:24 +08:00
#else
2000-01-22 13:43:03 +08:00
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
# define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
1991-10-19 03:26:24 +08:00
#endif /* POSIX */
1992-10-10 01:35:07 +08:00
#ifdef __MSDOS__
1994-09-27 06:20:56 +08:00
#include <ctype.h>
1997-04-07 15:21:16 +08:00
#include <fcntl.h>
/* If it's MSDOS that doesn't have _USE_LFN, disable LFN support. */
#ifndef _USE_LFN
#define _USE_LFN 0
#endif
static const char *
dosify (const char *filename)
{
static char dos_filename[14];
char *df;
int i;
1997-04-07 15:21:16 +08:00
if (filename == 0 || _USE_LFN)
return filename;
1997-04-07 15:21:16 +08:00
/* FIXME: what about filenames which violate
8+3 constraints, like "config.h.in", or ".emacs"? */
if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0)
return filename;
df = dos_filename;
/* First, transform the name part. */
for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)
*df++ = tolower ((unsigned char)*filename++);
/* Now skip to the next dot. */
while (*filename != '\0' && *filename != '.')
++filename;
if (*filename != '\0')
{
*df++ = *filename++;
for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)
*df++ = tolower ((unsigned char)*filename++);
}
/* Look for more dots. */
while (*filename != '\0' && *filename != '.')
++filename;
if (*filename == '.')
return filename;
*df = 0;
return dos_filename;
}
#endif /* __MSDOS__ */
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#include "pathstuff.h"
#endif
#ifdef _AMIGA
#include <ctype.h>
1998-07-31 04:54:47 +08:00
#endif
1998-07-31 04:54:47 +08:00
#ifdef HAVE_CASE_INSENSITIVE_FS
static const char *
downcase (const char *filename)
{
static PATH_VAR (new_filename);
char *df;
if (filename == 0)
return 0;
1998-07-31 04:54:47 +08:00
df = new_filename;
while (*filename != '\0')
{
*df++ = tolower ((unsigned char)*filename);
++filename;
}
*df = 0;
1998-07-31 04:54:47 +08:00
return new_filename;
}
1998-07-31 04:54:47 +08:00
#endif /* HAVE_CASE_INSENSITIVE_FS */
#ifdef VMS
static int
vms_hash (const char *name)
{
int h = 0;
int g;
while (*name)
{
2000-07-31 02:26:42 +08:00
unsigned char uc = *name;
#ifdef HAVE_CASE_INSENSITIVE_FS
2000-07-31 02:26:42 +08:00
h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
#else
h = (h << 4) + uc;
#endif
2000-01-22 13:43:03 +08:00
name++;
g = h & 0xf0000000;
if (g)
{
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h;
}
/* fake stat entry for a directory */
static int
vmsstat_dir (const char *name, struct stat *st)
{
char *s;
int h;
DIR *dir;
dir = opendir (name);
if (dir == 0)
return -1;
closedir (dir);
s = strchr (name, ':'); /* find device */
if (s)
{
/* to keep the compiler happy we said "const char *name", now we cheat */
*s++ = 0;
st->st_dev = (char *)vms_hash (name);
1997-08-28 04:30:54 +08:00
h = vms_hash (s);
*(s-1) = ':';
}
else
{
st->st_dev = 0;
h = vms_hash (name);
}
1997-08-28 04:30:54 +08:00
st->st_ino[0] = h & 0xff;
st->st_ino[1] = h & 0xff00;
st->st_ino[2] = h >> 16;
return 0;
}
#endif /* VMS */
1991-10-19 03:26:24 +08:00
/* Hash table of directories. */
1992-10-10 01:35:07 +08:00
#ifndef DIRECTORY_BUCKETS
#define DIRECTORY_BUCKETS 199
#endif
struct directory_contents
1991-10-19 03:26:24 +08:00
{
dev_t dev; /* Device and inode numbers of this dir. */
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
/* Inode means nothing on WINDOWS32. Even file key information is
* unreliable because it is random per file open and undefined for remote
* filesystems. The most unique attribute I can come up with is the fully
* qualified name of the directory. Beware though, this is also
* unreliable. I'm open to suggestion on a better way to emulate inode. */
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
char *path_key;
int ctime;
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
int mtime; /* controls check for stale directory cache */
1997-04-07 15:21:16 +08:00
int fs_flags; /* FS_FAT, FS_NTFS, ... */
# define FS_FAT 0x1
# define FS_NTFS 0x2
# define FS_UNKNOWN 0x4
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#else
# ifdef VMS
ino_t ino[3];
# else
ino_t ino;
# endif
1997-04-07 15:21:16 +08:00
#endif /* WINDOWS32 */
struct hash_table dirfiles; /* Files in this directory. */
1991-10-19 03:26:24 +08:00
DIR *dirstream; /* Stream reading this directory. */
};
static unsigned long
directory_contents_hash_1 (const void *key_0)
{
const struct directory_contents *key = key_0;
unsigned long hash;
#ifdef WINDOWS32
2003-07-19 10:46:25 +08:00
hash = 0;
ISTRING_HASH_1 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
^ ((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
+ (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
# endif
#endif /* WINDOWS32 */
return hash;
}
static unsigned long
directory_contents_hash_2 (const void *key_0)
{
const struct directory_contents *key = key_0;
unsigned long hash;
#ifdef WINDOWS32
2003-07-19 10:46:25 +08:00
hash = 0;
ISTRING_HASH_2 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
#else
# ifdef VMS
hash = (((unsigned int) key->dev << 4)
^ ~((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
+ (unsigned int) key->ino[2]));
# else
hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
# endif
#endif /* WINDOWS32 */
return hash;
}
/* Sometimes it's OK to use subtraction to get this value:
result = X - Y;
But, if we're not sure of the type of X and Y they may be too large for an
int (on a 64-bit system for example). So, use ?: instead.
See Savannah bug #15534.
NOTE! This macro has side-effects!
*/
#define MAKECMP(_x,_y) ((_x)<(_y)?-1:((_x)==(_y)?0:1))
static int
directory_contents_hash_cmp (const void *xv, const void *yv)
{
const struct directory_contents *x = xv;
const struct directory_contents *y = yv;
int result;
#ifdef WINDOWS32
ISTRING_COMPARE (x->path_key, y->path_key, result);
if (result)
return result;
result = MAKECMP(x->ctime, y->ctime);
if (result)
return result;
#else
# ifdef VMS
result = MAKECMP(x->ino[0], y->ino[0]);
if (result)
return result;
result = MAKECMP(x->ino[1], y->ino[1]);
if (result)
return result;
result = MAKECMP(x->ino[2], y->ino[2]);
if (result)
return result;
# else
result = MAKECMP(x->ino, y->ino);
if (result)
return result;
# endif
#endif /* WINDOWS32 */
return MAKECMP(x->dev, y->dev);
}
1992-10-10 01:35:07 +08:00
/* Table of directory contents hashed by device and inode number. */
static struct hash_table directory_contents;
1991-10-19 03:26:24 +08:00
1992-10-10 01:35:07 +08:00
struct directory
{
const char *name; /* Name of the directory. */
1992-10-10 01:35:07 +08:00
/* The directory's contents. This data may be shared by several
entries in the hash table, which refer to the same directory
(identified uniquely by `dev' and `ino') under different names. */
struct directory_contents *contents;
};
static unsigned long
directory_hash_1 (const void *key)
{
return_ISTRING_HASH_1 (((const struct directory *) key)->name);
}
static unsigned long
directory_hash_2 (const void *key)
{
return_ISTRING_HASH_2 (((const struct directory *) key)->name);
}
static int
directory_hash_cmp (const void *x, const void *y)
{
return_ISTRING_COMPARE (((const struct directory *) x)->name,
((const struct directory *) y)->name);
}
1991-10-19 03:26:24 +08:00
/* Table of directories hashed by name. */
static struct hash_table directories;
1991-10-19 03:26:24 +08:00
/* Never have more than this many directories open at once. */
#define MAX_OPEN_DIRECTORIES 10
static unsigned int open_directories = 0;
/* Hash table of files in each directory. */
struct dirfile
{
const char *name; /* Name of the file. */
short length;
short impossible; /* This file is impossible. */
1991-10-19 03:26:24 +08:00
};
static unsigned long
dirfile_hash_1 (const void *key)
{
return_ISTRING_HASH_1 (((struct dirfile const *) key)->name);
}
static unsigned long
dirfile_hash_2 (const void *key)
{
return_ISTRING_HASH_2 (((struct dirfile const *) key)->name);
}
static int
dirfile_hash_cmp (const void *xv, const void *yv)
{
const struct dirfile *x = xv;
const struct dirfile *y = yv;
int result = x->length - y->length;
if (result)
return result;
return_ISTRING_COMPARE (x->name, y->name);
}
1991-10-19 03:26:24 +08:00
#ifndef DIRFILE_BUCKETS
1992-10-10 01:35:07 +08:00
#define DIRFILE_BUCKETS 107
1991-10-19 03:26:24 +08:00
#endif
static int dir_contents_file_exists_p (struct directory_contents *dir,
const char *filename);
static struct directory *find_directory (const char *name);
1992-10-10 01:35:07 +08:00
1991-10-19 03:26:24 +08:00
/* Find the directory named NAME and return its `struct directory'. */
static struct directory *
find_directory (const char *name)
1991-10-19 03:26:24 +08:00
{
const char *p;
struct directory *dir;
struct directory **dir_slot;
struct directory dir_key;
int r;
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
char* w32_path;
1997-04-07 15:21:16 +08:00
char fs_label[BUFSIZ];
char fs_type[BUFSIZ];
unsigned long fs_serno;
unsigned long fs_flags;
unsigned long fs_len;
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#endif
#ifdef VMS
if ((*name == '.') && (*(name+1) == 0))
name = "[]";
else
name = vmsify (name,1);
#endif
1991-10-19 03:26:24 +08:00
dir_key.name = name;
dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
dir = *dir_slot;
1991-10-19 03:26:24 +08:00
if (HASH_VACANT (dir))
1991-10-19 03:26:24 +08:00
{
1992-10-10 01:35:07 +08:00
struct stat st;
/* The directory was not found. Create a new entry for it. */
p = name + strlen (name);
dir = xmalloc (sizeof (struct directory));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
dir->name = strcache_add_len (downcase(name), p - name);
#else
dir->name = strcache_add_len (name, p - name);
#endif
hash_insert_at (&directories, dir, dir_slot);
1992-10-10 01:35:07 +08:00
/* The directory is not in the name hash table.
Find its device and inode numbers, and look it up by them. */
#ifdef VMS
r = vmsstat_dir (name, &st);
#elif defined(WINDOWS32)
{
char tem[MAXPATHLEN], *tstart, *tend;
/* Remove any trailing slashes. Windows32 stat fails even on
valid directories if they end in a slash. */
memcpy (tem, name, p - name + 1);
tstart = tem;
if (tstart[1] == ':')
tstart += 2;
for (tend = tem + (p - name - 1);
tend > tstart && (*tend == '/' || *tend == '\\');
tend--)
*tend = '\0';
r = stat (tem, &st);
}
#else
EINTRLOOP (r, stat (name, &st));
#endif
if (r < 0)
{
1992-10-10 01:35:07 +08:00
/* Couldn't stat the directory. Mark this by
setting the `contents' member to a nil pointer. */
dir->contents = 0;
}
1991-10-19 03:26:24 +08:00
else
{
1992-10-10 01:35:07 +08:00
/* 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;
1992-10-10 01:35:07 +08:00
dc_key.dev = st.st_dev;
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
dc_key.path_key = w32_path = w32ify (name, 1);
dc_key.ctime = st.st_ctime;
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#else
2000-01-22 13:43:03 +08:00
# ifdef VMS
dc_key.ino[0] = st.st_ino[0];
dc_key.ino[1] = st.st_ino[1];
dc_key.ino[2] = st.st_ino[2];
2000-01-22 13:43:03 +08:00
# else
dc_key.ino = st.st_ino;
2000-01-22 13:43:03 +08:00
# endif
#endif
dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
dc = *dc_slot;
1992-10-10 01:35:07 +08:00
if (HASH_VACANT (dc))
1992-10-10 01:35:07 +08:00
{
/* Nope; this really is a directory we haven't seen before. */
dc = (struct directory_contents *)
xmalloc (sizeof (struct directory_contents));
/* Enter it in the contents hash table. */
dc->dev = st.st_dev;
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
dc->path_key = xstrdup (w32_path);
dc->ctime = st.st_ctime;
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
dc->mtime = st.st_mtime;
1997-04-07 15:21:16 +08:00
/*
* NTFS is the only WINDOWS32 filesystem that bumps mtime
* on a directory when files are added/deleted from
* a directory.
*/
w32_path[3] = '\0';
if (GetVolumeInformation(w32_path,
fs_label, sizeof (fs_label),
&fs_serno, &fs_len,
&fs_flags, fs_type, sizeof (fs_type)) == FALSE)
dc->fs_flags = FS_UNKNOWN;
else if (!strcmp(fs_type, "FAT"))
dc->fs_flags = FS_FAT;
else if (!strcmp(fs_type, "NTFS"))
dc->fs_flags = FS_NTFS;
else
dc->fs_flags = FS_UNKNOWN;
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#else
2000-01-22 13:43:03 +08:00
# ifdef VMS
dc->ino[0] = st.st_ino[0];
dc->ino[1] = st.st_ino[1];
dc->ino[2] = st.st_ino[2];
2000-01-22 13:43:03 +08:00
# else
1992-10-10 01:35:07 +08:00
dc->ino = st.st_ino;
2000-01-22 13:43:03 +08:00
# endif
1997-04-07 15:21:16 +08:00
#endif /* WINDOWS32 */
hash_insert_at (&directory_contents, dc, dc_slot);
ENULLLOOP (dc->dirstream, opendir (name));
1992-10-10 01:35:07 +08:00
if (dc->dirstream == 0)
/* Couldn't open the directory. Mark this by setting the
`files' member to a nil pointer. */
dc->dirfiles.ht_vec = 0;
1992-10-10 01:35:07 +08:00
else
{
hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
1992-10-10 01:35:07 +08:00
/* Keep track of how many directories are open. */
++open_directories;
if (open_directories == MAX_OPEN_DIRECTORIES)
/* We have too many directories open already.
Read the entire directory and then close it. */
dir_contents_file_exists_p (dc, 0);
1992-10-10 01:35:07 +08:00
}
}
/* Point the name-hashed entry for DIR at its contents data. */
dir->contents = dc;
1991-10-19 03:26:24 +08:00
}
}
return dir;
}
1992-10-10 01:35:07 +08:00
/* Return 1 if the name FILENAME is entered in DIR's hash table.
1991-10-19 03:26:24 +08:00
FILENAME must contain no slashes. */
1992-10-10 01:35:07 +08:00
static int
dir_contents_file_exists_p (struct directory_contents *dir,
const char *filename)
1991-10-19 03:26:24 +08:00
{
unsigned int hash;
struct dirfile *df;
struct dirent *d;
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
struct stat st;
int rehash = 0;
#endif
1991-10-19 03:26:24 +08:00
if (dir == 0 || dir->dirfiles.ht_vec == 0)
1992-10-10 01:35:07 +08:00
/* The directory could not be stat'd or opened. */
return 0;
#ifdef __MSDOS__
filename = dosify (filename);
#endif
1998-07-31 04:54:47 +08:00
#ifdef HAVE_CASE_INSENSITIVE_FS
filename = downcase (filename);
#endif
#ifdef __EMX__
if (filename != 0)
_fnlwr (filename); /* lower case for FAT drives */
#endif
#ifdef VMS
filename = vmsify (filename,0);
#endif
1991-10-19 03:26:24 +08:00
hash = 0;
if (filename != 0)
{
struct dirfile dirfile_key;
1991-10-19 03:26:24 +08:00
if (*filename == '\0')
{
/* Checking if the directory exists. */
return 1;
}
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
df = hash_find_item (&dir->dirfiles, &dirfile_key);
if (df)
return !df->impossible;
1991-10-19 03:26:24 +08:00
}
/* The file was not found in the hashed list.
Try to read the directory further. */
if (dir->dirstream == 0)
{
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
/*
* Check to see if directory has changed since last read. FAT
* filesystems force a rehash always as mtime does not change
* on directories (ugh!).
*/
if (dir->path_key)
{
if ((dir->fs_flags & FS_FAT) != 0)
{
dir->mtime = time ((time_t *) 0);
rehash = 1;
}
else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
{
/* reset date stamp to show most recent re-process. */
dir->mtime = st.st_mtime;
rehash = 1;
}
/* If it has been already read in, all done. */
if (!rehash)
return 0;
/* make sure directory can still be opened; if not return. */
dir->dirstream = opendir (dir->path_key);
if (!dir->dirstream)
return 0;
}
else
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#endif
/* The directory has been all read in. */
return 0;
}
1991-10-19 03:26:24 +08:00
while (1)
1991-10-19 03:26:24 +08:00
{
/* Enter the file in the hash table. */
1993-06-03 04:56:37 +08:00
unsigned int len;
struct dirfile dirfile_key;
struct dirfile **dirfile_slot;
1991-10-19 03:26:24 +08:00
ENULLLOOP (d, readdir (dir->dirstream));
if (d == 0)
{
if (errno)
fatal (NILF, "INTERNAL: readdir: %s\n", strerror (errno));
break;
}
2000-01-22 13:43:03 +08:00
#if defined(VMS) && defined(HAVE_DIRENT_H)
/* In VMS we get file versions too, which have to be stripped off */
{
char *p = strrchr (d->d_name, ';');
if (p)
*p = '\0';
}
#endif
1991-10-19 03:26:24 +08:00
if (!REAL_DIR_ENTRY (d))
continue;
len = NAMLEN (d);
dirfile_key.name = d->d_name;
dirfile_key.length = len;
dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
/*
* If re-reading a directory, don't cache files that have
* already been discovered.
*/
if (! rehash || HASH_VACANT (*dirfile_slot))
Wed May 15 10:14:14 CDT 1996 Rob Tulloh <tulloh@tivoli.com> * dir.c: WIN32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on WIN32 right now so it is lumped under port #ifdef WIN32. * function.c: WIN32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: WIN32: Added the code to do fork/exec/waitpid style processing on WIN32 systems via calls to subproc library. * main.c: WIN32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: WIN32: A few macros and header files for WIN32 support. * misc.c: WIN32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: WIN32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: WIN32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on WIN32. * variable.c: WIN32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: WIN32: Added detection for filenames containing forward or backward slashes. * NMakefile: WIN32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.WIN32: WIN32: Contains some helpful notes. * build_w32.bat: WIN32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.WIN32: WIN32 version of config.h * subproc.bat: WIN32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: WIN32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: WIN32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: WIN32: prototypes for subproc.lib functions. * w32/include/w32err.h: WIN32: prototypes for w32err.c. * w32/pathstuff.c: WIN32: File and Path/Path conversion functions. * w32/subproc/build.bat: WIN32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: WIN32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: WIN32: subproc library support code * w32/subproc/proc.h: WIN32: subproc library support code * w32/subproc/sub_proc.c: WIN32: subproc library source code * w32/subproc/w32err.c: WIN32: subproc library support code
1996-05-23 05:51:45 +08:00
#endif
{
df = xmalloc (sizeof (struct dirfile));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
df->name = strcache_add_len (downcase(d->d_name), len);
#else
df->name = strcache_add_len (d->d_name, len);
#endif
df->length = len;
df->impossible = 0;
hash_insert_at (&dir->dirfiles, df, dirfile_slot);
}
1991-10-19 03:26:24 +08:00
/* Check if the name matches the one we're searching for. */
if (filename != 0 && patheq (d->d_name, filename))
return 1;
1991-10-19 03:26:24 +08:00
}
/* If the directory has been completely read in,
close the stream and reset the pointer to nil. */
if (d == 0)
{
--open_directories;
closedir (dir->dirstream);
dir->dirstream = 0;
}
return 0;
}
1992-10-10 01:35:07 +08:00
/* Return 1 if the name FILENAME in directory DIRNAME
is entered in the dir hash table.
FILENAME must contain no slashes. */
int
dir_file_exists_p (const char *dirname, const char *filename)
1992-10-10 01:35:07 +08:00
{
return dir_contents_file_exists_p (find_directory (dirname)->contents,
filename);
}
1991-10-19 03:26:24 +08:00
/* Return 1 if the file named NAME exists. */
int
file_exists_p (const char *name)
1991-10-19 03:26:24 +08:00
{
const char *dirend;
const char *dirname;
const char *slash;
1991-10-19 03:26:24 +08:00
#ifndef NO_ARCHIVES
if (ar_name (name))
return ar_member_date (name) != (time_t) -1;
#endif
#ifdef VMS
dirend = strrchr (name, ']');
2000-01-22 13:43:03 +08:00
if (dirend == 0)
dirend = strrchr (name, ':');
if (dirend == 0)
return dir_file_exists_p ("[]", name);
#else /* !VMS */
dirend = strrchr (name, '/');
#ifdef HAVE_DOS_PATHS
1997-04-07 15:21:16 +08:00
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
const char *bslash = strrchr(name, '\\');
1997-04-07 15:21:16 +08:00
if (!dirend || bslash > dirend)
dirend = bslash;
1998-07-31 04:54:47 +08:00
/* The case of "d:file". */
if (!dirend && name[0] && name[1] == ':')
dirend = name + 1;
1997-04-07 15:21:16 +08:00
}
#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
#ifndef _AMIGA
return dir_file_exists_p (".", name);
#else /* !VMS && !AMIGA */
return dir_file_exists_p ("", name);
#endif /* AMIGA */
#endif /* VMS */
1991-10-19 03:26:24 +08:00
1998-07-31 04:54:47 +08:00
slash = dirend;
1997-04-07 15:21:16 +08:00
if (dirend == name)
dirname = "/";
else
{
char *p;
#ifdef HAVE_DOS_PATHS
1998-07-31 04:54:47 +08:00
/* d:/ and d: are *very* different... */
if (dirend < name + 3 && name[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
dirend++;
#endif
p = alloca (dirend - name + 1);
memcpy (p, name, dirend - name);
p[dirend - name] = '\0';
dirname = p;
1997-04-07 15:21:16 +08:00
}
1998-07-31 04:54:47 +08:00
return dir_file_exists_p (dirname, slash + 1);
1991-10-19 03:26:24 +08:00
}
/* Mark FILENAME as `impossible' for `file_impossible_p'.
This means an attempt has been made to search for FILENAME
as an intermediate file, and it has failed. */
void
file_impossible (const char *filename)
1991-10-19 03:26:24 +08:00
{
const char *dirend;
const char *p = filename;
struct directory *dir;
struct dirfile *new;
1991-10-19 03:26:24 +08:00
#ifdef VMS
dirend = strrchr (p, ']');
2000-01-22 13:43:03 +08:00
if (dirend == 0)
dirend = strrchr (p, ':');
dirend++;
if (dirend == (char *)1)
dir = find_directory ("[]");
#else
dirend = strrchr (p, '/');
# ifdef HAVE_DOS_PATHS
1997-04-07 15:21:16 +08:00
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
const char *bslash = strrchr(p, '\\');
1997-04-07 15:21:16 +08:00
if (!dirend || bslash > dirend)
dirend = bslash;
1998-07-31 04:54:47 +08:00
/* The case of "d:file". */
if (!dirend && p[0] && p[1] == ':')
dirend = p + 1;
1997-04-07 15:21:16 +08:00
}
# endif /* HAVE_DOS_PATHS */
1991-10-19 03:26:24 +08:00
if (dirend == 0)
# ifdef _AMIGA
dir = find_directory ("");
# else /* !VMS && !AMIGA */
1991-10-19 03:26:24 +08:00
dir = find_directory (".");
# endif /* AMIGA */
#endif /* VMS */
1991-10-19 03:26:24 +08:00
else
{
const char *dirname;
const char *slash = dirend;
1997-04-07 15:21:16 +08:00
if (dirend == p)
dirname = "/";
else
{
char *cp;
#ifdef HAVE_DOS_PATHS
1998-07-31 04:54:47 +08:00
/* d:/ and d: are *very* different... */
if (dirend < p + 3 && p[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
dirend++;
#endif
cp = alloca (dirend - p + 1);
memcpy (cp, p, dirend - p);
cp[dirend - p] = '\0';
dirname = cp;
1997-04-07 15:21:16 +08:00
}
1991-10-19 03:26:24 +08:00
dir = find_directory (dirname);
1998-07-31 04:54:47 +08:00
filename = p = slash + 1;
1991-10-19 03:26:24 +08:00
}
1992-10-10 01:35:07 +08:00
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 = xcalloc (sizeof (struct directory_contents));
1992-10-10 01:35:07 +08:00
if (dir->contents->dirfiles.ht_vec == 0)
1991-10-19 03:26:24 +08:00
{
hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
1991-10-19 03:26:24 +08:00
}
/* Make a new entry and put it in the table. */
new = xmalloc (sizeof (struct dirfile));
new->length = strlen (filename);
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
new->name = strcache_add_len (downcase(filename), new->length);
#else
new->name = strcache_add_len (filename, new->length);
#endif
1991-10-19 03:26:24 +08:00
new->impossible = 1;
hash_insert (&dir->contents->dirfiles, new);
1991-10-19 03:26:24 +08:00
}
/* Return nonzero if FILENAME has been marked impossible. */
int
file_impossible_p (const char *filename)
1991-10-19 03:26:24 +08:00
{
const char *dirend;
const char *p = filename;
struct directory_contents *dir;
struct dirfile *dirfile;
struct dirfile dirfile_key;
1991-10-19 03:26:24 +08:00
#ifdef VMS
dirend = strrchr (filename, ']');
if (dirend == 0)
dir = find_directory ("[]")->contents;
#else
dirend = strrchr (filename, '/');
#ifdef HAVE_DOS_PATHS
1997-04-07 15:21:16 +08:00
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
const char *bslash = strrchr(filename, '\\');
1997-04-07 15:21:16 +08:00
if (!dirend || bslash > dirend)
dirend = bslash;
1998-07-31 04:54:47 +08:00
/* The case of "d:file". */
if (!dirend && filename[0] && filename[1] == ':')
dirend = filename + 1;
1997-04-07 15:21:16 +08:00
}
#endif /* HAVE_DOS_PATHS */
1991-10-19 03:26:24 +08:00
if (dirend == 0)
#ifdef _AMIGA
dir = find_directory ("")->contents;
#else /* !VMS && !AMIGA */
1992-10-10 01:35:07 +08:00
dir = find_directory (".")->contents;
#endif /* AMIGA */
#endif /* VMS */
1991-10-19 03:26:24 +08:00
else
{
const char *dirname;
const char *slash = dirend;
1997-04-07 15:21:16 +08:00
if (dirend == filename)
dirname = "/";
else
{
char *cp;
#ifdef HAVE_DOS_PATHS
1998-07-31 04:54:47 +08:00
/* d:/ and d: are *very* different... */
if (dirend < filename + 3 && filename[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
dirend++;
#endif
cp = alloca (dirend - filename + 1);
memcpy (cp, p, dirend - p);
cp[dirend - p] = '\0';
dirname = cp;
1997-04-07 15:21:16 +08:00
}
1992-10-10 01:35:07 +08:00
dir = find_directory (dirname)->contents;
1998-07-31 04:54:47 +08:00
p = filename = slash + 1;
1991-10-19 03:26:24 +08:00
}
if (dir == 0 || dir->dirfiles.ht_vec == 0)
1991-10-19 03:26:24 +08:00
/* There are no files entered for this directory. */
return 0;
#ifdef __MSDOS__
filename = dosify (p);
#endif
1998-07-31 04:54:47 +08:00
#ifdef HAVE_CASE_INSENSITIVE_FS
filename = downcase (p);
#endif
#ifdef VMS
filename = vmsify (p, 1);
#endif
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
dirfile = hash_find_item (&dir->dirfiles, &dirfile_key);
if (dirfile)
return dirfile->impossible;
1991-10-19 03:26:24 +08:00
return 0;
}
/* Return the already allocated name in the
directory hash table that matches DIR. */
const char *
dir_name (const char *dir)
1991-10-19 03:26:24 +08:00
{
return find_directory (dir)->name;
}
/* Print the data base of directories. */
void
print_dir_data_base (void)
1991-10-19 03:26:24 +08:00
{
unsigned int files;
unsigned int impossible;
struct directory **dir_slot;
struct directory **dir_end;
1991-10-19 03:26:24 +08:00
puts (_("\n# Directories\n"));
1991-10-19 03:26:24 +08:00
files = impossible = 0;
dir_slot = (struct directory **) directories.ht_vec;
dir_end = dir_slot + directories.ht_size;
for ( ; dir_slot < dir_end; dir_slot++)
{
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)
{
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
dir->name, dir->contents->path_key,dir->contents->mtime);
1997-04-07 15:21:16 +08:00
#else /* WINDOWS32 */
#ifdef VMS
printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
dir->name, (long int) dir->contents->dev,
(long int) dir->contents->ino);
#endif
1997-04-07 15:21:16 +08:00
#endif /* WINDOWS32 */
}
else
{
unsigned int f = 0;
unsigned int im = 0;
struct dirfile **files_slot;
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++)
{
struct dirfile *df = *files_slot;
if (! HASH_VACANT (df))
{
if (df->impossible)
++im;
else
++f;
}
}
1997-04-07 15:21:16 +08:00
#ifdef WINDOWS32
printf (_("# %s (key %s, mtime %d): "),
dir->name, dir->contents->path_key, dir->contents->mtime);
1997-04-07 15:21:16 +08:00
#else /* WINDOWS32 */
#ifdef VMS
printf (_("# %s (device %d, inode [%d,%d,%d]): "),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
dir->contents->ino[2]);
#else
printf (_("# %s (device %ld, inode %ld): "),
dir->name,
(long)dir->contents->dev, (long)dir->contents->ino);
#endif
1997-04-07 15:21:16 +08:00
#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;
}
}
}
1991-10-19 03:26:24 +08:00
fputs ("\n# ", stdout);
if (files == 0)
fputs (_("No"), stdout);
1991-10-19 03:26:24 +08:00
else
printf ("%u", files);
fputs (_(" files, "), stdout);
1991-10-19 03:26:24 +08:00
if (impossible == 0)
fputs (_("no"), stdout);
1991-10-19 03:26:24 +08:00
else
printf ("%u", impossible);
printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill);
1991-10-19 03:26:24 +08:00
}
1992-10-12 05:25:04 +08:00
/* Hooks for globbing. */
#include <glob.h>
/* Structure describing state of iterating through a directory hash table. */
struct dirstream
{
struct directory_contents *contents; /* The directory being read. */
struct dirfile **dirfile_slot; /* Current slot in table. */
1992-10-12 05:25:04 +08:00
};
1993-01-23 03:46:10 +08:00
/* Forward declarations. */
static __ptr_t open_dirstream (const char *);
static struct dirent *read_dirstream (__ptr_t);
1993-01-23 03:46:10 +08:00
1992-10-12 05:25:04 +08:00
static __ptr_t
open_dirstream (const char *directory)
1992-10-12 05:25:04 +08:00
{
struct dirstream *new;
struct directory *dir = find_directory (directory);
1992-10-12 05:25:04 +08:00
if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0)
1992-11-11 04:43:35 +08:00
/* DIR->contents is nil if the directory could not be stat'd.
DIR->contents->dirfiles is nil if it could not be opened. */
1992-10-12 05:25:04 +08:00
return 0;
/* Read all the contents of the directory now. There is no benefit
in being lazy, since glob will want to see every file anyway. */
dir_contents_file_exists_p (dir->contents, 0);
1992-10-12 05:25:04 +08:00
new = xmalloc (sizeof (struct dirstream));
1992-10-12 05:25:04 +08:00
new->contents = dir->contents;
new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec;
1992-10-12 05:25:04 +08:00
1992-10-16 07:11:04 +08:00
return (__ptr_t) new;
1992-10-12 05:25:04 +08:00
}
static struct dirent *
read_dirstream (__ptr_t stream)
1992-10-12 05:25:04 +08:00
{
static char *buf;
static unsigned int bufsz;
1992-10-12 05:25:04 +08:00
struct dirstream *const ds = (struct dirstream *) stream;
struct directory_contents *dc = ds->contents;
struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size;
1992-10-12 05:25:04 +08:00
while (ds->dirfile_slot < dirfile_end)
1992-10-12 05:25:04 +08:00
{
struct dirfile *df = *ds->dirfile_slot++;
if (! HASH_VACANT (df) && !df->impossible)
1992-10-12 05:25:04 +08:00
{
/* The glob interface wants a `struct dirent', so mock one up. */
struct dirent *d;
unsigned int len = df->length + 1;
unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len;
if (sz > bufsz)
{
bufsz *= 2;
if (sz > bufsz)
bufsz = sz;
buf = xrealloc (buf, bufsz);
}
d = (struct dirent *) buf;
#ifdef __MINGW32__
# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
__MINGW32_MINOR_VERSION == 0)
d->d_name = xmalloc(len);
# endif
#endif
FAKE_DIR_ENTRY (d);
#ifdef _DIRENT_HAVE_D_NAMLEN
d->d_namlen = len - 1;
#endif
#ifdef _DIRENT_HAVE_D_TYPE
d->d_type = DT_UNKNOWN;
#endif
memcpy (d->d_name, df->name, len);
return d;
1992-10-12 05:25:04 +08:00
}
}
1992-10-13 02:05:41 +08:00
return 0;
1992-10-12 05:25:04 +08:00
}
1998-07-31 04:54:47 +08:00
static void
ansi_free (void *p)
1998-07-31 04:54:47 +08:00
{
if (p)
free(p);
1998-07-31 04:54:47 +08:00
}
/* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a
* macro for stat64(). If stat is a macro, make a local wrapper function to
* invoke it.
*/
#ifndef stat
# ifndef VMS
int stat (const char *path, struct stat *sbuf);
# endif
# define local_stat stat
#else
static int
local_stat (const char *path, struct stat *buf)
{
int e;
EINTRLOOP (e, stat (path, buf));
return e;
}
#endif
1992-10-12 05:25:04 +08:00
void
dir_setup_glob (glob_t *gl)
1992-10-12 05:25:04 +08:00
{
gl->gl_opendir = open_dirstream;
gl->gl_readdir = read_dirstream;
1998-07-31 04:54:47 +08:00
gl->gl_closedir = ansi_free;
gl->gl_stat = local_stat;
/* We don't bother setting gl_lstat, since glob never calls it.
The slot is only there for compatibility with 4.4 BSD. */
1992-10-12 05:25:04 +08:00
}
void
hash_init_directories (void)
{
hash_init (&directories, DIRECTORY_BUCKETS,
directory_hash_1, directory_hash_2, directory_hash_cmp);
hash_init (&directory_contents, DIRECTORY_BUCKETS,
directory_contents_hash_1, directory_contents_hash_2,
directory_contents_hash_cmp);
}