blob: 2105a1c9c6c9e2c3992c384a3850bd4c6dacf351 [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
Bram Moolenaare0659a62011-04-01 19:14:40 +0200209static char *pname;
210
211 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100212exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213{
214 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
215 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
216 fprintf(stderr, "Options:\n");
217 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100218 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200219 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000220 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
221 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100222 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100223 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224 fprintf(stderr, " -h print this summary.\n");
225 fprintf(stderr, " -i output in C include file style.\n");
226 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100227 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100228 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
230 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
231 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200232 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
234#ifdef TRY_SEEK
235 "[+][-]", "(or +: rel.) ");
236#else
237 "", "");
238#endif
239 fprintf(stderr, " -u use upper case hex letters.\n");
240 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
241 exit(1);
242}
243
Bram Moolenaare0659a62011-04-01 19:14:40 +0200244 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100245perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200246{
247 fprintf(stderr, "%s: ", pname);
248 perror(NULL);
249 exit(ret);
250}
251
DungSagaa2ffb432021-10-22 15:55:31 +0100252 static void
253error_exit(int ret, char *msg)
254{
255 fprintf(stderr, "%s: %s\n", pname, msg);
256 exit(ret);
257}
258
DungSagad1d8a592021-11-26 13:59:27 +0000259 static int
260getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000261{
DungSagad1d8a592021-11-26 13:59:27 +0000262 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000263 if (c == EOF && ferror(fpi))
264 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000265 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000266}
267
268 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000269putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000270{
271 if (putc(c, fpo) == EOF)
272 perror_exit(3);
273}
274
275 static void
276fputs_or_die(char *s, FILE *fpo)
277{
278 if (fputs(s, fpo) == EOF)
279 perror_exit(3);
280}
281
DungSaga7e5503c2021-12-01 11:24:52 +0000282/* Use a macro to allow for different arguments. */
283#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000284
285 static void
286fclose_or_die(FILE *fpi, FILE *fpo)
287{
288 if (fclose(fpo) != 0)
289 perror_exit(3);
290 if (fclose(fpi) != 0)
291 perror_exit(2);
292}
293
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000295 * If "c" is a hex digit, return the value.
296 * Otherwise return -1.
297 */
298 static int
299parse_hex_digit(int c)
300{
301 return (c >= '0' && c <= '9') ? c - '0'
302 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
303 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
304 : -1;
305}
306
307/*
308 * Ignore text on "fpi" until end-of-line or end-of-file.
309 * Return the '\n' or EOF character.
310 * When an error is encountered exit with an error message.
311 */
312 static int
313skip_to_eol(FILE *fpi, int c)
314{
315 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000316 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000317 return c;
318}
319
320/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321 * Max. cols binary characters are decoded from the input stream per line.
322 * Two adjacent garbage characters after evaluated data delimit valid data.
323 * Everything up to the next newline is discarded.
324 *
325 * The name is historic and came from 'undo type opt h'.
326 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200327 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100328huntype(
329 FILE *fpi,
330 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100331 int cols,
332 int hextype,
333 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000334{
335 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
336 long have_off = 0, want_off = 0;
337
338 rewind(fpi);
339
340 while ((c = getc(fpi)) != EOF)
341 {
342 if (c == '\r') /* Doze style input file? */
343 continue;
344
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100345 /* Allow multiple spaces. This doesn't work when there is normal text
346 * after the hex codes in the last line that looks like hex, thus only
347 * use it for PostScript format. */
348 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000349 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000350
Bram Moolenaar071d4272004-06-13 20:20:40 +0000351 n3 = n2;
352 n2 = n1;
353
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000354 n1 = parse_hex_digit(c);
355 if (n1 == -1 && ign_garb)
356 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357
358 ign_garb = 0;
359
DungSaga375c35a2021-10-18 13:16:03 +0100360 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361 {
DungSaga375c35a2021-10-18 13:16:03 +0100362 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000363 {
DungSaga375c35a2021-10-18 13:16:03 +0100364 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000365 continue;
366 }
DungSaga375c35a2021-10-18 13:16:03 +0100367 want_off = (want_off << 4) | n1;
368 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 }
370
371 if (base_off + want_off != have_off)
372 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200373 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100374 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000375#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000376 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377 have_off = base_off + want_off;
378#endif
379 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000380 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000382 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 }
384
385 if (n2 >= 0 && n1 >= 0)
386 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000387 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 have_off++;
389 want_off++;
390 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100391 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000392 /* skip the rest of the line as garbage */
393 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000395 else if (n1 < 0 && n2 < 0 && n3 < 0)
396 /* already stumbled into garbage, skip line, wait and see */
397 c = skip_to_eol(fpi, c);
398
DungSaga47810462021-10-22 12:55:42 +0100399 if (c == '\n')
400 {
401 if (!hextype)
402 want_off = 0;
403 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404 ign_garb = 1;
405 }
406 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200407 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100408 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000410 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000411#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000412 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413 return 0;
414}
415
416/*
417 * Print line l. If nz is false, xxdline regards the line a line of
418 * zeroes. If there are three or more consecutive lines of zeroes,
419 * they are replaced by a single '*' character.
420 *
421 * If the output ends with more than two lines of zeroes, you
422 * should call xxdline again with l being the last line and nz
423 * negative. This ensures that the last line is shown even when
424 * it is all zeroes.
425 *
426 * If nz is always positive, lines are never suppressed.
427 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200428 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100429xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430{
431 static char z[LLEN+1];
432 static int zero_seen = 0;
433
434 if (!nz && zero_seen == 1)
435 strcpy(z, l);
436
437 if (nz || !zero_seen++)
438 {
439 if (nz)
440 {
441 if (nz < 0)
442 zero_seen--;
443 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000444 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000445 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000446 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000447 }
448 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000449 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 if (nz)
451 zero_seen = 0;
452 }
453}
454
455/* This is an EBCDIC to ASCII conversion table */
456/* from a proposed BTL standard April 16, 1979 */
457static unsigned char etoa64[] =
458{
459 0040,0240,0241,0242,0243,0244,0245,0246,
460 0247,0250,0325,0056,0074,0050,0053,0174,
461 0046,0251,0252,0253,0254,0255,0256,0257,
462 0260,0261,0041,0044,0052,0051,0073,0176,
463 0055,0057,0262,0263,0264,0265,0266,0267,
464 0270,0271,0313,0054,0045,0137,0076,0077,
465 0272,0273,0274,0275,0276,0277,0300,0301,
466 0302,0140,0072,0043,0100,0047,0075,0042,
467 0303,0141,0142,0143,0144,0145,0146,0147,
468 0150,0151,0304,0305,0306,0307,0310,0311,
469 0312,0152,0153,0154,0155,0156,0157,0160,
470 0161,0162,0136,0314,0315,0316,0317,0320,
471 0321,0345,0163,0164,0165,0166,0167,0170,
472 0171,0172,0322,0323,0324,0133,0326,0327,
473 0330,0331,0332,0333,0334,0335,0336,0337,
474 0340,0341,0342,0343,0344,0135,0346,0347,
475 0173,0101,0102,0103,0104,0105,0106,0107,
476 0110,0111,0350,0351,0352,0353,0354,0355,
477 0175,0112,0113,0114,0115,0116,0117,0120,
478 0121,0122,0356,0357,0360,0361,0362,0363,
479 0134,0237,0123,0124,0125,0126,0127,0130,
480 0131,0132,0364,0365,0366,0367,0370,0371,
481 0060,0061,0062,0063,0064,0065,0066,0067,
482 0070,0071,0372,0373,0374,0375,0376,0377
483};
484
Bram Moolenaare0659a62011-04-01 19:14:40 +0200485 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100486main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487{
488 FILE *fp, *fpo;
489 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000490 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200491 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492 int ebcdic = 0;
493 int octspergrp = -1; /* number of octets grouped in output */
494 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100495 long length = -1, n = 0, seekoff = 0;
496 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200497 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200498 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100499 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100500 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000501
502#ifdef AMIGA
503 /* This program doesn't work when started from the Workbench */
504 if (argc == 0)
505 exit(1);
506#endif
507
508 pname = argv[0];
509 for (pp = pname; *pp; )
510 if (*pp++ == PATH_SEP)
511 pname = pp;
512#ifdef FILE_SEP
513 for (pp = pname; *pp; pp++)
514 if (*pp == FILE_SEP)
515 {
516 *pp = '\0';
517 break;
518 }
519#endif
520
521 while (argc >= 2)
522 {
523 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
524 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
525 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100526 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
528 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
529 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200530 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200531 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 else if (!STRNCMP(pp, "-r", 2)) revert++;
533 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
534 else if (!STRNCMP(pp, "-v", 2))
535 {
536 fprintf(stderr, "%s%s\n", version, osver);
537 exit(0);
538 }
539 else if (!STRNCMP(pp, "-c", 2))
540 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100541 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200542 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100543 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000544 {
545 colsgiven = 1;
546 cols = (int)strtol(pp + 2, NULL, 0);
547 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000548 else
549 {
550 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200551 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000552 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000553 cols = (int)strtol(argv[2], NULL, 0);
554 argv++;
555 argc--;
556 }
557 }
558 else if (!STRNCMP(pp, "-g", 2))
559 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100560 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561 octspergrp = (int)strtol(pp + 2, NULL, 0);
562 else
563 {
564 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200565 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 octspergrp = (int)strtol(argv[2], NULL, 0);
567 argv++;
568 argc--;
569 }
570 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100571 else if (!STRNCMP(pp, "-o", 2))
572 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100573 int reloffset = 0;
574 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100575 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100576 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100577 else
578 {
579 if (!argv[2])
580 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100581
582 if (argv[2][0] == '+')
583 reloffset++;
584 if (argv[2][reloffset] == '-')
585 negoffset++;
586
587 if (negoffset)
588 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
589 else
590 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
591
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100592 argv++;
593 argc--;
594 }
595 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000596 else if (!STRNCMP(pp, "-s", 2))
597 {
598 relseek = 0;
599 negseek = 0;
600 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
601 {
602#ifdef TRY_SEEK
603 if (pp[2] == '+')
604 relseek++;
605 if (pp[2+relseek] == '-')
606 negseek++;
607#endif
608 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
609 }
610 else
611 {
612 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200613 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000614#ifdef TRY_SEEK
615 if (argv[2][0] == '+')
616 relseek++;
617 if (argv[2][relseek] == '-')
618 negseek++;
619#endif
620 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
621 argv++;
622 argc--;
623 }
624 }
625 else if (!STRNCMP(pp, "-l", 2))
626 {
627 if (pp[2] && STRNCMP("en", pp + 2, 2))
628 length = strtol(pp + 2, (char **)NULL, 0);
629 else
630 {
631 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200632 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633 length = strtol(argv[2], (char **)NULL, 0);
634 argv++;
635 argc--;
636 }
637 }
David Gow83e11802022-06-29 20:24:49 +0100638 else if (!STRNCMP(pp, "-n", 2))
639 {
640 if (pp[2] && STRNCMP("ame", pp + 2, 3))
641 varname = pp + 2;
642 else
643 {
644 if (!argv[2])
645 exit_with_usage();
646 varname = argv[2];
647 argv++;
648 argc--;
649 }
650 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000651 else if (!strcmp(pp, "--")) /* end of options */
652 {
653 argv++;
654 argc--;
655 break;
656 }
657 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200658 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 else
660 break; /* not an option */
661
662 argv++; /* advance to next argument */
663 argc--;
664 }
665
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000666 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 switch (hextype)
668 {
669 case HEX_POSTSCRIPT: cols = 30; break;
670 case HEX_CINCLUDE: cols = 12; break;
671 case HEX_BITS: cols = 6; break;
672 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100673 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674 default: cols = 16; break;
675 }
676
677 if (octspergrp < 0)
678 switch (hextype)
679 {
680 case HEX_BITS: octspergrp = 1; break;
681 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100682 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683 case HEX_POSTSCRIPT:
684 case HEX_CINCLUDE:
685 default: octspergrp = 0; break;
686 }
687
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000688 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
689 (hextype != HEX_POSTSCRIPT && cols < 1) ||
690 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000691 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000692 {
693 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
694 exit(1);
695 }
696
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100697 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100699 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100700 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701
702 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200703 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704
705 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
706 BIN_ASSIGN(fp = stdin, !revert);
707 else
708 {
709 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
710 {
711 fprintf(stderr,"%s: ", pname);
712 perror(argv[1]);
713 return 2;
714 }
715 }
716
717 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
718 BIN_ASSIGN(fpo = stdout, revert);
719 else
720 {
721 int fd;
722 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
723
724 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
725 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
726 {
727 fprintf(stderr, "%s: ", pname);
728 perror(argv[2]);
729 return 3;
730 }
731 rewind(fpo);
732 }
733
734 if (revert)
735 {
736 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000737 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100738 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 negseek ? -seekoff : seekoff);
740 }
741
742 if (seekoff || negseek || !relseek)
743 {
744#ifdef TRY_SEEK
745 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000746 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000747 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000748 e = fseek(fp, negseek ? -seekoff : seekoff,
749 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000751 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752 if (e >= 0)
753 seekoff = ftell(fp);
754 else
755#endif
756 {
757 long s = seekoff;
758
759 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000760 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200761 {
DungSaga7e5503c2021-12-01 11:24:52 +0000762 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200763 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 }
765 }
766
767 if (hextype == HEX_CINCLUDE)
768 {
David Gow83e11802022-06-29 20:24:49 +0100769 /* A user-set variable name overrides fp == stdin */
770 if (varname == NULL && fp != stdin)
771 varname = argv[1];
772
773 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 {
David Gow83e11802022-06-29 20:24:49 +0100775 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
776 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000777 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
778 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 }
780
781 p = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000782 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 {
DungSaga7e5503c2021-12-01 11:24:52 +0000784 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
785 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 p++;
787 }
788
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000789 if (p)
790 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000791
David Gow83e11802022-06-29 20:24:49 +0100792 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 {
DungSagad1d8a592021-11-26 13:59:27 +0000794 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100795 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
796 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000797 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000798 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 }
800
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000801 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802 return 0;
803 }
804
805 if (hextype == HEX_POSTSCRIPT)
806 {
807 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000808 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000810 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
811 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000813 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000814 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000815 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 p = cols;
817 }
818 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000819 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000820 putc_or_die('\n', fpo);
821 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822 return 0;
823 }
824
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100825 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100827 if (hextype != HEX_BITS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
829 else /* hextype == HEX_BITS */
830 grplen = 8 * octspergrp + 1;
831
DungSagad1d8a592021-11-26 13:59:27 +0000832 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833 {
DungSaga48608b42021-11-24 11:18:07 +0000834 int x;
835
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 if (p == 0)
837 {
DungSaga581f41a2021-11-22 11:57:31 +0000838 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200839 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100840 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841 }
DungSaga48608b42021-11-24 11:18:07 +0000842 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
843 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000844 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 {
DungSaga48608b42021-11-24 11:18:07 +0000846 l[c] = hexx[(e >> 4) & 0xf];
DungSaga581f41a2021-11-22 11:57:31 +0000847 l[++c] = hexx[e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000848 }
849 else /* hextype == HEX_BITS */
850 {
851 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000853 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100855 if (e)
856 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 if (ebcdic)
858 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000859 /* When changing this update definition of LLEN above. */
DungSaga48608b42021-11-24 11:18:07 +0000860 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p;
861 l[c++] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862#ifdef __MVS__
863 (e >= 64)
864#else
865 (e > 31 && e < 127)
866#endif
867 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868 n++;
869 if (++p == cols)
870 {
DungSaga48608b42021-11-24 11:18:07 +0000871 l[c] = '\n';
872 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 xxdline(fpo, l, autoskip ? nonzero : 1);
874 nonzero = 0;
875 p = 0;
876 }
877 }
878 if (p)
879 {
DungSaga48608b42021-11-24 11:18:07 +0000880 l[c] = '\n';
881 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882 xxdline(fpo, l, 1);
883 }
884 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000885 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000887 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 return 0;
889}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200890
891/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */