Ignore:
Timestamp:
Mar 12, 2018, 8:32:29 PM (7 years ago)
Author:
bird
Message:

Imported make 4.2.1 (2e55f5e4abdc0e38c1d64be703b446695e70b3b6) from https://git.savannah.gnu.org/git/make.git.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/gnumake/current/dir.c

    r2596 r3138  
    11/* Directory hashing for GNU Make.
    2 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
    3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
    4 2010 Free Software Foundation, Inc.
     2Copyright (C) 1988-2016 Free Software Foundation, Inc.
    53This file is part of GNU Make.
    64
     
    1715this program.  If not, see <http://www.gnu.org/licenses/>.  */
    1816
    19 #include "make.h"
     17#include "makeint.h"
    2018#include "hash.h"
    21 
    22 #ifdef  HAVE_DIRENT_H
     19#include "filedef.h"
     20#include "dep.h"
     21
     22#ifdef  HAVE_DIRENT_H
    2323# include <dirent.h>
    2424# define NAMLEN(dirent) strlen((dirent)->d_name)
     
    8888
    8989  /* First, transform the name part.  */
    90   for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)
     90  for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
    9191    *df++ = tolower ((unsigned char)*filename++);
    9292
    9393  /* Now skip to the next dot.  */
    94   while (*filename != '\0' && *filename != '.')
     94  while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
    9595    ++filename;
    9696  if (*filename != '\0')
    9797    {
    9898      *df++ = *filename++;
    99       for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)
    100         *df++ = tolower ((unsigned char)*filename++);
     99      for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i)
     100        *df++ = tolower ((unsigned char)*filename++);
    101101    }
    102102
    103103  /* Look for more dots.  */
    104   while (*filename != '\0' && *filename != '.')
     104  while (! STOP_SET (*filename, MAP_DOT|MAP_NUL))
    105105    ++filename;
    106106  if (*filename == '.')
     
    144144#ifdef VMS
    145145
     146static char *
     147downcase_inplace(char *filename)
     148{
     149  char *name;
     150  name = filename;
     151  while (*name != '\0')
     152    {
     153      *name = tolower ((unsigned char)*name);
     154      ++name;
     155    }
     156  return filename;
     157}
     158
     159#ifndef _USE_STD_STAT
     160/* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino
     161   when _USE_STD_STAT is used on the compile line.
     162
     163   Prior to _USE_STD_STAT support, the st_dev is a pointer to thread
     164   static memory containing the device of the last filename looked up.
     165
     166   Todo: find out if the ino_t still needs to be faked on a directory.
     167 */
     168
     169/* Define this if the older VMS_INO_T is needed */
     170#define VMS_INO_T 1
     171
    146172static int
    147173vms_hash (const char *name)
    148174{
    149175  int h = 0;
    150   int g;
    151176
    152177  while (*name)
    153178    {
    154179      unsigned char uc = *name;
     180      int g;
    155181#ifdef HAVE_CASE_INSENSITIVE_FS
    156182      h = (h << 4) + (isupper (uc) ? tolower (uc) : uc);
     
    161187      g = h & 0xf0000000;
    162188      if (g)
    163         {
    164           h = h ^ (g >> 24);
    165           h = h ^ g;
    166         }
     189        {
     190          h = h ^ (g >> 24);
     191          h = h ^ g;
     192        }
    167193    }
    168194  return h;
     
    181207    return -1;
    182208  closedir (dir);
    183   s = strchr (name, ':');       /* find device */
     209  s = strchr (name, ':');       /* find device */
    184210  if (s)
    185211    {
     
    202228  return 0;
    203229}
     230
     231# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
     232
     233#endif /* _USE_STD_STAT */
    204234#endif /* VMS */
    205235
     
    207237/* Hash table of directories.  */
    208238
    209 #ifndef DIRECTORY_BUCKETS
     239#ifndef DIRECTORY_BUCKETS
    210240#define DIRECTORY_BUCKETS 199
    211241#endif
     
    213243struct directory_contents
    214244  {
    215     dev_t dev;                  /* Device and inode numbers of this dir.  */
     245    dev_t dev;                  /* Device and inode numbers of this dir.  */
    216246#ifdef WINDOWS32
    217247    /* Inode means nothing on WINDOWS32. Even file key information is
     
    221251     * unreliable. I'm open to suggestion on a better way to emulate inode.  */
    222252    char *path_key;
    223     int  ctime;
    224     int  mtime;        /* controls check for stale directory cache */
    225     int   fs_flags;     /* FS_FAT, FS_NTFS, ... */
     253    time_t ctime;
     254    time_t mtime;        /* controls check for stale directory cache */
     255    int fs_flags;     /* FS_FAT, FS_NTFS, ... */
    226256# define FS_FAT      0x1
    227257# define FS_NTFS     0x2
    228258# define FS_UNKNOWN  0x4
    229259#else
    230 # ifdef VMS
     260# ifdef VMS_INO_T
    231261    ino_t ino[3];
    232262# else
     
    234264# endif
    235265#endif /* WINDOWS32 */
    236     struct hash_table dirfiles; /* Files in this directory.  */
    237     DIR *dirstream;             /* Stream reading this directory.  */
     266    struct hash_table dirfiles; /* Files in this directory.  */
     267    DIR *dirstream;             /* Stream reading this directory.  */
    238268  };
    239269
     
    249279  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
    250280#else
    251 # ifdef VMS
     281# ifdef VMS_INO_T
    252282  hash = (((unsigned int) key->dev << 4)
    253           ^ ((unsigned int) key->ino[0]
    254              + (unsigned int) key->ino[1]
    255              + (unsigned int) key->ino[2]));
     283          ^ ((unsigned int) key->ino[0]
     284             + (unsigned int) key->ino[1]
     285             + (unsigned int) key->ino[2]));
    256286# else
    257287  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino;
     
    272302  hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
    273303#else
    274 # ifdef VMS
     304# ifdef VMS_INO_T
    275305  hash = (((unsigned int) key->dev << 4)
    276           ^ ~((unsigned int) key->ino[0]
    277               + (unsigned int) key->ino[1]
    278               + (unsigned int) key->ino[2]));
     306          ^ ~((unsigned int) key->ino[0]
     307              + (unsigned int) key->ino[1]
     308              + (unsigned int) key->ino[2]));
    279309# else
    280310  hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino;
     
    311341    return result;
    312342#else
    313 # ifdef VMS
     343# ifdef VMS_INO_T
    314344  result = MAKECMP(x->ino[0], y->ino[0]);
    315345  if (result)
     
    336366struct directory
    337367  {
    338     const char *name;                   /* Name of the directory.  */
     368    const char *name;                   /* Name of the directory.  */
    339369
    340370    /* The directory's contents.  This data may be shared by several
    341371       entries in the hash table, which refer to the same directory
    342        (identified uniquely by `dev' and `ino') under different names.  */
     372       (identified uniquely by 'dev' and 'ino') under different names.  */
    343373    struct directory_contents *contents;
    344374  };
     
    360390{
    361391  return_ISTRING_COMPARE (((const struct directory *) x)->name,
    362                           ((const struct directory *) y)->name);
     392                          ((const struct directory *) y)->name);
    363393}
    364394
     
    377407struct dirfile
    378408  {
    379     const char *name;           /* Name of the file.  */
    380     short length;
    381     short impossible;           /* This file is impossible.  */
     409    const char *name;           /* Name of the file.  */
     410    size_t length;
     411    short impossible;           /* This file is impossible.  */
    382412  };
    383413
     
    405435}
    406436
    407 #ifndef DIRFILE_BUCKETS
     437#ifndef DIRFILE_BUCKETS
    408438#define DIRFILE_BUCKETS 107
    409439#endif
     
    414444static struct directory *find_directory (const char *name);
    415445
    416 /* Find the directory named NAME and return its `struct directory'.  */
     446/* Find the directory named NAME and return its 'struct directory'.  */
    417447
    418448static struct directory *
    419449find_directory (const char *name)
    420450{
    421   const char *p;
    422451  struct directory *dir;
    423452  struct directory **dir_slot;
    424453  struct directory dir_key;
    425   int r;
    426 #ifdef WINDOWS32
    427   char* w32_path;
    428   char  fs_label[BUFSIZ];
    429   char  fs_type[BUFSIZ];
    430   unsigned long  fs_serno;
    431   unsigned long  fs_flags;
    432   unsigned long  fs_len;
    433 #endif
    434 #ifdef VMS
    435   if ((*name == '.') && (*(name+1) == 0))
    436     name = "[]";
    437   else
    438     name = vmsify (name,1);
    439 #endif
    440454
    441455  dir_key.name = name;
     
    445459  if (HASH_VACANT (dir))
    446460    {
     461      /* The directory was not found.  Create a new entry for it.  */
     462      const char *p = name + strlen (name);
    447463      struct stat st;
    448 
    449       /* The directory was not found.  Create a new entry for it.  */
    450 
    451       p = name + strlen (name);
     464      int r;
     465
    452466      dir = xmalloc (sizeof (struct directory));
    453467#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
    454       dir->name = strcache_add_len (downcase(name), p - name);
     468      /* Todo: Why is this only needed on VMS? */
     469      {
     470        char *lname = downcase_inplace (xstrdup (name));
     471        dir->name = strcache_add_len (lname, p - name);
     472        free (lname);
     473      }
    455474#else
    456475      dir->name = strcache_add_len (name, p - name);
     
    458477      hash_insert_at (&directories, dir, dir_slot);
    459478      /* The directory is not in the name hash table.
    460          Find its device and inode numbers, and look it up by them.  */
    461 
    462 #ifdef VMS
    463       r = vmsstat_dir (name, &st);
    464 #elif defined(WINDOWS32)
     479         Find its device and inode numbers, and look it up by them.  */
     480
     481#if defined(WINDOWS32)
    465482      {
    466483        char tem[MAXPATHLEN], *tstart, *tend;
     
    485502      if (r < 0)
    486503        {
    487         /* Couldn't stat the directory.  Mark this by
    488            setting the `contents' member to a nil pointer.  */
    489           dir->contents = 0;
    490         }
     504        /* Couldn't stat the directory.  Mark this by
     505           setting the 'contents' member to a nil pointer.  */
     506          dir->contents = 0;
     507        }
    491508      else
    492         {
    493           /* Search the contents hash table; device and inode are the key.  */
    494 
    495           struct directory_contents *dc;
    496           struct directory_contents **dc_slot;
    497           struct directory_contents dc_key;
    498 
    499           dc_key.dev = st.st_dev;
    500 #ifdef WINDOWS32
    501           dc_key.path_key = w32_path = w32ify (name, 1);
    502           dc_key.ctime = st.st_ctime;
    503 #else
    504 # ifdef VMS
    505           dc_key.ino[0] = st.st_ino[0];
    506           dc_key.ino[1] = st.st_ino[1];
    507           dc_key.ino[2] = st.st_ino[2];
     509        {
     510          /* Search the contents hash table; device and inode are the key.  */
     511
     512#ifdef WINDOWS32
     513          char *w32_path;
     514#endif
     515          struct directory_contents *dc;
     516          struct directory_contents **dc_slot;
     517          struct directory_contents dc_key;
     518
     519          dc_key.dev = st.st_dev;
     520#ifdef WINDOWS32
     521          dc_key.path_key = w32_path = w32ify (name, 1);
     522          dc_key.ctime = st.st_ctime;
     523#else
     524# ifdef VMS_INO_T
     525          dc_key.ino[0] = st.st_ino[0];
     526          dc_key.ino[1] = st.st_ino[1];
     527          dc_key.ino[2] = st.st_ino[2];
    508528# else
    509           dc_key.ino = st.st_ino;
     529          dc_key.ino = st.st_ino;
    510530# endif
    511531#endif
    512           dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
    513           dc = *dc_slot;
    514 
    515           if (HASH_VACANT (dc))
    516             {
    517               /* Nope; this really is a directory we haven't seen before.  */
    518 
    519               dc = (struct directory_contents *)
    520                 xmalloc (sizeof (struct directory_contents));
    521 
    522               /* Enter it in the contents hash table.  */
    523               dc->dev = st.st_dev;
     532          dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key);
     533          dc = *dc_slot;
     534
     535          if (HASH_VACANT (dc))
     536            {
     537              /* Nope; this really is a directory we haven't seen before.  */
     538#ifdef WINDOWS32
     539              char  fs_label[BUFSIZ];
     540              char  fs_type[BUFSIZ];
     541              unsigned long  fs_serno;
     542              unsigned long  fs_flags;
     543              unsigned long  fs_len;
     544#endif
     545              dc = (struct directory_contents *)
     546                xmalloc (sizeof (struct directory_contents));
     547
     548              /* Enter it in the contents hash table.  */
     549              dc->dev = st.st_dev;
    524550#ifdef WINDOWS32
    525551              dc->path_key = xstrdup (w32_path);
    526               dc->ctime = st.st_ctime;
     552              dc->ctime = st.st_ctime;
    527553              dc->mtime = st.st_mtime;
    528554
    529               /*
    530                * NTFS is the only WINDOWS32 filesystem that bumps mtime
    531                * on a directory when files are added/deleted from
    532                * a directory.
    533                */
     555              /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a
     556                 directory when files are added/deleted from a directory.  */
    534557              w32_path[3] = '\0';
    535               if (GetVolumeInformation(w32_path,
    536                      fs_label, sizeof (fs_label),
    537                      &fs_serno, &fs_len,
    538                      &fs_flags, fs_type, sizeof (fs_type)) == FALSE)
     558              if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label),
     559                                        &fs_serno, &fs_len, &fs_flags, fs_type,
     560                                        sizeof (fs_type)) == FALSE)
    539561                dc->fs_flags = FS_UNKNOWN;
    540               else if (!strcmp(fs_type, "FAT"))
     562              else if (!strcmp (fs_type, "FAT"))
    541563                dc->fs_flags = FS_FAT;
    542               else if (!strcmp(fs_type, "NTFS"))
     564              else if (!strcmp (fs_type, "NTFS"))
    543565                dc->fs_flags = FS_NTFS;
    544566              else
    545567                dc->fs_flags = FS_UNKNOWN;
    546568#else
    547 # ifdef VMS
    548               dc->ino[0] = st.st_ino[0];
    549               dc->ino[1] = st.st_ino[1];
    550               dc->ino[2] = st.st_ino[2];
     569# ifdef VMS_INO_T
     570              dc->ino[0] = st.st_ino[0];
     571              dc->ino[1] = st.st_ino[1];
     572              dc->ino[2] = st.st_ino[2];
    551573# else
    552               dc->ino = st.st_ino;
     574              dc->ino = st.st_ino;
    553575# endif
    554576#endif /* WINDOWS32 */
    555               hash_insert_at (&directory_contents, dc, dc_slot);
    556               ENULLLOOP (dc->dirstream, opendir (name));
    557               if (dc->dirstream == 0)
     577              hash_insert_at (&directory_contents, dc, dc_slot);
     578              ENULLLOOP (dc->dirstream, opendir (name));
     579              if (dc->dirstream == 0)
    558580                /* Couldn't open the directory.  Mark this by setting the
    559                    `files' member to a nil pointer.  */
     581                   'files' member to a nil pointer.  */
    560582                dc->dirfiles.ht_vec = 0;
    561               else
    562                 {
    563                   hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
    564                              dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
    565                   /* Keep track of how many directories are open.  */
    566                   ++open_directories;
    567                   if (open_directories == MAX_OPEN_DIRECTORIES)
    568                     /* We have too many directories open already.
    569                        Read the entire directory and then close it.  */
    570                     dir_contents_file_exists_p (dc, 0);
    571                 }
    572             }
    573 
    574           /* Point the name-hashed entry for DIR at its contents data.  */
    575           dir->contents = dc;
    576         }
     583              else
     584                {
     585                  hash_init (&dc->dirfiles, DIRFILE_BUCKETS,
     586                             dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
     587                  /* Keep track of how many directories are open.  */
     588                  ++open_directories;
     589                  if (open_directories == MAX_OPEN_DIRECTORIES)
     590                    /* We have too many directories open already.
     591                       Read the entire directory and then close it.  */
     592                    dir_contents_file_exists_p (dc, 0);
     593                }
     594            }
     595
     596          /* Point the name-hashed entry for DIR at its contents data.  */
     597          dir->contents = dc;
     598        }
    577599    }
    578600
     
    588610                            const char *filename)
    589611{
    590   unsigned int hash;
    591612  struct dirfile *df;
    592613  struct dirent *d;
     
    612633    _fnlwr (filename); /* lower case for FAT drives */
    613634#endif
    614 
    615 #ifdef VMS
    616   filename = vmsify (filename,0);
    617 #endif
    618 
    619   hash = 0;
    620635  if (filename != 0)
    621636    {
     
    623638
    624639      if (*filename == '\0')
    625         {
    626           /* Checking if the directory exists.  */
    627           return 1;
    628         }
     640        {
     641          /* Checking if the directory exists.  */
     642          return 1;
     643        }
    629644      dirfile_key.name = filename;
    630645      dirfile_key.length = strlen (filename);
     
    646661       */
    647662      if (dir->path_key)
    648         {
     663        {
    649664          if ((dir->fs_flags & FS_FAT) != 0)
    650             {
    651               dir->mtime = time ((time_t *) 0);
    652               rehash = 1;
    653             }
    654           else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
    655             {
    656               /* reset date stamp to show most recent re-process.  */
    657               dir->mtime = st.st_mtime;
    658               rehash = 1;
    659             }
     665            {
     666              dir->mtime = time ((time_t *) 0);
     667              rehash = 1;
     668            }
     669          else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
     670            {
     671              /* reset date stamp to show most recent re-process.  */
     672              dir->mtime = st.st_mtime;
     673              rehash = 1;
     674            }
    660675
    661676          /* If it has been already read in, all done.  */
    662           if (!rehash)
    663             return 0;
     677          if (!rehash)
     678            return 0;
    664679
    665680          /* make sure directory can still be opened; if not return.  */
     
    667682          if (!dir->dirstream)
    668683            return 0;
    669         }
     684        }
    670685      else
    671686#endif
    672         /* The directory has been all read in.  */
    673         return 0;
     687        /* The directory has been all read in.  */
     688        return 0;
    674689    }
    675690
     
    685700        {
    686701          if (errno)
    687             fatal (NILF, "INTERNAL: readdir: %s\n", strerror (errno));
     702            pfatal_with_name ("INTERNAL: readdir");
    688703          break;
    689704        }
    690705
    691706#if defined(VMS) && defined(HAVE_DIRENT_H)
    692       /* In VMS we get file versions too, which have to be stripped off */
     707      /* In VMS we get file versions too, which have to be stripped off.
     708         Some versions of VMS return versions on Unix files even when
     709         the feature option to strip them is set.  */
    693710      {
    694711        char *p = strrchr (d->d_name, ';');
     
    698715#endif
    699716      if (!REAL_DIR_ENTRY (d))
    700         continue;
     717        continue;
    701718
    702719      len = NAMLEN (d);
     
    711728      if (! rehash || HASH_VACANT (*dirfile_slot))
    712729#endif
    713         {
    714           df = xmalloc (sizeof (struct dirfile));
     730        {
     731          df = xmalloc (sizeof (struct dirfile));
    715732#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
    716           df->name = strcache_add_len (downcase(d->d_name), len);
    717 #else
    718           df->name = strcache_add_len (d->d_name, len);
    719 #endif
    720           df->length = len;
    721           df->impossible = 0;
    722           hash_insert_at (&dir->dirfiles, df, dirfile_slot);
    723         }
     733          /* TODO: Why is this only needed on VMS? */
     734          df->name = strcache_add_len (downcase_inplace (d->d_name), len);
     735#else
     736          df->name = strcache_add_len (d->d_name, len);
     737#endif
     738          df->length = len;
     739          df->impossible = 0;
     740          hash_insert_at (&dir->dirfiles, df, dirfile_slot);
     741        }
    724742      /* Check if the name matches the one we're searching for.  */
    725743      if (filename != 0 && patheq (d->d_name, filename))
     
    745763dir_file_exists_p (const char *dirname, const char *filename)
    746764{
     765#ifdef VMS
     766  if ((filename != NULL) && (dirname != NULL))
     767    {
     768      int want_vmsify;
     769      want_vmsify = (strpbrk (dirname, ":<[") != NULL);
     770      if (want_vmsify)
     771        filename = vmsify (filename, 0);
     772    }
     773#endif
    747774  return dir_contents_file_exists_p (find_directory (dirname)->contents,
    748                                      filename);
     775                                     filename);
    749776}
    750777
     
    759786  const char *slash;
    760787
    761 #ifndef NO_ARCHIVES
     788#ifndef NO_ARCHIVES
    762789  if (ar_name (name))
    763790    return ar_member_date (name) != (time_t) -1;
    764791#endif
    765792
     793  dirend = strrchr (name, '/');
    766794#ifdef VMS
    767   dirend = strrchr (name, ']');
    768795  if (dirend == 0)
    769     dirend = strrchr (name, ':');
     796    {
     797      dirend = strrchr (name, ']');
     798      dirend == NULL ? dirend : dirend++;
     799    }
    770800  if (dirend == 0)
    771     return dir_file_exists_p ("[]", name);
    772 #else /* !VMS */
    773   dirend = strrchr (name, '/');
     801    {
     802      dirend = strrchr (name, '>');
     803      dirend == NULL ? dirend : dirend++;
     804    }
     805  if (dirend == 0)
     806    {
     807      dirend = strrchr (name, ':');
     808      dirend == NULL ? dirend : dirend++;
     809    }
     810#endif /* VMS */
    774811#ifdef HAVE_DOS_PATHS
    775812  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
    776813  {
    777     const char *bslash = strrchr(name, '\\');
     814    const char *bslash = strrchr (name, '\\');
    778815    if (!dirend || bslash > dirend)
    779816      dirend = bslash;
     
    786823#ifndef _AMIGA
    787824    return dir_file_exists_p (".", name);
    788 #else /* !VMS && !AMIGA */
     825#else /* !AMIGA */
    789826    return dir_file_exists_p ("", name);
    790827#endif /* AMIGA */
    791 #endif /* VMS */
    792828
    793829  slash = dirend;
     
    800836  /* d:/ and d: are *very* different...  */
    801837      if (dirend < name + 3 && name[1] == ':' &&
    802           (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
    803         dirend++;
     838          (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
     839        dirend++;
    804840#endif
    805841      p = alloca (dirend - name + 1);
     
    808844      dirname = p;
    809845    }
    810   return dir_file_exists_p (dirname, slash + 1);
    811 }
    812 
    813 
    814 /* Mark FILENAME as `impossible' for `file_impossible_p'.
     846#ifdef VMS
     847  if (*slash == '/')
     848    slash++;
     849#else
     850  slash++;
     851#endif
     852  return dir_file_exists_p (dirname, slash);
     853}
     854
     855
     856/* Mark FILENAME as 'impossible' for 'file_impossible_p'.
    815857   This means an attempt has been made to search for FILENAME
    816858   as an intermediate file, and it has failed.  */
     
    824866  struct dirfile *new;
    825867
     868  dirend = strrchr (p, '/');
    826869#ifdef VMS
    827   dirend = strrchr (p, ']');
    828   if (dirend == 0)
    829     dirend = strrchr (p, ':');
    830   dirend++;
    831   if (dirend == (char *)1)
    832     dir = find_directory ("[]");
    833 #else
    834   dirend = strrchr (p, '/');
    835 # ifdef HAVE_DOS_PATHS
     870  if (dirend == NULL)
     871    {
     872      dirend = strrchr (p, ']');
     873      dirend == NULL ? dirend : dirend++;
     874    }
     875  if (dirend == NULL)
     876    {
     877      dirend = strrchr (p, '>');
     878      dirend == NULL ? dirend : dirend++;
     879    }
     880  if (dirend == NULL)
     881    {
     882      dirend = strrchr (p, ':');
     883      dirend == NULL ? dirend : dirend++;
     884    }
     885#endif
     886#ifdef HAVE_DOS_PATHS
    836887  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
    837888  {
    838     const char *bslash = strrchr(p, '\\');
     889    const char *bslash = strrchr (p, '\\');
    839890    if (!dirend || bslash > dirend)
    840891      dirend = bslash;
     
    843894      dirend = p + 1;
    844895  }
    845 # endif /* HAVE_DOS_PATHS */
     896#endif /* HAVE_DOS_PATHS */
    846897  if (dirend == 0)
    847 # ifdef _AMIGA
     898#ifdef _AMIGA
    848899    dir = find_directory ("");
    849 # else /* !VMS && !AMIGA */
     900#else /* !AMIGA */
    850901    dir = find_directory (".");
    851 # endif /* AMIGA */
    852 #endif /* VMS */
     902#endif /* AMIGA */
    853903  else
    854904    {
     
    856906      const char *slash = dirend;
    857907      if (dirend == p)
    858         dirname = "/";
     908        dirname = "/";
    859909      else
    860         {
     910        {
    861911          char *cp;
    862912#ifdef HAVE_DOS_PATHS
    863           /* d:/ and d: are *very* different...  */
    864           if (dirend < p + 3 && p[1] == ':' &&
    865               (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
    866             dirend++;
    867 #endif
    868           cp = alloca (dirend - p + 1);
    869           memcpy (cp, p, dirend - p);
    870           cp[dirend - p] = '\0';
     913          /* d:/ and d: are *very* different...  */
     914          if (dirend < p + 3 && p[1] == ':' &&
     915              (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
     916            dirend++;
     917#endif
     918          cp = alloca (dirend - p + 1);
     919          memcpy (cp, p, dirend - p);
     920          cp[dirend - p] = '\0';
    871921          dirname = cp;
    872         }
     922        }
    873923      dir = find_directory (dirname);
     924#ifdef VMS
     925      if (*slash == '/')
     926        filename = p = slash + 1;
     927      else
     928        filename = p = slash;
     929#else
    874930      filename = p = slash + 1;
     931#endif
    875932    }
    876933
     
    883940    {
    884941      hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS,
    885                 dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
     942                dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp);
    886943    }
    887944
     
    891948  new->length = strlen (filename);
    892949#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
    893   new->name = strcache_add_len (downcase(filename), new->length);
     950  /* todo: Why is this only needed on VMS? */
     951  new->name = strcache_add_len (downcase (filename), new->length);
    894952#else
    895953  new->name = strcache_add_len (filename, new->length);
     
    906964{
    907965  const char *dirend;
    908   const char *p = filename;
    909966  struct directory_contents *dir;
    910967  struct dirfile *dirfile;
    911968  struct dirfile dirfile_key;
    912 
    913969#ifdef VMS
    914   dirend = strrchr (filename, ']');
    915   if (dirend == 0)
    916     dir = find_directory ("[]")->contents;
    917 #else
     970  int want_vmsify = 0;
     971#endif
     972
    918973  dirend = strrchr (filename, '/');
     974#ifdef VMS
     975  if (dirend == NULL)
     976    {
     977      want_vmsify = (strpbrk (filename, "]>:^") != NULL);
     978      dirend = strrchr (filename, ']');
     979    }
     980  if (dirend == NULL && want_vmsify)
     981    dirend = strrchr (filename, '>');
     982  if (dirend == NULL && want_vmsify)
     983    dirend = strrchr (filename, ':');
     984#endif
    919985#ifdef HAVE_DOS_PATHS
    920986  /* Forward and backslashes might be mixed.  We need the rightmost one.  */
    921987  {
    922     const char *bslash = strrchr(filename, '\\');
     988    const char *bslash = strrchr (filename, '\\');
    923989    if (!dirend || bslash > dirend)
    924990      dirend = bslash;
     
    931997#ifdef _AMIGA
    932998    dir = find_directory ("")->contents;
    933 #else /* !VMS && !AMIGA */
     999#else /* !AMIGA */
    9341000    dir = find_directory (".")->contents;
    9351001#endif /* AMIGA */
    936 #endif /* VMS */
    9371002  else
    9381003    {
     
    9401005      const char *slash = dirend;
    9411006      if (dirend == filename)
    942         dirname = "/";
     1007        dirname = "/";
    9431008      else
    944         {
     1009        {
    9451010          char *cp;
    9461011#ifdef HAVE_DOS_PATHS
    947           /* d:/ and d: are *very* different...  */
    948           if (dirend < filename + 3 && filename[1] == ':' &&
    949               (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
    950             dirend++;
    951 #endif
    952           cp = alloca (dirend - filename + 1);
    953           memcpy (cp, p, dirend - p);
    954           cp[dirend - p] = '\0';
     1012          /* d:/ and d: are *very* different...  */
     1013          if (dirend < filename + 3 && filename[1] == ':' &&
     1014              (*dirend == '/' || *dirend == '\\' || *dirend == ':'))
     1015            dirend++;
     1016#endif
     1017          cp = alloca (dirend - filename + 1);
     1018          memcpy (cp, filename, dirend - filename);
     1019          cp[dirend - filename] = '\0';
    9551020          dirname = cp;
    956         }
     1021        }
    9571022      dir = find_directory (dirname)->contents;
    958       p = filename = slash + 1;
     1023#ifdef VMS
     1024      if (*slash == '/')
     1025        filename = slash + 1;
     1026      else
     1027        filename = slash;
     1028#else
     1029      filename = slash + 1;
     1030#endif
    9591031    }
    9601032
     
    9641036
    9651037#ifdef __MSDOS__
    966   filename = dosify (p);
     1038  filename = dosify (filename);
    9671039#endif
    9681040#ifdef HAVE_CASE_INSENSITIVE_FS
    969   filename = downcase (p);
     1041  filename = downcase (filename);
    9701042#endif
    9711043#ifdef VMS
    972   filename = vmsify (p, 1);
     1044  if (want_vmsify)
     1045    filename = vmsify (filename, 1);
    9731046#endif
    9741047
     
    10131086      struct directory *dir = *dir_slot;
    10141087      if (! HASH_VACANT (dir))
    1015         {
    1016           if (dir->contents == 0)
    1017             printf (_("# %s: could not be stat'd.\n"), dir->name);
    1018           else if (dir->contents->dirfiles.ht_vec == 0)
    1019             {
    1020 #ifdef WINDOWS32
    1021               printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
    1022                       dir->name, dir->contents->path_key,dir->contents->mtime);
     1088        {
     1089          if (dir->contents == 0)
     1090            printf (_("# %s: could not be stat'd.\n"), dir->name);
     1091          else if (dir->contents->dirfiles.ht_vec == 0)
     1092            {
     1093#ifdef WINDOWS32
     1094              printf (_("# %s (key %s, mtime %I64u): could not be opened.\n"),
     1095                      dir->name, dir->contents->path_key,
     1096                      (unsigned long long)dir->contents->mtime);
    10231097#else  /* WINDOWS32 */
    1024 #ifdef VMS
    1025               printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
    1026                       dir->name, dir->contents->dev,
    1027                       dir->contents->ino[0], dir->contents->ino[1],
    1028                       dir->contents->ino[2]);
    1029 #else
    1030               printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
    1031                       dir->name, (long int) dir->contents->dev,
    1032                       (long int) dir->contents->ino);
     1098#ifdef VMS_INO_T
     1099              printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
     1100                      dir->name, dir->contents->dev,
     1101                      dir->contents->ino[0], dir->contents->ino[1],
     1102                      dir->contents->ino[2]);
     1103#else
     1104              printf (_("# %s (device %ld, inode %ld): could not be opened.\n"),
     1105                      dir->name, (long int) dir->contents->dev,
     1106                      (long int) dir->contents->ino);
    10331107#endif
    10341108#endif /* WINDOWS32 */
    1035             }
    1036           else
    1037             {
    1038               unsigned int f = 0;
    1039               unsigned int im = 0;
    1040               struct dirfile **files_slot;
    1041               struct dirfile **files_end;
    1042 
    1043               files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
    1044               files_end = files_slot + dir->contents->dirfiles.ht_size;
    1045               for ( ; files_slot < files_end; files_slot++)
    1046                 {
    1047                   struct dirfile *df = *files_slot;
    1048                   if (! HASH_VACANT (df))
    1049                     {
    1050                       if (df->impossible)
    1051                         ++im;
    1052                       else
    1053                         ++f;
    1054                     }
    1055                 }
    1056 #ifdef WINDOWS32
    1057               printf (_("# %s (key %s, mtime %d): "),
    1058                       dir->name, dir->contents->path_key, dir->contents->mtime);
     1109            }
     1110          else
     1111            {
     1112              unsigned int f = 0;
     1113              unsigned int im = 0;
     1114              struct dirfile **files_slot;
     1115              struct dirfile **files_end;
     1116
     1117              files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec;
     1118              files_end = files_slot + dir->contents->dirfiles.ht_size;
     1119              for ( ; files_slot < files_end; files_slot++)
     1120                {
     1121                  struct dirfile *df = *files_slot;
     1122                  if (! HASH_VACANT (df))
     1123                    {
     1124                      if (df->impossible)
     1125                        ++im;
     1126                      else
     1127                        ++f;
     1128                    }
     1129                }
     1130#ifdef WINDOWS32
     1131              printf (_("# %s (key %s, mtime %I64u): "),
     1132                      dir->name, dir->contents->path_key,
     1133                      (unsigned long long)dir->contents->mtime);
    10591134#else  /* WINDOWS32 */
    1060 #ifdef VMS
    1061               printf (_("# %s (device %d, inode [%d,%d,%d]): "),
    1062                       dir->name, dir->contents->dev,
    1063                       dir->contents->ino[0], dir->contents->ino[1],
    1064                       dir->contents->ino[2]);
    1065 #else
    1066               printf (_("# %s (device %ld, inode %ld): "),
    1067                       dir->name,
    1068                       (long)dir->contents->dev, (long)dir->contents->ino);
     1135#ifdef VMS_INO_T
     1136              printf (_("# %s (device %d, inode [%d,%d,%d]): "),
     1137                      dir->name, dir->contents->dev,
     1138                      dir->contents->ino[0], dir->contents->ino[1],
     1139                      dir->contents->ino[2]);
     1140#else
     1141              printf (_("# %s (device %ld, inode %ld): "),
     1142                      dir->name,
     1143                      (long)dir->contents->dev, (long)dir->contents->ino);
    10691144#endif
    10701145#endif /* WINDOWS32 */
    1071               if (f == 0)
    1072                 fputs (_("No"), stdout);
    1073               else
    1074                 printf ("%u", f);
    1075               fputs (_(" files, "), stdout);
    1076               if (im == 0)
    1077                 fputs (_("no"), stdout);
    1078               else
    1079                 printf ("%u", im);
    1080               fputs (_(" impossibilities"), stdout);
    1081               if (dir->contents->dirstream == 0)
    1082                 puts (".");
    1083               else
    1084                 puts (_(" so far."));
    1085               files += f;
    1086               impossible += im;
    1087             }
    1088         }
     1146              if (f == 0)
     1147                fputs (_("No"), stdout);
     1148              else
     1149                printf ("%u", f);
     1150              fputs (_(" files, "), stdout);
     1151              if (im == 0)
     1152                fputs (_("no"), stdout);
     1153              else
     1154                printf ("%u", im);
     1155              fputs (_(" impossibilities"), stdout);
     1156              if (dir->contents->dirstream == 0)
     1157                puts (".");
     1158              else
     1159                puts (_(" so far."));
     1160              files += f;
     1161              impossible += im;
     1162            }
     1163        }
    10891164    }
    10901165
     
    11051180/* Hooks for globbing.  */
    11061181
    1107 #include <glob.h>
    1108 
    11091182/* Structure describing state of iterating through a directory hash table.  */
    11101183
     
    11561229      struct dirfile *df = *ds->dirfile_slot++;
    11571230      if (! HASH_VACANT (df) && !df->impossible)
    1158         {
    1159           /* The glob interface wants a `struct dirent', so mock one up.  */
    1160           struct dirent *d;
    1161           unsigned int len = df->length + 1;
     1231        {
     1232          /* The glob interface wants a 'struct dirent', so mock one up.  */
     1233          struct dirent *d;
     1234          unsigned int len = df->length + 1;
    11621235          unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len;
    1163           if (sz > bufsz)
    1164             {
    1165               bufsz *= 2;
    1166               if (sz > bufsz)
    1167                 bufsz = sz;
    1168               buf = xrealloc (buf, bufsz);
    1169             }
    1170           d = (struct dirent *) buf;
     1236          if (sz > bufsz)
     1237            {
     1238              bufsz *= 2;
     1239              if (sz > bufsz)
     1240                bufsz = sz;
     1241              buf = xrealloc (buf, bufsz);
     1242            }
     1243          d = (struct dirent *) buf;
    11711244#ifdef __MINGW32__
    11721245# if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \
    1173                                      __MINGW32_MINOR_VERSION == 0)
    1174           d->d_name = xmalloc(len);
     1246                                     __MINGW32_MINOR_VERSION == 0)
     1247          d->d_name = xmalloc (len);
    11751248# endif
    11761249#endif
    1177           FAKE_DIR_ENTRY (d);
     1250          FAKE_DIR_ENTRY (d);
    11781251#ifdef _DIRENT_HAVE_D_NAMLEN
    1179           d->d_namlen = len - 1;
     1252          d->d_namlen = len - 1;
    11801253#endif
    11811254#ifdef _DIRENT_HAVE_D_TYPE
    1182           d->d_type = DT_UNKNOWN;
    1183 #endif
    1184           memcpy (d->d_name, df->name, len);
    1185           return d;
    1186         }
     1255          d->d_type = DT_UNKNOWN;
     1256#endif
     1257          memcpy (d->d_name, df->name, len);
     1258          return d;
     1259        }
    11871260    }
    11881261
    11891262  return 0;
    1190 }
    1191 
    1192 static void
    1193 ansi_free (void *p)
    1194 {
    1195   if (p)
    1196     free(p);
    11971263}
    11981264
     
    12001266 * macro for stat64().  If stat is a macro, make a local wrapper function to
    12011267 * invoke it.
     1268 *
     1269 * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
     1270 * regular file; fix that here.
    12021271 */
    1203 #ifndef stat
     1272#if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
    12041273# ifndef VMS
     1274#  ifndef HAVE_SYS_STAT_H
    12051275int stat (const char *path, struct stat *sbuf);
     1276#  endif
     1277# else
     1278    /* We are done with the fake stat.  Go back to the real stat */
     1279#   ifdef stat
     1280#     undef stat
     1281#   endif
    12061282# endif
    12071283# define local_stat stat
     
    12111287{
    12121288  int e;
     1289#ifdef WINDOWS32
     1290  size_t plen = strlen (path);
     1291
     1292  /* Make sure the parent of "." exists and is a directory, not a
     1293     file.  This is because 'stat' on Windows normalizes the argument
     1294     foo/. => foo without checking first that foo is a directory.  */
     1295  if (plen > 1 && path[plen - 1] == '.'
     1296      && (path[plen - 2] == '/' || path[plen - 2] == '\\'))
     1297    {
     1298      char parent[MAXPATHLEN];
     1299
     1300      strncpy (parent, path, plen - 2);
     1301      parent[plen - 2] = '\0';
     1302      if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode))
     1303        return -1;
     1304    }
     1305#endif
    12131306
    12141307  EINTRLOOP (e, stat (path, buf));
     
    12221315  gl->gl_opendir = open_dirstream;
    12231316  gl->gl_readdir = read_dirstream;
    1224   gl->gl_closedir = ansi_free;
     1317  gl->gl_closedir = free;
    12251318  gl->gl_stat = local_stat;
    12261319  /* We don't bother setting gl_lstat, since glob never calls it.
     
    12321325{
    12331326  hash_init (&directories, DIRECTORY_BUCKETS,
    1234              directory_hash_1, directory_hash_2, directory_hash_cmp);
     1327             directory_hash_1, directory_hash_2, directory_hash_cmp);
    12351328  hash_init (&directory_contents, DIRECTORY_BUCKETS,
    1236              directory_contents_hash_1, directory_contents_hash_2,
     1329             directory_contents_hash_1, directory_contents_hash_2,
    12371330             directory_contents_hash_cmp);
    12381331}
Note: See TracChangeset for help on using the changeset viewer.