/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char* ptr = pattern; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob, limitp); if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) return globexp2(ptr, pattern, pglob, limitp); return glob0(pattern, pglob, limitp); }
/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob) { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == CHAR_LBRACE && pattern[1] == CHAR_RBRACE && pattern[2] == CHAR_EOS) return glob0(pattern, pglob); while ((ptr = (const Char *) g_strchr(ptr, CHAR_LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv)) return rv; return glob0(pattern, pglob); }
// // Expand recursively a glob {} pattern. When there is no more expansion // invoke the standard globbing routine to glob the rest of the magic // characters // static int globexp1(const char *pattern, glob_t *pglob, size_t *limit) { const char *ptr = pattern; int rv; // Protect a single {}, for find(1), like csh if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) { return glob0(pattern, pglob, limit); } while ((ptr = (const char *) strchr((char *) ptr, LBRACE)) != NULL) { if (!globexp2(ptr, pattern, pglob, &rv, limit)) return rv; } return glob0(pattern, pglob, limit); }
static int glob_(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob, unsigned long maxfiles, int maxdepth) { const unsigned char *patnext; int c; Char *bufnext, *bufend, patbuf[PATH_MAX]; struct glob_lim limit = { 0, 0, 0 }; pglob->gl_maxdepth = maxdepth; pglob->gl_maxfiles = maxfiles; patnext = (unsigned char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_statv = NULL; if (!(flags & GLOB_DOOFFS)) { pglob->gl_offs = 0; } } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) { return GLOB_NOSPACE; } if (strlen(pattern) >= PATH_MAX) { return GLOB_NOMATCH; } bufnext = patbuf; bufend = bufnext + PATH_MAX - 1; if (flags & GLOB_NOESCAPE) { while (bufnext < bufend && (c = *patnext++) != EOS) { *bufnext++ = c; } } else { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) { if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else { *bufnext++ = c; } } } *bufnext = EOS; if (flags & GLOB_BRACE) { return globexp1(patbuf, pglob, &limit, 0); } else { return glob0(patbuf, pglob, &limit); } }
int _wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob) { const unsigned char *patnext; int c; gchar *bufnext, *bufend, patbuf[PATH_MAX]; patnext = (unsigned char *) pattern; if (!(flags & WAPI_GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_offs = 0; } pglob->gl_flags = flags & ~WAPI_GLOB_MAGCHAR; bufnext = patbuf; bufend = bufnext + PATH_MAX - 1; /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; *bufnext = EOS; return glob0(dir, patbuf, pglob, flags & WAPI_GLOB_IGNORECASE, flags & WAPI_GLOB_UNIQUE); }
/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob, size_t *limit) { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob, limit); while ((ptr = g_strchr(ptr, LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv, limit)) return rv; return glob0(pattern, pglob, limit); }
/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp, int recursion) { const Char* ptr = pattern; if (pglob->gl_maxdepth > 0 && recursion > pglob->gl_maxdepth) { errno = 0; return 0; } /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) { return glob0(pattern, pglob, limitp); } if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) { return globexp2(ptr, pattern, pglob, limitp, recursion + 1); } return glob0(pattern, pglob, limitp); }
int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const char *patnext; size_t limit; char *bufnext, *bufend, patbuf[MAXPATH], prot; patnext = pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } if (flags & GLOB_LIMIT) { limit = pglob->gl_matchc; if (limit == 0) limit = ARG_MAX; } else { limit = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATH - 1; if (flags & GLOB_NOESCAPE) { while (bufend - bufnext >= 1) { if (*patnext == EOS) break; *bufnext++ = *patnext++; } } else { // Protect the quoted characters while (bufend - bufnext >= 1) { if (*patnext == EOS) break; if (*patnext == QUOTE) { if (*++patnext == EOS) { *bufnext++ = QUOTE | M_PROTECT; continue; } prot = M_PROTECT; } else { prot = 0; } *bufnext++ = *patnext++ | prot; } } *bufnext = EOS; if (flags & GLOB_BRACE) { return globexp1(patbuf, pglob, &limit); } else { return glob0(patbuf, pglob, &limit); } }
/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1 ( const Char *pattern, glob_t *pglob ) { const Char* ptr = pattern; int rv; ssize_t span; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob); while ((span = g_strchr(ptr, LBRACE)) >= 0) { ptr += span; if (!globexp2(ptr, pattern, pglob, &rv)) return rv; } return glob0(pattern, pglob); }
int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN]; struct glob_lim limit = { 0, 0, 0 }; if (strnlen(pattern, PATH_MAX) == PATH_MAX) return(GLOB_NOMATCH); patnext = (u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_statv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) return GLOB_NOSPACE; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; if (flags & GLOB_NOESCAPE) while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; else { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } *bufnext = EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob, &limit); else return glob0(patbuf, pglob, &limit); }
int bsd_glob ( const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob ) { const unsigned char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; patnext = (const unsigned char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN; if (flags & GLOB_QUOTE) { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != EOS) { if (c == QUOTE) { if ((c = *patnext++) == EOS) { c = QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } } else while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; *bufnext = EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob); else return glob0(patbuf, pglob); }
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const u_char *patnext; int c; Char *bufnext, *bufend, patbuf[MaxPathLen+1]; patnext = (const u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MaxPathLen; if (flags & GLOB_QUOTE) { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) if (c == CHAR_QUOTE) { if ((c = *patnext++) == CHAR_EOS) { c = CHAR_QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } else while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) *bufnext++ = c; *bufnext = CHAR_EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob); else return glob0(patbuf, pglob); }
int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const char *patnext; size_t limit; Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; mbstate_t mbs; wchar_t wc; size_t clen; patnext = pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } if (flags & GLOB_LIMIT) { limit = pglob->gl_matchc; if (limit == 0) limit = ARG_MAX; } else limit = 0; pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; if (flags & GLOB_NOESCAPE) { memset(&mbs, 0, sizeof(mbs)); while (bufend - bufnext >= MB_CUR_MAX) { clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); if (clen == (size_t)-1 || clen == (size_t)-2) return (GLOB_NOMATCH); else if (clen == 0) break; *bufnext++ = wc; patnext += clen; } } else { /* Protect the quoted characters. */ memset(&mbs, 0, sizeof(mbs)); while (bufend - bufnext >= MB_CUR_MAX) { if (*patnext == QUOTE) { if (*++patnext == EOS) { *bufnext++ = QUOTE | M_PROTECT; continue; } prot = M_PROTECT; } else prot = 0; clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); if (clen == (size_t)-1 || clen == (size_t)-2) return (GLOB_NOMATCH); else if (clen == 0) break; *bufnext++ = wc | prot; patnext += clen; } } *bufnext = EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob, &limit); else return glob0(patbuf, pglob, &limit); }
FOR_IN(dirname,dirs,5) FOR_IN_SEQ(name,glob1(dirname, basename),7,9) __last_yield = 2; return __os__::__path__::join(2, dirname, name); __after_yield_2:; END_FOR END_FOR } else { FOR_IN(dirname,dirs,11) FOR_IN_SEQ(name,glob0(dirname, basename),13,15) __last_yield = 3; return __os__::__path__::join(2, dirname, name); __after_yield_3:; END_FOR END_FOR } throw new StopIteration(); } }; __iter<str *> *iglob(str *pathname) { /**
int bsd_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const U8 *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN]; #ifdef MACOS_TRADITIONAL char *new_pat, *p, *np; int err; size_t len; #endif #ifndef MACOS_TRADITIONAL patnext = (U8 *) pattern; #endif /* TODO: GLOB_APPEND / GLOB_DOOFFS aren't supported yet */ #if 0 if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } #else pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_offs = 0; #endif pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; #ifdef DOSISH /* Nasty hack to treat patterns like "C:*" correctly. In this * case, the * should match any file in the current directory * on the C: drive. However, the glob code does not treat the * colon specially, so it looks for files beginning "C:" in * the current directory. To fix this, change the pattern to * add an explicit "./" at the start (just after the drive * letter and colon - ie change to "C:./"). */ if (isalpha(pattern[0]) && pattern[1] == ':' && pattern[2] != BG_SEP && pattern[2] != BG_SEP2 && bufend - bufnext > 4) { *bufnext++ = pattern[0]; *bufnext++ = ':'; *bufnext++ = '.'; *bufnext++ = BG_SEP; patnext += 2; } #endif #ifdef MACOS_TRADITIONAL /* Check if we need to match a volume name (e.g. '*HD:*') */ g_matchVol = false; p = (char *) pattern; if (*p != BG_SEP) { p++; while (*p != BG_EOS) { if (*p == BG_SEP) { g_matchVol = true; break; } p++; } } /* Transform the pattern: * (a) Resolve updirs, e.g. * '*:t*p::' -> '*:' * ':a*:tmp::::' -> '::' * ':base::t*p:::' -> '::' * '*HD::' -> return 0 (error, quit silently) * * (b) Remove a single trailing ':', unless it's a "match volume only" * pattern like '*HD:'; e.g. * '*:tmp:' -> '*:tmp' but * '*HD:' -> '*HD:' * (If we don't do that, even filenames will have a trailing ':' in * the result.) */ /* We operate on a copy of the pattern */ len = strlen(pattern); Newx(new_pat, len + 1, char); if (new_pat == NULL) return (GLOB_NOSPACE); p = (char *) pattern; np = new_pat; while (*np++ = *p++) ; /* Resolve updirs ... */ err = resolve_updirs(new_pat); if (err) { Safefree(new_pat); /* The pattern is incorrect: tried to move up above the volume root, see above. We quit silently. */ return 0; } /* remove trailing colon ... */ remove_trColon(new_pat); patnext = (U8 *) new_pat; #endif /* MACOS_TRADITIONAL */ if (flags & GLOB_QUOTE) { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != BG_EOS) if (c == BG_QUOTE) { #ifdef DOSISH /* To avoid backslashitis on Win32, * we only treat \ as a quoting character * if it precedes one of the * metacharacters []-{}~\ */ if ((c = *patnext++) != '[' && c != ']' && c != '-' && c != '{' && c != '}' && c != '~' && c != '\\') { #else if ((c = *patnext++) == BG_EOS) { #endif c = BG_QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } else while (bufnext < bufend && (c = *patnext++) != BG_EOS) *bufnext++ = c; *bufnext = BG_EOS; #ifdef MACOS_TRADITIONAL if (flags & GLOB_BRACE) err = globexp1(patbuf, pglob); else err = glob0(patbuf, pglob); Safefree(new_pat); return err; #else if (flags & GLOB_BRACE) return globexp1(patbuf, pglob); else return glob0(patbuf, pglob); #endif } /* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob) { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == BG_LBRACE && pattern[1] == BG_RBRACE && pattern[2] == BG_EOS) return glob0(pattern, pglob); while ((ptr = (const Char *) g_strchr((Char *) ptr, BG_LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv)) return rv; return glob0(pattern, pglob); } /* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) { int i; Char *lm, *ls; const Char *pe, *pm, *pl; Char patbuf[MAXPATHLEN]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) ; *lm = BG_EOS; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) if (*pe == BG_LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++) ; if (*pe == BG_EOS) { /* * We could not find a matching BG_RBRACKET. * Ignore and just look for BG_RBRACE */ pe = pm; } } else if (*pe == BG_LBRACE) i++; else if (*pe == BG_RBRACE) { if (i == 0) break; i--; } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == BG_EOS) { *rv = glob0(patbuf, pglob); return 0; } for (i = 0, pl = pm = ptr; pm <= pe; pm++) { switch (*pm) { case BG_LBRACKET: /* Ignore everything between [] */ for (pl = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++) ; if (*pm == BG_EOS) { /* * We could not find a matching BG_RBRACKET. * Ignore and just look for BG_RBRACE */ pm = pl; } break; case BG_LBRACE: i++; break; case BG_RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case BG_COMMA: if (i && *pm == BG_COMMA) break; else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) ; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS; ) ; /* Expand the current pattern */ #ifdef GLOB_DEBUG qprintf("globexp2:", patbuf); #endif /* GLOB_DEBUG */ *rv = globexp1(patbuf, pglob); /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } } *rv = 0; return 0; }
/* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit) { int i; Char *lm, *ls; const Char *pe, *pm, *pm1, *pl; Char patbuf[MAXPATHLEN]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) continue; *lm = EOS; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) if (*pe == LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) continue; if (*pe == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pe = pm; } } else if (*pe == LBRACE) i++; else if (*pe == RBRACE) { if (i == 0) break; i--; } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == EOS) { *rv = glob0(patbuf, pglob, limit); return 0; } for (i = 0, pl = pm = ptr; pm <= pe; pm++) switch (*pm) { case LBRACKET: /* Ignore everything between [] */ for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++) continue; if (*pm == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pm = pm1; } break; case LBRACE: i++; break; case RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case COMMA: if (i && *pm == COMMA) break; else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) continue; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != EOS;) continue; /* Expand the current pattern */ #ifdef DEBUG qprintf("globexp2:", patbuf); #endif *rv = globexp1(patbuf, pglob, limit); /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } *rv = 0; return 0; }
static int __glob(const char *pattern, glob_t *pglob) { const char *patnext; struct glob_limit limit = { 0, 0, 0, 0 }; Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; mbstate_t mbs; wchar_t wc; size_t clen; locale_t loc = __current_locale(); int mb_cur_max = MB_CUR_MAX_L(loc); patnext = pattern; if (!(pglob->gl_flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(pglob->gl_flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; if (pglob->gl_flags & GLOB_NOESCAPE) { memset(&mbs, 0, sizeof(mbs)); while (bufend - bufnext >= mb_cur_max) { clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc); if (clen == (size_t)-1 || clen == (size_t)-2) return (GLOB_NOMATCH); else if (clen == 0) break; *bufnext++ = wc; patnext += clen; } } else { /* Protect the quoted characters. */ memset(&mbs, 0, sizeof(mbs)); while (bufend - bufnext >= mb_cur_max) { if (*patnext == QUOTE) { if (*++patnext == EOS) { *bufnext++ = QUOTE | M_PROTECT; continue; } prot = M_PROTECT; } else prot = 0; clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc); if (clen == (size_t)-1 || clen == (size_t)-2) return (GLOB_NOMATCH); else if (clen == 0) break; *bufnext++ = wc | prot; patnext += clen; } } *bufnext = EOS; if (pglob->gl_flags & GLOB_BRACE) return globexp1(patbuf, pglob, &limit, loc); else return glob0(patbuf, pglob, &limit, loc); }
/* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, struct glob_lim *limitp, int recursion) { int i, rv; Char *lm, *ls; const Char *pe, *pm, *pl; Char patbuf[PATH_MAX]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) ; *lm = EOS; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) { if (*pe == LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) ; if (*pe == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pe = pm; } } else if (*pe == LBRACE) { i++; } else if (*pe == RBRACE) { if (i == 0) { break; } i--; } } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == EOS) { return glob0(patbuf, pglob, limitp); } for (i = 0, pl = pm = ptr; pm <= pe; pm++) { switch (*pm) { case LBRACKET: /* Ignore everything between [] */ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) ; if (*pm == EOS) { /* * We could not find a matching RBRACKET. * Ignore and just look for RBRACE */ pm = pl; } break; case LBRACE: i++; break; case RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case COMMA: if (i && *pm == COMMA) { break; } else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) ; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) ; /* Expand the current pattern */ rv = globexp1(patbuf, pglob, limitp, recursion + 1); if (rv && rv != GLOB_NOMATCH) { return rv; } /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } } return 0; }
int bsd_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const U8 *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN]; patnext = (U8 *) pattern; /* TODO: GLOB_APPEND / GLOB_DOOFFS aren't supported yet */ #if 0 if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } #else pglob->gl_pathc = 0; pglob->gl_pathv = NULL; pglob->gl_offs = 0; #endif pglob->gl_flags = flags & ~GLOB_MAGCHAR; pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; #ifdef DOSISH /* Nasty hack to treat patterns like "C:*" correctly. In this * case, the * should match any file in the current directory * on the C: drive. However, the glob code does not treat the * colon specially, so it looks for files beginning "C:" in * the current directory. To fix this, change the pattern to * add an explicit "./" at the start (just after the drive * letter and colon - ie change to "C:./"). */ if (isalpha(pattern[0]) && pattern[1] == ':' && pattern[2] != BG_SEP && pattern[2] != BG_SEP2 && bufend - bufnext > 4) { *bufnext++ = pattern[0]; *bufnext++ = ':'; *bufnext++ = '.'; *bufnext++ = BG_SEP; patnext += 2; } #endif if (flags & GLOB_QUOTE) { /* Protect the quoted characters. */ while (bufnext < bufend && (c = *patnext++) != BG_EOS) if (c == BG_QUOTE) { #ifdef DOSISH /* To avoid backslashitis on Win32, * we only treat \ as a quoting character * if it precedes one of the * metacharacters []-{}~\ */ if ((c = *patnext++) != '[' && c != ']' && c != '-' && c != '{' && c != '}' && c != '~' && c != '\\') { #else if ((c = *patnext++) == BG_EOS) { #endif c = BG_QUOTE; --patnext; } *bufnext++ = c | M_PROTECT; } else *bufnext++ = c; } else while (bufnext < bufend && (c = *patnext++) != BG_EOS) *bufnext++ = c; *bufnext = BG_EOS; if (flags & GLOB_BRACE) return globexp1(patbuf, pglob); else return glob0(patbuf, pglob); } /* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */ static int globexp1(const Char *pattern, glob_t *pglob) { const Char* ptr = pattern; int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == BG_LBRACE && pattern[1] == BG_RBRACE && pattern[2] == BG_EOS) return glob0(pattern, pglob); while ((ptr = (const Char *) g_strchr((Char *) ptr, BG_LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv)) return rv; return glob0(pattern, pglob); } /* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) { int i; Char *lm, *ls; const Char *pe, *pm, *pm1, *pl; Char patbuf[MAXPATHLEN]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) ; *lm = BG_EOS; ls = lm; /* Find the balanced brace */ for (i = 0, pe = ++ptr; *pe; pe++) if (*pe == BG_LBRACKET) { /* Ignore everything between [] */ for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++) ; if (*pe == BG_EOS) { /* * We could not find a matching BG_RBRACKET. * Ignore and just look for BG_RBRACE */ pe = pm; } } else if (*pe == BG_LBRACE) i++; else if (*pe == BG_RBRACE) { if (i == 0) break; i--; } /* Non matching braces; just glob the pattern */ if (i != 0 || *pe == BG_EOS) { *rv = glob0(patbuf, pglob); return 0; } for (i = 0, pl = pm = ptr; pm <= pe; pm++) { switch (*pm) { case BG_LBRACKET: /* Ignore everything between [] */ for (pm1 = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++) ; if (*pm == BG_EOS) { /* * We could not find a matching BG_RBRACKET. * Ignore and just look for BG_RBRACE */ pm = pm1; } break; case BG_LBRACE: i++; break; case BG_RBRACE: if (i) { i--; break; } /* FALLTHROUGH */ case BG_COMMA: if (i && *pm == BG_COMMA) break; else { /* Append the current string */ for (lm = ls; (pl < pm); *lm++ = *pl++) ; /* * Append the rest of the pattern after the * closing brace */ for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS; ) ; /* Expand the current pattern */ #ifdef GLOB_DEBUG qprintf("globexp2:", patbuf); #endif /* GLOB_DEBUG */ *rv = globexp1(patbuf, pglob); /* move after the comma, to the next string */ pl = pm + 1; } break; default: break; } } *rv = 0; return 0; }