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))
20 //#define BUFFERSIZE 4096
21 #define BUFFERSIZE 256
26 char *buffer
[BUFFERSIZE
] = {0};
29 char *progname
= NULL
;
35 FILE *fd
= ret
? stderr
: stdout
;
36 fprintf (fd
, "usage: %s [-i file] [-h] [-n nbcols] [-o file] [-v]\n", progname
);
37 fprintf (fd
, " -i: input file\n");
38 fprintf (fd
, " -h: help message\n");
39 fprintf (fd
, " -n: number of columns\n");
40 fprintf (fd
, " -e: commands\n");
41 fprintf (fd
, " -o: output file\n");
42 fprintf (fd
, " -v: verbose level (%d)\n", verbose
);
44 fprintf (fd
, "commands: [/hstr/|0xaddr] [a hstr] [d nb|-] [i hstr] [p nb|-] [s/h1/h2/[g]]\n");
45 fprintf (fd
, " 0x: move to address addr\n");
46 fprintf (fd
, " //: move to hexa stringi hstr\n");
47 fprintf (fd
, " a : append hexa string hstr to current address\n");
48 fprintf (fd
, " d : delete nb bytes (- until end file)\n");
49 fprintf (fd
, " i : insert hexa string hstr to current address\n");
50 fprintf (fd
, " p : print nb bytes (- until end file)\n");
51 fprintf (fd
, " s : substitute h1 by h2 (g for globally)\n");
56 /* get number of digits */
58 int getnbdigits (long int l
) {
69 void printline (char *buffer
, int nbcols
, int nb
, int addr
, int nbdigits
) {
72 printf ("0x%0*x:", nbdigits
, addr
);
73 for (i
= 0; i
< nb
; i
++) {
74 printf (" %02x", buffer
[i
]);
76 for (i
= nb
; i
< nbcols
; i
++) {
80 for (i
= 0; i
< nb
; i
++) {
82 printf ("%c", (c
> 31) && (c
< 127) ? c
: '.');
87 /* write file function */
89 int writefile (char *pt
, int nb
) {
91 fwrite (pt
, 1, nb
, fout
);
96 /* hexadecimal dump function */
98 int hexdump (int nbcols
, int len
) {
99 char buffer
[BUFFERSIZE
] = {0};
107 fseek (fin
, 0 , SEEK_END
);
108 long int filesize
= ftell (fin
);
109 fseek (fin
, 0 , SEEK_SET
);
110 nbdigits
= getnbdigits (filesize
);
117 while (!feof (fin
)) {
118 int nbtoread
= BUFFERSIZE
- (pt
- buffer
);
119 if ((len
> 0) && (nbtoread
> len
)) {
122 int nbread
= fread (pt
, 1, nbtoread
, fin
);
130 while ((nb
- (int)(pt
- buffer
)) / nbcols
> 0) {
131 printline (pt
, nbcols
, nbcols
, addr
, nbdigits
);
132 writefile (pt
, nbcols
);
137 /* copy end buffer */
139 for (i
= 0; i
< nb
; i
++) {
144 /* end partial reading */
152 printline (buffer
, nbcols
, nb
, addr
, nbdigits
);
161 int main (int argc
, char *argv
[])
167 char *commands
= NULL
;
171 char *pt
= progname
= argv
[0];
173 if ((*pt
== '/') || (*pt
== '\\')) {
180 while ((c
= getopt(argc
, argv
, "e:i:hn:o:v:")) != EOF
) {
186 if (commands
== NULL
) {
189 strcat (commands
, " ");
190 strcat (commands
, optarg
);
194 nbcols
= atoi (optarg
);
200 verbose
= atoi (optarg
);
207 if (argc
- optind
!= 0) {
208 fprintf (stderr
, "%s: invalid option -- %s\n", progname
, argv
[optind
]);
214 fin
= fopen (input
, "rb");
216 VERBOSE (ERROR
, fprintf (stderr
, "error: can't open file '%s'\n", input
));
225 fout
= fopen (output
, "wb");
227 VERBOSE (ERROR
, fprintf (stderr
, "error: can't open file '%s'\n", output
));
235 if (commands
== NULL
) {
236 hexdump (nbcols
, -1);
238 VERBOSE (DEBUG
, printf ("commands: %s\n", commands
));
239 while ((*commands
!= '\0') && (rc
== 0)) {
240 switch (*commands
++) {
245 case '/': /* read patern */
248 case '0': /* read address */
251 case 'a': /* append mode */
254 case 'd': /* delete mode */
257 case 'i': /* insert mode */
260 case 'p': /* print mode */
262 while (*commands
!= '\0') {
263 if ((*commands
== ' ') || (*commands
== '\t')) {
265 } else if ((*commands
>= '0') && (*commands
<= '9')) {
266 printlen
= strtol (commands
, &commands
, 10);
268 } else if (*commands
== '-') {
273 VERBOSE (ERROR
, fprintf (stderr
, "unkown print lenght (%s)\n", commands
));
278 if (rc
== 0) hexdump (nbcols
, printlen
);
281 case 's': /* substitute mode */
285 VERBOSE (ERROR
, fprintf (stderr
, "unknown command (%c)\n", commands
[-1]));
292 if ((rc
== 0) && (fout
!= NULL
)) {
293 while (!feof (fin
)) {
294 int nbread
= fread (buffer
, 1, BUFFERSIZE
, fin
);
296 fwrite (buffer
, 1, nbread
, fout
);
302 if (fin
) fclose (fin
);
303 if (fout
) fclose (fout
);
308 // test: hexdump.exe -h
309 // test: hexdump.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
310 // test: hexdump.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }'
311 // test: hexdump.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }'
312 // test: hexdump.exe -i hexdump.c | grep -q '0x[0-9a-f]*: '
313 // test: hexdump.exe -i hexdump.c -n 3 | head -2 | tail -1 | grep -q '0x0003: 64 65 70 dep'
314 // test: hexdump.exe -i hexdump.c -o test.c -e 'p 200' | tail -1 | grep -q '0x00c0:'
315 // test: cmp hexdump.c test.c
318 /* vim: set ts=4 sw=4 et: */