blob: b6756aa8992228791f2343b3f3edf4a9a87c5ad5 [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
Bram Moolenaar071d4272004-06-13 20:20:40 +000057 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020058 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000059 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020060 * I hereby grant permission to distribute and use xxd
61 * under X11-MIT or GPL-2.0 (at the user's choice).
62 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020063 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000065
66/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
67#if _MSC_VER >= 1400
68# define _CRT_SECURE_NO_DEPRECATE
69# define _CRT_NONSTDC_NO_DEPRECATE
70#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010071#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000072# define CYGWIN
73#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000074
Bram Moolenaar071d4272004-06-13 20:20:40 +000075#include <stdio.h>
76#ifdef VAXC
77# include <file.h>
78#else
79# include <fcntl.h>
80#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020081#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000082# include <io.h> /* for setmode() */
83#else
84# ifdef UNIX
85# include <unistd.h>
86# endif
87#endif
88#include <stdlib.h>
89#include <string.h> /* for strncmp() */
90#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010091#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000092#if __MWERKS__ && !defined(BEBOX)
93# include <unix.h> /* for fdopen() on MAC */
94#endif
95
Bram Moolenaar071d4272004-06-13 20:20:40 +000096
97/* This corrects the problem of missing prototypes for certain functions
98 * in some GNU installations (e.g. SunOS 4.1.x).
99 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
100 */
101#if defined(__GNUC__) && defined(__STDC__)
102# ifndef __USE_FIXED_PROTOTYPES__
103# define __USE_FIXED_PROTOTYPES__
104# endif
105#endif
106
107#ifndef __USE_FIXED_PROTOTYPES__
108/*
109 * This is historic and works only if the compiler really has no prototypes:
110 *
111 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
112 * FILE is defined on OS 4.x, not on 5.x (Solaris).
113 * if __SVR4 is defined (some Solaris versions), don't include this.
114 */
115#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
116# define __P(a) a
117/* excerpt from my sun_stdlib.h */
118extern int fprintf __P((FILE *, char *, ...));
119extern int fputs __P((char *, FILE *));
120extern int _flsbuf __P((unsigned char, FILE *));
121extern int _filbuf __P((FILE *));
122extern int fflush __P((FILE *));
123extern int fclose __P((FILE *));
124extern int fseek __P((FILE *, long, int));
125extern int rewind __P((FILE *));
126
127extern void perror __P((char *));
128# endif
129#endif
130
131extern long int strtol();
132extern long int ftell();
133
DungSaga47810462021-10-22 12:55:42 +0100134char version[] = "xxd 2021-10-22 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000135#ifdef WIN32
136char osver[] = " (Win32)";
137#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139#endif
140
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200141#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142# define BIN_READ(yes) ((yes) ? "rb" : "rt")
143# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
144# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
145# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000146# define PATH_SEP '\\'
147#elif defined(CYGWIN)
148# define BIN_READ(yes) ((yes) ? "rb" : "rt")
149# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
150# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
151# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
152# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153#else
154# ifdef VMS
155# define BIN_READ(dummy) "r"
156# define BIN_WRITE(dummy) "w"
157# define BIN_CREAT(dummy) O_CREAT
158# define BIN_ASSIGN(fp, dummy) fp
159# define PATH_SEP ']'
160# define FILE_SEP '.'
161# else
162# define BIN_READ(dummy) "r"
163# define BIN_WRITE(dummy) "w"
164# define BIN_CREAT(dummy) O_CREAT
165# define BIN_ASSIGN(fp, dummy) fp
166# define PATH_SEP '/'
167# endif
168#endif
169
170/* open has only to arguments on the Mac */
171#if __MWERKS__
172# define OPEN(name, mode, umask) open(name, mode)
173#else
174# define OPEN(name, mode, umask) open(name, mode, umask)
175#endif
176
177#ifdef AMIGA
178# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
179#else
180# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
181#endif
182
183#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200184# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185# define __P(a) a
186# else
187# define __P(a) ()
188# endif
189#endif
190
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
192#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100193#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194
195char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
196
197/* the different hextypes known by this program: */
198#define HEX_NORMAL 0
199#define HEX_POSTSCRIPT 1
200#define HEX_CINCLUDE 2
201#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100202#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000203
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200204#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
205
Bram Moolenaare0659a62011-04-01 19:14:40 +0200206static char *pname;
207
208 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100209exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000210{
211 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
212 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
213 fprintf(stderr, "Options:\n");
214 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100215 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200216 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
218 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100219 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100220 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221 fprintf(stderr, " -h print this summary.\n");
222 fprintf(stderr, " -i output in C include file style.\n");
223 fprintf(stderr, " -l len stop after <len> octets.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100224 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
226 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
227 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200228 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
230#ifdef TRY_SEEK
231 "[+][-]", "(or +: rel.) ");
232#else
233 "", "");
234#endif
235 fprintf(stderr, " -u use upper case hex letters.\n");
236 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
237 exit(1);
238}
239
Bram Moolenaare0659a62011-04-01 19:14:40 +0200240 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100241perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200242{
243 fprintf(stderr, "%s: ", pname);
244 perror(NULL);
245 exit(ret);
246}
247
DungSagaa2ffb432021-10-22 15:55:31 +0100248 static void
249error_exit(int ret, char *msg)
250{
251 fprintf(stderr, "%s: %s\n", pname, msg);
252 exit(ret);
253}
254
Bram Moolenaar071d4272004-06-13 20:20:40 +0000255/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000256 * If "c" is a hex digit, return the value.
257 * Otherwise return -1.
258 */
259 static int
260parse_hex_digit(int c)
261{
262 return (c >= '0' && c <= '9') ? c - '0'
263 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
264 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
265 : -1;
266}
267
268/*
269 * Ignore text on "fpi" until end-of-line or end-of-file.
270 * Return the '\n' or EOF character.
271 * When an error is encountered exit with an error message.
272 */
273 static int
274skip_to_eol(FILE *fpi, int c)
275{
276 while (c != '\n' && c != EOF)
277 c = getc(fpi);
278 if (c == EOF && ferror(fpi))
279 perror_exit(2);
280 return c;
281}
282
283/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000284 * Max. cols binary characters are decoded from the input stream per line.
285 * Two adjacent garbage characters after evaluated data delimit valid data.
286 * Everything up to the next newline is discarded.
287 *
288 * The name is historic and came from 'undo type opt h'.
289 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200290 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100291huntype(
292 FILE *fpi,
293 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100294 int cols,
295 int hextype,
296 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000297{
298 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
299 long have_off = 0, want_off = 0;
300
301 rewind(fpi);
302
303 while ((c = getc(fpi)) != EOF)
304 {
305 if (c == '\r') /* Doze style input file? */
306 continue;
307
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100308 /* Allow multiple spaces. This doesn't work when there is normal text
309 * after the hex codes in the last line that looks like hex, thus only
310 * use it for PostScript format. */
311 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000312 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000313
Bram Moolenaar071d4272004-06-13 20:20:40 +0000314 n3 = n2;
315 n2 = n1;
316
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000317 n1 = parse_hex_digit(c);
318 if (n1 == -1 && ign_garb)
319 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000320
321 ign_garb = 0;
322
DungSaga375c35a2021-10-18 13:16:03 +0100323 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000324 {
DungSaga375c35a2021-10-18 13:16:03 +0100325 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000326 {
DungSaga375c35a2021-10-18 13:16:03 +0100327 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000328 continue;
329 }
DungSaga375c35a2021-10-18 13:16:03 +0100330 want_off = (want_off << 4) | n1;
331 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000332 }
333
334 if (base_off + want_off != have_off)
335 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200336 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100337 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000339 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000340 have_off = base_off + want_off;
341#endif
342 if (base_off + want_off < have_off)
DungSagaa2ffb432021-10-22 15:55:31 +0100343 error_exit(5, "sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000344 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200345 if (putc(0, fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100346 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000347 }
348
349 if (n2 >= 0 && n1 >= 0)
350 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200351 if (putc((n2 << 4) | n1, fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100352 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000353 have_off++;
354 want_off++;
355 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100356 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000357 /* skip the rest of the line as garbage */
358 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000359 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000360 else if (n1 < 0 && n2 < 0 && n3 < 0)
361 /* already stumbled into garbage, skip line, wait and see */
362 c = skip_to_eol(fpi, c);
363
DungSaga47810462021-10-22 12:55:42 +0100364 if (c == '\n')
365 {
366 if (!hextype)
367 want_off = 0;
368 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 ign_garb = 1;
370 }
371 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200372 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100373 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000374#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000375 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000376#endif
Bram Moolenaare0659a62011-04-01 19:14:40 +0200377 if (fclose(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100378 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200379 if (fclose(fpi) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100380 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 return 0;
382}
383
384/*
385 * Print line l. If nz is false, xxdline regards the line a line of
386 * zeroes. If there are three or more consecutive lines of zeroes,
387 * they are replaced by a single '*' character.
388 *
389 * If the output ends with more than two lines of zeroes, you
390 * should call xxdline again with l being the last line and nz
391 * negative. This ensures that the last line is shown even when
392 * it is all zeroes.
393 *
394 * If nz is always positive, lines are never suppressed.
395 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200396 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100397xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398{
399 static char z[LLEN+1];
400 static int zero_seen = 0;
401
402 if (!nz && zero_seen == 1)
403 strcpy(z, l);
404
405 if (nz || !zero_seen++)
406 {
407 if (nz)
408 {
409 if (nz < 0)
410 zero_seen--;
411 if (zero_seen == 2)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200412 if (fputs(z, fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100413 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414 if (zero_seen > 2)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200415 if (fputs("*\n", fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100416 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 }
418 if (nz >= 0 || zero_seen > 0)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200419 if (fputs(l, fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100420 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000421 if (nz)
422 zero_seen = 0;
423 }
424}
425
426/* This is an EBCDIC to ASCII conversion table */
427/* from a proposed BTL standard April 16, 1979 */
428static unsigned char etoa64[] =
429{
430 0040,0240,0241,0242,0243,0244,0245,0246,
431 0247,0250,0325,0056,0074,0050,0053,0174,
432 0046,0251,0252,0253,0254,0255,0256,0257,
433 0260,0261,0041,0044,0052,0051,0073,0176,
434 0055,0057,0262,0263,0264,0265,0266,0267,
435 0270,0271,0313,0054,0045,0137,0076,0077,
436 0272,0273,0274,0275,0276,0277,0300,0301,
437 0302,0140,0072,0043,0100,0047,0075,0042,
438 0303,0141,0142,0143,0144,0145,0146,0147,
439 0150,0151,0304,0305,0306,0307,0310,0311,
440 0312,0152,0153,0154,0155,0156,0157,0160,
441 0161,0162,0136,0314,0315,0316,0317,0320,
442 0321,0345,0163,0164,0165,0166,0167,0170,
443 0171,0172,0322,0323,0324,0133,0326,0327,
444 0330,0331,0332,0333,0334,0335,0336,0337,
445 0340,0341,0342,0343,0344,0135,0346,0347,
446 0173,0101,0102,0103,0104,0105,0106,0107,
447 0110,0111,0350,0351,0352,0353,0354,0355,
448 0175,0112,0113,0114,0115,0116,0117,0120,
449 0121,0122,0356,0357,0360,0361,0362,0363,
450 0134,0237,0123,0124,0125,0126,0127,0130,
451 0131,0132,0364,0365,0366,0367,0370,0371,
452 0060,0061,0062,0063,0064,0065,0066,0067,
453 0070,0071,0372,0373,0374,0375,0376,0377
454};
455
Bram Moolenaare0659a62011-04-01 19:14:40 +0200456 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100457main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000458{
459 FILE *fp, *fpo;
460 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200461 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
462 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000463 int ebcdic = 0;
464 int octspergrp = -1; /* number of octets grouped in output */
465 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100466 long length = -1, n = 0, seekoff = 0;
467 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200468 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200469 char *pp;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100470 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000471
472#ifdef AMIGA
473 /* This program doesn't work when started from the Workbench */
474 if (argc == 0)
475 exit(1);
476#endif
477
478 pname = argv[0];
479 for (pp = pname; *pp; )
480 if (*pp++ == PATH_SEP)
481 pname = pp;
482#ifdef FILE_SEP
483 for (pp = pname; *pp; pp++)
484 if (*pp == FILE_SEP)
485 {
486 *pp = '\0';
487 break;
488 }
489#endif
490
491 while (argc >= 2)
492 {
493 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
494 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
495 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100496 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000497 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
498 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
499 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200500 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200501 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502 else if (!STRNCMP(pp, "-r", 2)) revert++;
503 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
504 else if (!STRNCMP(pp, "-v", 2))
505 {
506 fprintf(stderr, "%s%s\n", version, osver);
507 exit(0);
508 }
509 else if (!STRNCMP(pp, "-c", 2))
510 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100511 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200512 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100513 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
514 cols = (int)strtol(pp + 2, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000515 else
516 {
517 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200518 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000519 cols = (int)strtol(argv[2], NULL, 0);
520 argv++;
521 argc--;
522 }
523 }
524 else if (!STRNCMP(pp, "-g", 2))
525 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100526 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 octspergrp = (int)strtol(pp + 2, NULL, 0);
528 else
529 {
530 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200531 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 octspergrp = (int)strtol(argv[2], NULL, 0);
533 argv++;
534 argc--;
535 }
536 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100537 else if (!STRNCMP(pp, "-o", 2))
538 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100539 int reloffset = 0;
540 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100541 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100542 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100543 else
544 {
545 if (!argv[2])
546 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100547
548 if (argv[2][0] == '+')
549 reloffset++;
550 if (argv[2][reloffset] == '-')
551 negoffset++;
552
553 if (negoffset)
554 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
555 else
556 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
557
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100558 argv++;
559 argc--;
560 }
561 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000562 else if (!STRNCMP(pp, "-s", 2))
563 {
564 relseek = 0;
565 negseek = 0;
566 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
567 {
568#ifdef TRY_SEEK
569 if (pp[2] == '+')
570 relseek++;
571 if (pp[2+relseek] == '-')
572 negseek++;
573#endif
574 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
575 }
576 else
577 {
578 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200579 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000580#ifdef TRY_SEEK
581 if (argv[2][0] == '+')
582 relseek++;
583 if (argv[2][relseek] == '-')
584 negseek++;
585#endif
586 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
587 argv++;
588 argc--;
589 }
590 }
591 else if (!STRNCMP(pp, "-l", 2))
592 {
593 if (pp[2] && STRNCMP("en", pp + 2, 2))
594 length = strtol(pp + 2, (char **)NULL, 0);
595 else
596 {
597 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200598 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000599 length = strtol(argv[2], (char **)NULL, 0);
600 argv++;
601 argc--;
602 }
603 }
604 else if (!strcmp(pp, "--")) /* end of options */
605 {
606 argv++;
607 argc--;
608 break;
609 }
610 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200611 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612 else
613 break; /* not an option */
614
615 argv++; /* advance to next argument */
616 argc--;
617 }
618
619 if (!cols)
620 switch (hextype)
621 {
622 case HEX_POSTSCRIPT: cols = 30; break;
623 case HEX_CINCLUDE: cols = 12; break;
624 case HEX_BITS: cols = 6; break;
625 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100626 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000627 default: cols = 16; break;
628 }
629
630 if (octspergrp < 0)
631 switch (hextype)
632 {
633 case HEX_BITS: octspergrp = 1; break;
634 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100635 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 case HEX_POSTSCRIPT:
637 case HEX_CINCLUDE:
638 default: octspergrp = 0; break;
639 }
640
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100641 if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000642 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000643 {
644 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
645 exit(1);
646 }
647
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100648 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100650 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100651 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000652
653 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200654 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655
656 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
657 BIN_ASSIGN(fp = stdin, !revert);
658 else
659 {
660 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
661 {
662 fprintf(stderr,"%s: ", pname);
663 perror(argv[1]);
664 return 2;
665 }
666 }
667
668 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
669 BIN_ASSIGN(fpo = stdout, revert);
670 else
671 {
672 int fd;
673 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
674
675 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
676 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
677 {
678 fprintf(stderr, "%s: ", pname);
679 perror(argv[2]);
680 return 3;
681 }
682 rewind(fpo);
683 }
684
685 if (revert)
686 {
687 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSagaa2ffb432021-10-22 15:55:31 +0100688 error_exit(-1, "sorry, cannot revert this type of hexdump");
689 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690 negseek ? -seekoff : seekoff);
691 }
692
693 if (seekoff || negseek || !relseek)
694 {
695#ifdef TRY_SEEK
696 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000697 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000699 e = fseek(fp, negseek ? -seekoff : seekoff,
700 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 if (e < 0 && negseek)
DungSagaa2ffb432021-10-22 15:55:31 +0100702 error_exit(4, "sorry cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 if (e >= 0)
704 seekoff = ftell(fp);
705 else
706#endif
707 {
708 long s = seekoff;
709
710 while (s--)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200711 if (getc(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200712 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200713 if (ferror(fp))
714 {
DungSagaa2ffb432021-10-22 15:55:31 +0100715 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200716 }
717 else
718 {
DungSagaa2ffb432021-10-22 15:55:31 +0100719 error_exit(4, "sorry cannot seek.");
Bram Moolenaare0659a62011-04-01 19:14:40 +0200720 }
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200721 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000722 }
723 }
724
725 if (hextype == HEX_CINCLUDE)
726 {
727 if (fp != stdin)
728 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200729 if (fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100730 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200732 if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100733 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200734 if (fputs("[] = {\n", fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100735 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736 }
737
738 p = 0;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200739 c = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740 while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
741 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200742 if (fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
Bram Moolenaarfe70acb2013-06-21 18:31:23 +0200743 (p % cols) ? ", " : &",\n "[2*!p], c) < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100744 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000745 p++;
746 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200747 if (c == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100748 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749
Bram Moolenaar53eb37e2013-02-26 14:14:07 +0100750 if (p && fputs("\n", fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100751 perror_exit(3);
Bram Moolenaarfe70acb2013-06-21 18:31:23 +0200752 if (fputs(&"};\n"[3 * (fp == stdin)], fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100753 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754
755 if (fp != stdin)
756 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200757 if (fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100758 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200760 if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100761 perror_exit(3);
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200762 if (fprintf(fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p) < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100763 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 }
765
Bram Moolenaare0659a62011-04-01 19:14:40 +0200766 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100767 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200768 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100769 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770 return 0;
771 }
772
773 if (hextype == HEX_POSTSCRIPT)
774 {
775 p = cols;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200776 e = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000777 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
778 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200779 if (putc(hexx[(e >> 4) & 0xf], fpo) == EOF
780 || putc(hexx[e & 0xf], fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100781 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 n++;
783 if (!--p)
784 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200785 if (putc('\n', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100786 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787 p = cols;
788 }
789 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200790 if (e == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100791 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 if (p < cols)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200793 if (putc('\n', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100794 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200795 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100796 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200797 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100798 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 return 0;
800 }
801
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100802 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100804 if (hextype != HEX_BITS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
806 else /* hextype == HEX_BITS */
807 grplen = 8 * octspergrp + 1;
808
Bram Moolenaare0659a62011-04-01 19:14:40 +0200809 e = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
811 {
DungSaga48608b42021-11-24 11:18:07 +0000812 int x;
813
Bram Moolenaar071d4272004-06-13 20:20:40 +0000814 if (p == 0)
815 {
DungSaga581f41a2021-11-22 11:57:31 +0000816 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200817 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100818 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 }
DungSaga48608b42021-11-24 11:18:07 +0000820 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
821 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000822 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 {
DungSaga48608b42021-11-24 11:18:07 +0000824 l[c] = hexx[(e >> 4) & 0xf];
DungSaga581f41a2021-11-22 11:57:31 +0000825 l[++c] = hexx[e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 }
827 else /* hextype == HEX_BITS */
828 {
829 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000831 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100833 if (e)
834 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 if (ebcdic)
836 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000837 /* When changing this update definition of LLEN above. */
DungSaga48608b42021-11-24 11:18:07 +0000838 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p;
839 l[c++] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840#ifdef __MVS__
841 (e >= 64)
842#else
843 (e > 31 && e < 127)
844#endif
845 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 n++;
847 if (++p == cols)
848 {
DungSaga48608b42021-11-24 11:18:07 +0000849 l[c] = '\n';
850 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 xxdline(fpo, l, autoskip ? nonzero : 1);
852 nonzero = 0;
853 p = 0;
854 }
855 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200856 if (e == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100857 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858 if (p)
859 {
DungSaga48608b42021-11-24 11:18:07 +0000860 l[c] = '\n';
861 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 xxdline(fpo, l, 1);
863 }
864 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000865 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866
Bram Moolenaare0659a62011-04-01 19:14:40 +0200867 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100868 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200869 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100870 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 return 0;
872}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200873
874/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */