1 /* xxd: my hexdump facility. jw
3 * 2.10.90 changed to word output
4 * 3.03.93 new indent style, dumb bug inserted and fixed.
6 * 26.04.94 better option parser, -ps, -l, -s added.
7 * 1.07.94 -r badly needs - as input file. Per default autoskip over
8 * consecutive lines of zeroes, as unix od does.
10 * -i dump as c-style #include "file.h"
11 * 1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]'
12 * array is written in correct c-syntax.
13 * -s improved, now defaults to absolute seek, relative requires a '+'.
14 * -r improved, now -r -s -0x... is supported.
15 * change/suppress leading '\0' bytes.
16 * -l n improved: stops exactly after n bytes.
17 * -r improved, better handling of partial lines with trailing garbage.
18 * -r improved, now -r -p works again!
19 * -r improved, less flushing, much faster now! (that was silly)
20 * 3.04.96 Per repeated request of a single person: autoskip defaults to off.
21 * 15.05.96 -v added. They want to know the version.
22 * -a fixed, to show last line inf file ends in all zeros.
23 * -u added: Print upper case hex-letters, as preferred by unix bc.
24 * -h added to usage message. Usage message extended.
25 * Now using outfile if specified even in normal mode, aehem.
26 * No longer mixing of ints and longs. May help doze people.
27 * Added binify ioctl for same reason. (Enough Doze stress for 1996!)
28 * 16.05.96 -p improved, removed occasional superfluous linefeed.
29 * 20.05.96 -l 0 fixed. tried to read anyway.
30 * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames.
31 * compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-)
32 * support --gnuish-longhorn-options
33 * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h
34 * which is included by MacHeaders (Axel Kielhorn). Renamed to
36 * 7.06.96 -i printed 'int' instead of 'char'. *blush*
37 * added Bram's OS2 ifdefs...
38 * 18.07.96 gcc -Wall @ SunOS4 is now slient.
39 * Added osver for MSDOS/DJGPP/WIN32.
40 * 29.08.96 Added size_t to strncmp() for Amiga.
41 * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram)
42 * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII
44 * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com).
45 * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was
47 * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile.
48 * 27.10.98 Fixed: -g option parser required blank.
49 * option -b added: 01000101 binary output in normal format.
50 * 16.05.00 Added VAXC changes by Stephen P. Wall
51 * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
53 * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
55 * Small changes made afterwards by Bram Moolenaar et al.
57 * Distribute freely and credit me,
58 * make money and share with me,
59 * lose money and don't ask me.
62 /* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
64 # define _CRT_SECURE_NO_DEPRECATE
65 # define _CRT_NONSTDC_NO_DEPRECATE
67 #if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
80 #if !defined(OS2) && defined(__EMX__)
83 #if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BORLANDC__) \
85 # include <io.h> /* for setmode() */
92 #include <string.h> /* for strncmp() */
93 #include <ctype.h> /* for isalnum() */
94 #if __MWERKS__ && !defined(BEBOX)
95 # include <unix.h> /* for fdopen() on MAC */
98 #if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno)
99 /* Missing define and prototype grabbed from the BC 4.0 <stdio.h> */
100 # define fileno(f) ((f)->fd)
101 FILE _FAR
*_Cdecl _FARFUNC
fdopen(int __handle
, char _FAR
*__type
);
105 /* This corrects the problem of missing prototypes for certain functions
106 * in some GNU installations (e.g. SunOS 4.1.x).
107 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
109 #if defined(__GNUC__) && defined(__STDC__)
110 # ifndef __USE_FIXED_PROTOTYPES__
111 # define __USE_FIXED_PROTOTYPES__
115 #ifndef __USE_FIXED_PROTOTYPES__
117 * This is historic and works only if the compiler really has no prototypes:
119 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
120 * FILE is defined on OS 4.x, not on 5.x (Solaris).
121 * if __SVR4 is defined (some Solaris versions), don't include this.
123 #if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
125 /* excerpt from my sun_stdlib.h */
126 extern int fprintf
__P((FILE *, char *, ...));
127 extern int fputs
__P((char *, FILE *));
128 extern int _flsbuf
__P((unsigned char, FILE *));
129 extern int _filbuf
__P((FILE *));
130 extern int fflush
__P((FILE *));
131 extern int fclose
__P((FILE *));
132 extern int fseek
__P((FILE *, long, int));
133 extern int rewind
__P((FILE *));
135 extern void perror
__P((char *));
139 extern long int strtol();
140 extern long int ftell();
142 char version
[] = "xxd V1.10 27oct98 by Juergen Weigert";
144 char osver
[] = " (Win32)";
147 char osver
[] = " (dos 32 bit)";
150 char osver
[] = " (dos 16 bit)";
157 #if defined(MSDOS) || defined(WIN32) || defined(OS2)
158 # define BIN_READ(yes) ((yes) ? "rb" : "rt")
159 # define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
160 # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
161 # define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
162 # define PATH_SEP '\\'
163 #elif defined(CYGWIN)
164 # define BIN_READ(yes) ((yes) ? "rb" : "rt")
165 # define BIN_WRITE(yes) ((yes) ? "wb" : "w")
166 # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
167 # define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
168 # define PATH_SEP '/'
171 # define BIN_READ(dummy) "r"
172 # define BIN_WRITE(dummy) "w"
173 # define BIN_CREAT(dummy) O_CREAT
174 # define BIN_ASSIGN(fp, dummy) fp
175 # define PATH_SEP ']'
176 # define FILE_SEP '.'
178 # define BIN_READ(dummy) "r"
179 # define BIN_WRITE(dummy) "w"
180 # define BIN_CREAT(dummy) O_CREAT
181 # define BIN_ASSIGN(fp, dummy) fp
182 # define PATH_SEP '/'
186 /* open has only to arguments on the Mac */
188 # define OPEN(name, mode, umask) open(name, mode)
190 # define OPEN(name, mode, umask) open(name, mode, umask)
194 # define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
196 # define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
200 # if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2) \
201 || defined(__BORLANDC__)
208 /* Let's collect some prototypes */
209 /* CodeWarrior is really picky about missing prototypes */
210 static void exit_with_usage
__P((char *));
211 static int huntype
__P((FILE *, FILE *, FILE *, char *, int, int, long));
212 static void xxdline
__P((FILE *, char *, int));
214 #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
215 #define COLS 256 /* change here, if you ever need more columns */
216 #define LLEN (11 + (9*COLS-1)/1 + COLS + 2)
218 char hexxa
[] = "0123456789abcdef0123456789ABCDEF", *hexx
= hexxa
;
220 /* the different hextypes known by this program: */
222 #define HEX_POSTSCRIPT 1
223 #define HEX_CINCLUDE 2
224 #define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
227 exit_with_usage(pname
)
230 fprintf(stderr
, "Usage:\n %s [options] [infile [outfile]]\n", pname
);
231 fprintf(stderr
, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname
);
232 fprintf(stderr
, "Options:\n");
233 fprintf(stderr
, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
234 fprintf(stderr
, " -b binary digit dump (incompatible with -p,-i,-r). Default hex.\n");
235 fprintf(stderr
, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
236 fprintf(stderr
, " -E show characters in EBCDIC. Default ASCII.\n");
237 fprintf(stderr
, " -g number of octets per group in normal output. Default 2.\n");
238 fprintf(stderr
, " -h print this summary.\n");
239 fprintf(stderr
, " -i output in C include file style.\n");
240 fprintf(stderr
, " -l len stop after <len> octets.\n");
241 fprintf(stderr
, " -ps output in postscript plain hexdump style.\n");
242 fprintf(stderr
, " -r reverse operation: convert (or patch) hexdump into binary.\n");
243 fprintf(stderr
, " -r -s off revert with <off> added to file positions found in hexdump.\n");
244 fprintf(stderr
, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
246 "[+][-]", "(or +: rel.) ");
250 fprintf(stderr
, " -u use upper case hex letters.\n");
251 fprintf(stderr
, " -v show version: \"%s%s\".\n", version
, osver
);
256 * Max. cols binary characters are decoded from the input stream per line.
257 * Two adjacent garbage characters after evaluated data delimit valid data.
258 * Everything up to the next newline is discarded.
260 * The name is historic and came from 'undo type opt h'.
263 huntype(fpi
, fpo
, fperr
, pname
, cols
, hextype
, base_off
)
264 FILE *fpi
, *fpo
, *fperr
;
269 int c
, ign_garb
= 1, n1
= -1, n2
= 0, n3
, p
= cols
;
270 long have_off
= 0, want_off
= 0;
274 while ((c
= getc(fpi
)) != EOF
)
276 if (c
== '\r') /* Doze style input file? */
279 #if 0 /* this doesn't work when there is normal text after the hex codes in
280 the last line that looks like hex */
281 if (c
== ' ' || c
== '\n' || c
== '\t') /* allow multiple spaces */
288 if (c
>= '0' && c
<= '9')
290 else if (c
>= 'a' && c
<= 'f')
292 else if (c
>= 'A' && c
<= 'F')
312 want_off
= (want_off
<< 4) | n1
;
319 if (base_off
+ want_off
!= have_off
)
323 c
= fseek(fpo
, base_off
+ want_off
- have_off
, 1);
325 have_off
= base_off
+ want_off
;
327 if (base_off
+ want_off
< have_off
)
329 fprintf(fperr
, "%s: sorry, cannot seek backwards.\n", pname
);
332 for (; have_off
< base_off
+ want_off
; have_off
++)
336 if (n2
>= 0 && n1
>= 0)
338 putc((n2
<< 4) | n1
, fpo
);
342 if ((++p
>= cols
) && !hextype
)
344 /* skip rest of line as garbage */
346 while ((c
= getc(fpi
)) != '\n' && c
!= EOF
)
351 else if (n1
< 0 && n2
< 0 && n3
< 0)
353 /* already stumbled into garbage, skip line, wait and see */
356 while ((c
= getc(fpi
)) != '\n' && c
!= EOF
)
371 * Print line l. If nz is false, xxdline regards the line a line of
372 * zeroes. If there are three or more consecutive lines of zeroes,
373 * they are replaced by a single '*' character.
375 * If the output ends with more than two lines of zeroes, you
376 * should call xxdline again with l being the last line and nz
377 * negative. This ensures that the last line is shown even when
380 * If nz is always positive, lines are never suppressed.
388 static char z
[LLEN
+1];
389 static int zero_seen
= 0;
391 if (!nz
&& zero_seen
== 1)
394 if (nz
|| !zero_seen
++)
405 if (nz
>= 0 || zero_seen
> 0)
412 /* This is an EBCDIC to ASCII conversion table */
413 /* from a proposed BTL standard April 16, 1979 */
414 static unsigned char etoa64
[] =
416 0040,0240,0241,0242,0243,0244,0245,0246,
417 0247,0250,0325,0056,0074,0050,0053,0174,
418 0046,0251,0252,0253,0254,0255,0256,0257,
419 0260,0261,0041,0044,0052,0051,0073,0176,
420 0055,0057,0262,0263,0264,0265,0266,0267,
421 0270,0271,0313,0054,0045,0137,0076,0077,
422 0272,0273,0274,0275,0276,0277,0300,0301,
423 0302,0140,0072,0043,0100,0047,0075,0042,
424 0303,0141,0142,0143,0144,0145,0146,0147,
425 0150,0151,0304,0305,0306,0307,0310,0311,
426 0312,0152,0153,0154,0155,0156,0157,0160,
427 0161,0162,0136,0314,0315,0316,0317,0320,
428 0321,0345,0163,0164,0165,0166,0167,0170,
429 0171,0172,0322,0323,0324,0133,0326,0327,
430 0330,0331,0332,0333,0334,0335,0336,0337,
431 0340,0341,0342,0343,0344,0135,0346,0347,
432 0173,0101,0102,0103,0104,0105,0106,0107,
433 0110,0111,0350,0351,0352,0353,0354,0355,
434 0175,0112,0113,0114,0115,0116,0117,0120,
435 0121,0122,0356,0357,0360,0361,0362,0363,
436 0134,0237,0123,0124,0125,0126,0127,0130,
437 0131,0132,0364,0365,0366,0367,0370,0371,
438 0060,0061,0062,0063,0064,0065,0066,0067,
439 0070,0071,0372,0373,0374,0375,0376,0377
448 int c
, e
, p
= 0, relseek
= 1, negseek
= 0, revert
= 0;
449 int cols
= 0, nonzero
= 0, autoskip
= 0, hextype
= HEX_NORMAL
;
451 int octspergrp
= -1; /* number of octets grouped in output */
452 int grplen
; /* total chars per octet group */
453 long length
= -1, n
= 0, seekoff
= 0;
458 /* This program doesn't work when started from the Workbench */
464 for (pp
= pname
; *pp
; )
465 if (*pp
++ == PATH_SEP
)
468 for (pp
= pname
; *pp
; pp
++)
478 pp
= argv
[1] + (!STRNCMP(argv
[1], "--", 2) && argv
[1][2]);
479 if (!STRNCMP(pp
, "-a", 2)) autoskip
= 1 - autoskip
;
480 else if (!STRNCMP(pp
, "-b", 2)) hextype
= HEX_BITS
;
481 else if (!STRNCMP(pp
, "-u", 2)) hexx
= hexxa
+ 16;
482 else if (!STRNCMP(pp
, "-p", 2)) hextype
= HEX_POSTSCRIPT
;
483 else if (!STRNCMP(pp
, "-i", 2)) hextype
= HEX_CINCLUDE
;
484 else if (!STRNCMP(pp
, "-r", 2)) revert
++;
485 else if (!STRNCMP(pp
, "-E", 2)) ebcdic
++;
486 else if (!STRNCMP(pp
, "-v", 2))
488 fprintf(stderr
, "%s%s\n", version
, osver
);
491 else if (!STRNCMP(pp
, "-c", 2))
493 if (pp
[2] && STRNCMP("ols", pp
+ 2, 3))
494 cols
= (int)strtol(pp
+ 2, NULL
, 0);
498 exit_with_usage(pname
);
499 cols
= (int)strtol(argv
[2], NULL
, 0);
504 else if (!STRNCMP(pp
, "-g", 2))
506 if (pp
[2] && STRNCMP("group", pp
+ 2, 5))
507 octspergrp
= (int)strtol(pp
+ 2, NULL
, 0);
511 exit_with_usage(pname
);
512 octspergrp
= (int)strtol(argv
[2], NULL
, 0);
517 else if (!STRNCMP(pp
, "-s", 2))
521 if (pp
[2] && STRNCMP("kip", pp
+2, 3) && STRNCMP("eek", pp
+2, 3))
526 if (pp
[2+relseek
] == '-')
529 seekoff
= strtol(pp
+ 2+relseek
+negseek
, (char **)NULL
, 0);
534 exit_with_usage(pname
);
536 if (argv
[2][0] == '+')
538 if (argv
[2][relseek
] == '-')
541 seekoff
= strtol(argv
[2] + relseek
+negseek
, (char **)NULL
, 0);
546 else if (!STRNCMP(pp
, "-l", 2))
548 if (pp
[2] && STRNCMP("en", pp
+ 2, 2))
549 length
= strtol(pp
+ 2, (char **)NULL
, 0);
553 exit_with_usage(pname
);
554 length
= strtol(argv
[2], (char **)NULL
, 0);
559 else if (!strcmp(pp
, "--")) /* end of options */
565 else if (pp
[0] == '-' && pp
[1]) /* unknown option */
566 exit_with_usage(pname
);
568 break; /* not an option */
570 argv
++; /* advance to next argument */
577 case HEX_POSTSCRIPT
: cols
= 30; break;
578 case HEX_CINCLUDE
: cols
= 12; break;
579 case HEX_BITS
: cols
= 6; break;
581 default: cols
= 16; break;
587 case HEX_BITS
: octspergrp
= 1; break;
588 case HEX_NORMAL
: octspergrp
= 2; break;
591 default: octspergrp
= 0; break;
594 if (cols
< 1 || ((hextype
== HEX_NORMAL
|| hextype
== HEX_BITS
)
597 fprintf(stderr
, "%s: invalid number of columns (max. %d).\n", pname
, COLS
);
605 exit_with_usage(pname
);
607 if (argc
== 1 || (argv
[1][0] == '-' && !argv
[1][1]))
608 BIN_ASSIGN(fp
= stdin
, !revert
);
611 if ((fp
= fopen(argv
[1], BIN_READ(!revert
))) == NULL
)
613 fprintf(stderr
,"%s: ", pname
);
619 if (argc
< 3 || (argv
[2][0] == '-' && !argv
[2][1]))
620 BIN_ASSIGN(fpo
= stdout
, revert
);
624 int mode
= revert
? O_WRONLY
: (O_TRUNC
|O_WRONLY
);
626 if (((fd
= OPEN(argv
[2], mode
| BIN_CREAT(revert
), 0666)) < 0) ||
627 (fpo
= fdopen(fd
, BIN_WRITE(revert
))) == NULL
)
629 fprintf(stderr
, "%s: ", pname
);
638 if (hextype
&& (hextype
!= HEX_POSTSCRIPT
))
640 fprintf(stderr
, "%s: sorry, cannot revert this type of hexdump\n", pname
);
643 return huntype(fp
, fpo
, stderr
, pname
, cols
, hextype
,
644 negseek
? -seekoff
: seekoff
);
647 if (seekoff
|| negseek
|| !relseek
)
651 e
= fseek(fp
, negseek
? -seekoff
: seekoff
, 1);
653 e
= fseek(fp
, negseek
? -seekoff
: seekoff
, negseek
? 2 : 0);
654 if (e
< 0 && negseek
)
656 fprintf(stderr
, "%s: sorry cannot seek.\n", pname
);
671 if (hextype
== HEX_CINCLUDE
)
675 fprintf(fpo
, "unsigned char %s", isdigit((int)argv
[1][0]) ? "__" : "");
676 for (e
= 0; (c
= argv
[1][e
]) != 0; e
++)
677 putc(isalnum(c
) ? c
: '_', fpo
);
678 fputs("[] = {\n", fpo
);
682 while ((length
< 0 || p
< length
) && (c
= getc(fp
)) != EOF
)
684 fprintf(fpo
, (hexx
== hexxa
) ? "%s0x%02x" : "%s0X%02X",
685 (p
% cols
) ? ", " : ",\n "+2*!p
, c
);
690 fputs("\n};\n"+3*(fp
== stdin
), fpo
);
694 fprintf(fpo
, "unsigned int %s", isdigit((int)argv
[1][0]) ? "__" : "");
695 for (e
= 0; (c
= argv
[1][e
]) != 0; e
++)
696 putc(isalnum(c
) ? c
: '_', fpo
);
697 fprintf(fpo
, "_len = %d;\n", p
);
705 if (hextype
== HEX_POSTSCRIPT
)
708 while ((length
< 0 || n
< length
) && (e
= getc(fp
)) != EOF
)
710 putchar(hexx
[(e
>> 4) & 0xf]);
711 putchar(hexx
[(e
) & 0xf]);
726 /* hextype: HEX_NORMAL or HEX_BITS */
728 if (hextype
== HEX_NORMAL
)
729 grplen
= octspergrp
+ octspergrp
+ 1; /* chars per octet group */
730 else /* hextype == HEX_BITS */
731 grplen
= 8 * octspergrp
+ 1;
733 while ((length
< 0 || n
< length
) && (e
= getc(fp
)) != EOF
)
737 sprintf(l
, "%07lx: ", n
+ seekoff
);
738 for (c
= 9; c
< LLEN
; l
[c
++] = ' ');
740 if (hextype
== HEX_NORMAL
)
742 l
[c
= (9 + (grplen
* p
) / octspergrp
)] = hexx
[(e
>> 4) & 0xf];
743 l
[++c
] = hexx
[ e
& 0xf];
745 else /* hextype == HEX_BITS */
749 c
= (9 + (grplen
* p
) / octspergrp
) - 1;
750 for (i
= 7; i
>= 0; i
--)
751 l
[++c
] = (e
& (1 << i
)) ? '1' : '0';
754 e
= (e
< 64) ? '.' : etoa64
[e
-64];
755 /* When changing this update definition of LLEN above. */
756 l
[11 + (grplen
* cols
- 1)/octspergrp
+ p
] =
768 l
[c
= (11 + (grplen
* cols
- 1)/octspergrp
+ p
)] = '\n'; l
[++c
] = '\0';
769 xxdline(fpo
, l
, autoskip
? nonzero
: 1);
776 l
[c
= (11 + (grplen
* cols
- 1)/octspergrp
+ p
)] = '\n'; l
[++c
] = '\0';
780 xxdline(fpo
, l
, -1); /* last chance to flush out suppressed lines */