X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=pathexp.c;h=d7315e388bbeedaf8d430433855c6f23002b6bda;hb=ac50fbac377e32b98d2de396f016ea81e8ee9961;hp=f23995684acbe42a25af6bb4e7e68594890edc11;hpb=4539d736f1aff232857a854fd2a68df0c98d9f34;p=platform%2Fupstream%2Fbash.git diff --git a/pathexp.c b/pathexp.c index f239956..d7315e3 100644 --- a/pathexp.c +++ b/pathexp.c @@ -1,6 +1,6 @@ /* pathexp.c -- The shell interface to the globbing library. */ -/* Copyright (C) 1995-2009 Free Software Foundation, Inc. +/* Copyright (C) 1995-2014 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -41,7 +41,7 @@ static int glob_name_is_acceptable __P((const char *)); static void ignore_globbed_names __P((char **, sh_ignore_func_t *)); static char *split_ignorespec __P((char *, int *)); - + #if defined (USE_POSIX_GLOB_LIBRARY) # include typedef int posix_glob_errfunc_t __P((const char *, int)); @@ -157,7 +157,7 @@ glob_char_p (s) case '+': case '@': case '!': - if (s[1] == '(') /*(*/ + if (s[1] == '(') /*(*/ return 1; break; } @@ -173,7 +173,9 @@ glob_char_p (s) removal has not been done (for example, before attempting to match a pattern while executing a case statement), flags should include QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting - to match a filename should be performed. */ + to match a filename should be performed. QGLOB_REGEXP means we're + quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires + some special handling. */ char * quote_string_for_globbing (pathname, qflags) const char *pathname; @@ -181,8 +183,9 @@ quote_string_for_globbing (pathname, qflags) { char *temp; register int i, j; + int brack, cclass, collsym, equiv, c, last_was_backslash; - temp = (char *)xmalloc (strlen (pathname) + 1); + temp = (char *)xmalloc (2 * strlen (pathname) + 1); if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname)) { @@ -190,12 +193,28 @@ quote_string_for_globbing (pathname, qflags) return temp; } + brack = cclass = collsym = equiv = last_was_backslash = 0; for (i = j = 0; pathname[i]; i++) { - if (pathname[i] == CTLESC) + /* Fix for CTLESC at the end of the string? */ + if (pathname[i] == CTLESC && pathname[i+1] == '\0') + { + temp[j++] = pathname[i++]; + break; + } + /* If we are parsing regexp, turn CTLESC CTLESC into CTLESC. It's not an + ERE special character, so we should just be able to pass it through. */ + else if ((qflags & QGLOB_REGEXP) && pathname[i] == CTLESC && pathname[i+1] == CTLESC) + { + i++; + temp[j++] = pathname[i]; + continue; + } + else if (pathname[i] == CTLESC) { if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/') continue; + /* What to do if preceding char is backslash? */ if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0) continue; temp[j++] = '\\'; @@ -203,15 +222,90 @@ quote_string_for_globbing (pathname, qflags) if (pathname[i] == '\0') break; } - else if (pathname[i] == '\\') + else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/ + { + brack = 1; + temp[j++] = pathname[i++]; /* open bracket */ + c = pathname[i++]; /* c == char after open bracket */ + do + { + if (c == 0) + goto endpat; + else if (c == CTLESC) + { + /* skip c, check for EOS, let assignment at end of loop */ + /* pathname[i] == backslash-escaped character */ + if (pathname[i] == 0) + goto endpat; + temp[j++] = pathname[i++]; + } + else if (c == '[' && pathname[i] == ':') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + cclass = 1; + } + else if (cclass && c == ':' && pathname[i] == ']') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + cclass = 0; + } + else if (c == '[' && pathname[i] == '=') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + if (pathname[i] == ']') + temp[j++] = pathname[i++]; /* right brack can be in equiv */ + equiv = 1; + } + else if (equiv && c == '=' && pathname[i] == ']') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + equiv = 0; + } + else if (c == '[' && pathname[i] == '.') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + if (pathname[i] == ']') + temp[j++] = pathname[i++]; /* right brack can be in collsym */ + collsym = 1; + } + else if (collsym && c == '.' && pathname[i] == ']') + { + temp[j++] = c; + temp[j++] = pathname[i++]; + collsym = 0; + } + else + temp[j++] = c; + } + while ((c = pathname[i++]) != ']'); + temp[j++] = c; /* closing right bracket */ + i--; /* increment will happen above in loop */ + continue; /* skip double assignment below */ + } + else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP) == 0) { + /* XXX - if not quoting regexp, use backslash as quote char. Should + we just pass it through without treating it as special? That is + what ksh93 seems to do. */ + + /* If we want to pass through backslash unaltered, comment out these + lines. */ temp[j++] = '\\'; + i++; if (pathname[i] == '\0') break; } + else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP)) + last_was_backslash = 1; temp[j++] = pathname[i]; } +endpat: temp[j] = '\0'; return (temp); @@ -235,7 +329,7 @@ quote_globbing_chars (string) *t++ = '\\'; /* Copy a single (possibly multibyte) character from s to t, - incrementing both. */ + incrementing both. */ COPY_CHAR_P (t, s, send); } *t = '\0';