partial substitute command
authorLaurent Mazet <mazet@softndesign.org>
Sat, 14 Jan 2023 22:35:13 +0000 (23:35 +0100)
committerLaurent Mazet <mazet@softndesign.org>
Sat, 14 Jan 2023 22:35:13 +0000 (23:35 +0100)
hexdump.c

index dab192bac85922e29c6ceb204596a7d45f3ae557..d7faa681edc25e61ebbfecf5fa85882b471297b2 100644 (file)
--- a/hexdump.c
+++ b/hexdump.c
@@ -82,10 +82,10 @@ unsigned int getnbdigits (unsigned long int l) {
 
 /* print a line */
 
-void printline (char *buffer, int nb, int addr) {
+void printline (char *buffer, int nb, unsigned long int addr) {
     int i;
 
-    printf ("0x%0*x:", nbdigits, addr);
+    printf ("0x%0*lx:", nbdigits, addr);
     for (i = 0; i < nb; i++) {
         printf (" %02x", buffer[i]);
     }
@@ -353,17 +353,113 @@ int specialchar (char *s, char *b) {
     return j;
 }
 
+/* remove space function */
+
+void removespace (char *s, char **p) {
+    while (*s) {
+        if ((*s == ' ') || (*s == '\t')) {
+            s++;
+        } else {
+            break;
+        }
+    }
+    if (p != NULL) {
+        *p = s;
+    }
+}
+
+/* get pattern function */
+
+int getpattern (sequence_t *seq, char *s, char **p) {
+
+    seq->sequence = s;
+    seq->length = 0;
+
+    while (*s) {
+        if ((*s == '\\') && ((s[1] == '/') || (s[1] == '\\'))) {
+            s++;
+        } else if (*s == '/') {
+            *s++ = 0;
+            break;
+        }
+        s++;
+    }
+    seq->length = specialchar (seq->sequence, seq->bytes);
+
+    if (p != NULL) {
+        *p = s;
+    }
+
+    return (seq->length == 0);
+}
+
+/* get hexa sequence function */
+
+int gethexaseq (sequence_t *seq, char *s, char **p) {
+    int i = 0;
+
+    seq->sequence = s;
+    seq->length = 0;
+
+    while (*s) {
+        if (((*s >= '0') && (*s <= '9')) ||
+            ((*s >= 'A') && (*s <= 'F')) ||
+            ((*s >= 'a') && (*s <= 'f'))) {
+            s++;
+            i++;
+            if (i % 2 == 0) {
+                seq->bytes[seq->length] = hexa (seq->sequence + 2 * seq->length, 2);
+                if (seq->bytes[seq->length] == -1) {
+                    return 1;
+                }
+                seq->length++;
+            }
+        } else {
+            break;
+        }
+    }
+
+    if (p != NULL) {
+        *p = s;
+    }
+
+    return (seq->length == 0) || (i % 2 == 1);
+}
+
+/* get length function */
+
+long int getlength (char *s, char **p) {
+
+    while (*s != '\0') {
+        if ((*s == ' ') || (*s == '\t')) {
+            s++;
+        } else if ((*s >= '0') && (*s <= '9')) {
+            return strtol (s, p, 10);
+        } else if (*s == '-') {
+            if (p != NULL) {
+                *p = s + 1;
+            }
+            return -1;
+        } else {
+            VERBOSE (ERROR, fprintf (stderr, "unknown length (%s)\n", s));
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
 /* main function */
 
 int main (int argc, char *argv[])
 {
-    int i, rc = 0;
+    int rc = 0;
     char *input = NULL;
     char *output = NULL;
     char *commands = NULL;
     long int length = -1;
     sequence_t seq = {0};
-    long int addr = 0;
+    unsigned long int addr = 0;
     char c;
 
     /* get basename */
@@ -386,12 +482,8 @@ int main (int argc, char *argv[])
         case 'e':
             arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
             if (arg) {
-                if (commands == NULL) {
-                    commands = arg;
-                } else {
-                    strcat (commands, " ");
-                    strcat (commands, arg);
-                }
+                commands = (commands == NULL) ? arg :
+                    strcat (strcat (commands, " "), arg);
             }
             break;
         case 'i':
@@ -464,25 +556,15 @@ int main (int argc, char *argv[])
             case '\t':
                 break;
 
-            case '/': /* read patern */
-                seq.sequence = commands;
-                seq.length = 0;
-                while (*commands) {
-                    if ((*commands == '\\') &&
-                        ((commands[1] == '/') || (commands[1] == '\\'))) {
-                        commands++;
-                    } else if (*commands == '/') {
-                        *commands++ = 0;
-                        break;
-                    }
-                    commands++;
-                }
-                seq.length = specialchar (seq.sequence, seq.bytes);
-                if (seq.length != 0) {
+            case '/': /* search pattern */
+                rc = getpattern (&seq, commands, &commands);
+                if (rc == 0) {
                     rc = searchseq (&seq);
+                    if (rc == 1) {
+                        VERBOSE (ERROR, fprintf (stderr, "can't find pattern '%s'\n", seq.sequence));
+                    }
                 } else {
-                    VERBOSE (ERROR, fprintf (stderr, "incorrect sequence (%s)\n", seq.sequence));
-                    rc = 1;
+                    VERBOSE (ERROR, fprintf (stderr, "erroneous pattern '%s'\n", seq.sequence));
                 }
                 break;
 
@@ -495,6 +577,9 @@ int main (int argc, char *argv[])
                 }
                 if (addr) {
                     rc = gotoaddr (addr);
+                    if (rc == 1) {
+                        VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
+                    }
                 } else {
                     VERBOSE (ERROR, fprintf (stderr, "erroneous address\n"));
                     rc = 1;
@@ -514,6 +599,9 @@ int main (int argc, char *argv[])
                 commands--;
                 addr = strtol (commands, &commands, 10);
                 rc = gotoaddr (addr);
+                if (rc == 1) {
+                    VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
+                }
                 offset = 0;
                 break;
 
@@ -522,38 +610,12 @@ int main (int argc, char *argv[])
                 /* fall through */
 
             case 'i': /* insert mode */
-                while (*commands) {
-                    if ((*commands == ' ') || (*commands == '\t')) {
-                        commands++;
-                    } else {
-                        break;
-                    }
-                }
-                seq.sequence = commands;
-                seq.length = 0;
-                i = 0;
-                while (*commands) {
-                    if ((*commands == ' ') || (*commands == '\t')) {
-                       *commands++ = '\0';
-                       break;
-                    } else {
-                        commands++;
-                        i++;
-                        if (i % 2 == 0) {
-                            seq.bytes[seq.length] = hexa (seq.sequence + 2 * seq.length, 2);
-                            if (seq.bytes[seq.length] == -1) {
-                                rc = 1;
-                                break;
-                            }
-                            seq.length++;
-                        }
-                    }
-                }
-                if ((seq.length > 0) && (rc == 0) && (i % 2 == 0)) {
+                removespace (commands, &commands);
+                rc = gethexaseq (&seq, commands, &commands);
+                if (rc == 0) {
                     rc = insertseq (&seq);
                 } else {
                     VERBOSE (ERROR, fprintf (stderr, "erroneous sequence '%s'\n", seq.sequence));
-                    rc = 1;
                 }
                 offset = 0;
                 break;
@@ -565,27 +627,17 @@ int main (int argc, char *argv[])
                 /* fall through */
 
             case 'p': /* print mode */
-                length = -1;
-                while (*commands != '\0') {
-                    if ((*commands == ' ') || (*commands == '\t')) {
-                        commands++;
-                    } else if ((*commands >= '0') && (*commands <= '9')) {
-                        length = strtol (commands, &commands, 10);
-                        break;
-                    } else if (*commands == '-') {
-                        length = -1;
-                        commands++;
-                        break;
-                    } else {
-                        VERBOSE (ERROR, fprintf (stderr, "unknown length (%s)\n", commands));
-                        rc = 1;
-                        break;
-                    }
-                }
-                if (rc == 0) {
+                length = getlength (commands, &commands);
+                if (length == 0){
+                    VERBOSE (ERROR, fprintf (stderr, "erroneous length\n"));
+                    rc = 1;
+                } else {
                     switch (c) {
                     case '+':
                         rc = gotoaddr ((length > 0) ? addrfile + length : -1);
+                        if (rc == 1) {
+                            VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
+                        }
                         break;
 
                     case 'd':
@@ -601,11 +653,30 @@ int main (int argc, char *argv[])
                 break;
 
             case 's': /* substitute mode */
+                if (*commands == '/') {
+                    rc = getpattern (&seq, commands, &commands);
+                    if (rc == 0) {
+                        rc = searchseq (&seq);
+                        if (rc == 0) {
+                            fseek (fin, offset, SEEK_CUR);
+                            rc = gethexaseq (&seq, commands, &commands);
+                            if (rc == 0) {
+                                rc = insertseq (&seq);
+                            } else {
+                                VERBOSE (ERROR, fprintf (stderr, "erroneous sequence '%s'\n", seq.sequence));
+                            }
+                        } else {
+                            VERBOSE (ERROR, fprintf (stderr, "can't find pattern '%s'\n", seq.sequence));
+                        }
+                    } else {
+                        VERBOSE (ERROR, fprintf (stderr, "erroneous pattern '%s'\n", seq.sequence));
+                    }
+                }
                 offset = 0;
                 break;
 
             default:
-                VERBOSE (ERROR, fprintf (stderr, "unknown command (%c)\n", commands[-1]));
+                VERBOSE (ERROR, fprintf (stderr, "unknown command '%c'\n", commands[-1]));
                 rc = 1;
             }
         }
@@ -647,10 +718,10 @@ int main (int argc, char *argv[])
 // test: hexdump.exe -i hexdump.c -e ' /\n/ p 8' | grep -q '0x000d: 0a 2f 2a 20 63 66 6c 61  \./\* cfla'
 // test: hexdump.exe -i hexdump.c -o test.c -e ' /\a\b\e\f\r\t\v/ p 8'; x=$?; test x$x = x1
 // test: cmp hexdump.c test.c; x=$?; rm test.c; test x$x = x0
-// test: hexdump.exe -i hexdump.c -v 3 -e " /\'/" -e ' /\"/' -e ' /\\/' -e ' /\x2a/' -e ' s/\x3A/' | grep l: | wc -l | xargs test 5 =
+// test: hexdump.exe -i hexdump.c -v 3 -e " /\'/" -e ' /\"/' -e ' /\\/' -e ' /\x2a/' -e ' /\x3A/' | grep l: | wc -l | xargs test 5 =
 // test: hexdump.exe -i hexdump.c -e ' /\n\/* vim:/ p -' | grep -q ': 74 3a 20 2a 2f 0a *t: \*\/\.'
 // test: hexdump.exe -i hexdump.c -e 'p go_to_end' 2>&1 | grep -q 'unknown length'
-// test: hexdump.exe -i hexdump.c -e ' //' 2>&1 | grep -q 'incorrect sequence'
+// test: hexdump.exe -i hexdump.c -e ' //' 2>&1 | grep -q 'erroneous pattern'
 // test: hexdump.exe -i hexdump.c -e 'foo' 2>&1 | grep -q 'unknown command'
 // test: hexdump.exe -i hexdump.c -e '0x20 p 8 64 p 8 0200 p 16' | grep -q '0x0080:'
 // test: hexdump.exe -i hexdump.c -e '0xg' 2>&1 | grep -q 'erroneous address'