search sequence command
authorLaurent Mazet <laurent.mazet@thalesgroup.com>
Wed, 11 Jan 2023 15:57:21 +0000 (16:57 +0100)
committerLaurent Mazet <laurent.mazet@thalesgroup.com>
Wed, 11 Jan 2023 15:57:21 +0000 (16:57 +0100)
hexdump.c

index 6674970df831478cf7c0317e0cb28de540448195..c146b63797a4bd65a3c514a6da8db929d43240ee 100644 (file)
--- a/hexdump.c
+++ b/hexdump.c
@@ -3,7 +3,6 @@
 /* linker: debug.o */
 
 #include <assert.h>
-#include <getopt.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 //#define BUFFERSIZE 4096
 #define BUFFERSIZE 256
 #define NBCOLS 8
+#define NBDIGITS 6
 
 /* gobal variables */
 
-char *buffer[BUFFERSIZE] = {0};
+int nbcols = NBCOLS;
+int nbdigits = NBDIGITS;
+int offset = 1;
+
+char buffer[BUFFERSIZE] = {0};
 FILE *fin = NULL;
+int addrfile = 0;
 FILE *fout = NULL;
 char *progname = NULL;
 
 /* help function */
 
-void usage (int ret)
+int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
     fprintf (fd, "usage: %s [-i file] [-h] [-n nbcols] [-o file] [-v]\n", progname);
@@ -50,7 +55,7 @@ void usage (int ret)
     fprintf (fd, " p : print nb bytes (- until end file)\n");
     fprintf (fd, " s : substitute h1 by h2 (g for globally)\n");
 
-    exit (ret);
+    return ret;
 }
 
 /* get number of digits */
@@ -66,7 +71,7 @@ int getnbdigits (long int l) {
 
 /* print a line */
 
-void printline (char *buffer, int nbcols, int nb, int addr, int nbdigits) {
+void printline (char *buffer, int nb, int addr) {
     int i;
 
     printf ("0x%0*x:", nbdigits, addr);
@@ -93,26 +98,68 @@ int writefile (char *pt, int nb) {
     return 1;
 }
 
+/* search sequence function */
+
+int searchseq (char *seq) {
+    char *pt = buffer;
+    int nb = 0;
+    int i, j;
+    int valid = 0;
+    int len = strlen (seq);
+
+    VERBOSE (DEBUG, printf ("search sequence: %s\n", seq));
+
+    while (!feof (fin)) {
+        int nbread = fread (pt, 1, BUFFERSIZE - (pt - buffer), fin);
+        nb += nbread;
+        pt = buffer;
+        for (i = 0; i < nb - len; i++) {
+            valid = 1;
+            for (j = 0; (j < len) && (valid); j++) {
+                if (pt[i + j] != seq[j]) {
+                    valid = 0;
+                }
+            }
+            if (valid) {
+                break;
+            }
+        }
+
+        if (!valid) {
+            writefile (buffer, nb - len);
+            offset = 0;
+            addrfile += nb - len;
+            for (i = 0; i < len; i++) {
+                buffer[i] = buffer[nb - len + i];
+            }
+            pt = buffer + len;
+            nb = len;
+        } else {
+            writefile (buffer, i);
+            offset = len;
+            addrfile += i;
+            fseek (fin, i - nb, SEEK_CUR);
+            VERBOSE (DEBUG, printf ("found sequence (%d)\n", i - nb));
+            return 0;
+        }
+    }
+
+    if (!valid) {
+        writefile (buffer, nb);
+        addrfile += len;
+    }
+
+    return 1;
+}
+
 /* hexadecimal dump function */
 
-int hexdump (int nbcols, int len) {
+int hexdump (int len) {
     char buffer[BUFFERSIZE] = {0};
     int i;
 
     char *pt = buffer;
 
-    /* get file size */
-    int nbdigits = 0;
-    if (fin != stdin) {
-        fseek (fin, 0 , SEEK_END);
-        long int filesize = ftell (fin);
-        fseek (fin, 0 , SEEK_SET);
-        nbdigits = getnbdigits (filesize);
-    } else {
-        nbdigits = 6;
-    }
-
-    int addr = 0;
     int nb = 0;
     while (!feof (fin)) {
         int nbtoread = BUFFERSIZE - (pt - buffer);
@@ -128,10 +175,10 @@ int hexdump (int nbcols, int len) {
 
         /* print line */
         while ((nb - (int)(pt - buffer)) / nbcols > 0) {
-            printline (pt, nbcols, nbcols, addr, nbdigits);
+            printline (pt, nbcols, addrfile);
             writefile (pt, nbcols);
+            addrfile += nbcols;
             pt += nbcols;
-            addr += nbcols;
         }
 
         /* copy end buffer */
@@ -149,24 +196,91 @@ int hexdump (int nbcols, int len) {
 
     /* last line */
     if (nb > 0) {
-        printline (buffer, nbcols, nb, addr, nbdigits);
-        writefile (pt, nb);
+        printline (buffer, nb, addrfile);
+        writefile (buffer, nb);
+        addrfile += nb;
     }
 
     return 0;
 }
 
+/* special character function */
+
+char *specialchar (char *s) {
+    int i = 0, j = 0;
+    while (s[i] != 0) {
+        if (s[i] != '\\') {
+            s[j++] = s[i++];
+            continue;
+        }
+
+        int l = 0;
+        switch (s[i + 1]) {
+        case 'a': l = 0x07; i += 2; break;
+        case 'b': l = 0x08; i += 2; break;
+        case 'e': l = 0x1b; i += 2; break;
+        case 'f': l = 0x0c; i += 2; break;
+        case 'n': l = 0x0a; i += 2; break;
+        case 'r': l = 0x0d; i += 2; break;
+        case 't': l = 0x09; i += 2; break;
+        case 'v': l = 0x0b; i += 2; break;
+        case '\\': l = '\\'; i += 2; break;
+        case '\'': l = '\''; i += 2; break;
+        case '"': l = '"'; i += 2; break;
+        case '0':
+        case '1':
+        case '2':
+        case '3':
+            if ((s[i + 2] >= '0') && (s[i + 2] <= '9') &&
+                (s[i + 3] >= '0') && (s[i + 3] <= '9')) {
+                l = (s[i + 1] - '0') * 8 * 8 + (s[i + 2] - '0') * 8 + s[i + 3] - '0';
+                i += 4;
+            }
+            break;
+        case 'x':
+            if ((((s[i + 2] >= '0') && (s[i + 2] <= '9')) ||
+                 ((s[i + 2] >= 'A') && (s[i + 2] <= 'F')) ||
+                 ((s[i + 2] >= 'a') && (s[i + 2] <= 'f'))) &&
+                (((s[i + 3] >= '0') && (s[i + 3] <= '9')) ||
+                 ((s[i + 3] >= 'A') && (s[i + 3] <= 'F')) ||
+                 ((s[i + 3] >= 'a') && (s[i + 3] <= 'f')))) {
+                l = s[i + 2] - '0';
+                if (s[i + 2] >= 'a') {
+                    l += '0' + 10 - 'a';
+                } else if (s[i + 2] >= 'A') {
+                    l += '0' + 10 - 'A';
+                }
+                l = l * 16 + s[i + 3] - '0';
+                if (s[i + 3] >= 'a') {
+                    l += '0' + 10 - 'a';
+                } else if (s[i + 3] >= 'A') {
+                    l += '0' + 10 - 'A';
+                }
+                i += 4;
+            }
+            break;
+        default:
+        }
+        VERBOSE (DEBUG, printf("l: 0x%02x '%c'\n", l, l));
+        s[j++] = (l != 0) ? l : s[i++];
+    }
+    s[j] = '\0';
+
+    return s;
+}
+
 /* main function */
 
-int main (int argc, char *argv[]) 
+int main (int argc, char *argv[])
 {
     int rc = 0;
     char *input = NULL;
     char *output = NULL;
-    int nbcols = NBCOLS;
     char *commands = NULL;
     int printlen = -1;
-   
+    char *seq = NULL;
+    char *addr = NULL;
+
     /* get basename */
     char *pt = progname = argv[0];
     while (*pt) {
@@ -176,38 +290,53 @@ int main (int argc, char *argv[])
         pt++;
     }
 
-    int c;
-    while ((c = getopt(argc, argv, "e:i:hn:o:v:")) != EOF) {
+     while (argc-- > 1) {
+        char *arg = *(++argv);
+        if (arg[0] != '-') {
+            VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg));
+            return usage (1);
+        }
+        char c = arg[1];
         switch (c) {
-        case 'i':
-            input = optarg;
-            break;
         case 'e':
-            if (commands == NULL) {
-                commands = optarg;
-            } else {
-                strcat (commands, " ");
-                strcat (commands, optarg);
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg) {
+                arg = specialchar (arg);
+                if (commands == NULL) {
+                    commands = arg;
+                } else {
+                    strcat (commands, " ");
+                    strcat (commands, arg);
+                }
             }
             break;
+        case 'i':
+            input = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL;
+            break;
         case 'n':
-            nbcols = atoi (optarg);
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: missing number of columns\n", progname));
+                return usage (1);
+            }
+            nbcols = atoi (arg);
             break;
         case 'o':
-            output = optarg;
+            output = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL;
             break;
         case 'v':
-            verbose = atoi (optarg);
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname));
+                return usage (1);
+            }
+            verbose = atoi (arg);
             break;
         case 'h':
         default:
-            usage (c != 'h');
+            return usage (c != 'h');
         }
     }
-    if (argc - optind != 0) {
-        fprintf (stderr, "%s: invalid option -- %s\n", progname, argv[optind]);
-        usage (1);
-    }
 
     /* check input */
     if (input) {
@@ -232,8 +361,16 @@ int main (int argc, char *argv[])
         //fout = stdout;
     }
 
+    /* get file size */
+    if (fin != stdin) {
+        fseek (fin, 0 , SEEK_END);
+        long int filesize = ftell (fin);
+        fseek (fin, 0 , SEEK_SET);
+        nbdigits = getnbdigits (filesize);
+    }
+
     if (commands == NULL) {
-        hexdump (nbcols, -1);
+        hexdump (-1);
     } else {
         VERBOSE (DEBUG, printf ("commands: %s\n", commands));
         while ((*commands != '\0') && (rc == 0)) {
@@ -243,6 +380,20 @@ int main (int argc, char *argv[])
                 break;
 
             case '/': /* read patern */
+                seq = commands;
+                while (*commands) {
+                    if (*commands == '/') {
+                        *commands++ = 0;
+                        break;
+                    }
+                    commands++;
+                }
+                if (*seq != 0) {
+                    rc = searchseq (seq);
+                } else {
+                    VERBOSE (ERROR, fprintf (stderr, "no sequence definied\n"));
+                    rc = 1;
+                }
                 break;
 
             case '0': /* read address */
@@ -275,7 +426,9 @@ int main (int argc, char *argv[])
                         break;
                     }
                 }
-                if (rc == 0) hexdump (nbcols, printlen);
+                if (rc == 0) {
+                    hexdump (printlen);
+                }
                 break;
 
             case 's': /* substitute mode */
@@ -305,7 +458,6 @@ int main (int argc, char *argv[])
     return rc;
 }
 
-// test: hexdump.exe -h
 // test: hexdump.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
 // test: hexdump.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
 // test: hexdump.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
@@ -314,5 +466,9 @@ int main (int argc, char *argv[])
 // test: hexdump.exe -i hexdump.c -o test.c -e 'p 200' | tail -1 | grep -q '0x00c0:'
 // test: cmp hexdump.c test.c
 // test: rm test.c
+// test: hexdump.exe -i hexdump.c -e ' /cflags/ p 16 /debug/ p 8' | grep -q '0x0019: 2a 2f 0a 2f 2a 20 6c 69  \*/\./\* li'
+// test: hexdump.exe -i hexdump.c -o test.c -e ' /cflags/ p 16 /debug/ p 8' | grep -q '0x0027: 64 65 62 75 67 2e 6f 20  debug.o'
+// test: cmp hexdump.c test.c
+// test: rm test.c
 
 /* vim: set ts=4 sw=4 et: */