--- memory.c.orig	2011-02-14 16:43:57.000000000 -0700
+++ memory.c	2011-02-23 14:05:52.000000000 -0700
@@ -18,6 +18,7 @@
 
 #include "defs.h"
 #include <sys/mman.h>
+#include <ctype.h>
 
 struct meminfo {           /* general purpose memory information structure */
         ulong cache;       /* used by the various memory searching/dumping */
@@ -71,6 +72,48 @@ struct meminfo {           /* general pu
 	ulong container;
 };
 
+/*
+ * Search modes
+ */
+
+#define SEARCH_ULONG	(0)
+#define SEARCH_UINT	(1)
+#define SEARCH_USHORT	(2)
+#define SEARCH_CHARS	(3)
+#define SEARCH_DEFAULT	(SEARCH_ULONG)
+
+/* search mode information */
+struct searchinfo {
+	int mode;
+	int vcnt;
+	union {
+		/* default ulong search */
+		struct {
+			ulong value[MAXARGS];
+			ulong mask;
+		} s_ulong;
+
+		/* uint search */
+		struct {
+			uint value[MAXARGS];
+			uint mask;
+		} s_uint;
+
+		/* ushort search */
+		struct {
+			ushort value[MAXARGS];
+			ushort mask;
+		} s_ushort;
+
+		/* string (chars) search */
+		struct {
+			char *value[MAXARGS];
+			int len[MAXARGS];
+			int started_flag;  /* string search needs history */
+		} s_chars;
+	} s_parms;
+};
+
 static char *memtype_string(int, int);
 static char *error_handle_string(ulong);
 static void dump_mem_map(struct meminfo *);
@@ -132,8 +175,16 @@ static int dump_page_lists(struct meminf
 static void dump_kmeminfo(void);
 static int page_to_phys(ulong, physaddr_t *); 
 static void display_memory(ulonglong, long, ulong, int); 
-static void search_virtual(ulong, ulong, ulong, int, ulong *, int);
-static void search_physical(ulonglong, ulonglong, ulong, ulong *, int);
+static ulong search_ulong(ulong *, ulong, int, struct searchinfo *);
+static ulong search_uint(ulong *, ulong, int, struct searchinfo *);
+static ulong search_ushort(ulong *, ulong, int, struct searchinfo *);
+static ulong search_chars(ulong *, ulong, int, struct searchinfo *);
+static ulonglong search_ulong_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_uint_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_ushort_p(ulong *, ulonglong, int, struct searchinfo *);
+static ulonglong search_chars_p(ulong *, ulonglong, int, struct searchinfo *);
+static void search_virtual(ulong, ulong, int, struct searchinfo *);
+static void search_physical(ulonglong, ulonglong, struct searchinfo *);
 static int next_upage(struct task_context *, ulong, ulong *);
 static int next_kpage(ulong, ulong *);
 static int next_physpage(ulonglong, ulonglong *);
@@ -11322,6 +11373,8 @@ generic_get_kvaddr_ranges(struct vaddr_r
  *  space".  For processors with ambiguous user/kernel address spaces,
  *  -u or -k must be used (with or without -s) as a differentiator.
  */
+
+
 void
 cmd_search(void)
 {
@@ -11331,7 +11384,7 @@ cmd_search(void)
 	ulong uvaddr_start, uvaddr_end;
 	ulong kvaddr_start, kvaddr_end, range_start, range_end;
 	int sflag, Kflag, Vflag, pflag;
-	ulong value_array[MAXARGS];
+	struct searchinfo searchinfo;
 	struct syment *sp;
 	struct node_table *nt;
 	struct vaddr_range vaddr_ranges[MAX_KVADDR_RANGES];
@@ -11343,7 +11396,7 @@ cmd_search(void)
 	kvaddr_start = kvaddr_end = 0;
 	uvaddr_start = UNINITIALIZED;
 	uvaddr_end = COMMON_VADDR_SPACE() ? (ulong)(-1) : machdep->kvbase;
-	BZERO(value_array, sizeof(ulong) * MAXARGS);
+	BZERO(&searchinfo, sizeof(struct searchinfo));
 
 	vrp = &vaddr_ranges[0];
 	ranges = machdep->get_kvaddr_ranges(vrp);
@@ -11374,7 +11427,9 @@ cmd_search(void)
 		}
 	}
 
-        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:")) != EOF) {
+	searchinfo.mode = SEARCH_ULONG;	/* default search */
+
+        while ((c = getopt(argcnt, args, "l:ukKVps:e:v:m:hwc")) != EOF) {
                 switch(c)
                 {
 		case 'u':
@@ -11454,6 +11509,27 @@ cmd_search(void)
                         mask = htol(optarg, FAULT_ON_ERROR, NULL);
                         break;
 
+		case 'h':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search mode with \"h\"\n");
+			searchinfo.mode = SEARCH_USHORT;
+			break;
+
+		case 'w':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search mode with \"w\"\n");
+			searchinfo.mode = SEARCH_UINT;
+			break;
+
+		case 'c':
+			if (searchinfo.mode != SEARCH_DEFAULT)
+				error(INFO, "WARNING: overriding previously"
+					" set search type with \"c\"\n");
+			searchinfo.mode = SEARCH_CHARS;
+			break;
+
                 default:
                         argerrs++;
                         break;
@@ -11583,28 +11659,76 @@ cmd_search(void)
 		break;
 	}
 
-	c = 0;
+	if (mask) {
+		switch (searchinfo.mode) 
+		{
+		case SEARCH_ULONG:
+			searchinfo.s_parms.s_ulong.mask = mask;
+			break;
+		case SEARCH_UINT:
+			searchinfo.s_parms.s_uint.mask = mask;
+			break;
+		case SEARCH_USHORT:
+			searchinfo.s_parms.s_ushort.mask = mask;
+			break;
+		case SEARCH_CHARS:
+			error(INFO, "mask ignored on string search\n");
+			break;
+		}
+	}
+			
+		
+	searchinfo.vcnt = 0;
 	while (args[optind]) {
-		value_array[c] = htol(args[optind], FAULT_ON_ERROR, NULL);
-		c++;
+		switch (searchinfo.mode) 
+		{
+		case SEARCH_ULONG:
+			searchinfo.s_parms.s_ulong.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_UINT:
+			searchinfo.s_parms.s_uint.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_USHORT:
+			searchinfo.s_parms.s_ushort.value[searchinfo.vcnt] = 
+				htol(args[optind], FAULT_ON_ERROR, NULL);
+			searchinfo.vcnt++;
+			break;
+		case SEARCH_CHARS:
+			/* parser can deliver empty strings */
+			if (strlen(args[optind])) { 
+				searchinfo.s_parms.s_chars.value[searchinfo.vcnt] = 
+					args[optind];
+				searchinfo.s_parms.s_chars.len[searchinfo.vcnt] = 
+					strlen(args[optind]);
+				searchinfo.vcnt++;
+			}
+			break;
+		}
 		optind++;
 	}
 
+	if (!searchinfo.vcnt)
+                cmd_usage(pc->curcmd, SYNOPSIS);
+	
 	switch (memtype)
 	{
 	case PHYSADDR:
-		search_physical(start, end, mask, value_array, c);
+		search_physical(start, end, &searchinfo);
 		break;
 
 	case UVADDR:
-		search_virtual(uvaddr_start, uvaddr_end, mask, memtype, 
-			value_array, c);
+		search_virtual(uvaddr_start, uvaddr_end, memtype, 
+			&searchinfo);
 		break;
 
 	case KVADDR:
 		if (XEN_HYPER_MODE()) {
-			search_virtual(kvaddr_start, kvaddr_end, mask, 
-				memtype, value_array, c);
+			search_virtual(kvaddr_start, kvaddr_end, memtype, 
+				&searchinfo);
 			break;
 		}
 
@@ -11637,8 +11761,8 @@ cmd_search(void)
 				break;
 			}
 
-			search_virtual(range_start, range_end, mask,
-                                        memtype, value_array, c);
+			search_virtual(range_start, range_end, memtype,
+					 &searchinfo);
 		}
 		break;
 	}
