public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support
@ 2013-03-24  9:50 Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 01/11] hashtable: preparations to use hexport_r() for "env grep" Wolfgang Denk
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

The following patch series adds the SLRE "Super Light Regular
Expression" library and uses this to add regex support for
the "env grep" (aka "grepenv") command, and new functions (or
operators?) "gsub" and "sub" to the "setexpr" command.

The rework to "env grep" also fixed a few bugs (which caused it to
dump always _all_ environment variables on some systems), and adds
the capability to grep in either the variable name, or the value, or
in both (the old version always did the latter).  Instead of special
functions we now use common code (i. e. hexport_r()) for the variable
look-up, which gives us sorted output as a free additional benefit.

This allows to do things like

- print all MAC addresses:

	=> env grep -e eth.*addr
	eth1addr=00:10:ec:80:c5:15
	ethaddr=00:10:ec:00:c5:15

- print all variables that have at least 2 colons in their value:

	=> env grep -v -e :.*:
	addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1
	eth1addr=00:10:ec:80:c5:15
	ethaddr=00:10:ec:00:c5:15
	ver=U-Boot 2013.04-rc1-00289-g497746b-dirty (Mar 22 2013 - 12:50:25)

- Generate broadcast address by substituting the last two numbers of
  the IP address by "255.255":

  	=> print ipaddr
	ipaddr=192.168.1.104
	=> setexpr broadcast sub "(.*\\.).*\\..*" "\\1255.255" $ipaddr
	broadcast=192.168.255.255

- Depending on keyboard configuration (German vs. US keyboard) a
  bar code scanner may initialize the MAC address as C0:E5:4E:02:06:DC
  or as C0>E5>4E>02>06>DC.  Make sure we always have a correct value:

  	=> print ethaddr
	ethaddr=C0>E5>4E>02>06>DC
	=> setexpr ethaddr gsub > :
	ethaddr=C0:E5:4E:02:06:DC

etc.

Regex support can be enabled by defining  CONFIG_REGEX  in the board
config file.

Notes:

- This patch series has been compile-tested (and found to be clean
  with ELDK v5.3) on all of the following boards:

  ARM: m28evk

  PPC4xx: acadia bamboo bluestone bubinga canyonlands dlvision-10g
  dlvision ebony gdppc440etx icon intip io io64 iocon katmai kilauea
  luan makalu neo ocotea redwood sequoia t3corp taihu taishan walnut
  yosemite yucca

- Runtime / functional testing has been done mostly on PPC (Sequoia
  board).


Changes in v2:
- fixed trailing whitespace errors
- Note 1: The "line over 80 characters" warning will NOT be fixed due
  to the "never break user-visible strings" rule.
- Note 2: The "Alignment should match open parenthesis" check will NOT
  be fixed due to the "indent by TABs only" rule.
- Fix ERROR: "foo * bar" should be "foo *bar" errors
- Fix trailing whitespace error
- Note: the "Alignment should match open parenthesis" check will not
  be fixed due to the "indent always byy TABs" rule.
- no changes; most of this is imported code and is intentionally left
  as is
- the "Alignment should match open parenthesis" check is left due to
  the "indent only by TABs" rule
- the "line over 80 characters" warning is left due to the "never
  break user-visible strings" rule
- Fix trailing whitespace error
- fix "No space is necessary after a cast" checks
- fix "space prohibited before semicolon" and "space required after
  that ';'" errors (but I onsider the result less readable :-( )
- Note: the remaining warnings ("line over 80 characters") and checks
  ("Alignment should match open parenthesis") are intentionally left
  as is.
- Do the white space cleanup globally, and as separate patch

Wolfgang Denk (11):
  hashtable: preparations to use hexport_r() for "env grep"
  "env grep" - reimplement command using hexport_r()
  "env grep" - add options to grep in name, value, or both.
  Add SLRE - Super Light Regular Expression library
  "env grep" - add support for regular expression matches
  setexpr: simplify code, improve help message
  setexpr: add regex substring matching and substitution
  m28evk: white space cleanup
  m28evk: enable "env grep" and regexp support
  amcc-common.h: minor white space cleanup
  amcc-common.h: enable support for "env grep", "setexpr", and regex.

 README                        |   7 +
 common/cmd_nvedit.c           |  87 +++--
 common/cmd_setexpr.c          | 296 ++++++++++++++++-
 include/configs/amcc-common.h |   9 +-
 include/configs/m28evk.h      | 259 +++++++--------
 include/search.h              |  15 +-
 include/slre.h                | 100 ++++++
 lib/Makefile                  |   1 +
 lib/hashtable.c               |  93 ++++--
 lib/slre.c                    | 724 ++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 1391 insertions(+), 200 deletions(-)
 create mode 100644 include/slre.h
 create mode 100644 lib/slre.c

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 01/11] hashtable: preparations to use hexport_r() for "env grep"
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 02/11] "env grep" - reimplement command using hexport_r() Wolfgang Denk
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

The output of "env grep" is unsorted, and printing is done by a
private implementation to parse the hash table.  We have all the
needed code in place in hexport_r() alsready, so let's use this
instead.  Here we prepare the code for this, without any functional
changes yet.

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- fixed trailing whitespace errors
- Note 1: The "line over 80 characters" warning will NOT be fixed due
  to the "never break user-visible strings" rule.
- Note 2: The "Alignment should match open parenthesis" check will NOT
  be fixed due to the "indent by TABs only" rule.

 common/cmd_nvedit.c | 10 +++++++---
 include/search.h    |  8 +++++++-
 lib/hashtable.c     | 32 ++++++++++++++++++++++++--------
 3 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 947d6c4..36c2deb 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000-2010
+ * (C) Copyright 2000-2013
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
@@ -871,7 +871,9 @@ NXTARG:		;
 	argv++;
 
 	if (sep) {		/* export as text file */
-		len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv);
+		len = hexport_r(&env_htab, sep,
+				H_MATCH_KEY | H_MATCH_IDENT,
+				&addr, size, argc, argv);
 		if (len < 0) {
 			error("Cannot export environment: errno = %d\n", errno);
 			return 1;
@@ -889,7 +891,9 @@ NXTARG:		;
 	else			/* export as raw binary data */
 		res = addr;
 
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv);
+	len = hexport_r(&env_htab, '\0',
+			H_MATCH_KEY | H_MATCH_IDENT,
+			&res, ENV_SIZE, argc, argv);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
diff --git a/include/search.h b/include/search.h
index 13d3be6..9d9abd6 100644
--- a/include/search.h
+++ b/include/search.h
@@ -22,7 +22,7 @@
 /*
  * Based on code from uClibc-0.9.30.3
  * Extensions for use within U-Boot
- * Copyright (C) 2010 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
  */
 
 #ifndef _SEARCH_H
@@ -131,5 +131,11 @@ extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
 #define H_FORCE		(1 << 1) /* overwrite read-only/write-once variables */
 #define H_INTERACTIVE	(1 << 2) /* indicate that an import is user directed */
 #define H_HIDE_DOT	(1 << 3) /* don't print env vars that begin with '.' */
+#define H_MATCH_KEY	(1 << 4) /* search/grep key  = variable names	     */
+#define H_MATCH_DATA	(1 << 5) /* search/grep data = variable values	     */
+#define H_MATCH_BOTH	(H_MATCH_KEY | H_MATCH_DATA) /* search/grep both     */
+#define H_MATCH_IDENT	(1 << 6) /* search for indentical strings	     */
+#define H_MATCH_SUBSTR  (1 << 7) /* search for substring matches	     */
+#define H_MATCH_METHOD	(H_MATCH_IDENT | H_MATCH_SUBSTR)
 
 #endif /* search.h */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 07ebfb2..305824b 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -2,7 +2,7 @@
  * This implementation is based on code from uClibc-0.9.30.3 but was
  * modified and extended for use within U-Boot.
  *
- * Copyright (C) 2010 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2010-2013 Wolfgang Denk <wd@denx.de>
  *
  * Original license header:
  *
@@ -563,6 +563,28 @@ static int cmpkey(const void *p1, const void *p2)
 	return (strcmp(e1->key, e2->key));
 }
 
+static int match_strings(ENTRY *ep, int flag,
+		 int argc, char * const argv[])
+{
+	int arg;
+
+	for (arg = 0; arg < argc; ++arg) {
+		if (flag & H_MATCH_KEY) {
+			switch (flag & H_MATCH_METHOD) {
+			case H_MATCH_IDENT:
+				if (strcmp(argv[arg], ep->key) == 0)
+					return 1;
+				break;
+			default:
+				printf("## ERROR: unsupported match method: 0x%02x\n",
+					flag & H_MATCH_METHOD);
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
 ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 		 char **resp, size_t size,
 		 int argc, char * const argv[])
@@ -589,14 +611,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-			int arg, found = 0;
+			int found = match_strings(ep, flag, argc, argv);
 
-			for (arg = 0; arg < argc; ++arg) {
-				if (strcmp(argv[arg], ep->key) == 0) {
-					found = 1;
-					break;
-				}
-			}
 			if ((argc > 0) && (found == 0))
 				continue;
 
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 02/11] "env grep" - reimplement command using hexport_r()
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 01/11] hashtable: preparations to use hexport_r() for "env grep" Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 03/11] "env grep" - add options to grep in name, value, or both Wolfgang Denk
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Also drop hstrstr_r() which is not needed any more.
The new code is way more flexible.

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- Fix ERROR: "foo * bar" should be "foo *bar" errors
- Fix trailing whitespace error
- Note: the "Alignment should match open parenthesis" check will not
  be fixed due to the "indent always byy TABs" rule.

 common/cmd_nvedit.c | 30 ++++++++++---------------
 include/search.h    |  6 -----
 lib/hashtable.c     | 64 +++++++++++++++++++++++------------------------------
 3 files changed, 40 insertions(+), 60 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 36c2deb..487eca9 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -162,31 +162,25 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
 static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		       int argc, char * const argv[])
 {
-	ENTRY *match;
-	unsigned char matched[env_htab.size / 8];
-	int rcode = 1, arg = 1, idx;
+	char *res = NULL;
+	int len;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	memset(matched, 0, env_htab.size / 8);
+	len = hexport_r(&env_htab, '\n',
+			flag | H_MATCH_BOTH | H_MATCH_SUBSTR,
+			&res, 0, argc, argv);
 
-	while (arg <= argc) {
-		idx = 0;
-		while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) {
-			if (!(matched[idx / 8] & (1 << (idx & 7)))) {
-				puts(match->key);
-				puts("=");
-				puts(match->data);
-				puts("\n");
-			}
-			matched[idx / 8] |= 1 << (idx & 7);
-			rcode = 0;
-		}
-		arg++;
+	if (len > 0) {
+		puts(res);
+		free(res);
 	}
 
-	return rcode;
+	if (len < 2)
+		return 1;
+
+	return 0;
 }
 #endif
 #endif /* CONFIG_SPL_BUILD */
diff --git a/include/search.h b/include/search.h
index 9d9abd6..d06a201 100644
--- a/include/search.h
+++ b/include/search.h
@@ -98,12 +98,6 @@ extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
  */
 extern int hmatch_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
