📄 bsd_glob.c
字号:
; 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;}/* * expand tilde from the passwd file. */static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob){ char *h; const Char *p; Char *b, *eb; if (*pattern != BG_TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; h < (char*)eb && *p && *p != BG_SLASH; *h++ = (char)*p++) ; *h = BG_EOS;#if 0 if (h == (char *)eb) return what;#endif if (((char *) patbuf)[0] == BG_EOS) { /* * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ if ((h = getenv("HOME")) == NULL) {#ifdef HAS_PASSWD struct passwd *pwd; if ((pwd = getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir;#else return pattern;#endif } } else { /* * Expand a ~user */#ifdef HAS_PASSWD struct passwd *pwd; if ((pwd = getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir;#else return pattern;#endif } /* Copy the home directory */ for (b = patbuf; b < eb && *h; *b++ = *h++) ; /* Append the rest of the pattern */ while (b < eb && (*b++ = *p++) != BG_EOS) ; *b = BG_EOS; return patbuf;}/* * The main glob() routine: compiles the pattern (optionally processing * quotes), calls glob1() to do the real pattern matching, and finally * sorts the list (unless unsorted operation is requested). Returns 0 * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */static intglob0(const Char *pattern, glob_t *pglob){ const Char *qpat, *qpatnext; int c, err, oldflags, oldpathc; Char *bufnext, patbuf[MAXPATHLEN]; size_t limit = 0;#ifdef MACOS_TRADITIONAL if ( (*pattern == BG_TILDE) && (pglob->gl_flags & GLOB_TILDE) ) { return(globextend(pattern, pglob, &limit)); }#endif qpat = globtilde(pattern, patbuf, MAXPATHLEN, pglob); qpatnext = qpat; oldflags = pglob->gl_flags; oldpathc = pglob->gl_pathc; bufnext = patbuf; /* We don't need to check for buffer overflow any more. */ while ((c = *qpatnext++) != BG_EOS) { switch (c) { case BG_LBRACKET: c = *qpatnext; if (c == BG_NOT) ++qpatnext; if (*qpatnext == BG_EOS || g_strchr((Char *) qpatnext+1, BG_RBRACKET) == NULL) { *bufnext++ = BG_LBRACKET; if (c == BG_NOT) --qpatnext; break; } *bufnext++ = M_SET; if (c == BG_NOT) *bufnext++ = M_NOT; c = *qpatnext++; do { *bufnext++ = CHAR(c); if (*qpatnext == BG_RANGE && (c = qpatnext[1]) != BG_RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; } } while ((c = *qpatnext++) != BG_RBRACKET); pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_END; break; case BG_QUESTION: pglob->gl_flags |= GLOB_MAGCHAR; *bufnext++ = M_ONE; break; case BG_STAR: pglob->gl_flags |= GLOB_MAGCHAR; /* collapse adjacent stars to one, * to avoid exponential behavior */ if (bufnext == patbuf || bufnext[-1] != M_ALL) *bufnext++ = M_ALL; break; default: *bufnext++ = CHAR(c); break; } } *bufnext = BG_EOS;#ifdef GLOB_DEBUG qprintf("glob0:", patbuf);#endif /* GLOB_DEBUG */ if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) { pglob->gl_flags = oldflags; return(err); } /* * If there was no match we are going to append the pattern * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified * and the pattern did not contain any magic characters * GLOB_NOMAGIC is there just for compatibility with csh. */ if (pglob->gl_pathc == oldpathc && ((pglob->gl_flags & GLOB_NOCHECK) || ((pglob->gl_flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) {#ifdef GLOB_DEBUG printf("calling globextend from glob0\n");#endif /* GLOB_DEBUG */ pglob->gl_flags = oldflags; return(globextend(qpat, pglob, &limit)); } else if (!(pglob->gl_flags & GLOB_NOSORT)) qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), (pglob->gl_flags & (GLOB_ALPHASORT|GLOB_NOCASE)) ? ci_compare : compare); pglob->gl_flags = oldflags; return(0);}static intci_compare(const void *p, const void *q){ const char *pp = *(const char **)p; const char *qq = *(const char **)q; int ci; while (*pp && *qq) { if (toLOWER(*pp) != toLOWER(*qq)) break; ++pp; ++qq; } ci = toLOWER(*pp) - toLOWER(*qq); if (ci == 0) return compare(p, q); return ci;}static intcompare(const void *p, const void *q){ return(strcmp(*(char **)p, *(char **)q));}static intglob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp){ Char pathbuf[MAXPATHLEN]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == BG_EOS) return(0); return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, pathbuf, pathbuf+MAXPATHLEN-1, pattern, pattern_last, pglob, limitp));}/* * The functions glob2 and glob3 are mutually recursive; there is one level * of recursion for each segment in the pattern that contains one or more * meta characters. */static intglob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp){ Stat_t sb; Char *p, *q; int anymeta; /* * Loop over pattern segments until end of pattern or until * segment with meta character found. */ for (anymeta = 0;;) { if (*pattern == BG_EOS) { /* End of pattern? */ *pathend = BG_EOS; if (g_lstat(pathbuf, &sb, pglob)) return(0); if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != BG_SEP#ifdef DOSISH && pathend[-1] != BG_SEP2#endif ) && (S_ISDIR(sb.st_mode) || (S_ISLNK(sb.st_mode) && (g_stat(pathbuf, &sb, pglob) == 0) && S_ISDIR(sb.st_mode)))) {#ifdef MACOS_TRADITIONAL short err; err = glob_mark_Mac(pathbuf, pathend, pathend_last); if (err) return (err);#else if (pathend+1 > pathend_last) return (1); *pathend++ = BG_SEP; *pathend = BG_EOS;#endif } ++pglob->gl_matchc;#ifdef GLOB_DEBUG printf("calling globextend from glob2\n");#endif /* GLOB_DEBUG */ return(globextend(pathbuf, pglob, limitp)); } /* Find end of next segment, copy tentatively to pathend. */ q = pathend; p = pattern; while (*p != BG_EOS && *p != BG_SEP#ifdef DOSISH && *p != BG_SEP2#endif ) { if (ismeta(*p)) anymeta = 1; if (q+1 > pathend_last) return (1); *q++ = *p++; } if (!anymeta) { /* No expansion, do next segment. */ pathend = q; pattern = p; while (*pattern == BG_SEP#ifdef DOSISH || *pattern == BG_SEP2#endif ) { if (pathend+1 > pathend_last) return (1); *pathend++ = *pattern++; } } else /* Need expansion, recurse. */ return(glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, p, pattern_last, pglob, limitp)); } /* NOTREACHED */}static intglob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *pattern_last, Char *restpattern, Char *restpattern_last, glob_t *pglob, size_t *limitp){ register Direntry_t *dp; DIR *dirp; int err; int nocase; char buf[MAXPATHLEN]; /* * The readdirfunc declaration can't be prototyped, because it is * assigned, below, to two functions which are prototyped in glob.h * and dirent.h as taking pointers to differently typed opaque * structures. */ Direntry_t *(*readdirfunc)(DIR*); if (pathend > pathend_last) return (1); *pathend = BG_EOS; errno = 0;#ifdef VMS { Char *q = pathend; if (q - pathbuf > 5) { q -= 5; if (q[0] == '.' && tolower(q[1]) == 'd' && tolower(q[2]) == 'i' && tolower(q[3]) == 'r' && q[4] == '/') { q[0] = '/'; q[1] = BG_EOS; pathend = q+1; } } }#endif#ifdef MACOS_TRADITIONAL if ((!*pathbuf) && (g_matchVol)) { FSSpec spec; short index; StrFileName vol_name; /* unsigned char[64] on MacOS */ err = 0; nocase = ((pglob->gl_flags & GLOB_NOCASE) != 0); /* Get and match a list of volume names */ for (index = 0; !GetVolInfo(index+1, true, &spec); ++index) { register U8 *sc; register Char *dc; name_f_FSSpec(vol_name, &spec); /* Initial BG_DOT must be matched literally. */ if (*vol_name == BG_DOT && *pattern != BG_DOT) continue; dc = pathend; sc = (U8 *) vol_name; while (dc < pathend_last && (*dc++ = *sc++) != BG_EOS) ; if (dc >= pathend_last) { *dc = BG_EOS; err = 1; break; } if (!match(pathend, pattern, restpattern, nocase)) { *pathend = BG_EOS; continue; } err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, restpattern, restpattern_last, pglob, limitp); if (err) break; } return(err); } else { /* open dir */#endif /* MACOS_TRADITIONAL */ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { if (g_Ctoc(pathbuf, buf, sizeof(buf))) return (GLOB_ABEND); if (pglob->gl_errfunc(buf, errno) || (pglob->gl_flags & GLOB_ERR)) return (GLOB_ABEND); } return(0); } err = 0; nocase = ((pglob->gl_flags & GLOB_NOCASE) != 0); /* Search directory for matching names. */ if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = (Direntry_t *(*)(DIR *))pglob->gl_readdir; else readdirfunc = (Direntry_t *(*)(DIR *))my_readdir; while ((dp = (*readdirfunc)(dirp))) { register U8 *sc; register Char *dc; /* Initial BG_DOT must be matched literally. */ if (dp->d_name[0] == BG_DOT && *pattern != BG_DOT) continue; dc = pathend; sc = (U8 *) dp->d_name; while (dc < pathend_last && (*dc++ = *sc++) != BG_EOS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -