source: trunk/third/tcsh/glob.c @ 22036

Revision 22036, 18.6 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22035, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Guido van Rossum.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32#if defined(LIBC_SCCS) && !defined(lint)
33static char sccsid[] = "@(#)glob.c      5.12 (Berkeley) 6/24/91";
34#endif /* LIBC_SCCS and not lint */
35/*
36 * Glob: the interface is a superset of the one defined in POSIX 1003.2,
37 * draft 9.
38 *
39 * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
40 *
41 * Optional extra services, controlled by flags not defined by POSIX:
42 *
43 * GLOB_QUOTE:
44 *      Escaping convention: \ inhibits any special meaning the following
45 *      character might have (except \ at end of string is retained).
46 * GLOB_MAGCHAR:
47 *      Set in gl_flags if pattern contained a globbing character.
48 * GLOB_ALTNOT:
49 *      Use ^ instead of ! for "not".
50 * gl_matchc:
51 *      Number of matches in the current invocation of glob.
52 */
53
54#ifdef WINNT_NATIVE
55        #pragma warning(disable:4244)
56#endif /* WINNT_NATIVE */
57
58#define Char __Char
59#include "sh.h"
60#include "glob.h"
61
62#undef Char
63#undef QUOTE
64#undef TILDE
65#undef META
66#undef CHAR
67#undef ismeta
68#undef Strchr
69
70#ifndef S_ISDIR
71#define S_ISDIR(a)      (((a) & S_IFMT) == S_IFDIR)
72#endif
73
74#if !defined(S_ISLNK) && defined(S_IFLNK)
75#define S_ISLNK(a)      (((a) & S_IFMT) == S_IFLNK)
76#endif
77
78#if !defined(S_ISLNK) && !defined(lstat)
79#define lstat stat
80#endif
81
82typedef unsigned short Char;
83
84static  int      glob1          __P((Char *, glob_t *, int));
85static  int      glob2          __P((Char *, Char *, Char *, glob_t *, int));
86static  int      glob3          __P((Char *, Char *, Char *, Char *,
87                                     glob_t *, int));
88static  int      globextend     __P((Char *, glob_t *));
89static  int      match          __P((Char *, Char *, Char *, int));
90#ifndef __clipper__
91static  int      compare        __P((const ptr_t, const ptr_t));
92#endif
93static  DIR     *Opendir        __P((Char *));
94#ifdef S_IFLNK
95static  int      Lstat          __P((Char *, struct stat *));
96#endif
97static  int      Stat           __P((Char *, struct stat *sb));
98static  Char    *Strchr         __P((Char *, int));
99#ifdef DEBUG
100static  void     qprintf        __P((Char *));
101#endif
102
103#define DOLLAR          '$'
104#define DOT             '.'
105#define EOS             '\0'
106#define LBRACKET        '['
107#define NOT             '!'
108#define ALTNOT          '^'
109#define QUESTION        '?'
110#define QUOTE           '\\'
111#define RANGE           '-'
112#define RBRACKET        ']'
113#define SEP             '/'
114#define STAR            '*'
115#define TILDE           '~'
116#define UNDERSCORE      '_'
117
118#define M_META          0x8000
119#define M_PROTECT       0x4000
120#define M_MASK          0xffff
121#define M_ASCII         0x00ff
122
123#define CHAR(c)         ((c)&M_ASCII)
124#define META(c)         ((c)|M_META)
125#define M_ALL           META('*')
126#define M_END           META(']')
127#define M_NOT           META('!')
128#define M_ALTNOT        META('^')
129#define M_ONE           META('?')
130#define M_RNG           META('-')
131#define M_SET           META('[')
132#define ismeta(c)       (((c)&M_META) != 0)
133
134#ifndef BUFSIZE
135#define GLOBBUFLEN      MAXPATHLEN
136#else
137#define GLOBBUFLEN      BUFSIZE
138#endif
139
140int
141globcharcoll(c1, c2, cs)
142    NLSChar c1, c2;
143    int cs;
144{
145#if defined(NLS) && defined(LC_COLLATE) && !defined(NOSTRCOLL)
146# if defined(SHORT_STRINGS)
147    wchar_t s1[2], s2[2];
148
149    if (c1 == c2)
150        return (0);
151    if (cs) {
152        c1 = towlower(c1);
153        c2 = towlower(c2);
154    } else {
155        /* This should not be here, but I'll rather leave it in than engage in
156           a LC_COLLATE flamewar about a shell I don't use... */
157        if (iswlower(c1) && iswupper(c2))
158            return (1);
159        if (iswupper(c1) && iswlower(c2))
160            return (-1);
161    }
162    s1[0] = c1;
163    s2[0] = c2;
164    s1[1] = s2[1] = '\0';
165    return wcscoll(s1, s2);
166# else /* not SHORT_STRINGS */
167    char s1[2], s2[2];
168
169    if (c1 == c2)
170        return (0);
171    /*
172     * From kevin lyda <kevin@suberic.net>:
173     * strcoll does not guarantee case sorting, so we pre-process now:
174     */
175    if (cs) {
176        c1 = islower(c1) ? c1 : tolower(c1);
177        c2 = islower(c2) ? c2 : tolower(c2);
178    } else {
179        if (islower(c1) && isupper(c2))
180            return (1);
181        if (isupper(c1) && islower(c2))
182            return (-1);
183    }
184    s1[0] = c1;
185    s2[0] = c2;
186    s1[1] = s2[1] = '\0';
187    return strcoll(s1, s2);
188# endif
189#else
190    return (c1 - c2);
191#endif
192}
193
194/*
195 * Need to dodge two kernel bugs:
196 * opendir("") != opendir(".")
197 * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels.
198 *            POSIX specifies that they should be ignored in directories.
199 */
200
201static DIR *
202Opendir(str)
203    Char *str;
204{
205    char    buf[GLOBBUFLEN];
206    char *dc = buf;
207#if defined(hpux) || defined(__hpux)
208    struct stat st;
209#endif
210
211    if (!*str)
212        return (opendir("."));
213    while ((*dc++ = *str++) != '\0')
214        continue;
215#if defined(hpux) || defined(__hpux)
216    /*
217     * Opendir on some device files hangs, so avoid it
218     */
219    if (stat(buf, &st) == -1 || !S_ISDIR(st.st_mode))
220        return NULL;
221#endif
222    return (opendir(buf));
223}
224
225#ifdef S_IFLNK
226static int
227Lstat(fn, sb)
228    Char *fn;
229    struct stat *sb;
230{
231    char    buf[GLOBBUFLEN];
232    char *dc = buf;
233
234    while ((*dc++ = *fn++) != '\0')
235        continue;
236# ifdef NAMEI_BUG
237    {
238        int     st;
239
240        st = lstat(buf, sb);
241        if (*buf)
242            dc--;
243        return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
244    }
245# else
246    return (lstat(buf, sb));
247# endif /* NAMEI_BUG */
248}
249#else
250#define Lstat Stat
251#endif /* S_IFLNK */
252
253static int
254Stat(fn, sb)
255    Char *fn;
256    struct stat *sb;
257{
258    char    buf[GLOBBUFLEN];
259    char *dc = buf;
260
261    while ((*dc++ = *fn++) != '\0')
262        continue;
263#ifdef NAMEI_BUG
264    {
265        int     st;
266
267        st = stat(buf, sb);
268        if (*buf)
269            dc--;
270        return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
271    }
272#else
273    return (stat(buf, sb));
274#endif /* NAMEI_BUG */
275}
276
277static Char *
278Strchr(str, ch)
279    Char *str;
280    int ch;
281{
282    do
283        if (*str == ch)
284            return (str);
285    while (*str++);
286    return (NULL);
287}
288
289#ifdef DEBUG
290static void
291qprintf(s)
292Char *s;
293{
294    Char *p;
295
296    for (p = s; *p; p++)
297        printf("%c", *p & 0xff);
298    printf("\n");
299    for (p = s; *p; p++)
300        printf("%c", *p & M_PROTECT ? '"' : ' ');
301    printf("\n");
302    for (p = s; *p; p++)
303        printf("%c", *p & M_META ? '_' : ' ');
304    printf("\n");
305}
306#endif /* DEBUG */
307
308static int
309compare(p, q)
310    const ptr_t  p, q;
311{
312#if defined(NLS) && !defined(NOSTRCOLL)
313    errno = 0;  /* strcoll sets errno, another brain-damage */
314 
315    return (strcoll(*(char **) p, *(char **) q));
316#else
317    return (strcmp(*(char **) p, *(char **) q));
318#endif /* NLS && !NOSTRCOLL */
319}
320
321/*
322 * The main glob() routine: compiles the pattern (optionally processing
323 * quotes), calls glob1() to do the real pattern matching, and finally
324 * sorts the list (unless unsorted operation is requested).  Returns 0
325 * if things went well, nonzero if errors occurred.  It is not an error
326 * to find no matches.
327 */
328int
329glob(pattern, flags, errfunc, pglob)
330    const char *pattern;
331    int     flags;
332    int     (*errfunc) __P((const char *, int));
333    glob_t *pglob;
334{
335    int     err, oldpathc;
336    Char *bufnext, *bufend, *compilebuf, m_not;
337    const unsigned char *compilepat, *patnext;
338    int     c, not;
339    Char *qpatnext;
340#ifdef WIDE_STRINGS
341    Char patbuf[GLOBBUFLEN + MB_LEN_MAX + 1];
342#else
343    Char patbuf[GLOBBUFLEN + 1];
344#endif
345    int     no_match;
346
347    patnext = (const unsigned char *) pattern;
348    if (!(flags & GLOB_APPEND)) {
349        pglob->gl_pathc = 0;
350        pglob->gl_pathv = NULL;
351        if (!(flags & GLOB_DOOFFS))
352            pglob->gl_offs = 0;
353    }
354    pglob->gl_flags = flags & ~GLOB_MAGCHAR;
355    pglob->gl_errfunc = errfunc;
356    oldpathc = pglob->gl_pathc;
357    pglob->gl_matchc = 0;
358
359    if (pglob->gl_flags & GLOB_ALTNOT) {
360        not = ALTNOT;
361        m_not = M_ALTNOT;
362    }
363    else {
364        not = NOT;
365        m_not = M_NOT;
366    }
367
368    bufnext = patbuf;
369    bufend = bufnext + GLOBBUFLEN;
370    compilebuf = bufnext;
371    compilepat = patnext;
372
373    no_match = *patnext == not;
374    if (no_match)
375        patnext++;
376
377    if (flags & GLOB_QUOTE) {
378        /* Protect the quoted characters */
379        while (bufnext < bufend && (c = *patnext++) != EOS) {
380#ifdef WIDE_STRINGS
381            int len;
382           
383            len = mblen((const char *)(patnext - 1), MB_LEN_MAX);
384            if (len == -1)
385                mblen(NULL, 0);
386            if (len > 1) {
387                *bufnext++ = (Char) c;
388                while (--len != 0)
389                    *bufnext++ = (Char) (*patnext++ | M_PROTECT);
390            } else
391#endif /* WIDE_STRINGS */
392            if (c == QUOTE) {
393                if ((c = *patnext++) == EOS) {
394                    c = QUOTE;
395                    --patnext;
396                }
397                *bufnext++ = (Char) (c | M_PROTECT);
398            }
399            else
400                *bufnext++ = (Char) c;
401        }
402    }
403    else
404        while (bufnext < bufend && (c = *patnext++) != EOS)
405            *bufnext++ = (Char) c;
406    *bufnext = EOS;
407
408    bufnext = patbuf;
409    qpatnext = patbuf;
410    /* we don't need to check for buffer overflow any more */
411    while ((c = *qpatnext++) != EOS) {
412        switch (c) {
413        case LBRACKET:
414            c = *qpatnext;
415            if (c == not)
416                ++qpatnext;
417            if (*qpatnext == EOS ||
418                Strchr(qpatnext + 1, RBRACKET) == NULL) {
419                *bufnext++ = LBRACKET;
420                if (c == not)
421                    --qpatnext;
422                break;
423            }
424            pglob->gl_flags |= GLOB_MAGCHAR;
425            *bufnext++ = M_SET;
426            if (c == not)
427                *bufnext++ = m_not;
428            c = *qpatnext++;
429            do {
430                *bufnext++ = CHAR(c);
431                if (*qpatnext == RANGE &&
432                    (c = qpatnext[1]) != RBRACKET) {
433                    *bufnext++ = M_RNG;
434                    *bufnext++ = CHAR(c);
435                    qpatnext += 2;
436                }
437            } while ((c = *qpatnext++) != RBRACKET);
438            *bufnext++ = M_END;
439            break;
440        case QUESTION:
441            pglob->gl_flags |= GLOB_MAGCHAR;
442            *bufnext++ = M_ONE;
443            break;
444        case STAR:
445            pglob->gl_flags |= GLOB_MAGCHAR;
446            /* collapse adjacent stars to one, to avoid
447             * exponential behavior
448             */
449            if (bufnext == patbuf || bufnext[-1] != M_ALL)
450                *bufnext++ = M_ALL;
451            break;
452        default:
453            *bufnext++ = CHAR(c);
454            break;
455        }
456    }
457    *bufnext = EOS;
458#ifdef DEBUG
459    qprintf(patbuf);
460#endif
461
462    if ((err = glob1(patbuf, pglob, no_match)) != 0)
463        return (err);
464
465    /*
466     * If there was no match we are going to append the pattern
467     * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
468     * and the pattern did not contain any magic characters
469     * GLOB_NOMAGIC is there just for compatibility with csh.
470     */
471    if (pglob->gl_pathc == oldpathc &&
472        ((flags & GLOB_NOCHECK) ||
473         ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) {
474        if (!(flags & GLOB_QUOTE)) {
475            Char *dp = compilebuf;
476            const unsigned char *sp = compilepat;
477
478            while ((*dp++ = *sp++) != '\0')
479                continue;
480        }
481        else {
482            /*
483             * copy pattern, interpreting quotes; this is slightly different
484             * than the interpretation of quotes above -- which should prevail?
485             */
486            while (*compilepat != EOS) {
487                if (*compilepat == QUOTE) {
488                    if (*++compilepat == EOS)
489                        --compilepat;
490                }
491                *compilebuf++ = (unsigned char) *compilepat++;
492            }
493            *compilebuf = EOS;
494        }
495        return (globextend(patbuf, pglob));
496    }
497    else if (!(flags & GLOB_NOSORT) && (pglob->gl_pathc != oldpathc))
498        qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc),
499              pglob->gl_pathc - oldpathc, sizeof(char *),
500              (int (*) __P((const void *, const void *))) compare);
501    return (0);
502}
503
504static int
505glob1(pattern, pglob, no_match)
506    Char *pattern;
507    glob_t *pglob;
508    int     no_match;
509{
510    Char pathbuf[GLOBBUFLEN + 1];
511
512    /*
513     * a null pathname is invalid -- POSIX 1003.1 sect. 2.4.
514     */
515    if (*pattern == EOS)
516        return (0);
517    return (glob2(pathbuf, pathbuf, pattern, pglob, no_match));
518}
519
520/*
521 * functions glob2 and glob3 are mutually recursive; there is one level
522 * of recursion for each segment in the pattern that contains one or
523 * more meta characters.
524 */
525static int
526glob2(pathbuf, pathend, pattern, pglob, no_match)
527    Char *pathbuf, *pathend, *pattern;
528    glob_t *pglob;
529    int     no_match;
530{
531    struct stat sbuf;
532    int anymeta;
533    Char *p, *q;
534
535    /*
536     * loop over pattern segments until end of pattern or until segment with
537     * meta character found.
538     */
539    anymeta = 0;
540    for (;;) {
541        if (*pattern == EOS) {  /* end of pattern? */
542            *pathend = EOS;
543
544            if (Lstat(pathbuf, &sbuf))
545                return (0);
546
547            if (((pglob->gl_flags & GLOB_MARK) &&
548                 pathend[-1] != SEP) &&
549                (S_ISDIR(sbuf.st_mode)
550#ifdef S_IFLNK
551                 || (S_ISLNK(sbuf.st_mode) &&
552                     (Stat(pathbuf, &sbuf) == 0) &&
553                     S_ISDIR(sbuf.st_mode))
554#endif
555                 )) {
556                *pathend++ = SEP;
557                *pathend = EOS;
558            }
559            ++pglob->gl_matchc;
560            return (globextend(pathbuf, pglob));
561        }
562
563        /* find end of next segment, copy tentatively to pathend */
564        q = pathend;
565        p = pattern;
566        while (*p != EOS && *p != SEP) {
567            if (ismeta(*p))
568                anymeta = 1;
569            *q++ = *p++;
570        }
571
572        if (!anymeta) {         /* no expansion, do next segment */
573            pathend = q;
574            pattern = p;
575            while (*pattern == SEP)
576                *pathend++ = *pattern++;
577        }
578        else                    /* need expansion, recurse */
579            return (glob3(pathbuf, pathend, pattern, p, pglob, no_match));
580    }
581    /* NOTREACHED */
582}
583
584
585static int
586glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match)
587    Char *pathbuf, *pathend, *pattern, *restpattern;
588    glob_t *pglob;
589    int     no_match;
590{
591    DIR    *dirp;
592    struct dirent *dp;
593    int     err;
594    Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT;
595    char cpathbuf[GLOBBUFLEN], *ptr;;
596
597    *pathend = EOS;
598    errno = 0;
599
600    if (!(dirp = Opendir(pathbuf))) {
601        /* todo: don't call for ENOENT or ENOTDIR? */
602        for (ptr = cpathbuf; (*ptr++ = (char) *pathbuf++) != EOS;)
603            continue;
604        if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (cpathbuf, errno)) ||
605            (pglob->gl_flags & GLOB_ERR))
606            return (GLOB_ABEND);
607        else
608            return (0);
609    }
610
611    err = 0;
612
613    /* search directory for matching names */
614    while ((dp = readdir(dirp)) != NULL) {
615        unsigned char *sc;
616        Char *dc;
617
618        /* initial DOT must be matched literally */
619        if (dp->d_name[0] == DOT && *pattern != DOT)
620            continue;
621        for (sc = (unsigned char *) dp->d_name, dc = pathend;
622             (*dc++ = *sc++) != '\0';)
623            continue;
624        if (match(pathend, pattern, restpattern, (int) m_not) == no_match) {
625            *pathend = EOS;
626            continue;
627        }
628        err = glob2(pathbuf, --dc, restpattern, pglob, no_match);
629        if (err)
630            break;
631    }
632    /* todo: check error from readdir? */
633    (void) closedir(dirp);
634    return (err);
635}
636
637
638/*
639 * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
640 * add the new item, and update gl_pathc.
641 *
642 * This assumes the BSD realloc, which only copies the block when its size
643 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
644 * behavior.
645 *
646 * Return 0 if new item added, error code if memory couldn't be allocated.
647 *
648 * Invariant of the glob_t structure:
649 *      Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
650 *       gl_pathv points to (gl_offs + gl_pathc + 1) items.
651 */
652static int
653globextend(path, pglob)
654    Char *path;
655    glob_t *pglob;
656{
657    char **pathv;
658    int i;
659    unsigned int newsize;
660    char   *copy;
661    Char *p;
662
663    newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
664    pathv = (char **) (pglob->gl_pathv ?
665                       xrealloc((ptr_t) pglob->gl_pathv, (size_t) newsize) :
666                       xmalloc((size_t) newsize));
667    if (pathv == NULL)
668        return (GLOB_NOSPACE);
669
670    if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
671        /* first time around -- clear initial gl_offs items */
672        pathv += pglob->gl_offs;
673        for (i = pglob->gl_offs; --i >= 0;)
674            *--pathv = NULL;
675    }
676    pglob->gl_pathv = pathv;
677
678    for (p = path; *p++;)
679        continue;
680    if ((copy = (char *) xmalloc((size_t) (p - path))) != NULL) {
681        char *dc = copy;
682        Char *sc = path;
683
684        while ((*dc++ = *sc++) != '\0')
685            continue;
686        pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
687    }
688    pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
689    return ((copy == NULL) ? GLOB_NOSPACE : 0);
690}
691
692
693static size_t
694One_mbtowc(NLSChar *pwc, const Char *s, size_t n)
695{
696#ifdef WIDE_STRINGS
697    char buf[MB_LEN_MAX], *p;
698
699    if (n > MB_LEN_MAX)
700        n = MB_LEN_MAX;
701    p = buf;
702    while (p < buf + n && (*p++ = CHAR(*s++)) != 0)
703        ;
704    return one_mbtowc(pwc, buf, n);
705#else
706    return NLSFrom(s, n, pwc);
707#endif
708}
709
710/*
711 * pattern matching function for filenames.  Each occurrence of the *
712 * pattern causes a recursion level.
713 */
714static  int
715match(name, pat, patend, m_not)
716    Char *name, *pat, *patend;
717    int m_not;
718{
719    int ok, negate_range;
720    Char c, k;
721
722    while (pat < patend) {
723        size_t lwk;
724        NLSChar wc, wk;
725
726        USE(k);
727        c = *pat; /* Only for M_MASK bits */
728        pat += One_mbtowc(&wc, pat, MB_LEN_MAX);
729        lwk = One_mbtowc(&wk, name, MB_LEN_MAX);
730        switch (c & M_MASK) {
731        case M_ALL:
732            if (pat == patend)
733                return (1);
734            for (;;) {
735                if (match(name, pat, patend, m_not))
736                    return (1);
737                if (*name == EOS)
738                    break;
739                name += lwk;
740                lwk = One_mbtowc(&wk, name, MB_LEN_MAX);
741            }
742            return (0);
743        case M_ONE:
744            if (*name == EOS)
745                return (0);
746            name += lwk;
747            break;
748        case M_SET:
749            ok = 0;
750            if (*name == EOS)
751                return (0);
752            name += lwk;
753            if ((negate_range = ((*pat & M_MASK) == m_not)) != 0)
754                ++pat;
755            while ((*pat & M_MASK) != M_END) {
756                pat += One_mbtowc(&wc, pat, MB_LEN_MAX);
757                if ((*pat & M_MASK) == M_RNG) {
758                    NLSChar wc2;
759                   
760                    pat++;
761                    pat += One_mbtowc(&wc2, pat, MB_LEN_MAX);
762                    if (globcharcoll(wc, wk, 0) <= 0 &&
763                        globcharcoll(wk, wc2, 0) <= 0)
764                        ok = 1;
765                } else if (wc == wk)
766                    ok = 1;
767            }
768            pat += One_mbtowc(&wc, pat, MB_LEN_MAX);
769            if (ok == negate_range)
770                return (0);
771            break;
772        default:
773            name += lwk;
774            if (samecase(wk) != samecase(wc))
775                return (0);
776            break;
777        }
778    }
779    return (*name == EOS);
780}
781
782/* free allocated data belonging to a glob_t structure */
783void
784globfree(pglob)
785    glob_t *pglob;
786{
787    int i;
788    char **pp;
789
790    if (pglob->gl_pathv != NULL) {
791        pp = pglob->gl_pathv + pglob->gl_offs;
792        for (i = pglob->gl_pathc; i--; ++pp)
793            if (*pp)
794                xfree((ptr_t) *pp), *pp = NULL;
795        xfree((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL;
796    }
797}
Note: See TracBrowser for help on using the repository browser.