-/*
- * Search for an entry whose key or data contains `MATCH'.  Otherwise,
- * Same semantics as hsearch_r().
- */
-extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
-		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 305824b..1703941 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -210,29 +210,6 @@ void hdestroy_r(struct hsearch_data *htab)
  *   example for functions like hdelete().
  */
 
-/*
- * hstrstr_r - return index to entry whose key and/or data contains match
- */
-int hstrstr_r(const char *match, int last_idx, ENTRY ** retval,
-	      struct hsearch_data *htab)
-{
-	unsigned int idx;
-
-	for (idx = last_idx + 1; idx < htab->size; ++idx) {
-		if (htab->table[idx].used <= 0)
-			continue;
-		if (strstr(htab->table[idx].entry.key, match) ||
-		    strstr(htab->table[idx].entry.data, match)) {
-			*retval = &htab->table[idx].entry;
-			return idx;
-		}
-	}
-
-	__set_errno(ESRCH);
-	*retval = NULL;
-	return 0;
-}
-
 int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	     struct hsearch_data *htab)
 {
@@ -563,23 +540,38 @@ static int cmpkey(const void *p1, const void *p2)
 	return (strcmp(e1->key, e2->key));
 }
 
-static int match_strings(ENTRY *ep, int flag,
+static int match_string(int flag, const char *str, const char *pat)
+{
+	switch (flag & H_MATCH_METHOD) {
+	case H_MATCH_IDENT:
+		if (strcmp(str, pat) == 0)
+			return 1;
+		break;
+	case H_MATCH_SUBSTR:
+		if (strstr(str, pat))
+			return 1;
+		break;
+	default:
+		printf("## ERROR: unsupported match method: 0x%02x\n",
+			flag & H_MATCH_METHOD);
+		break;
+	}
+	return 0;
+}
+
+static int match_entry(ENTRY *ep, int flag,
 		 int argc, char * const argv[])
 {
 	int arg;
 
-	for (arg = 0; arg < argc; ++arg) {
+	for (arg = 1; arg < argc; ++arg) {
 		if (flag & H_MATCH_KEY) {
-			switch (flag & H_MATCH_METHOD) {
-			case H_MATCH_IDENT:
-				if (strcmp(argv[arg], ep->key) == 0)
-					return 1;
-				break;
-			default:
-				printf("## ERROR: unsupported match method: 0x%02x\n",
-					flag & H_MATCH_METHOD);
-				break;
-			}
+			if (match_string(flag, ep->key, argv[arg]))
+				return 1;
+		}
+		if (flag & H_MATCH_DATA) {
+			if (match_string(flag, ep->data, argv[arg]))
+				return 1;
 		}
 	}
 	return 0;
@@ -611,7 +603,7 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-			int found = match_strings(ep, flag, argc, argv);
+			int found = match_entry(ep, flag, argc, argv);
 
 			if ((argc > 0) && (found == 0))
 				continue;
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 03/11] "env grep" - add options to grep in name, value, or both.
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 01/11] hashtable: preparations to use hexport_r() for "env grep" Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 02/11] "env grep" - reimplement command using hexport_r() Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 04/11] Add SLRE - Super Light Regular Expression library Wolfgang Denk
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Add options to "env grep" command:

-n : search only the envrironment variable names
-v : search only their values
-b : search both names and values (= default)

An option "--" will stop parsing options, so to print variables that
contain the striing "- " please use:

	env grep -- "- "

Or to print all environment varioables which have a '-' in their name,
use:

	env grep -n -- -

Signed-off-by: Wolfgang Denk <wd@denx.de>
---
Changes in v2: None

 common/cmd_nvedit.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 487eca9..923e113 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -163,13 +163,39 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		       int argc, char * const argv[])
 {
 	char *res = NULL;
-	int len;
+	int len, grep_flags;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
+	grep_flags = H_MATCH_BOTH;
+
+	while (argc > 1 && **(argv + 1) == '-') {
+		char *arg = *++argv;
+
+		--argc;
+		while (*++arg) {
+			switch (*arg) {
+			case 'n':		/* grep for name */
+				grep_flags = H_MATCH_KEY;
+				break;
+			case 'v':		/* grep for value */
+				grep_flags = H_MATCH_DATA;
+				break;
+			case 'b':		/* grep for both */
+				grep_flags = H_MATCH_BOTH;
+				break;
+			case '-':
+				goto DONE;
+			default:
+				return CMD_RET_USAGE;
+			}
+		}
+	}
+
+DONE:
 	len = hexport_r(&env_htab, '\n',
-			flag | H_MATCH_BOTH | H_MATCH_SUBSTR,
+			flag | grep_flags | H_MATCH_SUBSTR,
 			&res, 0, argc, argv);
 
 	if (len > 0) {
@@ -1106,7 +1132,7 @@ static char env_help_text[] =
 	"env flags - print variables that have non-default flags\n"
 #endif
 #if defined(CONFIG_CMD_GREPENV)
-	"env grep string [...] - search environment\n"
+	"env grep [-n | -v | -b] string [...] - search environment\n"
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
 	"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
@@ -1153,8 +1179,10 @@ U_BOOT_CMD_COMPLETE(
 U_BOOT_CMD_COMPLETE(
 	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
 	"search environment variables",
-	"string ...\n"
-	"    - list environment name=value pairs matching 'string'",
+	"[-n | -v | -b] string ...\n"
+	"    - list environment name=value pairs matching 'string'\n"
+	"      \"-n\": search variable names; \"-v\": search values;\n"
+	"      \"-b\": search both names and values (default)",
 	var_complete
 );
 #endif
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 04/11] Add SLRE - Super Light Regular Expression library
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (2 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 03/11] "env grep" - add options to grep in name, value, or both Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 05/11] "env grep" - add support for regular expression matches Wolfgang Denk
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Downloaded from http://slre.sourceforge.net/
and adapted for U-Boot environment.

Used to implement regex operations on environment variables.
Code size is ~ 3.5 KiB on PPC.

To enable this code, define the  CONFIG_REGEX  option in your board
config file.

Note:  There are more recent versions of the SLRE library available at
http://slre.googlecode.com ; unfortunately, the new code has a heavily
reorked API which makes it less usable for our purposes:
- the return code is strings, which are more difficult to process
- we don't get any information any more which sub-string of the data
  was matched by the given regex
- it is much more cumbersome to work with arbitrary expressions, where
  for example the number of substrings for capturing are not known at
  compile time
Also, there does not seem to be any real changes or improvements of
the functionality.

Because of this, we deliberately stick with the older code.

Note 2: the test code (built when SLRE_TEST is defined) was modified
to allow for more extensive testing; now we can test the regexp
matching on all lines on a text file (instead of the whole data in the
file as a single block).

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- no changes; most of this is imported code and is intentionally left
  as is
- the "Alignment should match open parenthesis" check is left due to
  the "indent only by TABs" rule
- the "line over 80 characters" warning is left due to the "never
  break user-visible strings" rule

 README         |   7 +
 include/slre.h | 100 ++++++++
 lib/Makefile   |   1 +
 lib/slre.c     | 724 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 832 insertions(+)
 create mode 100644 include/slre.h
 create mode 100644 lib/slre.c

diff --git a/README b/README
index 7f2506a..f088d28 100644
--- a/README
+++ b/README
@@ -930,6 +930,13 @@ The following options need to be configured:
 
 		XXX - this list needs to get updated!
 
+- Regular expression support:
+		CONFIG_REGEX
+                If this variable is defined, U-Boot is linked against
+                the SLRE (Super Light Regular Expression) library,
+                which adds regex support to some commands, as for
+                example "env grep" and "setexpr".
+
 - Device tree:
 		CONFIG_OF_CONTROL
 		If this variable is defined, U-Boot will use a device tree
diff --git a/include/slre.h b/include/slre.h
new file mode 100644
index 0000000..4b41a4b
--- /dev/null
+++ b/include/slre.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ * All rights reserved
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+
+/*
+ * Downloaded Sat Nov  5 17:42:08 CET 2011 at
+ * http://slre.sourceforge.net/1.0/slre.h
+ */
+
+/*
+ * This is a regular expression library that implements a subset of Perl RE.
+ * Please refer to http://slre.sourceforge.net for detailed description.
+ *
+ * Usage example (parsing HTTP request):
+ *
+ * struct slre	slre;
+ * struct cap	captures[4 + 1];  // Number of braket pairs + 1
+ * ...
+ *
+ * slre_compile(&slre,"^(GET|POST) (\S+) HTTP/(\S+?)\r\n");
+ *
+ * if (slre_match(&slre, buf, len, captures)) {
+ *	printf("Request line length: %d\n", captures[0].len);
+ *	printf("Method: %.*s\n", captures[1].len, captures[1].ptr);
+ *	printf("URI: %.*s\n", captures[2].len, captures[2].ptr);
+ * }
+ *
+ * Supported syntax:
+ *	^		Match beginning of a buffer
+ *	$		Match end of a buffer
+ *	()		Grouping and substring capturing
+ *	[...]		Match any character from set
+ *	[^...]		Match any character but ones from set
+ *	\s		Match whitespace
+ *	\S		Match non-whitespace
+ *	\d		Match decimal digit
+ *	\r		Match carriage return
+ *	\n		Match newline
+ *	+		Match one or more times (greedy)
+ *	+?		Match one or more times (non-greedy)
+ *	*		Match zero or more times (greedy)
+ *	*?		Match zero or more times (non-greedy)
+ *	?		Match zero or once
+ *	\xDD		Match byte with hex value 0xDD
+ *	\meta		Match one of the meta character: ^$().[*+?\
+ */
+
+#ifndef SLRE_HEADER_DEFINED
+#define	SLRE_HEADER_DEFINED
+
+/*
+ * Compiled regular expression
+ */
+struct slre {
+	unsigned char	code[256];
+	unsigned char	data[256];
+	int		code_size;
+	int		data_size;
+	int		num_caps;	/* Number of bracket pairs	*/
+	int		anchored;	/* Must match from string start	*/
+	const char	*err_str;	/* Error string			*/
+};
+
+/*
+ * Captured substring
+ */
+struct cap {
+	const char	*ptr;		/* Pointer to the substring	*/
+	int		len;		/* Substring length		*/
+};
+
+/*
+ * Compile regular expression. If success, 1 is returned.
+ * If error, 0 is returned and slre.err_str points to the error message.
+ */
+int slre_compile(struct slre *, const char *re);
+
+/*
+ * Return 1 if match, 0 if no match.
+ * If `captured_substrings' array is not NULL, then it is filled with the
+ * values of captured substrings. captured_substrings[0] element is always
+ * a full matched substring. The round bracket captures start from
+ * captured_substrings[1].
+ * It is assumed that the size of captured_substrings array is enough to
+ * hold all captures. The caller function must make sure it is! So, the
+ * array_size = number_of_round_bracket_pairs + 1
+ */
+int slre_match(const struct slre *, const char *buf, int buf_len,
+	struct cap *captured_substrings);
+
+#ifdef SLRE_TEST
+void slre_dump(const struct slre *r, FILE *fp);
+#endif /* SLRE_TEST */
+#endif /* SLRE_HEADER_DEFINED */
diff --git a/lib/Makefile b/lib/Makefile
index 1bfd3ee..57a1cae 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -71,6 +71,7 @@ COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
 COBJS-y += linux_string.o
+COBJS-$(CONFIG_REGEX) += slre.o
 COBJS-y += string.o
 COBJS-y += time.o
 COBJS-$(CONFIG_BOOTP_PXE) += uuid.o
diff --git a/lib/slre.c b/lib/slre.c
new file mode 100644
index 0000000..8cdd192
--- /dev/null
+++ b/lib/slre.c
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
+ * All rights reserved
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Sergey Lyubka wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ */
+
+/*
+ * Downloaded Sat Nov  5 17:43:06 CET 2011 at
+ * http://slre.sourceforge.net/1.0/slre.c
+ */
+
+#ifdef SLRE_TEST
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <common.h>
+#include <linux/ctype.h>
+#endif /* SLRE_TEST */
+
+#include <errno.h>
+
+#include <slre.h>
+
+enum {END, BRANCH, ANY, EXACT, ANYOF, ANYBUT, OPEN, CLOSE, BOL, EOL,
+	STAR, PLUS, STARQ, PLUSQ, QUEST, SPACE, NONSPACE, DIGIT};
+
+#ifdef SLRE_TEST
+static struct {
+	const char	*name;
+	int		narg;
+	const char	*flags;
+} opcodes[] = {
+	{"END",		0, ""},		/* End of code block or program	*/
+	{"BRANCH",	2, "oo"},	/* Alternative operator, "|"	*/
+	{"ANY",		0, ""},		/* Match any character, "."	*/
+	{"EXACT",	2, "d"},	/* Match exact string		*/
+	{"ANYOF",	2, "D"},	/* Match any from set, "[]"	*/
+	{"ANYBUT",	2, "D"},	/* Match any but from set, "[^]"*/
+	{"OPEN ",	1, "i"},	/* Capture start, "("		*/
+	{"CLOSE",	1, "i"},	/* Capture end, ")"		*/
+	{"BOL",		0, ""},		/* Beginning of string, "^"	*/
+	{"EOL",		0, ""},		/* End of string, "$"		*/
+	{"STAR",	1, "o"},	/* Match zero or more times "*"	*/
+	{"PLUS",	1, "o"},	/* Match one or more times, "+"	*/
+	{"STARQ",	1, "o"},	/* Non-greedy STAR,  "*?"	*/
+	{"PLUSQ",	1, "o"},	/* Non-greedy PLUS, "+?"	*/
+	{"QUEST",	1, "o"},	/* Match zero or one time, "?"	*/
+	{"SPACE",	0, ""},		/* Match whitespace, "\s"	*/
+	{"NONSPACE",	0, ""},		/* Match non-space, "\S"	*/
+	{"DIGIT",	0, ""}		/* Match digit, "\d"		*/
+};
+#endif /* SLRE_TEST */
+
+/*
+ * Commands and operands are all unsigned char (1 byte long). All code offsets
+ * are relative to current address, and positive (always point forward). Data
+ * offsets are absolute. Commands with operands:
+ *
+ * BRANCH offset1 offset2
+ *	Try to match the code block that follows the BRANCH instruction
+ *	(code block ends with END). If no match, try to match code block that
+ *	starts at offset1. If either of these match, jump to offset2.
+ *
+ * EXACT data_offset data_length
+ *	Try to match exact string. String is recorded in data section from
+ *	data_offset, and has length data_length.
+ *
+ * OPEN capture_number
+ * CLOSE capture_number
+ *	If the user have passed 'struct cap' array for captures, OPEN
+ *	records the beginning of the matched substring (cap->ptr), CLOSE
+ *	sets the length (cap->len) for respective capture_number.
+ *
+ * STAR code_offset
+ * PLUS code_offset
+ * QUEST code_offset
+ *	*, +, ?, respectively. Try to gobble as much as possible from the
+ *	matched buffer, until code block that follows these instructions
+ *	matches. When the longest possible string is matched,
+ *	jump to code_offset
+ *
+ * STARQ, PLUSQ are non-greedy versions of STAR and PLUS.
+ */
+
+static const char *meta_chars = "|.^$*+?()[\\";
+
+#ifdef SLRE_TEST
+
+static void
+print_character_set(FILE *fp, const unsigned char *p, int len)
+{
+	int	i;
+
+	for (i = 0; i < len; i++) {
+		if (i > 0)
+			(void) fputc(',', fp);
+		if (p[i] == 0) {
+			i++;
+			if (p[i] == 0)
+				(void) fprintf(fp, "\\x%02x", p[i]);
+			else
+				(void) fprintf(fp, "%s", opcodes[p[i]].name);
+		} else if (isprint(p[i])) {
+			(void) fputc(p[i], fp);
+		} else {
+			(void) fprintf(fp, "\\x%02x", p[i]);
+		}
+	}
+}
+
+void
+slre_dump(const struct slre *r, FILE *fp)
+{
+	int	i, j, ch, op, pc;
+
+	for (pc = 0; pc < r->code_size; pc++) {
+
+		op = r->code[pc];
+		(void) fprintf(fp, "%3d %s ", pc, opcodes[op].name);
+
+		for (i = 0; opcodes[op].flags[i] != '\0'; i++)
+			switch (opcodes[op].flags[i]) {
+			case 'i':
+				(void) fprintf(fp, "%d ", r->code[pc + 1]);
+				pc++;
+				break;
+			case 'o':
+				(void) fprintf(fp, "%d ",
+				    pc + r->code[pc + 1] - i);
+				pc++;
+				break;
+			case 'D':
+				print_character_set(fp, r->data +
+				    r->code[pc + 1], r->code[pc + 2]);
+				pc += 2;
+				break;
+			case 'd':
+				(void) fputc('"', fp);
+				for (j = 0; j < r->code[pc + 2]; j++) {
+					ch = r->data[r->code[pc + 1] + j];
+					if (isprint(ch)) {
+						(void) fputc(ch, fp);
+					} else {
+						(void) fprintf(fp,
+							"\\x%02x", ch);
+					}
+				}
+				(void) fputc('"', fp);
+				pc += 2;
+				break;
+			}
+
+		(void) fputc('\n', fp);
+	}
+}
+#endif /* SLRE_TEST */
+
+static void
+set_jump_offset(struct slre *r, int pc, int offset)
+{
+	assert(offset < r->code_size);
+
+	if (r->code_size - offset > 0xff)
+		r->err_str = "Jump offset is too big";
+	else
+		r->code[pc] = (unsigned char) (r->code_size - offset);
+}
+
+static void
+emit(struct slre *r, int code)
+{
+	if (r->code_size >= (int) (sizeof(r->code) / sizeof(r->code[0])))
+		r->err_str = "RE is too long (code overflow)";
+	else
+		r->code[r->code_size++] = (unsigned char) code;
+}
+
+static void
+store_char_in_data(struct slre *r, int ch)
+{
+	if (r->data_size >= (int) sizeof(r->data))
+		r->err_str = "RE is too long (data overflow)";
+	else
+		r->data[r->data_size++] = ch;
+}
+
+static void
+exact(struct slre *r, const char **re)
+{
+	int	old_data_size = r->data_size;
+
+	while (**re != '\0' && (strchr(meta_chars, **re)) == NULL)
+		store_char_in_data(r, *(*re)++);
+
+	emit(r, EXACT);
+	emit(r, old_data_size);
+	emit(r, r->data_size - old_data_size);
+}
+
+static int
+get_escape_char(const char **re)
+{
+	int	res;
+
+	switch (*(*re)++) {
+	case 'n':
+		res = '\n';
+		break;
+	case 'r':
+		res = '\r';
+		break;
+	case 't':
+		res = '\t';
+		break;
+	case '0':
+		res = 0;
+		break;
+	case 'S':
+		res = NONSPACE << 8;
+		break;
+	case 's':
+		res = SPACE << 8;
+		break;
+	case 'd':
+		res = DIGIT << 8;
+		break;
+	default:
+		res = (*re)[-1];
+		break;
+	}
+
+	return res;
+}
+
+static void
+anyof(struct slre *r, const char **re)
+{
+	int	esc, old_data_size = r->data_size, op = ANYOF;
+
+	if (**re == '^') {
+		op = ANYBUT;
+		(*re)++;
+	}
+
+	while (**re != '\0')
+
+		switch (*(*re)++) {
+		case ']':
+			emit(r, op);
+			emit(r, old_data_size);
+			emit(r, r->data_size - old_data_size);
+			return;
+			/* NOTREACHED */
+			break;
+		case '\\':
+			esc = get_escape_char(re);
+			if ((esc & 0xff) == 0) {
+				store_char_in_data(r, 0);
+				store_char_in_data(r, esc >> 8);
+			} else {
+				store_char_in_data(r, esc);
+			}
+			break;
+		default:
+			store_char_in_data(r, (*re)[-1]);
+			break;
+		}
+
+	r->err_str = "No closing ']' bracket";
+}
+
+static void
+relocate(struct slre *r, int begin, int shift)
+{
+	emit(r, END);
+	memmove(r->code + begin + shift, r->code + begin, r->code_size - begin);
+	r->code_size += shift;
+}
+
+static void
+quantifier(struct slre *r, int prev, int op)
+{
+	if (r->code[prev] == EXACT && r->code[prev + 2] > 1) {
+		r->code[prev + 2]--;
+		emit(r, EXACT);
+		emit(r, r->code[prev + 1] + r->code[prev + 2]);
+		emit(r, 1);
+		prev = r->code_size - 3;
+	}
+	relocate(r, prev, 2);
+	r->code[prev] = op;
+	set_jump_offset(r, prev + 1, prev);
+}
+
+static void
+exact_one_char(struct slre *r, int ch)
+{
+	emit(r, EXACT);
+	emit(r, r->data_size);
+	emit(r, 1);
+	store_char_in_data(r, ch);
+}
+
+static void
+fixup_branch(struct slre *r, int fixup)
+{
+	if (fixup > 0) {
+		emit(r, END);
+		set_jump_offset(r, fixup, fixup - 2);
+	}
+}
+
+static void
+compile(struct slre *r, const char **re)
+{
+	int	op, esc, branch_start, last_op, fixup, cap_no, level;
+
+	fixup = 0;
+	level = r->num_caps;
+	branch_start = last_op = r->code_size;
+
+	for (;;)
+		switch (*(*re)++) {
+		case '\0':
+			(*re)--;
+			return;
+			/* NOTREACHED */
+			break;
+		case '^':
+			emit(r, BOL);
+			break;
+		case '$':
+			emit(r, EOL);
+			break;
+		case '.':
+			last_op = r->code_size;
+			emit(r, ANY);
+			break;
+		case '[':
+			last_op = r->code_size;
+			anyof(r, re);
+			break;
+		case '\\':
+			last_op = r->code_size;
+			esc = get_escape_char(re);
+			if (esc & 0xff00)
+				emit(r, esc >> 8);
+			else
+				exact_one_char(r, esc);
+			break;
+		case '(':
+			last_op = r->code_size;
+			cap_no = ++r->num_caps;
+			emit(r, OPEN);
+			emit(r, cap_no);
+
+			compile(r, re);
+			if (*(*re)++ != ')') {
+				r->err_str = "No closing bracket";
+				return;
+			}
+
+			emit(r, CLOSE);
+			emit(r, cap_no);
+			break;
+		case ')':
+			(*re)--;
+			fixup_branch(r, fixup);
+			if (level == 0) {
+				r->err_str = "Unbalanced brackets";
+				return;
+			}
+			return;
+			/* NOTREACHED */
+			break;
+		case '+':
+		case '*':
+			op = (*re)[-1] == '*' ? STAR : PLUS;
+			if (**re == '?') {
+				(*re)++;
+				op = op == STAR ? STARQ : PLUSQ;
+			}
+			quantifier(r, last_op, op);
+			break;
+		case '?':
+			quantifier(r, last_op, QUEST);
+			break;
+		case '|':
+			fixup_branch(r, fixup);
+			relocate(r, branch_start, 3);
+			r->code[branch_start] = BRANCH;
+			set_jump_offset(r, branch_start + 1, branch_start);
+			fixup = branch_start + 2;
+			r->code[fixup] = 0xff;
+			break;
+		default:
+			(*re)--;
+			last_op = r->code_size;
+			exact(r, re);
+			break;
+		}
+}
+
+int
+slre_compile(struct slre *r, const char *re)
+{
+	r->err_str = NULL;
+	r->code_size = r->data_size = r->num_caps = r->anchored = 0;
+
+	if (*re == '^')
+		r->anchored++;
+
+	emit(r, OPEN);	/* This will capture what matches full RE */
+	emit(r, 0);
+
+	while (*re != '\0')
+		compile(r, &re);
+
+	if (r->code[2] == BRANCH)
+		fixup_branch(r, 4);
+
+	emit(r, CLOSE);
+	emit(r, 0);
+	emit(r, END);
+
+	return (r->err_str == NULL ? 1 : 0);
+}
+
+static int match(const struct slre *, int,
+		const char *, int, int *, struct cap *);
+
+static void
+loop_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+	int	saved_offset, matched_offset;
+
+	saved_offset = matched_offset = *ofs;
+
+	while (match(r, pc + 2, s, len, ofs, NULL)) {
+		saved_offset = *ofs;
+		if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+			matched_offset = saved_offset;
+		*ofs = saved_offset;
+	}
+
+	*ofs = matched_offset;
+}
+
+static void
+loop_non_greedy(const struct slre *r, int pc, const char *s, int len, int *ofs)
+{
+	int	saved_offset = *ofs;
+
+	while (match(r, pc + 2, s, len, ofs, NULL)) {
+		saved_offset = *ofs;
+		if (match(r, pc + r->code[pc + 1], s, len, ofs, NULL))
+			break;
+	}
+
+	*ofs = saved_offset;
+}
+
+static int
+is_any_of(const unsigned char *p, int len, const char *s, int *ofs)
+{
+	int	i, ch;
+
+	ch = s[*ofs];
+
+	for (i = 0; i < len; i++)
+		if (p[i] == ch) {
+			(*ofs)++;
+			return 1;
+		}
+
+	return 0;
+}
+
+static int
+is_any_but(const unsigned char *p, int len, const char *s, int *ofs)
+{
+	int	i, ch;
+
+	ch = s[*ofs];
+
+	for (i = 0; i < len; i++) {
+		if (p[i] == ch)
+			return 0;
+	}
+
+	(*ofs)++;
+	return 1;
+}
+
+static int
+match(const struct slre *r, int pc, const char *s, int len,
+		int *ofs, struct cap *caps)
+{
+	int	n, saved_offset, res = 1;
+
+	while (res && r->code[pc] != END) {
+
+		assert(pc < r->code_size);
+		assert(pc < (int) (sizeof(r->code) / sizeof(r->code[0])));
+
+		switch (r->code[pc]) {
+		case BRANCH:
+			saved_offset = *ofs;
+			res = match(r, pc + 3, s, len, ofs, caps);
+			if (res == 0) {
+				*ofs = saved_offset;
+				res = match(r, pc + r->code[pc + 1],
+				    s, len, ofs, caps);
+			}
+			pc += r->code[pc + 2];
+			break;
+		case EXACT:
+			res = 0;
+			n = r->code[pc + 2];	/* String length */
+			if (n <= len - *ofs && !memcmp(s + *ofs, r->data +
+			    r->code[pc + 1], n)) {
+				(*ofs) += n;
+				res = 1;
+			}
+			pc += 3;
+			break;
+		case QUEST:
+			res = 1;
+			saved_offset = *ofs;
+			if (!match(r, pc + 2, s, len, ofs, caps))
+				*ofs = saved_offset;
+			pc += r->code[pc + 1];
+			break;
+		case STAR:
+			res = 1;
+			loop_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case STARQ:
+			res = 1;
+			loop_non_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case PLUS:
+			res = match(r, pc + 2, s, len, ofs, caps);
+			if (res == 0)
+				break;
+
+			loop_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case PLUSQ:
+			res = match(r, pc + 2, s, len, ofs, caps);
+			if (res == 0)
+				break;
+
+			loop_non_greedy(r, pc, s, len, ofs);
+			pc += r->code[pc + 1];
+			break;
+		case SPACE:
+			res = 0;
+			if (*ofs < len && isspace(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case NONSPACE:
+			res = 0;
+			if (*ofs < len &&
+					!isspace(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case DIGIT:
+			res = 0;
+			if (*ofs < len && isdigit(((unsigned char *)s)[*ofs])) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case ANY:
+			res = 0;
+			if (*ofs < len) {
+				(*ofs)++;
+				res = 1;
+			}
+			pc++;
+			break;
+		case ANYOF:
+			res = 0;
+			if (*ofs < len)
+				res = is_any_of(r->data + r->code[pc + 1],
+					r->code[pc + 2], s, ofs);
+			pc += 3;
+			break;
+		case ANYBUT:
+			res = 0;
+			if (*ofs < len)
+				res = is_any_but(r->data + r->code[pc + 1],
+					r->code[pc + 2], s, ofs);
+			pc += 3;
+			break;
+		case BOL:
+			res = *ofs == 0 ? 1 : 0;
+			pc++;
+			break;
+		case EOL:
+			res = *ofs == len ? 1 : 0;
+			pc++;
+			break;
+		case OPEN:
+			if (caps != NULL)
+				caps[r->code[pc + 1]].ptr = s + *ofs;
+			pc += 2;
+			break;
+		case CLOSE:
+			if (caps != NULL)
+				caps[r->code[pc + 1]].len = (s + *ofs) -
+				    caps[r->code[pc + 1]].ptr;
+			pc += 2;
+			break;
+		case END:
+			pc++;
+			break;
+		default:
+			printf("unknown cmd (%d) at %d\n", r->code[pc], pc);
+			assert(0);
+			break;
+		}
+	}
+
+	return res;
+}
+
+int
+slre_match(const struct slre *r, const char *buf, int len,
+		struct cap *caps)
+{
+	int	i, ofs = 0, res = 0;
+
+	if (r->anchored) {
+		res = match(r, 0, buf, len, &ofs, caps);
+	} else {
+		for (i = 0; i < len && res == 0; i++) {
+			ofs = i;
+			res = match(r, 0, buf, len, &ofs, caps);
+		}
+	}
+
+	return res;
+}
+
+#ifdef SLRE_TEST
+#define N_CAPS	5
+
+int main(int argc, char *argv[])
+{
+	struct slre	slre;
+	struct cap	caps[N_CAPS];
+	unsigned char	data[1 * 1024 * 1024];
+	FILE		*fp;
+	int		i, res, len;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s 'slre' <file>\n", argv[0]);
+		return 1;
+	}
+
+	fp = fopen(argv[2], "rb");
+	if (fp == NULL) {
+		fprintf(stderr, "Error: cannot open %s:%s\n",
+			argv[2], strerror(errno));
+		return 1;
+	}
+
+	if (!slre_compile(&slre, argv[1])) {
+		fprintf(stderr, "Error compiling slre: %s\n", slre.err_str);
+		return 1;
+	}
+	
+	slre_dump(&slre, stderr);
+
+	while (fgets(data, sizeof(data), fp) != NULL) {
+		len = strlen(data);
+
+		if ((len > 0) && (data[len-1] == '\n')) {
+			data[len-1] = '\0';
+			--len;
+		}
+
+		printf("Data = \"%s\"\n", data);
+
+		(void) memset(caps, 0, sizeof(caps));
+
+		res = 0;
+
+		res = slre_match(&slre, data, len, caps);
+		printf("Result [%d]: %d\n", i, res);
+
+		for (i = 0; i < N_CAPS; i++) {
+			if (caps[i].len > 0) {
+				printf("Substring %d: len=%d  [%.*s]\n", i,
+					caps[i].len,
+					caps[i].len, caps[i].ptr);
+			}
+		}
+		printf("----------------------------------------------------\n");
+	}
+	(void) fclose(fp);
+
+	return 0;
+}
+#endif /* SLRE_TEST */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 05/11] "env grep" - add support for regular expression matches
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (3 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 04/11] Add SLRE - Super Light Regular Expression library Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 06/11] setexpr: simplify code, improve help message Wolfgang Denk
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

When CONFIG_REGEX is enabled, the new option "-e" becomes available
which causes regular expression matches to be used.  This allows for
example things like these:

- print all MAC addresses:

	=> env grep -e eth.*addr
	eth1addr=00:10:ec:80:c5:15
	ethaddr=00:10:ec:00:c5:15

- print all variables that have at least 2 colons in their value:

	=> env grep -v -e :.*:
	addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off
	panic=1
	eth1addr=00:10:ec:80:c5:15
	ethaddr=00:10:ec:00:c5:15
	ver=U-Boot 2013.04-rc1-00289-g497746b-dirty (Mar 22 2013 - 12:50:25)

etc.

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- Fix trailing whitespace error

 common/cmd_nvedit.c | 29 +++++++++++++++++++++++------
 include/search.h    |  5 +++--
 lib/hashtable.c     | 29 ++++++++++++++++++++++++++---
 3 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 923e113..299d5d0 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -163,12 +163,13 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		       int argc, char * const argv[])
 {
 	char *res = NULL;
-	int len, grep_flags;
+	int len, grep_how, grep_what;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	grep_flags = H_MATCH_BOTH;
+	grep_how  = H_MATCH_SUBSTR;	/* default: substring search	*/
+	grep_what = H_MATCH_BOTH;	/* default: grep names and values */
 
 	while (argc > 1 && **(argv + 1) == '-') {
 		char *arg = *++argv;
@@ -176,14 +177,19 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		--argc;
 		while (*++arg) {
 			switch (*arg) {
+#ifdef CONFIG_REGEX
+			case 'e':		/* use regex matching */
+				grep_how  = H_MATCH_REGEX;
+				break;
+#endif
 			case 'n':		/* grep for name */
-				grep_flags = H_MATCH_KEY;
+				grep_what = H_MATCH_KEY;
 				break;
 			case 'v':		/* grep for value */
-				grep_flags = H_MATCH_DATA;
+				grep_what = H_MATCH_DATA;
 				break;
 			case 'b':		/* grep for both */
-				grep_flags = H_MATCH_BOTH;
+				grep_what = H_MATCH_BOTH;
 				break;
 			case '-':
 				goto DONE;
@@ -195,7 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 
 DONE:
 	len = hexport_r(&env_htab, '\n',
-			flag | grep_flags | H_MATCH_SUBSTR,
+			flag | grep_what | grep_how,
 			&res, 0, argc, argv);
 
 	if (len > 0) {
@@ -1132,8 +1138,12 @@ static char env_help_text[] =
 	"env flags - print variables that have non-default flags\n"
 #endif
 #if defined(CONFIG_CMD_GREPENV)
+#ifdef CONFIG_REGEX
+	"env grep [-e] [-n | -v | -b] string [...] - search environment\n"
+#else
 	"env grep [-n | -v | -b] string [...] - search environment\n"
 #endif
+#endif
 #if defined(CONFIG_CMD_IMPORTENV)
 	"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
 #endif
@@ -1179,8 +1189,15 @@ U_BOOT_CMD_COMPLETE(
 U_BOOT_CMD_COMPLETE(
 	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
 	"search environment variables",
+#ifdef CONFIG_REGEX
+	"[-e] [-n | -v | -b] string ...\n"
+#else
 	"[-n | -v | -b] string ...\n"
+#endif
 	"    - list environment name=value pairs matching 'string'\n"
+#ifdef CONFIG_REGEX
+	"      \"-e\": enable regular expressions;\n"
+#endif
 	"      \"-n\": search variable names; \"-v\": search values;\n"
 	"      \"-b\": search both names and values (default)",
 	var_complete
diff --git a/include/search.h b/include/search.h
index d06a201..d9ac8df 100644
--- a/include/search.h
+++ b/include/search.h
@@ -129,7 +129,8 @@ extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
 #define H_MATCH_DATA	(1 << 5) /* search/grep data = variable values	     */
 #define H_MATCH_BOTH	(H_MATCH_KEY | H_MATCH_DATA) /* search/grep both     */
 #define H_MATCH_IDENT	(1 << 6) /* search for indentical strings	     */
-#define H_MATCH_SUBSTR  (1 << 7) /* search for substring matches	     */
-#define H_MATCH_METHOD	(H_MATCH_IDENT | H_MATCH_SUBSTR)
+#define H_MATCH_SUBSTR	(1 << 7) /* search for substring matches	     */
+#define H_MATCH_REGEX	(1 << 8) /* search for regular expression matches    */
+#define H_MATCH_METHOD	(H_MATCH_IDENT | H_MATCH_SUBSTR | H_MATCH_REGEX)
 
 #endif /* search.h */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 1703941..6050dd0 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -57,6 +57,7 @@
 #include <env_callback.h>
 #include <env_flags.h>
 #include <search.h>
+#include <slre.h>
 
 /*
  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -540,7 +541,7 @@ static int cmpkey(const void *p1, const void *p2)
 	return (strcmp(e1->key, e2->key));
 }
 
-static int match_string(int flag, const char *str, const char *pat)
+static int match_string(int flag, const char *str, const char *pat, void *priv)
 {
 	switch (flag & H_MATCH_METHOD) {
 	case H_MATCH_IDENT:
@@ -551,6 +552,17 @@ static int match_string(int flag, const char *str, const char *pat)
 		if (strstr(str, pat))
 			return 1;
 		break;
+#ifdef CONFIG_REGEX
+	case H_MATCH_REGEX:
+		{
+			struct slre *slrep = (struct slre *)priv;
+			struct cap caps[slrep->num_caps + 2];
+
+			if (slre_match(slrep, str, strlen(str), caps))
+				return 1;
+		}
+		break;
+#endif
 	default:
 		printf("## ERROR: unsupported match method: 0x%02x\n",
 			flag & H_MATCH_METHOD);
@@ -563,14 +575,25 @@ static int match_entry(ENTRY *ep, int flag,
 		 int argc, char * const argv[])
 {
 	int arg;
+	void *priv = NULL;
 
 	for (arg = 1; arg < argc; ++arg) {
+#ifdef CONFIG_REGEX
+		struct slre slre;
+
+		if (slre_compile(&slre, argv[arg]) == 0) {
+			printf("Error compiling regex: %s\n", slre.err_str);
+			return 0;
+		}
+
+		priv = (void *)&slre;
+#endif
 		if (flag & H_MATCH_KEY) {
-			if (match_string(flag, ep->key, argv[arg]))
+			if (match_string(flag, ep->key, argv[arg], priv))
 				return 1;
 		}
 		if (flag & H_MATCH_DATA) {
-			if (match_string(flag, ep->data, argv[arg]))
+			if (match_string(flag, ep->data, argv[arg], priv))
 				return 1;
 		}
 	}
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 06/11] setexpr: simplify code, improve help message
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (4 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 05/11] "env grep" - add support for regular expression matches Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 07/11] setexpr: add regex substring matching and substitution Wolfgang Denk
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Simplify the argument checking for the "setexpr" command.  This is
done mainly to make future extensions easier.

Also improve the help message for the one argument version of the
command - this does not "load an address", but a value, which in
this context may be a plain number or a pointer dereference.

Signed-off-by: Wolfgang Denk <wd@denx.de>
---
Changes in v2: None

 common/cmd_setexpr.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c
index 7a38e94..ccd87f4 100644
--- a/common/cmd_setexpr.c
+++ b/common/cmd_setexpr.c
@@ -56,22 +56,26 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	ulong value;
 	int w;
 
-	/* Validate arguments */
-	if (argc != 5 && argc != 3)
-		return CMD_RET_USAGE;
-	if (argc == 5 && strlen(argv[3]) != 1)
+	if (argc < 3)
 		return CMD_RET_USAGE;
 
 	w = cmd_get_data_size(argv[0], 4);
 
 	a = get_arg(argv[2], w);
 
+	/* plain assignment: "setexpr name value" */
 	if (argc == 3) {
 		setenv_hex(argv[1], a);
-
 		return 0;
 	}
 
+	/* standard operators: "setexpr name val1 op val2" */
+	if (argc != 5)
+		return CMD_RET_USAGE;
+
+	if (strlen(argv[3]) != 1)
+		return CMD_RET_USAGE;
+
 	b = get_arg(argv[4], w);
 
 	switch (argv[3][0]) {
@@ -117,6 +121,6 @@ U_BOOT_CMD(
 	"      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
 	"      size argument is only meaningful if value1 and/or value2 are\n"
 	"      memory addresses (*)\n"
-	"setexpr[.b, .w, .l] name *value\n"
-	"    - load a memory address into a variable"
+	"setexpr[.b, .w, .l] name [*]value\n"
+	"    - load a value into a variable"
 );
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 07/11] setexpr: add regex substring matching and substitution
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (5 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 06/11] setexpr: simplify code, improve help message Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup Wolfgang Denk
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Add "setexpr name gsub r s [t]" and "setexpr name sub r s [t]"
commands which implement substring matching for the regular
expression <r> in the string <t>, and substitution of the string <s>.
The result is assigned to the environment variable <name>.  If <t> is
not supplied, the previous value of <name> is used instead.  "gsub"
performs global substitution, while "sub" will replace only the first
substring.

Both commands are closely modeled after the gawk functions with the
same names.

Examples:

- Generate broadcast address by substituting the last two numbers of
  the IP address by "255.255":

  	=> print ipaddr
	ipaddr=192.168.1.104
	=> setexpr broadcast sub "(.*\\.).*\\..*" "\\1255.255" $ipaddr
	broadcast=192.168.255.255

- Depending on keyboard configuration (German vs. US keyboard) a
  barcode scanner may initialize the MAC address as C0:E5:4E:02:06:DC
  or as C0>E5>4E>02>06>DC.  Make sure we always have a correct value:

	=> print ethaddr
	ethaddr=C0>E5>4E>02>06>DC
	=> setexpr ethaddr gsub > :
	ethaddr=C0:E5:4E:02:06:DC

- Do the same, but substitute one step at a time in a loop until no
  futher matches:

	=> setenv ethaddr C0>E5>4E>02>06>DC
	=> while setexpr ethaddr sub > :
	> do
	> echo -----
	> done
	ethaddr=C0:E5>4E>02>06>DC
	-----
	ethaddr=C0:E5:4E>02>06>DC
	-----
	ethaddr=C0:E5:4E:02>06>DC
	-----
	ethaddr=C0:E5:4E:02:06>DC
	-----
	ethaddr=C0:E5:4E:02:06:DC
	-----
	C0:E5:4E:02:06:DC: No match
	=> print ethaddr
	ethaddr=C0:E5:4E:02:06:DC

etc.

To enable this feature, the CONFIG_REGEX option has to be defined in
the board config file.

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- fix "No space is necessary after a cast" checks
- fix "space prohibited before semicolon" and "space required after
  that ';'" errors (but I consider the result less readable :-( )
- Note: the remaining warnings ("line over 80 characters") and checks
  ("Alignment should match open parenthesis") are intentionally left
  as is.

 common/cmd_setexpr.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 277 insertions(+), 3 deletions(-)

diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c
index ccd87f4..93cb255 100644
--- a/common/cmd_setexpr.c
+++ b/common/cmd_setexpr.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2013 Wolfgang Denk <wd@denx.de>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -50,13 +51,263 @@ static ulong get_arg(char *s, int w)
 	}
 }
 
+#ifdef CONFIG_REGEX
+
+#include <slre.h>
+
+#define SLRE_BUFSZ	16384
+#define SLRE_PATSZ	4096
+
+/*
+ * memstr - Find the first substring in memory
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ *
+ * Similar to and based on strstr(),
+ * but strings do not need to be NUL terminated.
+ */
+static char *memstr(const char *s1, int l1, const char *s2, int l2)
+{
+	if (!l2)
+		return (char *)s1;
+
+	while (l1 >= l2) {
+		l1--;
+		if (!memcmp(s1, s2, l2))
+			return (char *)s1;
+		s1++;
+	}
+	return NULL;
+}
+
+static char *substitute(char *string,	/* string buffer */
+			int *slen,	/* current string length */
+			int ssize,	/* string bufer size */
+			const char *old,/* old (replaced) string */
+			int olen,	/* length of old string */
+			const char *new,/* new (replacement) string */
+			int nlen)	/* length of new string */
+{
+	char *p = memstr(string, *slen, old, olen);
+
+	if (p == NULL)
+		return NULL;
+
+	debug("## Match at pos %ld: match len %d, subst len %d\n",
+		(long)(p - string), olen, nlen);
+
+	/* make sure replacement matches */
+	if (*slen + nlen - olen > ssize) {
+		printf("## error: substitution buffer overflow\n");
+		return NULL;
+	}
+
+	/* move tail if needed */
+	if (olen != nlen) {
+		int tail, len;
+
+		len = (olen > nlen) ? olen : nlen;
+
+		tail = ssize - (p + len - string);
+
+		debug("## tail len %d\n", tail);
+
+		memmove(p + nlen, p + olen, tail);
+	}
+
+	/* insert substitue */
+	memcpy(p, new, nlen);
+
+	*slen += nlen - olen;
+
+	return p + nlen;
+}
+
+/*
+ * Perform regex operations on a environment variable
+ *
+ * Returns 0 if OK, 1 in case of errors.
+ */
+static int regex_sub(const char *name,
+	const char *r, const char *s, const char *t,
+	int global)
+{
+	struct slre slre;
+	char data[SLRE_BUFSZ];
+	char *datap = data;
+	const char *value;
+	int res, len, nlen, loop;
+
+	if (name == NULL)
+		return 1;
+
+	if (slre_compile(&slre, r) == 0) {
+		printf("Error compiling regex: %s\n", slre.err_str);
+		return 1;
+	}
+
+	if (t == NULL) {
+		value = getenv(name);
+
+		if (value == NULL) {
+			printf("## Error: variable \"%s\" not defined\n", name);
+			return 1;
+		}
+		t = value;
+	}
+
+	debug("REGEX on %s=%s\n", name, t);
+	debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n",
+		r, s ? s : "<NULL>", global);
+
+	len = strlen(t);
+	if (len + 1 > SLRE_BUFSZ) {
+		printf("## error: subst buffer overflow: have %d, need %d\n",
+			SLRE_BUFSZ, len + 1);
+		return 1;
+	}
+
+	strcpy(data, t);
+
+	if (s == NULL)
+		nlen = 0;
+	else
+		nlen = strlen(s);
+
+	for (loop = 0;; loop++) {
+		struct cap caps[slre.num_caps + 2];
+		char nbuf[SLRE_PATSZ];
+		const char *old;
+		char *np;
+		int i, olen;
+
+		(void) memset(caps, 0, sizeof(caps));
+
+		res = slre_match(&slre, datap, len, caps);
+
+		debug("Result: %d\n", res);
+
+		for (i = 0; i < slre.num_caps; i++) {
+			if (caps[i].len > 0) {
+				debug("Substring %d: [%.*s]\n", i,
+					caps[i].len, caps[i].ptr);
+			}
+		}
+
+		if (res == 0) {
+			if (loop == 0) {
+				printf("%s: No match\n", t);
+				return 1;
+			} else {
+				break;
+			}
+		}
+
+		debug("## MATCH ## %s\n", data);
+
+		if (s == NULL) {
+			printf("%s=%s\n", name, t);
+			return 1;
+		}
+
+		old = caps[0].ptr;
+		olen = caps[0].len;
+
+		if (nlen + 1 >= SLRE_PATSZ) {
+			printf("## error: pattern buffer overflow: have %d, need %d\n",
+				SLRE_BUFSZ, nlen + 1);
+			return 1;
+		}
+		strcpy(nbuf, s);
+
+		debug("## SUBST(1) ## %s\n", nbuf);
+
+		/*
+		 * Handle back references
+		 *
+		 * Support for \0 ... \9, where \0 is the
+		 * whole matched pattern (similar to &).
+		 *
+		 * Implementation is a bit simpleminded as
+		 * backrefs are substituted sequentially, one
+		 * by one.  This will lead to somewhat
+		 * unexpected results if the replacement
+		 * strings contain any \N strings then then
+		 * may get substitued, too.  We accept this
+		 * restriction for the sake of simplicity.
+		 */
+		for (i = 0; i < 10; ++i) {
+			char backref[2] = {
+				'\\',
+				'0',
+			};
+
+			if (caps[i].len == 0)
+				break;
+
+			backref[1] += i;
+
+			debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n",
+				i,
+				2, backref,
+				caps[i].len, caps[i].ptr,
+				nbuf);
+
+			for (np = nbuf;;) {
+				char *p = memstr(np, nlen, backref, 2);
+
+				if (p == NULL)
+					break;
+
+				np = substitute(np, &nlen,
+					SLRE_PATSZ,
+					backref, 2,
+					caps[i].ptr, caps[i].len);
+
+				if (np == NULL)
+					return 1;
+			}
+		}
+		debug("## SUBST(2) ## %s\n", nbuf);
+
+		datap = substitute(datap, &len, SLRE_BUFSZ,
+				old, olen,
+				nbuf, nlen);
+
+		if (datap == NULL)
+			return 1;
+
+		debug("## REMAINDER: %s\n", datap);
+
+		debug("## RESULT: %s\n", data);
+
+		if (!global)
+			break;
+	}
+	debug("## FINAL (now setenv()) :  %s\n", data);
+
+	printf("%s=%s\n", name, data);
+
+	return setenv(name, data);
+}
+#endif
+
 static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong a, b;
 	ulong value;
 	int w;
 
-	if (argc < 3)
+	/*
+	 * We take 3, 5, or 6 arguments:
+	 * 3 : setexpr name value
+	 * 5 : setexpr name val1 op val2
+	 *     setexpr name [g]sub r s
+	 * 6 : setexpr name [g]sub r s t
+	 */
+
+	/* > 6 already tested by max command args */
+	if ((argc < 3) || (argc == 4))
 		return CMD_RET_USAGE;
 
 	w = cmd_get_data_size(argv[0], 4);
@@ -69,6 +320,19 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return 0;
 	}
 
+	/* 5 or 6 args (6 args only with [g]sub) */
+#ifdef CONFIG_REGEX
+	/*
+	 * rexep handling: "setexpr name [g]sub r s [t]"
+	 * with 5 args, "t" will be NULL
+	 */
+	if (strcmp(argv[2], "gsub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 1);
+
+	if (strcmp(argv[2], "sub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 0);
+#endif
+
 	/* standard operators: "setexpr name val1 op val2" */
 	if (argc != 5)
 		return CMD_RET_USAGE;
@@ -114,13 +378,23 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
-	setexpr, 5, 0, do_setexpr,
+	setexpr, 6, 0, do_setexpr,
 	"set environment variable as the result of eval expression",
 	"[.b, .w, .l] name [*]value1 <op> [*]value2\n"
 	"    - set environment variable 'name' to the result of the evaluated\n"
-	"      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
+	"      expression specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
 	"      size argument is only meaningful if value1 and/or value2 are\n"
 	"      memory addresses (*)\n"
 	"setexpr[.b, .w, .l] name [*]value\n"
 	"    - load a value into a variable"
+#ifdef CONFIG_REGEX
+	"\n"
+	"setexpr name gsub r s [t]\n"
+	"    - For each substring matching the regular expression <r> in the\n"
+	"      string <t>, substitute the string <s>.  The result is\n"
+	"      assigned to <name>.  If <t> is not supplied, use the old\n"
+	"      value of <name>\n"
+	"setexpr name sub r s [t]\n"
+	"    - Just like gsub(), but replace only the first matching substring"
+#endif
 );
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (6 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 07/11] setexpr: add regex substring matching and substitution Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24 12:08   ` Marek Vasut
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 09/11] m28evk: enable "env grep" and regexp support Wolfgang Denk
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Change all "#define<TAB>" sequences into "#define<SPACE>"

Signed-off-by: Wolfgang Denk <wd@denx.de>

---
Changes in v2:
- Do the white space cleanup globally, and as separate patch

 include/configs/m28evk.h | 256 +++++++++++++++++++++++------------------------
 1 file changed, 128 insertions(+), 128 deletions(-)

diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index f2725cc..95eb735 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -23,71 +23,71 @@
 /*
  * SoC configurations
  */
-#define	CONFIG_MX28				/* i.MX28 SoC */
-#define	CONFIG_MXS_GPIO				/* GPIO control */
-#define	CONFIG_SYS_HZ		1000		/* Ticks per second */
+#define CONFIG_MX28				/* i.MX28 SoC */
+#define CONFIG_MXS_GPIO				/* GPIO control */
+#define CONFIG_SYS_HZ		1000		/* Ticks per second */
 
 /*
  * Define M28EVK machine type by hand until it lands in mach-types
  */
-#define	MACH_TYPE_M28EVK	3613
+#define MACH_TYPE_M28EVK	3613
 
-#define	CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
+#define CONFIG_MACH_TYPE	MACH_TYPE_M28EVK
 
 #include <asm/arch/regs-base.h>
 
-#define	CONFIG_SYS_NO_FLASH
-#define	CONFIG_BOARD_EARLY_INIT_F
-#define	CONFIG_ARCH_MISC_INIT
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_ARCH_MISC_INIT
 
 /*
  * SPL
  */
-#define	CONFIG_SPL
-#define	CONFIG_SPL_NO_CPU_SUPPORT_CODE
-#define	CONFIG_SPL_START_S_PATH		"arch/arm/cpu/arm926ejs/mxs"
-#define	CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
-#define	CONFIG_SPL_LIBCOMMON_SUPPORT
-#define	CONFIG_SPL_LIBGENERIC_SUPPORT
-#define	CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL
+#define CONFIG_SPL_NO_CPU_SUPPORT_CODE
+#define CONFIG_SPL_START_S_PATH		"arch/arm/cpu/arm926ejs/mxs"
+#define CONFIG_SPL_LDSCRIPT	"arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds"
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
 
 /*
  * U-Boot Commands
  */
 #include <config_cmd_default.h>
-#define	CONFIG_DISPLAY_CPUINFO
-#define	CONFIG_DOS_PARTITION
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DOS_PARTITION
 
-#define	CONFIG_CMD_CACHE
-#define	CONFIG_CMD_DATE
-#define	CONFIG_CMD_DHCP
-#define	CONFIG_CMD_EEPROM
-#define	CONFIG_CMD_EXT2
-#define	CONFIG_CMD_FAT
-#define	CONFIG_CMD_GPIO
-#define	CONFIG_CMD_I2C
-#define	CONFIG_CMD_MII
-#define	CONFIG_CMD_MMC
-#define	CONFIG_CMD_NAND
-#define	CONFIG_CMD_NET
-#define	CONFIG_CMD_NFS
-#define	CONFIG_CMD_PING
-#define	CONFIG_CMD_SETEXPR
-#define	CONFIG_CMD_SF
-#define	CONFIG_CMD_SPI
-#define	CONFIG_CMD_USB
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SETEXPR
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_USB
 
 /*
  * Memory configurations
  */
-#define	CONFIG_NR_DRAM_BANKS		1		/* 1 bank of DRAM */
-#define	PHYS_SDRAM_1			0x40000000	/* Base address */
-#define	PHYS_SDRAM_1_SIZE		0x20000000	/* Max 512 MB RAM */
-#define	CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
-#define	CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
-#define	CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
-#define	CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
-#define	CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+#define CONFIG_NR_DRAM_BANKS		1		/* 1 bank of DRAM */
+#define PHYS_SDRAM_1			0x40000000	/* Base address */
+#define PHYS_SDRAM_1_SIZE		0x20000000	/* Max 512 MB RAM */
+#define CONFIG_SYS_MALLOC_LEN		0x00400000	/* 4 MB for malloc */
+#define CONFIG_SYS_GBL_DATA_SIZE	128		/* Initial data */
+#define CONFIG_SYS_MEMTEST_START	0x40000000	/* Memtest start adr */
+#define CONFIG_SYS_MEMTEST_END		0x40400000	/* 4 MB RAM test */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
 /* Point initial SP in SRAM so SPL can use it too. */
 
 #define CONFIG_SYS_INIT_RAM_ADDR	0x00000000
@@ -102,42 +102,42 @@
  * strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
  * binary. In case there was more of this mess, 0x100 bytes are skipped.
  */
-#define	CONFIG_SYS_TEXT_BASE		0x40000100
+#define CONFIG_SYS_TEXT_BASE		0x40000100
 
 /*
  * U-Boot general configurations
  */
-#define	CONFIG_SYS_LONGHELP
-#define	CONFIG_SYS_PROMPT	"=> "
-#define	CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
-#define	CONFIG_SYS_PBSIZE	\
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_PROMPT	"=> "
+#define CONFIG_SYS_CBSIZE	1024		/* Console I/O buffer size */
+#define CONFIG_SYS_PBSIZE	\
 	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
 						/* Print buffer size */
-#define	CONFIG_SYS_MAXARGS	32		/* Max number of command args */
-#define	CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_MAXARGS	32		/* Max number of command args */
+#define CONFIG_SYS_BARGSIZE	CONFIG_SYS_CBSIZE
 						/* Boot argument buffer size */
-#define	CONFIG_VERSION_VARIABLE			/* U-BOOT version */
-#define	CONFIG_AUTO_COMPLETE			/* Command auto complete */
-#define	CONFIG_CMDLINE_EDITING			/* Command history etc */
-#define	CONFIG_SYS_HUSH_PARSER
+#define CONFIG_VERSION_VARIABLE			/* U-BOOT version */
+#define CONFIG_AUTO_COMPLETE			/* Command auto complete */
+#define CONFIG_CMDLINE_EDITING			/* Command history etc */
+#define CONFIG_SYS_HUSH_PARSER
 
 /*
  * Serial Driver
  */
-#define	CONFIG_PL011_SERIAL
-#define	CONFIG_PL011_CLOCK		24000000
-#define	CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
-#define	CONFIG_CONS_INDEX		0
-#define	CONFIG_BAUDRATE			115200	/* Default baud rate */
+#define CONFIG_PL011_SERIAL
+#define CONFIG_PL011_CLOCK		24000000
+#define CONFIG_PL01x_PORTS		{ (void *)MXS_UARTDBG_BASE }
+#define CONFIG_CONS_INDEX		0
+#define CONFIG_BAUDRATE			115200	/* Default baud rate */
 
 /*
  * MMC Driver
  */
 #ifdef	CONFIG_CMD_MMC
-#define	CONFIG_MMC
-#define	CONFIG_BOUNCE_BUFFER
-#define	CONFIG_GENERIC_MMC
-#define	CONFIG_MXS_MMC
+#define CONFIG_MMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MXS_MMC
 #endif
 
 /*
@@ -148,31 +148,31 @@
 /*
  * NAND
  */
-#define	CONFIG_ENV_SIZE			(16 * 1024)
+#define CONFIG_ENV_SIZE			(16 * 1024)
 #ifdef	CONFIG_CMD_NAND
-#define	CONFIG_NAND_MXS
-#define	CONFIG_SYS_MAX_NAND_DEVICE	1
-#define	CONFIG_SYS_NAND_BASE		0x60000000
-#define	CONFIG_SYS_NAND_5_ADDR_CYCLE
+#define CONFIG_NAND_MXS
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		0x60000000
+#define CONFIG_SYS_NAND_5_ADDR_CYCLE
 
 /* Environment is in NAND */
-#define	CONFIG_ENV_IS_IN_NAND
-#define	CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
-#define	CONFIG_ENV_SECT_SIZE		(128 * 1024)
-#define	CONFIG_ENV_RANGE		(512 * 1024)
-#define	CONFIG_ENV_OFFSET		0x300000
-#define	CONFIG_ENV_OFFSET_REDUND	\
+#define CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SIZE_REDUND		CONFIG_ENV_SIZE
+#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define CONFIG_ENV_RANGE		(512 * 1024)
+#define CONFIG_ENV_OFFSET		0x300000
+#define CONFIG_ENV_OFFSET_REDUND	\
 		(CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE)
 
-#define	CONFIG_CMD_UBI
-#define	CONFIG_CMD_UBIFS
-#define	CONFIG_CMD_MTDPARTS
-#define	CONFIG_RBTREE
-#define	CONFIG_LZO
-#define	CONFIG_MTD_DEVICE
-#define	CONFIG_MTD_PARTITIONS
-#define	MTDIDS_DEFAULT			"nand0=gpmi-nand"
-#define	MTDPARTS_DEFAULT			\
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define MTDIDS_DEFAULT			"nand0=gpmi-nand"
+#define MTDPARTS_DEFAULT			\
 	"mtdparts=gpmi-nand:"			\
 		"3m(bootloader)ro,"		\
 		"512k(environment),"		\
@@ -182,34 +182,34 @@
 		"8m(ramdisk),"			\
 		"-(filesystem)"
 #else
-#define	CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_IS_NOWHERE
 #endif
 
 /*
  * Ethernet on SOC (FEC)
  */
 #ifdef	CONFIG_CMD_NET
-#define	CONFIG_ETHPRIME			"FEC0"
-#define	CONFIG_FEC_MXC
-#define	CONFIG_MII
-#define	CONFIG_FEC_XCV_TYPE		RMII
+#define CONFIG_ETHPRIME			"FEC0"
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define CONFIG_FEC_XCV_TYPE		RMII
 #endif
 
 /*
  * I2C
  */
 #ifdef	CONFIG_CMD_I2C
-#define	CONFIG_I2C_MXS
-#define	CONFIG_HARD_I2C
-#define	CONFIG_SYS_I2C_SPEED		400000
+#define CONFIG_I2C_MXS
+#define CONFIG_HARD_I2C
+#define CONFIG_SYS_I2C_SPEED		400000
 #endif
 
 /*
  * EEPROM
  */
 #ifdef	CONFIG_CMD_EEPROM
-#define	CONFIG_SYS_I2C_MULTI_EEPROMS
-#define	CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
+#define CONFIG_SYS_I2C_MULTI_EEPROMS
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	2
 #endif
 
 /*
@@ -217,13 +217,13 @@
  */
 #ifdef	CONFIG_CMD_DATE
 /* Use the internal RTC in the MXS chip */
-#define	CONFIG_RTC_INTERNAL
+#define CONFIG_RTC_INTERNAL
 #ifdef	CONFIG_RTC_INTERNAL
-#define	CONFIG_RTC_MXS
+#define CONFIG_RTC_MXS
 #else
-#define	CONFIG_RTC_M41T62
-#define	CONFIG_SYS_I2C_RTC_ADDR		0x68
-#define	CONFIG_SYS_M41T11_BASE_YEAR	2000
+#define CONFIG_RTC_M41T62
+#define CONFIG_SYS_I2C_RTC_ADDR		0x68
+#define CONFIG_SYS_M41T11_BASE_YEAR	2000
 #endif
 #endif
 
@@ -231,59 +231,59 @@
  * USB
  */
 #ifdef	CONFIG_CMD_USB
-#define	CONFIG_USB_EHCI
-#define	CONFIG_USB_EHCI_MXS
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MXS
 #define CONFIG_EHCI_MXS_PORT0
 #define CONFIG_EHCI_MXS_PORT1
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
-#define	CONFIG_EHCI_IS_TDI
-#define	CONFIG_USB_STORAGE
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
 #endif
 
 /*
  * SPI
  */
 #ifdef	CONFIG_CMD_SPI
-#define	CONFIG_HARD_SPI
-#define	CONFIG_MXS_SPI
-#define	CONFIG_SPI_HALF_DUPLEX
-#define	CONFIG_DEFAULT_SPI_BUS		2
-#define	CONFIG_DEFAULT_SPI_CS		0
-#define	CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
+#define CONFIG_HARD_SPI
+#define CONFIG_MXS_SPI
+#define CONFIG_SPI_HALF_DUPLEX
+#define CONFIG_DEFAULT_SPI_BUS		2
+#define CONFIG_DEFAULT_SPI_CS		0
+#define CONFIG_DEFAULT_SPI_MODE		SPI_MODE_0
 
 /* SPI FLASH */
 #ifdef	CONFIG_CMD_SF
-#define	CONFIG_SPI_FLASH
-#define	CONFIG_SPI_FLASH_STMICRO
-#define	CONFIG_SF_DEFAULT_BUS		2
-#define	CONFIG_SF_DEFAULT_CS		0
-#define	CONFIG_SF_DEFAULT_SPEED		40000000
-#define	CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SF_DEFAULT_BUS		2
+#define CONFIG_SF_DEFAULT_CS		0
+#define CONFIG_SF_DEFAULT_SPEED		40000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
 
-#define	CONFIG_ENV_SPI_BUS		2
-#define	CONFIG_ENV_SPI_CS		0
-#define	CONFIG_ENV_SPI_MAX_HZ		40000000
-#define	CONFIG_ENV_SPI_MODE		SPI_MODE_0
+#define CONFIG_ENV_SPI_BUS		2
+#define CONFIG_ENV_SPI_CS		0
+#define CONFIG_ENV_SPI_MAX_HZ		40000000
+#define CONFIG_ENV_SPI_MODE		SPI_MODE_0
 #endif
 #endif
 
 /*
  * Boot Linux
  */
-#define	CONFIG_CMDLINE_TAG
-#define	CONFIG_SETUP_MEMORY_TAGS
-#define	CONFIG_BOOTDELAY	3
-#define	CONFIG_BOOTFILE		"uImage"
-#define	CONFIG_BOOTARGS		"console=ttyAMA0,115200n8 "
-#define	CONFIG_BOOTCOMMAND	"run bootcmd_net"
-#define	CONFIG_LOADADDR		0x42000000
-#define	CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
-#define	CONFIG_OF_LIBFDT
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_BOOTDELAY	3
+#define CONFIG_BOOTFILE		"uImage"
+#define CONFIG_BOOTARGS		"console=ttyAMA0,115200n8 "
+#define CONFIG_BOOTCOMMAND	"run bootcmd_net"
+#define CONFIG_LOADADDR		0x42000000
+#define CONFIG_SYS_LOAD_ADDR	CONFIG_LOADADDR
+#define CONFIG_OF_LIBFDT
 
 /*
  * Extra Environments
  */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
+#define CONFIG_EXTRA_ENV_SETTINGS					\
 	"update_nand_full_filename=u-boot.nand\0"			\
 	"update_nand_firmware_filename=u-boot.sb\0"			\
 	"update_sd_firmware_filename=u-boot.sd\0"			\
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 09/11] m28evk: enable "env grep" and regexp support
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (7 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup Wolfgang Denk
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Wolfgang Denk <wd@denx.de>

Conflicts:
	include/configs/m28evk.h
---
Changes in v2: None

 include/configs/m28evk.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 95eb735..4ce4058 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -65,6 +65,7 @@
 #define CONFIG_CMD_EXT2
 #define CONFIG_CMD_FAT
 #define CONFIG_CMD_GPIO
+#define CONFIG_CMD_GREPENV
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_MMC
@@ -77,6 +78,8 @@
 #define CONFIG_CMD_SPI
 #define CONFIG_CMD_USB
 
+#define CONFIG_REGEX			/* Enable regular expression support */
+
 /*
  * Memory configurations
  */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (8 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 09/11] m28evk: enable "env grep" and regexp support Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-04-02  7:34   ` Stefan Roese
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex Wolfgang Denk
  2013-05-02 16:06 ` [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Tom Rini
  11 siblings, 1 reply; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Align some comments.

Signed-off-by: Wolfgang Denk <wd@denx.de>
---
Changes in v2: None

 include/configs/amcc-common.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/configs/amcc-common.h b/include/configs/amcc-common.h
index f2f522d..928b31f 100644
--- a/include/configs/amcc-common.h
+++ b/include/configs/amcc-common.h
@@ -108,12 +108,12 @@
 #define CONFIG_MX_CYCLIC		/* enable mdc/mwc commands      */
 #define CONFIG_ZERO_BOOTDELAY_CHECK	/* check for keypress on bootdelay==0 */
 #define CONFIG_VERSION_VARIABLE 	/* include version env variable */
-#define CONFIG_SYS_CONSOLE_INFO_QUIET		/* don't print console @ startup*/
+#define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup*/
 
-#define CONFIG_SYS_HUSH_PARSER			/* Use the HUSH parser		*/
+#define CONFIG_SYS_HUSH_PARSER		/* Use the HUSH parser		*/
 
 #define CONFIG_LOADS_ECHO		/* echo on for serial download	*/
-#define CONFIG_SYS_LOADS_BAUD_CHANGE		/* allow baudrate change	*/
+#define CONFIG_SYS_LOADS_BAUD_CHANGE	/* allow baudrate change	*/
 
 /*
  * BOOTP options
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex.
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (9 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup Wolfgang Denk
@ 2013-03-24  9:50 ` Wolfgang Denk
  2013-04-02  7:34   ` Stefan Roese
  2013-05-02 16:06 ` [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Tom Rini
  11 siblings, 1 reply; 16+ messages in thread
From: Wolfgang Denk @ 2013-03-24  9:50 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Wolfgang Denk <wd@denx.de>
---
Changes in v2: None

 include/configs/amcc-common.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/configs/amcc-common.h b/include/configs/amcc-common.h
index 928b31f..80e5735 100644
--- a/include/configs/amcc-common.h
+++ b/include/configs/amcc-common.h
@@ -71,6 +71,7 @@
 #define CONFIG_CMD_DIAG
 #define CONFIG_CMD_EEPROM
 #define CONFIG_CMD_ELF
+#define CONFIG_CMD_GREPENV
 #define CONFIG_CMD_I2C
 #define CONFIG_CMD_IRQ
 #define CONFIG_CMD_MII
@@ -78,6 +79,7 @@
 #define CONFIG_CMD_NFS
 #define CONFIG_CMD_PING
 #define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_SETEXPR
 
 /*
  * Miscellaneous configurable options
@@ -115,6 +117,7 @@
 #define CONFIG_LOADS_ECHO		/* echo on for serial download	*/
 #define CONFIG_SYS_LOADS_BAUD_CHANGE	/* allow baudrate change	*/
 
+#define CONFIG_REGEX			/* Enable regular expression support */
 /*
  * BOOTP options
  */
-- 
1.8.1.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup Wolfgang Denk
@ 2013-03-24 12:08   ` Marek Vasut
  0 siblings, 0 replies; 16+ messages in thread
From: Marek Vasut @ 2013-03-24 12:08 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Change all "#define<TAB>" sequences into "#define<SPACE>"
> 
> Signed-off-by: Wolfgang Denk <wd@denx.de>

Acked-by: Marek Vasut <marex@denx.de>

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup Wolfgang Denk
@ 2013-04-02  7:34   ` Stefan Roese
  0 siblings, 0 replies; 16+ messages in thread
From: Stefan Roese @ 2013-04-02  7:34 UTC (permalink / raw)
  To: u-boot

On 24.03.2013 10:50, Wolfgang Denk wrote:
> Align some comments.
> 
> Signed-off-by: Wolfgang Denk <wd@denx.de>

Acked-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex.
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex Wolfgang Denk
@ 2013-04-02  7:34   ` Stefan Roese
  0 siblings, 0 replies; 16+ messages in thread
From: Stefan Roese @ 2013-04-02  7:34 UTC (permalink / raw)
  To: u-boot

On 24.03.2013 10:50, Wolfgang Denk wrote:
> Signed-off-by: Wolfgang Denk <wd@denx.de>

Acked-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support
  2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
                   ` (10 preceding siblings ...)
  2013-03-24  9:50 ` [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex Wolfgang Denk
@ 2013-05-02 16:06 ` Tom Rini
  11 siblings, 0 replies; 16+ messages in thread
From: Tom Rini @ 2013-05-02 16:06 UTC (permalink / raw)
  To: u-boot

On Sun, Mar 24, 2013 at 10:50:27AM +0100, Wolfgang Denk wrote:

> The following patch series adds the SLRE "Super Light Regular
> Expression" library and uses this to add regex support for
> the "env grep" (aka "grepenv") command, and new functions (or
> operators?) "gsub" and "sub" to the "setexpr" command.
> 
> The rework to "env grep" also fixed a few bugs (which caused it to
> dump always _all_ environment variables on some systems), and adds
> the capability to grep in either the variable name, or the value, or
> in both (the old version always did the latter).  Instead of special
> functions we now use common code (i. e. hexport_r()) for the variable
> look-up, which gives us sorted output as a free additional benefit.
> 
> This allows to do things like
> 
> - print all MAC addresses:
> 
> 	=> env grep -e eth.*addr
> 	eth1addr=00:10:ec:80:c5:15
> 	ethaddr=00:10:ec:00:c5:15
> 
> - print all variables that have at least 2 colons in their value:
> 
> 	=> env grep -v -e :.*:
> 	addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1
> 	eth1addr=00:10:ec:80:c5:15
> 	ethaddr=00:10:ec:00:c5:15
> 	ver=U-Boot 2013.04-rc1-00289-g497746b-dirty (Mar 22 2013 - 12:50:25)
> 
> - Generate broadcast address by substituting the last two numbers of
>   the IP address by "255.255":
> 
>   	=> print ipaddr
> 	ipaddr=192.168.1.104
> 	=> setexpr broadcast sub "(.*\\.).*\\..*" "\\1255.255" $ipaddr
> 	broadcast=192.168.255.255
> 
> - Depending on keyboard configuration (German vs. US keyboard) a
>   bar code scanner may initialize the MAC address as C0:E5:4E:02:06:DC
>   or as C0>E5>4E>02>06>DC.  Make sure we always have a correct value:
> 
>   	=> print ethaddr
> 	ethaddr=C0>E5>4E>02>06>DC
> 	=> setexpr ethaddr gsub > :
> 	ethaddr=C0:E5:4E:02:06:DC
> 
> etc.
> 
> Regex support can be enabled by defining  CONFIG_REGEX  in the board
> config file.
> 
> Notes:
> 
> - This patch series has been compile-tested (and found to be clean
>   with ELDK v5.3) on all of the following boards:
> 
>   ARM: m28evk
> 
>   PPC4xx: acadia bamboo bluestone bubinga canyonlands dlvision-10g
>   dlvision ebony gdppc440etx icon intip io io64 iocon katmai kilauea
>   luan makalu neo ocotea redwood sequoia t3corp taihu taishan walnut
>   yosemite yucca
> 
> - Runtime / functional testing has been done mostly on PPC (Sequoia
>   board).
> 
> 
> Changes in v2:
> - fixed trailing whitespace errors
> - Note 1: The "line over 80 characters" warning will NOT be fixed due
>   to the "never break user-visible strings" rule.
> - Note 2: The "Alignment should match open parenthesis" check will NOT
>   be fixed due to the "indent by TABs only" rule.
> - Fix ERROR: "foo * bar" should be "foo *bar" errors
> - Fix trailing whitespace error
> - Note: the "Alignment should match open parenthesis" check will not
>   be fixed due to the "indent always byy TABs" rule.
> - no changes; most of this is imported code and is intentionally left
>   as is
> - the "Alignment should match open parenthesis" check is left due to
>   the "indent only by TABs" rule
> - the "line over 80 characters" warning is left due to the "never
>   break user-visible strings" rule
> - Fix trailing whitespace error
> - fix "No space is necessary after a cast" checks
> - fix "space prohibited before semicolon" and "space required after
>   that ';'" errors (but I onsider the result less readable :-( )
> - Note: the remaining warnings ("line over 80 characters") and checks
>   ("Alignment should match open parenthesis") are intentionally left
>   as is.
> - Do the white space cleanup globally, and as separate patch
> 
> Wolfgang Denk (11):
>   hashtable: preparations to use hexport_r() for "env grep"
>   "env grep" - reimplement command using hexport_r()
>   "env grep" - add options to grep in name, value, or both.
>   Add SLRE - Super Light Regular Expression library
>   "env grep" - add support for regular expression matches
>   setexpr: simplify code, improve help message
>   setexpr: add regex substring matching and substitution
>   m28evk: white space cleanup
>   m28evk: enable "env grep" and regexp support
>   amcc-common.h: minor white space cleanup
>   amcc-common.h: enable support for "env grep", "setexpr", and regex.
> 
>  README                        |   7 +
>  common/cmd_nvedit.c           |  87 +++--
>  common/cmd_setexpr.c          | 296 ++++++++++++++++-
>  include/configs/amcc-common.h |   9 +-
>  include/configs/m28evk.h      | 259 +++++++--------
>  include/search.h              |  15 +-
>  include/slre.h                | 100 ++++++
>  lib/Makefile                  |   1 +
>  lib/hashtable.c               |  93 ++++--
>  lib/slre.c                    | 724 ++++++++++++++++++++++++++++++++++++++++++
>  10 files changed, 1391 insertions(+), 200 deletions(-)
>  create mode 100644 include/slre.h
>  create mode 100644 lib/slre.c

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130502/a7aa76a2/attachment.pgp>

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-05-02 16:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-24  9:50 [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 01/11] hashtable: preparations to use hexport_r() for "env grep" Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 02/11] "env grep" - reimplement command using hexport_r() Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 03/11] "env grep" - add options to grep in name, value, or both Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 04/11] Add SLRE - Super Light Regular Expression library Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 05/11] "env grep" - add support for regular expression matches Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 06/11] setexpr: simplify code, improve help message Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 07/11] setexpr: add regex substring matching and substitution Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 08/11] m28evk: white space cleanup Wolfgang Denk
2013-03-24 12:08   ` Marek Vasut
2013-03-24  9:50 ` [U-Boot] [PATCH v2 09/11] m28evk: enable "env grep" and regexp support Wolfgang Denk
2013-03-24  9:50 ` [U-Boot] [PATCH v2 10/11] amcc-common.h: minor white space cleanup Wolfgang Denk
2013-04-02  7:34   ` Stefan Roese
2013-03-24  9:50 ` [U-Boot] [PATCH v2 11/11] amcc-common.h: enable support for "env grep", "setexpr", and regex Wolfgang Denk
2013-04-02  7:34   ` Stefan Roese
2013-05-02 16:06 ` [U-Boot] [PATCH v2 0/11] Add Regular Expressions Support Tom Rini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox