summaryrefslogtreecommitdiffstats
path: root/bin
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
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')
-rw-r--r--bin/sh/expand.c38
-rw-r--r--bin/sh/sh.112
2 files changed, 48 insertions, 2 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) {
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 3b7f3d3..67ffcc6 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd June 12, 2011
+.Dd June 15, 2011
.Dt SH 1
.Os
.Sh NAME
@@ -1648,6 +1648,15 @@ matches a
rather than introducing a character class.
A character class matches any of the characters between the square brackets.
A range of characters may be specified using a minus sign.
+A named class of characters (see
+.Xr wctype 3 )
+may be specified by surrounding the name with
+.Ql \&[:
+and
+.Ql :\&] .
+For example,
+.Ql \&[\&[:alpha:\&]\&]
+is a shell pattern that matches a single letter.
The character class may be complemented by making an exclamation point
.Pq Ql !\&
the first character of the character class.
@@ -2572,6 +2581,7 @@ will return the argument.
.Xr execve 2 ,
.Xr getrlimit 2 ,
.Xr umask 2 ,
+.Xr wctype 3 ,
.Xr editrc 5
.Sh HISTORY
A
OpenPOWER on IntegriCloud