blob: b6024ad96b6af5979a05e50560191ac65565761b [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/*
256 * Max. cols binary characters are decoded from the input stream per line.
257 * Two adjacent garbage characters after evaluated data delimit valid data.
258 * Everything up to the next newline is discarded.
259 *
260 * The name is historic and came from 'undo type opt h'.
261 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200262 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100263huntype(
264 FILE *fpi,
265 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100266 int cols,
267 int hextype,
268 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269{
270 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
271 long have_off = 0, want_off = 0;
272
273 rewind(fpi);
274
275 while ((c = getc(fpi)) != EOF)
276 {
277 if (c == '\r') /* Doze style input file? */
278 continue;
279
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100280 /* Allow multiple spaces. This doesn't work when there is normal text
281 * after the hex codes in the last line that looks like hex, thus only
282 * use it for PostScript format. */
283 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000284 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000285
Bram Moolenaar071d4272004-06-13 20:20:40 +0000286 n3 = n2;
287 n2 = n1;
288
289 if (c >= '0' && c <= '9')
290 n1 = c - '0';
291 else if (c >= 'a' && c <= 'f')
292 n1 = c - 'a' + 10;
293 else if (c >= 'A' && c <= 'F')
294 n1 = c - 'A' + 10;
295 else
296 {
297 n1 = -1;
298 if (ign_garb)
299 continue;
300 }
301
302 ign_garb = 0;
303
DungSaga375c35a2021-10-18 13:16:03 +0100304 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000305 {
DungSaga375c35a2021-10-18 13:16:03 +0100306 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000307 {
DungSaga375c35a2021-10-18 13:16:03 +0100308 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000309 continue;
310 }
DungSaga375c35a2021-10-18 13:16:03 +0100311 want_off = (want_off << 4) | n1;
312 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000313 }
314
315 if (base_off + want_off != have_off)
316 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200317 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100318 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000319#ifdef TRY_SEEK
DungSaga47810462021-10-22 12:55:42 +0100320 if (fseek(fpo, base_off + want_off - have_off, 1) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321 have_off = base_off + want_off;
322#endif
323 if (base_off + want_off < have_off)
DungSagaa2ffb432021-10-22 15:55:31 +0100324 error_exit(5, "sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000325 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200326 if (putc(0, fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100327 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000328 }
329
330 if (n2 >= 0 && n1 >= 0)
331 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200332 if (putc((n2 << 4) | n1, fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100333 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000334 have_off++;
335 want_off++;
336 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100337 if (!hextype && (++p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338 {
DungSagac89c91c2021-10-16 19:07:46 +0100339 /* skip the rest of the line as garbage */
340 n2 = -1;
341 n3 = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000342 }
343 }
DungSagac89c91c2021-10-16 19:07:46 +0100344 if (n1 < 0 && n2 < 0 && n3 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000345 {
346 /* already stumbled into garbage, skip line, wait and see */
DungSaga47810462021-10-22 12:55:42 +0100347 while (c != '\n' && c != EOF)
348 c = getc(fpi);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200349 if (c == EOF && ferror(fpi))
DungSagaa2ffb432021-10-22 15:55:31 +0100350 perror_exit(2);
DungSaga47810462021-10-22 12:55:42 +0100351 }
352 if (c == '\n')
353 {
354 if (!hextype)
355 want_off = 0;
356 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357 ign_garb = 1;
358 }
359 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200360 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100361 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000362#ifdef TRY_SEEK
363 fseek(fpo, 0L, 2);
364#endif
Bram Moolenaare0659a62011-04-01 19:14:40 +0200365 if (fclose(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100366 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200367 if (fclose(fpi) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100368 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 return 0;
370}
371
372/*
373 * Print line l. If nz is false, xxdline regards the line a line of
374 * zeroes. If there are three or more consecutive lines of zeroes,
375 * they are replaced by a single '*' character.
376 *
377 * If the output ends with more than two lines of zeroes, you
378 * should call xxdline again with l being the last line and nz
379 * negative. This ensures that the last line is shown even when
380 * it is all zeroes.
381 *
382 * If nz is always positive, lines are never suppressed.
383 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200384 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100385xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386{
387 static char z[LLEN+1];
388 static int zero_seen = 0;
389
390 if (!nz && zero_seen == 1)
391 strcpy(z, l);
392
393 if (nz || !zero_seen++)
394 {
395 if (nz)
396 {
397 if (nz < 0)
398 zero_seen--;
399 if (zero_seen == 2)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200400 if (fputs(z, fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100401 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000402 if (zero_seen > 2)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200403 if (fputs("*\n", fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100404 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405 }
406 if (nz >= 0 || zero_seen > 0)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200407 if (fputs(l, fp) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100408 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409 if (nz)
410 zero_seen = 0;
411 }
412}
413
414/* This is an EBCDIC to ASCII conversion table */
415/* from a proposed BTL standard April 16, 1979 */
416static unsigned char etoa64[] =
417{
418 0040,0240,0241,0242,0243,0244,0245,0246,
419 0247,0250,0325,0056,0074,0050,0053,0174,
420 0046,0251,0252,0253,0254,0255,0256,0257,
421 0260,0261,0041,0044,0052,0051,0073,0176,
422 0055,0057,0262,0263,0264,0265,0266,0267,
423 0270,0271,0313,0054,0045,0137,0076,0077,
424 0272,0273,0274,0275,0276,0277,0300,0301,
425 0302,0140,0072,0043,0100,0047,0075,0042,
426 0303,0141,0142,0143,0144,0145,0146,0147,
427 0150,0151,0304,0305,0306,0307,0310,0311,
428 0312,0152,0153,0154,0155,0156,0157,0160,
429 0161,0162,0136,0314,0315,0316,0317,0320,
430 0321,0345,0163,0164,0165,0166,0167,0170,
431 0171,0172,0322,0323,0324,0133,0326,0327,
432 0330,0331,0332,0333,0334,0335,0336,0337,
433 0340,0341,0342,0343,0344,0135,0346,0347,
434 0173,0101,0102,0103,0104,0105,0106,0107,
435 0110,0111,0350,0351,0352,0353,0354,0355,
436 0175,0112,0113,0114,0115,0116,0117,0120,
437 0121,0122,0356,0357,0360,0361,0362,0363,
438 0134,0237,0123,0124,0125,0126,0127,0130,
439 0131,0132,0364,0365,0366,0367,0370,0371,
440 0060,0061,0062,0063,0064,0065,0066,0067,
441 0070,0071,0372,0373,0374,0375,0376,0377
442};
443
Bram Moolenaare0659a62011-04-01 19:14:40 +0200444 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100445main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446{
447 FILE *fp, *fpo;
448 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200449 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
450 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451 int ebcdic = 0;
452 int octspergrp = -1; /* number of octets grouped in output */
453 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100454 long length = -1, n = 0, seekoff = 0;
455 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200456 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200457 char *pp;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100458 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459
460#ifdef AMIGA
461 /* This program doesn't work when started from the Workbench */
462 if (argc == 0)
463 exit(1);
464#endif
465
466 pname = argv[0];
467 for (pp = pname; *pp; )
468 if (*pp++ == PATH_SEP)
469 pname = pp;
470#ifdef FILE_SEP
471 for (pp = pname; *pp; pp++)
472 if (*pp == FILE_SEP)
473 {
474 *pp = '\0';
475 break;
476 }
477#endif
478
479 while (argc >= 2)
480 {
481 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
482 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
483 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100484 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
486 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
487 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200488 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200489 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490 else if (!STRNCMP(pp, "-r", 2)) revert++;
491 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
492 else if (!STRNCMP(pp, "-v", 2))
493 {
494 fprintf(stderr, "%s%s\n", version, osver);
495 exit(0);
496 }
497 else if (!STRNCMP(pp, "-c", 2))
498 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100499 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200500 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100501 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
502 cols = (int)strtol(pp + 2, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000503 else
504 {
505 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200506 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000507 cols = (int)strtol(argv[2], NULL, 0);
508 argv++;
509 argc--;
510 }
511 }
512 else if (!STRNCMP(pp, "-g", 2))
513 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100514 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000515 octspergrp = (int)strtol(pp + 2, NULL, 0);
516 else
517 {
518 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200519 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000520 octspergrp = (int)strtol(argv[2], NULL, 0);
521 argv++;
522 argc--;
523 }
524 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100525 else if (!STRNCMP(pp, "-o", 2))
526 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100527 int reloffset = 0;
528 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100529 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100530 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100531 else
532 {
533 if (!argv[2])
534 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100535
536 if (argv[2][0] == '+')
537 reloffset++;
538 if (argv[2][reloffset] == '-')
539 negoffset++;
540
541 if (negoffset)
542 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
543 else
544 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
545
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100546 argv++;
547 argc--;
548 }
549 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000550 else if (!STRNCMP(pp, "-s", 2))
551 {
552 relseek = 0;
553 negseek = 0;
554 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
555 {
556#ifdef TRY_SEEK
557 if (pp[2] == '+')
558 relseek++;
559 if (pp[2+relseek] == '-')
560 negseek++;
561#endif
562 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
563 }
564 else
565 {
566 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200567 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568#ifdef TRY_SEEK
569 if (argv[2][0] == '+')
570 relseek++;
571 if (argv[2][relseek] == '-')
572 negseek++;
573#endif
574 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
575 argv++;
576 argc--;
577 }
578 }
579 else if (!STRNCMP(pp, "-l", 2))
580 {
581 if (pp[2] && STRNCMP("en", pp + 2, 2))
582 length = strtol(pp + 2, (char **)NULL, 0);
583 else
584 {
585 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200586 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000587 length = strtol(argv[2], (char **)NULL, 0);
588 argv++;
589 argc--;
590 }
591 }
592 else if (!strcmp(pp, "--")) /* end of options */
593 {
594 argv++;
595 argc--;
596 break;
597 }
598 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200599 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600 else
601 break; /* not an option */
602
603 argv++; /* advance to next argument */
604 argc--;
605 }
606
607 if (!cols)
608 switch (hextype)
609 {
610 case HEX_POSTSCRIPT: cols = 30; break;
611 case HEX_CINCLUDE: cols = 12; break;
612 case HEX_BITS: cols = 6; break;
613 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100614 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 default: cols = 16; break;
616 }
617
618 if (octspergrp < 0)
619 switch (hextype)
620 {
621 case HEX_BITS: octspergrp = 1; break;
622 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100623 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624 case HEX_POSTSCRIPT:
625 case HEX_CINCLUDE:
626 default: octspergrp = 0; break;
627 }
628
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100629 if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000630 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 {
632 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
633 exit(1);
634 }
635
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100636 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100638 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100639 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640
641 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200642 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000643
644 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
645 BIN_ASSIGN(fp = stdin, !revert);
646 else
647 {
648 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
649 {
650 fprintf(stderr,"%s: ", pname);
651 perror(argv[1]);
652 return 2;
653 }
654 }
655
656 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
657 BIN_ASSIGN(fpo = stdout, revert);
658 else
659 {
660 int fd;
661 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
662
663 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
664 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
665 {
666 fprintf(stderr, "%s: ", pname);
667 perror(argv[2]);
668 return 3;
669 }
670 rewind(fpo);
671 }
672
673 if (revert)
674 {
675 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSagaa2ffb432021-10-22 15:55:31 +0100676 error_exit(-1, "sorry, cannot revert this type of hexdump");
677 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 negseek ? -seekoff : seekoff);
679 }
680
681 if (seekoff || negseek || !relseek)
682 {
683#ifdef TRY_SEEK
684 if (relseek)
685 e = fseek(fp, negseek ? -seekoff : seekoff, 1);
686 else
687 e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
688 if (e < 0 && negseek)
DungSagaa2ffb432021-10-22 15:55:31 +0100689 error_exit(4, "sorry cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000690 if (e >= 0)
691 seekoff = ftell(fp);
692 else
693#endif
694 {
695 long s = seekoff;
696
697 while (s--)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200698 if (getc(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200699 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200700 if (ferror(fp))
701 {
DungSagaa2ffb432021-10-22 15:55:31 +0100702 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200703 }
704 else
705 {
DungSagaa2ffb432021-10-22 15:55:31 +0100706 error_exit(4, "sorry cannot seek.");
Bram Moolenaare0659a62011-04-01 19:14:40 +0200707 }
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200708 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709 }
710 }
711
712 if (hextype == HEX_CINCLUDE)
713 {
714 if (fp != stdin)
715 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200716 if (fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100717 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200719 if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100720 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200721 if (fputs("[] = {\n", fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100722 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723 }
724
725 p = 0;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200726 c = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727 while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
728 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200729 if (fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
Bram Moolenaarfe70acb2013-06-21 18:31:23 +0200730 (p % cols) ? ", " : &",\n "[2*!p], c) < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100731 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 p++;
733 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200734 if (c == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100735 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736
Bram Moolenaar53eb37e2013-02-26 14:14:07 +0100737 if (p && fputs("\n", fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100738 perror_exit(3);
Bram Moolenaarfe70acb2013-06-21 18:31:23 +0200739 if (fputs(&"};\n"[3 * (fp == stdin)], fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100740 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000741
742 if (fp != stdin)
743 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200744 if (fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "") < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100745 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000746 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200747 if (putc(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100748 perror_exit(3);
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200749 if (fprintf(fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p) < 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100750 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000751 }
752
Bram Moolenaare0659a62011-04-01 19:14:40 +0200753 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100754 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200755 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100756 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000757 return 0;
758 }
759
760 if (hextype == HEX_POSTSCRIPT)
761 {
762 p = cols;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200763 e = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
765 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200766 if (putc(hexx[(e >> 4) & 0xf], fpo) == EOF
767 || putc(hexx[e & 0xf], fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100768 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000769 n++;
770 if (!--p)
771 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200772 if (putc('\n', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100773 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 p = cols;
775 }
776 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200777 if (e == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100778 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 if (p < cols)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200780 if (putc('\n', fpo) == EOF)
DungSagaa2ffb432021-10-22 15:55:31 +0100781 perror_exit(3);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200782 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100783 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200784 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100785 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 return 0;
787 }
788
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100789 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100791 if (hextype != HEX_BITS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
793 else /* hextype == HEX_BITS */
794 grplen = 8 * octspergrp + 1;
795
Bram Moolenaare0659a62011-04-01 19:14:40 +0200796 e = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000797 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
798 {
799 if (p == 0)
800 {
Bram Moolenaar363d6142020-05-30 20:50:25 +0200801 if (decimal_offset)
802 addrlen = sprintf(l, "%08ld:",
803 ((unsigned long)(n + seekoff + displayoff)));
804 else
805 addrlen = sprintf(l, "%08lx:",
806 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100807 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 }
809 if (hextype == HEX_NORMAL)
810 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100811 l[c = (addrlen + 1 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100812 l[++c] = hexx[ e & 0xf];
813 }
814 else if (hextype == HEX_LITTLEENDIAN)
815 {
816 int x = p ^ (octspergrp-1);
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100817 l[c = (addrlen + 1 + (grplen * x) / octspergrp)] = hexx[(e >> 4) & 0xf];
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100818 l[++c] = hexx[ e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 }
820 else /* hextype == HEX_BITS */
821 {
822 int i;
823
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100824 c = (addrlen + 1 + (grplen * p) / octspergrp) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 for (i = 7; i >= 0; i--)
826 l[++c] = (e & (1 << i)) ? '1' : '0';
827 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100828 if (e)
829 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 if (ebcdic)
831 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000832 /* When changing this update definition of LLEN above. */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100833 l[addrlen + 3 + (grplen * cols - 1)/octspergrp + p] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834#ifdef __MVS__
835 (e >= 64)
836#else
837 (e > 31 && e < 127)
838#endif
839 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840 n++;
841 if (++p == cols)
842 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100843 l[c = (addrlen + 3 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 xxdline(fpo, l, autoskip ? nonzero : 1);
845 nonzero = 0;
846 p = 0;
847 }
848 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200849 if (e == EOF && ferror(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100850 perror_exit(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 if (p)
852 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100853 l[c = (addrlen + 3 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 xxdline(fpo, l, 1);
855 }
856 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000857 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858
Bram Moolenaare0659a62011-04-01 19:14:40 +0200859 if (fclose(fp))
DungSagaa2ffb432021-10-22 15:55:31 +0100860 perror_exit(2);
Bram Moolenaare0659a62011-04-01 19:14:40 +0200861 if (fclose(fpo))
DungSagaa2ffb432021-10-22 15:55:31 +0100862 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 return 0;
864}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200865
866/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */