summaryrefslogtreecommitdiffstats
path: root/bin/sh/expand.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-06-15 21:48:10 +0000
committerjilles <jilles@FreeBSD.org>2011-06-15 21:48:10 +0000
commit84b55be725c7dfa96339786e79ce1935e17f7165 (patch)
tree96218b02aec3161b99056c7f828d160ff6dfb2f9 /bin/sh/expand.c
parentcaf476d4f9b966954fb606d0154f75e875ceadfa (diff)
downloadFreeBSD-src-84b55be725c7dfa96339786e79ce1935e17f7165.zip
FreeBSD-src-84b55be725c7dfa96339786e79ce1935e17f7165.tar.gz
sh: Add support for named character classes in bracket expressions.
Example: case x in [[:alpha:]]) echo yes ;; esac
Diffstat (limited to 'bin/sh/expand.c')
-rw-r--r--bin/sh/expand.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index 95a0d6a..ea8d78d 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
#include <wchar.h>
+#include <wctype.h>
/*
* Routines to expand arguments to commands. We have to deal with
@@ -1401,13 +1402,43 @@ get_wc(const char **p)
/*
+ * See if a character matches a character class, starting at the first colon
+ * of "[:class:]".
+ * If a valid character class is recognized, a pointer to the next character
+ * after the final closing bracket is stored into *end, otherwise a null
+ * pointer is stored into *end.
+ */
+static int
+match_charclass(const char *p, wchar_t chr, const char **end)
+{
+ char name[20];
+ const char *nameend;
+ wctype_t cclass;
+
+ *end = NULL;
+ p++;
+ nameend = strstr(p, ":]");
+ if (nameend == NULL || nameend - p >= sizeof(name) || nameend == p)
+ return 0;
+ memcpy(name, p, nameend - p);
+ name[nameend - p] = '\0';
+ *end = nameend + 2;
+ cclass = wctype(name);
+ /* An unknown class matches nothing but is valid nevertheless. */
+ if (cclass == 0)
+ return 0;
+ return iswctype(chr, cclass);
+}
+
+
+/*
* Returns true if the pattern matches the string.
*/
int
patmatch(const char *pattern, const char *string, int squoted)
{
- const char *p, *q;
+ const char *p, *q, *end;
char c;
wchar_t wc, wc2;
@@ -1495,6 +1526,11 @@ patmatch(const char *pattern, const char *string, int squoted)
do {
if (c == CTLQUOTEMARK)
continue;
+ if (c == '[' && *p == ':') {
+ found |= match_charclass(p, chr, &end);
+ if (end != NULL)
+ p = end;
+ }
if (c == CTLESC)
c = *p++;
if (localeisutf8 && c & 0x80) {
OpenPOWER on IntegriCloud