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