blob: 94a0e6146077545cf8e645d4296b496897ed2b1b [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* xxd: my hexdump facility. jw
2 *
3 * 2.10.90 changed to word output
4 * 3.03.93 new indent style, dumb bug inserted and fixed.
5 * -c option, mls
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
Bram Moolenaar82038d72007-05-10 17:15:45 +00008 * consecutive lines of zeroes, as unix od does.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009 * -a shows them too.
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
35 * xxdline().
36 * 7.06.96 -i printed 'int' instead of 'char'. *blush*
37 * added Bram's OS2 ifdefs...
Bram Moolenaar4b96df52020-01-26 22:00:26 +010038 * 18.07.96 gcc -Wall @ SunOS4 is now silent.
Bram Moolenaar071d4272004-06-13 20:20:40 +000039 * 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
Bram Moolenaar4317d9b2005-03-18 20:25:31 +000043 * (azc10@yahoo.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000044 * 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
46 * missing or wrong.
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
Bram Moolenaar82038d72007-05-10 17:15:45 +000051 * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
Bram Moolenaare0659a62011-04-01 19:14:40 +020052 * 2011 March Better error handling by Florian Zumbiehl.
53 * 2011 April Formatting by Bram Moolenaar
Bram Moolenaar4dcdf292015-03-05 17:51:15 +010054 * 08.06.2013 Little-endian hexdump (-e) and offset (-o) by Vadim Vygonets.
Bram Moolenaard8c56a02019-01-30 23:02:25 +010055 * 11.01.2019 Add full 64/32 bit range to -o and output by Christer Jensen.
Bram Moolenaar363d6142020-05-30 20:50:25 +020056 * 04.02.2020 Add -d for decimal offsets by Aapo Rantalainen
Erik Auerswaldc0a1d372022-01-14 11:58:48 +000057 * 14.01.2022 Disable extra newlines with -c0 -p by Erik Auerswald.
David Gow83e11802022-06-29 20:24:49 +010058 * 20.06.2022 Permit setting the variable names used by -i by David Gow
Christian Brabandt0ffa97e2023-08-31 21:03:02 +020059 * 31.08.2023 -R never/auto/always prints colored output
tristhaus85f45212023-10-06 19:51:13 +020060 * 06.10.2023 enable -r -b to reverse bit dumps
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020062 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000063 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020064 * I hereby grant permission to distribute and use xxd
65 * under X11-MIT or GPL-2.0 (at the user's choice).
66 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020067 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000068 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000069
70/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
71#if _MSC_VER >= 1400
72# define _CRT_SECURE_NO_DEPRECATE
73# define _CRT_NONSTDC_NO_DEPRECATE
74#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010075#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000076# define CYGWIN
77#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000078
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000079#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
80# define _XOPEN_SOURCE 700 /* for fdopen() */
81#endif
82
Bram Moolenaar071d4272004-06-13 20:20:40 +000083#include <stdio.h>
84#ifdef VAXC
85# include <file.h>
86#else
87# include <fcntl.h>
88#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020089#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090# include <io.h> /* for setmode() */
K.Takataf6fc2552023-09-01 18:41:04 +020091# include <windows.h>
92#endif
93#ifdef UNIX
94# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000095#endif
96#include <stdlib.h>
97#include <string.h> /* for strncmp() */
98#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010099#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100#if __MWERKS__ && !defined(BEBOX)
101# include <unix.h> /* for fdopen() on MAC */
102#endif
103
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104
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)
108 */
109#if defined(__GNUC__) && defined(__STDC__)
110# ifndef __USE_FIXED_PROTOTYPES__
111# define __USE_FIXED_PROTOTYPES__
112# endif
113#endif
114
115#ifndef __USE_FIXED_PROTOTYPES__
116/*
117 * This is historic and works only if the compiler really has no prototypes:
118 *
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.
122 */
123#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
124# define __P(a) a
125/* excerpt from my sun_stdlib.h */
126extern int fprintf __P((FILE *, char *, ...));
127extern int fputs __P((char *, FILE *));
128extern int _flsbuf __P((unsigned char, FILE *));
129extern int _filbuf __P((FILE *));
130extern int fflush __P((FILE *));
131extern int fclose __P((FILE *));
132extern int fseek __P((FILE *, long, int));
133extern int rewind __P((FILE *));
134
135extern void perror __P((char *));
136# endif
137#endif
138
OldWorldOrdr1c140302023-10-25 20:57:30 +0200139char version[] = "xxd 2023-10-24 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140#ifdef WIN32
141char osver[] = " (Win32)";
142#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144#endif
145
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200146#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147# define BIN_READ(yes) ((yes) ? "rb" : "rt")
148# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
149# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
150# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000151# define PATH_SEP '\\'
152#elif defined(CYGWIN)
153# define BIN_READ(yes) ((yes) ? "rb" : "rt")
154# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
155# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
156# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
157# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000158#else
159# ifdef VMS
160# define BIN_READ(dummy) "r"
161# define BIN_WRITE(dummy) "w"
162# define BIN_CREAT(dummy) O_CREAT
163# define BIN_ASSIGN(fp, dummy) fp
164# define PATH_SEP ']'
165# define FILE_SEP '.'
166# else
167# define BIN_READ(dummy) "r"
168# define BIN_WRITE(dummy) "w"
169# define BIN_CREAT(dummy) O_CREAT
170# define BIN_ASSIGN(fp, dummy) fp
171# define PATH_SEP '/'
172# endif
173#endif
174
175/* open has only to arguments on the Mac */
176#if __MWERKS__
177# define OPEN(name, mode, umask) open(name, mode)
178#else
179# define OPEN(name, mode, umask) open(name, mode, umask)
180#endif
181
182#ifdef AMIGA
183# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
184#else
185# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
186#endif
187
188#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200189# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190# define __P(a) a
191# else
192# define __P(a) ()
193# endif
194#endif
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
197#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100198#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199
200char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
201
202/* the different hextypes known by this program: */
203#define HEX_NORMAL 0
204#define HEX_POSTSCRIPT 1
205#define HEX_CINCLUDE 2
206#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100207#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200209#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
210
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200211#define COLOR_PROLOGUE \
212l[c++] = '\033'; \
213l[c++] = '['; \
214l[c++] = '1'; \
215l[c++] = ';'; \
216l[c++] = '3';
217
218#define COLOR_EPILOGUE \
219l[c++] = '\033'; \
220l[c++] = '['; \
221l[c++] = '0'; \
222l[c++] = 'm';
223#define COLOR_RED '1'
224#define COLOR_GREEN '2'
225#define COLOR_YELLOW '3'
226#define COLOR_BLUE '4'
227#define COLOR_WHITE '7'
228
Bram Moolenaare0659a62011-04-01 19:14:40 +0200229static char *pname;
230
231 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100232exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233{
234 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
235 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
236 fprintf(stderr, "Options:\n");
237 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200238 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200239 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000240 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
241 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100242 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100243 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 fprintf(stderr, " -h print this summary.\n");
245 fprintf(stderr, " -i output in C include file style.\n");
246 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100247 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100248 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
250 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
251 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200252 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000253 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
254#ifdef TRY_SEEK
255 "[+][-]", "(or +: rel.) ");
256#else
257 "", "");
258#endif
259 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200260 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
262 exit(1);
263}
264
Bram Moolenaare0659a62011-04-01 19:14:40 +0200265 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100266perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200267{
268 fprintf(stderr, "%s: ", pname);
269 perror(NULL);
270 exit(ret);
271}
272
DungSagaa2ffb432021-10-22 15:55:31 +0100273 static void
274error_exit(int ret, char *msg)
275{
276 fprintf(stderr, "%s: %s\n", pname, msg);
277 exit(ret);
278}
279
DungSagad1d8a592021-11-26 13:59:27 +0000280 static int
281getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000282{
DungSagad1d8a592021-11-26 13:59:27 +0000283 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000284 if (c == EOF && ferror(fpi))
285 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000286 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000287}
288
289 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000290putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000291{
292 if (putc(c, fpo) == EOF)
293 perror_exit(3);
294}
295
296 static void
297fputs_or_die(char *s, FILE *fpo)
298{
299 if (fputs(s, fpo) == EOF)
300 perror_exit(3);
301}
302
DungSaga7e5503c2021-12-01 11:24:52 +0000303/* Use a macro to allow for different arguments. */
304#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000305
306 static void
307fclose_or_die(FILE *fpi, FILE *fpo)
308{
309 if (fclose(fpo) != 0)
310 perror_exit(3);
311 if (fclose(fpi) != 0)
312 perror_exit(2);
313}
314
Bram Moolenaar071d4272004-06-13 20:20:40 +0000315/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000316 * If "c" is a hex digit, return the value.
317 * Otherwise return -1.
318 */
319 static int
320parse_hex_digit(int c)
321{
322 return (c >= '0' && c <= '9') ? c - '0'
323 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
324 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
325 : -1;
326}
327
328/*
tristhaus85f45212023-10-06 19:51:13 +0200329 * If "c" is a bin digit, return the value.
330 * Otherwise return -1.
331 */
332 static int
333parse_bin_digit(int c)
334{
335 return (c >= '0' && c <= '1') ? c - '0'
336 : -1;
337}
338
339/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000340 * Ignore text on "fpi" until end-of-line or end-of-file.
341 * Return the '\n' or EOF character.
342 * When an error is encountered exit with an error message.
343 */
344 static int
345skip_to_eol(FILE *fpi, int c)
346{
347 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000348 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000349 return c;
350}
351
352/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000353 * Max. cols binary characters are decoded from the input stream per line.
354 * Two adjacent garbage characters after evaluated data delimit valid data.
355 * Everything up to the next newline is discarded.
356 *
357 * The name is historic and came from 'undo type opt h'.
358 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200359 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100360huntype(
361 FILE *fpi,
362 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100363 int cols,
364 int hextype,
365 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200367 int c, ign_garb = 1, n1 = -1, n2 = 0, n3 = 0, p = cols, bt = 0, b = 0, bcnt = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368 long have_off = 0, want_off = 0;
369
370 rewind(fpi);
371
372 while ((c = getc(fpi)) != EOF)
373 {
374 if (c == '\r') /* Doze style input file? */
375 continue;
376
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100377 /* Allow multiple spaces. This doesn't work when there is normal text
378 * after the hex codes in the last line that looks like hex, thus only
379 * use it for PostScript format. */
380 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000381 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000382
tristhaus85f45212023-10-06 19:51:13 +0200383 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
384 {
385 n3 = n2;
386 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000387
tristhaus85f45212023-10-06 19:51:13 +0200388 n1 = parse_hex_digit(c);
389 if (n1 == -1 && ign_garb)
390 continue;
391 }
392 else /* HEX_BITS */
393 {
394 n1 = parse_hex_digit(c);
395 if (n1 == -1 && ign_garb)
396 continue;
397
398 bt = parse_bin_digit(c);
399 if (bt != -1)
400 {
401 b = ((b << 1) | bt);
402 ++bcnt;
403 }
404 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405
406 ign_garb = 0;
407
tristhaus85f45212023-10-06 19:51:13 +0200408 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409 {
tristhaus85f45212023-10-06 19:51:13 +0200410 if (hextype == HEX_NORMAL)
411 {
412 if (n1 < 0)
413 {
414 p = 0;
415 continue;
416 }
417 want_off = (want_off << 4) | n1;
418 }
419 else /* HEX_BITS */
420 {
OldWorldOrdr1c140302023-10-25 20:57:30 +0200421 if (n1 < 0)
422 {
423 p = 0;
tristhaus85f45212023-10-06 19:51:13 +0200424 bcnt = 0;
OldWorldOrdr1c140302023-10-25 20:57:30 +0200425 continue;
426 }
427 want_off = (want_off << 4) | n1;
tristhaus85f45212023-10-06 19:51:13 +0200428 }
429 continue;
430 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431
432 if (base_off + want_off != have_off)
433 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200434 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100435 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000437 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000438 have_off = base_off + want_off;
439#endif
440 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000441 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000442 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000443 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000444 }
445
tristhaus85f45212023-10-06 19:51:13 +0200446 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
447 {
448 if (n2 >= 0 && n1 >= 0)
449 {
450 putc_or_die((n2 << 4) | n1, fpo);
451 have_off++;
452 want_off++;
453 n1 = -1;
454 if (!hextype && (++p >= cols))
455 /* skip the rest of the line as garbage */
456 c = skip_to_eol(fpi, c);
457 }
458 else if (n1 < 0 && n2 < 0 && n3 < 0)
459 /* already stumbled into garbage, skip line, wait and see */
460 c = skip_to_eol(fpi, c);
461 }
462 else /* HEX_BITS */
463 {
464 if (bcnt == 8)
465 {
466 putc_or_die(b, fpo);
467 have_off++;
468 want_off++;
469 b = 0;
470 bcnt = 0;
471 if (++p >= cols)
472 /* skip the rest of the line as garbage */
473 c = skip_to_eol(fpi, c);
474 }
475 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000476
DungSaga47810462021-10-22 12:55:42 +0100477 if (c == '\n')
478 {
tristhaus85f45212023-10-06 19:51:13 +0200479 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100480 want_off = 0;
481 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000482 ign_garb = 1;
483 }
484 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200485 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100486 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000488 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000489#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000490 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000491 return 0;
492}
493
494/*
495 * Print line l. If nz is false, xxdline regards the line a line of
496 * zeroes. If there are three or more consecutive lines of zeroes,
497 * they are replaced by a single '*' character.
498 *
499 * If the output ends with more than two lines of zeroes, you
500 * should call xxdline again with l being the last line and nz
501 * negative. This ensures that the last line is shown even when
502 * it is all zeroes.
503 *
504 * If nz is always positive, lines are never suppressed.
505 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200506 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100507xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508{
509 static char z[LLEN+1];
510 static int zero_seen = 0;
511
512 if (!nz && zero_seen == 1)
513 strcpy(z, l);
514
515 if (nz || !zero_seen++)
516 {
517 if (nz)
518 {
519 if (nz < 0)
520 zero_seen--;
521 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000522 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000524 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525 }
526 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000527 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000528 if (nz)
529 zero_seen = 0;
530 }
531}
532
533/* This is an EBCDIC to ASCII conversion table */
534/* from a proposed BTL standard April 16, 1979 */
535static unsigned char etoa64[] =
536{
537 0040,0240,0241,0242,0243,0244,0245,0246,
538 0247,0250,0325,0056,0074,0050,0053,0174,
539 0046,0251,0252,0253,0254,0255,0256,0257,
540 0260,0261,0041,0044,0052,0051,0073,0176,
541 0055,0057,0262,0263,0264,0265,0266,0267,
542 0270,0271,0313,0054,0045,0137,0076,0077,
543 0272,0273,0274,0275,0276,0277,0300,0301,
544 0302,0140,0072,0043,0100,0047,0075,0042,
545 0303,0141,0142,0143,0144,0145,0146,0147,
546 0150,0151,0304,0305,0306,0307,0310,0311,
547 0312,0152,0153,0154,0155,0156,0157,0160,
548 0161,0162,0136,0314,0315,0316,0317,0320,
549 0321,0345,0163,0164,0165,0166,0167,0170,
550 0171,0172,0322,0323,0324,0133,0326,0327,
551 0330,0331,0332,0333,0334,0335,0336,0337,
552 0340,0341,0342,0343,0344,0135,0346,0347,
553 0173,0101,0102,0103,0104,0105,0106,0107,
554 0110,0111,0350,0351,0352,0353,0354,0355,
555 0175,0112,0113,0114,0115,0116,0117,0120,
556 0121,0122,0356,0357,0360,0361,0362,0363,
557 0134,0237,0123,0124,0125,0126,0127,0130,
558 0131,0132,0364,0365,0366,0367,0370,0371,
559 0060,0061,0062,0063,0064,0065,0066,0067,
560 0070,0071,0372,0373,0374,0375,0376,0377
561};
562
K.Takataf6fc2552023-09-01 18:41:04 +0200563 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200564begin_coloring_char (char *l, int *c, int e, int ebcdic)
565{
566 if (ebcdic)
567 {
568 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
569 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
570 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
571 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
572 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
573 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
574 (e == 173) || (e == 224) )
575 l[(*c)++] = COLOR_GREEN;
576
577 else if (e == 37 || e == 13 || e == 5)
578 l[(*c)++] = COLOR_YELLOW;
579 else if (e == 0)
580 l[(*c)++] = COLOR_WHITE;
581 else if (e == 255)
582 l[(*c)++] = COLOR_BLUE;
583 else
584 l[(*c)++] = COLOR_RED;
585 }
586 else /* ASCII */
587 {
588 #ifdef __MVS__
589 if (e >= 64)
590 l[(*c)++] = COLOR_GREEN;
591 #else
592 if (e > 31 && e < 127)
593 l[(*c)++] = COLOR_GREEN;
594 #endif
595
596 else if (e == 9 || e == 10 || e == 13)
597 l[(*c)++] = COLOR_YELLOW;
598 else if (e == 0)
599 l[(*c)++] = COLOR_WHITE;
600 else if (e == 255)
601 l[(*c)++] = COLOR_BLUE;
602 else
603 l[(*c)++] = COLOR_RED;
604 }
605 l[(*c)++] = 'm';
606}
607
K.Takataf6fc2552023-09-01 18:41:04 +0200608 static int
609enable_color(void)
610{
611#ifdef WIN32
612 DWORD mode;
613 HANDLE out;
614
615 if (!isatty(1))
616 return 0;
617
618 out = GetStdHandle(STD_OUTPUT_HANDLE);
619 GetConsoleMode(out, &mode);
620 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
621 return (int)SetConsoleMode(out, mode);
622#elif defined(UNIX)
623 return isatty(STDOUT_FILENO);
624#else
625 return 0;
626#endif
627}
628
Bram Moolenaare0659a62011-04-01 19:14:40 +0200629 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100630main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631{
632 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200633 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000634 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200635 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 int ebcdic = 0;
637 int octspergrp = -1; /* number of octets grouped in output */
638 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100639 long length = -1, n = 0, seekoff = 0;
640 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200641 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200642 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100643 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100644 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200645 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200646 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200647
K.Takataf6fc2552023-09-01 18:41:04 +0200648 no_color = getenv("NO_COLOR");
649 if (no_color == NULL || no_color[0] == '\0')
650 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651
652#ifdef AMIGA
653 /* This program doesn't work when started from the Workbench */
654 if (argc == 0)
655 exit(1);
656#endif
657
658 pname = argv[0];
659 for (pp = pname; *pp; )
660 if (*pp++ == PATH_SEP)
661 pname = pp;
662#ifdef FILE_SEP
663 for (pp = pname; *pp; pp++)
664 if (*pp == FILE_SEP)
665 {
666 *pp = '\0';
667 break;
668 }
669#endif
670
671 while (argc >= 2)
672 {
673 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
674 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
675 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100676 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
678 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
679 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200680 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200681 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 else if (!STRNCMP(pp, "-r", 2)) revert++;
683 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
684 else if (!STRNCMP(pp, "-v", 2))
685 {
686 fprintf(stderr, "%s%s\n", version, osver);
687 exit(0);
688 }
689 else if (!STRNCMP(pp, "-c", 2))
690 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100691 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200692 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100693 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000694 {
695 colsgiven = 1;
696 cols = (int)strtol(pp + 2, NULL, 0);
697 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698 else
699 {
700 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200701 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000702 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 cols = (int)strtol(argv[2], NULL, 0);
704 argv++;
705 argc--;
706 }
707 }
708 else if (!STRNCMP(pp, "-g", 2))
709 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100710 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000711 octspergrp = (int)strtol(pp + 2, NULL, 0);
712 else
713 {
714 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200715 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716 octspergrp = (int)strtol(argv[2], NULL, 0);
717 argv++;
718 argc--;
719 }
720 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100721 else if (!STRNCMP(pp, "-o", 2))
722 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100723 int reloffset = 0;
724 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100725 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100726 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100727 else
728 {
729 if (!argv[2])
730 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100731
732 if (argv[2][0] == '+')
733 reloffset++;
734 if (argv[2][reloffset] == '-')
735 negoffset++;
736
737 if (negoffset)
738 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
739 else
740 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
741
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100742 argv++;
743 argc--;
744 }
745 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000746 else if (!STRNCMP(pp, "-s", 2))
747 {
748 relseek = 0;
749 negseek = 0;
750 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
751 {
752#ifdef TRY_SEEK
753 if (pp[2] == '+')
754 relseek++;
755 if (pp[2+relseek] == '-')
756 negseek++;
757#endif
758 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
759 }
760 else
761 {
762 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200763 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764#ifdef TRY_SEEK
765 if (argv[2][0] == '+')
766 relseek++;
767 if (argv[2][relseek] == '-')
768 negseek++;
769#endif
770 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
771 argv++;
772 argc--;
773 }
774 }
775 else if (!STRNCMP(pp, "-l", 2))
776 {
777 if (pp[2] && STRNCMP("en", pp + 2, 2))
778 length = strtol(pp + 2, (char **)NULL, 0);
779 else
780 {
781 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200782 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 length = strtol(argv[2], (char **)NULL, 0);
784 argv++;
785 argc--;
786 }
787 }
David Gow83e11802022-06-29 20:24:49 +0100788 else if (!STRNCMP(pp, "-n", 2))
789 {
790 if (pp[2] && STRNCMP("ame", pp + 2, 3))
791 varname = pp + 2;
792 else
793 {
794 if (!argv[2])
795 exit_with_usage();
796 varname = argv[2];
797 argv++;
798 argc--;
799 }
800 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200801 else if (!STRNCMP(pp, "-R", 2))
802 {
K.Takataf6fc2552023-09-01 18:41:04 +0200803 char *pw = pp + 2;
804 if (!pw[0])
805 {
806 pw = argv[2];
807 argv++;
808 argc--;
809 }
810 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200811 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200812 if (!STRNCMP(pw, "always", 6))
813 {
814 (void)enable_color();
815 color = 1;
816 }
817 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200818 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200819 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200820 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200821 else
822 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200823 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824 else if (!strcmp(pp, "--")) /* end of options */
825 {
826 argv++;
827 argc--;
828 break;
829 }
830 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200831 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 else
833 break; /* not an option */
834
835 argv++; /* advance to next argument */
836 argc--;
837 }
838
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000839 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840 switch (hextype)
841 {
842 case HEX_POSTSCRIPT: cols = 30; break;
843 case HEX_CINCLUDE: cols = 12; break;
844 case HEX_BITS: cols = 6; break;
845 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100846 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 default: cols = 16; break;
848 }
849
850 if (octspergrp < 0)
851 switch (hextype)
852 {
853 case HEX_BITS: octspergrp = 1; break;
854 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100855 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 case HEX_POSTSCRIPT:
857 case HEX_CINCLUDE:
858 default: octspergrp = 0; break;
859 }
860
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000861 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
862 (hextype != HEX_POSTSCRIPT && cols < 1) ||
863 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000864 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 {
866 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
867 exit(1);
868 }
869
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100870 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100872 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100873 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874
875 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200876 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877
878 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
879 BIN_ASSIGN(fp = stdin, !revert);
880 else
881 {
882 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
883 {
884 fprintf(stderr,"%s: ", pname);
885 perror(argv[1]);
886 return 2;
887 }
888 }
889
890 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
891 BIN_ASSIGN(fpo = stdout, revert);
892 else
893 {
894 int fd;
895 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
896
897 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
898 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
899 {
900 fprintf(stderr, "%s: ", pname);
901 perror(argv[2]);
902 return 3;
903 }
904 rewind(fpo);
905 }
906
907 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200908 switch (hextype)
909 {
910 case HEX_NORMAL:
911 case HEX_POSTSCRIPT:
912 case HEX_BITS:
913 return huntype(fp, fpo, cols, hextype,
914 negseek ? -seekoff : seekoff);
915 break;
916 default:
917 error_exit(-1, "Sorry, cannot revert this type of hexdump");
918 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919
920 if (seekoff || negseek || !relseek)
921 {
922#ifdef TRY_SEEK
923 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000924 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000926 e = fseek(fp, negseek ? -seekoff : seekoff,
927 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000928 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000929 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000930 if (e >= 0)
931 seekoff = ftell(fp);
932 else
933#endif
934 {
935 long s = seekoff;
936
937 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000938 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200939 {
DungSaga7e5503c2021-12-01 11:24:52 +0000940 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200941 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 }
943 }
944
945 if (hextype == HEX_CINCLUDE)
946 {
David Gow83e11802022-06-29 20:24:49 +0100947 /* A user-set variable name overrides fp == stdin */
948 if (varname == NULL && fp != stdin)
949 varname = argv[1];
950
951 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000952 {
David Gow83e11802022-06-29 20:24:49 +0100953 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
954 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000955 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
956 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 }
958
959 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000960 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000961 {
DungSaga7e5503c2021-12-01 11:24:52 +0000962 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
963 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 p++;
965 }
966
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000967 if (p)
968 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969
David Gow83e11802022-06-29 20:24:49 +0100970 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000971 {
DungSagad1d8a592021-11-26 13:59:27 +0000972 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100973 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
974 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000975 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000976 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 }
978
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000979 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980 return 0;
981 }
982
983 if (hextype == HEX_POSTSCRIPT)
984 {
985 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000986 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000988 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
989 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000991 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000993 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 p = cols;
995 }
996 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000997 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000998 putc_or_die('\n', fpo);
999 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000 return 0;
1001 }
1002
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001003 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001005 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001006 {
1007 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1008 if (color)
1009 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1010 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011 else /* hextype == HEX_BITS */
1012 grplen = 8 * octspergrp + 1;
1013
DungSagad1d8a592021-11-26 13:59:27 +00001014 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015 {
1016 if (p == 0)
1017 {
DungSaga581f41a2021-11-22 11:57:31 +00001018 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001019 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001020 for (c = addrlen; c < LLEN; l[c++] = ' ')
1021 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 }
DungSaga48608b42021-11-24 11:18:07 +00001023 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1024 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001025 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001026 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001027 if (color)
1028 {
1029 COLOR_PROLOGUE
1030 begin_coloring_char(l,&c,e,ebcdic);
1031 l[c++] = hexx[(e >> 4) & 0xf];
1032 l[c++] = hexx[e & 0xf];
1033 COLOR_EPILOGUE
1034 }
1035 else /*No colors*/
1036 {
1037 l[c] = hexx[(e >> 4) & 0xf];
1038 l[++c] = hexx[e & 0xf];
1039 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001040 }
1041 else /* hextype == HEX_BITS */
1042 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001044 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001046 if (e)
1047 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001048 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001049 if (hextype == HEX_LITTLEENDIAN)
1050 /* last group will be fully used, round up */
1051 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1052 else
1053 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001054
1055 if (color)
1056 {
1057 if (hextype == HEX_BITS)
1058 c += addrlen + 3 + p*12;
1059 else
1060 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1061
1062 if (hextype == HEX_LITTLEENDIAN)
1063 c += 1;
1064
1065 COLOR_PROLOGUE
1066 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001068 if (e >= 64)
1069 l[c++] = e;
1070 else
1071 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001072#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001073 if (ebcdic)
1074 e = (e < 64) ? '.' : etoa64[e-64];
1075 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001076#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001077 COLOR_EPILOGUE
1078 n++;
1079 if (++p == cols)
1080 {
1081 l[c++] = '\n';
1082 l[c++] = '\0';
1083 xxdline(fpo, l, autoskip ? nonzero : 1);
1084 nonzero = 0;
1085 p = 0;
1086 }
1087 }
1088 else /*no colors*/
1089 {
1090 if (ebcdic)
1091 e = (e < 64) ? '.' : etoa64[e-64];
1092
1093 c += addrlen + 3 + p;
1094 l[c++] =
1095#ifdef __MVS__
1096 (e >= 64)
1097#else
1098 (e > 31 && e < 127)
1099#endif
1100 ? e : '.';
1101 n++;
1102 if (++p == cols)
1103 {
1104 l[c++] = '\n';
1105 l[c] = '\0';
1106 xxdline(fpo, l, autoskip ? nonzero : 1);
1107 nonzero = 0;
1108 p = 0;
1109 }
1110 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111 }
1112 if (p)
1113 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001114 l[c++] = '\n';
1115 l[c] = '\0';
1116 if (color)
1117 {
1118 c++;
1119
1120 x = p;
1121 if (hextype == HEX_LITTLEENDIAN)
1122 {
1123 int fill = octspergrp - (p % octspergrp);
1124 if (fill == octspergrp) fill = 0;
1125
1126 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1127
1128 for (i = 0; i < fill;i++)
1129 {
1130 COLOR_PROLOGUE
1131 l[c++] = COLOR_RED;
1132 l[c++] = 'm';
1133 l[c++] = ' '; /* empty space */
1134 COLOR_EPILOGUE
1135 x++;
1136 p++;
1137 }
1138 }
1139
1140 if (hextype != HEX_BITS)
1141 {
1142 c = addrlen + 1 + (grplen * x) / octspergrp;
1143 c += cols - p;
1144 c += (cols - p) / octspergrp;
1145
1146 for (i = cols - p; i > 0;i--)
1147 {
1148 COLOR_PROLOGUE
1149 l[c++] = COLOR_RED;
1150 l[c++] = 'm';
1151 l[c++] = ' '; /* empty space */
1152 COLOR_EPILOGUE
1153 }
1154 }
1155 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156 xxdline(fpo, l, 1);
1157 }
1158 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001159 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001160
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001161 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001162 return 0;
1163}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001164
1165/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */