int Gnmatch(const Char *string, const Char *pattern, const Char **endstr) { Char ***fblk, **p; const Char *tstring = string; int gpol = 1, gres = 0; if (*pattern == '^') { gpol = 0; pattern++; } fblk = xmalloc(sizeof(Char ***)); *fblk = xmalloc(GLOBSPACE * sizeof(Char *)); (*fblk)[0] = Strsave(pattern); (*fblk)[1] = NULL; cleanup_push(fblk, blk_indirect_cleanup); expbrace(fblk, NULL, GLOBSPACE); if (endstr == NULL) /* Exact matches only */ for (p = *fblk; *p; p++) gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0; else { const Char *end; /* partial matches */ end = Strend(string); for (p = *fblk; *p; p++) if (t_pmatch(string, *p, &tstring, 1) != 0) { gres |= 1; if (end > tstring) end = tstring; } *endstr = end; } cleanup_until(fblk); return(gres == gpol); }
/*ARGSUSED*/ void dolist(Char **v, struct command *c) { Char **globbed; int i, k, ret = 0; struct stat st; USE(c); if (*++v == NULL) { struct Strbuf word = Strbuf_INIT; Strbuf_terminate(&word); cleanup_push(&word, Strbuf_cleanup); (void) t_search(&word, LIST, TW_ZERO, 0, STRNULL, 0); cleanup_until(&word); return; } v = glob_all_or_error(v); globbed = v; cleanup_push(globbed, blk_cleanup); for (k = 0; v[k] != NULL && v[k][0] != '-'; k++) continue; if (v[k]) { /* * We cannot process a flag therefore we let ls do it right. */ Char *lspath; struct command *t; struct wordent cmd, *nextword, *lastword; Char *cp; struct varent *vp; if (setintr) { pintr_disabled++; cleanup_push(&pintr_disabled, disabled_cleanup); } if (seterr) { xfree(seterr); seterr = NULL; } lspath = STRls; STRmCF[1] = 'C'; STRmCF[3] = '\0'; /* Look at listflags, to add -A to the flags, to get a path of ls if necessary */ if ((vp = adrof(STRlistflags)) != NULL && vp->vec != NULL && vp->vec[0] != STRNULL) { if (vp->vec[1] != NULL && vp->vec[1][0] != '\0') lspath = vp->vec[1]; for (cp = vp->vec[0]; *cp; cp++) switch (*cp) { case 'x': STRmCF[1] = 'x'; break; case 'a': STRmCF[3] = 'a'; break; case 'A': STRmCF[3] = 'A'; break; default: break; } } cmd.word = STRNULL; lastword = &cmd; nextword = xcalloc(1, sizeof cmd); nextword->word = Strsave(lspath); lastword->next = nextword; nextword->prev = lastword; lastword = nextword; nextword = xcalloc(1, sizeof cmd); nextword->word = Strsave(STRmCF); lastword->next = nextword; nextword->prev = lastword; #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) if (dspmbyte_ls) { lastword = nextword; nextword = xcalloc(1, sizeof cmd); nextword->word = Strsave(STRmmliteral); lastword->next = nextword; nextword->prev = lastword; } #endif #ifdef COLOR_LS_F if (color_context_ls) { lastword = nextword; nextword = xcalloc(1, sizeof cmd); nextword->word = Strsave(STRmmcolormauto); lastword->next = nextword; nextword->prev = lastword; } #endif /* COLOR_LS_F */ lastword = nextword; for (cp = *v; cp; cp = *++v) { nextword = xcalloc(1, sizeof cmd); nextword->word = quote(Strsave(cp)); lastword->next = nextword; nextword->prev = lastword; lastword = nextword; } lastword->next = &cmd; cmd.prev = lastword; cleanup_push(&cmd, lex_cleanup); /* build a syntax tree for the command. */ t = syntax(cmd.next, &cmd, 0); cleanup_push(t, syntax_cleanup); if (seterr) stderror(ERR_OLD); /* expand aliases like process() does */ /* alias(&cmd); */ /* execute the parse tree. */ execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL, FALSE); /* done. free the lex list and parse tree. */ cleanup_until(&cmd); if (setintr) cleanup_until(&pintr_disabled); } else { Char *dp, *tmp; struct Strbuf buf = Strbuf_INIT; cleanup_push(&buf, Strbuf_cleanup); for (k = 0, i = 0; v[k] != NULL; k++) { tmp = dnormalize(v[k], symlinks == SYM_IGNORE); cleanup_push(tmp, xfree); dp = Strend(tmp) - 1; if (*dp == '/' && dp != tmp) #ifdef apollo if (dp != &tmp[1]) #endif /* apollo */ *dp = '\0'; if (stat(short2str(tmp), &st) == -1) { int err; err = errno; if (k != i) { if (i != 0) xputchar('\n'); print_by_column(STRNULL, &v[i], k - i, FALSE); } haderr = 1; xprintf("%S: %s.\n", tmp, strerror(err)); haderr = 0; i = k + 1; ret = 1; } else if (S_ISDIR(st.st_mode)) { Char *cp; if (k != i) { if (i != 0) xputchar('\n'); print_by_column(STRNULL, &v[i], k - i, FALSE); } if (k != 0 && v[1] != NULL) xputchar('\n'); xprintf("%S:\n", tmp); buf.len = 0; for (cp = tmp; *cp; cp++) Strbuf_append1(&buf, (*cp | QUOTE)); Strbuf_terminate(&buf); dp = &buf.s[buf.len - 1]; if ( #ifdef WINNT_NATIVE (*dp != (Char) (':' | QUOTE)) && #endif /* WINNT_NATIVE */ (*dp != (Char) ('/' | QUOTE))) { Strbuf_append1(&buf, '/'); Strbuf_terminate(&buf); } else *dp &= TRIM; (void) t_search(&buf, LIST, TW_ZERO, 0, STRNULL, 0); i = k + 1; } cleanup_until(tmp); } cleanup_until(&buf); if (k != i) { if (i != 0) xputchar('\n'); print_by_column(STRNULL, &v[i], k - i, FALSE); } if (ret) stderror(ERR_SILENT); } cleanup_until(globbed); }
/* t_pmatch(): * Return 2 on exact match, * Return 1 on substring match. * Return 0 on no match. * *estr will point to the end of the longest exact or substring match. */ int t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs) { Char stringc, patternc, rangec; int match, negate_range; const Char *pestr, *nstring; for (nstring = string;; string = nstring) { stringc = *nstring++ & TRIM; patternc = *pattern++ & TRIM; switch (patternc) { case '\0': *estr = string; return (stringc == '\0' ? 2 : 1); case '?': if (stringc == 0) return (0); break; case '*': if (!*pattern) { *estr = Strend(string); return (2); } pestr = NULL; for (;;) { switch(t_pmatch(string, pattern, estr, cs)) { case 0: break; case 1: pestr = *estr;/*FIXME: does not guarantee longest match */ break; case 2: return 2; default: abort(); /* Cannot happen */ } stringc = *string++ & TRIM; if (!stringc) break; } if (pestr) { *estr = pestr; return 1; } else return 0; case '[': match = 0; if ((negate_range = (*pattern == '^')) != 0) pattern++; while ((rangec = *pattern++ & TRIM) != '\0') { if (rangec == ']') break; if (match) continue; if (*pattern == '-' && pattern[1] != ']') { Char rangec2; pattern++; rangec2 = *pattern++ & TRIM; match = (globcharcoll(stringc, rangec2, 0) <= 0 && globcharcoll(rangec, stringc, 0) <= 0); } else match = (stringc == rangec); } if (rangec == '\0') stderror(ERR_NAME | ERR_MISSING, ']'); if ((!match) && (stringc == '\0')) return (0); if (match == negate_range) return (0); break; default: if (cs ? patternc != stringc : Tolower(patternc) != Tolower(stringc)) return (0); break; } } }