blob: 590cd44aaded43c09aac3427fb2184fc39810f61 [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() */
90#else
91# ifdef UNIX
92# include <unistd.h>
93# endif
94#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
Christian Brabandt0ffa97e2023-08-31 21:03:02 +0200138char version[] = "xxd 2023-08-31 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");
Aapo Rantalainene2528ae2023-08-31 17:58:13 +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
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200505 static void
506begin_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
Bram Moolenaare0659a62011-04-01 19:14:40 +0200550 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100551main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000552{
553 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200554 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000555 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200556 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557 int ebcdic = 0;
558 int octspergrp = -1; /* number of octets grouped in output */
559 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100560 long length = -1, n = 0, seekoff = 0;
561 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200562 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200563 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100564 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100565 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200566 int color = 0;
567
568#ifdef UNIX
569 color = isatty(STDOUT_FILENO);
570#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000571
572#ifdef AMIGA
573 /* This program doesn't work when started from the Workbench */
574 if (argc == 0)
575 exit(1);
576#endif
577
578 pname = argv[0];
579 for (pp = pname; *pp; )
580 if (*pp++ == PATH_SEP)
581 pname = pp;
582#ifdef FILE_SEP
583 for (pp = pname; *pp; pp++)
584 if (*pp == FILE_SEP)
585 {
586 *pp = '\0';
587 break;
588 }
589#endif
590
591 while (argc >= 2)
592 {
593 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
594 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
595 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100596 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
598 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
599 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200600 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200601 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000602 else if (!STRNCMP(pp, "-r", 2)) revert++;
603 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
604 else if (!STRNCMP(pp, "-v", 2))
605 {
606 fprintf(stderr, "%s%s\n", version, osver);
607 exit(0);
608 }
609 else if (!STRNCMP(pp, "-c", 2))
610 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100611 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200612 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100613 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000614 {
615 colsgiven = 1;
616 cols = (int)strtol(pp + 2, NULL, 0);
617 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000618 else
619 {
620 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200621 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000622 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000623 cols = (int)strtol(argv[2], NULL, 0);
624 argv++;
625 argc--;
626 }
627 }
628 else if (!STRNCMP(pp, "-g", 2))
629 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100630 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 octspergrp = (int)strtol(pp + 2, NULL, 0);
632 else
633 {
634 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200635 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 octspergrp = (int)strtol(argv[2], NULL, 0);
637 argv++;
638 argc--;
639 }
640 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100641 else if (!STRNCMP(pp, "-o", 2))
642 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100643 int reloffset = 0;
644 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100645 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100646 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100647 else
648 {
649 if (!argv[2])
650 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100651
652 if (argv[2][0] == '+')
653 reloffset++;
654 if (argv[2][reloffset] == '-')
655 negoffset++;
656
657 if (negoffset)
658 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
659 else
660 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
661
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100662 argv++;
663 argc--;
664 }
665 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000666 else if (!STRNCMP(pp, "-s", 2))
667 {
668 relseek = 0;
669 negseek = 0;
670 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
671 {
672#ifdef TRY_SEEK
673 if (pp[2] == '+')
674 relseek++;
675 if (pp[2+relseek] == '-')
676 negseek++;
677#endif
678 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
679 }
680 else
681 {
682 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200683 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684#ifdef TRY_SEEK
685 if (argv[2][0] == '+')
686 relseek++;
687 if (argv[2][relseek] == '-')
688 negseek++;
689#endif
690 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
691 argv++;
692 argc--;
693 }
694 }
695 else if (!STRNCMP(pp, "-l", 2))
696 {
697 if (pp[2] && STRNCMP("en", pp + 2, 2))
698 length = strtol(pp + 2, (char **)NULL, 0);
699 else
700 {
701 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200702 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 length = strtol(argv[2], (char **)NULL, 0);
704 argv++;
705 argc--;
706 }
707 }
David Gow83e11802022-06-29 20:24:49 +0100708 else if (!STRNCMP(pp, "-n", 2))
709 {
710 if (pp[2] && STRNCMP("ame", pp + 2, 3))
711 varname = pp + 2;
712 else
713 {
714 if (!argv[2])
715 exit_with_usage();
716 varname = argv[2];
717 argv++;
718 argc--;
719 }
720 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200721 else if (!STRNCMP(pp, "-R", 2))
722 {
723 if (!argv[2])
724 exit_with_usage();
725 if (!STRNCMP(argv[2], "always", 2))
726 color = 1;
727 else if (!STRNCMP(argv[2], "never", 1))
728 color = 0;
729 argv++;
730 argc--;
731 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 else if (!strcmp(pp, "--")) /* end of options */
733 {
734 argv++;
735 argc--;
736 break;
737 }
738 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200739 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740 else
741 break; /* not an option */
742
743 argv++; /* advance to next argument */
744 argc--;
745 }
746
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000747 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000748 switch (hextype)
749 {
750 case HEX_POSTSCRIPT: cols = 30; break;
751 case HEX_CINCLUDE: cols = 12; break;
752 case HEX_BITS: cols = 6; break;
753 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100754 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755 default: cols = 16; break;
756 }
757
758 if (octspergrp < 0)
759 switch (hextype)
760 {
761 case HEX_BITS: octspergrp = 1; break;
762 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100763 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 case HEX_POSTSCRIPT:
765 case HEX_CINCLUDE:
766 default: octspergrp = 0; break;
767 }
768
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000769 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
770 (hextype != HEX_POSTSCRIPT && cols < 1) ||
771 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000772 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773 {
774 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
775 exit(1);
776 }
777
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100778 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100780 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100781 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782
783 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200784 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785
786 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
787 BIN_ASSIGN(fp = stdin, !revert);
788 else
789 {
790 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
791 {
792 fprintf(stderr,"%s: ", pname);
793 perror(argv[1]);
794 return 2;
795 }
796 }
797
798 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
799 BIN_ASSIGN(fpo = stdout, revert);
800 else
801 {
802 int fd;
803 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
804
805 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
806 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
807 {
808 fprintf(stderr, "%s: ", pname);
809 perror(argv[2]);
810 return 3;
811 }
812 rewind(fpo);
813 }
814
815 if (revert)
816 {
817 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000818 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100819 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 negseek ? -seekoff : seekoff);
821 }
822
823 if (seekoff || negseek || !relseek)
824 {
825#ifdef TRY_SEEK
826 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000827 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000829 e = fseek(fp, negseek ? -seekoff : seekoff,
830 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000832 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833 if (e >= 0)
834 seekoff = ftell(fp);
835 else
836#endif
837 {
838 long s = seekoff;
839
840 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000841 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200842 {
DungSaga7e5503c2021-12-01 11:24:52 +0000843 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200844 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 }
846 }
847
848 if (hextype == HEX_CINCLUDE)
849 {
David Gow83e11802022-06-29 20:24:49 +0100850 /* A user-set variable name overrides fp == stdin */
851 if (varname == NULL && fp != stdin)
852 varname = argv[1];
853
854 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855 {
David Gow83e11802022-06-29 20:24:49 +0100856 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
857 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000858 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
859 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860 }
861
862 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000863 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000864 {
DungSaga7e5503c2021-12-01 11:24:52 +0000865 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
866 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 p++;
868 }
869
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000870 if (p)
871 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872
David Gow83e11802022-06-29 20:24:49 +0100873 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 {
DungSagad1d8a592021-11-26 13:59:27 +0000875 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100876 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
877 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000878 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000879 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880 }
881
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000882 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 return 0;
884 }
885
886 if (hextype == HEX_POSTSCRIPT)
887 {
888 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000889 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000891 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
892 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000894 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000895 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000896 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897 p = cols;
898 }
899 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000900 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000901 putc_or_die('\n', fpo);
902 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 return 0;
904 }
905
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100906 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000907
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100908 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200909 {
910 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
911 if (color)
912 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
913 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914 else /* hextype == HEX_BITS */
915 grplen = 8 * octspergrp + 1;
916
DungSagad1d8a592021-11-26 13:59:27 +0000917 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918 {
919 if (p == 0)
920 {
DungSaga581f41a2021-11-22 11:57:31 +0000921 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200922 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +0000923 for (c = addrlen; c < LLEN; l[c++] = ' ')
924 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000925 }
DungSaga48608b42021-11-24 11:18:07 +0000926 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
927 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000928 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200930 if (color)
931 {
932 COLOR_PROLOGUE
933 begin_coloring_char(l,&c,e,ebcdic);
934 l[c++] = hexx[(e >> 4) & 0xf];
935 l[c++] = hexx[e & 0xf];
936 COLOR_EPILOGUE
937 }
938 else /*No colors*/
939 {
940 l[c] = hexx[(e >> 4) & 0xf];
941 l[++c] = hexx[e & 0xf];
942 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000943 }
944 else /* hextype == HEX_BITS */
945 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000947 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000948 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100949 if (e)
950 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000951 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +0000952 if (hextype == HEX_LITTLEENDIAN)
953 /* last group will be fully used, round up */
954 c = grplen * ((cols + octspergrp - 1) / octspergrp);
955 else
956 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200957
958 if (color)
959 {
960 if (hextype == HEX_BITS)
961 c += addrlen + 3 + p*12;
962 else
963 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
964
965 if (hextype == HEX_LITTLEENDIAN)
966 c += 1;
967
968 COLOR_PROLOGUE
969 begin_coloring_char(l,&c,e,ebcdic);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970#ifdef __MVS__
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200971 if (e >= 64)
972 l[c++] = e;
973 else
974 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200976 if (ebcdic)
977 e = (e < 64) ? '.' : etoa64[e-64];
978 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200980 COLOR_EPILOGUE
981 n++;
982 if (++p == cols)
983 {
984 l[c++] = '\n';
985 l[c++] = '\0';
986 xxdline(fpo, l, autoskip ? nonzero : 1);
987 nonzero = 0;
988 p = 0;
989 }
990 }
991 else /*no colors*/
992 {
993 if (ebcdic)
994 e = (e < 64) ? '.' : etoa64[e-64];
995
996 c += addrlen + 3 + p;
997 l[c++] =
998#ifdef __MVS__
999 (e >= 64)
1000#else
1001 (e > 31 && e < 127)
1002#endif
1003 ? e : '.';
1004 n++;
1005 if (++p == cols)
1006 {
1007 l[c++] = '\n';
1008 l[c] = '\0';
1009 xxdline(fpo, l, autoskip ? nonzero : 1);
1010 nonzero = 0;
1011 p = 0;
1012 }
1013 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001014 }
1015 if (p)
1016 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001017 l[c++] = '\n';
1018 l[c] = '\0';
1019 if (color)
1020 {
1021 c++;
1022
1023 x = p;
1024 if (hextype == HEX_LITTLEENDIAN)
1025 {
1026 int fill = octspergrp - (p % octspergrp);
1027 if (fill == octspergrp) fill = 0;
1028
1029 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1030
1031 for (i = 0; i < fill;i++)
1032 {
1033 COLOR_PROLOGUE
1034 l[c++] = COLOR_RED;
1035 l[c++] = 'm';
1036 l[c++] = ' '; /* empty space */
1037 COLOR_EPILOGUE
1038 x++;
1039 p++;
1040 }
1041 }
1042
1043 if (hextype != HEX_BITS)
1044 {
1045 c = addrlen + 1 + (grplen * x) / octspergrp;
1046 c += cols - p;
1047 c += (cols - p) / octspergrp;
1048
1049 for (i = cols - p; i > 0;i--)
1050 {
1051 COLOR_PROLOGUE
1052 l[c++] = COLOR_RED;
1053 l[c++] = 'm';
1054 l[c++] = ' '; /* empty space */
1055 COLOR_EPILOGUE
1056 }
1057 }
1058 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001059 xxdline(fpo, l, 1);
1060 }
1061 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001062 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001063
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001064 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065 return 0;
1066}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001067
1068/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */