[BACK]Return to dir.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/dir.c between version 1.25 and 1.26

version 1.25, 2000/09/14 13:43:30 version 1.26, 2000/09/14 13:46:44
Line 194 
Line 194 
                              * be two rules to update a single file, so this                               * be two rules to update a single file, so this
                              * should be ok, but... */                               * should be ok, but... */
   
   static struct hash_info file_info = { 0,
       NULL, hash_alloc, hash_free, element_alloc };
   
 static struct hash_info dir_info = { offsetof(Path, name),  static struct hash_info dir_info = { offsetof(Path, name),
     NULL, hash_alloc, hash_free, element_alloc };      NULL, hash_alloc, hash_free, element_alloc };
   
   static void add_file __P((Path *, const char *));
   static char *find_file_hash __P((Path *, const char *, const char *, u_int32_t));
   static void free_hash __P((struct hash *));
   
 static Path *DirReaddir __P((const char *, const char *));  static Path *DirReaddir __P((const char *, const char *));
 static int DirMatchFiles __P((char *, Path *, Lst));  static void DirMatchFiles __P((char *, Path *, Lst));
 static void DirExpandCurly __P((char *, char *, Lst, Lst));  static void DirExpandCurly __P((char *, char *, Lst, Lst));
 static void DirExpandInt __P((char *, Lst, Lst));  static void DirExpandInt __P((char *, Lst, Lst));
 static void DirPrintWord __P((void *));  static void DirPrintWord __P((void *));
 static void DirPrintDir __P((void *));  static void DirPrintDir __P((void *));
   
   static void
   add_file(p, file)
       Path                *p;
       const char          *file;
   {
       unsigned            slot;
       const char          *end = NULL;
       char                *n;
       struct hash         *h = &p->files;
   
       slot = hash_qlookupi(h, file, &end);
       n = hash_find(h, slot);
       if (n == NULL) {
           n = hash_create_entry(&file_info, file, &end);
           hash_insert(h, slot, n);
       }
   }
   
   static char *
   find_file_hash(p, file, e, hv)
       Path                *p;
       const char          *file;
       const char          *e;
       u_int32_t           hv;
   {
       struct hash         *h = &p->files;
   
       return hash_find(h, hash_lookup_interval(h, file, e, hv));
   }
   
   static void
   free_hash(h)
       struct hash         *h;
   {
       void                *e;
       unsigned            i;
   
       for (e = hash_first(h, &i); e != NULL; e = hash_next(h, &i))
           free(e);
       hash_delete(h);
   }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Dir_Init --   * Dir_Init --
Line 320 
Line 369 
  *      src / *src / *.c properly (just *.c on any of the directories), but it   *      src / *src / *.c properly (just *.c on any of the directories), but it
  *      will do for now.   *      will do for now.
  *   *
  * Results:  
  *      Always returns 0  
  *  
  * Side Effects:   * Side Effects:
  *      File names are added to the expansions lst. The directory will be   *      File names are added to the expansions lst. The directory will be
  *      fully hashed when this is done.   *      fully hashed when this is done.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static void
 DirMatchFiles (pattern, p, expansions)  DirMatchFiles (pattern, p, expansions)
     char          *pattern;     /* Pattern to look for */      char          *pattern;     /* Pattern to look for */
     Path          *p;           /* Directory to search */      Path          *p;           /* Directory to search */
     Lst           expansions;   /* Place to store the results */      Lst           expansions;   /* Place to store the results */
 {  {
     Hash_Search   search;       /* Index into the directory's table */      unsigned int  search;       /* Index into the directory's table */
     Hash_Entry    *entry;       /* Current entry in the table */      char          *entry;       /* Current entry in the table */
     Boolean       isDot;        /* TRUE if the directory being searched is . */      Boolean       isDot;        /* TRUE if the directory being searched is . */
   
     isDot = (*p->name == '.' && p->name[1] == '\0');      isDot = (*p->name == '.' && p->name[1] == '\0');
   
     for (entry = Hash_EnumFirst(&p->files, &search);      for (entry = hash_first(&p->files, &search); entry != NULL;
          entry != (Hash_Entry *)NULL;           entry = hash_next(&p->files, &search)) {
          entry = Hash_EnumNext(&search))          /* See if the file matches the given pattern. Note we follow the UNIX
     {  
         /*  
          * See if the file matches the given pattern. Note we follow the UNIX  
          * 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 (note also that as a side effect of the hashing           * begins with a dot (note also that as a side effect of the hashing
          * scheme, .* won't match . or .. since they aren't hashed).           * scheme, .* won't match . or .. since they aren't hashed).  */
          */          if (*pattern != '.' && * entry == '.')
         if (Str_Match(entry->name, pattern) &&                  continue;
             ((entry->name[0] != '.') ||          if (Str_Match(entry, pattern))
              (pattern[0] == '.')))  
         {  
             Lst_AtEnd(expansions,              Lst_AtEnd(expansions,
                             (isDot ? estrdup(entry->name) :                              (isDot ? estrdup(entry) :
                              str_concat(p->name, entry->name, '/')));                               str_concat(p->name, entry, '/')));
         }  
     }      }
     return (0);  
 }  }
   
 /*-  /*-
Line 481 
Line 520 
  *      path one by one, calling DirMatchFiles for each. NOTE: This still   *      path one by one, calling DirMatchFiles for each. NOTE: This still
  *      doesn't handle patterns in directories...   *      doesn't handle patterns in directories...
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Things are added to the expansions list.   *      Things are added to the expansions list.
  *   *
Line 639 
Line 675 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 char *  char *
 Dir_FindFile (name, path)  Dir_FindFile(name, path)
     char          *name;    /* the file to find */      char          *name;    /* the file to find */
     Lst           path;     /* the Lst of directories to search */      Lst           path;     /* the Lst of directories to search */
 {  {
Line 651 
Line 687 
     register char *cp;      /* index of first slash, if any */      register char *cp;      /* index of first slash, if any */
     Boolean       hasSlash; /* true if 'name' contains a / */      Boolean       hasSlash; /* true if 'name' contains a / */
     struct stat   stb;      /* Buffer for stat, if necessary */      struct stat   stb;      /* Buffer for stat, if necessary */
     Hash_Entry    *entry;   /* Entry for mtimes table */      const char    *e;
       u_int32_t     hv;
       Hash_Entry    *entry;
   
     /*      /*
      * Find the final component of the name and note whether it has a       * Find the final component of the name and note whether it has a
      * slash in it (the name, I mean)       * slash in it (the name, I mean)
      */       */
     cp = strrchr (name, '/');      cp = strrchr(name, '/');
     if (cp) {      if (cp) {
         hasSlash = TRUE;          hasSlash = TRUE;
         cp += 1;          cp += 1;
Line 666 
Line 704 
         cp = name;          cp = name;
     }      }
   
       e = NULL;
       hv = hash_interval(cp, &e);
   
     if (DEBUG(DIR)) {      if (DEBUG(DIR)) {
         printf("Searching for %s...", name);          printf("Searching for %s...", name);
     }      }
Line 676 
Line 717 
      * (fish.c) and what pmake finds (./fish.c).       * (fish.c) and what pmake finds (./fish.c).
      */       */
     if ((!hasSlash || (cp - name == 2 && *name == '.')) &&      if ((!hasSlash || (cp - name == 2 && *name == '.')) &&
         (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL)) {          find_file_hash(dot, cp, e, hv) != NULL) {
             if (DEBUG(DIR)) {              if (DEBUG(DIR))
                 printf("in '.'\n");                  printf("in '.'\n");
             }  
             hits += 1;              hits += 1;
             dot->hits += 1;              dot->hits += 1;
             return (estrdup (name));              return (estrdup (name));
     }      }
   
     Lst_Open(path);  
   
     /*      /*
      * We look through all the directories on the path seeking one which       * We look through all the directories on the path seeking one which
      * contains the final component of the given name and whose final       * contains the final component of the given name and whose final
Line 695 
Line 733 
      * and return the resulting string. If we don't find any such thing,       * and return the resulting string. If we don't find any such thing,
      * we go on to phase two...       * we go on to phase two...
      */       */
     while ((ln = Lst_Next (path)) != NULL) {      for (ln = Lst_First(path); ln != NULL; ln = Lst_Adv(ln)) {
         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_hash(p, cp, e, hv) != NULL) {
         if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {              if (DEBUG(DIR))
             if (DEBUG(DIR)) {  
                 printf("here...");                  printf("here...");
             }  
             if (hasSlash) {              if (hasSlash) {
                 /*                  /*
                  * If the name had a slash, its initial components and p's                   * If the name had a slash, its initial components and p's
Line 719 
Line 755 
                     p1 -= 1; p2 -= 1;                      p1 -= 1; p2 -= 1;
                 }                  }
                 if (p2 >= name || (p1 >= p->name && *p1 != '/')) {                  if (p2 >= name || (p1 >= p->name && *p1 != '/')) {
                     if (DEBUG(DIR)) {                      if (DEBUG(DIR))
                         printf("component mismatch -- continuing...");                          printf("component mismatch -- continuing...");
                     }  
                     continue;                      continue;
                 }                  }
             }              }
             file = str_concat(p->name, cp, '/');              file = str_concat(p->name, cp, '/');
             if (DEBUG(DIR)) {              if (DEBUG(DIR))
                 printf("returning %s\n", file);                  printf("returning %s\n", file);
             }  
             Lst_Close (path);  
             p->hits += 1;              p->hits += 1;
             hits += 1;              hits += 1;
             return (file);              return file;
         } else if (hasSlash) {          } else if (hasSlash) {
             /*              /* If the file has a leading path component and that component
              * If the file has a leading path component and that component  
              * exactly matches the entire name of the current search               * exactly matches the entire name of the current search
              * directory, we assume the file doesn't exist and return NULL.               * directory, we assume the file doesn't exist and return NULL.  */
              */  
             for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {              for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {
                 continue;                  continue;
             }              }
             if (*p1 == '\0' && p2 == cp - 1) {              if (*p1 == '\0' && p2 == cp - 1) {
                 if (DEBUG(DIR)) {                  if (DEBUG(DIR))
                     printf("must be here but isn't -- returing NULL\n");                      printf("must be here but isn't -- returing NULL\n");
                 }                  return NULL;
                 Lst_Close (path);  
                 return ((char *) NULL);  
             }              }
         }          }
     }      }
   
     /*      /* We didn't find the file on any existing members of the directory.
      * We didn't find the file on any existing members of the directory.  
      * If the name doesn't contain a slash, that means it doesn't exist.       * If the name doesn't contain a slash, that means it doesn't exist.
      * If it *does* contain a slash, however, there is still hope: it       * If it *does* contain a slash, however, there is still hope: it
      * could be in a subdirectory of one of the members of the search       * could be in a subdirectory of one of the members of the search
Line 762 
Line 790 
      * /usr/include/sys/types.h) If we find such a beast, we assume there       * /usr/include/sys/types.h) If we find such a beast, we assume there
      * will be more (what else can we assume?) and add all but the last       * will be more (what else can we assume?) and add all but the last
      * component of the resulting name onto the search path (at the       * component of the resulting name onto the search path (at the
      * end). This phase is only performed if the file is *not* absolute.       * end). This phase is only performed if the file is *not* absolute.  */
      */  
     if (!hasSlash) {      if (!hasSlash) {
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("failed.\n");              printf("failed.\n");
         }  
         misses += 1;          misses += 1;
         return ((char *) NULL);          return NULL;
     }      }
   
     if (*name != '/') {      if (*name != '/') {
         Boolean checkedDot = FALSE;          Boolean checkedDot = FALSE;
   
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("failed. Trying subdirectories...");              printf("failed. Trying subdirectories...");
         }  
         Lst_Open(path);          Lst_Open(path);
         while ((ln = Lst_Next (path)) != NULL) {          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_concat(p->name, name, '/');                  file = str_concat(p->name, name, '/');
             } 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 = estrdup(name);                  file = estrdup(name);
                 checkedDot = TRUE;                  checkedDot = TRUE;
             }              }
             if (DEBUG(DIR)) {              if (DEBUG(DIR))
                 printf("checking %s...", file);                  printf("checking %s...", file);
             }  
   
               if (stat(file, &stb) == 0) {
             if (stat (file, &stb) == 0) {                  if (DEBUG(DIR))
                 if (DEBUG(DIR)) {  
                     printf("got it.\n");                      printf("got it.\n");
                 }  
   
                 Lst_Close (path);                  /* We've found another directory to search. We know there's
                    * a slash in 'file' because we put one there. We call
                 /*                   * Dir_AddDir to add this new directory onto the existing
                  * We've found another directory to search. We know there's                   * search path. Once that's done, we return the file name,
                  * a slash in 'file' because we put one there. We nuke it after                   * knowing that should a file in this directory ever be
                  * finding it and call Dir_AddDir to add this new directory                   * referenced again in such a manner, we will find it
                  * onto the existing search path. Once that's done, we restore                   * without having to do numerous access calls. Hurrah!  */
                  * the slash and triumphantly return the file name, knowing  
                  * that should a file in this directory every be referenced  
                  * again in such a manner, we will find it without having to do  
                  * numerous numbers of access calls. Hurrah!  
                  */  
                 cp = strrchr(file, '/');                  cp = strrchr(file, '/');
                 Dir_AddDir(path, file, cp);                  Dir_AddDir(path, file, cp);
   
                 /*                  /* Save the modification time so if it's needed, we don't have
                  * Save the modification time so if it's needed, we don't have                   * to fetch it again.  */
                  * to fetch it again.                  if (DEBUG(DIR))
                  */  
                 if (DEBUG(DIR)) {  
                     printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),                      printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
                             file);                              file);
                 }  
                 entry = Hash_CreateEntry(&mtimes, (char *) file,                  entry = Hash_CreateEntry(&mtimes, (char *) file,
                                          (Boolean *)NULL);                                           (Boolean *)NULL);
                 /* XXX */                  /* XXX */
                 Hash_SetValue(entry, (void *)((long)stb.st_mtime));                  Hash_SetValue(entry, (void *)((long)stb.st_mtime));
                 nearmisses += 1;                  nearmisses += 1;
                 return (file);                  return file;
             } else {              } else
                 free (file);                  free(file);
             }  
         }          }
   
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("failed. ");              printf("failed. ");
         }  
         Lst_Close (path);  
   
         if (checkedDot) {          if (checkedDot) {
             /*              /* Already checked by the given name, since . was in the path,
              * Already checked by the given name, since . was in the path,               * so no point in proceeding...  */
              * so no point in proceeding...              if (DEBUG(DIR))
              */  
             if (DEBUG(DIR)) {  
                 printf("Checked . already, returning NULL\n");                  printf("Checked . already, returning NULL\n");
             }              return NULL;
             return(NULL);  
         }          }
     }      }
   
     /*      /* Didn't find it that way, either. Sigh. Phase 3. Add its directory
      * Didn't find it that way, either. Sigh. Phase 3. Add its directory  
      * onto the search path in any case, just in case, then look for the       * onto the search path in any case, just in case, then look for the
      * thing in the hash table. If we find it, grand. We return a new       * thing in the hash table. If we find it, grand. We return a new
      * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.       * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.
Line 866 
Line 870 
      *       *
      * $(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...  */
      */  
 #ifdef notdef  #ifdef notdef
     Dir_AddDir(path, name, cp-1);      Dir_AddDir(path, name, cp-1);
   
