Hex search made more robust
Pavel Roskin
proski at gnu.org
Mon Jul 9 23:20:48 UTC 2001
Hello!
I have reimplemented the parser used to process user input in the hex
search routine in the internal viewer. I'm using two sscanf()s - not sure
if it's optimal, but it works better than the old parser. Using the "%i"
format in sscanf() means that not only hexadecimal, but also decimal and
octal numbers are supported.
I've also implemented some minimal error reporting - there was none. Now
an average hacker should be able to figure out how to use it without
reading the code.
The patch is a bit hard to read, but it hopefully gives the idea.
Have fun translating "Invalid hex search expression" into your favorite
language :-)
ChangeLog:
* view.c (hex_search): Reimplement parser using sscanf. Add
support for decimal and octal numbers. Add error reporting.
Allocate buffer dynamically.
_______________________________________________
--- view.c
+++ view.c
@@ -1671,78 +1671,64 @@ block_search (WView *view, char *buffer,
return -1;
}
-/* States of our funny recognizer */
-enum {
- normal,
- inside_quotes,
- zero,
- hex1,
- hex2,
- oct1
-};
-
-/* This routine doesn't report all the user mistakes, it just ignores them */
+/*
+ * Search in the hex mode. Supported input:
+ * - numbers (oct, dec, hex). Each of them matches one byte.
+ * - strings in double quotes. Matches exactly without quotes.
+ */
static void
hex_search (WView *view, char *text)
{
- char buffer [120]; /* Where we hold the information */
- int i, block_len;
- int v = 0;
+ char *buffer; /* Where we hold the information */
long pos; /* Where did we found the string */
- char *p; /* Temporary */
- int state = normal; /* Initial state of the micro-scanner */
-
+ int i = 0;
+ int block_len = 0;
+ int parse_error = 0;
+
+ /* buffer will never be longer that text */
+ buffer = g_new (char, strlen (text));
+
/* First convert the string to a stream of bytes */
- for (i = block_len = 0; text [i] && block_len < sizeof (buffer); i++){
- switch (state){
- case inside_quotes:
- if (text [i] == '"')
- state = normal;
- else
- buffer [block_len++] = text [i];
- break;
-
- case normal:
- if (text [i] == '"'){
- state = inside_quotes;
- break;
- }
- if (text [i] == '0'){
- state = zero;
- break;
- }
- if (text [i] == 'x'){
- state = hex1;
+ while (text [i]) {
+ int val;
+ int ptr;
+
+ /* %i matches octal, decimal, and hexadecimal numbers */
+ if (sscanf (text + i, "%i%n", &val, &ptr) > 0) {
+ /* Allow signed and unsigned char in the user input */
+ if (val < -128 || val > 255) {
+ parse_error = 1;
break;
}
- break;
- case zero:
- if (text [i] == 'x')
- state = hex1;
- break;
-
- case hex1:
- v = 0;
- text [i] = toupper (text [i]);
- if ((p = strchr (hex_char, text [i])) != 0){
- v = (p - hex_char) << 4;
- state = hex2;
- }
- break;
+ buffer [block_len++] = (char) val;
+ i += ptr;
+ continue;
+ }
- case hex2:
- text [i] = toupper (text [i]);
- if ((p = strchr (hex_char, text [i])) != 0){
- v |= (p - hex_char);
- state = normal;
- }
- buffer [block_len++] = v;
- break;
+ /* Try quoted string, strip quotes */
+ if (sscanf (text + i, "\"%[^\"]\"%n", buffer + block_len, &ptr) > 0) {
+ i += ptr;
+ block_len += ptr - 2;
+ continue;
}
+
+ parse_error = 1;
+ break;
}
+
+ /* No valid bytes in the user input */
+ if (block_len <= 0 || parse_error) {
+ if (*text)
+ message (0, _(" Search "), _("Invalid hex search expression"));
+ g_free (buffer);
+ view->found_len = 0;
+ return;
+ }
+
/* Then start the search */
pos = block_search (view, buffer, block_len);
+
if (pos == -1){
message (0, _(" Search "), _(" Search string not found "));
view->found_len = 0;
_______________________________________________
Regards,
Pavel Roskin
More information about the mc-devel
mailing list