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
77 #if !defined(OS2) && defined(__EMX__)
80 #if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BORLANDC__)
81 # include <io.h> /* for setmode() */
88 #include <string.h> /* for strncmp() */
89 #include <ctype.h> /* for isalnum() */
90 #if __MWERKS__ && !defined(BEBOX)
91 # include <unix.h> /* for fdopen() on MAC */
94 #if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno)
95 /* Missing define and prototype grabbed from the BC 4.0 <stdio.h> */
96 # define fileno(f) ((f)->fd)
97 FILE _FAR
*_Cdecl _FARFUNC
fdopen(int __handle
, char _FAR
*__type
);
101 /* This corrects the problem of missing prototypes for certain functions
102 * in some GNU installations (e.g. SunOS 4.1.x).
103 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
105 #if defined(__GNUC__) && defined(__STDC__)
106 # ifndef __USE_FIXED_PROTOTYPES__
107 # define __USE_FIXED_PROTOTYPES__
111 #ifndef __USE_FIXED_PROTOTYPES__
113 * This is historic and works only if the compiler really has no prototypes:
115 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
116 * FILE is defined on OS 4.x, not on 5.x (Solaris).
117 * if __SVR4 is defined (some Solaris versions), don't include this.
119 #if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
121 /* excerpt from my sun_stdlib.h */
122 extern int fprintf
__P((FILE *, char *, ...));
123 extern int fputs
__P((char *, FILE *));
124 extern int _flsbuf
__P((unsigned char, FILE *));
125 extern int _filbuf
__P((FILE *));
126 extern int fflush
__P((FILE *));
127 extern int fclose
__P((FILE *));
128 extern int fseek
__P((FILE *, long, int));
129 extern int rewind
__P((FILE *));
131 extern void perror
__P((char *));
135 extern long int strtol();
136 extern long int ftell();
138 char version
[] = "xxd V1.10 27oct98 by Juergen Weigert";
140 char osver
[] = " (Win32)";
143 char osver
[] = " (dos 32 bit)";
146 char osver
[] = " (dos 16 bit)";
153 #if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
156 #if defined(MSDOS) || defined(WIN32) || defined(OS2)
157 # define BIN_READ(yes) ((yes) ? "rb" : "rt")
158 # define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
159 # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
160 # define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
161 # define PATH_SEP '\\'
162 #elif defined(CYGWIN)
163 # define BIN_READ(yes) ((yes) ? "rb" : "rt")
164 # define BIN_WRITE(yes) ((yes) ? "wb" : "w")
165 # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
166 # define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
167 # define PATH_SEP '/'
170 # define BIN_READ(dummy) "r"
171 # define BIN_WRITE(dummy) "w"
172 # define BIN_CREAT(dummy) O_CREAT
173 # define BIN_ASSIGN(fp, dummy) fp
174 # define PATH_SEP ']'
175 # define FILE_SEP '.'
177 # define BIN_READ(dummy) "r"
178 # define BIN_WRITE(dummy) "w"
179 # define BIN_CREAT(dummy) O_CREAT
180 # define BIN_ASSIGN(fp, dummy) fp
181 # define PATH_SEP '/'
185 /* open has only to arguments on the Mac */
187 # define OPEN(name, mode, umask) open(name, mode)
189 # define OPEN(name, mode, umask) open(name, mode, umask)
193 # define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
195 # define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
199 # if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2) \
200 || defined(__BORLANDC__)
207 /* Let's collect some prototypes */
208 /* CodeWarrior is really picky about missing prototypes */
209 static void exit_with_usage
__P((char *));
210 static int huntype
__P((FILE *, FILE *, FILE *, char *, int, int, long));
211 static void xxdline
__P((FILE *, char *, int));
213 #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
214 #define COLS 256 /* change here, if you ever need more columns */
215 #define LLEN (11 + (9*COLS-1)/1 + COLS + 2)
217 char hexxa
[] = "0123456789abcdef0123456789ABCDEF", *hexx
= hexxa
;
219 /* the different hextypes known by this program: */
221 #define HEX_POSTSCRIPT 1
222 #define HEX_CINCLUDE 2
223 #define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
226 exit_with_usage(pname
)
229 fprintf(stderr
, "Usage:\n %s [options] [infile [outfile]]\n", pname
);
230 fprintf(stderr
, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname
);
231 fprintf(stderr
, "Options:\n");
232 fprintf(stderr
, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
233 fprintf(stderr
, " -b binary digit dump (incompatible with -p,-i,-r). Default hex.\n");
234 fprintf(stderr
, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
235 fprintf(stderr
, " -E show characters in EBCDIC. Default ASCII.\n");
236 fprintf(stderr
, " -g number of octets per group in normal output. Default 2.\n");
237 fprintf(stderr
, " -h print this summary.\n");
238 fprintf(stderr
, " -i output in C include file style.\n");
239 fprintf(stderr
, " -l len stop after <len> octets.\n");
240 fprintf(stderr
, " -ps output in postscript plain hexdump style.\n");
241 fprintf(stderr
, " -r reverse operation: convert (or patch) hexdump into binary.\n");
242 fprintf(stderr
, " -r -s off revert with <off> added to file positions found in hexdump.\n");
243 fprintf(stderr
, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
245 "[+][-]", "(or +: rel.) ");
249 fprintf(stderr
, " -u use upper case hex letters.\n");
250 fprintf(stderr
, " -v show version: \"%s%s\".\n", version
, osver
);
255 * Max. cols binary characters are decoded from the input stream per line.
256 * Two adjacent garbage characters after evaluated data delimit valid data.
257 * Everything up to the next newline is discarded.
259 * The name is historic and came from 'undo type opt h'.
262 huntype(fpi
, fpo
, fperr
, pname
, cols
, hextype
, base_off
)
263 FILE *fpi
, *fpo
, *fperr
;
268 int c
, ign_garb
= 1, n1
= -1, n2
= 0, n3
, p
= cols
;
269 long have_off
= 0, want_off
= 0;
273 while ((c
= getc(fpi
)) != EOF
)
275 if (c
== '\r') /* Doze style input file? */
278 #if 0 /* this doesn't work when there is normal text after the hex codes in
279 the last line that looks like hex */
280 if (c
== ' ' || c
== '\n' || c
== '\t') /* allow multiple spaces */
287 if (c
>= '0' && c
<= '9')
289 else if (c
>= 'a' && c
<= 'f')
291 else if (c
>= 'A' && c
<= 'F')
311 want_off
= (want_off
<< 4) | n1
;
318 if (base_off
+ want_off
!= have_off
)
322 c
= fseek(fpo
, base_off
+ want_off
- have_off
, 1);
324 have_off
= base_off
+ want_off
;
326 if (base_off
+ want_off
< have_off
)
328 fprintf(fperr
, "%s: sorry, cannot seek backwards.\n", pname
);
331 for (; have_off
< base_off
+ want_off
; have_off
++)
335 if (n2
>= 0 && n1
>= 0)
337 putc((n2
<< 4) | n1
, fpo
);
341 if ((++p
>= cols
) && !hextype
)
343 /* skip rest of line as garbage */
345 while ((c
= getc(fpi
)) != '\n' && c
!= EOF
)
350 else if (n1
< 0 && n2
< 0 && n3
< 0)
352 /* already stumbled into garbage, skip line, wait and see */
355 while ((c
= getc(fpi
)) != '\n' && c
!= EOF
)
370 * Print line l. If nz is false, xxdline regards the line a line of
371 * zeroes. If there are three or more consecutive lines of zeroes,
372 * they are replaced by a single '*' character.
374 * If the output ends with more than two lines of zeroes, you
375 * should call xxdline again with l being the last line and nz
376 * negative. This ensures that the last line is shown even when
379 * If nz is always positive, lines are never suppressed.
387 static char z
[LLEN
+1];
388 static int zero_seen
= 0;
390 if (!nz
&& zero_seen
== 1)
393 if (nz
|| !zero_seen
++)
404 if (nz
>= 0 || zero_seen
> 0)
411 /* This is an EBCDIC to ASCII conversion table */
412 /* from a proposed BTL standard April 16, 1979 */
413 static unsigned char etoa64
[] =
415 0040,0240,0241,0242,0243,0244,0245,0246,
416 0247,0250,0325,0056,0074,0050,0053,0174,
417 0046,0251,0252,0253,0254,0255,0256,0257,
418 0260,0261,0041,0044,0052,0051,0073,0176,
419 0055,0057,0262,0263,0264,0265,0266,0267,
420 0270,0271,0313,0054,0045,0137,0076,0077,
421 0272,0273,0274,0275,0276,0277,0300,0301,
422 0302,0140,0072,0043,0100,0047,0075,0042,
423 0303,0141,0142,0143,0144,0145,0146,0147,
424 0150,0151,0304,0305,0306,0307,0310,0311,
425 0312,0152,0153,0154,0155,0156,0157,0160,
426 0161,0162,0136,0314,0315,0316,0317,0320,
427 0321,0345,0163,0164,0165,0166,0167,0170,
428 0171,0172,0322,0323,0324,0133,0326,0327,
429 0330,0331,0332,0333,0334,0335,0336,0337,
430 0340,0341,0342,0343,0344,0135,0346,0347,
431 0173,0101,0102,0103,0104,0105,0106,0107,
432 0110,0111,0350,0351,0352,0353,0354,0355,
433 0175,0112,0113,0114,0115,0116,0117,0120,
434 0121,0122,0356,0357,0360,0361,0362,0363,
435 0134,0237,0123,0124,0125,0126,0127,0130,
436 0131,0132,0364,0365,0366,0367,0370,0371,
437 0060,0061,0062,0063,0064,0065,0066,0067,
438 0070,0071,0372,0373,0374,0375,0376,0377
447 int c
, e
, p
= 0, relseek
= 1, negseek
= 0, revert
= 0;
448 int cols
= 0, nonzero
= 0, autoskip
= 0, hextype
= HEX_NORMAL
;
450 int octspergrp
= -1; /* number of octets grouped in output */
451 int grplen
; /* total chars per octet group */
452 long length
= -1, n
= 0, seekoff
= 0;
457 /* This program doesn't work when started from the Workbench */
463 for (pp
= pname
; *pp
; )
464 if (*pp
++ == PATH_SEP
)
467 for (pp
= pname
; *pp
; pp
++)
477 pp
= argv
[1] + (!STRNCMP(argv
[1], "--", 2) && argv
[1][2]);
478 if (!STRNCMP(pp
, "-a", 2)) autoskip
= 1 - autoskip
;
479 else if (!STRNCMP(pp
, "-b", 2)) hextype
= HEX_BITS
;
480 else if (!STRNCMP(pp
, "-u", 2)) hexx
= hexxa
+ 16;
481 else if (!STRNCMP(pp
, "-p", 2)) hextype
= HEX_POSTSCRIPT
;
482 else if (!STRNCMP(pp
, "-i", 2)) hextype
= HEX_CINCLUDE
;
483 else if (!STRNCMP(pp
, "-r", 2)) revert
++;
484 else if (!STRNCMP(pp
, "-E", 2)) ebcdic
++;
485 else if (!STRNCMP(pp
, "-v", 2))
487 fprintf(stderr
, "%s%s\n", version
, osver
);
490 else if (!STRNCMP(pp
, "-c", 2))
492 if (pp
[2] && STRNCMP("ols", pp
+ 2, 3))
493 cols
= (int)strtol(pp
+ 2, NULL
, 0);
497 exit_with_usage(pname
);
498 cols
= (int)strtol(argv
[2], NULL
, 0);
503 else if (!STRNCMP(pp
, "-g", 2))
505 if (pp
[2] && STRNCMP("group", pp
+ 2, 5))
506 octspergrp
= (int)strtol(pp
+ 2, NULL
, 0);
510 exit_with_usage(pname
);
511 octspergrp
= (int)strtol(argv
[2], NULL
, 0);
516 else if (!STRNCMP(pp
, "-s", 2))
520 if (pp
[2] && STRNCMP("kip", pp
+2, 3) && STRNCMP("eek", pp
+2, 3))
525 if (pp
[2+relseek
] == '-')
528 seekoff
= strtol(pp
+ 2+relseek
+negseek
, (char **)NULL
, 0);
533 exit_with_usage(pname
);
535 if (argv
[2][0] == '+')
537 if (argv
[2][relseek
] == '-')
540 seekoff
= strtol(argv
[2] + relseek
+negseek
, (char **)NULL
, 0);
545 else if (!STRNCMP(pp
, "-l", 2))
547 if (pp
[2] && STRNCMP("en", pp
+ 2, 2))
548 length
= strtol(pp
+ 2, (char **)NULL
, 0);
552 exit_with_usage(pname
);
553 length
= strtol(argv
[2], (char **)NULL
, 0);
558 else if (!strcmp(pp
, "--")) /* end of options */
564 else if (pp
[0] == '-' && pp
[1]) /* unknown option */
565 exit_with_usage(pname
);
567 break; /* not an option */
569 argv
++; /* advance to next argument */
576 case HEX_POSTSCRIPT
: cols
= 30; break;
577 case HEX_CINCLUDE
: cols
= 12; break;
578 case HEX_BITS
: cols
= 6; break;
580 default: cols
= 16; break;
586 case HEX_BITS
: octspergrp
= 1; break;
587 case HEX_NORMAL
: octspergrp
= 2; break;
590 default: octspergrp
= 0; break;
593 if (cols
< 1 || ((hextype
== HEX_NORMAL
|| hextype
== HEX_BITS
)
596 fprintf(stderr
, "%s: invalid number of columns (max. %d).\n", pname
, COLS
);
604 exit_with_usage(pname
);
606 if (argc
== 1 || (argv
[1][0] == '-' && !argv
[1][1]))
607 BIN_ASSIGN(fp
= stdin
, !revert
);
610 if ((fp
= fopen(argv
[1], BIN_READ(!revert
))) == NULL
)
612 fprintf(stderr
,"%s: ", pname
);
618 if (argc
< 3 || (argv
[2][0] == '-' && !argv
[2][1]))
619 BIN_ASSIGN(fpo
= stdout
, revert
);
623 int mode
= revert
? O_WRONLY
: (O_TRUNC
|O_WRONLY
);
625 if (((fd
= OPEN(argv
[2], mode
| BIN_CREAT(revert
), 0666)) < 0) ||
626 (fpo
= fdopen(fd
, BIN_WRITE(revert
))) == NULL
)
628 fprintf(stderr
, "%s: ", pname
);
637 if (hextype
&& (hextype
!= HEX_POSTSCRIPT
))
639 fprintf(stderr
, "%s: sorry, cannot revert this type of hexdump\n", pname
);
642 return huntype(fp
, fpo
, stderr
, pname
, cols
, hextype
,
643 negseek
? -seekoff
: seekoff
);
646 if (seekoff
|| negseek
|| !relseek
)
650 e
= fseek(fp
, negseek
? -seekoff
: seekoff
, 1);
652 e
= fseek(fp
, negseek
? -seekoff
: seekoff
, negseek
? 2 : 0);
653 if (e
< 0 && negseek
)
655 fprintf(stderr
, "%s: sorry cannot seek.\n", pname
);
670 if (hextype
== HEX_CINCLUDE
)
674 fprintf(fpo
, "unsigned char %s", isdigit((int)argv
[1][0]) ? "__" : "");
675 for (e
= 0; (c
= argv
[1][e
]) != 0; e
++)
676 putc(isalnum(c
) ? c
: '_', fpo
);
677 fputs("[] = {\n", fpo
);
681 while ((length
< 0 || p
< length
) && (c
= getc(fp
)) != EOF
)
683 fprintf(fpo
, (hexx
== hexxa
) ? "%s0x%02x" : "%s0X%02X",
684 (p
% cols
) ? ", " : ",\n "+2*!p
, c
);
689 fputs("\n};\n"+3*(fp
== stdin
), fpo
);
693 fprintf(fpo
, "unsigned int %s", isdigit((int)argv
[1][0]) ? "__" : "");
694 for (e
= 0; (c
= argv
[1][e
]) != 0; e
++)
695 putc(isalnum(c
) ? c
: '_', fpo
);
696 fprintf(fpo
, "_len = %d;\n", p
);
704 if (hextype
== HEX_POSTSCRIPT
)
707 while ((length
< 0 || n
< length
) && (e
= getc(fp
)) != EOF
)
709 putchar(hexx
[(e
>> 4) & 0xf]);
710 putchar(hexx
[(e
) & 0xf]);
725 /* hextype: HEX_NORMAL or HEX_BITS */
727 if (hextype
== HEX_NORMAL
)
728 grplen
= octspergrp
+ octspergrp
+ 1; /* chars per octet group */
729 else /* hextype == HEX_BITS */
730 grplen
= 8 * octspergrp
+ 1;
732 while ((length
< 0 || n
< length
) && (e
= getc(fp
)) != EOF
)
736 sprintf(l
, "%07lx: ", n
+ seekoff
);
737 for (c
= 9; c
< LLEN
; l
[c
++] = ' ');
739 if (hextype
== HEX_NORMAL
)
741 l
[c
= (9 + (grplen
* p
) / octspergrp
)] = hexx
[(e
>> 4) & 0xf];
742 l
[++c
] = hexx
[ e
& 0xf];
744 else /* hextype == HEX_BITS */
748 c
= (9 + (grplen
* p
) / octspergrp
) - 1;
749 for (i
= 7; i
>= 0; i
--)
750 l
[++c
] = (e
& (1 << i
)) ? '1' : '0';
753 e
= (e
< 64) ? '.' : etoa64
[e
-64];
754 /* When changing this update definition of LLEN above. */
755 l
[11 + (grplen
* cols
- 1)/octspergrp
+ p
] =
767 l
[c
= (11 + (grplen
* cols
- 1)/octspergrp
+ p
)] = '\n'; l
[++c
] = '\0';
768 xxdline(fpo
, l
, autoskip
? nonzero
: 1);
775 l
[c
= (11 + (grplen
* cols
- 1)/octspergrp
+ p
)] = '\n'; l
[++c
] = '\0';
779 xxdline(fpo
, l
, -1); /* last chance to flush out suppressed lines */