blob: a3827a4b8ede4a4c50412c60deede4b533ae7ee7 [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
Bram Moolenaar071d4272004-06-13 20:20:40 +000059 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020060 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000061 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020062 * I hereby grant permission to distribute and use xxd
63 * under X11-MIT or GPL-2.0 (at the user's choice).
64 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020065 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000066 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000067
68/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
69#if _MSC_VER >= 1400
70# define _CRT_SECURE_NO_DEPRECATE
71# define _CRT_NONSTDC_NO_DEPRECATE
72#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010073#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000074# define CYGWIN
75#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000076
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000077#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
78# define _XOPEN_SOURCE 700 /* for fdopen() */
79#endif
80
Bram Moolenaar071d4272004-06-13 20:20:40 +000081#include <stdio.h>
82#ifdef VAXC
83# include <file.h>
84#else
85# include <fcntl.h>
86#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020087#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000088# include <io.h> /* for setmode() */
89#else
90# ifdef UNIX
91# include <unistd.h>
92# endif
93#endif
94#include <stdlib.h>
95#include <string.h> /* for strncmp() */
96#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010097#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000098#if __MWERKS__ && !defined(BEBOX)
99# include <unix.h> /* for fdopen() on MAC */
100#endif
101
Bram Moolenaar071d4272004-06-13 20:20:40 +0000102
103/* This corrects the problem of missing prototypes for certain functions
104 * in some GNU installations (e.g. SunOS 4.1.x).
105 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
106 */
107#if defined(__GNUC__) && defined(__STDC__)
108# ifndef __USE_FIXED_PROTOTYPES__
109# define __USE_FIXED_PROTOTYPES__
110# endif
111#endif
112
113#ifndef __USE_FIXED_PROTOTYPES__
114/*
115 * This is historic and works only if the compiler really has no prototypes:
116 *
117 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
118 * FILE is defined on OS 4.x, not on 5.x (Solaris).
119 * if __SVR4 is defined (some Solaris versions), don't include this.
120 */
121#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
122# define __P(a) a
123/* excerpt from my sun_stdlib.h */
124extern int fprintf __P((FILE *, char *, ...));
125extern int fputs __P((char *, FILE *));
126extern int _flsbuf __P((unsigned char, FILE *));
127extern int _filbuf __P((FILE *));
128extern int fflush __P((FILE *));
129extern int fclose __P((FILE *));
130extern int fseek __P((FILE *, long, int));
131extern int rewind __P((FILE *));
132
133extern void perror __P((char *));
134# endif
135#endif
136
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000137char version[] = "xxd 2022-01-14 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138#ifdef WIN32
139char osver[] = " (Win32)";
140#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000141char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142#endif
143
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200144#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145# define BIN_READ(yes) ((yes) ? "rb" : "rt")
146# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
147# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
148# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000149# define PATH_SEP '\\'
150#elif defined(CYGWIN)
151# define BIN_READ(yes) ((yes) ? "rb" : "rt")
152# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
153# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
154# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
155# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156#else
157# ifdef VMS
158# define BIN_READ(dummy) "r"
159# define BIN_WRITE(dummy) "w"
160# define BIN_CREAT(dummy) O_CREAT
161# define BIN_ASSIGN(fp, dummy) fp
162# define PATH_SEP ']'
163# define FILE_SEP '.'
164# else
165# define BIN_READ(dummy) "r"
166# define BIN_WRITE(dummy) "w"
167# define BIN_CREAT(dummy) O_CREAT
168# define BIN_ASSIGN(fp, dummy) fp
169# define PATH_SEP '/'
170# endif
171#endif
172
173/* open has only to arguments on the Mac */
174#if __MWERKS__
175# define OPEN(name, mode, umask) open(name, mode)
176#else
177# define OPEN(name, mode, umask) open(name, mode, umask)
178#endif
179
180#ifdef AMIGA
181# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
182#else
183# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
184#endif
185
186#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200187# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000188# define __P(a) a
189# else
190# define __P(a) ()
191# endif
192#endif
193
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
195#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100196#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197
198char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
199
200/* the different hextypes known by this program: */
201#define HEX_NORMAL 0
202#define HEX_POSTSCRIPT 1
203#define HEX_CINCLUDE 2
204#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100205#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200207#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
208
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200209#define COLOR_PROLOGUE \
210l[c++] = '\033'; \
211l[c++] = '['; \
212l[c++] = '1'; \
213l[c++] = ';'; \
214l[c++] = '3';
215
216#define COLOR_EPILOGUE \
217l[c++] = '\033'; \
218l[c++] = '['; \
219l[c++] = '0'; \
220l[c++] = 'm';
221#define COLOR_RED '1'
222#define COLOR_GREEN '2'
223#define COLOR_YELLOW '3'
224#define COLOR_BLUE '4'
225#define COLOR_WHITE '7'
226
Bram Moolenaare0659a62011-04-01 19:14:40 +0200227static char *pname;
228
229 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100230exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000231{
232 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
233 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
234 fprintf(stderr, "Options:\n");
235 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100236 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200237 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
239 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100240 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100241 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 fprintf(stderr, " -h print this summary.\n");
243 fprintf(stderr, " -i output in C include file style.\n");
244 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100245 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100246 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
248 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
249 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200250 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
252#ifdef TRY_SEEK
253 "[+][-]", "(or +: rel.) ");
254#else
255 "", "");
256#endif
257 fprintf(stderr, " -u use upper case hex letters.\n");
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200258 fprintf(stderr, " -R [WHEN] colorize the output; WHEN can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000259 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
260 exit(1);
261}
262
Bram Moolenaare0659a62011-04-01 19:14:40 +0200263 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100264perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200265{
266 fprintf(stderr, "%s: ", pname);
267 perror(NULL);
268 exit(ret);
269}
270
DungSagaa2ffb432021-10-22 15:55:31 +0100271 static void
272error_exit(int ret, char *msg)
273{
274 fprintf(stderr, "%s: %s\n", pname, msg);
275 exit(ret);
276}
277
DungSagad1d8a592021-11-26 13:59:27 +0000278 static int
279getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000280{
DungSagad1d8a592021-11-26 13:59:27 +0000281 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000282 if (c == EOF && ferror(fpi))
283 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000284 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000285}
286
287 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000288putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000289{
290 if (putc(c, fpo) == EOF)
291 perror_exit(3);
292}
293
294 static void
295fputs_or_die(char *s, FILE *fpo)
296{
297 if (fputs(s, fpo) == EOF)
298 perror_exit(3);
299}
300
DungSaga7e5503c2021-12-01 11:24:52 +0000301/* Use a macro to allow for different arguments. */
302#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000303
304 static void
305fclose_or_die(FILE *fpi, FILE *fpo)
306{
307 if (fclose(fpo) != 0)
308 perror_exit(3);
309 if (fclose(fpi) != 0)
310 perror_exit(2);
311}
312
Bram Moolenaar071d4272004-06-13 20:20:40 +0000313/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000314 * If "c" is a hex digit, return the value.
315 * Otherwise return -1.
316 */
317 static int
318parse_hex_digit(int c)
319{
320 return (c >= '0' && c <= '9') ? c - '0'
321 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
322 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
323 : -1;
324}
325
326/*
327 * Ignore text on "fpi" until end-of-line or end-of-file.
328 * Return the '\n' or EOF character.
329 * When an error is encountered exit with an error message.
330 */
331 static int
332skip_to_eol(FILE *fpi, int c)
333{
334 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000335 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000336 return c;
337}
338
339/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000340 * Max. cols binary characters are decoded from the input stream per line.
341 * Two adjacent garbage characters after evaluated data delimit valid data.
342 * Everything up to the next newline is discarded.
343 *
344 * The name is historic and came from 'undo type opt h'.
345 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200346 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100347huntype(
348 FILE *fpi,
349 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100350 int cols,
351 int hextype,
352 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000353{
354 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
355 long have_off = 0, want_off = 0;
356
357 rewind(fpi);
358
359 while ((c = getc(fpi)) != EOF)
360 {
361 if (c == '\r') /* Doze style input file? */
362 continue;
363
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100364 /* Allow multiple spaces. This doesn't work when there is normal text
365 * after the hex codes in the last line that looks like hex, thus only
366 * use it for PostScript format. */
367 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000368 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000369
Bram Moolenaar071d4272004-06-13 20:20:40 +0000370 n3 = n2;
371 n2 = n1;
372
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000373 n1 = parse_hex_digit(c);
374 if (n1 == -1 && ign_garb)
375 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000376
377 ign_garb = 0;
378
DungSaga375c35a2021-10-18 13:16:03 +0100379 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000380 {
DungSaga375c35a2021-10-18 13:16:03 +0100381 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000382 {
DungSaga375c35a2021-10-18 13:16:03 +0100383 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000384 continue;
385 }
DungSaga375c35a2021-10-18 13:16:03 +0100386 want_off = (want_off << 4) | n1;
387 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 }
389
390 if (base_off + want_off != have_off)
391 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200392 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100393 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000395 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000396 have_off = base_off + want_off;
397#endif
398 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000399 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000400 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000401 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000402 }
403
404 if (n2 >= 0 && n1 >= 0)
405 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000406 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000407 have_off++;
408 want_off++;
409 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100410 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000411 /* skip the rest of the line as garbage */
412 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000414 else if (n1 < 0 && n2 < 0 && n3 < 0)
415 /* already stumbled into garbage, skip line, wait and see */
416 c = skip_to_eol(fpi, c);
417
DungSaga47810462021-10-22 12:55:42 +0100418 if (c == '\n')
419 {
420 if (!hextype)
421 want_off = 0;
422 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000423 ign_garb = 1;
424 }
425 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200426 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100427 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000429 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000431 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000432 return 0;
433}
434
435/*
436 * Print line l. If nz is false, xxdline regards the line a line of
437 * zeroes. If there are three or more consecutive lines of zeroes,
438 * they are replaced by a single '*' character.
439 *
440 * If the output ends with more than two lines of zeroes, you
441 * should call xxdline again with l being the last line and nz
442 * negative. This ensures that the last line is shown even when
443 * it is all zeroes.
444 *
445 * If nz is always positive, lines are never suppressed.
446 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200447 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100448xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000449{
450 static char z[LLEN+1];
451 static int zero_seen = 0;
452
453 if (!nz && zero_seen == 1)
454 strcpy(z, l);
455
456 if (nz || !zero_seen++)
457 {
458 if (nz)
459 {
460 if (nz < 0)
461 zero_seen--;
462 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000463 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000464 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000465 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000466 }
467 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000468 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000469 if (nz)
470 zero_seen = 0;
471 }
472}
473
474/* This is an EBCDIC to ASCII conversion table */
475/* from a proposed BTL standard April 16, 1979 */
476static unsigned char etoa64[] =
477{
478 0040,0240,0241,0242,0243,0244,0245,0246,
479 0247,0250,0325,0056,0074,0050,0053,0174,
480 0046,0251,0252,0253,0254,0255,0256,0257,
481 0260,0261,0041,0044,0052,0051,0073,0176,
482 0055,0057,0262,0263,0264,0265,0266,0267,
483 0270,0271,0313,0054,0045,0137,0076,0077,
484 0272,0273,0274,0275,0276,0277,0300,0301,
485 0302,0140,0072,0043,0100,0047,0075,0042,
486 0303,0141,0142,0143,0144,0145,0146,0147,
487 0150,0151,0304,0305,0306,0307,0310,0311,
488 0312,0152,0153,0154,0155,0156,0157,0160,
489 0161,0162,0136,0314,0315,0316,0317,0320,
490 0321,0345,0163,0164,0165,0166,0167,0170,
491 0171,0172,0322,0323,0324,0133,0326,0327,
492 0330,0331,0332,0333,0334,0335,0336,0337,
493 0340,0341,0342,0343,0344,0135,0346,0347,
494 0173,0101,0102,0103,0104,0105,0106,0107,
495 0110,0111,0350,0351,0352,0353,0354,0355,
496 0175,0112,0113,0114,0115,0116,0117,0120,
497 0121,0122,0356,0357,0360,0361,0362,0363,
498 0134,0237,0123,0124,0125,0126,0127,0130,
499 0131,0132,0364,0365,0366,0367,0370,0371,
500 0060,0061,0062,0063,0064,0065,0066,0067,
501 0070,0071,0372,0373,0374,0375,0376,0377
502};
503
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200504 static void
505begin_coloring_char (char *l, int *c, int e, int ebcdic)
506{
507 if (ebcdic)
508 {
509 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
510 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
511 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
512 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
513 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
514 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
515 (e == 173) || (e == 224) )
516 l[(*c)++] = COLOR_GREEN;
517
518 else if (e == 37 || e == 13 || e == 5)
519 l[(*c)++] = COLOR_YELLOW;
520 else if (e == 0)
521 l[(*c)++] = COLOR_WHITE;
522 else if (e == 255)
523 l[(*c)++] = COLOR_BLUE;
524 else
525 l[(*c)++] = COLOR_RED;
526 }
527 else /* ASCII */
528 {
529 #ifdef __MVS__
530 if (e >= 64)
531 l[(*c)++] = COLOR_GREEN;
532 #else
533 if (e > 31 && e < 127)
534 l[(*c)++] = COLOR_GREEN;
535 #endif
536
537 else if (e == 9 || e == 10 || e == 13)
538 l[(*c)++] = COLOR_YELLOW;
539 else if (e == 0)
540 l[(*c)++] = COLOR_WHITE;
541 else if (e == 255)
542 l[(*c)++] = COLOR_BLUE;
543 else
544 l[(*c)++] = COLOR_RED;
545 }
546 l[(*c)++] = 'm';
547}
548
Bram Moolenaare0659a62011-04-01 19:14:40 +0200549 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100550main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551{
552 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200553 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000554 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200555 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 int ebcdic = 0;
557 int octspergrp = -1; /* number of octets grouped in output */
558 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100559 long length = -1, n = 0, seekoff = 0;
560 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200561 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200562 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100563 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100564 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200565 int color = 0;
566
567#ifdef UNIX
568 color = isatty(STDOUT_FILENO);
569#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570
571#ifdef AMIGA
572 /* This program doesn't work when started from the Workbench */
573 if (argc == 0)
574 exit(1);
575#endif
576
577 pname = argv[0];
578 for (pp = pname; *pp; )
579 if (*pp++ == PATH_SEP)
580 pname = pp;
581#ifdef FILE_SEP
582 for (pp = pname; *pp; pp++)
583 if (*pp == FILE_SEP)
584 {
585 *pp = '\0';
586 break;
587 }
588#endif
589
590 while (argc >= 2)
591 {
592 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
593 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
594 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100595 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000596 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
597 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
598 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200599 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200600 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000601 else if (!STRNCMP(pp, "-r", 2)) revert++;
602 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
603 else if (!STRNCMP(pp, "-v", 2))
604 {
605 fprintf(stderr, "%s%s\n", version, osver);
606 exit(0);
607 }
608 else if (!STRNCMP(pp, "-c", 2))
609 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100610 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200611 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100612 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000613 {
614 colsgiven = 1;
615 cols = (int)strtol(pp + 2, NULL, 0);
616 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000617 else
618 {
619 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200620 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000621 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622 cols = (int)strtol(argv[2], NULL, 0);
623 argv++;
624 argc--;
625 }
626 }
627 else if (!STRNCMP(pp, "-g", 2))
628 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100629 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000630 octspergrp = (int)strtol(pp + 2, NULL, 0);
631 else
632 {
633 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200634 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000635 octspergrp = (int)strtol(argv[2], NULL, 0);
636 argv++;
637 argc--;
638 }
639 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100640 else if (!STRNCMP(pp, "-o", 2))
641 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100642 int reloffset = 0;
643 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100644 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100645 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100646 else
647 {
648 if (!argv[2])
649 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100650
651 if (argv[2][0] == '+')
652 reloffset++;
653 if (argv[2][reloffset] == '-')
654 negoffset++;
655
656 if (negoffset)
657 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
658 else
659 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
660
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100661 argv++;
662 argc--;
663 }
664 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 else if (!STRNCMP(pp, "-s", 2))
666 {
667 relseek = 0;
668 negseek = 0;
669 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
670 {
671#ifdef TRY_SEEK
672 if (pp[2] == '+')
673 relseek++;
674 if (pp[2+relseek] == '-')
675 negseek++;
676#endif
677 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
678 }
679 else
680 {
681 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200682 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683#ifdef TRY_SEEK
684 if (argv[2][0] == '+')
685 relseek++;
686 if (argv[2][relseek] == '-')
687 negseek++;
688#endif
689 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
690 argv++;
691 argc--;
692 }
693 }
694 else if (!STRNCMP(pp, "-l", 2))
695 {
696 if (pp[2] && STRNCMP("en", pp + 2, 2))
697 length = strtol(pp + 2, (char **)NULL, 0);
698 else
699 {
700 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200701 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 length = strtol(argv[2], (char **)NULL, 0);
703 argv++;
704 argc--;
705 }
706 }
David Gow83e11802022-06-29 20:24:49 +0100707 else if (!STRNCMP(pp, "-n", 2))
708 {
709 if (pp[2] && STRNCMP("ame", pp + 2, 3))
710 varname = pp + 2;
711 else
712 {
713 if (!argv[2])
714 exit_with_usage();
715 varname = argv[2];
716 argv++;
717 argc--;
718 }
719 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200720 else if (!STRNCMP(pp, "-R", 2))
721 {
722 if (!argv[2])
723 exit_with_usage();
724 if (!STRNCMP(argv[2], "always", 2))
725 color = 1;
726 else if (!STRNCMP(argv[2], "never", 1))
727 color = 0;
728 argv++;
729 argc--;
730 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731 else if (!strcmp(pp, "--")) /* end of options */
732 {
733 argv++;
734 argc--;
735 break;
736 }
737 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200738 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 else
740 break; /* not an option */
741
742 argv++; /* advance to next argument */
743 argc--;
744 }
745
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000746 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000747 switch (hextype)
748 {
749 case HEX_POSTSCRIPT: cols = 30; break;
750 case HEX_CINCLUDE: cols = 12; break;
751 case HEX_BITS: cols = 6; break;
752 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100753 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754 default: cols = 16; break;
755 }
756
757 if (octspergrp < 0)
758 switch (hextype)
759 {
760 case HEX_BITS: octspergrp = 1; break;
761 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100762 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000763 case HEX_POSTSCRIPT:
764 case HEX_CINCLUDE:
765 default: octspergrp = 0; break;
766 }
767
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000768 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
769 (hextype != HEX_POSTSCRIPT && cols < 1) ||
770 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000771 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000772 {
773 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
774 exit(1);
775 }
776
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100777 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000778 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100779 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100780 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781
782 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200783 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784
785 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
786 BIN_ASSIGN(fp = stdin, !revert);
787 else
788 {
789 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
790 {
791 fprintf(stderr,"%s: ", pname);
792 perror(argv[1]);
793 return 2;
794 }
795 }
796
797 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
798 BIN_ASSIGN(fpo = stdout, revert);
799 else
800 {
801 int fd;
802 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
803
804 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
805 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
806 {
807 fprintf(stderr, "%s: ", pname);
808 perror(argv[2]);
809 return 3;
810 }
811 rewind(fpo);
812 }
813
814 if (revert)
815 {
816 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000817 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100818 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 negseek ? -seekoff : seekoff);
820 }
821
822 if (seekoff || negseek || !relseek)
823 {
824#ifdef TRY_SEEK
825 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000826 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000828 e = fseek(fp, negseek ? -seekoff : seekoff,
829 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000831 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 if (e >= 0)
833 seekoff = ftell(fp);
834 else
835#endif
836 {
837 long s = seekoff;
838
839 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000840 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200841 {
DungSaga7e5503c2021-12-01 11:24:52 +0000842 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200843 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 }
845 }
846
847 if (hextype == HEX_CINCLUDE)
848 {
David Gow83e11802022-06-29 20:24:49 +0100849 /* A user-set variable name overrides fp == stdin */
850 if (varname == NULL && fp != stdin)
851 varname = argv[1];
852
853 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 {
David Gow83e11802022-06-29 20:24:49 +0100855 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
856 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000857 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
858 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 }
860
861 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000862 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 {
DungSaga7e5503c2021-12-01 11:24:52 +0000864 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
865 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 p++;
867 }
868
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000869 if (p)
870 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871
David Gow83e11802022-06-29 20:24:49 +0100872 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 {
DungSagad1d8a592021-11-26 13:59:27 +0000874 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100875 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
876 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000877 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000878 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879 }
880
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000881 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 return 0;
883 }
884
885 if (hextype == HEX_POSTSCRIPT)
886 {
887 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000888 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000890 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
891 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000893 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000895 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896 p = cols;
897 }
898 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000899 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000900 putc_or_die('\n', fpo);
901 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000902 return 0;
903 }
904
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100905 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100907 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200908 {
909 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
910 if (color)
911 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
912 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 else /* hextype == HEX_BITS */
914 grplen = 8 * octspergrp + 1;
915
DungSagad1d8a592021-11-26 13:59:27 +0000916 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917 {
918 if (p == 0)
919 {
DungSaga581f41a2021-11-22 11:57:31 +0000920 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200921 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +0000922 for (c = addrlen; c < LLEN; l[c++] = ' ')
923 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924 }
DungSaga48608b42021-11-24 11:18:07 +0000925 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
926 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000927 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000928 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200929 if (color)
930 {
931 COLOR_PROLOGUE
932 begin_coloring_char(l,&c,e,ebcdic);
933 l[c++] = hexx[(e >> 4) & 0xf];
934 l[c++] = hexx[e & 0xf];
935 COLOR_EPILOGUE
936 }
937 else /*No colors*/
938 {
939 l[c] = hexx[(e >> 4) & 0xf];
940 l[++c] = hexx[e & 0xf];
941 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 }
943 else /* hextype == HEX_BITS */
944 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000946 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000947 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100948 if (e)
949 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000950 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +0000951 if (hextype == HEX_LITTLEENDIAN)
952 /* last group will be fully used, round up */
953 c = grplen * ((cols + octspergrp - 1) / octspergrp);
954 else
955 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200956
957 if (color)
958 {
959 if (hextype == HEX_BITS)
960 c += addrlen + 3 + p*12;
961 else
962 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
963
964 if (hextype == HEX_LITTLEENDIAN)
965 c += 1;
966
967 COLOR_PROLOGUE
968 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000969#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200970 if (e >= 64)
971 l[c++] = e;
972 else
973 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200975 if (ebcdic)
976 e = (e < 64) ? '.' : etoa64[e-64];
977 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200979 COLOR_EPILOGUE
980 n++;
981 if (++p == cols)
982 {
983 l[c++] = '\n';
984 l[c++] = '\0';
985 xxdline(fpo, l, autoskip ? nonzero : 1);
986 nonzero = 0;
987 p = 0;
988 }
989 }
990 else /*no colors*/
991 {
992 if (ebcdic)
993 e = (e < 64) ? '.' : etoa64[e-64];
994
995 c += addrlen + 3 + p;
996 l[c++] =
997#ifdef __MVS__
998 (e >= 64)
999#else
1000 (e > 31 && e < 127)
1001#endif
1002 ? e : '.';
1003 n++;
1004 if (++p == cols)
1005 {
1006 l[c++] = '\n';
1007 l[c] = '\0';
1008 xxdline(fpo, l, autoskip ? nonzero : 1);
1009 nonzero = 0;
1010 p = 0;
1011 }
1012 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013 }
1014 if (p)
1015 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001016 l[c++] = '\n';
1017 l[c] = '\0';
1018 if (color)
1019 {
1020 c++;
1021
1022 x = p;
1023 if (hextype == HEX_LITTLEENDIAN)
1024 {
1025 int fill = octspergrp - (p % octspergrp);
1026 if (fill == octspergrp) fill = 0;
1027
1028 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1029
1030 for (i = 0; i < fill;i++)
1031 {
1032 COLOR_PROLOGUE
1033 l[c++] = COLOR_RED;
1034 l[c++] = 'm';
1035 l[c++] = ' '; /* empty space */
1036 COLOR_EPILOGUE
1037 x++;
1038 p++;
1039 }
1040 }
1041
1042 if (hextype != HEX_BITS)
1043 {
1044 c = addrlen + 1 + (grplen * x) / octspergrp;
1045 c += cols - p;
1046 c += (cols - p) / octspergrp;
1047
1048 for (i = cols - p; i > 0;i--)
1049 {
1050 COLOR_PROLOGUE
1051 l[c++] = COLOR_RED;
1052 l[c++] = 'm';
1053 l[c++] = ' '; /* empty space */
1054 COLOR_EPILOGUE
1055 }
1056 }
1057 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 xxdline(fpo, l, 1);
1059 }
1060 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001061 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001063 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 return 0;
1065}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001066
1067/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */