15 #define CEIL(x, y) (((x) + (y) - 1) / (y))
16 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
17 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
19 //#define BUFFERSIZE 4096
20 #define BUFFERSIZE 256
27 int nbdigits
= NBDIGITS
;
30 char buffer
[BUFFERSIZE
] = {0};
34 char *progname
= NULL
;
40 FILE *fd
= ret
? stderr
: stdout
;
41 fprintf (fd
, "usage: %s [-i file] [-h] [-n nbcols] [-o file] [-v]\n", progname
);
42 fprintf (fd
, " -i: input file\n");
43 fprintf (fd
, " -h: help message\n");
44 fprintf (fd
, " -n: number of columns\n");
45 fprintf (fd
, " -e: commands\n");
46 fprintf (fd
, " -o: output file\n");
47 fprintf (fd
, " -v: verbose level (%d)\n", verbose
);
49 fprintf (fd
, "commands: [/hstr/|0xaddr] [a hstr] [d nb|-] [i hstr] [p nb|-] [s/h1/h2/[g]]\n");
50 fprintf (fd
, " 0x: move to address addr\n");
51 fprintf (fd
, " //: move to hexa stringi hstr\n");
52 fprintf (fd
, " a : append hexa string hstr to current address\n");
53 fprintf (fd
, " d : delete nb bytes (- until end file)\n");
54 fprintf (fd
, " i : insert hexa string hstr to current address\n");
55 fprintf (fd
, " p : print nb bytes (- until end file)\n");
56 fprintf (fd
, " s : substitute h1 by h2 (g for globally)\n");
61 /* get number of digits */
63 int getnbdigits (long int l
) {
74 void printline (char *buffer
, int nb
, int addr
) {
77 printf ("0x%0*x:", nbdigits
, addr
);
78 for (i
= 0; i
< nb
; i
++) {
79 printf (" %02x", buffer
[i
]);
81 for (i
= nb
; i
< nbcols
; i
++) {
85 for (i
= 0; i
< nb
; i
++) {
87 printf ("%c", (c
> 31) && (c
< 127) ? c
: '.');
92 /* write file function */
94 int writefile (char *pt
, int nb
) {
96 fwrite (pt
, 1, nb
, fout
);
101 /* search sequence function */
103 int searchseq (char *seq
) {
108 int len
= strlen (seq
);
110 VERBOSE (DEBUG
, printf ("search sequence: %s\n", seq
));
112 while (!feof (fin
)) {
113 int nbread
= fread (pt
, 1, BUFFERSIZE
- (pt
- buffer
), fin
);
116 for (i
= 0; i
< nb
- len
; i
++) {
118 for (j
= 0; (j
< len
) && (valid
); j
++) {
119 if (pt
[i
+ j
] != seq
[j
]) {
129 writefile (buffer
, nb
- len
);
131 addrfile
+= nb
- len
;
132 for (i
= 0; i
< len
; i
++) {
133 buffer
[i
] = buffer
[nb
- len
+ i
];
138 writefile (buffer
, i
);
141 fseek (fin
, i
- nb
, SEEK_CUR
);
142 VERBOSE (DEBUG
, printf ("found sequence (%d)\n", i
- nb
));
148 writefile (buffer
, nb
);
155 /* hexadecimal dump function */
157 int hexdump (int len
) {
158 char buffer
[BUFFERSIZE
] = {0};
164 while (!feof (fin
)) {
165 int nbtoread
= BUFFERSIZE
- (pt
- buffer
);
166 if ((len
> 0) && (nbtoread
> len
)) {
169 int nbread
= fread (pt
, 1, nbtoread
, fin
);
177 while ((nb
- (int)(pt
- buffer
)) / nbcols
> 0) {
178 printline (pt
, nbcols
, addrfile
);
179 writefile (pt
, nbcols
);
184 /* copy end buffer */
186 for (i
= 0; i
< nb
; i
++) {
191 /* end partial reading */
199 printline (buffer
, nb
, addrfile
);
200 writefile (buffer
, nb
);
207 /* parse octal string */
209 long int octal (char *s
, int n
) {
212 for (i
= 0; i
< n
; i
++) {
213 if ((s
[i
] >= '0') && (s
[i
] <= '9')) {
214 l
= l
* 8 + s
[i
] - '0';
222 /* parse hexa string */
224 long int hexa (char *s
, int n
) {
227 for (i
= 0; i
< n
; i
++) {
229 if ((s
[i
] >= '0') && (s
[i
] <= '9')) {
231 } else if ((s
[i
] >= 'A') && (s
[i
] <= 'F')) {
232 l
+= s
[i
] + 10 - 'A';
233 } else if ((s
[i
] >= 'a') && (s
[i
] <= 'f')) {
234 l
+= s
[i
] + 10 - 'a';
242 /* special character function */
244 char *specialchar (char *s
) {
254 case 'a': l
= 0x07; i
+= 2; break;
255 case 'b': l
= 0x08; i
+= 2; break;
256 case 'e': l
= 0x1b; i
+= 2; break;
257 case 'f': l
= 0x0c; i
+= 2; break;
258 case 'n': l
= 0x0a; i
+= 2; break;
259 case 'r': l
= 0x0d; i
+= 2; break;
260 case 't': l
= 0x09; i
+= 2; break;
261 case 'v': l
= 0x0b; i
+= 2; break;
262 case '\\': l
= '\\'; i
+= 2; break;
263 case '\'': l
= '\''; i
+= 2; break;
264 case '"': l
= '"'; i
+= 2; break;
269 l
= octal (s
+ 1, 3);
282 VERBOSE (DEBUG
, printf("l: 0x%02x '%c'\n", l
, l
));
283 s
[j
++] = (l
!= -1) ? l
: s
[i
++];
292 int main (int argc
, char *argv
[])
297 char *commands
= NULL
;
303 char *pt
= progname
= argv
[0];
305 if ((*pt
== '/') || (*pt
== '\\')) {
312 char *arg
= *(++argv
);
314 VERBOSE (ERROR
, fprintf (stderr
, "%s: invalid option -- %s\n", progname
, arg
));
320 arg
= (arg
[2]) ? arg
+ 2 : (--argc
> 0) ? *(++argv
) : NULL
;
322 arg
= specialchar (arg
);
323 if (commands
== NULL
) {
326 strcat (commands
, " ");
327 strcat (commands
, arg
);
332 input
= (arg
[2]) ? arg
+ 2 : (--argc
> 0 ) ? *(++argv
) : NULL
;
335 arg
= (arg
[2]) ? arg
+ 2 : (--argc
> 0) ? *(++argv
) : NULL
;
337 VERBOSE (ERROR
, fprintf (stderr
, "%s: missing number of columns\n", progname
));
343 output
= (arg
[2]) ? arg
+ 2 : (--argc
> 0 ) ? *(++argv
) : NULL
;
346 arg
= (arg
[2]) ? arg
+ 2 : (--argc
> 0) ? *(++argv
) : NULL
;
348 VERBOSE (ERROR
, fprintf (stderr
, "%s: missing verbose level\n", progname
));
351 verbose
= atoi (arg
);
355 return usage (c
!= 'h');
361 fin
= fopen (input
, "rb");
363 VERBOSE (ERROR
, fprintf (stderr
, "error: can't open file '%s'\n", input
));
372 fout
= fopen (output
, "wb");
374 VERBOSE (ERROR
, fprintf (stderr
, "error: can't open file '%s'\n", output
));
384 fseek (fin
, 0 , SEEK_END
);
385 long int filesize
= ftell (fin
);
386 fseek (fin
, 0 , SEEK_SET
);
387 nbdigits
= getnbdigits (filesize
);
390 if (commands
== NULL
) {
393 VERBOSE (DEBUG
, printf ("commands: %s\n", commands
));
394 while ((*commands
!= '\0') && (rc
== 0)) {
395 switch (*commands
++) {
400 case '/': /* read patern */
403 if (*commands
== '/') {
410 rc
= searchseq (seq
);
412 VERBOSE (ERROR
, fprintf (stderr
, "no sequence definied\n"));
417 case '0': /* read address */
420 case 'a': /* append mode */
423 case 'd': /* delete mode */
426 case 'i': /* insert mode */
429 case 'p': /* print mode */
431 while (*commands
!= '\0') {
432 if ((*commands
== ' ') || (*commands
== '\t')) {
434 } else if ((*commands
>= '0') && (*commands
<= '9')) {
435 printlen
= strtol (commands
, &commands
, 10);
437 } else if (*commands
== '-') {
442 VERBOSE (ERROR
, fprintf (stderr
, "unkown print lenght (%s)\n", commands
));
452 case 's': /* substitute mode */
456 VERBOSE (ERROR
, fprintf (stderr
, "unknown command (%c)\n", commands
[-1]));
463 if ((rc
== 0) && (fout
!= NULL
)) {
464 while (!feof (fin
)) {
465 int nbread
= fread (buffer
, 1, BUFFERSIZE
, fin
);
467 fwrite (buffer
, 1, nbread
, fout
);
473 if (fin
) fclose (fin
);
474 if (fout
) fclose (fout
);
479 // test: hexdump.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
480 // test: hexdump.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
481 // test: hexdump.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
482 // test: hexdump.exe -i hexdump.c | grep -q '0x[0-9a-f]*: '
483 // test: hexdump.exe -i hexdump.c -n 3 | head -2 | tail -1 | grep -q '0x0003: 64 65 70 dep'
484 // test: hexdump.exe -i hexdump.c -o test.c -e 'p 200' | tail -1 | grep -q '0x00c0:'
485 // test: cmp hexdump.c test.c
487 // 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'
488 // 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'
489 // test: cmp hexdump.c test.c
492 /* vim: set ts=4 sw=4 et: */