diff options
-rwxr-xr-x | glob/COPYING.LIB.old | 2 | ||||
-rw-r--r-- | glob/ChangeLog | 7 | ||||
-rw-r--r-- | glob/glob.c | 139 |
3 files changed, 114 insertions, 34 deletions
diff --git a/glob/COPYING.LIB.old b/glob/COPYING.LIB.old index bbe3fe1..eb685a5 100755 --- a/glob/COPYING.LIB.old +++ b/glob/COPYING.LIB.old @@ -133,7 +133,7 @@ such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. - + 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an diff --git a/glob/ChangeLog b/glob/ChangeLog index 623cca8..5d6cc49 100644 --- a/glob/ChangeLog +++ b/glob/ChangeLog @@ -1,3 +1,10 @@ +Thu Mar 14 06:01:07 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> + + * posix/glob.c (glob): In GLOB_BRACE brace expansion, fix buffer size + calculation to include trailing invariant portion. Don't use alloca; + instead use a dynamic auto array for GCC, malloc for non-GCC. + Handle nested braces properly. + Fri Mar 1 10:09:46 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu> * posix/glob.c: Use canonical code from autoconf manual for dirent diff --git a/glob/glob.c b/glob/glob.c index 8646bba..eea126d 100644 --- a/glob/glob.c +++ b/glob/glob.c @@ -268,48 +268,121 @@ glob (pattern, flags, errfunc, pglob) const char *begin = strchr (pattern, '{'); if (begin != NULL) { - const char *end = strchr (begin + 1, '}'); - if (end != NULL && end != begin + 1) + int firstc; + size_t restlen; + const char *p, *end, *next; + unsigned int depth = 0; + + /* Find the end of the brace expression, by counting braces. + While we're at it, notice the first comma at top brace level. */ + end = begin + 1; + next = NULL; + while (1) { - size_t restlen = strlen (end + 1) + 1; - const char *p, *comma; - char *buf; - size_t bufsz = 0; - int firstc; - if (!(flags & GLOB_APPEND)) + switch (*end++) { - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; + case ',': + if (depth == 0 && next == NULL) + next = end; + continue; + case '{': + ++depth; + continue; + case '}': + if (depth-- == 0) + break; + continue; + case '\0': + return glob (pattern, flags &~ GLOB_BRACE, errfunc, pglob); } - firstc = pglob->gl_pathc; - for (p = begin + 1;; p = comma + 1) + break; + } + restlen = strlen (end) + 1; + if (next == NULL) + next = end; + + /* We have a brace expression. BEGIN points to the opening {, + NEXT points past the terminator of the first element, and END + points past the final }. We will accumulate result names from + recursive runs for each brace alternative in the buffer using + GLOB_APPEND. */ + + if (!(flags & GLOB_APPEND)) + { + /* This call is to set a new vector, so clear out the + vector so we can append to it. */ + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + firstc = pglob->gl_pathc; + + /* In this loop P points to the beginning of the current element + and NEXT points past its terminator. */ + p = begin + 1; + while (1) + { + /* Construct a whole name that is one of the brace + alternatives in a temporary buffer. */ + int result; + size_t bufsz = (begin - pattern) + (next - 1 - p) + restlen; +#ifdef __GNUC__ + char onealt[bufsz]; +#else + char *onealt = malloc (bufsz); + if (onealt == NULL) { - int result; - comma = strchr (p, ','); - if (comma == NULL) - comma = strchr (p, '\0'); - if ((begin - pattern) + (comma - p) + 1 > bufsz) + if (!(flags & GLOB_APPEND)) + globfree (&pglob); + return GLOB_NOSPACE; + } +#endif + memcpy (onealt, pattern, begin - pattern); + memcpy (&onealt[begin - pattern], p, next - 1 - p); + memcpy (&onealt[(begin - pattern) + (next - 1 - p)], + end, restlen); + result = glob (onealt, + ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) | + GLOB_APPEND), errfunc, pglob); +#ifndef __GNUC__ + free (onealt); +#endif + + /* If we got an error, return it. */ + if (result && result != GLOB_NOMATCH) + { + if (!(flags & GLOB_APPEND)) + globfree (pglob); + return result; + } + + /* Advance past this alternative and process the next. */ + p = next; + depth = 0; + scan: + switch (*p++) + { + case ',': + if (depth == 0) { - if (bufsz * 2 < comma - p + 1) - bufsz *= 2; - else - bufsz = comma - p + 1; - buf = __alloca (bufsz); + /* Found the next alternative. Loop to glob it. */ + next = p; + continue; } - memcpy (buf, pattern, begin - pattern); - memcpy (buf + (begin - pattern), p, comma - p); - memcpy (buf + (begin - pattern) + (comma - p), end, restlen); - result = glob (buf, ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) | - GLOB_APPEND), errfunc, pglob); - if (result && result != GLOB_NOMATCH) - return result; - if (*comma == '\0') + goto scan; + case '{': + ++depth; + goto scan; + case '}': + if (depth-- == 0) + /* End of the brace expression. Break out of the loop. */ break; + goto scan; } - if (pglob->gl_pathc == firstc && - !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) - return GLOB_NOMATCH; } + + if (pglob->gl_pathc == firstc && + !(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + return GLOB_NOMATCH; } } |