version 1.40, 2003/06/03 02:56:11 |
version 1.41, 2004/04/07 13:11:35 |
|
|
static void DirPrintDir(void *); |
static void DirPrintDir(void *); |
|
|
static void |
static void |
record_stamp(file, t) |
record_stamp(const char *file, TIMESTAMP t) |
const char *file; |
|
TIMESTAMP t; |
|
{ |
{ |
unsigned int slot; |
unsigned int slot; |
const char *end = NULL; |
const char *end = NULL; |
|
|
} |
} |
|
|
static struct file_stamp * |
static struct file_stamp * |
find_stampi(file, end) |
find_stampi(const char *file, const char *efile) |
const char *file; |
|
const char *end; |
|
{ |
{ |
return ohash_find(&mtimes, ohash_qlookupi(&mtimes, file, &end)); |
return ohash_find(&mtimes, ohash_qlookupi(&mtimes, file, &efile)); |
} |
} |
|
|
static void |
static void |
add_file(p, file) |
add_file(Path *p, const char *file) |
Path *p; |
|
const char *file; |
|
{ |
{ |
unsigned int slot; |
unsigned int slot; |
const char *end = NULL; |
const char *end = NULL; |
|
|
} |
} |
|
|
static char * |
static char * |
find_file_hashi(p, file, e, hv) |
find_file_hashi(Path *p, const char *file, const char *efile, u_int32_t hv) |
Path *p; |
|
const char *file; |
|
const char *e; |
|
u_int32_t hv; |
|
{ |
{ |
struct ohash *h = &p->files; |
struct ohash *h = &p->files; |
|
|
return ohash_find(h, ohash_lookup_interval(h, file, e, hv)); |
return ohash_find(h, ohash_lookup_interval(h, file, efile, hv)); |
} |
} |
|
|
static void |
static void |
free_hash(h) |
free_hash(struct ohash *h) |
struct ohash *h; |
|
{ |
{ |
void *e; |
void *e; |
unsigned int i; |
unsigned int i; |
|
|
|
|
/* Side Effects: cache the current directory */ |
/* Side Effects: cache the current directory */ |
void |
void |
Dir_Init() |
Dir_Init(void) |
{ |
{ |
char *dotname = "."; |
char *dotname = "."; |
|
|
|
|
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
void |
void |
Dir_End() |
Dir_End(void) |
{ |
{ |
struct Path *p; |
struct Path *p; |
unsigned int i; |
unsigned int i; |
|
|
|
|
/* XXX: This code is not 100% correct ([^]] fails) */ |
/* XXX: This code is not 100% correct ([^]] fails) */ |
bool |
bool |
Dir_HasWildcardsi(name, end) |
Dir_HasWildcardsi(const char *name, const char *ename) |
const char *name; |
|
const char *end; |
|
{ |
{ |
const char *cp; |
const char *cp; |
bool wild = false; |
bool wild = false; |
unsigned long brace = 0, bracket = 0; |
unsigned long brace = 0, bracket = 0; |
|
|
for (cp = name; cp != end; cp++) { |
for (cp = name; cp != ename; cp++) { |
switch (*cp) { |
switch (*cp) { |
case '{': |
case '{': |
brace++; |
brace++; |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
DirMatchFilesi(pattern, end, p, expansions) |
DirMatchFilesi(const char *word, const char *eword, Path *p, Lst expansions) |
const char *pattern; /* Pattern to look for */ |
|
const char *end; /* End of pattern */ |
|
Path *p; /* Directory to search */ |
|
Lst expansions; /* Place to store the results */ |
|
{ |
{ |
unsigned int search; /* Index into the directory's table */ |
unsigned int search; /* Index into the directory's table */ |
const char *entry; /* Current entry in the table */ |
const char *entry; /* Current entry in the table */ |
|
|
* convention that dot files will only be found if the pattern |
* convention that dot files will only be found if the pattern |
* begins with a dot (the hashing scheme doesn't hash . or .., |
* begins with a dot (the hashing scheme doesn't hash . or .., |
* so they won't match `.*'. */ |
* so they won't match `.*'. */ |
if (*pattern != '.' && *entry == '.') |
if (*word != '.' && *entry == '.') |
continue; |
continue; |
if (Str_Matchi(entry, strchr(entry, '\0'), pattern, end)) |
if (Str_Matchi(entry, strchr(entry, '\0'), word, eword)) |
Lst_AtEnd(expansions, |
Lst_AtEnd(expansions, |
isDot ? estrdup(entry) : Str_concat(p->name, entry, '/')); |
isDot ? estrdup(entry) : Str_concat(p->name, entry, '/')); |
} |
} |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
PathMatchFilesi(word, end, path, expansions) |
PathMatchFilesi(const char *word, const char *eword, Lst path, Lst expansions) |
const char *word; /* Word to expand */ |
|
const char *end; /* End of word */ |
|
Lst path; /* Path on which to look */ |
|
Lst expansions; /* Place to store the result */ |
|
{ |
{ |
LstNode ln; /* Current node */ |
LstNode ln; /* Current node */ |
|
|
for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) |
for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) |
DirMatchFilesi(word, end, (Path *)Lst_Datum(ln), expansions); |
DirMatchFilesi(word, eword, (Path *)Lst_Datum(ln), expansions); |
} |
} |
|
|
static void |
static void |
DirPrintWord(word) |
DirPrintWord(void *word) |
void *word; |
|
{ |
{ |
printf("%s ", (char *)word); |
printf("%s ", (char *)word); |
} |
} |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
DirExpandWildi(word, end, path, expansions) |
DirExpandWildi(const char *word, const char *eword, Lst path, Lst expansions) |
const char *word; /* the word to expand */ |
|
const char *end; /* end of word */ |
|
Lst path; /* the list of directories in which to find |
|
* the resulting files */ |
|
Lst expansions; /* the list on which to place the results */ |
|
{ |
{ |
const char *cp; |
const char *cp; |
const char *slash; /* keep track of first slash before wildcard */ |
const char *slash; /* keep track of first slash before wildcard */ |
|
|
slash = memchr(word, '/', end - word); |
slash = memchr(word, '/', eword - word); |
if (slash == NULL) { |
if (slash == NULL) { |
/* First the files in dot. */ |
/* First the files in dot. */ |
DirMatchFilesi(word, end, dot, expansions); |
DirMatchFilesi(word, eword, dot, expansions); |
|
|
/* Then the files in every other directory on the path. */ |
/* Then the files in every other directory on the path. */ |
PathMatchFilesi(word, end, path, expansions); |
PathMatchFilesi(word, eword, path, expansions); |
return; |
return; |
} |
} |
/* The thing has a directory component -- find the first wildcard |
/* The thing has a directory component -- find the first wildcard |
* in the string. */ |
* in the string. */ |
slash = word; |
slash = word; |
for (cp = word; cp != end; cp++) { |
for (cp = word; cp != eword; cp++) { |
if (*cp == '/') |
if (*cp == '/') |
slash = cp; |
slash = cp; |
if (*cp == '?' || *cp == '[' || *cp == '*') { |
if (*cp == '?' || *cp == '[' || *cp == '*') { |
|
|
|
|
Lst_Init(&temp); |
Lst_Init(&temp); |
Dir_AddDiri(&temp, dirpath, dp); |
Dir_AddDiri(&temp, dirpath, dp); |
PathMatchFilesi(slash+1, end, &temp, expansions); |
PathMatchFilesi(slash+1, eword, &temp, expansions); |
Lst_Destroy(&temp, NOFREE); |
Lst_Destroy(&temp, NOFREE); |
} |
} |
} else |
} else |
/* Start the search from the local directory. */ |
/* Start the search from the local directory. */ |
PathMatchFilesi(word, end, path, expansions); |
PathMatchFilesi(word, eword, path, expansions); |
return; |
return; |
} |
} |
} |
} |
/* Return the file -- this should never happen. */ |
/* Return the file -- this should never happen. */ |
PathMatchFilesi(word, end, path, expansions); |
PathMatchFilesi(word, eword, path, expansions); |
} |
} |
|
|
/*- |
/*- |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
DirExpandCurlyi(word, endw, path, expansions) |
DirExpandCurlyi(const char *word, const char *eword, Lst path, Lst expansions) |
const char *word; /* Entire word to expand */ |
|
const char *endw; /* End of word */ |
|
Lst path; /* Search path to use */ |
|
Lst expansions; /* Place to store the expansions */ |
|
{ |
{ |
const char *cp2; /* Pointer for checking for wildcards in |
const char *cp2; /* Pointer for checking for wildcards in |
* expansion before calling Dir_Expand */ |
* expansion before calling Dir_Expand */ |
|
|
|
|
/* Determine once and for all if there is something else going on */ |
/* Determine once and for all if there is something else going on */ |
dowild = false; |
dowild = false; |
for (cp2 = word; cp2 != endw; cp2++) |
for (cp2 = word; cp2 != eword; cp2++) |
if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') { |
if (*cp2 == '*' || *cp2 == '?' || *cp2 == '[') { |
dowild = true; |
dowild = true; |
break; |
break; |
|
|
|
|
/* Prime queue with copy of initial word */ |
/* Prime queue with copy of initial word */ |
Lst_Init(&curled); |
Lst_Init(&curled); |
Lst_EnQueue(&curled, Str_dupi(word, endw)); |
Lst_EnQueue(&curled, Str_dupi(word, eword)); |
while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) { |
while ((toexpand = (char *)Lst_DeQueue(&curled)) != NULL) { |
const char *brace; |
const char *brace; |
const char *start; /* Start of current chunk of brace clause */ |
const char *start; /* Start of current chunk of brace clause */ |
|
|
/* Side effects: |
/* Side effects: |
* Dir_Expandi will hash directories that were not yet visited */ |
* Dir_Expandi will hash directories that were not yet visited */ |
void |
void |
Dir_Expandi(word, end, path, expansions) |
Dir_Expandi(const char *word, const char *eword, Lst path, Lst expansions) |
const char *word; /* the word to expand */ |
|
const char *end; /* end of word */ |
|
Lst path; /* the list of directories in which to find |
|
* the resulting files */ |
|
Lst expansions; /* the list on which to place the results */ |
|
{ |
{ |
const char *cp; |
const char *cp; |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
char *s = Str_dupi(word, end); |
char *s = Str_dupi(word, eword); |
printf("expanding \"%s\"...", s); |
printf("expanding \"%s\"...", s); |
free(s); |
free(s); |
} |
} |
|
|
cp = memchr(word, '{', end - word); |
cp = memchr(word, '{', eword - word); |
if (cp) |
if (cp) |
DirExpandCurlyi(word, end, path, expansions); |
DirExpandCurlyi(word, eword, path, expansions); |
else |
else |
DirExpandWildi(word, end, path, expansions); |
DirExpandWildi(word, eword, path, expansions); |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
Lst_Every(expansions, DirPrintWord); |
Lst_Every(expansions, DirPrintWord); |
|
|
* that directory later on. |
* that directory later on. |
*/ |
*/ |
char * |
char * |
Dir_FindFilei(name, end, path) |
Dir_FindFilei(const char *name, const char *ename, Lst path) |
const char *name; |
|
const char *end; |
|
Lst path; |
|
{ |
{ |
Path *p; /* current path member */ |
Path *p; /* current path member */ |
char *p1; /* pointer into p->name */ |
char *p1; /* pointer into p->name */ |
|
|
struct stat stb; /* Buffer for stat, if necessary */ |
struct stat stb; /* Buffer for stat, if necessary */ |
struct file_stamp *entry; /* Entry for mtimes table */ |
struct file_stamp *entry; /* Entry for mtimes table */ |
u_int32_t hv; /* hash value for last component in file name */ |
u_int32_t hv; /* hash value for last component in file name */ |
char *q; /* Str_dupi(name, end) */ |
char *q; /* Str_dupi(name, ename) */ |
|
|
/* Find the final component of the name and note whether name has a |
/* Find the final component of the name and note whether name has a |
* slash in it */ |
* slash in it */ |
cp = Str_rchri(name, end, '/'); |
cp = Str_rchri(name, ename, '/'); |
if (cp) { |
if (cp) { |
hasSlash = true; |
hasSlash = true; |
cp++; |
cp++; |
|
|
cp = name; |
cp = name; |
} |
} |
|
|
hv = ohash_interval(cp, &end); |
hv = ohash_interval(cp, &ename); |
|
|
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("Searching for %s...", name); |
printf("Searching for %s...", name); |
|
|
* before anywhere else and we always return exactly what the caller |
* before anywhere else and we always return exactly what the caller |
* specified. */ |
* specified. */ |
if ((!hasSlash || (cp - name == 2 && *name == '.')) && |
if ((!hasSlash || (cp - name == 2 && *name == '.')) && |
find_file_hashi(dot, cp, end, hv) != NULL) { |
find_file_hashi(dot, cp, ename, hv) != NULL) { |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("in '.'\n"); |
printf("in '.'\n"); |
#ifdef DEBUG_DIRECTORY_CACHE |
#ifdef DEBUG_DIRECTORY_CACHE |
hits++; |
hits++; |
dot->hits++; |
dot->hits++; |
#endif |
#endif |
return Str_dupi(name, end); |
return Str_dupi(name, ename); |
} |
} |
|
|
/* Then, we look through all the directories on path, seeking one |
/* Then, we look through all the directories on path, seeking one |
|
|
p = (Path *)Lst_Datum(ln); |
p = (Path *)Lst_Datum(ln); |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("%s...", p->name); |
printf("%s...", p->name); |
if (find_file_hashi(p, cp, end, hv) != NULL) { |
if (find_file_hashi(p, cp, ename, hv) != NULL) { |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("here..."); |
printf("here..."); |
if (hasSlash) { |
if (hasSlash) { |
|
|
continue; |
continue; |
} |
} |
} |
} |
file = Str_concati(p->name, strchr(p->name, '\0'), cp, end, '/'); |
file = Str_concati(p->name, strchr(p->name, '\0'), cp, ename, '/'); |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("returning %s\n", file); |
printf("returning %s\n", file); |
#ifdef DEBUG_DIRECTORY_CACHE |
#ifdef DEBUG_DIRECTORY_CACHE |
|
|
for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { |
for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) { |
p = (Path *)Lst_Datum(ln); |
p = (Path *)Lst_Datum(ln); |
if (p != dot) |
if (p != dot) |
file = Str_concati(p->name, strchr(p->name, '\0'), name, end, '/'); |
file = Str_concati(p->name, strchr(p->name, '\0'), name, ename, '/'); |
else { |
else { |
/* Checking in dot -- DON'T put a leading ./ on the thing. */ |
/* Checking in dot -- DON'T put a leading ./ on the thing. */ |
file = Str_dupi(name, end); |
file = Str_dupi(name, ename); |
checkedDot = true; |
checkedDot = true; |
} |
} |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
|
|
* $(FILE) exists in $(INSTALLDIR) but not in the current one. |
* $(FILE) exists in $(INSTALLDIR) but not in the current one. |
* When searching for $(FILE), we will find it in $(INSTALLDIR) |
* When searching for $(FILE), we will find it in $(INSTALLDIR) |
* b/c we added it here. This is not good... */ |
* b/c we added it here. This is not good... */ |
q = Str_dupi(name, end); |
q = Str_dupi(name, ename); |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("Looking for \"%s\"...", q); |
printf("Looking for \"%s\"...", q); |
|
|
#ifdef DEBUG_DIRECTORY_CACHE |
#ifdef DEBUG_DIRECTORY_CACHE |
bigmisses++; |
bigmisses++; |
#endif |
#endif |
entry = find_stampi(name, end); |
entry = find_stampi(name, ename); |
if (entry != NULL) { |
if (entry != NULL) { |
if (DEBUG(DIR)) |
if (DEBUG(DIR)) |
printf("got it (in mtime cache)\n"); |
printf("got it (in mtime cache)\n"); |
|
|
|
|
/* Read a directory, either from the disk, or from the cache. */ |
/* Read a directory, either from the disk, or from the cache. */ |
static Path * |
static Path * |
DirReaddiri(name, end) |
DirReaddiri(const char *name, const char *ename) |
const char *name; |
|
const char *end; |
|
{ |
{ |
Path *p; /* pointer to new Path structure */ |
Path *p; /* pointer to new Path structure */ |
DIR *d; /* for reading directory */ |
DIR *d; /* for reading directory */ |
struct dirent *dp; /* entry in directory */ |
struct dirent *dp; /* entry in directory */ |
unsigned int slot; |
unsigned int slot; |
|
|
slot = ohash_qlookupi(&openDirectories, name, &end); |
slot = ohash_qlookupi(&openDirectories, name, &ename); |
p = ohash_find(&openDirectories, slot); |
p = ohash_find(&openDirectories, slot); |
|
|
if (p != NULL) |
if (p != NULL) |
return p; |
return p; |
|
|
p = ohash_create_entry(&dir_info, name, &end); |
p = ohash_create_entry(&dir_info, name, &ename); |
#ifdef DEBUG_DIRECTORY_CACHE |
#ifdef DEBUG_DIRECTORY_CACHE |
p->hits = 0; |
p->hits = 0; |
#endif |
#endif |
|
|
*/ |
*/ |
|
|
void |
void |
Dir_AddDiri(path, name, end) |
Dir_AddDiri(Lst path, const char *name, const char *ename) |
Lst path; /* the path to which the directory should be added */ |
|
const char *name; /* the name of the directory to add */ |
|
const char *end; |
|
{ |
{ |
Path *p; /* pointer to new Path structure */ |
Path *p; /* pointer to new Path structure */ |
|
|
p = DirReaddiri(name, end); |
p = DirReaddiri(name, ename); |
if (p == NULL) |
if (p == NULL) |
return; |
return; |
if (p->refCount == 0) |
if (p->refCount == 0) |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void * |
void * |
Dir_CopyDir(p) |
Dir_CopyDir(void *p) |
void *p; |
|
{ |
{ |
((Path *)p)->refCount++; |
((Path *)p)->refCount++; |
return p; |
return p; |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
char * |
char * |
Dir_MakeFlags(flag, path) |
Dir_MakeFlags(const char *flag, Lst path) |
const char *flag; /* flag which should precede each directory */ |
|
Lst path; /* list of directories */ |
|
{ |
{ |
LstNode ln; /* the node of the current directory */ |
LstNode ln; /* the node of the current directory */ |
BUFFER buf; |
BUFFER buf; |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Dir_Destroy(pp) |
Dir_Destroy(void *pp) |
void *pp; /* The directory descriptor to nuke */ |
|
{ |
{ |
Path *p = (Path *)pp; |
Path *p = (Path *)pp; |
|
|
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
void |
void |
Dir_Concat(path1, path2) |
Dir_Concat(Lst path1, Lst path2) |
Lst path1; /* Dest */ |
|
Lst path2; /* Source */ |
|
{ |
{ |
LstNode ln; |
LstNode ln; |
Path *p; |
Path *p; |
|
|
|
|
#ifdef DEBUG_DIRECTORY_CACHE |
#ifdef DEBUG_DIRECTORY_CACHE |
void |
void |
Dir_PrintDirectories() |
Dir_PrintDirectories(void) |
{ |
{ |
Path *p; |
Path *p; |
unsigned int i; |
unsigned int i; |
|
|
#endif |
#endif |
|
|
static void |
static void |
DirPrintDir(p) |
DirPrintDir(void *p) |
void *p; |
|
{ |
{ |
printf("%s ", ((Path *)p)->name); |
printf("%s ", ((Path *)p)->name); |
} |
} |
|
|
void |
void |
Dir_PrintPath(path) |
Dir_PrintPath(Lst path) |
Lst path; |
|
{ |
{ |
Lst_Every(path, DirPrintDir); |
Lst_Every(path, DirPrintDir); |
} |
} |
|
|
TIMESTAMP |
TIMESTAMP |
Dir_MTime(gn) |
Dir_MTime(GNode *gn) |
GNode *gn; /* the file whose modification time is |
|
* desired */ |
|
{ |
{ |
char *fullName; /* the full pathname of name */ |
char *fullName; /* the full pathname of name */ |
struct stat stb; /* buffer for finding the mod time */ |
struct stat stb; /* buffer for finding the mod time */ |