From 1291ede609002c0e696717afd21ed3ee56aa497a Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Sat, 14 Jan 2023 23:35:13 +0100 Subject: [PATCH] partial substitute command --- hexdump.c | 225 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 148 insertions(+), 77 deletions(-) diff --git a/hexdump.c b/hexdump.c index dab192b..d7faa68 100644 --- 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' -- 2.30.2