blob: 544aa50b955248a9997ad834e9afb3f6ba2a6e74 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* xxd: my hexdump facility. jw
2 *
3 * 2.10.90 changed to word output
4 * 3.03.93 new indent style, dumb bug inserted and fixed.
5 * -c option, mls
6 * 26.04.94 better option parser, -ps, -l, -s added.
7 * 1.07.94 -r badly needs - as input file. Per default autoskip over
Bram Moolenaar82038d72007-05-10 17:15:45 +00008 * consecutive lines of zeroes, as unix od does.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009 * -a shows them too.
10 * -i dump as c-style #include "file.h"
11 * 1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]'
12 * array is written in correct c-syntax.
13 * -s improved, now defaults to absolute seek, relative requires a '+'.
14 * -r improved, now -r -s -0x... is supported.
15 * change/suppress leading '\0' bytes.
16 * -l n improved: stops exactly after n bytes.
17 * -r improved, better handling of partial lines with trailing garbage.
18 * -r improved, now -r -p works again!
19 * -r improved, less flushing, much faster now! (that was silly)
20 * 3.04.96 Per repeated request of a single person: autoskip defaults to off.
21 * 15.05.96 -v added. They want to know the version.
22 * -a fixed, to show last line inf file ends in all zeros.
23 * -u added: Print upper case hex-letters, as preferred by unix bc.
24 * -h added to usage message. Usage message extended.
25 * Now using outfile if specified even in normal mode, aehem.
26 * No longer mixing of ints and longs. May help doze people.
27 * Added binify ioctl for same reason. (Enough Doze stress for 1996!)
28 * 16.05.96 -p improved, removed occasional superfluous linefeed.
29 * 20.05.96 -l 0 fixed. tried to read anyway.
30 * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames.
31 * compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-)
32 * support --gnuish-longhorn-options
33 * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h
34 * which is included by MacHeaders (Axel Kielhorn). Renamed to
35 * xxdline().
36 * 7.06.96 -i printed 'int' instead of 'char'. *blush*
37 * added Bram's OS2 ifdefs...
Bram Moolenaar4b96df52020-01-26 22:00:26 +010038 * 18.07.96 gcc -Wall @ SunOS4 is now silent.
Bram Moolenaar071d4272004-06-13 20:20:40 +000039 * Added osver for MSDOS/DJGPP/WIN32.
40 * 29.08.96 Added size_t to strncmp() for Amiga.
41 * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram)
42 * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII
Bram Moolenaar4317d9b2005-03-18 20:25:31 +000043 * (azc10@yahoo.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000044 * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com).
45 * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was
46 * missing or wrong.
47 * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile.
48 * 27.10.98 Fixed: -g option parser required blank.
49 * option -b added: 01000101 binary output in normal format.
50 * 16.05.00 Added VAXC changes by Stephen P. Wall
Bram Moolenaar82038d72007-05-10 17:15:45 +000051 * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
Bram Moolenaare0659a62011-04-01 19:14:40 +020052 * 2011 March Better error handling by Florian Zumbiehl.
53 * 2011 April Formatting by Bram Moolenaar
Bram Moolenaar4dcdf292015-03-05 17:51:15 +010054 * 08.06.2013 Little-endian hexdump (-e) and offset (-o) by Vadim Vygonets.
Bram Moolenaard8c56a02019-01-30 23:02:25 +010055 * 11.01.2019 Add full 64/32 bit range to -o and output by Christer Jensen.
Bram Moolenaar363d6142020-05-30 20:50:25 +020056 * 04.02.2020 Add -d for decimal offsets by Aapo Rantalainen
Erik Auerswaldc0a1d372022-01-14 11:58:48 +000057 * 14.01.2022 Disable extra newlines with -c0 -p by Erik Auerswald.
David Gow83e11802022-06-29 20:24:49 +010058 * 20.06.2022 Permit setting the variable names used by -i by David Gow
Christian Brabandt0ffa97e2023-08-31 21:03:02 +020059 * 31.08.2023 -R never/auto/always prints colored output
tristhaus85f45212023-10-06 19:51:13 +020060 * 06.10.2023 enable -r -b to reverse bit dumps
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020062 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000063 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020064 * I hereby grant permission to distribute and use xxd
65 * under X11-MIT or GPL-2.0 (at the user's choice).
66 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020067 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000068 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000069
70/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
71#if _MSC_VER >= 1400
72# define _CRT_SECURE_NO_DEPRECATE
73# define _CRT_NONSTDC_NO_DEPRECATE
74#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010075#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000076# define CYGWIN
77#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000078
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000079#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
80# define _XOPEN_SOURCE 700 /* for fdopen() */
81#endif
82
Bram Moolenaar071d4272004-06-13 20:20:40 +000083#include <stdio.h>
84#ifdef VAXC
85# include <file.h>
86#else
87# include <fcntl.h>
88#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020089#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090# include <io.h> /* for setmode() */
K.Takataf6fc2552023-09-01 18:41:04 +020091# include <windows.h>
92#endif
93#ifdef UNIX
94# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000095#endif
96#include <stdlib.h>
97#include <string.h> /* for strncmp() */
98#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010099#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100#if __MWERKS__ && !defined(BEBOX)
101# include <unix.h> /* for fdopen() on MAC */
102#endif
103
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104
105/* This corrects the problem of missing prototypes for certain functions
106 * in some GNU installations (e.g. SunOS 4.1.x).
107 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
108 */
109#if defined(__GNUC__) && defined(__STDC__)
110# ifndef __USE_FIXED_PROTOTYPES__
111# define __USE_FIXED_PROTOTYPES__
112# endif
113#endif
114
115#ifndef __USE_FIXED_PROTOTYPES__
116/*
117 * This is historic and works only if the compiler really has no prototypes:
118 *
119 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
120 * FILE is defined on OS 4.x, not on 5.x (Solaris).
121 * if __SVR4 is defined (some Solaris versions), don't include this.
122 */
123#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
124# define __P(a) a
125/* excerpt from my sun_stdlib.h */
126extern int fprintf __P((FILE *, char *, ...));
127extern int fputs __P((char *, FILE *));
128extern int _flsbuf __P((unsigned char, FILE *));
129extern int _filbuf __P((FILE *));
130extern int fflush __P((FILE *));
131extern int fclose __P((FILE *));
132extern int fseek __P((FILE *, long, int));
133extern int rewind __P((FILE *));
134
135extern void perror __P((char *));
136# endif
137#endif
138
Christian Brabandt7879bc52023-10-08 20:36:44 +0200139char version[] = "xxd 2023-10-08 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140#ifdef WIN32
141char osver[] = " (Win32)";
142#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144#endif
145
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200146#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147# define BIN_READ(yes) ((yes) ? "rb" : "rt")
148# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
149# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
150# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000151# define PATH_SEP '\\'
152#elif defined(CYGWIN)
153# define BIN_READ(yes) ((yes) ? "rb" : "rt")
154# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
155# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
156# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
157# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000158#else
159# ifdef VMS
160# define BIN_READ(dummy) "r"
161# define BIN_WRITE(dummy) "w"
162# define BIN_CREAT(dummy) O_CREAT
163# define BIN_ASSIGN(fp, dummy) fp
164# define PATH_SEP ']'
165# define FILE_SEP '.'
166# else
167# define BIN_READ(dummy) "r"
168# define BIN_WRITE(dummy) "w"
169# define BIN_CREAT(dummy) O_CREAT
170# define BIN_ASSIGN(fp, dummy) fp
171# define PATH_SEP '/'
172# endif
173#endif
174
175/* open has only to arguments on the Mac */
176#if __MWERKS__
177# define OPEN(name, mode, umask) open(name, mode)
178#else
179# define OPEN(name, mode, umask) open(name, mode, umask)
180#endif
181
182#ifdef AMIGA
183# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
184#else
185# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
186#endif
187
188#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200189# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190# define __P(a) a
191# else
192# define __P(a) ()
193# endif
194#endif
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
197#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100198#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199
200char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
201
202/* the different hextypes known by this program: */
203#define HEX_NORMAL 0
204#define HEX_POSTSCRIPT 1
205#define HEX_CINCLUDE 2
206#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100207#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200209#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
210
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200211#define COLOR_PROLOGUE \
212l[c++] = '\033'; \
213l[c++] = '['; \
214l[c++] = '1'; \
215l[c++] = ';'; \
216l[c++] = '3';
217
218#define COLOR_EPILOGUE \
219l[c++] = '\033'; \
220l[c++] = '['; \
221l[c++] = '0'; \
222l[c++] = 'm';
223#define COLOR_RED '1'
224#define COLOR_GREEN '2'
225#define COLOR_YELLOW '3'
226#define COLOR_BLUE '4'
227#define COLOR_WHITE '7'
228
Bram Moolenaare0659a62011-04-01 19:14:40 +0200229static char *pname;
230
231 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100232exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233{
234 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
235 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
236 fprintf(stderr, "Options:\n");
237 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200238 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200239 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000240 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
241 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100242 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100243 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 fprintf(stderr, " -h print this summary.\n");
245 fprintf(stderr, " -i output in C include file style.\n");
246 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100247 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100248 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000249 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
250 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
251 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200252 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000253 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
254#ifdef TRY_SEEK
255 "[+][-]", "(or +: rel.) ");
256#else
257 "", "");
258#endif
259 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200260 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
262 exit(1);
263}
264
Bram Moolenaare0659a62011-04-01 19:14:40 +0200265 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100266perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200267{
268 fprintf(stderr, "%s: ", pname);
269 perror(NULL);
270 exit(ret);
271}
272
DungSagaa2ffb432021-10-22 15:55:31 +0100273 static void
274error_exit(int ret, char *msg)
275{
276 fprintf(stderr, "%s: %s\n", pname, msg);
277 exit(ret);
278}
279
DungSagad1d8a592021-11-26 13:59:27 +0000280 static int
281getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000282{
DungSagad1d8a592021-11-26 13:59:27 +0000283 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000284 if (c == EOF && ferror(fpi))
285 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000286 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000287}
288
289 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000290putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000291{
292 if (putc(c, fpo) == EOF)
293 perror_exit(3);
294}
295
296 static void
297fputs_or_die(char *s, FILE *fpo)
298{
299 if (fputs(s, fpo) == EOF)
300 perror_exit(3);
301}
302
DungSaga7e5503c2021-12-01 11:24:52 +0000303/* Use a macro to allow for different arguments. */
304#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000305
306 static void
307fclose_or_die(FILE *fpi, FILE *fpo)
308{
309 if (fclose(fpo) != 0)
310 perror_exit(3);
311 if (fclose(fpi) != 0)
312 perror_exit(2);
313}
314
Bram Moolenaar071d4272004-06-13 20:20:40 +0000315/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000316 * If "c" is a hex digit, return the value.
317 * Otherwise return -1.
318 */
319 static int
320parse_hex_digit(int c)
321{
322 return (c >= '0' && c <= '9') ? c - '0'
323 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
324 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
325 : -1;
326}
327
328/*
tristhaus85f45212023-10-06 19:51:13 +0200329 * If "c" is a bin digit, return the value.
330 * Otherwise return -1.
331 */
332 static int
333parse_bin_digit(int c)
334{
335 return (c >= '0' && c <= '1') ? c - '0'
336 : -1;
337}
338
339/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000340 * Ignore text on "fpi" until end-of-line or end-of-file.
341 * Return the '\n' or EOF character.
342 * When an error is encountered exit with an error message.
343 */
344 static int
345skip_to_eol(FILE *fpi, int c)
346{
347 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000348 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000349 return c;
350}
351
352/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000353 * Max. cols binary characters are decoded from the input stream per line.
354 * Two adjacent garbage characters after evaluated data delimit valid data.
355 * Everything up to the next newline is discarded.
356 *
357 * The name is historic and came from 'undo type opt h'.
358 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200359 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100360huntype(
361 FILE *fpi,
362 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100363 int cols,
364 int hextype,
365 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200367 int c, ign_garb = 1, n1 = -1, n2 = 0, n3 = 0, p = cols, bt = 0, b = 0, bcnt = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368 long have_off = 0, want_off = 0;
369
370 rewind(fpi);
371
372 while ((c = getc(fpi)) != EOF)
373 {
374 if (c == '\r') /* Doze style input file? */
375 continue;
376
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100377 /* Allow multiple spaces. This doesn't work when there is normal text
378 * after the hex codes in the last line that looks like hex, thus only
379 * use it for PostScript format. */
380 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000381 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000382
tristhaus85f45212023-10-06 19:51:13 +0200383 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
384 {
385 n3 = n2;
386 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000387
tristhaus85f45212023-10-06 19:51:13 +0200388 n1 = parse_hex_digit(c);
389 if (n1 == -1 && ign_garb)
390 continue;
391 }
392 else /* HEX_BITS */
393 {
394 n1 = parse_hex_digit(c);
395 if (n1 == -1 && ign_garb)
396 continue;
397
398 bt = parse_bin_digit(c);
399 if (bt != -1)
400 {
401 b = ((b << 1) | bt);
402 ++bcnt;
403 }
404 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405
406 ign_garb = 0;
407
tristhaus85f45212023-10-06 19:51:13 +0200408 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409 {
tristhaus85f45212023-10-06 19:51:13 +0200410 if (hextype == HEX_NORMAL)
411 {
412 if (n1 < 0)
413 {
414 p = 0;
415 continue;
416 }
417 want_off = (want_off << 4) | n1;
418 }
419 else /* HEX_BITS */
420 {
421 n1 = parse_hex_digit(c);
422 if (n1 >= 0)
423 {
424 want_off = (want_off << 4) | n1;
425 }
426
427 if (bt < 0)
428 {
429 p = 0;
430 bcnt = 0;
431 b = 0;
432 continue;
433 }
434 }
435 continue;
436 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000437
438 if (base_off + want_off != have_off)
439 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200440 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100441 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000442#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000443 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000444 have_off = base_off + want_off;
445#endif
446 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000447 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000448 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000449 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 }
451
tristhaus85f45212023-10-06 19:51:13 +0200452 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
453 {
454 if (n2 >= 0 && n1 >= 0)
455 {
456 putc_or_die((n2 << 4) | n1, fpo);
457 have_off++;
458 want_off++;
459 n1 = -1;
460 if (!hextype && (++p >= cols))
461 /* skip the rest of the line as garbage */
462 c = skip_to_eol(fpi, c);
463 }
464 else if (n1 < 0 && n2 < 0 && n3 < 0)
465 /* already stumbled into garbage, skip line, wait and see */
466 c = skip_to_eol(fpi, c);
467 }
468 else /* HEX_BITS */
469 {
470 if (bcnt == 8)
471 {
472 putc_or_die(b, fpo);
473 have_off++;
474 want_off++;
475 b = 0;
476 bcnt = 0;
477 if (++p >= cols)
478 /* skip the rest of the line as garbage */
479 c = skip_to_eol(fpi, c);
480 }
481 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000482
DungSaga47810462021-10-22 12:55:42 +0100483 if (c == '\n')
484 {
tristhaus85f45212023-10-06 19:51:13 +0200485 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100486 want_off = 0;
487 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488 ign_garb = 1;
489 }
490 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200491 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100492 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000494 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000496 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000497 return 0;
498}
499
500/*
501 * Print line l. If nz is false, xxdline regards the line a line of
502 * zeroes. If there are three or more consecutive lines of zeroes,
503 * they are replaced by a single '*' character.
504 *
505 * If the output ends with more than two lines of zeroes, you
506 * should call xxdline again with l being the last line and nz
507 * negative. This ensures that the last line is shown even when
508 * it is all zeroes.
509 *
510 * If nz is always positive, lines are never suppressed.
511 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200512 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100513xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514{
515 static char z[LLEN+1];
516 static int zero_seen = 0;
517
518 if (!nz && zero_seen == 1)
519 strcpy(z, l);
520
521 if (nz || !zero_seen++)
522 {
523 if (nz)
524 {
525 if (nz < 0)
526 zero_seen--;
527 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000528 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000530 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531 }
532 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000533 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000534 if (nz)
535 zero_seen = 0;
536 }
537}
538
539/* This is an EBCDIC to ASCII conversion table */
540/* from a proposed BTL standard April 16, 1979 */
541static unsigned char etoa64[] =
542{
543 0040,0240,0241,0242,0243,0244,0245,0246,
544 0247,0250,0325,0056,0074,0050,0053,0174,
545 0046,0251,0252,0253,0254,0255,0256,0257,
546 0260,0261,0041,0044,0052,0051,0073,0176,
547 0055,0057,0262,0263,0264,0265,0266,0267,
548 0270,0271,0313,0054,0045,0137,0076,0077,
549 0272,0273,0274,0275,0276,0277,0300,0301,
550 0302,0140,0072,0043,0100,0047,0075,0042,
551 0303,0141,0142,0143,0144,0145,0146,0147,
552 0150,0151,0304,0305,0306,0307,0310,0311,
553 0312,0152,0153,0154,0155,0156,0157,0160,
554 0161,0162,0136,0314,0315,0316,0317,0320,
555 0321,0345,0163,0164,0165,0166,0167,0170,
556 0171,0172,0322,0323,0324,0133,0326,0327,
557 0330,0331,0332,0333,0334,0335,0336,0337,
558 0340,0341,0342,0343,0344,0135,0346,0347,
559 0173,0101,0102,0103,0104,0105,0106,0107,
560 0110,0111,0350,0351,0352,0353,0354,0355,
561 0175,0112,0113,0114,0115,0116,0117,0120,
562 0121,0122,0356,0357,0360,0361,0362,0363,
563 0134,0237,0123,0124,0125,0126,0127,0130,
564 0131,0132,0364,0365,0366,0367,0370,0371,
565 0060,0061,0062,0063,0064,0065,0066,0067,
566 0070,0071,0372,0373,0374,0375,0376,0377
567};
568
K.Takataf6fc2552023-09-01 18:41:04 +0200569 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200570begin_coloring_char (char *l, int *c, int e, int ebcdic)
571{
572 if (ebcdic)
573 {
574 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
575 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
576 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
577 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
578 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
579 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
580 (e == 173) || (e == 224) )
581 l[(*c)++] = COLOR_GREEN;
582
583 else if (e == 37 || e == 13 || e == 5)
584 l[(*c)++] = COLOR_YELLOW;
585 else if (e == 0)
586 l[(*c)++] = COLOR_WHITE;
587 else if (e == 255)
588 l[(*c)++] = COLOR_BLUE;
589 else
590 l[(*c)++] = COLOR_RED;
591 }
592 else /* ASCII */
593 {
594 #ifdef __MVS__
595 if (e >= 64)
596 l[(*c)++] = COLOR_GREEN;
597 #else
598 if (e > 31 && e < 127)
599 l[(*c)++] = COLOR_GREEN;
600 #endif
601
602 else if (e == 9 || e == 10 || e == 13)
603 l[(*c)++] = COLOR_YELLOW;
604 else if (e == 0)
605 l[(*c)++] = COLOR_WHITE;
606 else if (e == 255)
607 l[(*c)++] = COLOR_BLUE;
608 else
609 l[(*c)++] = COLOR_RED;
610 }
611 l[(*c)++] = 'm';
612}
613
K.Takataf6fc2552023-09-01 18:41:04 +0200614 static int
615enable_color(void)
616{
617#ifdef WIN32
618 DWORD mode;
619 HANDLE out;
620
621 if (!isatty(1))
622 return 0;
623
624 out = GetStdHandle(STD_OUTPUT_HANDLE);
625 GetConsoleMode(out, &mode);
626 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
627 return (int)SetConsoleMode(out, mode);
628#elif defined(UNIX)
629 return isatty(STDOUT_FILENO);
630#else
631 return 0;
632#endif
633}
634
Bram Moolenaare0659a62011-04-01 19:14:40 +0200635 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100636main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637{
638 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200639 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000640 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200641 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642 int ebcdic = 0;
643 int octspergrp = -1; /* number of octets grouped in output */
644 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100645 long length = -1, n = 0, seekoff = 0;
646 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200647 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200648 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100649 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100650 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200651 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200652 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200653
K.Takataf6fc2552023-09-01 18:41:04 +0200654 no_color = getenv("NO_COLOR");
655 if (no_color == NULL || no_color[0] == '\0')
656 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000657
658#ifdef AMIGA
659 /* This program doesn't work when started from the Workbench */
660 if (argc == 0)
661 exit(1);
662#endif
663
664 pname = argv[0];
665 for (pp = pname; *pp; )
666 if (*pp++ == PATH_SEP)
667 pname = pp;
668#ifdef FILE_SEP
669 for (pp = pname; *pp; pp++)
670 if (*pp == FILE_SEP)
671 {
672 *pp = '\0';
673 break;
674 }
675#endif
676
677 while (argc >= 2)
678 {
679 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
680 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
681 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100682 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
684 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
685 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200686 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200687 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688 else if (!STRNCMP(pp, "-r", 2)) revert++;
689 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
690 else if (!STRNCMP(pp, "-v", 2))
691 {
692 fprintf(stderr, "%s%s\n", version, osver);
693 exit(0);
694 }
695 else if (!STRNCMP(pp, "-c", 2))
696 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100697 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200698 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100699 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000700 {
701 colsgiven = 1;
702 cols = (int)strtol(pp + 2, NULL, 0);
703 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704 else
705 {
706 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200707 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000708 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709 cols = (int)strtol(argv[2], NULL, 0);
710 argv++;
711 argc--;
712 }
713 }
714 else if (!STRNCMP(pp, "-g", 2))
715 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100716 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717 octspergrp = (int)strtol(pp + 2, NULL, 0);
718 else
719 {
720 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200721 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722 octspergrp = (int)strtol(argv[2], NULL, 0);
723 argv++;
724 argc--;
725 }
726 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100727 else if (!STRNCMP(pp, "-o", 2))
728 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100729 int reloffset = 0;
730 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100731 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100732 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100733 else
734 {
735 if (!argv[2])
736 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100737
738 if (argv[2][0] == '+')
739 reloffset++;
740 if (argv[2][reloffset] == '-')
741 negoffset++;
742
743 if (negoffset)
744 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
745 else
746 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
747
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100748 argv++;
749 argc--;
750 }
751 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752 else if (!STRNCMP(pp, "-s", 2))
753 {
754 relseek = 0;
755 negseek = 0;
756 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
757 {
758#ifdef TRY_SEEK
759 if (pp[2] == '+')
760 relseek++;
761 if (pp[2+relseek] == '-')
762 negseek++;
763#endif
764 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
765 }
766 else
767 {
768 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200769 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770#ifdef TRY_SEEK
771 if (argv[2][0] == '+')
772 relseek++;
773 if (argv[2][relseek] == '-')
774 negseek++;
775#endif
776 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
777 argv++;
778 argc--;
779 }
780 }
781 else if (!STRNCMP(pp, "-l", 2))
782 {
783 if (pp[2] && STRNCMP("en", pp + 2, 2))
784 length = strtol(pp + 2, (char **)NULL, 0);
785 else
786 {
787 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200788 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 length = strtol(argv[2], (char **)NULL, 0);
790 argv++;
791 argc--;
792 }
793 }
David Gow83e11802022-06-29 20:24:49 +0100794 else if (!STRNCMP(pp, "-n", 2))
795 {
796 if (pp[2] && STRNCMP("ame", pp + 2, 3))
797 varname = pp + 2;
798 else
799 {
800 if (!argv[2])
801 exit_with_usage();
802 varname = argv[2];
803 argv++;
804 argc--;
805 }
806 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200807 else if (!STRNCMP(pp, "-R", 2))
808 {
K.Takataf6fc2552023-09-01 18:41:04 +0200809 char *pw = pp + 2;
810 if (!pw[0])
811 {
812 pw = argv[2];
813 argv++;
814 argc--;
815 }
816 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200817 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200818 if (!STRNCMP(pw, "always", 6))
819 {
820 (void)enable_color();
821 color = 1;
822 }
823 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200824 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200825 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200826 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200827 else
828 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200829 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 else if (!strcmp(pp, "--")) /* end of options */
831 {
832 argv++;
833 argc--;
834 break;
835 }
836 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200837 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 else
839 break; /* not an option */
840
841 argv++; /* advance to next argument */
842 argc--;
843 }
844
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000845 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 switch (hextype)
847 {
848 case HEX_POSTSCRIPT: cols = 30; break;
849 case HEX_CINCLUDE: cols = 12; break;
850 case HEX_BITS: cols = 6; break;
851 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100852 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853 default: cols = 16; break;
854 }
855
856 if (octspergrp < 0)
857 switch (hextype)
858 {
859 case HEX_BITS: octspergrp = 1; break;
860 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100861 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 case HEX_POSTSCRIPT:
863 case HEX_CINCLUDE:
864 default: octspergrp = 0; break;
865 }
866
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000867 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
868 (hextype != HEX_POSTSCRIPT && cols < 1) ||
869 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000870 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 {
872 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
873 exit(1);
874 }
875
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100876 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100878 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100879 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880
881 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200882 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883
884 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
885 BIN_ASSIGN(fp = stdin, !revert);
886 else
887 {
888 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
889 {
890 fprintf(stderr,"%s: ", pname);
891 perror(argv[1]);
892 return 2;
893 }
894 }
895
896 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
897 BIN_ASSIGN(fpo = stdout, revert);
898 else
899 {
900 int fd;
901 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
902
903 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
904 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
905 {
906 fprintf(stderr, "%s: ", pname);
907 perror(argv[2]);
908 return 3;
909 }
910 rewind(fpo);
911 }
912
913 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200914 switch (hextype)
915 {
916 case HEX_NORMAL:
917 case HEX_POSTSCRIPT:
918 case HEX_BITS:
919 return huntype(fp, fpo, cols, hextype,
920 negseek ? -seekoff : seekoff);
921 break;
922 default:
923 error_exit(-1, "Sorry, cannot revert this type of hexdump");
924 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925
926 if (seekoff || negseek || !relseek)
927 {
928#ifdef TRY_SEEK
929 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000930 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000932 e = fseek(fp, negseek ? -seekoff : seekoff,
933 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000934 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000935 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936 if (e >= 0)
937 seekoff = ftell(fp);
938 else
939#endif
940 {
941 long s = seekoff;
942
943 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000944 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200945 {
DungSaga7e5503c2021-12-01 11:24:52 +0000946 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200947 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000948 }
949 }
950
951 if (hextype == HEX_CINCLUDE)
952 {
David Gow83e11802022-06-29 20:24:49 +0100953 /* A user-set variable name overrides fp == stdin */
954 if (varname == NULL && fp != stdin)
955 varname = argv[1];
956
957 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958 {
David Gow83e11802022-06-29 20:24:49 +0100959 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
960 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000961 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
962 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 }
964
965 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000966 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000967 {
DungSaga7e5503c2021-12-01 11:24:52 +0000968 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
969 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 p++;
971 }
972
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000973 if (p)
974 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975
David Gow83e11802022-06-29 20:24:49 +0100976 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 {
DungSagad1d8a592021-11-26 13:59:27 +0000978 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100979 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
980 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000981 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000982 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000983 }
984
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000985 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 return 0;
987 }
988
989 if (hextype == HEX_POSTSCRIPT)
990 {
991 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000992 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000994 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
995 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000997 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000999 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000 p = cols;
1001 }
1002 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +00001003 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001004 putc_or_die('\n', fpo);
1005 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001006 return 0;
1007 }
1008
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001009 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001010
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001011 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001012 {
1013 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1014 if (color)
1015 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1016 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001017 else /* hextype == HEX_BITS */
1018 grplen = 8 * octspergrp + 1;
1019
DungSagad1d8a592021-11-26 13:59:27 +00001020 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 {
1022 if (p == 0)
1023 {
DungSaga581f41a2021-11-22 11:57:31 +00001024 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001025 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001026 for (c = addrlen; c < LLEN; l[c++] = ' ')
1027 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 }
DungSaga48608b42021-11-24 11:18:07 +00001029 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1030 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001031 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001032 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001033 if (color)
1034 {
1035 COLOR_PROLOGUE
1036 begin_coloring_char(l,&c,e,ebcdic);
1037 l[c++] = hexx[(e >> 4) & 0xf];
1038 l[c++] = hexx[e & 0xf];
1039 COLOR_EPILOGUE
1040 }
1041 else /*No colors*/
1042 {
1043 l[c] = hexx[(e >> 4) & 0xf];
1044 l[++c] = hexx[e & 0xf];
1045 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001046 }
1047 else /* hextype == HEX_BITS */
1048 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001050 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001052 if (e)
1053 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001054 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001055 if (hextype == HEX_LITTLEENDIAN)
1056 /* last group will be fully used, round up */
1057 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1058 else
1059 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001060
1061 if (color)
1062 {
1063 if (hextype == HEX_BITS)
1064 c += addrlen + 3 + p*12;
1065 else
1066 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1067
1068 if (hextype == HEX_LITTLEENDIAN)
1069 c += 1;
1070
1071 COLOR_PROLOGUE
1072 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001073#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001074 if (e >= 64)
1075 l[c++] = e;
1076 else
1077 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001079 if (ebcdic)
1080 e = (e < 64) ? '.' : etoa64[e-64];
1081 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001083 COLOR_EPILOGUE
1084 n++;
1085 if (++p == cols)
1086 {
1087 l[c++] = '\n';
1088 l[c++] = '\0';
1089 xxdline(fpo, l, autoskip ? nonzero : 1);
1090 nonzero = 0;
1091 p = 0;
1092 }
1093 }
1094 else /*no colors*/
1095 {
1096 if (ebcdic)
1097 e = (e < 64) ? '.' : etoa64[e-64];
1098
1099 c += addrlen + 3 + p;
1100 l[c++] =
1101#ifdef __MVS__
1102 (e >= 64)
1103#else
1104 (e > 31 && e < 127)
1105#endif
1106 ? e : '.';
1107 n++;
1108 if (++p == cols)
1109 {
1110 l[c++] = '\n';
1111 l[c] = '\0';
1112 xxdline(fpo, l, autoskip ? nonzero : 1);
1113 nonzero = 0;
1114 p = 0;
1115 }
1116 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 }
1118 if (p)
1119 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001120 l[c++] = '\n';
1121 l[c] = '\0';
1122 if (color)
1123 {
1124 c++;
1125
1126 x = p;
1127 if (hextype == HEX_LITTLEENDIAN)
1128 {
1129 int fill = octspergrp - (p % octspergrp);
1130 if (fill == octspergrp) fill = 0;
1131
1132 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1133
1134 for (i = 0; i < fill;i++)
1135 {
1136 COLOR_PROLOGUE
1137 l[c++] = COLOR_RED;
1138 l[c++] = 'm';
1139 l[c++] = ' '; /* empty space */
1140 COLOR_EPILOGUE
1141 x++;
1142 p++;
1143 }
1144 }
1145
1146 if (hextype != HEX_BITS)
1147 {
1148 c = addrlen + 1 + (grplen * x) / octspergrp;
1149 c += cols - p;
1150 c += (cols - p) / octspergrp;
1151
1152 for (i = cols - p; i > 0;i--)
1153 {
1154 COLOR_PROLOGUE
1155 l[c++] = COLOR_RED;
1156 l[c++] = 'm';
1157 l[c++] = ' '; /* empty space */
1158 COLOR_EPILOGUE
1159 }
1160 }
1161 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001162 xxdline(fpo, l, 1);
1163 }
1164 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001165 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001167 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 return 0;
1169}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001170
1171/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */