blob: 1ba22477fd94876671a75d93521917963c3a3298 [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
Bram Moolenaar071d4272004-06-13 20:20:40 +000060 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020061 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000062 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020063 * I hereby grant permission to distribute and use xxd
64 * under X11-MIT or GPL-2.0 (at the user's choice).
65 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020066 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000068
69/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
70#if _MSC_VER >= 1400
71# define _CRT_SECURE_NO_DEPRECATE
72# define _CRT_NONSTDC_NO_DEPRECATE
73#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010074#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000075# define CYGWIN
76#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000077
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000078#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
79# define _XOPEN_SOURCE 700 /* for fdopen() */
80#endif
81
Bram Moolenaar071d4272004-06-13 20:20:40 +000082#include <stdio.h>
83#ifdef VAXC
84# include <file.h>
85#else
86# include <fcntl.h>
87#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020088#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000089# include <io.h> /* for setmode() */
K.Takataf6fc2552023-09-01 18:41:04 +020090# include <windows.h>
91#endif
92#ifdef UNIX
93# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000094#endif
95#include <stdlib.h>
96#include <string.h> /* for strncmp() */
97#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010098#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000099#if __MWERKS__ && !defined(BEBOX)
100# include <unix.h> /* for fdopen() on MAC */
101#endif
102
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103
104/* This corrects the problem of missing prototypes for certain functions
105 * in some GNU installations (e.g. SunOS 4.1.x).
106 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
107 */
108#if defined(__GNUC__) && defined(__STDC__)
109# ifndef __USE_FIXED_PROTOTYPES__
110# define __USE_FIXED_PROTOTYPES__
111# endif
112#endif
113
114#ifndef __USE_FIXED_PROTOTYPES__
115/*
116 * This is historic and works only if the compiler really has no prototypes:
117 *
118 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
119 * FILE is defined on OS 4.x, not on 5.x (Solaris).
120 * if __SVR4 is defined (some Solaris versions), don't include this.
121 */
122#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
123# define __P(a) a
124/* excerpt from my sun_stdlib.h */
125extern int fprintf __P((FILE *, char *, ...));
126extern int fputs __P((char *, FILE *));
127extern int _flsbuf __P((unsigned char, FILE *));
128extern int _filbuf __P((FILE *));
129extern int fflush __P((FILE *));
130extern int fclose __P((FILE *));
131extern int fseek __P((FILE *, long, int));
132extern int rewind __P((FILE *));
133
134extern void perror __P((char *));
135# endif
136#endif
137
K.Takata233f9562023-09-04 07:46:59 +0200138char version[] = "xxd 2023-09-04 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139#ifdef WIN32
140char osver[] = " (Win32)";
141#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143#endif
144
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200145#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146# define BIN_READ(yes) ((yes) ? "rb" : "rt")
147# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
148# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
149# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000150# define PATH_SEP '\\'
151#elif defined(CYGWIN)
152# define BIN_READ(yes) ((yes) ? "rb" : "rt")
153# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
154# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
155# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
156# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157#else
158# ifdef VMS
159# define BIN_READ(dummy) "r"
160# define BIN_WRITE(dummy) "w"
161# define BIN_CREAT(dummy) O_CREAT
162# define BIN_ASSIGN(fp, dummy) fp
163# define PATH_SEP ']'
164# define FILE_SEP '.'
165# else
166# define BIN_READ(dummy) "r"
167# define BIN_WRITE(dummy) "w"
168# define BIN_CREAT(dummy) O_CREAT
169# define BIN_ASSIGN(fp, dummy) fp
170# define PATH_SEP '/'
171# endif
172#endif
173
174/* open has only to arguments on the Mac */
175#if __MWERKS__
176# define OPEN(name, mode, umask) open(name, mode)
177#else
178# define OPEN(name, mode, umask) open(name, mode, umask)
179#endif
180
181#ifdef AMIGA
182# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
183#else
184# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
185#endif
186
187#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200188# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000189# define __P(a) a
190# else
191# define __P(a) ()
192# endif
193#endif
194
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
196#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100197#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198
199char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
200
201/* the different hextypes known by this program: */
202#define HEX_NORMAL 0
203#define HEX_POSTSCRIPT 1
204#define HEX_CINCLUDE 2
205#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100206#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200208#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
209
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200210#define COLOR_PROLOGUE \
211l[c++] = '\033'; \
212l[c++] = '['; \
213l[c++] = '1'; \
214l[c++] = ';'; \
215l[c++] = '3';
216
217#define COLOR_EPILOGUE \
218l[c++] = '\033'; \
219l[c++] = '['; \
220l[c++] = '0'; \
221l[c++] = 'm';
222#define COLOR_RED '1'
223#define COLOR_GREEN '2'
224#define COLOR_YELLOW '3'
225#define COLOR_BLUE '4'
226#define COLOR_WHITE '7'
227
Bram Moolenaare0659a62011-04-01 19:14:40 +0200228static char *pname;
229
230 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100231exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232{
233 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
234 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
235 fprintf(stderr, "Options:\n");
236 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100237 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200238 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
240 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100241 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100242 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000243 fprintf(stderr, " -h print this summary.\n");
244 fprintf(stderr, " -i output in C include file style.\n");
245 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100246 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100247 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
249 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
250 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200251 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000252 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
253#ifdef TRY_SEEK
254 "[+][-]", "(or +: rel.) ");
255#else
256 "", "");
257#endif
258 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200259 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000260 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
261 exit(1);
262}
263
Bram Moolenaare0659a62011-04-01 19:14:40 +0200264 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100265perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200266{
267 fprintf(stderr, "%s: ", pname);
268 perror(NULL);
269 exit(ret);
270}
271
DungSagaa2ffb432021-10-22 15:55:31 +0100272 static void
273error_exit(int ret, char *msg)
274{
275 fprintf(stderr, "%s: %s\n", pname, msg);
276 exit(ret);
277}
278
DungSagad1d8a592021-11-26 13:59:27 +0000279 static int
280getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000281{
DungSagad1d8a592021-11-26 13:59:27 +0000282 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000283 if (c == EOF && ferror(fpi))
284 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000285 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000286}
287
288 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000289putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000290{
291 if (putc(c, fpo) == EOF)
292 perror_exit(3);
293}
294
295 static void
296fputs_or_die(char *s, FILE *fpo)
297{
298 if (fputs(s, fpo) == EOF)
299 perror_exit(3);
300}
301
DungSaga7e5503c2021-12-01 11:24:52 +0000302/* Use a macro to allow for different arguments. */
303#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000304
305 static void
306fclose_or_die(FILE *fpi, FILE *fpo)
307{
308 if (fclose(fpo) != 0)
309 perror_exit(3);
310 if (fclose(fpi) != 0)
311 perror_exit(2);
312}
313
Bram Moolenaar071d4272004-06-13 20:20:40 +0000314/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000315 * If "c" is a hex digit, return the value.
316 * Otherwise return -1.
317 */
318 static int
319parse_hex_digit(int c)
320{
321 return (c >= '0' && c <= '9') ? c - '0'
322 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
323 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
324 : -1;
325}
326
327/*
328 * Ignore text on "fpi" until end-of-line or end-of-file.
329 * Return the '\n' or EOF character.
330 * When an error is encountered exit with an error message.
331 */
332 static int
333skip_to_eol(FILE *fpi, int c)
334{
335 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000336 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000337 return c;
338}
339
340/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000341 * Max. cols binary characters are decoded from the input stream per line.
342 * Two adjacent garbage characters after evaluated data delimit valid data.
343 * Everything up to the next newline is discarded.
344 *
345 * The name is historic and came from 'undo type opt h'.
346 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200347 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100348huntype(
349 FILE *fpi,
350 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100351 int cols,
352 int hextype,
353 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000354{
355 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
356 long have_off = 0, want_off = 0;
357
358 rewind(fpi);
359
360 while ((c = getc(fpi)) != EOF)
361 {
362 if (c == '\r') /* Doze style input file? */
363 continue;
364
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100365 /* Allow multiple spaces. This doesn't work when there is normal text
366 * after the hex codes in the last line that looks like hex, thus only
367 * use it for PostScript format. */
368 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000369 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000370
Bram Moolenaar071d4272004-06-13 20:20:40 +0000371 n3 = n2;
372 n2 = n1;
373
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000374 n1 = parse_hex_digit(c);
375 if (n1 == -1 && ign_garb)
376 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377
378 ign_garb = 0;
379
DungSaga375c35a2021-10-18 13:16:03 +0100380 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 {
DungSaga375c35a2021-10-18 13:16:03 +0100382 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 {
DungSaga375c35a2021-10-18 13:16:03 +0100384 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000385 continue;
386 }
DungSaga375c35a2021-10-18 13:16:03 +0100387 want_off = (want_off << 4) | n1;
388 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389 }
390
391 if (base_off + want_off != have_off)
392 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200393 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100394 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000396 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000397 have_off = base_off + want_off;
398#endif
399 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000400 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000401 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000402 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000403 }
404
405 if (n2 >= 0 && n1 >= 0)
406 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000407 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000408 have_off++;
409 want_off++;
410 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100411 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000412 /* skip the rest of the line as garbage */
413 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000415 else if (n1 < 0 && n2 < 0 && n3 < 0)
416 /* already stumbled into garbage, skip line, wait and see */
417 c = skip_to_eol(fpi, c);
418
DungSaga47810462021-10-22 12:55:42 +0100419 if (c == '\n')
420 {
421 if (!hextype)
422 want_off = 0;
423 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000424 ign_garb = 1;
425 }
426 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200427 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100428 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000429#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000430 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000432 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433 return 0;
434}
435
436/*
437 * Print line l. If nz is false, xxdline regards the line a line of
438 * zeroes. If there are three or more consecutive lines of zeroes,
439 * they are replaced by a single '*' character.
440 *
441 * If the output ends with more than two lines of zeroes, you
442 * should call xxdline again with l being the last line and nz
443 * negative. This ensures that the last line is shown even when
444 * it is all zeroes.
445 *
446 * If nz is always positive, lines are never suppressed.
447 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200448 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100449xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450{
451 static char z[LLEN+1];
452 static int zero_seen = 0;
453
454 if (!nz && zero_seen == 1)
455 strcpy(z, l);
456
457 if (nz || !zero_seen++)
458 {
459 if (nz)
460 {
461 if (nz < 0)
462 zero_seen--;
463 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000464 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000465 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000466 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000467 }
468 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000469 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000470 if (nz)
471 zero_seen = 0;
472 }
473}
474
475/* This is an EBCDIC to ASCII conversion table */
476/* from a proposed BTL standard April 16, 1979 */
477static unsigned char etoa64[] =
478{
479 0040,0240,0241,0242,0243,0244,0245,0246,
480 0247,0250,0325,0056,0074,0050,0053,0174,
481 0046,0251,0252,0253,0254,0255,0256,0257,
482 0260,0261,0041,0044,0052,0051,0073,0176,
483 0055,0057,0262,0263,0264,0265,0266,0267,
484 0270,0271,0313,0054,0045,0137,0076,0077,
485 0272,0273,0274,0275,0276,0277,0300,0301,
486 0302,0140,0072,0043,0100,0047,0075,0042,
487 0303,0141,0142,0143,0144,0145,0146,0147,
488 0150,0151,0304,0305,0306,0307,0310,0311,
489 0312,0152,0153,0154,0155,0156,0157,0160,
490 0161,0162,0136,0314,0315,0316,0317,0320,
491 0321,0345,0163,0164,0165,0166,0167,0170,
492 0171,0172,0322,0323,0324,0133,0326,0327,
493 0330,0331,0332,0333,0334,0335,0336,0337,
494 0340,0341,0342,0343,0344,0135,0346,0347,
495 0173,0101,0102,0103,0104,0105,0106,0107,
496 0110,0111,0350,0351,0352,0353,0354,0355,
497 0175,0112,0113,0114,0115,0116,0117,0120,
498 0121,0122,0356,0357,0360,0361,0362,0363,
499 0134,0237,0123,0124,0125,0126,0127,0130,
500 0131,0132,0364,0365,0366,0367,0370,0371,
501 0060,0061,0062,0063,0064,0065,0066,0067,
502 0070,0071,0372,0373,0374,0375,0376,0377
503};
504
K.Takataf6fc2552023-09-01 18:41:04 +0200505 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200506begin_coloring_char (char *l, int *c, int e, int ebcdic)
507{
508 if (ebcdic)
509 {
510 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
511 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
512 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
513 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
514 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
515 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
516 (e == 173) || (e == 224) )
517 l[(*c)++] = COLOR_GREEN;
518
519 else if (e == 37 || e == 13 || e == 5)
520 l[(*c)++] = COLOR_YELLOW;
521 else if (e == 0)
522 l[(*c)++] = COLOR_WHITE;
523 else if (e == 255)
524 l[(*c)++] = COLOR_BLUE;
525 else
526 l[(*c)++] = COLOR_RED;
527 }
528 else /* ASCII */
529 {
530 #ifdef __MVS__
531 if (e >= 64)
532 l[(*c)++] = COLOR_GREEN;
533 #else
534 if (e > 31 && e < 127)
535 l[(*c)++] = COLOR_GREEN;
536 #endif
537
538 else if (e == 9 || e == 10 || e == 13)
539 l[(*c)++] = COLOR_YELLOW;
540 else if (e == 0)
541 l[(*c)++] = COLOR_WHITE;
542 else if (e == 255)
543 l[(*c)++] = COLOR_BLUE;
544 else
545 l[(*c)++] = COLOR_RED;
546 }
547 l[(*c)++] = 'm';
548}
549
K.Takataf6fc2552023-09-01 18:41:04 +0200550 static int
551enable_color(void)
552{
553#ifdef WIN32
554 DWORD mode;
555 HANDLE out;
556
557 if (!isatty(1))
558 return 0;
559
560 out = GetStdHandle(STD_OUTPUT_HANDLE);
561 GetConsoleMode(out, &mode);
562 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
563 return (int)SetConsoleMode(out, mode);
564#elif defined(UNIX)
565 return isatty(STDOUT_FILENO);
566#else
567 return 0;
568#endif
569}
570
Bram Moolenaare0659a62011-04-01 19:14:40 +0200571 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100572main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000573{
574 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200575 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000576 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200577 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000578 int ebcdic = 0;
579 int octspergrp = -1; /* number of octets grouped in output */
580 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100581 long length = -1, n = 0, seekoff = 0;
582 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200583 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200584 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100585 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100586 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200587 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200588 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200589
K.Takataf6fc2552023-09-01 18:41:04 +0200590 no_color = getenv("NO_COLOR");
591 if (no_color == NULL || no_color[0] == '\0')
592 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000593
594#ifdef AMIGA
595 /* This program doesn't work when started from the Workbench */
596 if (argc == 0)
597 exit(1);
598#endif
599
600 pname = argv[0];
601 for (pp = pname; *pp; )
602 if (*pp++ == PATH_SEP)
603 pname = pp;
604#ifdef FILE_SEP
605 for (pp = pname; *pp; pp++)
606 if (*pp == FILE_SEP)
607 {
608 *pp = '\0';
609 break;
610 }
611#endif
612
613 while (argc >= 2)
614 {
615 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
616 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
617 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100618 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000619 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
620 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
621 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200622 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200623 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624 else if (!STRNCMP(pp, "-r", 2)) revert++;
625 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
626 else if (!STRNCMP(pp, "-v", 2))
627 {
628 fprintf(stderr, "%s%s\n", version, osver);
629 exit(0);
630 }
631 else if (!STRNCMP(pp, "-c", 2))
632 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100633 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200634 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100635 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000636 {
637 colsgiven = 1;
638 cols = (int)strtol(pp + 2, NULL, 0);
639 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640 else
641 {
642 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200643 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000644 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000645 cols = (int)strtol(argv[2], NULL, 0);
646 argv++;
647 argc--;
648 }
649 }
650 else if (!STRNCMP(pp, "-g", 2))
651 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100652 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000653 octspergrp = (int)strtol(pp + 2, NULL, 0);
654 else
655 {
656 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200657 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000658 octspergrp = (int)strtol(argv[2], NULL, 0);
659 argv++;
660 argc--;
661 }
662 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100663 else if (!STRNCMP(pp, "-o", 2))
664 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100665 int reloffset = 0;
666 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100667 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100668 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100669 else
670 {
671 if (!argv[2])
672 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100673
674 if (argv[2][0] == '+')
675 reloffset++;
676 if (argv[2][reloffset] == '-')
677 negoffset++;
678
679 if (negoffset)
680 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
681 else
682 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
683
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100684 argv++;
685 argc--;
686 }
687 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688 else if (!STRNCMP(pp, "-s", 2))
689 {
690 relseek = 0;
691 negseek = 0;
692 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
693 {
694#ifdef TRY_SEEK
695 if (pp[2] == '+')
696 relseek++;
697 if (pp[2+relseek] == '-')
698 negseek++;
699#endif
700 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
701 }
702 else
703 {
704 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200705 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706#ifdef TRY_SEEK
707 if (argv[2][0] == '+')
708 relseek++;
709 if (argv[2][relseek] == '-')
710 negseek++;
711#endif
712 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
713 argv++;
714 argc--;
715 }
716 }
717 else if (!STRNCMP(pp, "-l", 2))
718 {
719 if (pp[2] && STRNCMP("en", pp + 2, 2))
720 length = strtol(pp + 2, (char **)NULL, 0);
721 else
722 {
723 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200724 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725 length = strtol(argv[2], (char **)NULL, 0);
726 argv++;
727 argc--;
728 }
729 }
David Gow83e11802022-06-29 20:24:49 +0100730 else if (!STRNCMP(pp, "-n", 2))
731 {
732 if (pp[2] && STRNCMP("ame", pp + 2, 3))
733 varname = pp + 2;
734 else
735 {
736 if (!argv[2])
737 exit_with_usage();
738 varname = argv[2];
739 argv++;
740 argc--;
741 }
742 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200743 else if (!STRNCMP(pp, "-R", 2))
744 {
K.Takataf6fc2552023-09-01 18:41:04 +0200745 char *pw = pp + 2;
746 if (!pw[0])
747 {
748 pw = argv[2];
749 argv++;
750 argc--;
751 }
752 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200753 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200754 if (!STRNCMP(pw, "always", 6))
755 {
756 (void)enable_color();
757 color = 1;
758 }
759 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200760 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200761 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200762 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200763 else
764 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200765 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766 else if (!strcmp(pp, "--")) /* end of options */
767 {
768 argv++;
769 argc--;
770 break;
771 }
772 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200773 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 else
775 break; /* not an option */
776
777 argv++; /* advance to next argument */
778 argc--;
779 }
780
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000781 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 switch (hextype)
783 {
784 case HEX_POSTSCRIPT: cols = 30; break;
785 case HEX_CINCLUDE: cols = 12; break;
786 case HEX_BITS: cols = 6; break;
787 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100788 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 default: cols = 16; break;
790 }
791
792 if (octspergrp < 0)
793 switch (hextype)
794 {
795 case HEX_BITS: octspergrp = 1; break;
796 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100797 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798 case HEX_POSTSCRIPT:
799 case HEX_CINCLUDE:
800 default: octspergrp = 0; break;
801 }
802
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000803 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
804 (hextype != HEX_POSTSCRIPT && cols < 1) ||
805 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000806 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807 {
808 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
809 exit(1);
810 }
811
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100812 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100814 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100815 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816
817 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200818 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819
820 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
821 BIN_ASSIGN(fp = stdin, !revert);
822 else
823 {
824 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
825 {
826 fprintf(stderr,"%s: ", pname);
827 perror(argv[1]);
828 return 2;
829 }
830 }
831
832 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
833 BIN_ASSIGN(fpo = stdout, revert);
834 else
835 {
836 int fd;
837 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
838
839 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
840 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
841 {
842 fprintf(stderr, "%s: ", pname);
843 perror(argv[2]);
844 return 3;
845 }
846 rewind(fpo);
847 }
848
849 if (revert)
850 {
851 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000852 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100853 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 negseek ? -seekoff : seekoff);
855 }
856
857 if (seekoff || negseek || !relseek)
858 {
859#ifdef TRY_SEEK
860 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000861 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000863 e = fseek(fp, negseek ? -seekoff : seekoff,
864 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000866 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 if (e >= 0)
868 seekoff = ftell(fp);
869 else
870#endif
871 {
872 long s = seekoff;
873
874 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000875 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200876 {
DungSaga7e5503c2021-12-01 11:24:52 +0000877 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200878 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879 }
880 }
881
882 if (hextype == HEX_CINCLUDE)
883 {
David Gow83e11802022-06-29 20:24:49 +0100884 /* A user-set variable name overrides fp == stdin */
885 if (varname == NULL && fp != stdin)
886 varname = argv[1];
887
888 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 {
David Gow83e11802022-06-29 20:24:49 +0100890 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
891 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000892 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
893 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 }
895
896 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000897 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 {
DungSaga7e5503c2021-12-01 11:24:52 +0000899 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
900 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901 p++;
902 }
903
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000904 if (p)
905 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906
David Gow83e11802022-06-29 20:24:49 +0100907 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908 {
DungSagad1d8a592021-11-26 13:59:27 +0000909 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100910 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
911 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000912 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000913 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914 }
915
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000916 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917 return 0;
918 }
919
920 if (hextype == HEX_POSTSCRIPT)
921 {
922 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000923 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000925 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
926 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000928 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000930 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931 p = cols;
932 }
933 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000934 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000935 putc_or_die('\n', fpo);
936 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 return 0;
938 }
939
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100940 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100942 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200943 {
944 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
945 if (color)
946 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
947 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000948 else /* hextype == HEX_BITS */
949 grplen = 8 * octspergrp + 1;
950
DungSagad1d8a592021-11-26 13:59:27 +0000951 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000952 {
953 if (p == 0)
954 {
DungSaga581f41a2021-11-22 11:57:31 +0000955 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200956 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +0000957 for (c = addrlen; c < LLEN; l[c++] = ' ')
958 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 }
DungSaga48608b42021-11-24 11:18:07 +0000960 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
961 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000962 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200964 if (color)
965 {
966 COLOR_PROLOGUE
967 begin_coloring_char(l,&c,e,ebcdic);
968 l[c++] = hexx[(e >> 4) & 0xf];
969 l[c++] = hexx[e & 0xf];
970 COLOR_EPILOGUE
971 }
972 else /*No colors*/
973 {
974 l[c] = hexx[(e >> 4) & 0xf];
975 l[++c] = hexx[e & 0xf];
976 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 }
978 else /* hextype == HEX_BITS */
979 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000981 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100983 if (e)
984 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000985 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +0000986 if (hextype == HEX_LITTLEENDIAN)
987 /* last group will be fully used, round up */
988 c = grplen * ((cols + octspergrp - 1) / octspergrp);
989 else
990 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200991
992 if (color)
993 {
994 if (hextype == HEX_BITS)
995 c += addrlen + 3 + p*12;
996 else
997 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
998
999 if (hextype == HEX_LITTLEENDIAN)
1000 c += 1;
1001
1002 COLOR_PROLOGUE
1003 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001005 if (e >= 64)
1006 l[c++] = e;
1007 else
1008 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001010 if (ebcdic)
1011 e = (e < 64) ? '.' : etoa64[e-64];
1012 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001014 COLOR_EPILOGUE
1015 n++;
1016 if (++p == cols)
1017 {
1018 l[c++] = '\n';
1019 l[c++] = '\0';
1020 xxdline(fpo, l, autoskip ? nonzero : 1);
1021 nonzero = 0;
1022 p = 0;
1023 }
1024 }
1025 else /*no colors*/
1026 {
1027 if (ebcdic)
1028 e = (e < 64) ? '.' : etoa64[e-64];
1029
1030 c += addrlen + 3 + p;
1031 l[c++] =
1032#ifdef __MVS__
1033 (e >= 64)
1034#else
1035 (e > 31 && e < 127)
1036#endif
1037 ? e : '.';
1038 n++;
1039 if (++p == cols)
1040 {
1041 l[c++] = '\n';
1042 l[c] = '\0';
1043 xxdline(fpo, l, autoskip ? nonzero : 1);
1044 nonzero = 0;
1045 p = 0;
1046 }
1047 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 }
1049 if (p)
1050 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001051 l[c++] = '\n';
1052 l[c] = '\0';
1053 if (color)
1054 {
1055 c++;
1056
1057 x = p;
1058 if (hextype == HEX_LITTLEENDIAN)
1059 {
1060 int fill = octspergrp - (p % octspergrp);
1061 if (fill == octspergrp) fill = 0;
1062
1063 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1064
1065 for (i = 0; i < fill;i++)
1066 {
1067 COLOR_PROLOGUE
1068 l[c++] = COLOR_RED;
1069 l[c++] = 'm';
1070 l[c++] = ' '; /* empty space */
1071 COLOR_EPILOGUE
1072 x++;
1073 p++;
1074 }
1075 }
1076
1077 if (hextype != HEX_BITS)
1078 {
1079 c = addrlen + 1 + (grplen * x) / octspergrp;
1080 c += cols - p;
1081 c += (cols - p) / octspergrp;
1082
1083 for (i = cols - p; i > 0;i--)
1084 {
1085 COLOR_PROLOGUE
1086 l[c++] = COLOR_RED;
1087 l[c++] = 'm';
1088 l[c++] = ' '; /* empty space */
1089 COLOR_EPILOGUE
1090 }
1091 }
1092 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093 xxdline(fpo, l, 1);
1094 }
1095 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001096 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001098 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 return 0;
1100}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001101
1102/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */