[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00266] Re: wildcard expansion problem
- Subject: [FDclone-users:00266] Re: wildcard expansion problem
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Fri, 21 May 2004 01:16:07 +0900
しらいです。
In Message-Id <86vfitrojv.knu@iDaemons.org>
"Akinori MUSHA" <knu@iDaemons.org>さんwrites:
> 文字列の一部がクオートもしくはエスケープされていると、ワイルド
> カードが展開されないようです。
んー、これは parse の順番を考え直さないと対処出来ませんね。
wild card の展開を内部実装のみで完結すると割と楽に実現出来る
のですが、regcomp() や re_comp() という選択肢も一応用意して
あるので、そっちを選んだ時の対処が厄介そうです。
環境によっては、そういう正規表現 library を使った方が賢い
場合もあるので、なかなか簡単には捨てられない選択肢です。
> 2.05d を使っていて気づきましたが、手元にあるいちばん古い版である
> 2.04a でも同様でした。
多分初期の実装からずっとそうだと思います。wild card のある
directory 要素のみ quote 処理してますから。
正規表現 library の種類によっては、_NOORIGGROB を使った場
合の挙動が期待通りにならないかも知れませんが、取り敢えずはこ
んな感じの対処でどうでしょうか?
---- Cut Here ----
diff -u old/doscom.c new/doscom.c
--- old/doscom.c Tue Jan 6 15:36:55 2004
+++ new/doscom.c Fri May 21 00:23:39 2004
@@ -1701,7 +1701,7 @@
} while (!strchr("ynYN", key));
if (key == 'n' || key == 'N') return(RET_SUCCESS);
}
- if (!(wild = evalwild(argv[n]))) {
+ if (!(wild = evalwild(argv[n], 0))) {
doserror(argv[n], ER_FILENOTFOUND);
return(RET_FAIL);
}
@@ -1779,7 +1779,7 @@
return(RET_FAIL);
}
- if (!(wild = evalwild(argv[1]))) {
+ if (!(wild = evalwild(argv[1], 0))) {
doserror(argv[1], ER_FILENOTFOUND);
return(RET_FAIL);
}
@@ -2190,7 +2190,7 @@
copyflag |= CF_VERBOSE;
}
for (n = 0; n < nf; n++) {
- if (!(wild = evalwild(arg[n]))) {
+ if (!(wild = evalwild(arg[n], 0))) {
if (nf > 1) continue;
doserror(arg[n], ER_FILENOTFOUND);
ret = RET_FAIL;
diff -u old/pathname.c new/pathname.c
--- old/pathname.c Sat Apr 24 05:25:17 2004
+++ new/pathname.c Fri May 21 01:10:00 2004
@@ -147,13 +147,10 @@
#else
static int NEAR _regexp_exec __P_((char **, char *));
#endif
-static char *NEAR catpath __P_((char *, char *, int *, int, int));
-#ifdef NODIRLOOP
-static int NEAR _evalwild __P_((int, char ***, char *, char *, int));
-#else
-static int NEAR _evalwild __P_((int, char ***, char *, char *, int,
- int, devino_t *));
-#endif
+static void NEAR addstrbuf __P_((strbuf_t *, char *, int));
+static void NEAR duplwild(wild_t *, wild_t *);
+static void NEAR freewild(wild_t *);
+static int NEAR _evalwild __P_((int, char ***, wild_t *));
#ifndef _NOUSEHASH
static int NEAR calchash __P_((char *));
static VOID NEAR inithash __P_((VOID_A));
@@ -1282,245 +1279,228 @@
# endif /* !USEREGCOMP */
#endif /* !USERE_COMP */
-static char *NEAR catpath(path, file, plenp, flen, isoverwrite)
-char *path, *file;
-int *plenp, flen, isoverwrite;
+static void NEAR addstrbuf(sp, s, len)
+strbuf_t *sp;
+char *s;
+int len;
{
- char *new;
- int i, sc;
-
-#if MSDOS || (defined (FD) && !defined (_NODOSDRIVE))
- if (*plenp >= 2 && _dospath(path)) i = 2;
- else
-#endif
- i = 0;
+ sp -> s = c_realloc(sp -> s, sp -> len + len, &(sp -> size));
+ memcpy(&(sp -> s[sp -> len]), s, len);
+ sp -> len += len;
+ sp -> s[sp -> len] = '\0';
+}
- if (*plenp <= i) sc = 0;
- else {
- sc = 1;
- if (path[i] == _SC_) {
- for (i++; i < *plenp; i++) if (path[i] != _SC_) break;
- if (i >= *plenp) sc = 0;
- }
- }
+static void NEAR duplwild(dst, src)
+wild_t *dst, *src;
+{
+ memcpy(dst, src, sizeof(wild_t));
+ dst -> fixed.s = (char *)malloc2(src -> fixed.size);
+ memcpy(dst -> fixed.s, src -> fixed.s, src -> fixed.len + 1);
+ dst -> path.s = (char *)malloc2(src -> path.size);
+ memcpy(dst -> path.s, src -> path.s, src -> path.len + 1);
- if (isoverwrite) new = realloc2(path, *plenp + sc + flen + 1);
- else {
- new = malloc2(*plenp + sc + flen + 1);
- strncpy(new, path, *plenp);
+#ifndef NODIRLOOP
+ if (src -> ino) {
+ dst -> ino = (devino_t *)malloc2(src -> nino
+ * sizeof(devino_t));
+ memcpy(dst -> ino, src -> ino, src -> nino * sizeof(devino_t));
}
- if (sc) new[(*plenp)++] = _SC_;
- strncpy2(&(new[*plenp]), file, flen);
- *plenp += flen;
- return(new);
+#endif /* !NODIRLOOP */
}
-#ifdef NODIRLOOP
-static int NEAR _evalwild(argc, argvp, s, fixed, len)
-int argc;
-char ***argvp, *s, *fixed;
-int len;
-#else
-static int NEAR _evalwild(argc, argvp, s, fixed, len, nino, ino)
-int argc;
-char ***argvp, *s, *fixed;
-int len, nino;
-devino_t *ino;
-#endif
+static void NEAR freewild(wp)
+wild_t *wp;
{
+ if (wp -> fixed.s) free(wp -> fixed.s);
+ if (wp -> path.s) free(wp -> path.s);
#ifndef NODIRLOOP
- devino_t *dupino;
+ if (wp -> ino) free(wp -> ino);
#endif
+}
+
+static int NEAR _evalwild(argc, argvp, wp)
+int argc;
+char ***argvp;
+wild_t *wp;
+{
DIR *dirp;
struct dirent *dp;
struct stat st;
reg_t *re;
+ wild_t dupl;
+ ALLOC_T flen, plen;
char *cp;
- int i, n, l;
+ int i, n, w, pc, quote, isdir;
- if (!*s) {
- if (len) {
- fixed = realloc2(fixed, len + 1 + 1);
- fixed[len++] = _SC_;
- fixed[len] = '\0';
- *argvp = (char **)realloc2(*argvp,
- (argc + 2) * sizeof(char *));
- (*argvp)[argc++] = fixed;
+ if (!*(wp -> s)) return(argc);
+
+ flen = wp -> fixed.len;
+ plen = wp -> path.len;
+ quote = wp -> quote;
+
+ if (wp -> fixed.len) addstrbuf(&(wp -> path), _SS_, 1);
+
+ for (i = w = 0; wp -> s[i]; i++) {
+ pc = parsechar(&(wp -> s[i]), -1,
+ _SC_, 0, &(wp -> quote), NULL);
+ if (pc == PC_OPQUOTE || pc == PC_CLQUOTE) {
+ if (!(wp -> flags & EA_STRIPQ))
+ addstrbuf(&(wp -> fixed), &(wp -> s[i]), 1);
+ continue;
+ }
+ else if (pc == PC_WORD) {
+ addstrbuf(&(wp -> fixed), &(wp -> s[i]), 1);
+ addstrbuf(&(wp -> path), &(wp -> s[i]), 1);
+ i++;
+ }
+ else if (pc == PC_META) {
+ if (wp -> flags & EA_KEEPMETA)
+ addstrbuf(&(wp -> fixed), &(wp -> s[i]), 1);
+ if (wp -> s[i + 1] == _SC_) continue;
+
+ if (wp -> quote == '\''
+ || (wp -> quote == '"'
+ && !strchr(DQ_METACHAR, wp -> s[i + 1]))) {
+ if (!(wp -> flags & EA_KEEPMETA))
+ addstrbuf(&(wp -> fixed),
+ &(wp -> s[i]), 1);
+ addstrbuf(&(wp -> path), &(wp -> s[i]), 1);
+ }
+ i++;
+ }
+ else if (pc == _SC_) break;
+ else if (pc == PC_NORMAL && strchr("?*[", wp -> s[i])) {
+ if (w >= 0 && wp -> s[i] == '*') w++;
+ else w = -1;
}
-#ifndef NODIRLOOP
- if (ino) free(ino);
-#endif
- return(argc);
- }
-#if MSDOS || (defined (FD) && !defined (_NODOSDRIVE))
- if (!len && _dospath(s)) {
- fixed = malloc2(2 + 1);
- fixed[0] = *s;
- fixed[1] = ':';
- fixed[2] = '\0';
-# ifdef NODIRLOOP
- return(_evalwild(argc, argvp, &(s[2]), fixed, 2));
-# else
- return(_evalwild(argc, argvp, &(s[2]), fixed, 2, nino, ino));
-# endif
+ addstrbuf(&(wp -> fixed), &(wp -> s[i]), 1);
+ addstrbuf(&(wp -> path), &(wp -> s[i]), 1);
}
-#endif
- n = 0;
- for (i = 0; s[i]; i++) {
- if (s[i] == _SC_) break;
- if (s[i] == '*' || s[i] == '?'
- || s[i] == '[' || s[i] == ']') n = 1;
-#ifdef BSPATHDELIM
- if (iskanji1(s, i)) i++;
-#endif
+ if (!(wp -> s[i])) isdir = 0;
+ else {
+ isdir = 1;
+ addstrbuf(&(wp -> fixed), _SS_, 1);
}
- if (!i) {
- fixed = realloc2(fixed, len + 1 + 1);
- fixed[len++] = _SC_;
- fixed[len] = '\0';
-#ifdef NODIRLOOP
- return(_evalwild(argc, argvp, &(s[1]), fixed, len));
-#else
- return(_evalwild(argc, argvp, &(s[1]), fixed, len, nino, ino));
-#endif
- }
+ if (!w) {
+ if (wp -> path.len <= plen) w++;
+ else if (Xstat(wp -> path.s, &st) < 0) return(argc);
- if (!n) {
- fixed = catpath(fixed, s, &len, i, 1);
- if (Xstat(fixed, &st) < 0) free(fixed);
- else if (s[i]) {
- if ((st.st_mode & S_IFMT) != S_IFDIR) free(fixed);
- else {
-#ifdef NODIRLOOP
- return(_evalwild(argc, argvp,
- &(s[i + 1]), fixed, len));
-#else
- ino = (devino_t *)realloc2(ino,
- (nino + 1) * sizeof(devino_t));
- ino[nino].dev = st.st_dev;
- ino[nino++].ino = st.st_ino;
- return(_evalwild(argc, argvp,
- &(s[i + 1]), fixed, len, nino, ino));
-#endif
- }
- }
- else {
- *argvp = (char **)realloc2(*argvp,
- (argc + 2) * sizeof(char *));
- (*argvp)[argc++] = fixed;
+ wp -> s += i;
+ if (isdir) {
+ if (!w && (st.st_mode & S_IFMT) != S_IFDIR)
+ return(argc);
+ (wp -> s)++;
}
+
+ if (*(wp -> s)) {
#ifndef NODIRLOOP
- if (ino) free(ino);
+ if (!w) {
+ wp -> ino = (devino_t *)realloc2(wp -> ino,
+ (wp -> nino + 1) * sizeof(devino_t));
+ wp -> ino[wp -> nino].dev = st.st_dev;
+ wp -> ino[(wp -> nino)++].ino = st.st_ino;
+ }
#endif
+ return(_evalwild(argc, argvp, wp));
+ }
+
+ if (!(wp -> fixed.len)) return(argc);
+ *argvp = (char **)realloc2(*argvp,
+ (argc + 2) * sizeof(char *));
+ (*argvp)[argc++] = wp -> fixed.s;
+ wp -> fixed.s = NULL;
return(argc);
}
- if (i == 2 && s[i] && s[0] == '*' && s[1] == '*') {
-#ifdef NODIRLOOP
- argc = _evalwild(argc, argvp, &(s[3]), strdup2(fixed), len);
-#else
- if (!ino) dupino = NULL;
- else {
- dupino = (devino_t *)malloc2(nino * sizeof(devino_t));
- for (n = 0; n < nino; n++) {
- dupino[n].dev = ino[n].dev;
- dupino[n].ino = ino[n].ino;
- }
- }
- argc = _evalwild(argc, argvp,
- &(s[3]), strdup2(fixed), len, nino, dupino);
-#endif
+ if (w != 2 || !isdir || strcmp(&(wp -> path.s[plen]), "**")) w = -1;
+ wp -> fixed.len = flen;
+ wp -> path.len = plen;
+ wp -> fixed.s[flen] = wp -> path.s[plen] = '\0';
+
+ if (w > 0) {
+ duplwild(&dupl, wp);
+ dupl.s += i + 1;
+ argc = _evalwild(argc, argvp, &dupl);
+ freewild(&dupl);
re = NULL;
}
- else if (!(re = regexp_init(s, i))) {
- if (fixed) free(fixed);
-#ifndef NODIRLOOP
- if (ino) free(ino);
-#endif
- return(argc);
+ else {
+ cp = malloc2(i + 2);
+ n = 0;
+ if (quote) cp[n++] = quote;
+ memcpy(&(cp[n]), wp -> s, i);
+ n += i;
+ if (wp -> quote) cp[n++] = wp -> quote;
+ re = regexp_init(cp, n);
+ free(cp);
+ if (!re) return(argc);
+ wp -> s += i + 1;
}
- if (!(dirp = Xopendir((len) ? fixed : "."))) {
+
+ if (wp -> path.len) cp = wp -> path.s;
+ else if (wp -> fixed.len) cp = _SS_;
+ else cp = ".";
+
+ if (!(dirp = Xopendir(cp))) {
regexp_free(re);
- if (fixed) free(fixed);
-#ifndef NODIRLOOP
- if (ino) free(ino);
-#endif
return(argc);
}
+ addstrbuf(&(wp -> path), _SS_, 1);
while ((dp = Xreaddir(dirp))) {
if (isdotdir(dp -> d_name)) continue;
- l = len;
- cp = catpath(fixed, dp -> d_name, &l, strlen(dp -> d_name), 0);
- if (s[i]) {
- if (Xstat(cp, &st) < 0
+ duplwild(&dupl, wp);
+ n = strlen(dp -> d_name);
+ addstrbuf(&(dupl.fixed), dp -> d_name, n);
+ addstrbuf(&(dupl.path), dp -> d_name, n);
+
+ if (isdir) {
+ if (re) n = regexp_exec(re, dp -> d_name, 1);
+ else n = (*(dp -> d_name) == '.') ? 0 : 1;
+
+ if (!n || Xstat(dupl.path.s, &st) < 0
|| (st.st_mode & S_IFMT) != S_IFDIR) {
- free(cp);
+ freewild(&dupl);
continue;
}
#ifndef NODIRLOOP
- dupino = (devino_t *)malloc2((nino + 1)
- * sizeof(devino_t));
- for (n = 0; n < nino; n++) {
- dupino[n].dev = ino[n].dev;
- dupino[n].ino = ino[n].ino;
- }
- dupino[n].dev = st.st_dev;
- dupino[n].ino = st.st_ino;
-#endif
if (!re) {
- if (*(dp -> d_name) == '.') {
- free(cp);
-#ifndef NODIRLOOP
- free(dupino);
-#endif
+ for (n = 0; n < dupl.nino; n++)
+ if (dupl.ino[n].dev == st.st_dev
+ && dupl.ino[n].ino == st.st_ino)
+ break;
+ if (n < dupl.nino) {
+ freewild(&dupl);
continue;
}
-#ifdef NODIRLOOP
- argc = _evalwild(argc, argvp, s, cp, l);
-#else
- for (n = 0; n < nino; n++)
- if (ino[n].dev == st.st_dev
- && ino[n].ino == st.st_ino) break;
- if (n < nino) {
- free(cp);
- free(dupino);
- }
- else argc = _evalwild(argc, argvp,
- s, cp, l, nino + 1, dupino);
-#endif
- }
- else if (!regexp_exec(re, dp -> d_name, 1)) {
- free(cp);
-#ifndef NODIRLOOP
- free(dupino);
-#endif
}
-#ifdef NODIRLOOP
- else argc = _evalwild(argc, argvp, &(s[i + 1]), cp, l);
-#else
- else argc = _evalwild(argc, argvp,
- &(s[i + 1]), cp, l, nino + 1, dupino);
+
+ dupl.ino = (devino_t *)realloc2(dupl.ino,
+ (dupl.nino + 1) * sizeof(devino_t));
+ dupl.ino[dupl.nino].dev = st.st_dev;
+ dupl.ino[(dupl.nino)++].ino = st.st_ino;
#endif
+
+ addstrbuf(&(dupl.fixed), _SS_, 1);
+ argc = _evalwild(argc, argvp, &dupl);
}
- else if (!re || !regexp_exec(re, dp -> d_name, 1)) free(cp);
- else {
+ else if (regexp_exec(re, dp -> d_name, 1)) {
*argvp = (char **)realloc2(*argvp,
(argc + 2) * sizeof(char *));
- (*argvp)[argc++] = cp;
+ (*argvp)[argc++] = dupl.fixed.s;
+ dupl.fixed.s = NULL;
}
+
+ freewild(&dupl);
}
Xclosedir(dirp);
regexp_free(re);
- if (fixed) free(fixed);
-#ifndef NODIRLOOP
- if (ino) free(ino);
-#endif
+
return(argc);
}
@@ -1531,18 +1511,29 @@
return(strpathcmp2(*((char **)vp1), *((char **)vp2)));
}
-char **evalwild(s)
+char **evalwild(s, flags)
char *s;
+int flags;
{
+ wild_t w;
char **argv;
int argc;
argv = (char **)malloc2(1 * sizeof(char *));
-#ifdef NODIRLOOP
- argc = _evalwild(0, &argv, s, NULL, 0);
-#else
- argc = _evalwild(0, &argv, s, NULL, 0, 0, NULL);
+ w.s = s;
+ w.fixed.s = c_realloc(NULL, 0, &(w.fixed.size));
+ w.path.s = c_realloc(NULL, 0, &(w.path.size));
+ w.fixed.len = w.path.len = (ALLOC_T)0;
+ w.quote = '\0';
+#ifndef NODIRLOOP
+ w.nino = 0;
+ w.ino = NULL;
#endif
+ w.flags = flags;
+
+ argc = _evalwild(0, &argv, &w);
+ freewild(&w);
+
if (!argc) {
free(argv);
return(NULL);
@@ -3188,60 +3179,29 @@
char ***argvp;
int flags;
{
- char *cp, **wild;
- ALLOC_T size;
- int i, j, n, pc, w, quote;
+ char **wild;
+ int i, n;
for (n = 0; n < argc; n++) {
- cp = c_realloc(NULL, 0, &size);
- for (i = j = w = 0, quote = '\0'; (*argvp)[n][i]; i++) {
- cp = c_realloc(cp, j + 1, &size);
- pc = parsechar(&((*argvp)[n][i]), -1,
- '\0', 0, "e, NULL);
- if (pc == PC_OPQUOTE || pc == PC_CLQUOTE) {
- if (flags & EA_STRIPQ) continue;
- }
- else if (pc == PC_WORD) cp[j++] = (*argvp)[n][i++];
- else if (pc == PC_META) {
- i++;
- if (quote
- && !strchr(DQ_METACHAR, (*argvp)[n][i]))
- cp[j++] = PMETA;
- }
- else if (pc != PC_NORMAL) /*EMPTY*/;
- else if (!strchr("?*[", (*argvp)[n][i])) /*EMPTY*/;
- else if ((wild = evalwild((*argvp)[n]))) {
- w = countvar(wild);
- if (w > 1) {
- *argvp = (char **)realloc2(*argvp,
- (argc + w) * sizeof(char *));
- if (!*argvp) {
- free(cp);
- freevar(wild);
- return(argc);
- }
- memmove((char *)(&((*argvp)[n + w])),
- (char *)(&((*argvp)[n + 1])),
- (argc - n) * sizeof(char *));
- argc += w - 1;
- }
- free((*argvp)[n]);
- free(cp);
- memmove((char *)(&((*argvp)[n])),
- (char *)wild, w * sizeof(char *));
- free(wild);
- n += w - 1;
- break;
- }
-
- cp[j++] = (*argvp)[n][i];
+ if (!(wild = evalwild((*argvp)[n], flags))) {
+ stripquote((*argvp)[n], flags);
+ continue;
}
- if (!w) {
- cp[j] = '\0';
- free((*argvp)[n]);
- (*argvp)[n] = cp;
- }
+ i = countvar(wild);
+ if (i > 1) {
+ *argvp = (char **)realloc2(*argvp,
+ (argc + i) * sizeof(char *));
+ memmove((char *)(&((*argvp)[n + i])),
+ (char *)(&((*argvp)[n + 1])),
+ (argc - n) * sizeof(char *));
+ argc += i - 1;
+ }
+ free((*argvp)[n]);
+ memmove((char *)(&((*argvp)[n])),
+ (char *)wild, i * sizeof(char *));
+ free(wild);
+ n += i - 1;
}
return(argc);
}
diff -u old/pathname.h new/pathname.h
--- old/pathname.h Sat Apr 24 03:37:06 2004
+++ new/pathname.h Fri May 21 00:23:15 2004
@@ -104,6 +104,12 @@
#define CM_RECALC 0100
#define CM_REHASH 0200
+typedef struct _strbuf_t {
+ char *s;
+ ALLOC_T size;
+ ALLOC_T len;
+} strbuf_t;
+
#ifndef NODIRLOOP
typedef struct _devino_t {
dev_t dev;
@@ -111,6 +117,18 @@
} devino_t;
#endif
+typedef struct _wild_t {
+ char *s;
+ strbuf_t fixed;
+ strbuf_t path;
+ int quote;
+#ifndef NODIRLOOP
+ int nino;
+ devino_t *ino;
+#endif
+ u_char flags;
+} wild_t;
+
#ifdef NOUID_T
typedef u_short uid_t;
typedef u_short gid_t;
@@ -202,7 +220,7 @@
extern int regexp_exec __P_((reg_t *, char *, int));
extern VOID regexp_free __P_((reg_t *));
extern int cmppath __P_((CONST VOID_P, CONST VOID_P));
-extern char **evalwild __P_((char *));
+extern char **evalwild __P_((char *, int));
#ifndef _NOUSEHASH
hashlist **duplhash __P_((hashlist **));
#endif
---- Cut Here ----
しらい たかし