blob: 8429b98ec5663da3dd6f073fb85c69c6b4d4aa2b [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
137extern long int strtol();
138extern long int ftell();
139
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000140char version[] = "xxd 2022-01-14 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000141#ifdef WIN32
142char osver[] = " (Win32)";
143#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145#endif
146
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200147#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148# define BIN_READ(yes) ((yes) ? "rb" : "rt")
149# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
150# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
151# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000152# define PATH_SEP '\\'
153#elif defined(CYGWIN)
154# define BIN_READ(yes) ((yes) ? "rb" : "rt")
155# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
156# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
157# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
158# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159#else
160# ifdef VMS
161# define BIN_READ(dummy) "r"
162# define BIN_WRITE(dummy) "w"
163# define BIN_CREAT(dummy) O_CREAT
164# define BIN_ASSIGN(fp, dummy) fp
165# define PATH_SEP ']'
166# define FILE_SEP '.'
167# else
168# define BIN_READ(dummy) "r"
169# define BIN_WRITE(dummy) "w"
170# define BIN_CREAT(dummy) O_CREAT
171# define BIN_ASSIGN(fp, dummy) fp
172# define PATH_SEP '/'
173# endif
174#endif
175
176/* open has only to arguments on the Mac */
177#if __MWERKS__
178# define OPEN(name, mode, umask) open(name, mode)
179#else
180# define OPEN(name, mode, umask) open(name, mode, umask)
181#endif
182
183#ifdef AMIGA
184# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
185#else
186# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
187#endif
188
189#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200190# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191# define __P(a) a
192# else
193# define __P(a) ()
194# endif
195#endif
196
Bram Moolenaar071d4272004-06-13 20:20:40 +0000197#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
198#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100199#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000200
201char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
202
203/* the different hextypes known by this program: */
204#define HEX_NORMAL 0
205#define HEX_POSTSCRIPT 1
206#define HEX_CINCLUDE 2
207#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100208#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200210#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
211
Bram Moolenaare0659a62011-04-01 19:14:40 +0200212static char *pname;
213
214 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100215exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216{
217 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
218 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
219 fprintf(stderr, "Options:\n");
220 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100221 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200222 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000223 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
224 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100225 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100226 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227 fprintf(stderr, " -h print this summary.\n");
228 fprintf(stderr, " -i output in C include file style.\n");
229 fprintf(stderr, " -l len stop after <len> octets.\n");
David Gow83e11802022-06-29 20:24:49 +0100230 fprintf(stderr, " -n name set the variable name used in C include output (-i).\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100231 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
233 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
234 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200235 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000236 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
237#ifdef TRY_SEEK
238 "[+][-]", "(or +: rel.) ");
239#else
240 "", "");
241#endif
242 fprintf(stderr, " -u use upper case hex letters.\n");
243 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
244 exit(1);
245}
246
Bram Moolenaare0659a62011-04-01 19:14:40 +0200247 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100248perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200249{
250 fprintf(stderr, "%s: ", pname);
251 perror(NULL);
252 exit(ret);
253}
254
DungSagaa2ffb432021-10-22 15:55:31 +0100255 static void
256error_exit(int ret, char *msg)
257{
258 fprintf(stderr, "%s: %s\n", pname, msg);
259 exit(ret);
260}
261
DungSagad1d8a592021-11-26 13:59:27 +0000262 static int
263getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000264{
DungSagad1d8a592021-11-26 13:59:27 +0000265 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000266 if (c == EOF && ferror(fpi))
267 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000268 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000269}
270
271 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000272putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000273{
274 if (putc(c, fpo) == EOF)
275 perror_exit(3);
276}
277
278 static void
279fputs_or_die(char *s, FILE *fpo)
280{
281 if (fputs(s, fpo) == EOF)
282 perror_exit(3);
283}
284
DungSaga7e5503c2021-12-01 11:24:52 +0000285/* Use a macro to allow for different arguments. */
286#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000287
288 static void
289fclose_or_die(FILE *fpi, FILE *fpo)
290{
291 if (fclose(fpo) != 0)
292 perror_exit(3);
293 if (fclose(fpi) != 0)
294 perror_exit(2);
295}
296
Bram Moolenaar071d4272004-06-13 20:20:40 +0000297/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000298 * If "c" is a hex digit, return the value.
299 * Otherwise return -1.
300 */
301 static int
302parse_hex_digit(int c)
303{
304 return (c >= '0' && c <= '9') ? c - '0'
305 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
306 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
307 : -1;
308}
309
310/*
311 * Ignore text on "fpi" until end-of-line or end-of-file.
312 * Return the '\n' or EOF character.
313 * When an error is encountered exit with an error message.
314 */
315 static int
316skip_to_eol(FILE *fpi, int c)
317{
318 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000319 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000320 return c;
321}
322
323/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000324 * Max. cols binary characters are decoded from the input stream per line.
325 * Two adjacent garbage characters after evaluated data delimit valid data.
326 * Everything up to the next newline is discarded.
327 *
328 * The name is historic and came from 'undo type opt h'.
329 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200330 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100331huntype(
332 FILE *fpi,
333 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100334 int cols,
335 int hextype,
336 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337{
338 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
339 long have_off = 0, want_off = 0;
340
341 rewind(fpi);
342
343 while ((c = getc(fpi)) != EOF)
344 {
345 if (c == '\r') /* Doze style input file? */
346 continue;
347
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100348 /* Allow multiple spaces. This doesn't work when there is normal text
349 * after the hex codes in the last line that looks like hex, thus only
350 * use it for PostScript format. */
351 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000352 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000353
Bram Moolenaar071d4272004-06-13 20:20:40 +0000354 n3 = n2;
355 n2 = n1;
356
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000357 n1 = parse_hex_digit(c);
358 if (n1 == -1 && ign_garb)
359 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000360
361 ign_garb = 0;
362
DungSaga375c35a2021-10-18 13:16:03 +0100363 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 {
DungSaga375c35a2021-10-18 13:16:03 +0100365 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366 {
DungSaga375c35a2021-10-18 13:16:03 +0100367 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368 continue;
369 }
DungSaga375c35a2021-10-18 13:16:03 +0100370 want_off = (want_off << 4) | n1;
371 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000372 }
373
374 if (base_off + want_off != have_off)
375 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200376 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100377 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000379 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000380 have_off = base_off + want_off;
381#endif
382 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000383 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000384 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000385 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386 }
387
388 if (n2 >= 0 && n1 >= 0)
389 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000390 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000391 have_off++;
392 want_off++;
393 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100394 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000395 /* skip the rest of the line as garbage */
396 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000397 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000398 else if (n1 < 0 && n2 < 0 && n3 < 0)
399 /* already stumbled into garbage, skip line, wait and see */
400 c = skip_to_eol(fpi, c);
401
DungSaga47810462021-10-22 12:55:42 +0100402 if (c == '\n')
403 {
404 if (!hextype)
405 want_off = 0;
406 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000407 ign_garb = 1;
408 }
409 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200410 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100411 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000412#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000413 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000415 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000416 return 0;
417}
418
419/*
420 * Print line l. If nz is false, xxdline regards the line a line of
421 * zeroes. If there are three or more consecutive lines of zeroes,
422 * they are replaced by a single '*' character.
423 *
424 * If the output ends with more than two lines of zeroes, you
425 * should call xxdline again with l being the last line and nz
426 * negative. This ensures that the last line is shown even when
427 * it is all zeroes.
428 *
429 * If nz is always positive, lines are never suppressed.
430 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200431 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100432xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000433{
434 static char z[LLEN+1];
435 static int zero_seen = 0;
436
437 if (!nz && zero_seen == 1)
438 strcpy(z, l);
439
440 if (nz || !zero_seen++)
441 {
442 if (nz)
443 {
444 if (nz < 0)
445 zero_seen--;
446 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000447 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000448 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000449 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 }
451 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000452 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000453 if (nz)
454 zero_seen = 0;
455 }
456}
457
458/* This is an EBCDIC to ASCII conversion table */
459/* from a proposed BTL standard April 16, 1979 */
460static unsigned char etoa64[] =
461{
462 0040,0240,0241,0242,0243,0244,0245,0246,
463 0247,0250,0325,0056,0074,0050,0053,0174,
464 0046,0251,0252,0253,0254,0255,0256,0257,
465 0260,0261,0041,0044,0052,0051,0073,0176,
466 0055,0057,0262,0263,0264,0265,0266,0267,
467 0270,0271,0313,0054,0045,0137,0076,0077,
468 0272,0273,0274,0275,0276,0277,0300,0301,
469 0302,0140,0072,0043,0100,0047,0075,0042,
470 0303,0141,0142,0143,0144,0145,0146,0147,
471 0150,0151,0304,0305,0306,0307,0310,0311,
472 0312,0152,0153,0154,0155,0156,0157,0160,
473 0161,0162,0136,0314,0315,0316,0317,0320,
474 0321,0345,0163,0164,0165,0166,0167,0170,
475 0171,0172,0322,0323,0324,0133,0326,0327,
476 0330,0331,0332,0333,0334,0335,0336,0337,
477 0340,0341,0342,0343,0344,0135,0346,0347,
478 0173,0101,0102,0103,0104,0105,0106,0107,
479 0110,0111,0350,0351,0352,0353,0354,0355,
480 0175,0112,0113,0114,0115,0116,0117,0120,
481 0121,0122,0356,0357,0360,0361,0362,0363,
482 0134,0237,0123,0124,0125,0126,0127,0130,
483 0131,0132,0364,0365,0366,0367,0370,0371,
484 0060,0061,0062,0063,0064,0065,0066,0067,
485 0070,0071,0372,0373,0374,0375,0376,0377
486};
487
Bram Moolenaare0659a62011-04-01 19:14:40 +0200488 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100489main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490{
491 FILE *fp, *fpo;
492 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000493 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200494 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495 int ebcdic = 0;
496 int octspergrp = -1; /* number of octets grouped in output */
497 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100498 long length = -1, n = 0, seekoff = 0;
499 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200500 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200501 char *pp;
David Gow83e11802022-06-29 20:24:49 +0100502 char *varname = NULL;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100503 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504
505#ifdef AMIGA
506 /* This program doesn't work when started from the Workbench */
507 if (argc == 0)
508 exit(1);
509#endif
510
511 pname = argv[0];
512 for (pp = pname; *pp; )
513 if (*pp++ == PATH_SEP)
514 pname = pp;
515#ifdef FILE_SEP
516 for (pp = pname; *pp; pp++)
517 if (*pp == FILE_SEP)
518 {
519 *pp = '\0';
520 break;
521 }
522#endif
523
524 while (argc >= 2)
525 {
526 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
527 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
528 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100529 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000530 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
531 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
532 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200533 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200534 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000535 else if (!STRNCMP(pp, "-r", 2)) revert++;
536 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
537 else if (!STRNCMP(pp, "-v", 2))
538 {
539 fprintf(stderr, "%s%s\n", version, osver);
540 exit(0);
541 }
542 else if (!STRNCMP(pp, "-c", 2))
543 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100544 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200545 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100546 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000547 {
548 colsgiven = 1;
549 cols = (int)strtol(pp + 2, NULL, 0);
550 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 else
552 {
553 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200554 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000555 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 cols = (int)strtol(argv[2], NULL, 0);
557 argv++;
558 argc--;
559 }
560 }
561 else if (!STRNCMP(pp, "-g", 2))
562 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100563 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000564 octspergrp = (int)strtol(pp + 2, NULL, 0);
565 else
566 {
567 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200568 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000569 octspergrp = (int)strtol(argv[2], NULL, 0);
570 argv++;
571 argc--;
572 }
573 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100574 else if (!STRNCMP(pp, "-o", 2))
575 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100576 int reloffset = 0;
577 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100578 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100579 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100580 else
581 {
582 if (!argv[2])
583 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100584
585 if (argv[2][0] == '+')
586 reloffset++;
587 if (argv[2][reloffset] == '-')
588 negoffset++;
589
590 if (negoffset)
591 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
592 else
593 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
594
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100595 argv++;
596 argc--;
597 }
598 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000599 else if (!STRNCMP(pp, "-s", 2))
600 {
601 relseek = 0;
602 negseek = 0;
603 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
604 {
605#ifdef TRY_SEEK
606 if (pp[2] == '+')
607 relseek++;
608 if (pp[2+relseek] == '-')
609 negseek++;
610#endif
611 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
612 }
613 else
614 {
615 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200616 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000617#ifdef TRY_SEEK
618 if (argv[2][0] == '+')
619 relseek++;
620 if (argv[2][relseek] == '-')
621 negseek++;
622#endif
623 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
624 argv++;
625 argc--;
626 }
627 }
628 else if (!STRNCMP(pp, "-l", 2))
629 {
630 if (pp[2] && STRNCMP("en", pp + 2, 2))
631 length = strtol(pp + 2, (char **)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 length = strtol(argv[2], (char **)NULL, 0);
637 argv++;
638 argc--;
639 }
640 }
David Gow83e11802022-06-29 20:24:49 +0100641 else if (!STRNCMP(pp, "-n", 2))
642 {
643 if (pp[2] && STRNCMP("ame", pp + 2, 3))
644 varname = pp + 2;
645 else
646 {
647 if (!argv[2])
648 exit_with_usage();
649 varname = argv[2];
650 argv++;
651 argc--;
652 }
653 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 else if (!strcmp(pp, "--")) /* end of options */
655 {
656 argv++;
657 argc--;
658 break;
659 }
660 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200661 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000662 else
663 break; /* not an option */
664
665 argv++; /* advance to next argument */
666 argc--;
667 }
668
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000669 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 switch (hextype)
671 {
672 case HEX_POSTSCRIPT: cols = 30; break;
673 case HEX_CINCLUDE: cols = 12; break;
674 case HEX_BITS: cols = 6; break;
675 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100676 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677 default: cols = 16; break;
678 }
679
680 if (octspergrp < 0)
681 switch (hextype)
682 {
683 case HEX_BITS: octspergrp = 1; break;
684 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100685 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 case HEX_POSTSCRIPT:
687 case HEX_CINCLUDE:
688 default: octspergrp = 0; break;
689 }
690
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000691 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
692 (hextype != HEX_POSTSCRIPT && cols < 1) ||
693 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000694 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000695 {
696 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
697 exit(1);
698 }
699
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100700 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100702 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100703 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704
705 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200706 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707
708 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
709 BIN_ASSIGN(fp = stdin, !revert);
710 else
711 {
712 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
713 {
714 fprintf(stderr,"%s: ", pname);
715 perror(argv[1]);
716 return 2;
717 }
718 }
719
720 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
721 BIN_ASSIGN(fpo = stdout, revert);
722 else
723 {
724 int fd;
725 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
726
727 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
728 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
729 {
730 fprintf(stderr, "%s: ", pname);
731 perror(argv[2]);
732 return 3;
733 }
734 rewind(fpo);
735 }
736
737 if (revert)
738 {
739 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000740 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100741 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742 negseek ? -seekoff : seekoff);
743 }
744
745 if (seekoff || negseek || !relseek)
746 {
747#ifdef TRY_SEEK
748 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000749 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000751 e = fseek(fp, negseek ? -seekoff : seekoff,
752 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000754 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755 if (e >= 0)
756 seekoff = ftell(fp);
757 else
758#endif
759 {
760 long s = seekoff;
761
762 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000763 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200764 {
DungSaga7e5503c2021-12-01 11:24:52 +0000765 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200766 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 }
768 }
769
770 if (hextype == HEX_CINCLUDE)
771 {
David Gow83e11802022-06-29 20:24:49 +0100772 /* A user-set variable name overrides fp == stdin */
773 if (varname == NULL && fp != stdin)
774 varname = argv[1];
775
776 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000777 {
David Gow83e11802022-06-29 20:24:49 +0100778 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)varname[0]) ? "__" : ""));
779 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000780 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
781 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 }
783
784 p = 0;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200785 c = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000786 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 {
DungSaga7e5503c2021-12-01 11:24:52 +0000788 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
789 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790 p++;
791 }
792
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000793 if (p)
794 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000795
David Gow83e11802022-06-29 20:24:49 +0100796 if (varname != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797 {
DungSagad1d8a592021-11-26 13:59:27 +0000798 fputs_or_die("};\n", fpo);
David Gow83e11802022-06-29 20:24:49 +0100799 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)varname[0]) ? "__" : ""));
800 for (e = 0; (c = varname[e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000801 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000802 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 }
804
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000805 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 return 0;
807 }
808
809 if (hextype == HEX_POSTSCRIPT)
810 {
811 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000812 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000814 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
815 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000817 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000819 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 p = cols;
821 }
822 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000823 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000824 putc_or_die('\n', fpo);
825 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 return 0;
827 }
828
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100829 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100831 if (hextype != HEX_BITS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
833 else /* hextype == HEX_BITS */
834 grplen = 8 * octspergrp + 1;
835
DungSagad1d8a592021-11-26 13:59:27 +0000836 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837 {
DungSaga48608b42021-11-24 11:18:07 +0000838 int x;
839
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840 if (p == 0)
841 {
DungSaga581f41a2021-11-22 11:57:31 +0000842 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200843 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100844 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 }
DungSaga48608b42021-11-24 11:18:07 +0000846 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
847 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000848 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 {
DungSaga48608b42021-11-24 11:18:07 +0000850 l[c] = hexx[(e >> 4) & 0xf];
DungSaga581f41a2021-11-22 11:57:31 +0000851 l[++c] = hexx[e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 }
853 else /* hextype == HEX_BITS */
854 {
855 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000857 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100859 if (e)
860 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 if (ebcdic)
862 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000863 /* When changing this update definition of LLEN above. */
DungSaga48608b42021-11-24 11:18:07 +0000864 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p;
865 l[c++] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866#ifdef __MVS__
867 (e >= 64)
868#else
869 (e > 31 && e < 127)
870#endif
871 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 n++;
873 if (++p == cols)
874 {
DungSaga48608b42021-11-24 11:18:07 +0000875 l[c] = '\n';
876 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 xxdline(fpo, l, autoskip ? nonzero : 1);
878 nonzero = 0;
879 p = 0;
880 }
881 }
882 if (p)
883 {
DungSaga48608b42021-11-24 11:18:07 +0000884 l[c] = '\n';
885 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886 xxdline(fpo, l, 1);
887 }
888 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000889 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000891 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892 return 0;
893}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200894
895/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */