From 4c4a10dd292a9c2316db808f90e7f33b7dc46aca Mon Sep 17 00:00:00 2001 From: Laurent Mazet Date: Wed, 11 Jan 2023 16:57:21 +0100 Subject: [PATCH] search sequence command --- hexdump.c | 248 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 202 insertions(+), 46 deletions(-) diff --git a/hexdump.c b/hexdump.c index 6674970..c146b63 100644 --- a/hexdump.c +++ b/hexdump.c @@ -3,7 +3,6 @@ /* linker: debug.o */ #include -#include #include #include #include @@ -20,17 +19,23 @@ //#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: */ -- 2.30.2