tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

make: exists("quoted dir names")



Hi Christos,

Like most of *nix, make does not much like paths with spaces
and does not handle them gracefully.
Using :Q can help, but is painful and unnatural.
Per recent complaints from some users, handling quoted paths would be nice.

The makefile below

it=${HOME}/tmp/

.for x in ${it} "${it}" "/Library/Modem Scripts"
.if exists($x)
.info $x found
.else
.warning $x not found
.endif
.endfor

all:

when run on a Mac (only thing I have with spaces in pathnames ;-)
with existing make produces:

bmake: "/tmp/tmf" line 5: /Users/sjg/tmp/ found
bmake: "/tmp/tmf" line 7: warning: "/Users/sjg/tmp/" not found
bmake: "/tmp/tmf" line 7: warning: "/Library/Modem Scripts" not found

but by dequoting the arg to Dir_FindFile:

bmake: "/tmp/tmf" line 5: /Users/sjg/tmp/ found
bmake: "/tmp/tmf" line 5: "/Users/sjg/tmp/" found
bmake: "/tmp/tmf" line 5: "/Library/Modem Scripts" found

all the current unit-tests pass (fwiw), and the dequote() below
is pretty simple minded - though not sure if worth making too
complicated.

Probably not the only change needed...

Thoughts?

diff -r 3a2bed417444 bmake/dir.c
--- a/bmake/dir.c	Sat May 06 20:44:53 2017 -0700
+++ b/bmake/dir.c	Sun May 07 10:51:25 2017 -0700
@@ -257,6 +257,43 @@
 static char *DirFindDot(Boolean, const char *, const char *);
 static char *DirLookupAbs(Path *, const char *, const char *);
 
+/**
+ * dequote input string
+ *
+ * handle "'string'", '"string"' and """string"""
+ * as well as more mundane versions.
+ * return original string if not quoted.
+ */
+char *
+dequote(const char *s, char **fp)
+{
+    static char quotes[] = "\"'";
+    char *cp;
+    char *ep;
+    int n;
+
+    if (fp)
+	*fp = NULL;			/* nothing to free */
+
+    n = 0;
+    do {
+	for (cp = quotes; *cp && s[n] != *cp; cp++) ;
+	if (*cp)
+	    n++;
+    } while (*cp);
+
+    if (n == 0)
+	return (char *)s;
+
+    /* XXX we just trim the same number of chars from the end */
+    cp = bmake_strdup(&s[n]);
+    if (fp)
+	*fp = cp;
+    ep = cp + strlen(cp) - n;
+    if (ep >= cp)
+	*ep = '\0';
+    return cp;
+}
 
 /*
  * We use stat(2) a lot, cache the results
@@ -1136,11 +1173,13 @@
     struct stat	  stb;			/* Buffer for stat, if necessary */
     Hash_Entry	  *entry;		/* Entry for mtimes table */
     const char   *trailing_dot = ".";
+    char	  *fp;
 
     /*
      * Find the final component of the name and note whether it has a
      * slash in it (the name, I mean)
      */
+    name = (const char *)dequote(name, &fp);
     cp = strrchr(name, '/');
     if (cp) {
 	hasSlash = TRUE;
@@ -1159,6 +1198,7 @@
 	    fprintf(debug_file, "couldn't open path, file not found\n");
 	}
 	misses += 1;
+	free(fp);
 	return NULL;
     }
 
@@ -1197,6 +1237,7 @@
 	    if (!hasLastDot &&
 			(file = DirFindDot(hasSlash, name, cp)) != NULL) {
 		    Lst_Close(path);
+		    free(fp);
 		    return file;
 	    }
 
@@ -1206,6 +1247,7 @@
 		    continue;
 		if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) {
 		    Lst_Close(path);
+		    free(fp);
 		    return file;
 		}
 	    }
@@ -1213,6 +1255,7 @@
 	    if (hasLastDot &&
 			(file = DirFindDot(hasSlash, name, cp)) != NULL) {
 		    Lst_Close(path);
+		    free(fp);
 		    return file;
 	    }
     }
@@ -1237,6 +1280,7 @@
 	    fprintf(debug_file, "   failed.\n");
 	}
 	misses += 1;
+	free(fp);
 	return NULL;
     }
 
@@ -1255,11 +1299,15 @@
 	if (!hasLastDot) {
 		if (dot) {
 			checkedDot = TRUE;
-			if ((file = DirLookupSubdir(dot, name)) != NULL)
+			if ((file = DirLookupSubdir(dot, name)) != NULL) {
+				free(fp);
 				return file;
+			}
 		}
-		if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
+		if (cur && (file = DirLookupSubdir(cur, name)) != NULL) {
+			free(fp);
 			return file;
+		}
 	}
 
 	(void)Lst_Open(path);
@@ -1274,6 +1322,7 @@
 	    }
 	    if ((file = DirLookupSubdir(p, name)) != NULL) {
 		Lst_Close(path);
+		free(fp);
 		return file;
 	    }
 	}
@@ -1282,11 +1331,15 @@
 	if (hasLastDot) {
 		if (dot && !checkedDot) {
 			checkedDot = TRUE;
-			if ((file = DirLookupSubdir(dot, name)) != NULL)
+			if ((file = DirLookupSubdir(dot, name)) != NULL) {
+				free(fp);
 				return file;
+			}
 		}
-		if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
+		if (cur && (file = DirLookupSubdir(cur, name)) != NULL) {
+			free(fp);
 			return file;
+		}
 	}
 
 	if (checkedDot) {
@@ -1297,6 +1350,7 @@
 	    if (DEBUG(DIR)) {
 		fprintf(debug_file, "   Checked . already, returning NULL\n");
 	    }
+	    free(fp);
 	    return NULL;
 	}
 
@@ -1317,6 +1371,7 @@
 
 	if (!hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp))
 		!= NULL)) {
+	    free(fp);
 	    if (file[0] == '\0') {
 		free(file);
 		return NULL;
@@ -1331,6 +1386,7 @@
 		continue;
 	    if ((file = DirLookupAbs(p, name, cp)) != NULL) {
 		Lst_Close(path);
+		free(fp);
 		if (file[0] == '\0') {
 		    free(file);
 		    return NULL;
@@ -1342,6 +1398,7 @@
 
 	if (hasLastDot && cur && ((file = DirLookupAbs(cur, name, cp))
 		!= NULL)) {
+	    free(fp);
 	    if (file[0] == '\0') {
 		free(file);
 		return NULL;
@@ -1379,14 +1436,16 @@
     bigmisses += 1;
     ln = Lst_Last(path);
     if (ln == NULL) {
+	free(fp);
 	return NULL;
     } else {
 	p = (Path *)Lst_Datum(ln);
     }
 
     if (Hash_FindEntry(&p->files, cp) != NULL) {
-	return (bmake_strdup(name));
+	return ((fp) ? fp : bmake_strdup(name));
     } else {
+	free(fp);
 	return NULL;
     }
 #else /* !notdef */
@@ -1400,17 +1459,18 @@
 	if (DEBUG(DIR)) {
 	    fprintf(debug_file, "   got it (in mtime cache)\n");
 	}
-	return(bmake_strdup(name));
+	return ((fp) ? fp : bmake_strdup(name));
     } else if (cached_stat(name, &stb) == 0) {
 	if (DEBUG(DIR)) {
 	    fprintf(debug_file, "   Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
 		    name);
 	}
-	return (bmake_strdup(name));
+	return ((fp) ? fp : bmake_strdup(name));
     } else {
 	if (DEBUG(DIR)) {
 	    fprintf(debug_file, "   failed. Returning NULL\n");
 	}
+	free(fp);
 	return NULL;
     }
 #endif /* notdef */
diff -r 3a2bed417444 bmake/dir.h
--- a/bmake/dir.h	Sat May 06 20:44:53 2017 -0700
+++ b/bmake/dir.h	Sun May 07 10:51:25 2017 -0700
@@ -86,6 +86,7 @@
     Hash_Table    files;    	/* Hash table of files in directory */
 } Path;
 
+char *dequote(const char *, char **);
 void Dir_Init(const char *);
 void Dir_InitCur(const char *);
 void Dir_InitDot(void);


Home | Main Index | Thread Index | Old Index