@@ -11650,10 +11774,306 @@ cmd_search(void)
 
 #define SEARCHMASK(X) ((X) | mask) 
 
+static ulong
+search_ulong(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	ulong mask = si->s_parms.s_ulong.mask;
+	for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j]))
+				fprintf(fp, "%lx: %lx\n", addr, *bufptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_ulong_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	ulong mask = si->s_parms.s_ulong.mask;
+	for (i = 0; i < longcnt; i++, bufptr++, addr += sizeof(long)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*bufptr) == SEARCHMASK(si->s_parms.s_ulong.value[j]))
+				fprintf(fp, "%llx: %lx\n", addr, *bufptr);
+                }
+	}
+	return addr;
+}
+
+static ulong
+search_uint(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(int));
+	uint *ptr = (uint *)bufptr;
+	uint mask = si->s_parms.s_uint.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j]))
+				fprintf(fp, "%lx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_uint_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(int));
+	uint *ptr = (uint *)bufptr;
+	uint mask = si->s_parms.s_uint.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(int)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_uint.value[j]))
+				fprintf(fp, "%llx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+static ulong
+search_ushort(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(short));
+	ushort *ptr = (ushort *)bufptr;
+	ushort mask = si->s_parms.s_ushort.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j]))
+				fprintf(fp, "%lx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/* phys search uses ulonglong address representation */
+static ulonglong
+search_ushort_p(ulong *bufptr, ulonglong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int cnt = longcnt * (sizeof(long)/sizeof(short));
+	ushort *ptr = (ushort *)bufptr;
+	ushort mask = si->s_parms.s_ushort.mask;
+
+	for (i = 0; i < cnt; i++, ptr++, addr += sizeof(short)) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (SEARCHMASK(*ptr) == SEARCHMASK(si->s_parms.s_ushort.value[j]))
+				fprintf(fp, "%llx: %x\n", addr, *ptr);
+                }
+	}
+	return addr;
+}
+
+/*
+ * String search "memory" to remember possible matches that cross
+ * page (or search buffer) boundaries.
+ * The cross_match zone is the last strlen-1 chars of the page for
+ * each of the possible targets.
+ */
+struct cross_match {
+	int cnt;	/* possible hits in the cross_match zone */
+	ulong addr; 	/* starting addr of crossing match zone for this target */
+	ulonglong addr_p; /* for physical search */
+	char hit[BUFSIZE]; /* array of hit locations in the crossing match zone */
+			/* This should really be the much-smaller MAXARGLEN, but
+			 * no one seems to be enforcing that in the parser.
+			 */
+} cross[MAXARGS];
+
+ulong cross_match_next_addr; /* the expected starting value of the next page */
+ulong cross_match_next_addr_p; /* the expected starting value of the next physical page */
+	
+#define CHARS_CTX 56
+
 static void
-search_virtual(ulong start, ulong end, ulong mask, int memtype, ulong *value, int vcnt)
+report_match(ulong addr, char *ptr1, int len1, char *ptr2, int len2)
+{
+	int i;
+	fprintf(fp, "%lx: ", addr);
+	for (i = 0; i < len1; i++) {
+		if (isprint(ptr1[i]))
+			fprintf(fp, "%c", ptr1[i]);
+		else
+			fprintf(fp, ".");
+	}
+	for (i = 0; i < len2; i++) {
+		if (isprint(ptr2[i]))
+			fprintf(fp, "%c", ptr2[i]);
+		else
+			fprintf(fp, ".");
+	}
+	fprintf(fp, "\n");	
+}
+	
+static ulong
+search_chars(ulong *bufptr, ulong addr, int longcnt, struct searchinfo *si)
+{
+	int i, j;
+	int len;
+	char *target;
+	int charcnt = longcnt * sizeof(long);
+	char *ptr = (char *)bufptr;
+
+	/* is this the first page of this search? */
+	if (si->s_parms.s_chars.started_flag == 0) {
+		for (j = 0; j < si->vcnt; j++) {
+			cross[j].cnt = 0;   /* no hits */
+		}
+		cross_match_next_addr = (ulong)-1; /* no page match for first page */
+		si->s_parms.s_chars.started_flag++;
+	}
+
+	if (cross_match_next_addr == addr) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (cross[j].cnt) {
+				target = si->s_parms.s_chars.value[j];
+				len = si->s_parms.s_chars.len[j];
+				for (i = 0; i < len - 1; i++) {
+					if (cross[j].hit[i] &&
+						!strncmp(&target[len - 1 - i], ptr, i + 1)) 
+							report_match(cross[j].addr + i, 
+									target, len,
+									&ptr[i+1], 
+									CHARS_CTX - len);
+				}
+			}
+		}
+	}
+
+	/* set up for possible cross matches on this page */
+	cross_match_next_addr = addr + charcnt;
+	for (j = 0; j < si->vcnt; j++) {
+		len = si->s_parms.s_chars.len[j];
+		cross[j].cnt = 0;
+		cross[j].addr = addr + longcnt * sizeof(long) - (len - 1);
+		for (i = 0; i < len - 1; i++) 
+			cross[j].hit[i] = 0;
+	}
+	
+	for (i = 0; i < charcnt; i++, ptr++, addr++) {
+		for (j = 0; j < si->vcnt; j++) {
+			target = si->s_parms.s_chars.value[j];
+			len = si->s_parms.s_chars.len[j];
+			if ((i + len) > charcnt) {
+				/* check for cross match */
+				if (!strncmp(target, ptr, charcnt - i)) {
+					cross[j].hit[len + i - charcnt - 1] = 1;
+					cross[j].cnt++;
+				} 
+			} else {
+				if (!strncmp(target, ptr, len)) {
+					int slen = CHARS_CTX;
+					if ((i + CHARS_CTX) > charcnt) 
+						slen = charcnt - i;
+					report_match(addr, ptr, slen, (char *)0, 0);
+				}
+			}
+		}
+	}
+	return addr;
+}
+						
+
+static void
+report_match_p(ulonglong addr, char *ptr1, int len1, char *ptr2, int len2)
+{
+	int i;
+	fprintf(fp, "%llx: ", addr);
+	for (i = 0; i < len1; i++) {
+		if (isprint(ptr1[i]))
+			fprintf(fp, "%c", ptr1[i]);
+		else
+			fprintf(fp, ".");
+	}
+	for (i = 0; i < len2; i++) {
+		if (isprint(ptr2[i]))
+			fprintf(fp, "%c", ptr2[i]);
+		else
+			fprintf(fp, ".");
+	}
+	fprintf(fp, "\n");	
+}
+
+static ulonglong
+search_chars_p(ulong *bufptr, ulonglong addr_p, int longcnt, struct searchinfo *si)
 {
 	int i, j;
+	int len;
+	char *target;
+	int charcnt = longcnt * sizeof(long);
+	char *ptr = (char *)bufptr;
+
+	/* is this the first page of this search? */
+	if (si->s_parms.s_chars.started_flag == 0) {
+		for (j = 0; j < si->vcnt; j++) {
+			cross[j].cnt = 0;   /* no hits */
+		}
+		cross_match_next_addr_p = (ulonglong)-1; /* no page match for first page */
+		si->s_parms.s_chars.started_flag++;
+	}
+
+	if (cross_match_next_addr_p == addr_p) {
+		for (j = 0; j < si->vcnt; j++) {
+			if (cross[j].cnt) {
+				target = si->s_parms.s_chars.value[j];
+				len = si->s_parms.s_chars.len[j];
+				for (i = 0; i < len - 1; i++) {
+					if (cross[j].hit[i] &&
+						!strncmp(&target[len - 1 - i], ptr, i + 1)) 
+							report_match_p(cross[j].addr_p + i, 
+									target, len,
+									&ptr[i+1], 
+									CHARS_CTX - len);
+				}
+			}
+		}
+	}
+
+	/* set up for possible cross matches on this page */
+	cross_match_next_addr_p = addr_p + charcnt;
+	for (j = 0; j < si->vcnt; j++) {
+		len = si->s_parms.s_chars.len[j];
+		cross[j].cnt = 0;
+		cross[j].addr_p = addr_p + longcnt * sizeof(long) - (len - 1);
+		for (i = 0; i < len - 1; i++) 
+			cross[j].hit[i] = 0;
+	}
+	
+	for (i = 0; i < charcnt; i++, ptr++, addr_p++) {
+		for (j = 0; j < si->vcnt; j++) {
+			target = si->s_parms.s_chars.value[j];
+			len = si->s_parms.s_chars.len[j];
+			if ((i + len) > charcnt) {
+				/* check for cross match */
+				if (!strncmp(target, ptr, charcnt - i)) {
+					cross[j].hit[len + i - charcnt - 1] = 1;
+					cross[j].cnt++;
+				} 
+			} else {
+				if (!strncmp(target, ptr, len)) {
+					int slen = CHARS_CTX;
+					if ((i + CHARS_CTX) > charcnt) 
+						slen = charcnt - i;
+					report_match_p(addr_p, ptr, slen, (char *)0, 0);
+				}
+			}
+		}
+	}
+	return addr_p;
+}
+
+static void
+search_virtual(ulong start, ulong end, int memtype, struct searchinfo *si)
+{
 	ulong pp, next, *ubp;
 	int wordcnt, lastpage;
 	ulong page;
@@ -11738,11 +12158,24 @@ virtual:
 		} else
 			wordcnt = (PAGESIZE() - (next - pp))/sizeof(long);
 
-		for (i = 0; i < wordcnt; i++, ubp++, next += sizeof(long)) {
-			for (j = 0; j < vcnt; j++) {
-				if (SEARCHMASK(*ubp) == SEARCHMASK(value[j])) 
-					fprintf(fp, "%lx: %lx\n", next, *ubp);
-			}
+		switch (si->mode)
+		{
+		case SEARCH_ULONG:
+			next = search_ulong(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_UINT:
+			next = search_uint(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_USHORT:
+			next = search_ushort(ubp, next, wordcnt, si);
+			break;
+		case SEARCH_CHARS:
+			next = search_chars(ubp, next, wordcnt, si);
+			break;
+		default:
+			/* unimplemented search type */
+			next += wordcnt * (sizeof(long));
+			break;
 		}
 
 		if (CRASHDEBUG(1))
@@ -11764,9 +12197,8 @@ done:
 
 
 static void
-search_physical(ulonglong start_in, ulonglong end_in, ulong mask, ulong *value, int vcnt)
+search_physical(ulonglong start_in, ulonglong end_in, struct searchinfo *si)
 {
-	int i, j;
 	ulong *ubp;
 	int wordcnt, lastpage;
 	ulonglong pnext, ppp;
@@ -11815,12 +12247,25 @@ search_physical(ulonglong start_in, ulon
                 } else
                         wordcnt = (PAGESIZE() - (pnext - ppp))/sizeof(long);
 
-                for (i = 0; i < wordcnt; i++, ubp++, pnext += sizeof(long)) {
-                        for (j = 0; j < vcnt; j++) {
-                                if (SEARCHMASK(*ubp) == SEARCHMASK(value[j]))
-					fprintf(fp, "%llx: %lx\n", pnext, *ubp);
-                        }
-                }
+		switch (si->mode)
+		{
+		case SEARCH_ULONG:
+			pnext = search_ulong_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_UINT:
+			pnext = search_uint_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_USHORT:
+			pnext = search_ushort_p(ubp, pnext, wordcnt, si);
+			break;
+		case SEARCH_CHARS:
+			pnext = search_chars_p(ubp, pnext, wordcnt, si);
+			break;
+		default:
+			/* unimplemented search type */
+			pnext += wordcnt * (sizeof(long));
+			break;
+		}
 
 		ppp += PAGESIZE();
 	}
--- help.c.orig	2011-02-18 12:11:54.000000000 -0700
+++ help.c	2011-02-23 14:48:05.000000000 -0700
@@ -2100,7 +2100,8 @@ NULL               
 char *help_search[] = {
 "seach",
 "search memory",
-"[-s start | -[kKV] | -u | -p ] [-e end | -l length] [-m mask] value ...",
+"[-s start] [ -[kKV] | -u | -p ] [-e end | -l length] [-m mask]"
+"                 [ -c | -w | -h ] value ...",
 "  This command searches for a given value within a range of user virtual, kernel",
 "  virtual, or physical memory space.  If no end nor length value is entered, ",
 "  then the search stops at the end of user virtual, kernel virtual, or physical",
@@ -2131,7 +2132,10 @@ char *help_search[] = {
 "             appropriate for the memory type specified.",
 "  -l length  Length in bytes of address range to search.",
 "    -m mask  Ignore the bits that are set in the hexadecimal mask value.",
-"      value  Search for this hexadecimal value.",
+"         -c  Search for character string values instead of unsigned longs",
+"         -w  Search for unsigned hexadecimal ints instead of unsigned longs",
+"         -h  Search for unsigned hexadecimal shorts instead of unsigned longs",
+"      value  Search for a hexadecimal long unless modified by -c, -w, or -h",
 " ",
 "  If -k, -K, -V, -u or -p are not used, then the search defaults to kernel",
 "  virtual address space.  The starting address must be long-word aligned. ",
@@ -2197,6 +2201,28 @@ char *help_search[] = {
 "    48579a4: babe2600",
 "    4864a68: babe2600",
 "    ...",
+"\n  Search physical memory for all instances of 0xbabe occuring in the",
+"  upper 16 bits of each 32-bit word on a 64-bit system:\n",
+"    %s> search -p babe0000 -m ffff -w",
+"    102e248: babe1174",
+"    11d2f90: babe813d",
+"    122d3ad70: babe6b27",
+"    124d8cd30: babe3dc8",
+"    124d8eefc: babef981",
+"    124d8f060: babe3dc8",
+"    124d8f17c: babefc81",
+"    ...",
+"\n  Search kernel memory for all instances of 32-bit value 0xbabe1174",
+"  on a 64-bit system:\n",
+"    %s> search -k -w babe1174",
+"    ffff88000102e248: babe1174",
+"    ffffffff8102e248: babe1174",
+"\n  Search kernel memory for two strings:\n",
+"    %s> search -k -c \"can\'t allocate memory\" \"Failure to\"",
+"    ffff8800013ddec1: can\'t allocate memory for key lists..<3>%%s %%s: error con",
+"    ffff8801258be748: Failure to install fence: %%d..<3>[drm:%%s] *ERROR* Failed",
+"    ffff880125f07ec9: can\'t allocate memory..<3>ACPI: Invalid data..Too many d",
+"    ffffffff813ddec1: can\'t allocate memory for key lists..<3>%%s %%s: error con",
 NULL               
 };
 
--- tools.c.orig	2011-02-18 12:19:16.000000000 -0700
+++ tools.c	2011-02-18 12:21:11.000000000 -0700
@@ -182,7 +182,7 @@ parse_line(char *str, char *argv[])
 	                i++;
 	            }
 
-                    if (str[i] == '(') {     
+                    if (!string && str[i] == '(') {     
                         expression = TRUE;
                     }
 	
