blob: 20023e0ee102ae5e9b47680e4174535565697c80 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* xxd: my hexdump facility. jw
2 *
3 * 2.10.90 changed to word output
4 * 3.03.93 new indent style, dumb bug inserted and fixed.
5 * -c option, mls
6 * 26.04.94 better option parser, -ps, -l, -s added.
7 * 1.07.94 -r badly needs - as input file. Per default autoskip over
Bram Moolenaar82038d72007-05-10 17:15:45 +00008 * consecutive lines of zeroes, as unix od does.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009 * -a shows them too.
10 * -i dump as c-style #include "file.h"
11 * 1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]'
12 * array is written in correct c-syntax.
13 * -s improved, now defaults to absolute seek, relative requires a '+'.
14 * -r improved, now -r -s -0x... is supported.
15 * change/suppress leading '\0' bytes.
16 * -l n improved: stops exactly after n bytes.
17 * -r improved, better handling of partial lines with trailing garbage.
18 * -r improved, now -r -p works again!
19 * -r improved, less flushing, much faster now! (that was silly)
20 * 3.04.96 Per repeated request of a single person: autoskip defaults to off.
21 * 15.05.96 -v added. They want to know the version.
22 * -a fixed, to show last line inf file ends in all zeros.
23 * -u added: Print upper case hex-letters, as preferred by unix bc.
24 * -h added to usage message. Usage message extended.
25 * Now using outfile if specified even in normal mode, aehem.
26 * No longer mixing of ints and longs. May help doze people.
27 * Added binify ioctl for same reason. (Enough Doze stress for 1996!)
28 * 16.05.96 -p improved, removed occasional superfluous linefeed.
29 * 20.05.96 -l 0 fixed. tried to read anyway.
30 * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames.
31 * compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-)
32 * support --gnuish-longhorn-options
33 * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h
34 * which is included by MacHeaders (Axel Kielhorn). Renamed to
35 * xxdline().
36 * 7.06.96 -i printed 'int' instead of 'char'. *blush*
37 * added Bram's OS2 ifdefs...
Bram Moolenaar4b96df52020-01-26 22:00:26 +010038 * 18.07.96 gcc -Wall @ SunOS4 is now silent.
Bram Moolenaar071d4272004-06-13 20:20:40 +000039 * Added osver for MSDOS/DJGPP/WIN32.
40 * 29.08.96 Added size_t to strncmp() for Amiga.
41 * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram)
42 * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII
Bram Moolenaar4317d9b2005-03-18 20:25:31 +000043 * (azc10@yahoo.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000044 * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com).
45 * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was
46 * missing or wrong.
47 * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile.
48 * 27.10.98 Fixed: -g option parser required blank.
49 * option -b added: 01000101 binary output in normal format.
50 * 16.05.00 Added VAXC changes by Stephen P. Wall
Bram Moolenaar82038d72007-05-10 17:15:45 +000051 * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
Bram Moolenaare0659a62011-04-01 19:14:40 +020052 * 2011 March Better error handling by Florian Zumbiehl.
53 * 2011 April Formatting by Bram Moolenaar
Bram Moolenaar4dcdf292015-03-05 17:51:15 +010054 * 08.06.2013 Little-endian hexdump (-e) and offset (-o) by Vadim Vygonets.
Bram Moolenaard8c56a02019-01-30 23:02:25 +010055 * 11.01.2019 Add full 64/32 bit range to -o and output by Christer Jensen.
Bram Moolenaar363d6142020-05-30 20:50:25 +020056 * 04.02.2020 Add -d for decimal offsets by Aapo Rantalainen
Erik Auerswaldc0a1d372022-01-14 11:58:48 +000057 * 14.01.2022 Disable extra newlines with -c0 -p by Erik Auerswald.
David Gow83e11802022-06-29 20:24:49 +010058 * 20.06.2022 Permit setting the variable names used by -i by David Gow
Christian Brabandt0ffa97e2023-08-31 21:03:02 +020059 * 31.08.2023 -R never/auto/always prints colored output
tristhaus85f45212023-10-06 19:51:13 +020060 * 06.10.2023 enable -r -b to reverse bit dumps
Igor Todorovski48a75f32024-01-09 21:05:48 +000061 * 12.01.2024 disable auto-conversion for z/OS (MVS)
Bram Moolenaar071d4272004-06-13 20:20:40 +000062 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020063 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020065 * I hereby grant permission to distribute and use xxd
66 * under X11-MIT or GPL-2.0 (at the user's choice).
67 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020068 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000069 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000070
71/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
72#if _MSC_VER >= 1400
73# define _CRT_SECURE_NO_DEPRECATE
74# define _CRT_NONSTDC_NO_DEPRECATE
75#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010076#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000077# define CYGWIN
78#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000079
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000080#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
81# define _XOPEN_SOURCE 700 /* for fdopen() */
82#endif
83
Bram Moolenaar071d4272004-06-13 20:20:40 +000084#include <stdio.h>
85#ifdef VAXC
86# include <file.h>
87#else
88# include <fcntl.h>
89#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020090#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000091# include <io.h> /* for setmode() */
Ken Takatac4a40382023-10-25 21:17:35 +020092#endif
93#ifdef WIN32
K.Takataf6fc2552023-09-01 18:41:04 +020094# include <windows.h>
95#endif
96#ifdef UNIX
97# include <unistd.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000098#endif
99#include <stdlib.h>
Keith Thompson184f71c2024-01-04 21:19:04 +0100100#include <string.h>
101#include <ctype.h>
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100102#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103#if __MWERKS__ && !defined(BEBOX)
104# include <unix.h> /* for fdopen() on MAC */
105#endif
106
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107
108/* This corrects the problem of missing prototypes for certain functions
109 * in some GNU installations (e.g. SunOS 4.1.x).
110 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
111 */
112#if defined(__GNUC__) && defined(__STDC__)
113# ifndef __USE_FIXED_PROTOTYPES__
114# define __USE_FIXED_PROTOTYPES__
115# endif
116#endif
117
118#ifndef __USE_FIXED_PROTOTYPES__
119/*
120 * This is historic and works only if the compiler really has no prototypes:
121 *
122 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
123 * FILE is defined on OS 4.x, not on 5.x (Solaris).
124 * if __SVR4 is defined (some Solaris versions), don't include this.
125 */
126#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
127# define __P(a) a
128/* excerpt from my sun_stdlib.h */
129extern int fprintf __P((FILE *, char *, ...));
130extern int fputs __P((char *, FILE *));
131extern int _flsbuf __P((unsigned char, FILE *));
132extern int _filbuf __P((FILE *));
133extern int fflush __P((FILE *));
134extern int fclose __P((FILE *));
135extern int fseek __P((FILE *, long, int));
136extern int rewind __P((FILE *));
137
138extern void perror __P((char *));
139# endif
140#endif
141
Igor Todorovski48a75f32024-01-09 21:05:48 +0000142char version[] = "xxd 2024-01-12 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143#ifdef WIN32
144char osver[] = " (Win32)";
145#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147#endif
148
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200149#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150# define BIN_READ(yes) ((yes) ? "rb" : "rt")
151# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
152# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
153# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000154# define PATH_SEP '\\'
155#elif defined(CYGWIN)
156# define BIN_READ(yes) ((yes) ? "rb" : "rt")
157# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
158# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
159# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
160# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161#else
162# ifdef VMS
163# define BIN_READ(dummy) "r"
164# define BIN_WRITE(dummy) "w"
165# define BIN_CREAT(dummy) O_CREAT
166# define BIN_ASSIGN(fp, dummy) fp
167# define PATH_SEP ']'
168# define FILE_SEP '.'
169# else
170# define BIN_READ(dummy) "r"
171# define BIN_WRITE(dummy) "w"
172# define BIN_CREAT(dummy) O_CREAT
173# define BIN_ASSIGN(fp, dummy) fp
174# define PATH_SEP '/'
175# endif
176#endif
177
178/* open has only to arguments on the Mac */
179#if __MWERKS__
180# define OPEN(name, mode, umask) open(name, mode)
181#else
182# define OPEN(name, mode, umask) open(name, mode, umask)
183#endif
184
185#ifdef AMIGA
186# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
187#else
188# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
189#endif
190
191#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200192# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193# define __P(a) a
194# else
195# define __P(a) ()
196# endif
197#endif
198
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
200#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100201#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000202
203char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
204
205/* the different hextypes known by this program: */
206#define HEX_NORMAL 0
207#define HEX_POSTSCRIPT 1
208#define HEX_CINCLUDE 2
209#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100210#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000211
Keith Thompson184f71c2024-01-04 21:19:04 +0100212#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((unsigned char)(c)) : (c))
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200213
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200214#define COLOR_PROLOGUE \
215l[c++] = '\033'; \
216l[c++] = '['; \
217l[c++] = '1'; \
218l[c++] = ';'; \
219l[c++] = '3';
220
221#define COLOR_EPILOGUE \
222l[c++] = '\033'; \
223l[c++] = '['; \
224l[c++] = '0'; \
225l[c++] = 'm';
226#define COLOR_RED '1'
227#define COLOR_GREEN '2'
228#define COLOR_YELLOW '3'
229#define COLOR_BLUE '4'
230#define COLOR_WHITE '7'
231
Bram Moolenaare0659a62011-04-01 19:14:40 +0200232static char *pname;
233
234 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100235exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000236{
237 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
238 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
239 fprintf(stderr, "Options:\n");
240 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
tristhaus85f45212023-10-06 19:51:13 +0200241 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200242 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000243 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
244 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100245 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100246 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 fprintf(stderr, " -h print this summary.\n");
248 fprintf(stderr, " -i output in C include file style.\n");
249 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100250 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100251 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000252 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
253 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
254 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200255 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
257#ifdef TRY_SEEK
258 "[+][-]", "(or +: rel.) ");
259#else
260 "", "");
261#endif
262 fprintf(stderr, " -u use upper case hex letters.\n");
K.Takataf6fc2552023-09-01 18:41:04 +0200263 fprintf(stderr, " -R when colorize the output; <when> can be 'always', 'auto' or 'never'. Default: 'auto'.\n"),
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
265 exit(1);
266}
267
Bram Moolenaare0659a62011-04-01 19:14:40 +0200268 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100269perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200270{
271 fprintf(stderr, "%s: ", pname);
272 perror(NULL);
273 exit(ret);
274}
275
DungSagaa2ffb432021-10-22 15:55:31 +0100276 static void
277error_exit(int ret, char *msg)
278{
279 fprintf(stderr, "%s: %s\n", pname, msg);
280 exit(ret);
281}
282
DungSagad1d8a592021-11-26 13:59:27 +0000283 static int
284getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000285{
DungSagad1d8a592021-11-26 13:59:27 +0000286 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000287 if (c == EOF && ferror(fpi))
288 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000289 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000290}
291
292 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000293putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000294{
295 if (putc(c, fpo) == EOF)
296 perror_exit(3);
297}
298
299 static void
300fputs_or_die(char *s, FILE *fpo)
301{
302 if (fputs(s, fpo) == EOF)
303 perror_exit(3);
304}
305
DungSaga7e5503c2021-12-01 11:24:52 +0000306/* Use a macro to allow for different arguments. */
307#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000308
309 static void
310fclose_or_die(FILE *fpi, FILE *fpo)
311{
312 if (fclose(fpo) != 0)
313 perror_exit(3);
314 if (fclose(fpi) != 0)
315 perror_exit(2);
316}
317
Bram Moolenaar071d4272004-06-13 20:20:40 +0000318/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000319 * If "c" is a hex digit, return the value.
320 * Otherwise return -1.
321 */
322 static int
323parse_hex_digit(int c)
324{
325 return (c >= '0' && c <= '9') ? c - '0'
326 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
327 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
328 : -1;
329}
330
331/*
tristhaus85f45212023-10-06 19:51:13 +0200332 * If "c" is a bin digit, return the value.
333 * Otherwise return -1.
334 */
335 static int
336parse_bin_digit(int c)
337{
338 return (c >= '0' && c <= '1') ? c - '0'
339 : -1;
340}
341
342/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000343 * Ignore text on "fpi" until end-of-line or end-of-file.
344 * Return the '\n' or EOF character.
345 * When an error is encountered exit with an error message.
346 */
347 static int
348skip_to_eol(FILE *fpi, int c)
349{
350 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000351 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000352 return c;
353}
354
355/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000356 * Max. cols binary characters are decoded from the input stream per line.
357 * Two adjacent garbage characters after evaluated data delimit valid data.
358 * Everything up to the next newline is discarded.
359 *
360 * The name is historic and came from 'undo type opt h'.
361 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200362 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100363huntype(
364 FILE *fpi,
365 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100366 int cols,
367 int hextype,
368 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369{
Christian Brabandt7879bc52023-10-08 20:36:44 +0200370 int c, ign_garb = 1, n1 = -1, n2 = 0, n3 = 0, p = cols, bt = 0, b = 0, bcnt = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000371 long have_off = 0, want_off = 0;
372
373 rewind(fpi);
374
375 while ((c = getc(fpi)) != EOF)
376 {
377 if (c == '\r') /* Doze style input file? */
378 continue;
379
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100380 /* Allow multiple spaces. This doesn't work when there is normal text
381 * after the hex codes in the last line that looks like hex, thus only
382 * use it for PostScript format. */
383 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000384 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000385
tristhaus85f45212023-10-06 19:51:13 +0200386 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
387 {
388 n3 = n2;
389 n2 = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000390
tristhaus85f45212023-10-06 19:51:13 +0200391 n1 = parse_hex_digit(c);
392 if (n1 == -1 && ign_garb)
393 continue;
394 }
395 else /* HEX_BITS */
396 {
397 n1 = parse_hex_digit(c);
398 if (n1 == -1 && ign_garb)
399 continue;
400
401 bt = parse_bin_digit(c);
402 if (bt != -1)
403 {
404 b = ((b << 1) | bt);
405 ++bcnt;
406 }
407 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000408
409 ign_garb = 0;
410
tristhaus85f45212023-10-06 19:51:13 +0200411 if ((hextype != HEX_POSTSCRIPT) && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000412 {
tristhaus85f45212023-10-06 19:51:13 +0200413 if (hextype == HEX_NORMAL)
414 {
415 if (n1 < 0)
416 {
417 p = 0;
418 continue;
419 }
420 want_off = (want_off << 4) | n1;
421 }
422 else /* HEX_BITS */
423 {
OldWorldOrdr1c140302023-10-25 20:57:30 +0200424 if (n1 < 0)
425 {
426 p = 0;
tristhaus85f45212023-10-06 19:51:13 +0200427 bcnt = 0;
OldWorldOrdr1c140302023-10-25 20:57:30 +0200428 continue;
429 }
430 want_off = (want_off << 4) | n1;
tristhaus85f45212023-10-06 19:51:13 +0200431 }
432 continue;
433 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000434
435 if (base_off + want_off != have_off)
436 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200437 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100438 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000439#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000440 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441 have_off = base_off + want_off;
442#endif
443 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000444 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000445 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000446 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000447 }
448
tristhaus85f45212023-10-06 19:51:13 +0200449 if (hextype == HEX_NORMAL || hextype == HEX_POSTSCRIPT)
450 {
451 if (n2 >= 0 && n1 >= 0)
452 {
453 putc_or_die((n2 << 4) | n1, fpo);
454 have_off++;
455 want_off++;
456 n1 = -1;
457 if (!hextype && (++p >= cols))
458 /* skip the rest of the line as garbage */
459 c = skip_to_eol(fpi, c);
460 }
461 else if (n1 < 0 && n2 < 0 && n3 < 0)
462 /* already stumbled into garbage, skip line, wait and see */
463 c = skip_to_eol(fpi, c);
464 }
465 else /* HEX_BITS */
466 {
467 if (bcnt == 8)
468 {
469 putc_or_die(b, fpo);
470 have_off++;
471 want_off++;
472 b = 0;
473 bcnt = 0;
474 if (++p >= cols)
475 /* skip the rest of the line as garbage */
476 c = skip_to_eol(fpi, c);
477 }
478 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000479
DungSaga47810462021-10-22 12:55:42 +0100480 if (c == '\n')
481 {
tristhaus85f45212023-10-06 19:51:13 +0200482 if (hextype == HEX_NORMAL || hextype == HEX_BITS)
DungSaga47810462021-10-22 12:55:42 +0100483 want_off = 0;
484 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485 ign_garb = 1;
486 }
487 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200488 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100489 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000491 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000493 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000494 return 0;
495}
496
497/*
498 * Print line l. If nz is false, xxdline regards the line a line of
499 * zeroes. If there are three or more consecutive lines of zeroes,
500 * they are replaced by a single '*' character.
501 *
502 * If the output ends with more than two lines of zeroes, you
503 * should call xxdline again with l being the last line and nz
504 * negative. This ensures that the last line is shown even when
505 * it is all zeroes.
506 *
507 * If nz is always positive, lines are never suppressed.
508 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200509 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100510xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000511{
512 static char z[LLEN+1];
513 static int zero_seen = 0;
514
515 if (!nz && zero_seen == 1)
516 strcpy(z, l);
517
518 if (nz || !zero_seen++)
519 {
520 if (nz)
521 {
522 if (nz < 0)
523 zero_seen--;
524 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000525 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000527 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000528 }
529 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000530 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531 if (nz)
532 zero_seen = 0;
533 }
534}
535
536/* This is an EBCDIC to ASCII conversion table */
537/* from a proposed BTL standard April 16, 1979 */
538static unsigned char etoa64[] =
539{
540 0040,0240,0241,0242,0243,0244,0245,0246,
541 0247,0250,0325,0056,0074,0050,0053,0174,
542 0046,0251,0252,0253,0254,0255,0256,0257,
543 0260,0261,0041,0044,0052,0051,0073,0176,
544 0055,0057,0262,0263,0264,0265,0266,0267,
545 0270,0271,0313,0054,0045,0137,0076,0077,
546 0272,0273,0274,0275,0276,0277,0300,0301,
547 0302,0140,0072,0043,0100,0047,0075,0042,
548 0303,0141,0142,0143,0144,0145,0146,0147,
549 0150,0151,0304,0305,0306,0307,0310,0311,
550 0312,0152,0153,0154,0155,0156,0157,0160,
551 0161,0162,0136,0314,0315,0316,0317,0320,
552 0321,0345,0163,0164,0165,0166,0167,0170,
553 0171,0172,0322,0323,0324,0133,0326,0327,
554 0330,0331,0332,0333,0334,0335,0336,0337,
555 0340,0341,0342,0343,0344,0135,0346,0347,
556 0173,0101,0102,0103,0104,0105,0106,0107,
557 0110,0111,0350,0351,0352,0353,0354,0355,
558 0175,0112,0113,0114,0115,0116,0117,0120,
559 0121,0122,0356,0357,0360,0361,0362,0363,
560 0134,0237,0123,0124,0125,0126,0127,0130,
561 0131,0132,0364,0365,0366,0367,0370,0371,
562 0060,0061,0062,0063,0064,0065,0066,0067,
563 0070,0071,0372,0373,0374,0375,0376,0377
564};
565
K.Takataf6fc2552023-09-01 18:41:04 +0200566 static void
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200567begin_coloring_char (char *l, int *c, int e, int ebcdic)
568{
569 if (ebcdic)
570 {
571 if ((e >= 75 && e <= 80) || (e >= 90 && e <= 97) ||
572 (e >= 107 && e <= 111) || (e >= 121 && e <= 127) ||
573 (e >= 129 && e <= 137) || (e >= 145 && e <= 154) ||
574 (e >= 162 && e <= 169) || (e >= 192 && e <= 201) ||
575 (e >= 208 && e <= 217) || (e >= 226 && e <= 233) ||
576 (e >= 240 && e <= 249) || (e == 189) || (e == 64) ||
577 (e == 173) || (e == 224) )
578 l[(*c)++] = COLOR_GREEN;
579
580 else if (e == 37 || e == 13 || e == 5)
581 l[(*c)++] = COLOR_YELLOW;
582 else if (e == 0)
583 l[(*c)++] = COLOR_WHITE;
584 else if (e == 255)
585 l[(*c)++] = COLOR_BLUE;
586 else
587 l[(*c)++] = COLOR_RED;
588 }
589 else /* ASCII */
590 {
Igor Todorovski48a75f32024-01-09 21:05:48 +0000591 #if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200592 if (e >= 64)
593 l[(*c)++] = COLOR_GREEN;
594 #else
595 if (e > 31 && e < 127)
596 l[(*c)++] = COLOR_GREEN;
597 #endif
598
599 else if (e == 9 || e == 10 || e == 13)
600 l[(*c)++] = COLOR_YELLOW;
601 else if (e == 0)
602 l[(*c)++] = COLOR_WHITE;
603 else if (e == 255)
604 l[(*c)++] = COLOR_BLUE;
605 else
606 l[(*c)++] = COLOR_RED;
607 }
608 l[(*c)++] = 'm';
609}
610
K.Takataf6fc2552023-09-01 18:41:04 +0200611 static int
612enable_color(void)
613{
614#ifdef WIN32
615 DWORD mode;
616 HANDLE out;
617
618 if (!isatty(1))
619 return 0;
620
621 out = GetStdHandle(STD_OUTPUT_HANDLE);
622 GetConsoleMode(out, &mode);
623 mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
624 return (int)SetConsoleMode(out, mode);
625#elif defined(UNIX)
626 return isatty(STDOUT_FILENO);
627#else
628 return 0;
629#endif
630}
631
Bram Moolenaare0659a62011-04-01 19:14:40 +0200632 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100633main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634{
635 FILE *fp, *fpo;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200636 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0, i, x;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000637 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200638 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000639 int ebcdic = 0;
640 int octspergrp = -1; /* number of octets grouped in output */
641 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100642 long length = -1, n = 0, seekoff = 0;
643 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200644 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200645 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100646 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100647 int addrlen = 9;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200648 int color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200649 char *no_color;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200650
K.Takataf6fc2552023-09-01 18:41:04 +0200651 no_color = getenv("NO_COLOR");
652 if (no_color == NULL || no_color[0] == '\0')
653 color = enable_color();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654
655#ifdef AMIGA
656 /* This program doesn't work when started from the Workbench */
657 if (argc == 0)
658 exit(1);
659#endif
660
661 pname = argv[0];
662 for (pp = pname; *pp; )
663 if (*pp++ == PATH_SEP)
664 pname = pp;
665#ifdef FILE_SEP
666 for (pp = pname; *pp; pp++)
667 if (*pp == FILE_SEP)
668 {
669 *pp = '\0';
670 break;
671 }
672#endif
673
674 while (argc >= 2)
675 {
676 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
677 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
678 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100679 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000680 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
681 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
682 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200683 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200684 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 else if (!STRNCMP(pp, "-r", 2)) revert++;
686 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
687 else if (!STRNCMP(pp, "-v", 2))
688 {
689 fprintf(stderr, "%s%s\n", version, osver);
690 exit(0);
691 }
692 else if (!STRNCMP(pp, "-c", 2))
693 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100694 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200695 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100696 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000697 {
698 colsgiven = 1;
699 cols = (int)strtol(pp + 2, NULL, 0);
700 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 else
702 {
703 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200704 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000705 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706 cols = (int)strtol(argv[2], NULL, 0);
707 argv++;
708 argc--;
709 }
710 }
711 else if (!STRNCMP(pp, "-g", 2))
712 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100713 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000714 octspergrp = (int)strtol(pp + 2, NULL, 0);
715 else
716 {
717 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200718 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719 octspergrp = (int)strtol(argv[2], NULL, 0);
720 argv++;
721 argc--;
722 }
723 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100724 else if (!STRNCMP(pp, "-o", 2))
725 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100726 int reloffset = 0;
727 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100728 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100729 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100730 else
731 {
732 if (!argv[2])
733 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100734
735 if (argv[2][0] == '+')
736 reloffset++;
737 if (argv[2][reloffset] == '-')
738 negoffset++;
739
740 if (negoffset)
741 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
742 else
743 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
744
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100745 argv++;
746 argc--;
747 }
748 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749 else if (!STRNCMP(pp, "-s", 2))
750 {
751 relseek = 0;
752 negseek = 0;
753 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
754 {
755#ifdef TRY_SEEK
756 if (pp[2] == '+')
757 relseek++;
758 if (pp[2+relseek] == '-')
759 negseek++;
760#endif
761 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
762 }
763 else
764 {
765 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200766 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767#ifdef TRY_SEEK
768 if (argv[2][0] == '+')
769 relseek++;
770 if (argv[2][relseek] == '-')
771 negseek++;
772#endif
773 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
774 argv++;
775 argc--;
776 }
777 }
778 else if (!STRNCMP(pp, "-l", 2))
779 {
780 if (pp[2] && STRNCMP("en", pp + 2, 2))
781 length = strtol(pp + 2, (char **)NULL, 0);
782 else
783 {
784 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200785 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 length = strtol(argv[2], (char **)NULL, 0);
787 argv++;
788 argc--;
789 }
790 }
David Gow83e11802022-06-29 20:24:49 +0100791 else if (!STRNCMP(pp, "-n", 2))
792 {
793 if (pp[2] && STRNCMP("ame", pp + 2, 3))
794 varname = pp + 2;
795 else
796 {
797 if (!argv[2])
798 exit_with_usage();
799 varname = argv[2];
800 argv++;
801 argc--;
802 }
803 }
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200804 else if (!STRNCMP(pp, "-R", 2))
805 {
K.Takataf6fc2552023-09-01 18:41:04 +0200806 char *pw = pp + 2;
807 if (!pw[0])
808 {
809 pw = argv[2];
810 argv++;
811 argc--;
812 }
813 if (!pw)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200814 exit_with_usage();
K.Takataf6fc2552023-09-01 18:41:04 +0200815 if (!STRNCMP(pw, "always", 6))
816 {
817 (void)enable_color();
818 color = 1;
819 }
820 else if (!STRNCMP(pw, "never", 5))
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200821 color = 0;
K.Takataf6fc2552023-09-01 18:41:04 +0200822 else if (!STRNCMP(pw, "auto", 4))
K.Takata233f9562023-09-04 07:46:59 +0200823 color = enable_color();
K.Takataf6fc2552023-09-01 18:41:04 +0200824 else
825 exit_with_usage();
Aapo Rantalainene2528ae2023-08-31 17:58:13 +0200826 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827 else if (!strcmp(pp, "--")) /* end of options */
828 {
829 argv++;
830 argc--;
831 break;
832 }
833 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200834 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 else
836 break; /* not an option */
837
838 argv++; /* advance to next argument */
839 argc--;
840 }
841
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000842 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843 switch (hextype)
844 {
845 case HEX_POSTSCRIPT: cols = 30; break;
846 case HEX_CINCLUDE: cols = 12; break;
847 case HEX_BITS: cols = 6; break;
848 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100849 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000850 default: cols = 16; break;
851 }
852
853 if (octspergrp < 0)
854 switch (hextype)
855 {
856 case HEX_BITS: octspergrp = 1; break;
857 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100858 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 case HEX_POSTSCRIPT:
860 case HEX_CINCLUDE:
861 default: octspergrp = 0; break;
862 }
863
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000864 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
865 (hextype != HEX_POSTSCRIPT && cols < 1) ||
866 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000867 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868 {
869 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
870 exit(1);
871 }
872
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100873 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100875 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100876 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877
878 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200879 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880
881 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
882 BIN_ASSIGN(fp = stdin, !revert);
883 else
884 {
885 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
886 {
887 fprintf(stderr,"%s: ", pname);
888 perror(argv[1]);
889 return 2;
890 }
891 }
892
893 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
894 BIN_ASSIGN(fpo = stdout, revert);
895 else
896 {
897 int fd;
898 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
899
900 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
901 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
902 {
903 fprintf(stderr, "%s: ", pname);
904 perror(argv[2]);
905 return 3;
906 }
907 rewind(fpo);
908 }
Igor Todorovski48a75f32024-01-09 21:05:48 +0000909#ifdef __MVS__
910 // Disable auto-conversion on input file descriptors
911 __disableautocvt(fileno(fp));
912#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913
914 if (revert)
tristhaus85f45212023-10-06 19:51:13 +0200915 switch (hextype)
916 {
917 case HEX_NORMAL:
918 case HEX_POSTSCRIPT:
919 case HEX_BITS:
920 return huntype(fp, fpo, cols, hextype,
921 negseek ? -seekoff : seekoff);
922 break;
923 default:
924 error_exit(-1, "Sorry, cannot revert this type of hexdump");
925 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926
927 if (seekoff || negseek || !relseek)
928 {
929#ifdef TRY_SEEK
930 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000931 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000933 e = fseek(fp, negseek ? -seekoff : seekoff,
934 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000936 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 if (e >= 0)
938 seekoff = ftell(fp);
939 else
940#endif
941 {
942 long s = seekoff;
943
944 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000945 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200946 {
DungSaga7e5503c2021-12-01 11:24:52 +0000947 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200948 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 }
950 }
951
952 if (hextype == HEX_CINCLUDE)
953 {
David Gow83e11802022-06-29 20:24:49 +0100954 /* A user-set variable name overrides fp == stdin */
955 if (varname == NULL && fp != stdin)
956 varname = argv[1];
957
958 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 {
Keith Thompson184f71c2024-01-04 21:19:04 +0100960 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100961 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100962 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000963 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 }
965
966 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000967 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 {
DungSaga7e5503c2021-12-01 11:24:52 +0000969 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
970 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000971 p++;
972 }
973
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000974 if (p)
975 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976
David Gow83e11802022-06-29 20:24:49 +0100977 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000978 {
DungSagad1d8a592021-11-26 13:59:27 +0000979 fputs_or_die("};\n", fpo);
Keith Thompson184f71c2024-01-04 21:19:04 +0100980 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((unsigned char)varname[0]) ? "__" : ""));
David Gow83e11802022-06-29 20:24:49 +0100981 for (e = 0; (c = varname[e]) != 0; e++)
Keith Thompson184f71c2024-01-04 21:19:04 +0100982 putc_or_die(isalnum((unsigned char)c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000983 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984 }
985
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000986 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987 return 0;
988 }
989
990 if (hextype == HEX_POSTSCRIPT)
991 {
992 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000993 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000995 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
996 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000998 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001000 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001 p = cols;
1002 }
1003 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +00001004 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001005 putc_or_die('\n', fpo);
1006 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001007 return 0;
1008 }
1009
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001010 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011
Bram Moolenaar4dcdf292015-03-05 17:51:15 +01001012 if (hextype != HEX_BITS)
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001013 {
1014 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
1015 if (color)
1016 grplen += 11 * octspergrp; /* color-code needs 11 extra characters */
1017 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001018 else /* hextype == HEX_BITS */
1019 grplen = 8 * octspergrp + 1;
1020
DungSagad1d8a592021-11-26 13:59:27 +00001021 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 {
1023 if (p == 0)
1024 {
DungSaga581f41a2021-11-22 11:57:31 +00001025 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +02001026 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaar4390d872023-03-05 20:17:39 +00001027 for (c = addrlen; c < LLEN; l[c++] = ' ')
1028 ;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 }
DungSaga48608b42021-11-24 11:18:07 +00001030 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
1031 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +00001032 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001034 if (color)
1035 {
1036 COLOR_PROLOGUE
1037 begin_coloring_char(l,&c,e,ebcdic);
1038 l[c++] = hexx[(e >> 4) & 0xf];
1039 l[c++] = hexx[e & 0xf];
1040 COLOR_EPILOGUE
1041 }
1042 else /*No colors*/
1043 {
1044 l[c] = hexx[(e >> 4) & 0xf];
1045 l[++c] = hexx[e & 0xf];
1046 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047 }
1048 else /* hextype == HEX_BITS */
1049 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001050 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +00001051 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052 }
Bram Moolenaar085346f2018-02-24 18:30:55 +01001053 if (e)
1054 nonzero++;
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +00001055 /* When changing this update definition of LLEN above. */
Bram Moolenaar4390d872023-03-05 20:17:39 +00001056 if (hextype == HEX_LITTLEENDIAN)
1057 /* last group will be fully used, round up */
1058 c = grplen * ((cols + octspergrp - 1) / octspergrp);
1059 else
1060 c = (grplen * cols - 1) / octspergrp;
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001061
1062 if (color)
1063 {
1064 if (hextype == HEX_BITS)
1065 c += addrlen + 3 + p*12;
1066 else
1067 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p*12;
1068
1069 if (hextype == HEX_LITTLEENDIAN)
1070 c += 1;
1071
1072 COLOR_PROLOGUE
1073 begin_coloring_char(l,&c,e,ebcdic);
Igor Todorovski48a75f32024-01-09 21:05:48 +00001074#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001075 if (e >= 64)
1076 l[c++] = e;
1077 else
1078 l[c++] = '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079#else
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001080 if (ebcdic)
1081 e = (e < 64) ? '.' : etoa64[e-64];
1082 l[c++] = (e > 31 && e < 127) ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +00001083#endif
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001084 COLOR_EPILOGUE
1085 n++;
1086 if (++p == cols)
1087 {
1088 l[c++] = '\n';
1089 l[c++] = '\0';
1090 xxdline(fpo, l, autoskip ? nonzero : 1);
1091 nonzero = 0;
1092 p = 0;
1093 }
1094 }
1095 else /*no colors*/
1096 {
1097 if (ebcdic)
1098 e = (e < 64) ? '.' : etoa64[e-64];
1099
1100 c += addrlen + 3 + p;
1101 l[c++] =
Igor Todorovski48a75f32024-01-09 21:05:48 +00001102#if defined(__MVS__) && __CHARSET_LIB == 0
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001103 (e >= 64)
1104#else
1105 (e > 31 && e < 127)
1106#endif
1107 ? e : '.';
1108 n++;
1109 if (++p == cols)
1110 {
1111 l[c++] = '\n';
1112 l[c] = '\0';
1113 xxdline(fpo, l, autoskip ? nonzero : 1);
1114 nonzero = 0;
1115 p = 0;
1116 }
1117 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001118 }
1119 if (p)
1120 {
Aapo Rantalainene2528ae2023-08-31 17:58:13 +02001121 l[c++] = '\n';
1122 l[c] = '\0';
1123 if (color)
1124 {
1125 c++;
1126
1127 x = p;
1128 if (hextype == HEX_LITTLEENDIAN)
1129 {
1130 int fill = octspergrp - (p % octspergrp);
1131 if (fill == octspergrp) fill = 0;
1132
1133 c = addrlen + 1 + (grplen * (x - (octspergrp-fill))) / octspergrp;
1134
1135 for (i = 0; i < fill;i++)
1136 {
1137 COLOR_PROLOGUE
1138 l[c++] = COLOR_RED;
1139 l[c++] = 'm';
1140 l[c++] = ' '; /* empty space */
1141 COLOR_EPILOGUE
1142 x++;
1143 p++;
1144 }
1145 }
1146
1147 if (hextype != HEX_BITS)
1148 {
1149 c = addrlen + 1 + (grplen * x) / octspergrp;
1150 c += cols - p;
1151 c += (cols - p) / octspergrp;
1152
1153 for (i = cols - p; i > 0;i--)
1154 {
1155 COLOR_PROLOGUE
1156 l[c++] = COLOR_RED;
1157 l[c++] = 'm';
1158 l[c++] = ' '; /* empty space */
1159 COLOR_EPILOGUE
1160 }
1161 }
1162 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163 xxdline(fpo, l, 1);
1164 }
1165 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +00001166 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167
Bram Moolenaar8af87bd2021-11-25 11:16:50 +00001168 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169 return 0;
1170}
Bram Moolenaare0659a62011-04-01 19:14:40 +02001171
1172/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */