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