#include "make.h" #include "hash.h" #include # ifdef HAVE_DOS_PATHS # define IS_PATHSEP(c) ((c) == '/' || (c) == '\\') # define IS_DRIVESEP(c) ((c) == ';') # else # define IS_PATHSEP(c) ((c) == '/') # define IS_DRIVESEP(c) 0 # endif #if 0 # define log(s) printf s, fflush(stdout) #else # define log(s) #endif int cache_flg; int cache_n1; int cache_n2; int stat_n; int stat_n2; int t0; void dir_atexit(void) { #if 0 int t; if (cache_n1 || cache_n2) printf("cache queries: %d/%d - stat calls: %d\n\n", cache_n1, cache_n2, stat_n); else printf("make stat calls: %d (%d)\n", stat_n, stat_n2); t = clock() - t0; printf("Time: %d.%d\n", t / 1000, t % 1000); #endif } int STAT (const char *path, struct stat *sbuf) { int r = stat(path, sbuf); log(("stat (%d) %s\n", r, path)); ++stat_n; if (-1 != r) ++stat_n2; return r; } /* Return 1 if the name FILENAME in directory DIRNAME exists. */ int dir_file_exists_p (const char *dirname, const char *filename) { char path[4000]; int x, y, n; x = dirname ? strlen(dirname) : 0; y = filename ? strlen(filename) : 0; n = 0; if (x) { memcpy(path + n, dirname, x); n += x; } if (y) { if (n && !IS_PATHSEP(path[n-1])) path[n++] = '/'; memcpy(path + n, filename, y); n += y; } path[n] = 0; return file_exists_p(path); } /* Return 1 if the file named NAME exists. */ int file_exists_p (const char *filename) { struct stat sb; int r; #ifdef WINDOWS32 char tmp[1000]; int n = strlen(filename); if (n >= 2 && IS_PATHSEP(filename[n-1]) && !IS_DRIVESEP(filename[n-2]) && n < sizeof tmp) { memcpy(tmp, filename, --n); tmp[n] = 0; filename = tmp; } #endif EINTRLOOP (r, STAT (filename, &sb)); r = -1 != r; //log(("file_exists (%d) %s\n", r, filename)); return r; } /* ----------------------------------------------------------------------- */ /* 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. */ static struct hash_table impossible_tab; struct impossible_file { char name[1]; }; static unsigned long impossible_hash_1 (const void *key) { return_STRING_HASH_1 (((const struct impossible_file *) key)->name); } static unsigned long impossible_hash_2 (const void *key) { return_STRING_HASH_2 (((const struct impossible_file *) key)->name); } static int impossible_hash_cmp (const void *x, const void *y) { return_STRING_COMPARE ( ((const struct impossible_file *) x)->name, ((const struct impossible_file *) y)->name ); } void file_impossible (const char *filename) { struct impossible_file *p; int l; l = strlen(filename); p = (struct impossible_file *)xmalloc(sizeof *p + l); memcpy(p->name, filename, l+1); hash_insert (&impossible_tab, p); log(("file_impossible: %s\n", filename)); } /* Return nonzero if FILENAME has been marked impossible. */ int file_impossible_p (const char *filename) { struct impossible_file *p; int r; p = hash_find_item (&impossible_tab, filename); r = NULL != p; log(("file_impossible_p: (%d) %s\n", r, filename)); return r; } void file_impossible_reset(const char *filename) { hash_free_items(&impossible_tab); log(("file_impossible_reset %s\n", filename)); } /* ----------------------------------------------------------------------- */ /* Return the already allocated name in the directory hash table that matches DIR. */ const char * dir_name (const char *dir) { // log(("dir_name: %s\n", dir)); return strcache_add(dir); } /* Print the data base of directories. */ void print_dir_data_base (void) { // puts (_("\n# Directories\n")); } void hash_init_directories (void) { hash_init (&impossible_tab, 32, impossible_hash_1, impossible_hash_2, impossible_hash_cmp); t0 = clock(); atexit(dir_atexit); } /* ----------------------------------------------------------------------- */ /* Hooks for globbing. */ #include #include static int local_stat (const char *path, struct stat *buf) { int e; EINTRLOOP (e, STAT (path, buf)); return e; } void dir_setup_glob (glob_t *gl) { gl->gl_opendir = (void*)opendir; gl->gl_readdir = (void*)readdir; gl->gl_closedir = (void*)closedir; gl->gl_stat = (void*)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. */ } /* ----------------------------------------------------------------------- */