Line 878 
Line 881 
     else      else
         p = (Path *)Lst_Datum(ln);          p = (Path *)Lst_Datum(ln);
   
     if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {      if (find_file_hash(p, cp, e, hv) != NULL)
         return (estrdup (name));          return estrdup (name);
     } else {      else
         return ((char *) NULL);          return NULL;
     }  
 #else /* !notdef */  #else /* !notdef */
     if (DEBUG(DIR)) {      if (DEBUG(DIR))
         printf("Looking for \"%s\"...", name);          printf("Looking for \"%s\"...", name);
     }  
   
     bigmisses += 1;      bigmisses += 1;
     entry = Hash_FindEntry(&mtimes, name);      entry = Hash_FindEntry(&mtimes, name);
     if (entry != (Hash_Entry *)NULL) {      if (entry != (Hash_Entry *)NULL) {
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("got it (in mtime cache)\n");              printf("got it (in mtime cache)\n");
         }          return estrdup(name);
         return(estrdup(name));      } else if (stat(name, &stb) == 0) {
     } else if (stat (name, &stb) == 0) {  
         entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);          entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),              printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
                     name);                      name);
         }  
         /* XXX */          /* XXX */
         Hash_SetValue(entry, (void *)(long)stb.st_mtime);          Hash_SetValue(entry, (void *)(long)stb.st_mtime);
         return (estrdup (name));          return estrdup(name);
     } else {      } else {
         if (DEBUG(DIR)) {          if (DEBUG(DIR))
             printf("failed. Returning NULL\n");              printf("failed. Returning NULL\n");
         }          return NULL;
         return ((char *)NULL);  
     }      }
 #endif /* notdef */  #endif /* notdef */
 }  }
Line 1007 
Line 1005 
     p = hash_create_entry(&dir_info, name, &end);      p = hash_create_entry(&dir_info, name, &end);
     p->hits = 0;      p->hits = 0;
     p->refCount = 0;      p->refCount = 0;
     Hash_InitTable(&p->files, -1);      hash_init(&p->files, 4, &file_info);
   
     if (DEBUG(DIR)) {      if (DEBUG(DIR)) {
         printf("Caching %s...", p->name);          printf("Caching %s...", p->name);
Line 1028 
Line 1026 
         if (dp->d_fileno == 0)          if (dp->d_fileno == 0)
             continue;              continue;
 #endif /* sun && d_ino */  #endif /* sun && d_ino */
         (void)Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL);          add_file(p, dp->d_name);
     }      }
     (void)closedir(d);      (void)closedir(d);
     if (DEBUG(DIR))      if (DEBUG(DIR))
Line 1153 
Line 1151 
   
     if (--p->refCount == 0) {      if (--p->refCount == 0) {
         hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name));          hash_remove(&openDirectories, hash_qlookup(&openDirectories, p->name));
         Hash_DeleteTable (&p->files);          free_hash(&p->files);
         free(p);          free(p);
     }      }
 }  }

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.26