blob: 26f8d8365d79a39951e1a32ef8028859858f08aa [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() */
Ken Takatac4a40382023-10-25 21:17:35 +020091#endif
92#ifdef WIN32
K.Takataf6fc2552023-09-01 18:41:04 +020093# include <windows.h>
94#endif
95#ifdef UNIX
96# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000097#endif
98#include <stdlib.h>
Keith Thompson184f71c2024-01-04 21:19:04 +010099#include <string.h>
100#include <ctype.h>
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100101#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102#if __MWERKS__ && !defined(BEBOX)
103# include <unix.h> /* for fdopen() on MAC */
104#endif
105
Bram Moolenaar071d4272004-06-13 20:20:40 +0000106
107/* This corrects the problem of missing prototypes for certain functions
108 * in some GNU installations (e.g. SunOS 4.1.x).
109 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
110 */
111#if defined(__GNUC__) && defined(__STDC__)
112# ifndef __USE_FIXED_PROTOTYPES__
113# define __USE_FIXED_PROTOTYPES__
114# endif
115#endif
116
117#ifndef __USE_FIXED_PROTOTYPES__
118/*
119 * This is historic and works only if the compiler really has no prototypes:
120 *
121 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
122 * FILE is defined on OS 4.x, not on 5.x (Solaris).
123 * if __SVR4 is defined (some Solaris versions), don't include this.
124 */
125#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
126# define __P(a) a
127/* excerpt from my sun_stdlib.h */
128extern int fprintf __P((FILE *, char *, ...));
129extern int fputs __P((char *, FILE *));
130extern int _flsbuf __P((unsigned char, FILE *));
131extern int _filbuf __P((FILE *));
132extern int fflush __P((FILE *));
133extern int fclose __P((FILE *));
134extern int fseek __P((FILE *, long, int));
135extern int rewind __P((FILE *));
136
137extern void perror __P((char *));
138# endif
139#endif
140
Ken Takatac4a40382023-10-25 21:17:35 +0200141char version[] = "xxd 2023-10-25 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142#ifdef WIN32
143char osver[] = " (Win32)";
144#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146#endif
147
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200148#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000149# define BIN_READ(yes) ((yes) ? "rb" : "rt")
150# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
151# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
152# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000153# define PATH_SEP '\\'
154#elif defined(CYGWIN)
155# define BIN_READ(yes) ((yes) ? "rb" : "rt")
156# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
157# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
158# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
159# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160#else
161# ifdef VMS
162# define BIN_READ(dummy) "r"
163# define BIN_WRITE(dummy) "w"
164# define BIN_CREAT(dummy) O_CREAT
165# define BIN_ASSIGN(fp, dummy) fp
166# define PATH_SEP ']'
167# define FILE_SEP '.'
168# else
169# define BIN_READ(dummy) "r"
170# define BIN_WRITE(dummy) "w"
171# define BIN_CREAT(dummy) O_CREAT
172# define BIN_ASSIGN(fp, dummy) fp
173# define PATH_SEP '/'
174# endif
175#endif
176
177/* open has only to arguments on the Mac */
178#if __MWERKS__
179# define OPEN(name, mode, umask) open(name, mode)
180#else
181# define OPEN(name, mode, umask) open(name, mode, umask)
182#endif
183
184#ifdef AMIGA
185# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
186#else
187# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
188#endif
189
190#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200191# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192# define __P(a) a
193# else
194# define __P(a) ()
195# endif
196#endif
197
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
199#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100200#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201
202char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
203
204/* the different hextypes known by this program: */
205#define HEX_NORMAL 0
206#define HEX_POSTSCRIPT 1
207#define HEX_CINCLUDE 2
208#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100209#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000210
Keith Thompson184f71c2024-01-04 21:19:04 +0100211#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : (c))
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200212
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200213#define COLOR_PROLOGUE \
214l[c++] = '\033'; \
215l[c++] = '['; \
216l[c++] = '1'; \
217l[c++] = ';'; \
218l[c++] = '3';
219
220#define COLOR_EPILOGUE \
221l[c++] = '\033'; \
222l[c++] = '['; \
223l[c++] = '0'; \
224l[c++] = 'm';
225#define COLOR_RED '1'
226#define COLOR_GREEN '2'
227#define COLOR_YELLOW '3'
228#define COLOR_BLUE '4'
229#define COLOR_WHITE '7'
230
Bram Moolenaare0659a62011-04-01 19:14:40 +0200231static char *pname;
232
233 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100234exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235{
236 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
237 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
238 fprintf(stderr, "Options:\n");
239 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200240 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200241 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
243 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100244 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100245 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000246 fprintf(stderr, " -h print this summary.\n");
247 fprintf(stderr, " -i output in C include file style.\n");
248 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100249 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100250 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
252 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
253 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200254 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000255 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
256#ifdef TRY_SEEK
257 "[+][-]", "(or +: rel.) ");
258#else
259 "", "");
260#endif
261 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200262 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
264 exit(1);
265}
266
Bram Moolenaare0659a62011-04-01 19:14:40 +0200267 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100268perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200269{
270 fprintf(stderr, "%s: ", pname);
271 perror(NULL);
272 exit(ret);
273}
274
DungSagaa2ffb432021-10-22 15:55:31 +0100275 static void
276error_exit(int ret, char *msg)
277{
278 fprintf(stderr, "%s: %s\n", pname, msg);
279 exit(ret);
280}
281
DungSagad1d8a592021-11-26 13:59:27 +0000282 static int
283getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000284{
DungSagad1d8a592021-11-26 13:59:27 +0000285 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000286 if (c == EOF && ferror(fpi))
287 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000288 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000289}
290
291 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000292putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000293{
294 if (putc(c, fpo) == EOF)
295 perror_exit(3);
296}
297
298 static void
299fputs_or_die(char *s, FILE *fpo)
300{
301 if (fputs(s, fpo) == EOF)
302 perror_exit(3);
303}
304
DungSaga7e5503c2021-12-01 11:24:52 +0000305/* Use a macro to allow for different arguments. */
306#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000307
308 static void
309fclose_or_die(FILE *fpi, FILE *fpo)
310{
311 if (fclose(fpo) != 0)
312 perror_exit(3);
313 if (fclose(fpi) != 0)
314 perror_exit(2);
315}
316
Bram Moolenaar071d4272004-06-13 20:20:40 +0000317/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000318 * If "c" is a hex digit, return the value.
319 * Otherwise return -1.
320 */
321 static int
322parse_hex_digit(int c)
323{
324 return (c >= '0' && c <= '9') ? c - '0'
325 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
326 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
327 : -1;
328}
329
330/*
tristhaus85f45212023-10-06 19:51:13 +0200331 * If "c" is a bin digit, return the value.
332 * Otherwise return -1.
333 */
334 static int
335parse_bin_digit(int c)
336{
337 return (c >= '0' && c <= '1') ? c - '0'
338 : -1;
339}
340
341/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000342 * Ignore text on "fpi" until end-of-line or end-of-file.
343 * Return the '\n' or EOF character.
344 * When an error is encountered exit with an error message.
345 */
346 static int
347skip_to_eol(FILE *fpi, int c)
348{
349 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000350 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000351 return c;
352}
353
354/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000355 * Max. cols binary characters are decoded from the input stream per line.
356 * Two adjacent garbage characters after evaluated data delimit valid data.
357 * Everything up to the next newline is discarded.
358 *
359 * The name is historic and came from 'undo type opt h'.
360 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200361 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100362huntype(
363 FILE *fpi,
364 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100365 int cols,
366 int hextype,
367 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200369 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 +0000370 long have_off = 0, want_off = 0;
371
372 rewind(fpi);
373
374 while ((c = getc(fpi)) != EOF)
375 {
376 if (c == '\r') /* Doze style input file? */
377 continue;
378
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100379 /* Allow multiple spaces. This doesn't work when there is normal text
380 * after the hex codes in the last line that looks like hex, thus only
381 * use it for PostScript format. */
382 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000383 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000384
tristhaus85f45212023-10-06 19:51:13 +0200385 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
386 {
387 n3 = n2;
388 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389
tristhaus85f45212023-10-06 19:51:13 +0200390 n1 = parse_hex_digit(c);
391 if (n1 == -1 && ign_garb)
392 continue;
393 }
394 else /* HEX_BITS */
395 {
396 n1 = parse_hex_digit(c);
397 if (n1 == -1 && ign_garb)
398 continue;
399
400 bt = parse_bin_digit(c);
401 if (bt != -1)
402 {
403 b = ((b << 1) | bt);
404 ++bcnt;
405 }
406 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000407
408 ign_garb = 0;
409
tristhaus85f45212023-10-06 19:51:13 +0200410 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000411 {
tristhaus85f45212023-10-06 19:51:13 +0200412 if (hextype == HEX_NORMAL)
413 {
414 if (n1 < 0)
415 {
416 p = 0;
417 continue;
418 }
419 want_off = (want_off << 4) | n1;
420 }
421 else /* HEX_BITS */
422 {
OldWorldOrdr1c140302023-10-25 20:57:30 +0200423 if (n1 < 0)
424 {
425 p = 0;
tristhaus85f45212023-10-06 19:51:13 +0200426 bcnt = 0;
OldWorldOrdr1c140302023-10-25 20:57:30 +0200427 continue;
428 }
429 want_off = (want_off << 4) | n1;
tristhaus85f45212023-10-06 19:51:13 +0200430 }
431 continue;
432 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433
434 if (base_off + want_off != have_off)
435 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200436 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100437 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000438#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000439 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000440 have_off = base_off + want_off;
441#endif
442 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000443 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000444 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000445 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 }
447
tristhaus85f45212023-10-06 19:51:13 +0200448 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
449 {
450 if (n2 >= 0 && n1 >= 0)
451 {
452 putc_or_die((n2 << 4) | n1, fpo);
453 have_off++;
454 want_off++;
455 n1 = -1;
456 if (!hextype && (++p >= cols))
457 /* skip the rest of the line as garbage */
458 c = skip_to_eol(fpi, c);
459 }
460 else if (n1 < 0 && n2 < 0 && n3 < 0)
461 /* already stumbled into garbage, skip line, wait and see */
462 c = skip_to_eol(fpi, c);
463 }
464 else /* HEX_BITS */
465 {
466 if (bcnt == 8)
467 {
468 putc_or_die(b, fpo);
469 have_off++;
470 want_off++;
471 b = 0;
472 bcnt = 0;
473 if (++p >= cols)
474 /* skip the rest of the line as garbage */
475 c = skip_to_eol(fpi, c);
476 }
477 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000478
DungSaga47810462021-10-22 12:55:42 +0100479 if (c == '\n')
480 {
tristhaus85f45212023-10-06 19:51:13 +0200481 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100482 want_off = 0;
483 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000484 ign_garb = 1;
485 }
486 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200487 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100488 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000489#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000490 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000491#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000492 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 return 0;
494}
495
496/*
497 * Print line l. If nz is false, xxdline regards the line a line of
498 * zeroes. If there are three or more consecutive lines of zeroes,
499 * they are replaced by a single '*' character.
500 *
501 * If the output ends with more than two lines of zeroes, you
502 * should call xxdline again with l being the last line and nz
503 * negative. This ensures that the last line is shown even when
504 * it is all zeroes.
505 *
506 * If nz is always positive, lines are never suppressed.
507 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200508 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100509xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000510{
511 static char z[LLEN+1];
512 static int zero_seen = 0;
513
514 if (!nz && zero_seen == 1)
515 strcpy(z, l);
516
517 if (nz || !zero_seen++)
518 {
519 if (nz)
520 {
521 if (nz < 0)
522 zero_seen--;
523 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000524 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000526 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 }
528 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000529 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000530 if (nz)
531 zero_seen = 0;
532 }
533}
534
535/* This is an EBCDIC to ASCII conversion table */
536/* from a proposed BTL standard April 16, 1979 */
537static unsigned char etoa64[] =
538{
539 0040,0240,0241,0242,0243,0244,0245,0246,
540 0247,0250,0325,0056,0074,0050,0053,0174,
541 0046,0251,0252,0253,0254,0255,0256,0257,
542 0260,0261,0041,0044,0052,0051,0073,0176,
543 0055,0057,0262,0263,0264,0265,0266,0267,
544 0270,0271,0313,0054,0045,0137,0076,0077,
545 0272,0273,0274,0275,0276,0277,0300,0301,
546 0302,0140,0072,0043,0100,0047,0075,0042,
547 0303,0141,0142,0143,0144,0145,0146,0147,
548 0150,0151,0304,0305,0306,0307,0310,0311,
549 0312,0152,0153,0154,0155,0156,0157,0160,
550 0161,0162,0136,0314,0315,0316,0317,0320,
551 0321,0345,0163,0164,0165,0166,0167,0170,
552 0171,0172,0322,0323,0324,0133,0326,0327,
553 0330,0331,0332,0333,0334,0335,0336,0337,
554 0340,0341,0342,0343,0344,0135,0346,0347,
555 0173,0101,0102,0103,0104,0105,0106,0107,
556 0110,0111,0350,0351,0352,0353,0354,0355,
557 0175,0112,0113,0114,0115,0116,0117,0120,
558 0121,0122,0356,0357,0360,0361,0362,0363,
559 0134,0237,0123,0124,0125,0126,0127,0130,
560 0131,0132,0364,0365,0366,0367,0370,0371,
561 0060,0061,0062,0063,0064,0065,0066,0067,
562 0070,0071,0372,0373,0374,0375,0376,0377
563};
564
K.Takataf6fc2552023-09-01 18:41:04 +0200565 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200566begin_coloring_char (char *l, int *c, int e, int ebcdic)
567{
568 if (ebcdic)
569 {
570 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
571 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
572 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
573 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
574 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
575 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
576 (e == 173) || (e == 224) )
577 l[(*c)++] = COLOR_GREEN;
578
579 else if (e == 37 || e == 13 || e == 5)
580 l[(*c)++] = COLOR_YELLOW;
581 else if (e == 0)
582 l[(*c)++] = COLOR_WHITE;
583 else if (e == 255)
584 l[(*c)++] = COLOR_BLUE;
585 else
586 l[(*c)++] = COLOR_RED;
587 }
588 else /* ASCII */
589 {
590 #ifdef __MVS__
591 if (e >= 64)
592 l[(*c)++] = COLOR_GREEN;
593 #else
594 if (e > 31 && e < 127)
595 l[(*c)++] = COLOR_GREEN;
596 #endif
597
598 else if (e == 9 || e == 10 || e == 13)
599 l[(*c)++] = COLOR_YELLOW;
600 else if (e == 0)
601 l[(*c)++] = COLOR_WHITE;
602 else if (e == 255)
603 l[(*c)++] = COLOR_BLUE;
604 else
605 l[(*c)++] = COLOR_RED;
606 }
607 l[(*c)++] = 'm';
608}
609
K.Takataf6fc2552023-09-01 18:41:04 +0200610 static int
611enable_color(void)
612{
613#ifdef WIN32
614 DWORD mode;
615 HANDLE out;
616
617 if (!isatty(1))
618 return 0;
619
620 out = GetStdHandle(STD_OUTPUT_HANDLE);
621 GetConsoleMode(out, &mode);
622 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
623 return (int)SetConsoleMode(out, mode);
624#elif defined(UNIX)
625 return isatty(STDOUT_FILENO);
626#else
627 return 0;
628#endif
629}
630
Bram Moolenaare0659a62011-04-01 19:14:40 +0200631 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100632main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633{
634 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200635 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000636 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200637 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000638 int ebcdic = 0;
639 int octspergrp = -1; /* number of octets grouped in output */
640 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100641 long length = -1, n = 0, seekoff = 0;
642 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200643 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200644 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100645 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100646 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200647 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200648 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200649
K.Takataf6fc2552023-09-01 18:41:04 +0200650 no_color = getenv("NO_COLOR");
651 if (no_color == NULL || no_color[0] == '\0')
652 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000653
654#ifdef AMIGA
655 /* This program doesn't work when started from the Workbench */
656 if (argc == 0)
657 exit(1);
658#endif
659
660 pname = argv[0];
661 for (pp = pname; *pp; )
662 if (*pp++ == PATH_SEP)
663 pname = pp;
664#ifdef FILE_SEP
665 for (pp = pname; *pp; pp++)
666 if (*pp == FILE_SEP)
667 {
668 *pp = '\0';
669 break;
670 }
671#endif
672
673 while (argc >= 2)
674 {
675 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
676 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
677 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100678 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000679 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
680 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
681 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200682 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200683 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684 else if (!STRNCMP(pp, "-r", 2)) revert++;
685 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
686 else if (!STRNCMP(pp, "-v", 2))
687 {
688 fprintf(stderr, "%s%s\n", version, osver);
689 exit(0);
690 }
691 else if (!STRNCMP(pp, "-c", 2))
692 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100693 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200694 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100695 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000696 {
697 colsgiven = 1;
698 cols = (int)strtol(pp + 2, NULL, 0);
699 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000700 else
701 {
702 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200703 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000704 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705 cols = (int)strtol(argv[2], NULL, 0);
706 argv++;
707 argc--;
708 }
709 }
710 else if (!STRNCMP(pp, "-g", 2))
711 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100712 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 octspergrp = (int)strtol(pp + 2, NULL, 0);
714 else
715 {
716 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200717 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 octspergrp = (int)strtol(argv[2], NULL, 0);
719 argv++;
720 argc--;
721 }
722 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100723 else if (!STRNCMP(pp, "-o", 2))
724 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100725 int reloffset = 0;
726 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100727 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100728 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100729 else
730 {
731 if (!argv[2])
732 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100733
734 if (argv[2][0] == '+')
735 reloffset++;
736 if (argv[2][reloffset] == '-')
737 negoffset++;
738
739 if (negoffset)
740 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
741 else
742 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
743
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100744 argv++;
745 argc--;
746 }
747 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000748 else if (!STRNCMP(pp, "-s", 2))
749 {
750 relseek = 0;
751 negseek = 0;
752 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
753 {
754#ifdef TRY_SEEK
755 if (pp[2] == '+')
756 relseek++;
757 if (pp[2+relseek] == '-')
758 negseek++;
759#endif
760 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
761 }
762 else
763 {
764 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200765 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766#ifdef TRY_SEEK
767 if (argv[2][0] == '+')
768 relseek++;
769 if (argv[2][relseek] == '-')
770 negseek++;
771#endif
772 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
773 argv++;
774 argc--;
775 }
776 }
777 else if (!STRNCMP(pp, "-l", 2))
778 {
779 if (pp[2] && STRNCMP("en", pp + 2, 2))
780 length = strtol(pp + 2, (char **)NULL, 0);
781 else
782 {
783 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200784 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785 length = strtol(argv[2], (char **)NULL, 0);
786 argv++;
787 argc--;
788 }
789 }
David Gow83e11802022-06-29 20:24:49 +0100790 else if (!STRNCMP(pp, "-n", 2))
791 {
792 if (pp[2] && STRNCMP("ame", pp + 2, 3))
793 varname = pp + 2;
794 else
795 {
796 if (!argv[2])
797 exit_with_usage();
798 varname = argv[2];
799 argv++;
800 argc--;
801 }
802 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200803 else if (!STRNCMP(pp, "-R", 2))
804 {
K.Takataf6fc2552023-09-01 18:41:04 +0200805 char *pw = pp + 2;
806 if (!pw[0])
807 {
808 pw = argv[2];
809 argv++;
810 argc--;
811 }
812 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200813 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200814 if (!STRNCMP(pw, "always", 6))
815 {
816 (void)enable_color();
817 color = 1;
818 }
819 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200820 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200821 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200822 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200823 else
824 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200825 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 else if (!strcmp(pp, "--")) /* end of options */
827 {
828 argv++;
829 argc--;
830 break;
831 }
832 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200833 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 else
835 break; /* not an option */
836
837 argv++; /* advance to next argument */
838 argc--;
839 }
840
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000841 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 switch (hextype)
843 {
844 case HEX_POSTSCRIPT: cols = 30; break;
845 case HEX_CINCLUDE: cols = 12; break;
846 case HEX_BITS: cols = 6; break;
847 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100848 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 default: cols = 16; break;
850 }
851
852 if (octspergrp < 0)
853 switch (hextype)
854 {
855 case HEX_BITS: octspergrp = 1; break;
856 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100857 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858 case HEX_POSTSCRIPT:
859 case HEX_CINCLUDE:
860 default: octspergrp = 0; break;
861 }
862
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000863 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
864 (hextype != HEX_POSTSCRIPT && cols < 1) ||
865 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000866 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 {
868 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
869 exit(1);
870 }
871
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100872 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100874 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100875 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000876
877 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200878 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879
880 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
881 BIN_ASSIGN(fp = stdin, !revert);
882 else
883 {
884 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
885 {
886 fprintf(stderr,"%s: ", pname);
887 perror(argv[1]);
888 return 2;
889 }
890 }
891
892 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
893 BIN_ASSIGN(fpo = stdout, revert);
894 else
895 {
896 int fd;
897 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
898
899 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
900 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
901 {
902 fprintf(stderr, "%s: ", pname);
903 perror(argv[2]);
904 return 3;
905 }
906 rewind(fpo);
907 }
908
909 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200910 switch (hextype)
911 {
912 case HEX_NORMAL:
913 case HEX_POSTSCRIPT:
914 case HEX_BITS:
915 return huntype(fp, fpo, cols, hextype,
916 negseek ? -seekoff : seekoff);
917 break;
918 default:
919 error_exit(-1, "Sorry, cannot revert this type of hexdump");
920 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921
922 if (seekoff || negseek || !relseek)
923 {
924#ifdef TRY_SEEK
925 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000926 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000928 e = fseek(fp, negseek ? -seekoff : seekoff,
929 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000930 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000931 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932 if (e >= 0)
933 seekoff = ftell(fp);
934 else
935#endif
936 {
937 long s = seekoff;
938
939 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000940 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200941 {
DungSaga7e5503c2021-12-01 11:24:52 +0000942 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200943 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000944 }
945 }
946
947 if (hextype == HEX_CINCLUDE)
948 {
David Gow83e11802022-06-29 20:24:49 +0100949 /* A user-set variable name overrides fp == stdin */
950 if (varname == NULL && fp != stdin)
951 varname = argv[1];
952
953 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000954 {
Keith Thompson184f71c2024-01-04 21:19:04 +0100955 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100956 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100957 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000958 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 }
960
961 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000962 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 {
DungSaga7e5503c2021-12-01 11:24:52 +0000964 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
965 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 p++;
967 }
968
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000969 if (p)
970 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000971
David Gow83e11802022-06-29 20:24:49 +0100972 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 {
DungSagad1d8a592021-11-26 13:59:27 +0000974 fputs_or_die("};\n", fpo);
Keith Thompson184f71c2024-01-04 21:19:04 +0100975 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100976 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100977 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000978 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979 }
980
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000981 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 return 0;
983 }
984
985 if (hextype == HEX_POSTSCRIPT)
986 {
987 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000988 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000990 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
991 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000993 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000995 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996 p = cols;
997 }
998 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000999 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001000 putc_or_die('\n', fpo);
1001 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 return 0;
1003 }
1004
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001005 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001006
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001007 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001008 {
1009 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1010 if (color)
1011 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1012 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013 else /* hextype == HEX_BITS */
1014 grplen = 8 * octspergrp + 1;
1015
DungSagad1d8a592021-11-26 13:59:27 +00001016 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001017 {
1018 if (p == 0)
1019 {
DungSaga581f41a2021-11-22 11:57:31 +00001020 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001021 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001022 for (c = addrlen; c < LLEN; l[c++] = ' ')
1023 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 }
DungSaga48608b42021-11-24 11:18:07 +00001025 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1026 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001027 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001029 if (color)
1030 {
1031 COLOR_PROLOGUE
1032 begin_coloring_char(l,&c,e,ebcdic);
1033 l[c++] = hexx[(e >> 4) & 0xf];
1034 l[c++] = hexx[e & 0xf];
1035 COLOR_EPILOGUE
1036 }
1037 else /*No colors*/
1038 {
1039 l[c] = hexx[(e >> 4) & 0xf];
1040 l[++c] = hexx[e & 0xf];
1041 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042 }
1043 else /* hextype == HEX_BITS */
1044 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001046 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001048 if (e)
1049 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001050 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001051 if (hextype == HEX_LITTLEENDIAN)
1052 /* last group will be fully used, round up */
1053 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1054 else
1055 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001056
1057 if (color)
1058 {
1059 if (hextype == HEX_BITS)
1060 c += addrlen + 3 + p*12;
1061 else
1062 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1063
1064 if (hextype == HEX_LITTLEENDIAN)
1065 c += 1;
1066
1067 COLOR_PROLOGUE
1068 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001069#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001070 if (e >= 64)
1071 l[c++] = e;
1072 else
1073 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001075 if (ebcdic)
1076 e = (e < 64) ? '.' : etoa64[e-64];
1077 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001079 COLOR_EPILOGUE
1080 n++;
1081 if (++p == cols)
1082 {
1083 l[c++] = '\n';
1084 l[c++] = '\0';
1085 xxdline(fpo, l, autoskip ? nonzero : 1);
1086 nonzero = 0;
1087 p = 0;
1088 }
1089 }
1090 else /*no colors*/
1091 {
1092 if (ebcdic)
1093 e = (e < 64) ? '.' : etoa64[e-64];
1094
1095 c += addrlen + 3 + p;
1096 l[c++] =
1097#ifdef __MVS__
1098 (e >= 64)
1099#else
1100 (e > 31 && e < 127)
1101#endif
1102 ? e : '.';
1103 n++;
1104 if (++p == cols)
1105 {
1106 l[c++] = '\n';
1107 l[c] = '\0';
1108 xxdline(fpo, l, autoskip ? nonzero : 1);
1109 nonzero = 0;
1110 p = 0;
1111 }
1112 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001113 }
1114 if (p)
1115 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001116 l[c++] = '\n';
1117 l[c] = '\0';
1118 if (color)
1119 {
1120 c++;
1121
1122 x = p;
1123 if (hextype == HEX_LITTLEENDIAN)
1124 {
1125 int fill = octspergrp - (p % octspergrp);
1126 if (fill == octspergrp) fill = 0;
1127
1128 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1129
1130 for (i = 0; i < fill;i++)
1131 {
1132 COLOR_PROLOGUE
1133 l[c++] = COLOR_RED;
1134 l[c++] = 'm';
1135 l[c++] = ' '; /* empty space */
1136 COLOR_EPILOGUE
1137 x++;
1138 p++;
1139 }
1140 }
1141
1142 if (hextype != HEX_BITS)
1143 {
1144 c = addrlen + 1 + (grplen * x) / octspergrp;
1145 c += cols - p;
1146 c += (cols - p) / octspergrp;
1147
1148 for (i = cols - p; i > 0;i--)
1149 {
1150 COLOR_PROLOGUE
1151 l[c++] = COLOR_RED;
1152 l[c++] = 'm';
1153 l[c++] = ' '; /* empty space */
1154 COLOR_EPILOGUE
1155 }
1156 }
1157 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 xxdline(fpo, l, 1);
1159 }
1160 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001161 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001162
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001163 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164 return 0;
1165}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001166
1167/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */