blob: 75de98281069ebd92473d1b7784a98652cd2855d [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
Bram Moolenaar071d4272004-06-13 20:20:40 +000063 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020064 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000065 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020066 * I hereby grant permission to distribute and use xxd
67 * under X11-MIT or GPL-2.0 (at the user's choice).
68 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020069 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000070 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000071
72/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
73#if _MSC_VER >= 1400
74# define _CRT_SECURE_NO_DEPRECATE
75# define _CRT_NONSTDC_NO_DEPRECATE
76#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010077#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000078# define CYGWIN
79#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000080
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000081#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
82# define _XOPEN_SOURCE 700 /* for fdopen() */
83#endif
84
Bram Moolenaar071d4272004-06-13 20:20:40 +000085#include <stdio.h>
86#ifdef VAXC
87# include <file.h>
88#else
89# include <fcntl.h>
90#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020091#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000092# include <io.h> /* for setmode() */
Ken Takatac4a40382023-10-25 21:17:35 +020093#endif
94#ifdef WIN32
K.Takataf6fc2552023-09-01 18:41:04 +020095# include <windows.h>
96#endif
97#ifdef UNIX
98# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000099#endif
100#include <stdlib.h>
Keith Thompson184f71c2024-01-04 21:19:04 +0100101#include <string.h>
102#include <ctype.h>
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100103#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104#if __MWERKS__ && !defined(BEBOX)
105# include <unix.h> /* for fdopen() on MAC */
106#endif
107
Bram Moolenaar071d4272004-06-13 20:20:40 +0000108
109/* This corrects the problem of missing prototypes for certain functions
110 * in some GNU installations (e.g. SunOS 4.1.x).
111 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
112 */
113#if defined(__GNUC__) && defined(__STDC__)
114# ifndef __USE_FIXED_PROTOTYPES__
115# define __USE_FIXED_PROTOTYPES__
116# endif
117#endif
118
119#ifndef __USE_FIXED_PROTOTYPES__
120/*
121 * This is historic and works only if the compiler really has no prototypes:
122 *
123 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
124 * FILE is defined on OS 4.x, not on 5.x (Solaris).
125 * if __SVR4 is defined (some Solaris versions), don't include this.
126 */
127#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
128# define __P(a) a
129/* excerpt from my sun_stdlib.h */
130extern int fprintf __P((FILE *, char *, ...));
131extern int fputs __P((char *, FILE *));
132extern int _flsbuf __P((unsigned char, FILE *));
133extern int _filbuf __P((FILE *));
134extern int fflush __P((FILE *));
135extern int fclose __P((FILE *));
136extern int fseek __P((FILE *, long, int));
137extern int rewind __P((FILE *));
138
139extern void perror __P((char *));
140# endif
141#endif
142
Kuratius7062be12024-01-17 18:37:32 +0100143char version[] = "xxd 2024-01-17 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144#ifdef WIN32
145char osver[] = " (Win32)";
146#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148#endif
149
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200150#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151# define BIN_READ(yes) ((yes) ? "rb" : "rt")
152# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
153# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
154# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000155# define PATH_SEP '\\'
156#elif defined(CYGWIN)
157# define BIN_READ(yes) ((yes) ? "rb" : "rt")
158# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
159# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
160# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
161# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162#else
163# ifdef VMS
164# define BIN_READ(dummy) "r"
165# define BIN_WRITE(dummy) "w"
166# define BIN_CREAT(dummy) O_CREAT
167# define BIN_ASSIGN(fp, dummy) fp
168# define PATH_SEP ']'
169# define FILE_SEP '.'
170# else
171# define BIN_READ(dummy) "r"
172# define BIN_WRITE(dummy) "w"
173# define BIN_CREAT(dummy) O_CREAT
174# define BIN_ASSIGN(fp, dummy) fp
175# define PATH_SEP '/'
176# endif
177#endif
178
179/* open has only to arguments on the Mac */
180#if __MWERKS__
181# define OPEN(name, mode, umask) open(name, mode)
182#else
183# define OPEN(name, mode, umask) open(name, mode, umask)
184#endif
185
186#ifdef AMIGA
187# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
188#else
189# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
190#endif
191
192#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200193# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194# define __P(a) a
195# else
196# define __P(a) ()
197# endif
198#endif
199
Bram Moolenaar071d4272004-06-13 20:20:40 +0000200#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
201#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100202#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000203
204char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
205
206/* the different hextypes known by this program: */
207#define HEX_NORMAL 0
208#define HEX_POSTSCRIPT 1
209#define HEX_CINCLUDE 2
210#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100211#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000212
Keith Thompson184f71c2024-01-04 21:19:04 +0100213#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : (c))
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200214
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200215#define COLOR_PROLOGUE \
216l[c++] = '\033'; \
217l[c++] = '['; \
218l[c++] = '1'; \
219l[c++] = ';'; \
220l[c++] = '3';
221
222#define COLOR_EPILOGUE \
223l[c++] = '\033'; \
224l[c++] = '['; \
225l[c++] = '0'; \
226l[c++] = 'm';
227#define COLOR_RED '1'
228#define COLOR_GREEN '2'
229#define COLOR_YELLOW '3'
230#define COLOR_BLUE '4'
231#define COLOR_WHITE '7'
232
Bram Moolenaare0659a62011-04-01 19:14:40 +0200233static char *pname;
234
235 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100236exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000237{
238 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
239 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
240 fprintf(stderr, "Options:\n");
241 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200242 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200243 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
245 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100246 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100247 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 fprintf(stderr, " -h print this summary.\n");
249 fprintf(stderr, " -i output in C include file style.\n");
250 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100251 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100252 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000253 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
254 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
255 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200256 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000257 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
258#ifdef TRY_SEEK
259 "[+][-]", "(or +: rel.) ");
260#else
261 "", "");
262#endif
263 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200264 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
266 exit(1);
267}
268
Bram Moolenaare0659a62011-04-01 19:14:40 +0200269 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100270perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200271{
272 fprintf(stderr, "%s: ", pname);
273 perror(NULL);
274 exit(ret);
275}
276
DungSagaa2ffb432021-10-22 15:55:31 +0100277 static void
278error_exit(int ret, char *msg)
279{
280 fprintf(stderr, "%s: %s\n", pname, msg);
281 exit(ret);
282}
283
DungSagad1d8a592021-11-26 13:59:27 +0000284 static int
285getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000286{
DungSagad1d8a592021-11-26 13:59:27 +0000287 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000288 if (c == EOF && ferror(fpi))
289 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000290 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000291}
292
293 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000294putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000295{
296 if (putc(c, fpo) == EOF)
297 perror_exit(3);
298}
299
300 static void
301fputs_or_die(char *s, FILE *fpo)
302{
303 if (fputs(s, fpo) == EOF)
304 perror_exit(3);
305}
306
DungSaga7e5503c2021-12-01 11:24:52 +0000307/* Use a macro to allow for different arguments. */
308#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000309
310 static void
311fclose_or_die(FILE *fpi, FILE *fpo)
312{
313 if (fclose(fpo) != 0)
314 perror_exit(3);
315 if (fclose(fpi) != 0)
316 perror_exit(2);
317}
318
Bram Moolenaar071d4272004-06-13 20:20:40 +0000319/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000320 * If "c" is a hex digit, return the value.
321 * Otherwise return -1.
322 */
323 static int
324parse_hex_digit(int c)
325{
326 return (c >= '0' && c <= '9') ? c - '0'
327 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
328 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
329 : -1;
330}
331
332/*
tristhaus85f45212023-10-06 19:51:13 +0200333 * If "c" is a bin digit, return the value.
334 * Otherwise return -1.
335 */
336 static int
337parse_bin_digit(int c)
338{
339 return (c >= '0' && c <= '1') ? c - '0'
340 : -1;
341}
342
343/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000344 * Ignore text on "fpi" until end-of-line or end-of-file.
345 * Return the '\n' or EOF character.
346 * When an error is encountered exit with an error message.
347 */
348 static int
349skip_to_eol(FILE *fpi, int c)
350{
351 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000352 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000353 return c;
354}
355
356/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357 * Max. cols binary characters are decoded from the input stream per line.
358 * Two adjacent garbage characters after evaluated data delimit valid data.
359 * Everything up to the next newline is discarded.
360 *
361 * The name is historic and came from 'undo type opt h'.
362 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200363 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100364huntype(
365 FILE *fpi,
366 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100367 int cols,
368 int hextype,
369 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000370{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200371 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 +0000372 long have_off = 0, want_off = 0;
373
374 rewind(fpi);
375
376 while ((c = getc(fpi)) != EOF)
377 {
378 if (c == '\r') /* Doze style input file? */
379 continue;
380
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100381 /* Allow multiple spaces. This doesn't work when there is normal text
382 * after the hex codes in the last line that looks like hex, thus only
383 * use it for PostScript format. */
384 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000385 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000386
tristhaus85f45212023-10-06 19:51:13 +0200387 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
388 {
389 n3 = n2;
390 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000391
tristhaus85f45212023-10-06 19:51:13 +0200392 n1 = parse_hex_digit(c);
393 if (n1 == -1 && ign_garb)
394 continue;
395 }
396 else /* HEX_BITS */
397 {
398 n1 = parse_hex_digit(c);
399 if (n1 == -1 && ign_garb)
400 continue;
401
402 bt = parse_bin_digit(c);
403 if (bt != -1)
404 {
405 b = ((b << 1) | bt);
406 ++bcnt;
407 }
408 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409
410 ign_garb = 0;
411
tristhaus85f45212023-10-06 19:51:13 +0200412 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413 {
tristhaus85f45212023-10-06 19:51:13 +0200414 if (hextype == HEX_NORMAL)
415 {
416 if (n1 < 0)
417 {
418 p = 0;
419 continue;
420 }
421 want_off = (want_off << 4) | n1;
422 }
423 else /* HEX_BITS */
424 {
OldWorldOrdr1c140302023-10-25 20:57:30 +0200425 if (n1 < 0)
426 {
427 p = 0;
tristhaus85f45212023-10-06 19:51:13 +0200428 bcnt = 0;
OldWorldOrdr1c140302023-10-25 20:57:30 +0200429 continue;
430 }
431 want_off = (want_off << 4) | n1;
tristhaus85f45212023-10-06 19:51:13 +0200432 }
433 continue;
434 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000435
436 if (base_off + want_off != have_off)
437 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200438 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100439 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000440#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000441 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000442 have_off = base_off + want_off;
443#endif
444 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000445 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000447 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000448 }
449
tristhaus85f45212023-10-06 19:51:13 +0200450 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
451 {
452 if (n2 >= 0 && n1 >= 0)
453 {
454 putc_or_die((n2 << 4) | n1, fpo);
455 have_off++;
456 want_off++;
457 n1 = -1;
458 if (!hextype && (++p >= cols))
459 /* skip the rest of the line as garbage */
460 c = skip_to_eol(fpi, c);
461 }
462 else if (n1 < 0 && n2 < 0 && n3 < 0)
463 /* already stumbled into garbage, skip line, wait and see */
464 c = skip_to_eol(fpi, c);
465 }
466 else /* HEX_BITS */
467 {
468 if (bcnt == 8)
469 {
470 putc_or_die(b, fpo);
471 have_off++;
472 want_off++;
473 b = 0;
474 bcnt = 0;
475 if (++p >= cols)
476 /* skip the rest of the line as garbage */
477 c = skip_to_eol(fpi, c);
478 }
479 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000480
DungSaga47810462021-10-22 12:55:42 +0100481 if (c == '\n')
482 {
tristhaus85f45212023-10-06 19:51:13 +0200483 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100484 want_off = 0;
485 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000486 ign_garb = 1;
487 }
488 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200489 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100490 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000491#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000492 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000494 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495 return 0;
496}
497
498/*
499 * Print line l. If nz is false, xxdline regards the line a line of
500 * zeroes. If there are three or more consecutive lines of zeroes,
501 * they are replaced by a single '*' character.
502 *
503 * If the output ends with more than two lines of zeroes, you
504 * should call xxdline again with l being the last line and nz
505 * negative. This ensures that the last line is shown even when
506 * it is all zeroes.
507 *
508 * If nz is always positive, lines are never suppressed.
509 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200510 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100511xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000512{
513 static char z[LLEN+1];
514 static int zero_seen = 0;
515
516 if (!nz && zero_seen == 1)
517 strcpy(z, l);
518
519 if (nz || !zero_seen++)
520 {
521 if (nz)
522 {
523 if (nz < 0)
524 zero_seen--;
525 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000526 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000528 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 }
530 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000531 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 if (nz)
533 zero_seen = 0;
534 }
535}
536
537/* This is an EBCDIC to ASCII conversion table */
538/* from a proposed BTL standard April 16, 1979 */
539static unsigned char etoa64[] =
540{
541 0040,0240,0241,0242,0243,0244,0245,0246,
542 0247,0250,0325,0056,0074,0050,0053,0174,
543 0046,0251,0252,0253,0254,0255,0256,0257,
544 0260,0261,0041,0044,0052,0051,0073,0176,
545 0055,0057,0262,0263,0264,0265,0266,0267,
546 0270,0271,0313,0054,0045,0137,0076,0077,
547 0272,0273,0274,0275,0276,0277,0300,0301,
548 0302,0140,0072,0043,0100,0047,0075,0042,
549 0303,0141,0142,0143,0144,0145,0146,0147,
550 0150,0151,0304,0305,0306,0307,0310,0311,
551 0312,0152,0153,0154,0155,0156,0157,0160,
552 0161,0162,0136,0314,0315,0316,0317,0320,
553 0321,0345,0163,0164,0165,0166,0167,0170,
554 0171,0172,0322,0323,0324,0133,0326,0327,
555 0330,0331,0332,0333,0334,0335,0336,0337,
556 0340,0341,0342,0343,0344,0135,0346,0347,
557 0173,0101,0102,0103,0104,0105,0106,0107,
558 0110,0111,0350,0351,0352,0353,0354,0355,
559 0175,0112,0113,0114,0115,0116,0117,0120,
560 0121,0122,0356,0357,0360,0361,0362,0363,
561 0134,0237,0123,0124,0125,0126,0127,0130,
562 0131,0132,0364,0365,0366,0367,0370,0371,
563 0060,0061,0062,0063,0064,0065,0066,0067,
564 0070,0071,0372,0373,0374,0375,0376,0377
565};
566
K.Takataf6fc2552023-09-01 18:41:04 +0200567 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200568begin_coloring_char (char *l, int *c, int e, int ebcdic)
569{
570 if (ebcdic)
571 {
572 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
573 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
574 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
575 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
576 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
577 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
578 (e == 173) || (e == 224) )
579 l[(*c)++] = COLOR_GREEN;
580
581 else if (e == 37 || e == 13 || e == 5)
582 l[(*c)++] = COLOR_YELLOW;
583 else if (e == 0)
584 l[(*c)++] = COLOR_WHITE;
585 else if (e == 255)
586 l[(*c)++] = COLOR_BLUE;
587 else
588 l[(*c)++] = COLOR_RED;
589 }
590 else /* ASCII */
591 {
Igor Todorovski48a75f32024-01-09 21:05:48 +0000592 #if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200593 if (e >= 64)
594 l[(*c)++] = COLOR_GREEN;
595 #else
596 if (e > 31 && e < 127)
597 l[(*c)++] = COLOR_GREEN;
598 #endif
599
600 else if (e == 9 || e == 10 || e == 13)
601 l[(*c)++] = COLOR_YELLOW;
602 else if (e == 0)
603 l[(*c)++] = COLOR_WHITE;
604 else if (e == 255)
605 l[(*c)++] = COLOR_BLUE;
606 else
607 l[(*c)++] = COLOR_RED;
608 }
609 l[(*c)++] = 'm';
610}
611
K.Takataf6fc2552023-09-01 18:41:04 +0200612 static int
613enable_color(void)
614{
615#ifdef WIN32
616 DWORD mode;
617 HANDLE out;
618
619 if (!isatty(1))
620 return 0;
621
622 out = GetStdHandle(STD_OUTPUT_HANDLE);
623 GetConsoleMode(out, &mode);
624 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
625 return (int)SetConsoleMode(out, mode);
626#elif defined(UNIX)
627 return isatty(STDOUT_FILENO);
628#else
629 return 0;
630#endif
631}
632
Bram Moolenaare0659a62011-04-01 19:14:40 +0200633 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100634main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000635{
636 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200637 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000638 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200639 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640 int ebcdic = 0;
641 int octspergrp = -1; /* number of octets grouped in output */
642 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100643 long length = -1, n = 0, seekoff = 0;
644 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200645 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200646 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100647 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100648 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200649 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200650 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200651
K.Takataf6fc2552023-09-01 18:41:04 +0200652 no_color = getenv("NO_COLOR");
653 if (no_color == NULL || no_color[0] == '\0')
654 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655
656#ifdef AMIGA
657 /* This program doesn't work when started from the Workbench */
658 if (argc == 0)
659 exit(1);
660#endif
661
662 pname = argv[0];
663 for (pp = pname; *pp; )
664 if (*pp++ == PATH_SEP)
665 pname = pp;
666#ifdef FILE_SEP
667 for (pp = pname; *pp; pp++)
668 if (*pp == FILE_SEP)
669 {
670 *pp = '\0';
671 break;
672 }
673#endif
674
675 while (argc >= 2)
676 {
677 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
678 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
679 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100680 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
682 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
683 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200684 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200685 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 else if (!STRNCMP(pp, "-r", 2)) revert++;
687 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
688 else if (!STRNCMP(pp, "-v", 2))
689 {
690 fprintf(stderr, "%s%s\n", version, osver);
691 exit(0);
692 }
693 else if (!STRNCMP(pp, "-c", 2))
694 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100695 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200696 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100697 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000698 {
699 colsgiven = 1;
700 cols = (int)strtol(pp + 2, NULL, 0);
701 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 else
703 {
704 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200705 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000706 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707 cols = (int)strtol(argv[2], NULL, 0);
708 argv++;
709 argc--;
710 }
711 }
712 else if (!STRNCMP(pp, "-g", 2))
713 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100714 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715 octspergrp = (int)strtol(pp + 2, NULL, 0);
716 else
717 {
718 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200719 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000720 octspergrp = (int)strtol(argv[2], NULL, 0);
721 argv++;
722 argc--;
723 }
724 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100725 else if (!STRNCMP(pp, "-o", 2))
726 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100727 int reloffset = 0;
728 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100729 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100730 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100731 else
732 {
733 if (!argv[2])
734 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100735
736 if (argv[2][0] == '+')
737 reloffset++;
738 if (argv[2][reloffset] == '-')
739 negoffset++;
740
741 if (negoffset)
742 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
743 else
744 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
745
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100746 argv++;
747 argc--;
748 }
749 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750 else if (!STRNCMP(pp, "-s", 2))
751 {
752 relseek = 0;
753 negseek = 0;
754 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
755 {
756#ifdef TRY_SEEK
757 if (pp[2] == '+')
758 relseek++;
759 if (pp[2+relseek] == '-')
760 negseek++;
761#endif
762 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
763 }
764 else
765 {
766 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200767 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768#ifdef TRY_SEEK
769 if (argv[2][0] == '+')
770 relseek++;
771 if (argv[2][relseek] == '-')
772 negseek++;
773#endif
774 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
775 argv++;
776 argc--;
777 }
778 }
779 else if (!STRNCMP(pp, "-l", 2))
780 {
781 if (pp[2] && STRNCMP("en", pp + 2, 2))
782 length = strtol(pp + 2, (char **)NULL, 0);
783 else
784 {
785 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200786 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 length = strtol(argv[2], (char **)NULL, 0);
788 argv++;
789 argc--;
790 }
791 }
David Gow83e11802022-06-29 20:24:49 +0100792 else if (!STRNCMP(pp, "-n", 2))
793 {
794 if (pp[2] && STRNCMP("ame", pp + 2, 3))
795 varname = pp + 2;
796 else
797 {
798 if (!argv[2])
799 exit_with_usage();
800 varname = argv[2];
801 argv++;
802 argc--;
803 }
804 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200805 else if (!STRNCMP(pp, "-R", 2))
806 {
K.Takataf6fc2552023-09-01 18:41:04 +0200807 char *pw = pp + 2;
808 if (!pw[0])
809 {
810 pw = argv[2];
811 argv++;
812 argc--;
813 }
814 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200815 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200816 if (!STRNCMP(pw, "always", 6))
817 {
818 (void)enable_color();
819 color = 1;
820 }
821 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200822 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200823 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200824 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200825 else
826 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200827 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 else if (!strcmp(pp, "--")) /* end of options */
829 {
830 argv++;
831 argc--;
832 break;
833 }
834 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200835 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 else
837 break; /* not an option */
838
839 argv++; /* advance to next argument */
840 argc--;
841 }
842
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000843 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 switch (hextype)
845 {
846 case HEX_POSTSCRIPT: cols = 30; break;
847 case HEX_CINCLUDE: cols = 12; break;
848 case HEX_BITS: cols = 6; break;
849 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100850 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 default: cols = 16; break;
852 }
853
854 if (octspergrp < 0)
855 switch (hextype)
856 {
857 case HEX_BITS: octspergrp = 1; break;
858 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100859 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860 case HEX_POSTSCRIPT:
861 case HEX_CINCLUDE:
862 default: octspergrp = 0; break;
863 }
864
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000865 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
866 (hextype != HEX_POSTSCRIPT && cols < 1) ||
867 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000868 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000869 {
870 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
871 exit(1);
872 }
873
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100874 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100876 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100877 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878
879 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200880 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000881
882 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
883 BIN_ASSIGN(fp = stdin, !revert);
884 else
885 {
886 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
887 {
888 fprintf(stderr,"%s: ", pname);
889 perror(argv[1]);
890 return 2;
891 }
892 }
893
894 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
895 BIN_ASSIGN(fpo = stdout, revert);
896 else
897 {
898 int fd;
899 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
900
901 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
902 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
903 {
904 fprintf(stderr, "%s: ", pname);
905 perror(argv[2]);
906 return 3;
907 }
908 rewind(fpo);
909 }
Igor Todorovski48a75f32024-01-09 21:05:48 +0000910#ifdef __MVS__
911 // Disable auto-conversion on input file descriptors
912 __disableautocvt(fileno(fp));
913#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914
915 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200916 switch (hextype)
917 {
918 case HEX_NORMAL:
919 case HEX_POSTSCRIPT:
920 case HEX_BITS:
921 return huntype(fp, fpo, cols, hextype,
922 negseek ? -seekoff : seekoff);
923 break;
924 default:
925 error_exit(-1, "Sorry, cannot revert this type of hexdump");
926 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927
928 if (seekoff || negseek || !relseek)
929 {
930#ifdef TRY_SEEK
931 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000932 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000934 e = fseek(fp, negseek ? -seekoff : seekoff,
935 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000937 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000938 if (e >= 0)
939 seekoff = ftell(fp);
940 else
941#endif
942 {
943 long s = seekoff;
944
945 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000946 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200947 {
DungSaga7e5503c2021-12-01 11:24:52 +0000948 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200949 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000950 }
951 }
952
953 if (hextype == HEX_CINCLUDE)
954 {
David Gow83e11802022-06-29 20:24:49 +0100955 /* A user-set variable name overrides fp == stdin */
956 if (varname == NULL && fp != stdin)
957 varname = argv[1];
958
959 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960 {
Keith Thompson184f71c2024-01-04 21:19:04 +0100961 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100962 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100963 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000964 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000965 }
966
967 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000968 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969 {
DungSaga7e5503c2021-12-01 11:24:52 +0000970 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
971 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972 p++;
973 }
974
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000975 if (p)
976 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977
David Gow83e11802022-06-29 20:24:49 +0100978 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979 {
DungSagad1d8a592021-11-26 13:59:27 +0000980 fputs_or_die("};\n", fpo);
Kuratius7062be12024-01-17 18:37:32 +0100981 FPRINTF_OR_DIE((fpo, "size_t %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100982 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100983 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000984 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000985 }
986
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000987 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988 return 0;
989 }
990
991 if (hextype == HEX_POSTSCRIPT)
992 {
993 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000994 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000996 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
997 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000999 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001001 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 p = cols;
1003 }
1004 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +00001005 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001006 putc_or_die('\n', fpo);
1007 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001008 return 0;
1009 }
1010
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001011 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001013 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001014 {
1015 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1016 if (color)
1017 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1018 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 else /* hextype == HEX_BITS */
1020 grplen = 8 * octspergrp + 1;
1021
DungSagad1d8a592021-11-26 13:59:27 +00001022 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001023 {
1024 if (p == 0)
1025 {
DungSaga581f41a2021-11-22 11:57:31 +00001026 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001027 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001028 for (c = addrlen; c < LLEN; l[c++] = ' ')
1029 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030 }
DungSaga48608b42021-11-24 11:18:07 +00001031 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1032 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001033 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001035 if (color)
1036 {
1037 COLOR_PROLOGUE
1038 begin_coloring_char(l,&c,e,ebcdic);
1039 l[c++] = hexx[(e >> 4) & 0xf];
1040 l[c++] = hexx[e & 0xf];
1041 COLOR_EPILOGUE
1042 }
1043 else /*No colors*/
1044 {
1045 l[c] = hexx[(e >> 4) & 0xf];
1046 l[++c] = hexx[e & 0xf];
1047 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 }
1049 else /* hextype == HEX_BITS */
1050 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001052 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001054 if (e)
1055 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001056 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001057 if (hextype == HEX_LITTLEENDIAN)
1058 /* last group will be fully used, round up */
1059 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1060 else
1061 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001062
1063 if (color)
1064 {
1065 if (hextype == HEX_BITS)
1066 c += addrlen + 3 + p*12;
1067 else
1068 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1069
1070 if (hextype == HEX_LITTLEENDIAN)
1071 c += 1;
1072
1073 COLOR_PROLOGUE
1074 begin_coloring_char(l,&c,e,ebcdic);
Igor Todorovski48a75f32024-01-09 21:05:48 +00001075#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001076 if (e >= 64)
1077 l[c++] = e;
1078 else
1079 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001081 if (ebcdic)
1082 e = (e < 64) ? '.' : etoa64[e-64];
1083 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001085 COLOR_EPILOGUE
1086 n++;
1087 if (++p == cols)
1088 {
1089 l[c++] = '\n';
1090 l[c++] = '\0';
1091 xxdline(fpo, l, autoskip ? nonzero : 1);
1092 nonzero = 0;
1093 p = 0;
1094 }
1095 }
1096 else /*no colors*/
1097 {
1098 if (ebcdic)
1099 e = (e < 64) ? '.' : etoa64[e-64];
1100
1101 c += addrlen + 3 + p;
1102 l[c++] =
Igor Todorovski48a75f32024-01-09 21:05:48 +00001103#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001104 (e >= 64)
1105#else
1106 (e > 31 && e < 127)
1107#endif
1108 ? e : '.';
1109 n++;
1110 if (++p == cols)
1111 {
1112 l[c++] = '\n';
1113 l[c] = '\0';
1114 xxdline(fpo, l, autoskip ? nonzero : 1);
1115 nonzero = 0;
1116 p = 0;
1117 }
1118 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001119 }
1120 if (p)
1121 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001122 l[c++] = '\n';
1123 l[c] = '\0';
1124 if (color)
1125 {
1126 c++;
1127
1128 x = p;
1129 if (hextype == HEX_LITTLEENDIAN)
1130 {
1131 int fill = octspergrp - (p % octspergrp);
1132 if (fill == octspergrp) fill = 0;
1133
1134 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1135
1136 for (i = 0; i < fill;i++)
1137 {
1138 COLOR_PROLOGUE
1139 l[c++] = COLOR_RED;
1140 l[c++] = 'm';
1141 l[c++] = ' '; /* empty space */
1142 COLOR_EPILOGUE
1143 x++;
1144 p++;
1145 }
1146 }
1147
1148 if (hextype != HEX_BITS)
1149 {
1150 c = addrlen + 1 + (grplen * x) / octspergrp;
1151 c += cols - p;
1152 c += (cols - p) / octspergrp;
1153
1154 for (i = cols - p; i > 0;i--)
1155 {
1156 COLOR_PROLOGUE
1157 l[c++] = COLOR_RED;
1158 l[c++] = 'm';
1159 l[c++] = ' '; /* empty space */
1160 COLOR_EPILOGUE
1161 }
1162 }
1163 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164 xxdline(fpo, l, 1);
1165 }
1166 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001167 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001169 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170 return 0;
1171}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001172
1173/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */