blob: a5f5f04ade27d1dbd93cf9c021cdee4a477caf20 [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
Igor Todorovski48a75f32024-01-09 21:05:48 +000061 * 12.01.2024 disable auto-conversion for z/OS (MVS)
Kuratius7062be12024-01-17 18:37:32 +010062 * 17.01.2024 use size_t instead of usigned int for code-generation (-i), #13876
Christian Brabandtfa8c9712024-01-25 20:50:49 +010063 * 25.01.2024 revert the previous patch (size_t instead of unsigned int)
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020065 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000066 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020067 * I hereby grant permission to distribute and use xxd
68 * under X11-MIT or GPL-2.0 (at the user's choice).
69 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020070 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000071 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000072
73/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
74#if _MSC_VER >= 1400
75# define _CRT_SECURE_NO_DEPRECATE
76# define _CRT_NONSTDC_NO_DEPRECATE
77#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010078#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000079# define CYGWIN
80#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000081
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000082#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
83# define _XOPEN_SOURCE 700 /* for fdopen() */
84#endif
85
Bram Moolenaar071d4272004-06-13 20:20:40 +000086#include <stdio.h>
87#ifdef VAXC
88# include <file.h>
89#else
90# include <fcntl.h>
91#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020092#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000093# include <io.h> /* for setmode() */
Ken Takatac4a40382023-10-25 21:17:35 +020094#endif
95#ifdef WIN32
K.Takataf6fc2552023-09-01 18:41:04 +020096# include <windows.h>
97#endif
98#ifdef UNIX
99# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100#endif
101#include <stdlib.h>
Keith Thompson184f71c2024-01-04 21:19:04 +0100102#include <string.h>
103#include <ctype.h>
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100104#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105#if __MWERKS__ && !defined(BEBOX)
106# include <unix.h> /* for fdopen() on MAC */
107#endif
108
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109
110/* This corrects the problem of missing prototypes for certain functions
111 * in some GNU installations (e.g. SunOS 4.1.x).
112 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
113 */
114#if defined(__GNUC__) && defined(__STDC__)
115# ifndef __USE_FIXED_PROTOTYPES__
116# define __USE_FIXED_PROTOTYPES__
117# endif
118#endif
119
120#ifndef __USE_FIXED_PROTOTYPES__
121/*
122 * This is historic and works only if the compiler really has no prototypes:
123 *
124 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
125 * FILE is defined on OS 4.x, not on 5.x (Solaris).
126 * if __SVR4 is defined (some Solaris versions), don't include this.
127 */
128#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
129# define __P(a) a
130/* excerpt from my sun_stdlib.h */
131extern int fprintf __P((FILE *, char *, ...));
132extern int fputs __P((char *, FILE *));
133extern int _flsbuf __P((unsigned char, FILE *));
134extern int _filbuf __P((FILE *));
135extern int fflush __P((FILE *));
136extern int fclose __P((FILE *));
137extern int fseek __P((FILE *, long, int));
138extern int rewind __P((FILE *));
139
140extern void perror __P((char *));
141# endif
142#endif
143
Christian Brabandtfa8c9712024-01-25 20:50:49 +0100144char version[] = "xxd 2024-01-25 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145#ifdef WIN32
146char osver[] = " (Win32)";
147#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149#endif
150
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200151#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000152# define BIN_READ(yes) ((yes) ? "rb" : "rt")
153# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
154# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
155# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000156# define PATH_SEP '\\'
157#elif defined(CYGWIN)
158# define BIN_READ(yes) ((yes) ? "rb" : "rt")
159# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
160# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
161# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
162# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000163#else
164# ifdef VMS
165# define BIN_READ(dummy) "r"
166# define BIN_WRITE(dummy) "w"
167# define BIN_CREAT(dummy) O_CREAT
168# define BIN_ASSIGN(fp, dummy) fp
169# define PATH_SEP ']'
170# define FILE_SEP '.'
171# else
172# define BIN_READ(dummy) "r"
173# define BIN_WRITE(dummy) "w"
174# define BIN_CREAT(dummy) O_CREAT
175# define BIN_ASSIGN(fp, dummy) fp
176# define PATH_SEP '/'
177# endif
178#endif
179
180/* open has only to arguments on the Mac */
181#if __MWERKS__
182# define OPEN(name, mode, umask) open(name, mode)
183#else
184# define OPEN(name, mode, umask) open(name, mode, umask)
185#endif
186
187#ifdef AMIGA
188# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
189#else
190# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
191#endif
192
193#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200194# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195# define __P(a) a
196# else
197# define __P(a) ()
198# endif
199#endif
200
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
202#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100203#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000204
205char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
206
207/* the different hextypes known by this program: */
208#define HEX_NORMAL 0
209#define HEX_POSTSCRIPT 1
210#define HEX_CINCLUDE 2
211#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100212#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213
Keith Thompson184f71c2024-01-04 21:19:04 +0100214#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : (c))
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200215
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200216#define COLOR_PROLOGUE \
217l[c++] = '\033'; \
218l[c++] = '['; \
219l[c++] = '1'; \
220l[c++] = ';'; \
221l[c++] = '3';
222
223#define COLOR_EPILOGUE \
224l[c++] = '\033'; \
225l[c++] = '['; \
226l[c++] = '0'; \
227l[c++] = 'm';
228#define COLOR_RED '1'
229#define COLOR_GREEN '2'
230#define COLOR_YELLOW '3'
231#define COLOR_BLUE '4'
232#define COLOR_WHITE '7'
233
Bram Moolenaare0659a62011-04-01 19:14:40 +0200234static char *pname;
235
236 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100237exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238{
239 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
240 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
241 fprintf(stderr, "Options:\n");
242 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200243 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200244 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000245 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
246 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100247 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100248 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249 fprintf(stderr, " -h print this summary.\n");
250 fprintf(stderr, " -i output in C include file style.\n");
251 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100252 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100253 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000254 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
255 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
256 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200257 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000258 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
259#ifdef TRY_SEEK
260 "[+][-]", "(or +: rel.) ");
261#else
262 "", "");
263#endif
264 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200265 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000266 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
267 exit(1);
268}
269
Bram Moolenaare0659a62011-04-01 19:14:40 +0200270 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100271perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200272{
273 fprintf(stderr, "%s: ", pname);
274 perror(NULL);
275 exit(ret);
276}
277
DungSagaa2ffb432021-10-22 15:55:31 +0100278 static void
279error_exit(int ret, char *msg)
280{
281 fprintf(stderr, "%s: %s\n", pname, msg);
282 exit(ret);
283}
284
DungSagad1d8a592021-11-26 13:59:27 +0000285 static int
286getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000287{
DungSagad1d8a592021-11-26 13:59:27 +0000288 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000289 if (c == EOF && ferror(fpi))
290 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000291 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000292}
293
294 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000295putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000296{
297 if (putc(c, fpo) == EOF)
298 perror_exit(3);
299}
300
301 static void
302fputs_or_die(char *s, FILE *fpo)
303{
304 if (fputs(s, fpo) == EOF)
305 perror_exit(3);
306}
307
DungSaga7e5503c2021-12-01 11:24:52 +0000308/* Use a macro to allow for different arguments. */
309#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000310
311 static void
312fclose_or_die(FILE *fpi, FILE *fpo)
313{
314 if (fclose(fpo) != 0)
315 perror_exit(3);
316 if (fclose(fpi) != 0)
317 perror_exit(2);
318}
319
Bram Moolenaar071d4272004-06-13 20:20:40 +0000320/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000321 * If "c" is a hex digit, return the value.
322 * Otherwise return -1.
323 */
324 static int
325parse_hex_digit(int c)
326{
327 return (c >= '0' && c <= '9') ? c - '0'
328 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
329 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
330 : -1;
331}
332
333/*
tristhaus85f45212023-10-06 19:51:13 +0200334 * If "c" is a bin digit, return the value.
335 * Otherwise return -1.
336 */
337 static int
338parse_bin_digit(int c)
339{
340 return (c >= '0' && c <= '1') ? c - '0'
341 : -1;
342}
343
344/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000345 * Ignore text on "fpi" until end-of-line or end-of-file.
346 * Return the '\n' or EOF character.
347 * When an error is encountered exit with an error message.
348 */
349 static int
350skip_to_eol(FILE *fpi, int c)
351{
352 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000353 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000354 return c;
355}
356
357/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358 * Max. cols binary characters are decoded from the input stream per line.
359 * Two adjacent garbage characters after evaluated data delimit valid data.
360 * Everything up to the next newline is discarded.
361 *
362 * The name is historic and came from 'undo type opt h'.
363 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200364 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100365huntype(
366 FILE *fpi,
367 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100368 int cols,
369 int hextype,
370 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000371{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200372 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 +0000373 long have_off = 0, want_off = 0;
374
375 rewind(fpi);
376
377 while ((c = getc(fpi)) != EOF)
378 {
379 if (c == '\r') /* Doze style input file? */
380 continue;
381
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100382 /* Allow multiple spaces. This doesn't work when there is normal text
383 * after the hex codes in the last line that looks like hex, thus only
384 * use it for PostScript format. */
385 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000386 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000387
tristhaus85f45212023-10-06 19:51:13 +0200388 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
389 {
390 n3 = n2;
391 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000392
tristhaus85f45212023-10-06 19:51:13 +0200393 n1 = parse_hex_digit(c);
394 if (n1 == -1 && ign_garb)
395 continue;
396 }
397 else /* HEX_BITS */
398 {
399 n1 = parse_hex_digit(c);
400 if (n1 == -1 && ign_garb)
401 continue;
402
403 bt = parse_bin_digit(c);
404 if (bt != -1)
405 {
406 b = ((b << 1) | bt);
407 ++bcnt;
408 }
409 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410
411 ign_garb = 0;
412
tristhaus85f45212023-10-06 19:51:13 +0200413 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414 {
tristhaus85f45212023-10-06 19:51:13 +0200415 if (hextype == HEX_NORMAL)
416 {
417 if (n1 < 0)
418 {
419 p = 0;
420 continue;
421 }
422 want_off = (want_off << 4) | n1;
423 }
424 else /* HEX_BITS */
425 {
OldWorldOrdr1c140302023-10-25 20:57:30 +0200426 if (n1 < 0)
427 {
428 p = 0;
tristhaus85f45212023-10-06 19:51:13 +0200429 bcnt = 0;
OldWorldOrdr1c140302023-10-25 20:57:30 +0200430 continue;
431 }
432 want_off = (want_off << 4) | n1;
tristhaus85f45212023-10-06 19:51:13 +0200433 }
434 continue;
435 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436
437 if (base_off + want_off != have_off)
438 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200439 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100440 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000442 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000443 have_off = base_off + want_off;
444#endif
445 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000446 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000447 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000448 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449 }
450
tristhaus85f45212023-10-06 19:51:13 +0200451 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
452 {
453 if (n2 >= 0 && n1 >= 0)
454 {
455 putc_or_die((n2 << 4) | n1, fpo);
456 have_off++;
457 want_off++;
458 n1 = -1;
459 if (!hextype && (++p >= cols))
460 /* skip the rest of the line as garbage */
461 c = skip_to_eol(fpi, c);
462 }
463 else if (n1 < 0 && n2 < 0 && n3 < 0)
464 /* already stumbled into garbage, skip line, wait and see */
465 c = skip_to_eol(fpi, c);
466 }
467 else /* HEX_BITS */
468 {
469 if (bcnt == 8)
470 {
471 putc_or_die(b, fpo);
472 have_off++;
473 want_off++;
474 b = 0;
475 bcnt = 0;
476 if (++p >= cols)
477 /* skip the rest of the line as garbage */
478 c = skip_to_eol(fpi, c);
479 }
480 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000481
DungSaga47810462021-10-22 12:55:42 +0100482 if (c == '\n')
483 {
tristhaus85f45212023-10-06 19:51:13 +0200484 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100485 want_off = 0;
486 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487 ign_garb = 1;
488 }
489 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200490 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100491 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000493 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000494#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000495 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496 return 0;
497}
498
499/*
500 * Print line l. If nz is false, xxdline regards the line a line of
501 * zeroes. If there are three or more consecutive lines of zeroes,
502 * they are replaced by a single '*' character.
503 *
504 * If the output ends with more than two lines of zeroes, you
505 * should call xxdline again with l being the last line and nz
506 * negative. This ensures that the last line is shown even when
507 * it is all zeroes.
508 *
509 * If nz is always positive, lines are never suppressed.
510 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200511 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100512xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000513{
514 static char z[LLEN+1];
515 static int zero_seen = 0;
516
517 if (!nz && zero_seen == 1)
518 strcpy(z, l);
519
520 if (nz || !zero_seen++)
521 {
522 if (nz)
523 {
524 if (nz < 0)
525 zero_seen--;
526 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000527 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000528 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000529 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000530 }
531 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000532 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533 if (nz)
534 zero_seen = 0;
535 }
536}
537
538/* This is an EBCDIC to ASCII conversion table */
539/* from a proposed BTL standard April 16, 1979 */
540static unsigned char etoa64[] =
541{
542 0040,0240,0241,0242,0243,0244,0245,0246,
543 0247,0250,0325,0056,0074,0050,0053,0174,
544 0046,0251,0252,0253,0254,0255,0256,0257,
545 0260,0261,0041,0044,0052,0051,0073,0176,
546 0055,0057,0262,0263,0264,0265,0266,0267,
547 0270,0271,0313,0054,0045,0137,0076,0077,
548 0272,0273,0274,0275,0276,0277,0300,0301,
549 0302,0140,0072,0043,0100,0047,0075,0042,
550 0303,0141,0142,0143,0144,0145,0146,0147,
551 0150,0151,0304,0305,0306,0307,0310,0311,
552 0312,0152,0153,0154,0155,0156,0157,0160,
553 0161,0162,0136,0314,0315,0316,0317,0320,
554 0321,0345,0163,0164,0165,0166,0167,0170,
555 0171,0172,0322,0323,0324,0133,0326,0327,
556 0330,0331,0332,0333,0334,0335,0336,0337,
557 0340,0341,0342,0343,0344,0135,0346,0347,
558 0173,0101,0102,0103,0104,0105,0106,0107,
559 0110,0111,0350,0351,0352,0353,0354,0355,
560 0175,0112,0113,0114,0115,0116,0117,0120,
561 0121,0122,0356,0357,0360,0361,0362,0363,
562 0134,0237,0123,0124,0125,0126,0127,0130,
563 0131,0132,0364,0365,0366,0367,0370,0371,
564 0060,0061,0062,0063,0064,0065,0066,0067,
565 0070,0071,0372,0373,0374,0375,0376,0377
566};
567
K.Takataf6fc2552023-09-01 18:41:04 +0200568 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200569begin_coloring_char (char *l, int *c, int e, int ebcdic)
570{
571 if (ebcdic)
572 {
573 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
574 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
575 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
576 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
577 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
578 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
579 (e == 173) || (e == 224) )
580 l[(*c)++] = COLOR_GREEN;
581
582 else if (e == 37 || e == 13 || e == 5)
583 l[(*c)++] = COLOR_YELLOW;
584 else if (e == 0)
585 l[(*c)++] = COLOR_WHITE;
586 else if (e == 255)
587 l[(*c)++] = COLOR_BLUE;
588 else
589 l[(*c)++] = COLOR_RED;
590 }
591 else /* ASCII */
592 {
Igor Todorovski48a75f32024-01-09 21:05:48 +0000593 #if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200594 if (e >= 64)
595 l[(*c)++] = COLOR_GREEN;
596 #else
597 if (e > 31 && e < 127)
598 l[(*c)++] = COLOR_GREEN;
599 #endif
600
601 else if (e == 9 || e == 10 || e == 13)
602 l[(*c)++] = COLOR_YELLOW;
603 else if (e == 0)
604 l[(*c)++] = COLOR_WHITE;
605 else if (e == 255)
606 l[(*c)++] = COLOR_BLUE;
607 else
608 l[(*c)++] = COLOR_RED;
609 }
610 l[(*c)++] = 'm';
611}
612
K.Takataf6fc2552023-09-01 18:41:04 +0200613 static int
614enable_color(void)
615{
616#ifdef WIN32
617 DWORD mode;
618 HANDLE out;
619
620 if (!isatty(1))
621 return 0;
622
623 out = GetStdHandle(STD_OUTPUT_HANDLE);
624 GetConsoleMode(out, &mode);
625 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
626 return (int)SetConsoleMode(out, mode);
627#elif defined(UNIX)
628 return isatty(STDOUT_FILENO);
629#else
630 return 0;
631#endif
632}
633
Bram Moolenaare0659a62011-04-01 19:14:40 +0200634 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100635main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636{
637 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200638 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000639 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200640 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000641 int ebcdic = 0;
642 int octspergrp = -1; /* number of octets grouped in output */
643 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100644 long length = -1, n = 0, seekoff = 0;
645 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200646 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200647 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100648 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100649 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200650 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200651 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200652
K.Takataf6fc2552023-09-01 18:41:04 +0200653 no_color = getenv("NO_COLOR");
654 if (no_color == NULL || no_color[0] == '\0')
655 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000656
657#ifdef AMIGA
658 /* This program doesn't work when started from the Workbench */
659 if (argc == 0)
660 exit(1);
661#endif
662
663 pname = argv[0];
664 for (pp = pname; *pp; )
665 if (*pp++ == PATH_SEP)
666 pname = pp;
667#ifdef FILE_SEP
668 for (pp = pname; *pp; pp++)
669 if (*pp == FILE_SEP)
670 {
671 *pp = '\0';
672 break;
673 }
674#endif
675
676 while (argc >= 2)
677 {
678 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
679 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
680 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100681 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
683 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
684 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200685 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200686 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687 else if (!STRNCMP(pp, "-r", 2)) revert++;
688 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
689 else if (!STRNCMP(pp, "-v", 2))
690 {
691 fprintf(stderr, "%s%s\n", version, osver);
692 exit(0);
693 }
694 else if (!STRNCMP(pp, "-c", 2))
695 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100696 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200697 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100698 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000699 {
700 colsgiven = 1;
701 cols = (int)strtol(pp + 2, NULL, 0);
702 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 else
704 {
705 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200706 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000707 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000708 cols = (int)strtol(argv[2], NULL, 0);
709 argv++;
710 argc--;
711 }
712 }
713 else if (!STRNCMP(pp, "-g", 2))
714 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100715 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716 octspergrp = (int)strtol(pp + 2, NULL, 0);
717 else
718 {
719 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200720 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000721 octspergrp = (int)strtol(argv[2], NULL, 0);
722 argv++;
723 argc--;
724 }
725 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100726 else if (!STRNCMP(pp, "-o", 2))
727 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100728 int reloffset = 0;
729 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100730 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100731 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100732 else
733 {
734 if (!argv[2])
735 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100736
737 if (argv[2][0] == '+')
738 reloffset++;
739 if (argv[2][reloffset] == '-')
740 negoffset++;
741
742 if (negoffset)
743 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
744 else
745 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
746
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100747 argv++;
748 argc--;
749 }
750 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000751 else if (!STRNCMP(pp, "-s", 2))
752 {
753 relseek = 0;
754 negseek = 0;
755 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
756 {
757#ifdef TRY_SEEK
758 if (pp[2] == '+')
759 relseek++;
760 if (pp[2+relseek] == '-')
761 negseek++;
762#endif
763 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
764 }
765 else
766 {
767 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200768 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000769#ifdef TRY_SEEK
770 if (argv[2][0] == '+')
771 relseek++;
772 if (argv[2][relseek] == '-')
773 negseek++;
774#endif
775 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
776 argv++;
777 argc--;
778 }
779 }
780 else if (!STRNCMP(pp, "-l", 2))
781 {
782 if (pp[2] && STRNCMP("en", pp + 2, 2))
783 length = strtol(pp + 2, (char **)NULL, 0);
784 else
785 {
786 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200787 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 length = strtol(argv[2], (char **)NULL, 0);
789 argv++;
790 argc--;
791 }
792 }
David Gow83e11802022-06-29 20:24:49 +0100793 else if (!STRNCMP(pp, "-n", 2))
794 {
795 if (pp[2] && STRNCMP("ame", pp + 2, 3))
796 varname = pp + 2;
797 else
798 {
799 if (!argv[2])
800 exit_with_usage();
801 varname = argv[2];
802 argv++;
803 argc--;
804 }
805 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200806 else if (!STRNCMP(pp, "-R", 2))
807 {
K.Takataf6fc2552023-09-01 18:41:04 +0200808 char *pw = pp + 2;
809 if (!pw[0])
810 {
811 pw = argv[2];
812 argv++;
813 argc--;
814 }
815 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200816 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200817 if (!STRNCMP(pw, "always", 6))
818 {
819 (void)enable_color();
820 color = 1;
821 }
822 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200823 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200824 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200825 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200826 else
827 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200828 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 else if (!strcmp(pp, "--")) /* end of options */
830 {
831 argv++;
832 argc--;
833 break;
834 }
835 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200836 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837 else
838 break; /* not an option */
839
840 argv++; /* advance to next argument */
841 argc--;
842 }
843
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000844 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 switch (hextype)
846 {
847 case HEX_POSTSCRIPT: cols = 30; break;
848 case HEX_CINCLUDE: cols = 12; break;
849 case HEX_BITS: cols = 6; break;
850 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100851 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 default: cols = 16; break;
853 }
854
855 if (octspergrp < 0)
856 switch (hextype)
857 {
858 case HEX_BITS: octspergrp = 1; break;
859 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100860 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 case HEX_POSTSCRIPT:
862 case HEX_CINCLUDE:
863 default: octspergrp = 0; break;
864 }
865
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000866 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
867 (hextype != HEX_POSTSCRIPT && cols < 1) ||
868 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000869 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870 {
871 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
872 exit(1);
873 }
874
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100875 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000876 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100877 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100878 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879
880 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200881 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882
883 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
884 BIN_ASSIGN(fp = stdin, !revert);
885 else
886 {
887 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
888 {
889 fprintf(stderr,"%s: ", pname);
890 perror(argv[1]);
891 return 2;
892 }
893 }
894
895 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
896 BIN_ASSIGN(fpo = stdout, revert);
897 else
898 {
899 int fd;
900 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
901
902 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
903 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
904 {
905 fprintf(stderr, "%s: ", pname);
906 perror(argv[2]);
907 return 3;
908 }
909 rewind(fpo);
910 }
Igor Todorovski48a75f32024-01-09 21:05:48 +0000911#ifdef __MVS__
912 // Disable auto-conversion on input file descriptors
913 __disableautocvt(fileno(fp));
914#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915
916 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200917 switch (hextype)
918 {
919 case HEX_NORMAL:
920 case HEX_POSTSCRIPT:
921 case HEX_BITS:
922 return huntype(fp, fpo, cols, hextype,
923 negseek ? -seekoff : seekoff);
924 break;
925 default:
926 error_exit(-1, "Sorry, cannot revert this type of hexdump");
927 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000928
929 if (seekoff || negseek || !relseek)
930 {
931#ifdef TRY_SEEK
932 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000933 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000934 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000935 e = fseek(fp, negseek ? -seekoff : seekoff,
936 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000938 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 if (e >= 0)
940 seekoff = ftell(fp);
941 else
942#endif
943 {
944 long s = seekoff;
945
946 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000947 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200948 {
DungSaga7e5503c2021-12-01 11:24:52 +0000949 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200950 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 }
952 }
953
954 if (hextype == HEX_CINCLUDE)
955 {
David Gow83e11802022-06-29 20:24:49 +0100956 /* A user-set variable name overrides fp == stdin */
957 if (varname == NULL && fp != stdin)
958 varname = argv[1];
959
960 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000961 {
Keith Thompson184f71c2024-01-04 21:19:04 +0100962 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100963 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100964 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000965 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 }
967
968 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000969 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 {
DungSaga7e5503c2021-12-01 11:24:52 +0000971 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
972 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 p++;
974 }
975
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000976 if (p)
977 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978
David Gow83e11802022-06-29 20:24:49 +0100979 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980 {
DungSagad1d8a592021-11-26 13:59:27 +0000981 fputs_or_die("};\n", fpo);
Christian Brabandtfa8c9712024-01-25 20:50:49 +0100982 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100983 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100984 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000985 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 }
987
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000988 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 return 0;
990 }
991
992 if (hextype == HEX_POSTSCRIPT)
993 {
994 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000995 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000997 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
998 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +00001000 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001002 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 p = cols;
1004 }
1005 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +00001006 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001007 putc_or_die('\n', fpo);
1008 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009 return 0;
1010 }
1011
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001012 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001014 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001015 {
1016 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1017 if (color)
1018 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1019 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020 else /* hextype == HEX_BITS */
1021 grplen = 8 * octspergrp + 1;
1022
DungSagad1d8a592021-11-26 13:59:27 +00001023 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 {
1025 if (p == 0)
1026 {
DungSaga581f41a2021-11-22 11:57:31 +00001027 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001028 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001029 for (c = addrlen; c < LLEN; l[c++] = ' ')
1030 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 }
DungSaga48608b42021-11-24 11:18:07 +00001032 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1033 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001034 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001035 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001036 if (color)
1037 {
1038 COLOR_PROLOGUE
1039 begin_coloring_char(l,&c,e,ebcdic);
1040 l[c++] = hexx[(e >> 4) & 0xf];
1041 l[c++] = hexx[e & 0xf];
1042 COLOR_EPILOGUE
1043 }
1044 else /*No colors*/
1045 {
1046 l[c] = hexx[(e >> 4) & 0xf];
1047 l[++c] = hexx[e & 0xf];
1048 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049 }
1050 else /* hextype == HEX_BITS */
1051 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001053 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001054 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001055 if (e)
1056 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001057 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001058 if (hextype == HEX_LITTLEENDIAN)
1059 /* last group will be fully used, round up */
1060 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1061 else
1062 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001063
1064 if (color)
1065 {
1066 if (hextype == HEX_BITS)
1067 c += addrlen + 3 + p*12;
1068 else
1069 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1070
1071 if (hextype == HEX_LITTLEENDIAN)
1072 c += 1;
1073
1074 COLOR_PROLOGUE
1075 begin_coloring_char(l,&c,e,ebcdic);
Igor Todorovski48a75f32024-01-09 21:05:48 +00001076#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001077 if (e >= 64)
1078 l[c++] = e;
1079 else
1080 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001082 if (ebcdic)
1083 e = (e < 64) ? '.' : etoa64[e-64];
1084 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001086 COLOR_EPILOGUE
1087 n++;
1088 if (++p == cols)
1089 {
1090 l[c++] = '\n';
1091 l[c++] = '\0';
1092 xxdline(fpo, l, autoskip ? nonzero : 1);
1093 nonzero = 0;
1094 p = 0;
1095 }
1096 }
1097 else /*no colors*/
1098 {
1099 if (ebcdic)
1100 e = (e < 64) ? '.' : etoa64[e-64];
1101
1102 c += addrlen + 3 + p;
1103 l[c++] =
Igor Todorovski48a75f32024-01-09 21:05:48 +00001104#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001105 (e >= 64)
1106#else
1107 (e > 31 && e < 127)
1108#endif
1109 ? e : '.';
1110 n++;
1111 if (++p == cols)
1112 {
1113 l[c++] = '\n';
1114 l[c] = '\0';
1115 xxdline(fpo, l, autoskip ? nonzero : 1);
1116 nonzero = 0;
1117 p = 0;
1118 }
1119 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001120 }
1121 if (p)
1122 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001123 l[c++] = '\n';
1124 l[c] = '\0';
1125 if (color)
1126 {
1127 c++;
1128
1129 x = p;
1130 if (hextype == HEX_LITTLEENDIAN)
1131 {
1132 int fill = octspergrp - (p % octspergrp);
1133 if (fill == octspergrp) fill = 0;
1134
1135 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1136
1137 for (i = 0; i < fill;i++)
1138 {
1139 COLOR_PROLOGUE
1140 l[c++] = COLOR_RED;
1141 l[c++] = 'm';
1142 l[c++] = ' '; /* empty space */
1143 COLOR_EPILOGUE
1144 x++;
1145 p++;
1146 }
1147 }
1148
1149 if (hextype != HEX_BITS)
1150 {
1151 c = addrlen + 1 + (grplen * x) / octspergrp;
1152 c += cols - p;
1153 c += (cols - p) / octspergrp;
1154
1155 for (i = cols - p; i > 0;i--)
1156 {
1157 COLOR_PROLOGUE
1158 l[c++] = COLOR_RED;
1159 l[c++] = 'm';
1160 l[c++] = ' '; /* empty space */
1161 COLOR_EPILOGUE
1162 }
1163 }
1164 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001165 xxdline(fpo, l, 1);
1166 }
1167 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001168 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001170 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001171 return 0;
1172}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001173
1174/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */