cleaning
[hexdump.git] / hexdump.c
CommitLineData
a1ab98f9
LM
1/* depend: */
2/* cflags: */
3/* linker: debug.o */
4
5#include <assert.h>
0304c8cc 6#include <limits.h>
a1ab98f9
LM
7#include <malloc.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "debug.h"
13
14/* macros */
15
16#define CEIL(x, y) (((x) + (y) - 1) / (y))
17#define MIN(x, y) (((x) < (y)) ? (x) : (y))
18#define MAX(x, y) (((x) > (y)) ? (x) : (y))
19
20//#define BUFFERSIZE 4096
21#define BUFFERSIZE 256
22#define NBCOLS 8
4c4a10dd 23#define NBDIGITS 6
5bcbfcca 24#define SEQLEN 32
a1ab98f9
LM
25
26/* gobal variables */
27
4c4a10dd
LM
28int nbcols = NBCOLS;
29int nbdigits = NBDIGITS;
9e439809 30int offset = 0;
4c4a10dd
LM
31
32char buffer[BUFFERSIZE] = {0};
ce305529 33FILE *fin = NULL;
0304c8cc 34long int addrfile = 0;
ce305529 35FILE *fout = NULL;
a1ab98f9
LM
36char *progname = NULL;
37
5bcbfcca
LM
38/* type definitions */
39
40typedef struct {
41 char *sequence;
42 char bytes[SEQLEN];
43 int length;
44} sequence_t;
45
a1ab98f9
LM
46/* help function */
47
4c4a10dd 48int usage (int ret)
a1ab98f9
LM
49{
50 FILE *fd = ret ? stderr : stdout;
51 fprintf (fd, "usage: %s [-i file] [-h] [-n nbcols] [-o file] [-v]\n", progname);
5272fae8
LM
52 fprintf (fd, " -i: input file\n");
53 fprintf (fd, " -h: help message\n");
54 fprintf (fd, " -n: number of columns\n");
55 fprintf (fd, " -e: commands\n");
56 fprintf (fd, " -o: output file\n");
57 fprintf (fd, " -v: verbose level (%d)\n", verbose);
58 fprintf (fd, "\n");
0304c8cc 59 fprintf (fd, "commands: [/hstr/|addr|+nb] [a hstr] [d nb|-] [i hstr] [p nb|-] [s/h1/h2/[g]]\n");
cc02a838 60 fprintf (fd, " addr: move to address (0... octal, [1-9]... deci, 0x... hexa)\n");
0304c8cc 61 fprintf (fd, " +nb: move to offset (0... octal, [1-9]... deci, 0x... hexa)\n");
40c51071 62 fprintf (fd, " //: move to hexa string hstr\n");
5272fae8
LM
63 fprintf (fd, " a : append hexa string hstr to current address\n");
64 fprintf (fd, " d : delete nb bytes (- until end file)\n");
65 fprintf (fd, " i : insert hexa string hstr to current address\n");
66 fprintf (fd, " p : print nb bytes (- until end file)\n");
67 fprintf (fd, " s : substitute h1 by h2 (g for globally)\n");
a1ab98f9 68
4c4a10dd 69 return ret;
a1ab98f9
LM
70}
71
72/* get number of digits */
73
cc02a838 74unsigned int getnbdigits (unsigned long int l) {
a1ab98f9
LM
75 int n = 0;
76 while (l) {
77 n += 2;
78 l /= 256;
79 }
80 return n;
81}
82
83/* print a line */
84
1291ede6 85void printline (char *buffer, int nb, unsigned long int addr) {
a1ab98f9
LM
86 int i;
87
1291ede6 88 printf ("0x%0*lx:", nbdigits, addr);
a1ab98f9 89 for (i = 0; i < nb; i++) {
60e280f7 90 printf (" %02x", (unsigned char)buffer[i]);
a1ab98f9
LM
91 }
92 for (i = nb; i < nbcols; i++) {
93 printf (" ");
94 }
95 printf (" ");
96 for (i = 0; i < nb; i++) {
97 char c = buffer[i];
98 printf ("%c", (c > 31) && (c < 127) ? c : '.');
99 }
100 printf ("\n");
101}
102
ce305529 103/* write file function */
a1ab98f9 104
ce305529
LM
105int writefile (char *pt, int nb) {
106 if (fout) {
107 fwrite (pt, 1, nb, fout);
108 }
109 return 1;
110}
111
4c4a10dd
LM
112/* search sequence function */
113
5bcbfcca 114int searchseq (sequence_t *seq) {
4c4a10dd
LM
115 char *pt = buffer;
116 int nb = 0;
117 int i, j;
118 int valid = 0;
4c4a10dd 119
5bcbfcca 120 VERBOSE (DEBUG, printf ("search sequence: %s\n", seq->sequence));
4c4a10dd
LM
121
122 while (!feof (fin)) {
123 int nbread = fread (pt, 1, BUFFERSIZE - (pt - buffer), fin);
124 nb += nbread;
125 pt = buffer;
5bcbfcca 126 for (i = 0; i < nb - seq->length; i++) {
4c4a10dd 127 valid = 1;
5bcbfcca
LM
128 for (j = 0; (j < seq->length) && (valid); j++) {
129 if (pt[i + j] != seq->bytes[j]) {
4c4a10dd
LM
130 valid = 0;
131 }
132 }
133 if (valid) {
134 break;
135 }
136 }
137
138 if (!valid) {
5bcbfcca 139 writefile (buffer, nb - seq->length);
4c4a10dd 140 offset = 0;
5bcbfcca
LM
141 addrfile += nb - seq->length;
142 for (i = 0; i < seq->length; i++) {
143 buffer[i] = buffer[nb - seq->length + i];
4c4a10dd 144 }
5bcbfcca
LM
145 pt = buffer + seq->length;
146 nb = seq->length;
4c4a10dd
LM
147 } else {
148 writefile (buffer, i);
5bcbfcca 149 offset = seq->length;
4c4a10dd
LM
150 addrfile += i;
151 fseek (fin, i - nb, SEEK_CUR);
1286d873 152 VERBOSE (DEBUG, printf ("found sequence at 0x%0*lx\n", getnbdigits (addrfile), addrfile));
4c4a10dd
LM
153 return 0;
154 }
155 }
156
157 if (!valid) {
158 writefile (buffer, nb);
5bcbfcca 159 addrfile += seq->length;
4c4a10dd
LM
160 }
161
162 return 1;
163}
164
cc02a838
LM
165/* go to address function */
166
0304c8cc 167int gotoaddr (long int addr) {
cc02a838
LM
168 char buffer[BUFFERSIZE] = {0};
169
0304c8cc
LM
170 if (addr == -1) {
171 addr = LONG_MAX;
172 } else if (addrfile > addr) {
cc02a838
LM
173 return 1;
174 }
175
176 VERBOSE (DEBUG, printf ("look for address: 0x%04lx\n", addr));
177 while (!feof (fin)) {
178 int nbtoread = (addrfile + BUFFERSIZE > addr) ? addr - addrfile : BUFFERSIZE;
179 int nbread = fread (buffer, 1, nbtoread, fin);
180 writefile (buffer, nbread);
181 addrfile += nbread;
182 if (addrfile == addr) {
183 return 0;
184 }
185 }
186
187 return 1;
188}
189
9e439809
LM
190/* insert sequence function */
191
192int insertseq (sequence_t *seq) {
193 char buffer[BUFFERSIZE] = {0};
194
195 VERBOSE (DEBUG, printf ("insert (%d): '%s'\n", offset, seq->sequence);
196 int i;
197 for (i = 0; i < seq->length; i++) {
198 char c = seq->bytes[i];
199 printf (" 0x%02x (%c)", c, ((c >= 32) && (c < 127)) ? c : '.');
200 };
201 printf ("\n"));
202 if (offset > 0) {
203 int nbread = fread (buffer, 1, offset, fin);
204 if (nbread != offset) {
205 return 1;
206 }
207 writefile (buffer, offset);
208 offset = 0;
209 }
210 writefile (seq->bytes, seq->length);
211
212 return 0;
213}
214
ce305529
LM
215/* hexadecimal dump function */
216
4c4a10dd 217int hexdump (int len) {
a1ab98f9
LM
218 char buffer[BUFFERSIZE] = {0};
219 int i;
220
221 char *pt = buffer;
222
a1ab98f9
LM
223 int nb = 0;
224 while (!feof (fin)) {
5272fae8
LM
225 int nbtoread = BUFFERSIZE - (pt - buffer);
226 if ((len > 0) && (nbtoread > len)) {
227 nbtoread = len;
228 }
229 int nbread = fread (pt, 1, nbtoread, fin);
230 if (len > 0) {
231 len -= nbread;
232 }
233 nb += nbread;
a1ab98f9
LM
234 pt = buffer;
235
236 /* print line */
237 while ((nb - (int)(pt - buffer)) / nbcols > 0) {
4c4a10dd 238 printline (pt, nbcols, addrfile);
ce305529 239 writefile (pt, nbcols);
4c4a10dd 240 addrfile += nbcols;
a1ab98f9 241 pt += nbcols;
a1ab98f9
LM
242 }
243
244 /* copy end buffer */
245 nb -= pt - buffer;
246 for (i = 0; i < nb; i++) {
247 buffer[i] = pt[i];
248 }
249 pt = buffer + nb;
5272fae8
LM
250
251 /* end partial reading */
252 if (len == 0) {
253 break;
254 }
a1ab98f9
LM
255 }
256
257 /* last line */
258 if (nb > 0) {
4c4a10dd
LM
259 printline (buffer, nb, addrfile);
260 writefile (buffer, nb);
261 addrfile += nb;
a1ab98f9
LM
262 }
263
264 return 0;
265}
266
47db4fc7
LM
267/* parse octal string */
268
9e439809 269long int octal (char *s, int n) {
47db4fc7 270 int i;
cc02a838 271 unsigned long int l = 0;
47db4fc7 272 for (i = 0; i < n; i++) {
09776c0a 273 if ((s[i] >= '0') && (s[i] < '8')) {
47db4fc7
LM
274 l = l * 8 + s[i] - '0';
275 } else {
276 return -1;
277 }
278 }
279 return l;
280}
281
282/* parse hexa string */
283
9e439809 284long int hexa (char *s, int n) {
47db4fc7 285 int i;
cc02a838 286 unsigned long int l = 0;
47db4fc7
LM
287 for (i = 0; i < n; i++) {
288 l *= 16;
289 if ((s[i] >= '0') && (s[i] <= '9')) {
290 l += s[i] - '0';
291 } else if ((s[i] >= 'A') && (s[i] <= 'F')) {
292 l += s[i] + 10 - 'A';
293 } else if ((s[i] >= 'a') && (s[i] <= 'f')) {
294 l += s[i] + 10 - 'a';
295 } else {
296 return -1;
297 }
298 }
299 return l;
300}
301
4c4a10dd
LM
302/* special character function */
303
5bcbfcca 304int specialchar (char *s, char *b) {
4c4a10dd
LM
305 int i = 0, j = 0;
306 while (s[i] != 0) {
5bcbfcca
LM
307 if (j == SEQLEN) {
308 return 0;
309 }
4c4a10dd 310 if (s[i] != '\\') {
5bcbfcca 311 b[j++] = s[i++];
4c4a10dd
LM
312 continue;
313 }
314
47db4fc7 315 int l = -1;
4c4a10dd
LM
316 switch (s[i + 1]) {
317 case 'a': l = 0x07; i += 2; break;
318 case 'b': l = 0x08; i += 2; break;
319 case 'e': l = 0x1b; i += 2; break;
320 case 'f': l = 0x0c; i += 2; break;
321 case 'n': l = 0x0a; i += 2; break;
322 case 'r': l = 0x0d; i += 2; break;
323 case 't': l = 0x09; i += 2; break;
324 case 'v': l = 0x0b; i += 2; break;
f975557c 325 case '/': l = '/'; i += 2; break;
4c4a10dd
LM
326 case '\\': l = '\\'; i += 2; break;
327 case '\'': l = '\''; i += 2; break;
328 case '"': l = '"'; i += 2; break;
329 case '0':
330 case '1':
331 case '2':
332 case '3':
5bcbfcca 333 l = octal (s + i + 1, 3);
09776c0a
LM
334 if (l == -1) {
335 VERBOSE (WARNING, fprintf (stderr, "incorrect special char (\\%c%c%c)\n", s[i + 1], s[i + 2], s[i + 3]));
4c4a10dd 336 }
09776c0a 337 i += 4;
4c4a10dd
LM
338 break;
339 case 'x':
5bcbfcca 340 l = hexa (s + i + 2, 2);
09776c0a
LM
341 if (l == -1) {
342 VERBOSE (WARNING, fprintf (stderr, "incorrect special char (\\x%c%c)\n", s[i + 2], s[i + 3]));
4c4a10dd 343 }
09776c0a 344 i += 4;
4c4a10dd
LM
345 break;
346 default:
09776c0a
LM
347 VERBOSE (WARNING, fprintf (stderr, "incorrect special char (\\%c)\n", s[i + 1]));
348 i += 2;
cc02a838 349 break;
4c4a10dd 350 }
5bcbfcca
LM
351 if (l != -1) {
352 VERBOSE (DEBUG, printf("l: 0x%02x '%c'\n", l, l));
09776c0a 353 b[j++] = l;
5bcbfcca 354 }
4c4a10dd 355 }
4c4a10dd 356
5bcbfcca 357 return j;
4c4a10dd
LM
358}
359
1291ede6
LM
360/* remove space function */
361
362void removespace (char *s, char **p) {
363 while (*s) {
364 if ((*s == ' ') || (*s == '\t')) {
365 s++;
366 } else {
367 break;
368 }
369 }
370 if (p != NULL) {
371 *p = s;
372 }
373}
374
375/* get pattern function */
376
377int getpattern (sequence_t *seq, char *s, char **p) {
378
379 seq->sequence = s;
380 seq->length = 0;
381
382 while (*s) {
383 if ((*s == '\\') && ((s[1] == '/') || (s[1] == '\\'))) {
384 s++;
385 } else if (*s == '/') {
386 *s++ = 0;
387 break;
388 }
389 s++;
390 }
391 seq->length = specialchar (seq->sequence, seq->bytes);
392
393 if (p != NULL) {
394 *p = s;
395 }
396
397 return (seq->length == 0);
398}
399
400/* get hexa sequence function */
401
402int gethexaseq (sequence_t *seq, char *s, char **p) {
403 int i = 0;
404
405 seq->sequence = s;
406 seq->length = 0;
407
408 while (*s) {
409 if (((*s >= '0') && (*s <= '9')) ||
410 ((*s >= 'A') && (*s <= 'F')) ||
411 ((*s >= 'a') && (*s <= 'f'))) {
412 s++;
413 i++;
414 if (i % 2 == 0) {
415 seq->bytes[seq->length] = hexa (seq->sequence + 2 * seq->length, 2);
416 if (seq->bytes[seq->length] == -1) {
417 return 1;
418 }
419 seq->length++;
420 }
421 } else {
422 break;
423 }
424 }
425
426 if (p != NULL) {
427 *p = s;
428 }
429
430 return (seq->length == 0) || (i % 2 == 1);
431}
432
433/* get length function */
434
435long int getlength (char *s, char **p) {
436
437 while (*s != '\0') {
438 if ((*s == ' ') || (*s == '\t')) {
439 s++;
440 } else if ((*s >= '0') && (*s <= '9')) {
441 return strtol (s, p, 10);
442 } else if (*s == '-') {
443 if (p != NULL) {
444 *p = s + 1;
445 }
446 return -1;
447 } else {
448 VERBOSE (ERROR, fprintf (stderr, "unknown length (%s)\n", s));
449 return 0;
450 }
451 }
452
453 return 0;
454}
455
a1ab98f9
LM
456/* main function */
457
4c4a10dd 458int main (int argc, char *argv[])
a1ab98f9 459{
1291ede6 460 int rc = 0;
a1ab98f9
LM
461 char *input = NULL;
462 char *output = NULL;
5272fae8 463 char *commands = NULL;
0304c8cc 464 long int length = -1;
5bcbfcca 465 sequence_t seq = {0};
1291ede6 466 unsigned long int addr = 0;
6429544e 467 char c;
4c4a10dd 468
a1ab98f9
LM
469 /* get basename */
470 char *pt = progname = argv[0];
471 while (*pt) {
472 if ((*pt == '/') || (*pt == '\\')) {
473 progname = pt + 1;
474 }
475 pt++;
476 }
477
4c4a10dd
LM
478 while (argc-- > 1) {
479 char *arg = *(++argv);
480 if (arg[0] != '-') {
481 VERBOSE (ERROR, fprintf (stderr, "%s: invalid option -- %s\n", progname, arg));
482 return usage (1);
483 }
484 char c = arg[1];
a1ab98f9 485 switch (c) {
5272fae8 486 case 'e':
4c4a10dd
LM
487 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
488 if (arg) {
40c51071
LM
489 //commands = (commands == NULL) ? arg :
490 // strcat (strcat (commands, " "), arg);
491 if (commands == NULL) {
492 commands = arg;
493 } else {
494 char *tmp = (char *) malloc (strlen (arg) + 1);
495 strcat (strcat (commands, " "), strcpy (tmp, arg));
09776c0a 496 free (tmp);
40c51071 497 }
5272fae8
LM
498 }
499 break;
4c4a10dd
LM
500 case 'i':
501 input = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL;
502 break;
a1ab98f9 503 case 'n':
4c4a10dd
LM
504 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
505 if (arg == NULL) {
506 VERBOSE (ERROR, fprintf (stderr, "%s: missing number of columns\n", progname));
507 return usage (1);
508 }
509 nbcols = atoi (arg);
a1ab98f9
LM
510 break;
511 case 'o':
4c4a10dd 512 output = (arg[2]) ? arg + 2 : (--argc > 0 ) ? *(++argv) : NULL;
a1ab98f9
LM
513 break;
514 case 'v':
4c4a10dd
LM
515 arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
516 if (arg == NULL) {
517 VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname));
518 return usage (1);
519 }
520 verbose = atoi (arg);
a1ab98f9
LM
521 break;
522 case 'h':
523 default:
4c4a10dd 524 return usage (c != 'h');
a1ab98f9
LM
525 }
526 }
a1ab98f9
LM
527
528 /* check input */
6aa9bee8 529 fin = stdin;
a1ab98f9
LM
530 if (input) {
531 fin = fopen (input, "rb");
532 if (!fin) {
533 VERBOSE (ERROR, fprintf (stderr, "error: can't open file '%s'\n", input));
5272fae8 534 return 1;
a1ab98f9 535 }
a1ab98f9
LM
536 }
537
538 /* check output */
a1ab98f9 539 if (output) {
ce305529 540 fout = fopen (output, "wb");
a1ab98f9
LM
541 if (!fout) {
542 VERBOSE (ERROR, fprintf (stderr, "error: can't open file '%s'\n", output));
543 fclose (fin);
5272fae8 544 return 1;
a1ab98f9
LM
545 }
546 } else {
ce305529 547 //fout = stdout;
a1ab98f9
LM
548 }
549
4c4a10dd
LM
550 /* get file size */
551 if (fin != stdin) {
552 fseek (fin, 0 , SEEK_END);
cc02a838 553 unsigned long int filesize = ftell (fin);
4c4a10dd
LM
554 fseek (fin, 0 , SEEK_SET);
555 nbdigits = getnbdigits (filesize);
556 }
557
5272fae8 558 if (commands == NULL) {
3bf29ac6 559 VERBOSE (DEBUG, printf ("no command\n"));
4c4a10dd 560 hexdump (-1);
5272fae8
LM
561 } else {
562 VERBOSE (DEBUG, printf ("commands: %s\n", commands));
563 while ((*commands != '\0') && (rc == 0)) {
6429544e 564 switch (c = *commands++) {
5272fae8
LM
565 case ' ':
566 case '\t':
567 break;
568
1291ede6
LM
569 case '/': /* search pattern */
570 rc = getpattern (&seq, commands, &commands);
571 if (rc == 0) {
5bcbfcca 572 rc = searchseq (&seq);
1291ede6
LM
573 if (rc == 1) {
574 VERBOSE (ERROR, fprintf (stderr, "can't find pattern '%s'\n", seq.sequence));
575 }
4c4a10dd 576 } else {
09776c0a 577 VERBOSE (ERROR, fprintf (stderr, "erroneous pattern \"%s'\n", seq.sequence));
4c4a10dd 578 }
5272fae8
LM
579 break;
580
581 case '0': /* read address */
cc02a838
LM
582 if (*commands == 'x') {
583 commands++;
584 addr = strtol (commands, &commands, 16);
585 } else {
586 addr = strtol (commands, &commands, 8);
587 }
588 if (addr) {
589 rc = gotoaddr (addr);
1291ede6
LM
590 if (rc == 1) {
591 VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
592 }
cc02a838
LM
593 } else {
594 VERBOSE (ERROR, fprintf (stderr, "erroneous address\n"));
9e439809 595 rc = 1;
cc02a838 596 }
0304c8cc 597 offset = 0;
cc02a838
LM
598 break;
599
600 case '1':
601 case '2':
602 case '3':
603 case '4':
604 case '5':
605 case '6':
606 case '7':
607 case '8':
608 case '9': /* read address */
609 commands--;
610 addr = strtol (commands, &commands, 10);
09776c0a
LM
611 if ((*commands != 0) && (*commands != ' ')) {
612 VERBOSE (ERROR, fprintf (stderr, "erroneous address ()\n"));
613 rc = 1;
614 } else {
615 rc = gotoaddr (addr);
616 if (rc == 1) {
617 VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
618 }
619 offset = 0;
1291ede6 620 }
5272fae8
LM
621 break;
622
623 case 'a': /* append mode */
9e439809
LM
624 offset = 0;
625 /* fall through */
5272fae8 626
9e439809 627 case 'i': /* insert mode */
1291ede6
LM
628 removespace (commands, &commands);
629 rc = gethexaseq (&seq, commands, &commands);
630 if (rc == 0) {
9e439809 631 rc = insertseq (&seq);
1286d873
ML
632 if (rc == 1) {
633 VERBOSE (ERROR, fprintf (stderr, "can't jump (%d)\n", offset));
634 }
9e439809
LM
635 } else {
636 VERBOSE (ERROR, fprintf (stderr, "erroneous sequence '%s'\n", seq.sequence));
9e439809 637 }
0304c8cc 638 offset = 0;
5272fae8
LM
639 break;
640
0304c8cc
LM
641 case '+': /* relative move */
642 /* fall through */
643
9e439809 644 case 'd': /* delete mode */
6429544e 645 /* fall through */
5272fae8
LM
646
647 case 'p': /* print mode */
1291ede6
LM
648 length = getlength (commands, &commands);
649 if (length == 0){
650 VERBOSE (ERROR, fprintf (stderr, "erroneous length\n"));
651 rc = 1;
652 } else {
6429544e 653 switch (c) {
0304c8cc
LM
654 case '+':
655 rc = gotoaddr ((length > 0) ? addrfile + length : -1);
1291ede6
LM
656 if (rc == 1) {
657 VERBOSE (ERROR, fprintf (stderr, "can't find address (0x%0*lx)\n", getnbdigits (addr), addr));
658 }
0304c8cc
LM
659 break;
660
6429544e
LM
661 case 'd':
662 fseek (fin, length, SEEK_CUR);
663 break;
0304c8cc 664
6429544e
LM
665 case 'p':
666 hexdump (length);
667 break;
668 }
4c4a10dd 669 }
0304c8cc 670 offset = 0;
5272fae8
LM
671 break;
672
673 case 's': /* substitute mode */
1291ede6 674 if (*commands == '/') {
1286d873 675 rc = getpattern (&seq, ++commands, &commands);
1291ede6
LM
676 if (rc == 0) {
677 rc = searchseq (&seq);
678 if (rc == 0) {
679 fseek (fin, offset, SEEK_CUR);
680 rc = gethexaseq (&seq, commands, &commands);
1286d873 681 commands++;
1291ede6 682 if (rc == 0) {
1286d873 683 offset = 0;
1291ede6 684 rc = insertseq (&seq);
1286d873
ML
685 if (rc == 1) {
686 VERBOSE (ERROR, fprintf (stderr, "can't jump (%d)\n", offset));
687 }
1291ede6
LM
688 } else {
689 VERBOSE (ERROR, fprintf (stderr, "erroneous sequence '%s'\n", seq.sequence));
690 }
691 } else {
692 VERBOSE (ERROR, fprintf (stderr, "can't find pattern '%s'\n", seq.sequence));
693 }
694 } else {
695 VERBOSE (ERROR, fprintf (stderr, "erroneous pattern '%s'\n", seq.sequence));
696 }
1286d873
ML
697 } else {
698 VERBOSE (ERROR, fprintf (stderr, "erroneous sequence '%s'\n", seq.sequence));
699 rc = 1;
1291ede6 700 }
0304c8cc 701 offset = 0;
5272fae8
LM
702 break;
703
704 default:
1291ede6 705 VERBOSE (ERROR, fprintf (stderr, "unknown command '%c'\n", commands[-1]));
5272fae8
LM
706 rc = 1;
707 }
708 }
709 }
a1ab98f9 710
ce305529
LM
711 /* end of file */
712 if ((rc == 0) && (fout != NULL)) {
713 while (!feof (fin)) {
714 int nbread = fread (buffer, 1, BUFFERSIZE, fin);
715 if (nbread) {
716 fwrite (buffer, 1, nbread, fout);
717 }
718 }
719 }
720
a1ab98f9 721 /* close all */
5272fae8
LM
722 if (fin) fclose (fin);
723 if (fout) fclose (fout);
a1ab98f9 724
5272fae8 725 return rc;
a1ab98f9
LM
726}
727
a1ab98f9 728// test: hexdump.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
f975557c
LM
729// test: hexdump.exe foo 2>&1 | grep -q 'invalid option'
730// test: hexdump.exe -n 2>&1 | grep -q 'missing number of columns'
731// test: hexdump.exe -v 2>&1 | grep -q 'missing verbose level'
a1ab98f9
LM
732// test: hexdump.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
733// test: hexdump.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
734// test: hexdump.exe -i hexdump.c | grep -q '0x[0-9a-f]*: '
f975557c
LM
735// test: hexdump.exe -i hexdump.ko 2>&1 | grep -q "can't open file"
736// test: hexdump.exe -i hexdump.c -o ko/test.c 2>&1 | grep -q "can't open file"
737// test: cat hexdump.c | hexdump.exe -n 3 | head -2 | tail -1 | grep -q '0x000003: 64 65 70 dep'
ce305529 738// test: hexdump.exe -i hexdump.c -n 3 | head -2 | tail -1 | grep -q '0x0003: 64 65 70 dep'
1286d873 739// test: hexdump.exe -i hexdump.c -v 3 -n 8 | grep -q 'no command'
ce305529 740// test: hexdump.exe -i hexdump.c -o test.c -e 'p 200' | tail -1 | grep -q '0x00c0:'
5bcbfcca 741// test: cmp hexdump.c test.c; x=$?; rm test.c; test x$x = x0
1286d873 742// test: hexdump.exe -i hexdump.c -n 8 -e ' /cflags/ p 17 /debug/ p 8' | grep -q '0x0019: 2a 2f 0a 2f 2a 20 6c 69 \*\/\./\* li'
09776c0a 743// test: hexdump.exe -i hexdump.c -e ' /\099\411\xgg\y/' 2>&1 | grep -c 'incorrect special char' | xargs test 4 -eq
5bcbfcca
LM
744// test: hexdump.exe -i hexdump.c -o test.c -e ' /cfl\x61gs/ p 16 /d\145bug/ p 8' | grep -q '0x0027: 64 65 62 75 67 2e 6f 20 debug.o'
745// test: cmp hexdump.c test.c; x=$?; rm test.c; test x$x = x0
746// test: hexdump.exe -i hexdump.c -e ' /\n/ p 8' | grep -q '0x000d: 0a 2f 2a 20 63 66 6c 61 \./\* cfla'
747// test: hexdump.exe -i hexdump.c -o test.c -e ' /\a\b\e\f\r\t\v/ p 8'; x=$?; test x$x = x1
748// test: cmp hexdump.c test.c; x=$?; rm test.c; test x$x = x0
1291ede6 749// test: hexdump.exe -i hexdump.c -v 3 -e " /\'/" -e ' /\"/' -e ' /\\/' -e ' /\x2a/' -e ' /\x3A/' | grep l: | wc -l | xargs test 5 =
f975557c 750// test: hexdump.exe -i hexdump.c -e ' /\n\/* vim:/ p -' | grep -q ': 74 3a 20 2a 2f 0a *t: \*\/\.'
6429544e 751// test: hexdump.exe -i hexdump.c -e 'p go_to_end' 2>&1 | grep -q 'unknown length'
1286d873 752// test: hexdump.exe -i hexdump.c -e ' /\x41BCD/' 2>&1 | grep -q "can't find pattern"
1291ede6 753// test: hexdump.exe -i hexdump.c -e ' //' 2>&1 | grep -q 'erroneous pattern'
f975557c 754// test: hexdump.exe -i hexdump.c -e 'foo' 2>&1 | grep -q 'unknown command'
cc02a838 755// test: hexdump.exe -i hexdump.c -e '0x20 p 8 64 p 8 0200 p 16' | grep -q '0x0080:'
1286d873
ML
756// test: hexdump.exe -i hexdump.c -e '07777777' 2>&1 | grep -q "can't find address"
757// test: hexdump.exe -i hexdump.c -e '0xFFFFFF' 2>&1 | grep -q "can't find address"
758// test: hexdump.exe -i hexdump.c -e '99999999' 2>&1 | grep -q "can't find address"
759// test: hexdump.exe -i hexdump.c -e '+9999999' 2>&1 | grep -q "can't find address"
09776c0a 760// test: hexdump.exe -i hexdump.c -e '09' 2>&1 | grep -q 'erroneous address'
3bf29ac6 761// test: hexdump.exe -i hexdump.c -e '0xg' 2>&1 | grep -q 'erroneous address'
09776c0a 762// test: hexdump.exe -i hexdump.c -e '1a' 2>&1 | grep -q 'erroneous address'
3bf29ac6 763// test: hexdump.exe -i hexdump.c -o test.c -e ' /cflags/ a 414e5a /link/ i 2F333B'
1286d873
ML
764// test: grep -q '[A]NZcflags' test.c && grep -q '[l]ink/3;er' test.c; x=$?; rm test.c; test x$x = x0
765// test: hexdump.exe -i hexdump.c -e ' /cflags/ a 414e5' 2>&1 | grep -q 'erroneous sequence'
6429544e 766// test: hexdump.exe -i hexdump.c -o test.c -e ' /lags/ d 2'
1286d873 767// test: grep -q '[c]fgs' test.c; x=$?; rm test.c; test x$x = x0
0304c8cc 768// test: hexdump.exe -i hexdump.c -o test.c -e ' /lags/ +2 i 2041'
1286d873
ML
769// test: grep -q '[c]fla Ags:' test.c; x=$?; rm test.c; test x$x = x0
770// test: hexdump.exe -i hexdump.c -o test.c -e ' s/lags/2041/'
771// test: grep -q '[c]f A:' test.c; x=$?; rm test.c; test x$x = x0
772// test: hexdump.exe -i hexdump.c -e ' s' 2>&1 | grep -q 'erroneous sequence'
773// test: hexdump.exe -i hexdump.c -e ' s//' 2>&1 | grep -q 'erroneous pattern'
774// test: hexdump.exe -i hexdump.c -e ' s/\x41BCD/2041/' 2>&1 | grep -q "can't find pattern"
775// test: hexdump.exe -i hexdump.c -e ' s/cflags/414e5/' 2>&1 | grep -q 'erroneous sequence'
60e280f7 776// test: hexdump.exe -i hexdump.exe | grep -q 'ffff'; test x$? = x1
a1ab98f9
LM
777
778/* vim: set ts=4 sw=4 et: */