Add ISDIRSEP() helper macro and use it

Create a ISDIRSEP() macro to check for directory separator chars
using the stopchar_map, and replace inline checks and explicit
STOP_SET calls with this macro.

* src/makeint.h (ISDIRSEP): Create the macro using MAP_DIRSEP.
* src/dir.c (find_directory): Replace inline checks with ISDIRSEP.
(file_exists_p): Ditto.
(file_impossible): Ditto.
(file_impossible_p): Ditto.
(local_stat): Ditto.
* src/file.c (lookup_file): Ditto.
* src/function.c (abspath): Ditto.
* src/job.c (_is_unixy_shell): Ditto.
(is_bourne_compatible_shell): Ditto.
(construct_command_argv): Ditto.
* src/main.c (find_and_set_default_shell): Ditto.
(main): Ditto.
* src/read.c (eval): Ditto.
(parse_file_seq): Ditto.
* src/remake.c (name_mtime): Ditto.
* src/vpath.c (construct_vpath_list): Ditto.
This commit is contained in:
Paul Smith 2022-10-17 23:36:36 -04:00
parent b79791533b
commit 7bb7bb4ba4
9 changed files with 39 additions and 63 deletions

View File

@ -530,9 +530,7 @@ find_directory (const char *name)
tstart = tem;
if (tstart[1] == ':')
tstart += 2;
for (tend = tem + (len - 1);
tend > tstart && (*tend == '/' || *tend == '\\');
tend--)
for (tend = tem + (len - 1); tend > tstart && ISDIRSEP (*tend); tend--)
*tend = '\0';
r = stat (tem, &st);
@ -867,7 +865,7 @@ file_exists_p (const char *name)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < name + 3 && name[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
(ISDIRSEP (*dirend) || *dirend == ':'))
dirend++;
#endif
p = alloca (dirend - name + 1);
@ -943,7 +941,7 @@ file_impossible (const char *filename)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < p + 3 && p[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
(ISDIRSEP (*dirend) || *dirend == ':'))
dirend++;
#endif
cp = alloca (dirend - p + 1);
@ -1041,7 +1039,7 @@ file_impossible_p (const char *filename)
#ifdef HAVE_DOS_PATHS
/* d:/ and d: are *very* different... */
if (dirend < filename + 3 && filename[1] == ':' &&
(*dirend == '/' || *dirend == '\\' || *dirend == ':'))
(ISDIRSEP (*dirend) || *dirend == ':'))
dirend++;
#endif
cp = alloca (dirend - filename + 1);
@ -1314,8 +1312,7 @@ local_stat (const char *path, struct stat *buf)
/* Make sure the parent of "." exists and is a directory, not a
file. This is because 'stat' on Windows normalizes the argument
foo/. => foo without checking first that foo is a directory. */
if (plen > 2 && path[plen - 1] == '.'
&& (path[plen - 2] == '/' || path[plen - 2] == '\\'))
if (plen > 2 && path[plen - 1] == '.' && ISDIRSEP (path[plen - 2]))
{
char parent[MAXPATHLEN+1];

View File

@ -108,20 +108,10 @@ lookup_file (const char *name)
while (name[0] == '<' && name[1] == '>' && name[2] != '\0')
name += 2;
#endif
while (name[0] == '.'
#ifdef HAVE_DOS_PATHS
&& (name[1] == '/' || name[1] == '\\')
#else
&& name[1] == '/'
#endif
&& name[2] != '\0')
while (name[0] == '.' && ISDIRSEP (name[1]) && name[2] != '\0')
{
name += 2;
while (*name == '/'
#ifdef HAVE_DOS_PATHS
|| *name == '\\'
#endif
)
while (ISDIRSEP (*name))
/* Skip following slashes: ".//foo" is "foo", not "/foo". */
++name;
}

View File

@ -2135,7 +2135,7 @@ func_not (char *o, char **argv, char *funcname UNUSED)
#ifdef HAVE_DOS_PATHS
# ifdef __CYGWIN__
# define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_DIRSEP))
# define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || ISDIRSEP (n[0]))
# else
# define IS_ABSOLUTE(n) (n[0] && n[1] == ':')
# endif
@ -2169,9 +2169,9 @@ abspath (const char *name, char *apath)
strcpy (apath, starting_directory);
#ifdef HAVE_DOS_PATHS
if (STOP_SET (name[0], MAP_DIRSEP))
if (ISDIRSEP (name[0]))
{
if (STOP_SET (name[1], MAP_DIRSEP))
if (ISDIRSEP (name[1]))
{
/* A UNC. Don't prepend a drive letter. */
apath[0] = name[0];
@ -2191,7 +2191,7 @@ abspath (const char *name, char *apath)
else
{
#if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS)
if (STOP_SET (name[0], MAP_DIRSEP))
if (ISDIRSEP (name[0]))
root_len = 1;
#endif
memcpy (apath, name, root_len);
@ -2200,7 +2200,7 @@ abspath (const char *name, char *apath)
/* Get past the root, since we already copied it. */
name += root_len;
#ifdef HAVE_DOS_PATHS
if (! STOP_SET (apath[root_len - 1], MAP_DIRSEP))
if (! ISDIRSEP (apath[root_len - 1]))
{
/* Convert d:foo into d:./foo and increase root_len. */
apath[2] = '.';
@ -2220,7 +2220,7 @@ abspath (const char *name, char *apath)
size_t len;
/* Skip sequence of multiple path-separators. */
while (STOP_SET (*start, MAP_DIRSEP))
while (ISDIRSEP (*start))
++start;
/* Find end of path component. */
@ -2237,12 +2237,12 @@ abspath (const char *name, char *apath)
{
/* Back up to previous component, ignore if at root already. */
if (dest > apath + root_len)
for (--dest; ! STOP_SET (dest[-1], MAP_DIRSEP); --dest)
for (--dest; ! ISDIRSEP (dest[-1]); --dest)
;
}
else
{
if (! STOP_SET (dest[-1], MAP_DIRSEP))
if (! ISDIRSEP (dest[-1]))
*dest++ = '/';
if (dest + len >= apath_limit)
@ -2254,7 +2254,7 @@ abspath (const char *name, char *apath)
}
/* Unless it is root strip trailing separator. */
if (dest > apath + root_len && STOP_SET (dest[-1], MAP_DIRSEP))
if (dest > apath + root_len && ISDIRSEP (dest[-1]))
--dest;
*dest = '\0';

View File

@ -416,7 +416,8 @@ _is_unixy_shell (const char *path)
else if (!name) /* name and p must be 0 */
name = path;
if (*name == '/' || *name == '\\') name++;
if (ISDIRSEP (*name))
name++;
i = 0;
while (known_os2shells[i] != NULL)
@ -439,38 +440,30 @@ is_bourne_compatible_shell (const char *path)
static const char *unix_shells[] = {
"sh",
"bash",
"dash",
"ksh",
"rksh",
"zsh",
"ash",
"dash",
NULL
};
const char **s;
/* find the rightmost '/' or '\\' */
const char *name = strrchr (path, '/');
char *p = strrchr (path, '\\');
/* find the last directory separator, or the beginning of the string. */
const char *cp = path + strlen (path);
if (name && p) /* take the max */
name = (name > p) ? name : p;
else if (p) /* name must be 0 */
name = p;
else if (!name) /* name and p must be 0 */
name = path;
if (*name == '/' || *name == '\\')
++name;
while (cp > path && !ISDIRSEP (cp[-1]))
--cp;
/* this should be able to deal with extensions on Windows-like systems */
for (s = unix_shells; *s != NULL; ++s)
{
#if defined(WINDOWS32) || defined(__MSDOS__)
size_t len = strlen (*s);
if ((strlen (name) >= len && STOP_SET (name[len], MAP_DOT|MAP_NUL))
&& strncasecmp (name, *s, len) == 0)
if ((strlen (cp) >= len && STOP_SET (cp[len], MAP_DOT|MAP_NUL))
&& strncasecmp (cp, *s, len) == 0)
#else
if (strcmp (name, *s) == 0)
if (strcmp (cp, *s) == 0)
#endif
return 1; /* a known unix-style shell */
}
@ -3053,8 +3046,7 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
}
else
#endif
if (p[1] != '\\' && p[1] != '\''
&& !ISSPACE (p[1])
if (p[1] != '\\' && p[1] != '\'' && !ISSPACE (p[1])
&& strchr (sh_chars_sh, p[1]) == 0)
/* back up one notch, to copy the backslash */
--p;
@ -3688,8 +3680,7 @@ construct_command_argv (char *line, char **restp, struct file *file,
performed) and if shell is an absolute path without drive letter,
try whether it exists e.g.: if "/bin/sh" does not exist use
"$UNIXROOT/bin/sh" instead. */
if (unixroot && shell && strcmp (shell, last_shell) != 0
&& (shell[0] == '/' || shell[0] == '\\'))
if (unixroot && shell && ISDIRSEP (shell[0]) && !streq (shell, last_shell))
{
/* trying a new shell, check whether it exists */
size_t size = strlen (shell);

View File

@ -1016,12 +1016,10 @@ find_and_set_default_shell (const char *token)
"cmd.exe" case-insensitive. */
tokend = search_token + strlen (search_token) - 3;
if (((tokend == search_token
|| (tokend > search_token
&& (tokend[-1] == '/' || tokend[-1] == '\\')))
|| (tokend > search_token && ISDIRSEP (tokend[-1])))
&& !strcasecmp (tokend, "cmd"))
|| ((tokend - 4 == search_token
|| (tokend - 4 > search_token
&& (tokend[-5] == '/' || tokend[-5] == '\\')))
|| (tokend - 4 > search_token && ISDIRSEP (tokend[-5])))
&& !strcasecmp (tokend - 4, "cmd.exe")))
{
batch_mode_shell = 1;
@ -1320,7 +1318,7 @@ main (int argc, char **argv, char **envp)
else
{
program = start + strlen (start);
while (program > start && ! STOP_SET (program[-1], MAP_DIRSEP))
while (program > start && ! ISDIRSEP (program[-1]))
--program;
/* Remove the .exe extension if present. */
@ -1762,7 +1760,7 @@ main (int argc, char **argv, char **envp)
But allow -C/ just in case someone wants that. */
{
char *p = (char *)dir + strlen (dir) - 1;
while (p > dir && (p[0] == '/' || p[0] == '\\'))
while (p > dir && ISDIRSEP (p[0]))
--p;
p[1] = '\0';
}

View File

@ -468,6 +468,8 @@ extern int unixy_shell;
#define STOP_SET(_v,_m) ANY_SET(stopchar_map[(unsigned char)(_v)],(_m))
/* True if C is a directory separator on the current system. */
#define ISDIRSEP(c) STOP_SET((c),MAP_DIRSEP)
/* True if C is whitespace but not newline. */
#define ISBLANK(c) STOP_SET((c),MAP_BLANK)
/* True if C is whitespace including newlines. */

View File

@ -1108,7 +1108,7 @@ eval (struct ebuffer *ebuf, int set_default)
Note that the only separators of targets in this context are
whitespace and a left paren. If others are possible, add them
to the string in the call to strchr. */
while (colonp && (colonp[1] == '/' || colonp[1] == '\\') &&
while (colonp && ISDIRSEP (colonp[1]) &&
isalpha ((unsigned char) colonp[-1]) &&
(colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0))
colonp = find_char_unquote (colonp + 1, ':');
@ -1279,8 +1279,7 @@ eval (struct ebuffer *ebuf, int set_default)
do {
check_again = 0;
/* For DOS-style paths, skip a "C:\..." or a "C:/..." */
if (p != 0 && (p[1] == '\\' || p[1] == '/') &&
isalpha ((unsigned char)p[-1]) &&
if (p != 0 && ISDIRSEP (p[1]) && isalpha ((unsigned char)p[-1]) &&
(p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) {
p = strchr (p + 1, ':');
check_again = 1;
@ -3270,7 +3269,7 @@ parse_file_seq (char **stringp, size_t size, int stopmap,
Tokens separated by spaces are treated as separate paths since make
doesn't allow path names with spaces. */
if (p && p == s+1 && p[0] == ':'
&& isalpha ((unsigned char)s[0]) && STOP_SET (p[1], MAP_DIRSEP))
&& isalpha ((unsigned char)s[0]) && ISDIRSEP (p[1]))
p = find_map_unquote (p+1, findmap);
#endif

View File

@ -1564,7 +1564,7 @@ name_mtime (const char *name)
tend--;
if (*tend == '.' && tend > tstart)
tend--;
for ( ; tend > tstart && (*tend == '/' || *tend == '\\'); tend--)
for ( ; tend > tstart && ISDIRSEP (*tend); tend--)
*tend = '\0';
}
else

View File

@ -239,8 +239,7 @@ construct_vpath_list (char *pattern, char *dirpath)
also define HAVE_DOS_PATHS would like us to recognize
colons after the drive letter in the likes of
"D:/foo/bar:C:/xyzzy". */
&& (*p != PATH_SEPARATOR_CHAR
|| (p == v + 1 && (p[1] == '/' || p[1] == '\\')))
&& (*p != PATH_SEPARATOR_CHAR || (p == v + 1 && ISDIRSEP (p[1])))
#else
&& *p != PATH_SEPARATOR_CHAR
#endif