summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authorJohn Malmberg <wb8tyw@qsl.net>2014-10-07 19:23:47 -0500
committerPaul Smith <psmith@gnu.org>2014-10-20 01:31:42 -0400
commitc0380823a27f14cdc8274ad03c0dcab216d1380b (patch)
tree544dc236327c1524afa1f3680f26b03b23fc511c /dir.c
parent1faae1d4edbe9889f000ccba1dfd77ccad1d7de9 (diff)
downloadgunmake-c0380823a27f14cdc8274ad03c0dcab216d1380b.tar.gz
Fix VMS implicit rules and UNIX paths.
This fixes VMS implicit rules and UNIX style pathname handling. It also fixes some of the VMS style pathname handling, more work there will be needed later. TODO: There are other case insensitive platforms besides VMS. We need to find out why there is extra VMS code for this. This indicates either the extra VMS code is not needed, or the case insensitive support may not be complete on the other case insensitive platforms. * default.c: Add missing definitions to default_suffix_rules[] and default_variables[]. TODO: As it is important that VMS DCL mode definitions must always be a superset of UNIX definitions, a better way of maintaining the VMS DCL mode definitions should be devised. * dir.c (downcase_inplace): Add a reentrant downcase() routine. Add future support for VMS 8.2+ _USE_STD_STAT macro which will disable a lot of VMS specific code from compiling. (dir_file_exists_p): vmsify filename only if directory name has VMS directory delimiters. (file_exists_p): Handle both VMS and UNIX directories. (file_impossible): Handle both VMS and Unix directories. Track whether a VMS format path is needed for the return value. * file.c (lookup_file): Check if vmsify is needed; handle UNIX paths. * implicit.c (pattern_search): Enable UNIX paths. * read.c (parse_file_seq): Enable UNIX paths. * remake.c (f_mtime): Fix gpath_search call for VMS paths. * rule.c (count_implicit_rule): Enable UNIX paths, Fix VMS paths. * vpath.c (selective_vpath_search): Enable UNIX paths.
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c199
1 files changed, 142 insertions, 57 deletions
diff --git a/dir.c b/dir.c
index 7e00b8f..1fca3ba 100644
--- a/dir.c
+++ b/dir.c
@@ -142,6 +142,32 @@ downcase (const char *filename)
#ifdef VMS
+static char *
+downcase_inplace(char *filename)
+{
+ char *name;
+ name = filename;
+ while (*name != '\0')
+ {
+ *name = tolower ((unsigned char)*name);
+ ++name;
+ }
+ return filename;
+}
+
+#ifndef _USE_STD_STAT
+/* VMS 8.2 fixed the VMS stat output to have unique st_dev and st_ino
+ when _USE_STD_STAT is used on the compile line.
+
+ Prior to _USE_STD_STAT support, the st_dev is a pointer to thread
+ static memory containing the device of the last filename looked up.
+
+ Todo: find out if the ino_t still needs to be faked on a directory.
+ */
+
+/* Define this if the older VMS_INO_T is needed */
+#define VMS_INO_T 1
+
static int
vms_hash (const char *name)
{
@@ -200,6 +226,10 @@ vmsstat_dir (const char *name, struct stat *st)
return 0;
}
+
+# define stat(__path, __sbuf) vmsstat_dir (__path, __sbuf)
+
+#endif /* _USE_STD_STAT */
#endif /* VMS */
/* Hash table of directories. */
@@ -225,7 +255,7 @@ struct directory_contents
# define FS_NTFS 0x2
# define FS_UNKNOWN 0x4
#else
-# ifdef VMS
+# ifdef VMS_INO_T
ino_t ino[3];
# else
ino_t ino;
@@ -246,7 +276,7 @@ directory_contents_hash_1 (const void *key_0)
ISTRING_HASH_1 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime;
#else
-# ifdef VMS
+# ifdef VMS_INO_T
hash = (((unsigned int) key->dev << 4)
^ ((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
@@ -269,7 +299,7 @@ directory_contents_hash_2 (const void *key_0)
ISTRING_HASH_2 (key->path_key, hash);
hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime;
#else
-# ifdef VMS
+# ifdef VMS_INO_T
hash = (((unsigned int) key->dev << 4)
^ ~((unsigned int) key->ino[0]
+ (unsigned int) key->ino[1]
@@ -308,7 +338,7 @@ directory_contents_hash_cmp (const void *xv, const void *yv)
if (result)
return result;
#else
-# ifdef VMS
+# ifdef VMS_INO_T
result = MAKECMP(x->ino[0], y->ino[0]);
if (result)
return result;
@@ -419,13 +449,6 @@ find_directory (const char *name)
struct directory **dir_slot;
struct directory dir_key;
-#ifdef VMS
- if ((*name == '.') && (*(name+1) == 0))
- name = "[]";
- else
- name = vmsify (name,1);
-#endif
-
dir_key.name = name;
dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key);
dir = *dir_slot;
@@ -439,7 +462,12 @@ find_directory (const char *name)
dir = xmalloc (sizeof (struct directory));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
- dir->name = strcache_add_len (downcase (name), p - name);
+ /* Todo: Why is this only needed on VMS? */
+ {
+ char *lname = downcase_inplace (xstrdup (name));
+ dir->name = strcache_add_len (lname, p - name);
+ free (lname);
+ }
#else
dir->name = strcache_add_len (name, p - name);
#endif
@@ -447,9 +475,7 @@ find_directory (const char *name)
/* The directory is not in the name hash table.
Find its device and inode numbers, and look it up by them. */
-#ifdef VMS
- r = vmsstat_dir (name, &st);
-#elif defined(WINDOWS32)
+#if defined(WINDOWS32)
{
char tem[MAXPATHLEN], *tstart, *tend;
@@ -492,7 +518,7 @@ find_directory (const char *name)
dc_key.path_key = w32_path = w32ify (name, 1);
dc_key.ctime = st.st_ctime;
#else
-# ifdef VMS
+# ifdef VMS_INO_T
dc_key.ino[0] = st.st_ino[0];
dc_key.ino[1] = st.st_ino[1];
dc_key.ino[2] = st.st_ino[2];
@@ -537,7 +563,7 @@ find_directory (const char *name)
else
dc->fs_flags = FS_UNKNOWN;
#else
-# ifdef VMS
+# ifdef VMS_INO_T
dc->ino[0] = st.st_ino[0];
dc->ino[1] = st.st_ino[1];
dc->ino[2] = st.st_ino[2];
@@ -602,11 +628,6 @@ dir_contents_file_exists_p (struct directory_contents *dir,
if (filename != 0)
_fnlwr (filename); /* lower case for FAT drives */
#endif
-
-#ifdef VMS
- filename = vmsify (filename,0);
-#endif
-
if (filename != 0)
{
struct dirfile dirfile_key;
@@ -679,7 +700,9 @@ dir_contents_file_exists_p (struct directory_contents *dir,
}
#if defined(VMS) && defined(HAVE_DIRENT_H)
- /* In VMS we get file versions too, which have to be stripped off */
+ /* In VMS we get file versions too, which have to be stripped off.
+ Some versions of VMS return versions on Unix files even when
+ the feature option to strip them is set. */
{
char *p = strrchr (d->d_name, ';');
if (p)
@@ -703,7 +726,8 @@ dir_contents_file_exists_p (struct directory_contents *dir,
{
df = xmalloc (sizeof (struct dirfile));
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
- df->name = strcache_add_len (downcase (d->d_name), len);
+ /* TODO: Why is this only needed on VMS? */
+ df->name = strcache_add_len (downcase_inplace (d->d_name), len);
#else
df->name = strcache_add_len (d->d_name, len);
#endif
@@ -734,6 +758,15 @@ dir_contents_file_exists_p (struct directory_contents *dir,
int
dir_file_exists_p (const char *dirname, const char *filename)
{
+#ifdef VMS
+ if ((filename != NULL) && (dirname != NULL))
+ {
+ int want_vmsify;
+ want_vmsify = (strpbrk (dirname, ":<[") != NULL);
+ if (want_vmsify)
+ filename = vmsify (filename, 0);
+ }
+#endif
return dir_contents_file_exists_p (find_directory (dirname)->contents,
filename);
}
@@ -752,14 +785,24 @@ file_exists_p (const char *name)
return ar_member_date (name) != (time_t) -1;
#endif
+ dirend = strrchr (name, '/');
#ifdef VMS
- dirend = strrchr (name, ']');
if (dirend == 0)
- dirend = strrchr (name, ':');
+ {
+ dirend = strrchr (name, ']');
+ dirend == NULL ? dirend : dirend++;
+ }
if (dirend == 0)
- return dir_file_exists_p ("[]", name);
-#else /* !VMS */
- dirend = strrchr (name, '/');
+ {
+ dirend = strrchr (name, '>');
+ dirend == NULL ? dirend : dirend++;
+ }
+ if (dirend == 0)
+ {
+ dirend = strrchr (name, ':');
+ dirend == NULL ? dirend : dirend++;
+ }
+#endif /* VMS */
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
@@ -774,10 +817,9 @@ file_exists_p (const char *name)
if (dirend == 0)
#ifndef _AMIGA
return dir_file_exists_p (".", name);
-#else /* !VMS && !AMIGA */
+#else /* !AMIGA */
return dir_file_exists_p ("", name);
#endif /* AMIGA */
-#endif /* VMS */
slash = dirend;
if (dirend == name)
@@ -796,7 +838,13 @@ file_exists_p (const char *name)
p[dirend - name] = '\0';
dirname = p;
}
- return dir_file_exists_p (dirname, slash + 1);
+#ifdef VMS
+ if (*slash == '/')
+ slash++;
+#else
+ slash++;
+#endif
+ return dir_file_exists_p (dirname, slash);
}
/* Mark FILENAME as 'impossible' for 'file_impossible_p'.
@@ -811,16 +859,25 @@ file_impossible (const char *filename)
struct directory *dir;
struct dirfile *new;
-#ifdef VMS
- dirend = strrchr (p, ']');
- if (dirend == 0)
- dirend = strrchr (p, ':');
- dirend++;
- if (dirend == (char *)1)
- dir = find_directory ("[]");
-#else
dirend = strrchr (p, '/');
-# ifdef HAVE_DOS_PATHS
+#ifdef VMS
+ if (dirend == NULL)
+ {
+ dirend = strrchr (p, ']');
+ dirend == NULL ? dirend : dirend++;
+ }
+ if (dirend == NULL)
+ {
+ dirend = strrchr (p, '>');
+ dirend == NULL ? dirend : dirend++;
+ }
+ if (dirend == NULL)
+ {
+ dirend = strrchr (p, ':');
+ dirend == NULL ? dirend : dirend++;
+ }
+#endif
+#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
const char *bslash = strrchr (p, '\\');
@@ -830,14 +887,13 @@ file_impossible (const char *filename)
if (!dirend && p[0] && p[1] == ':')
dirend = p + 1;
}
-# endif /* HAVE_DOS_PATHS */
+#endif /* HAVE_DOS_PATHS */
if (dirend == 0)
-# ifdef _AMIGA
+#ifdef _AMIGA
dir = find_directory ("");
-# else /* !VMS && !AMIGA */
+#else /* !AMIGA */
dir = find_directory (".");
-# endif /* AMIGA */
-#endif /* VMS */
+#endif /* AMIGA */
else
{
const char *dirname;
@@ -859,7 +915,14 @@ file_impossible (const char *filename)
dirname = cp;
}
dir = find_directory (dirname);
+#ifdef VMS
+ if (*slash == '/')
+ filename = p = slash + 1;
+ else
+ filename = p = slash;
+#else
filename = p = slash + 1;
+#endif
}
if (dir->contents == 0)
@@ -878,6 +941,7 @@ file_impossible (const char *filename)
new = xmalloc (sizeof (struct dirfile));
new->length = strlen (filename);
#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS)
+ /* todo: Why is this only needed on VMS? */
new->name = strcache_add_len (downcase (filename), new->length);
#else
new->name = strcache_add_len (filename, new->length);
@@ -895,13 +959,22 @@ file_impossible_p (const char *filename)
struct directory_contents *dir;
struct dirfile *dirfile;
struct dirfile dirfile_key;
-
#ifdef VMS
- dirend = strrchr (filename, ']');
- if (dirend == 0)
- dir = find_directory ("[]")->contents;
-#else
+ int want_vmsify = 0;
+#endif
+
dirend = strrchr (filename, '/');
+#ifdef VMS
+ if (dirend == NULL)
+ {
+ want_vmsify = (strpbrk (filename, "]>:^") != NULL);
+ dirend = strrchr (filename, ']');
+ }
+ if (dirend == NULL && want_vmsify)
+ dirend = strrchr (filename, '>');
+ if (dirend == NULL && want_vmsify)
+ dirend = strrchr (filename, ':');
+#endif
#ifdef HAVE_DOS_PATHS
/* Forward and backslashes might be mixed. We need the rightmost one. */
{
@@ -916,10 +989,9 @@ file_impossible_p (const char *filename)
if (dirend == 0)
#ifdef _AMIGA
dir = find_directory ("")->contents;
-#else /* !VMS && !AMIGA */
+#else /* !AMIGA */
dir = find_directory (".")->contents;
#endif /* AMIGA */
-#endif /* VMS */
else
{
const char *dirname;
@@ -941,7 +1013,14 @@ file_impossible_p (const char *filename)
dirname = cp;
}
dir = find_directory (dirname)->contents;
+#ifdef VMS
+ if (*slash == '/')
+ filename = slash + 1;
+ else
+ filename = slash;
+#else
filename = slash + 1;
+#endif
}
if (dir == 0 || dir->dirfiles.ht_vec == 0)
@@ -955,7 +1034,8 @@ file_impossible_p (const char *filename)
filename = downcase (filename);
#endif
#ifdef VMS
- filename = vmsify (filename, 1);
+ if (want_vmsify)
+ filename = vmsify (filename, 1);
#endif
dirfile_key.name = filename;
@@ -1005,7 +1085,7 @@ print_dir_data_base (void)
printf (_("# %s (key %s, mtime %d): could not be opened.\n"),
dir->name, dir->contents->path_key,dir->contents->mtime);
#else /* WINDOWS32 */
-#ifdef VMS
+#ifdef VMS_INO_T
printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
@@ -1041,7 +1121,7 @@ print_dir_data_base (void)
printf (_("# %s (key %s, mtime %d): "),
dir->name, dir->contents->path_key, dir->contents->mtime);
#else /* WINDOWS32 */
-#ifdef VMS
+#ifdef VMS_INO_T
printf (_("# %s (device %d, inode [%d,%d,%d]): "),
dir->name, dir->contents->dev,
dir->contents->ino[0], dir->contents->ino[1],
@@ -1179,9 +1259,14 @@ read_dirstream (__ptr_t stream)
* On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a
* regular file; fix that here.
*/
-#if !defined(stat) && !defined(WINDOWS32)
+#if !defined(stat) && !defined(WINDOWS32) || defined(VMS)
# ifndef VMS
int stat (const char *path, struct stat *sbuf);
+# else
+ /* We are done with the fake stat. Go back to the real stat */
+# ifdef stat
+# undef stat
+# endif
# endif
# define local_stat stat
#else