integrate mainline changes
[p5sagit/p5-mst-13.2.git] / ext / File / Glob / bsd_glob.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  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
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static char sccsid[] = "@(#)glob.c      8.3 (Berkeley) 10/13/93";
35 #endif /* LIBC_SCCS and not lint */
36
37 /*
38  * glob(3) -- a superset of the one defined in POSIX 1003.2.
39  *
40  * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
41  *
42  * Optional extra services, controlled by flags not defined by POSIX:
43  *
44  * GLOB_QUOTE:
45  *      Escaping convention: \ inhibits any special meaning the following
46  *      character might have (except \ at end of string is retained).
47  * GLOB_MAGCHAR:
48  *      Set in gl_flags if pattern contained a globbing character.
49  * GLOB_NOMAGIC:
50  *      Same as GLOB_NOCHECK, but it will only append pattern if it did
51  *      not contain any magic characters.  [Used in csh style globbing]
52  * GLOB_ALTDIRFUNC:
53  *      Use alternately specified directory access functions.
54  * GLOB_TILDE:
55  *      expand ~user/foo to the /home/dir/of/user/foo
56  * GLOB_BRACE:
57  *      expand {1,2}{a,b} to 1a 1b 2a 2b
58  * gl_matchc:
59  *      Number of matches in the current invocation of glob.
60  */
61
62 #include <EXTERN.h>
63 #include <perl.h>
64 #include <XSUB.h>
65
66 #include "bsd_glob.h"
67 #ifdef I_PWD
68 #       include <pwd.h>
69 #else
70 #ifdef HAS_PASSWD
71         struct passwd *getpwnam(char *);
72         struct passwd *getpwuid(Uid_t);
73 #endif
74 #endif
75
76 #ifndef MAXPATHLEN
77 #  ifdef PATH_MAX
78 #    define     MAXPATHLEN      PATH_MAX
79 #  else
80 #    define     MAXPATHLEN      1024
81 #  endif
82 #endif
83
84 #define BG_DOLLAR       '$'
85 #define BG_DOT          '.'
86 #define BG_EOS          '\0'
87 #define BG_LBRACKET     '['
88 #define BG_NOT          '!'
89 #define BG_QUESTION     '?'
90 #define BG_QUOTE        '\\'
91 #define BG_RANGE        '-'
92 #define BG_RBRACKET     ']'
93 #define BG_SEP          '/'
94 #ifdef DOSISH
95 #define BG_SEP2         '\\'
96 #endif
97 #define BG_STAR         '*'
98 #define BG_TILDE        '~'
99 #define BG_UNDERSCORE   '_'
100 #define BG_LBRACE       '{'
101 #define BG_RBRACE       '}'
102 #define BG_SLASH        '/'
103 #define BG_COMMA        ','
104
105 #ifndef GLOB_DEBUG
106
107 #define M_QUOTE         0x8000
108 #define M_PROTECT       0x4000
109 #define M_MASK          0xffff
110 #define M_ASCII         0x00ff
111
112 typedef U16 Char;
113
114 #else
115
116 #define M_QUOTE         0x80
117 #define M_PROTECT       0x40
118 #define M_MASK          0xff
119 #define M_ASCII         0x7f
120
121 typedef U8 Char;
122
123 #endif /* !GLOB_DEBUG */
124
125
126 #define CHAR(c)         ((Char)((c)&M_ASCII))
127 #define META(c)         ((Char)((c)|M_QUOTE))
128 #define M_ALL           META('*')
129 #define M_END           META(']')
130 #define M_NOT           META('!')
131 #define M_ONE           META('?')
132 #define M_RNG           META('-')
133 #define M_SET           META('[')
134 #define ismeta(c)       (((c)&M_QUOTE) != 0)
135
136
137 static int       compare(const void *, const void *);
138 static int       ci_compare(const void *, const void *);
139 static void      g_Ctoc(const Char *, char *);
140 static int       g_lstat(Char *, Stat_t *, glob_t *);
141 static DIR      *g_opendir(Char *, glob_t *);
142 static Char     *g_strchr(Char *, int);
143 #ifdef notdef
144 static Char     *g_strcat(Char *, const Char *);
145 #endif
146 static int       g_stat(Char *, Stat_t *, glob_t *);
147 static int       glob0(const Char *, glob_t *);
148 static int       glob1(Char *, glob_t *);
149 static int       glob2(Char *, Char *, Char *, glob_t *);
150 static int       glob3(Char *, Char *, Char *, Char *, glob_t *);
151 static int       globextend(const Char *, glob_t *);
152 static const Char *      globtilde(const Char *, Char *, glob_t *);
153 static int       globexp1(const Char *, glob_t *);
154 static int       globexp2(const Char *, const Char *, glob_t *, int *);
155 static int       match(Char *, Char *, Char *, int);
156 #ifdef GLOB_DEBUG
157 static void      qprintf(const char *, Char *);
158 #endif /* GLOB_DEBUG */
159
160 #ifdef PERL_IMPLICIT_CONTEXT
161 static Direntry_t *     my_readdir(DIR*);
162
163 static Direntry_t *
164 my_readdir(DIR *d)
165 {
166     return PerlDir_read(d);
167 }
168 #else
169 #define my_readdir      readdir
170 #endif
171
172 int
173 bsd_glob(const char *pattern, int flags,
174          int (*errfunc)(const char *, int), glob_t *pglob)
175 {
176         const U8 *patnext;
177         int c;
178         Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
179
180         patnext = (U8 *) pattern;
181         if (!(flags & GLOB_APPEND)) {
182                 pglob->gl_pathc = 0;
183                 pglob->gl_pathv = NULL;
184                 if (!(flags & GLOB_DOOFFS))
185                         pglob->gl_offs = 0;
186         }
187         pglob->gl_flags = flags & ~GLOB_MAGCHAR;
188         pglob->gl_errfunc = errfunc;
189         pglob->gl_matchc = 0;
190
191         bufnext = patbuf;
192         bufend = bufnext + MAXPATHLEN;
193 #ifdef DOSISH
194         /* Nasty hack to treat patterns like "C:*" correctly. In this
195          * case, the * should match any file in the current directory
196          * on the C: drive. However, the glob code does not treat the
197          * colon specially, so it looks for files beginning "C:" in
198          * the current directory. To fix this, change the pattern to
199          * add an explicit "./" at the start (just after the drive
200          * letter and colon - ie change to "C:./*").
201          */
202         if (isalpha(pattern[0]) && pattern[1] == ':' &&
203             pattern[2] != BG_SEP && pattern[2] != BG_SEP2 &&
204             bufend - bufnext > 4) {
205                 *bufnext++ = pattern[0];
206                 *bufnext++ = ':';
207                 *bufnext++ = '.';
208                 *bufnext++ = BG_SEP;
209                 patnext += 2;
210         }
211 #endif
212         if (flags & GLOB_QUOTE) {
213                 /* Protect the quoted characters. */
214                 while (bufnext < bufend && (c = *patnext++) != BG_EOS)
215                         if (c == BG_QUOTE) {
216 #ifdef DOSISH
217                                     /* To avoid backslashitis on Win32,
218                                      * we only treat \ as a quoting character
219                                      * if it precedes one of the
220                                      * metacharacters []-{}~\
221                                      */
222                                 if ((c = *patnext++) != '[' && c != ']' &&
223                                     c != '-' && c != '{' && c != '}' &&
224                                     c != '~' && c != '\\') {
225 #else
226                                 if ((c = *patnext++) == BG_EOS) {
227 #endif
228                                         c = BG_QUOTE;
229                                         --patnext;
230                                 }
231                                 *bufnext++ = c | M_PROTECT;
232                         }
233                         else
234                                 *bufnext++ = c;
235         }
236         else
237             while (bufnext < bufend && (c = *patnext++) != BG_EOS)
238                     *bufnext++ = c;
239         *bufnext = BG_EOS;
240
241         if (flags & GLOB_BRACE)
242             return globexp1(patbuf, pglob);
243         else
244             return glob0(patbuf, pglob);
245 }
246
247 /*
248  * Expand recursively a glob {} pattern. When there is no more expansion
249  * invoke the standard globbing routine to glob the rest of the magic
250  * characters
251  */
252 static int globexp1(const Char *pattern, glob_t *pglob)
253 {
254         const Char* ptr = pattern;
255         int rv;
256
257         /* Protect a single {}, for find(1), like csh */
258         if (pattern[0] == BG_LBRACE && pattern[1] == BG_RBRACE && pattern[2] == BG_EOS)
259                 return glob0(pattern, pglob);
260
261         while ((ptr = (const Char *) g_strchr((Char *) ptr, BG_LBRACE)) != NULL)
262                 if (!globexp2(ptr, pattern, pglob, &rv))
263                         return rv;
264
265         return glob0(pattern, pglob);
266 }
267
268
269 /*
270  * Recursive brace globbing helper. Tries to expand a single brace.
271  * If it succeeds then it invokes globexp1 with the new pattern.
272  * If it fails then it tries to glob the rest of the pattern and returns.
273  */
274 static int globexp2(const Char *ptr, const Char *pattern,
275                     glob_t *pglob, int *rv)
276 {
277         int     i;
278         Char   *lm, *ls;
279         const Char *pe, *pm, *pl;
280         Char    patbuf[MAXPATHLEN + 1];
281
282         /* copy part up to the brace */
283         for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
284                 continue;
285         ls = lm;
286
287         /* Find the balanced brace */
288         for (i = 0, pe = ++ptr; *pe; pe++)
289                 if (*pe == BG_LBRACKET) {
290                         /* Ignore everything between [] */
291                         for (pm = pe++; *pe != BG_RBRACKET && *pe != BG_EOS; pe++)
292                                 continue;
293                         if (*pe == BG_EOS) {
294                                 /*
295                                  * We could not find a matching BG_RBRACKET.
296                                  * Ignore and just look for BG_RBRACE
297                                  */
298                                 pe = pm;
299                         }
300                 }
301                 else if (*pe == BG_LBRACE)
302                         i++;
303                 else if (*pe == BG_RBRACE) {
304                         if (i == 0)
305                                 break;
306                         i--;
307                 }
308
309         /* Non matching braces; just glob the pattern */
310         if (i != 0 || *pe == BG_EOS) {
311                 *rv = glob0(patbuf, pglob);
312                 return 0;
313         }
314
315         for (i = 0, pl = pm = ptr; pm <= pe; pm++)
316                 switch (*pm) {
317                 case BG_LBRACKET:
318                         /* Ignore everything between [] */
319                         for (pl = pm++; *pm != BG_RBRACKET && *pm != BG_EOS; pm++)
320                                 continue;
321                         if (*pm == BG_EOS) {
322                                 /*
323                                  * We could not find a matching BG_RBRACKET.
324                                  * Ignore and just look for BG_RBRACE
325                                  */
326                                 pm = pl;
327                         }
328                         break;
329
330                 case BG_LBRACE:
331                         i++;
332                         break;
333
334                 case BG_RBRACE:
335                         if (i) {
336                             i--;
337                             break;
338                         }
339                         /* FALLTHROUGH */
340                 case BG_COMMA:
341                         if (i && *pm == BG_COMMA)
342                                 break;
343                         else {
344                                 /* Append the current string */
345                                 for (lm = ls; (pl < pm); *lm++ = *pl++)
346                                         continue;
347                                 /*
348                                  * Append the rest of the pattern after the
349                                  * closing brace
350                                  */
351                                 for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS;)
352                                         continue;
353
354                                 /* Expand the current pattern */
355 #ifdef GLOB_DEBUG
356                                 qprintf("globexp2:", patbuf);
357 #endif /* GLOB_DEBUG */
358                                 *rv = globexp1(patbuf, pglob);
359
360                                 /* move after the comma, to the next string */
361                                 pl = pm + 1;
362                         }
363                         break;
364
365                 default:
366                         break;
367                 }
368         *rv = 0;
369         return 0;
370 }
371
372
373
374 /*
375  * expand tilde from the passwd file.
376  */
377 static const Char *
378 globtilde(const Char *pattern, Char *patbuf, glob_t *pglob)
379 {
380         struct passwd *pwd;
381         char *h;
382         const Char *p;
383         Char *b;
384
385         if (*pattern != BG_TILDE || !(pglob->gl_flags & GLOB_TILDE))
386                 return pattern;
387
388         /* Copy up to the end of the string or / */
389         for (p = pattern + 1, h = (char *) patbuf; *p && *p != BG_SLASH;
390              *h++ = *p++)
391                 continue;
392
393         *h = BG_EOS;
394
395         if (((char *) patbuf)[0] == BG_EOS) {
396                 /*
397                  * handle a plain ~ or ~/ by expanding $HOME
398                  * first and then trying the password file
399                  */
400                 if ((h = getenv("HOME")) == NULL) {
401 #ifdef HAS_PASSWD
402                         if ((pwd = getpwuid(getuid())) == NULL)
403                                 return pattern;
404                         else
405                                 h = pwd->pw_dir;
406 #else
407                         return pattern;
408 #endif
409                 }
410         }
411         else {
412                 /*
413                  * Expand a ~user
414                  */
415 #ifdef HAS_PASSWD
416                 if ((pwd = getpwnam((char*) patbuf)) == NULL)
417                         return pattern;
418                 else
419                         h = pwd->pw_dir;
420 #else
421                 return pattern;
422 #endif
423         }
424
425         /* Copy the home directory */
426         for (b = patbuf; *h; *b++ = *h++)
427                 continue;
428
429         /* Append the rest of the pattern */
430         while ((*b++ = *p++) != BG_EOS)
431                 continue;
432
433         return patbuf;
434 }
435
436
437 /*
438  * The main glob() routine: compiles the pattern (optionally processing
439  * quotes), calls glob1() to do the real pattern matching, and finally
440  * sorts the list (unless unsorted operation is requested).  Returns 0
441  * if things went well, nonzero if errors occurred.  It is not an error
442  * to find no matches.
443  */
444 static int
445 glob0(const Char *pattern, glob_t *pglob)
446 {
447         const Char *qpat, *qpatnext;
448         int c, err, oldflags, oldpathc;
449         Char *bufnext, patbuf[MAXPATHLEN+1];
450
451         qpat = globtilde(pattern, patbuf, pglob);
452         qpatnext = qpat;
453         oldflags = pglob->gl_flags;
454         oldpathc = pglob->gl_pathc;
455         bufnext = patbuf;
456
457         /* We don't need to check for buffer overflow any more. */
458         while ((c = *qpatnext++) != BG_EOS) {
459                 switch (c) {
460                 case BG_LBRACKET:
461                         c = *qpatnext;
462                         if (c == BG_NOT)
463                                 ++qpatnext;
464                         if (*qpatnext == BG_EOS ||
465                             g_strchr((Char *) qpatnext+1, BG_RBRACKET) == NULL) {
466                                 *bufnext++ = BG_LBRACKET;
467                                 if (c == BG_NOT)
468                                         --qpatnext;
469                                 break;
470                         }
471                         *bufnext++ = M_SET;
472                         if (c == BG_NOT)
473                                 *bufnext++ = M_NOT;
474                         c = *qpatnext++;
475                         do {
476                                 *bufnext++ = CHAR(c);
477                                 if (*qpatnext == BG_RANGE &&
478                                     (c = qpatnext[1]) != BG_RBRACKET) {
479                                         *bufnext++ = M_RNG;
480                                         *bufnext++ = CHAR(c);
481                                         qpatnext += 2;
482                                 }
483                         } while ((c = *qpatnext++) != BG_RBRACKET);
484                         pglob->gl_flags |= GLOB_MAGCHAR;
485                         *bufnext++ = M_END;
486                         break;
487                 case BG_QUESTION:
488                         pglob->gl_flags |= GLOB_MAGCHAR;
489                         *bufnext++ = M_ONE;
490                         break;
491                 case BG_STAR:
492                         pglob->gl_flags |= GLOB_MAGCHAR;
493                         /* collapse adjacent stars to one,
494                          * to avoid exponential behavior
495                          */
496                         if (bufnext == patbuf || bufnext[-1] != M_ALL)
497                             *bufnext++ = M_ALL;
498                         break;
499                 default:
500                         *bufnext++ = CHAR(c);
501                         break;
502                 }
503         }
504         *bufnext = BG_EOS;
505 #ifdef GLOB_DEBUG
506         qprintf("glob0:", patbuf);
507 #endif /* GLOB_DEBUG */
508
509         if ((err = glob1(patbuf, pglob)) != 0) {
510                 pglob->gl_flags = oldflags;
511                 return(err);
512         }
513
514         /*
515          * If there was no match we are going to append the pattern
516          * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
517          * and the pattern did not contain any magic characters
518          * GLOB_NOMAGIC is there just for compatibility with csh.
519          */
520         if (pglob->gl_pathc == oldpathc &&
521             ((pglob->gl_flags & GLOB_NOCHECK) ||
522               ((pglob->gl_flags & GLOB_NOMAGIC) &&
523                !(pglob->gl_flags & GLOB_MAGCHAR))))
524         {
525 #ifdef GLOB_DEBUG
526                 printf("calling globextend from glob0\n");
527 #endif /* GLOB_DEBUG */
528                 pglob->gl_flags = oldflags;
529                 return(globextend(qpat, pglob));
530         }
531         else if (!(pglob->gl_flags & GLOB_NOSORT))
532                 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
533                     pglob->gl_pathc - oldpathc, sizeof(char *), 
534                     (pglob->gl_flags & GLOB_NOCASE) ? ci_compare : compare);
535         pglob->gl_flags = oldflags;
536         return(0);
537 }
538
539 static int
540 ci_compare(const void *p, const void *q)
541 {
542     const char *pp = *(const char **)p;
543     const char *qq = *(const char **)q;
544     while (*pp && *qq) {
545         if (tolower(*pp) != tolower(*qq))
546             break;
547         ++pp;
548         ++qq;
549     }
550     return (tolower(*pp) - tolower(*qq));
551 }
552
553 static int
554 compare(const void *p, const void *q)
555 {
556         return(strcmp(*(char **)p, *(char **)q));
557 }
558
559 static int
560 glob1(Char *pattern, glob_t *pglob)
561 {
562         Char pathbuf[MAXPATHLEN+1];
563
564         /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
565         if (*pattern == BG_EOS)
566                 return(0);
567         return(glob2(pathbuf, pathbuf, pattern, pglob));
568 }
569
570 /*
571  * The functions glob2 and glob3 are mutually recursive; there is one level
572  * of recursion for each segment in the pattern that contains one or more
573  * meta characters.
574  */
575 static int
576 glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob)
577 {
578         Stat_t sb;
579         Char *p, *q;
580         int anymeta;
581
582         /*
583          * Loop over pattern segments until end of pattern or until
584          * segment with meta character found.
585          */
586         for (anymeta = 0;;) {
587                 if (*pattern == BG_EOS) {               /* End of pattern? */
588                         *pathend = BG_EOS;
589
590                         if (g_lstat(pathbuf, &sb, pglob))
591                                 return(0);
592
593                         if (((pglob->gl_flags & GLOB_MARK) &&
594                             pathend[-1] != BG_SEP
595 #ifdef DOSISH
596                             && pathend[-1] != BG_SEP2
597 #endif
598                             ) && (S_ISDIR(sb.st_mode)
599                             || (S_ISLNK(sb.st_mode) &&
600                             (g_stat(pathbuf, &sb, pglob) == 0) &&
601                             S_ISDIR(sb.st_mode)))) {
602                                 *pathend++ = BG_SEP;
603                                 *pathend = BG_EOS;
604                         }
605                         ++pglob->gl_matchc;
606 #ifdef GLOB_DEBUG
607                         printf("calling globextend from glob2\n");
608 #endif /* GLOB_DEBUG */
609                         return(globextend(pathbuf, pglob));
610                 }
611
612                 /* Find end of next segment, copy tentatively to pathend. */
613                 q = pathend;
614                 p = pattern;
615                 while (*p != BG_EOS && *p != BG_SEP
616 #ifdef DOSISH
617                        && *p != BG_SEP2
618 #endif
619                        ) {
620                         if (ismeta(*p))
621                                 anymeta = 1;
622                         *q++ = *p++;
623                 }
624
625                 if (!anymeta) {         /* No expansion, do next segment. */
626                         pathend = q;
627                         pattern = p;
628                         while (*pattern == BG_SEP
629 #ifdef DOSISH
630                                || *pattern == BG_SEP2
631 #endif
632                                )
633                                 *pathend++ = *pattern++;
634                 } else                  /* Need expansion, recurse. */
635                         return(glob3(pathbuf, pathend, pattern, p, pglob));
636         }
637         /* NOTREACHED */
638 }
639
640 static int
641 glob3(Char *pathbuf, Char *pathend, Char *pattern,
642       Char *restpattern, glob_t *pglob)
643 {
644         register Direntry_t *dp;
645         DIR *dirp;
646         int err;
647         int nocase;
648         char buf[MAXPATHLEN];
649
650         /*
651          * The readdirfunc declaration can't be prototyped, because it is
652          * assigned, below, to two functions which are prototyped in glob.h
653          * and dirent.h as taking pointers to differently typed opaque
654          * structures.
655          */
656         Direntry_t *(*readdirfunc)();
657
658         *pathend = BG_EOS;
659         errno = 0;
660
661         if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
662                 /* TODO: don't call for ENOENT or ENOTDIR? */
663                 if (pglob->gl_errfunc) {
664                         g_Ctoc(pathbuf, buf);
665                         if (pglob->gl_errfunc(buf, errno) ||
666                             (pglob->gl_flags & GLOB_ERR))
667                                 return (GLOB_ABEND);
668                 }
669                 return(0);
670         }
671
672         err = 0;
673         nocase = ((pglob->gl_flags & GLOB_NOCASE) != 0);
674
675         /* Search directory for matching names. */
676         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
677                 readdirfunc = pglob->gl_readdir;
678         else
679                 readdirfunc = my_readdir;
680         while ((dp = (*readdirfunc)(dirp))) {
681                 register U8 *sc;
682                 register Char *dc;
683
684                 /* Initial BG_DOT must be matched literally. */
685                 if (dp->d_name[0] == BG_DOT && *pattern != BG_DOT)
686                         continue;
687                 for (sc = (U8 *) dp->d_name, dc = pathend;
688                      (*dc++ = *sc++) != BG_EOS;)
689                         continue;
690                 if (!match(pathend, pattern, restpattern, nocase)) {
691                         *pathend = BG_EOS;
692                         continue;
693                 }
694                 err = glob2(pathbuf, --dc, restpattern, pglob);
695                 if (err)
696                         break;
697         }
698
699         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
700                 (*pglob->gl_closedir)(dirp);
701         else
702                 PerlDir_close(dirp);
703         return(err);
704 }
705
706
707 /*
708  * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
709  * add the new item, and update gl_pathc.
710  *
711  * This assumes the BSD realloc, which only copies the block when its size
712  * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
713  * behavior.
714  *
715  * Return 0 if new item added, error code if memory couldn't be allocated.
716  *
717  * Invariant of the glob_t structure:
718  *      Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
719  *      gl_pathv points to (gl_offs + gl_pathc + 1) items.
720  */
721 static int
722 globextend(const Char *path, glob_t *pglob)
723 {
724         register char **pathv;
725         register int i;
726         char *copy;
727         const Char *p;
728
729 #ifdef GLOB_DEBUG
730         printf("Adding ");
731         for (p = path; *p; p++)
732                 (void)printf("%c", CHAR(*p));
733         printf("\n");
734 #endif /* GLOB_DEBUG */
735
736         if (pglob->gl_pathv)
737                 pathv = Renew(pglob->gl_pathv,
738                               (2 + pglob->gl_pathc + pglob->gl_offs),char*);
739         else
740                 New(0,pathv,(2 + pglob->gl_pathc + pglob->gl_offs),char*);
741         if (pathv == NULL)
742                 return(GLOB_NOSPACE);
743
744         if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
745                 /* first time around -- clear initial gl_offs items */
746                 pathv += pglob->gl_offs;
747                 for (i = pglob->gl_offs; --i >= 0; )
748                         *--pathv = NULL;
749         }
750         pglob->gl_pathv = pathv;
751
752         for (p = path; *p++;)
753                 continue;
754         New(0, copy, p-path, char);
755         if (copy != NULL) {
756                 g_Ctoc(path, copy);
757                 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
758         }
759         pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
760         return(copy == NULL ? GLOB_NOSPACE : 0);
761 }
762
763
764 /*
765  * pattern matching function for filenames.  Each occurrence of the *
766  * pattern causes a recursion level.
767  */
768 static int
769 match(register Char *name, register Char *pat, register Char *patend, int nocase)
770 {
771         int ok, negate_range;
772         Char c, k;
773
774         while (pat < patend) {
775                 c = *pat++;
776                 switch (c & M_MASK) {
777                 case M_ALL:
778                         if (pat == patend)
779                                 return(1);
780                         do
781                             if (match(name, pat, patend, nocase))
782                                     return(1);
783                         while (*name++ != BG_EOS);
784                         return(0);
785                 case M_ONE:
786                         if (*name++ == BG_EOS)
787                                 return(0);
788                         break;
789                 case M_SET:
790                         ok = 0;
791                         if ((k = *name++) == BG_EOS)
792                                 return(0);
793                         if ((negate_range = ((*pat & M_MASK) == M_NOT)) != BG_EOS)
794                                 ++pat;
795                         while (((c = *pat++) & M_MASK) != M_END)
796                                 if ((*pat & M_MASK) == M_RNG) {
797                                         if (nocase) {
798                                                 if (tolower(c) <= tolower(k) && tolower(k) <= tolower(pat[1]))
799                                                         ok = 1;
800                                         } else {
801                                                 if (c <= k && k <= pat[1])
802                                                         ok = 1;
803                                         }
804                                         pat += 2;
805                                 } else if (nocase ? (tolower(c) == tolower(k)) : (c == k))
806                                         ok = 1;
807                         if (ok == negate_range)
808                                 return(0);
809                         break;
810                 default:
811                         k = *name++;
812                         if (nocase ? (tolower(k) != tolower(c)) : (k != c))
813                                 return(0);
814                         break;
815                 }
816         }
817         return(*name == BG_EOS);
818 }
819
820 /* Free allocated data belonging to a glob_t structure. */
821 void
822 bsd_globfree(glob_t *pglob)
823 {
824         register int i;
825         register char **pp;
826
827         if (pglob->gl_pathv != NULL) {
828                 pp = pglob->gl_pathv + pglob->gl_offs;
829                 for (i = pglob->gl_pathc; i--; ++pp)
830                         if (*pp)
831                                 Safefree(*pp);
832                 Safefree(pglob->gl_pathv);
833         }
834 }
835
836 static DIR *
837 g_opendir(register Char *str, glob_t *pglob)
838 {
839         char buf[MAXPATHLEN];
840
841         if (!*str)
842                 strcpy(buf, ".");
843         else
844                 g_Ctoc(str, buf);
845
846         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
847                 return((*pglob->gl_opendir)(buf));
848         else
849             return(PerlDir_open(buf));
850 }
851
852 static int
853 g_lstat(register Char *fn, Stat_t *sb, glob_t *pglob)
854 {
855         char buf[MAXPATHLEN];
856
857         g_Ctoc(fn, buf);
858         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
859                 return((*pglob->gl_lstat)(buf, sb));
860 #ifdef HAS_LSTAT
861         return(PerlLIO_lstat(buf, sb));
862 #else
863         return(PerlLIO_stat(buf, sb));
864 #endif /* HAS_LSTAT */
865 }
866
867 static int
868 g_stat(register Char *fn, Stat_t *sb, glob_t *pglob)
869 {
870         char buf[MAXPATHLEN];
871
872         g_Ctoc(fn, buf);
873         if (pglob->gl_flags & GLOB_ALTDIRFUNC)
874                 return((*pglob->gl_stat)(buf, sb));
875         return(PerlLIO_stat(buf, sb));
876 }
877
878 static Char *
879 g_strchr(Char *str, int ch)
880 {
881         do {
882                 if (*str == ch)
883                         return (str);
884         } while (*str++);
885         return (NULL);
886 }
887
888 #ifdef notdef
889 static Char *
890 g_strcat(Char *dst, const Char *src)
891 {
892         Char *sdst = dst;
893
894         while (*dst++)
895                 continue;
896         --dst;
897         while((*dst++ = *src++) != BG_EOS)
898             continue;
899
900         return (sdst);
901 }
902 #endif
903
904 static void
905 g_Ctoc(register const Char *str, char *buf)
906 {
907         register char *dc;
908
909         for (dc = buf; (*dc++ = *str++) != BG_EOS;)
910                 continue;
911 }
912
913 #ifdef GLOB_DEBUG
914 static void
915 qprintf(const char *str, register Char *s)
916 {
917         register Char *p;
918
919         (void)printf("%s:\n", str);
920         for (p = s; *p; p++)
921                 (void)printf("%c", CHAR(*p));
922         (void)printf("\n");
923         for (p = s; *p; p++)
924                 (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
925         (void)printf("\n");
926         for (p = s; *p; p++)
927                 (void)printf("%c", ismeta(*p) ? '_' : ' ');
928         (void)printf("\n");
929 }
930 #endif /* GLOB_DEBUG */