blob: 0e056c93d7e2629ff286536aa107f3df8d6214ff [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.
Bram Moolenaar071d4272004-06-13 20:20:40 +000058 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020059 * (c) 1990-1998 by Juergen Weigert (jnweiger@gmail.com)
Bram Moolenaar071d4272004-06-13 20:20:40 +000060 *
Bram Moolenaar43fe3292015-08-04 17:29:07 +020061 * I hereby grant permission to distribute and use xxd
62 * under X11-MIT or GPL-2.0 (at the user's choice).
63 *
=?UTF-8?q?J=C3=BCrgen=20Weigert?=80b2ba32021-06-29 20:36:25 +020064 * Contributions by Bram Moolenaar et al.
Bram Moolenaar071d4272004-06-13 20:20:40 +000065 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000066
67/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
68#if _MSC_VER >= 1400
69# define _CRT_SECURE_NO_DEPRECATE
70# define _CRT_NONSTDC_NO_DEPRECATE
71#endif
Bram Moolenaar6ef8f9e2019-03-02 07:15:28 +010072#if !defined(CYGWIN) && defined(__CYGWIN__)
Bram Moolenaardc40a2b2009-06-16 16:29:10 +000073# define CYGWIN
74#endif
Bram Moolenaar362e1a32006-03-06 23:29:24 +000075
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000076#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
77# define _XOPEN_SOURCE 700 /* for fdopen() */
78#endif
79
Bram Moolenaar071d4272004-06-13 20:20:40 +000080#include <stdio.h>
81#ifdef VAXC
82# include <file.h>
83#else
84# include <fcntl.h>
85#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020086#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000087# include <io.h> /* for setmode() */
88#else
89# ifdef UNIX
90# include <unistd.h>
91# endif
92#endif
93#include <stdlib.h>
94#include <string.h> /* for strncmp() */
95#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010096#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000097#if __MWERKS__ && !defined(BEBOX)
98# include <unix.h> /* for fdopen() on MAC */
99#endif
100
Bram Moolenaar071d4272004-06-13 20:20:40 +0000101
102/* This corrects the problem of missing prototypes for certain functions
103 * in some GNU installations (e.g. SunOS 4.1.x).
104 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
105 */
106#if defined(__GNUC__) && defined(__STDC__)
107# ifndef __USE_FIXED_PROTOTYPES__
108# define __USE_FIXED_PROTOTYPES__
109# endif
110#endif
111
112#ifndef __USE_FIXED_PROTOTYPES__
113/*
114 * This is historic and works only if the compiler really has no prototypes:
115 *
116 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
117 * FILE is defined on OS 4.x, not on 5.x (Solaris).
118 * if __SVR4 is defined (some Solaris versions), don't include this.
119 */
120#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
121# define __P(a) a
122/* excerpt from my sun_stdlib.h */
123extern int fprintf __P((FILE *, char *, ...));
124extern int fputs __P((char *, FILE *));
125extern int _flsbuf __P((unsigned char, FILE *));
126extern int _filbuf __P((FILE *));
127extern int fflush __P((FILE *));
128extern int fclose __P((FILE *));
129extern int fseek __P((FILE *, long, int));
130extern int rewind __P((FILE *));
131
132extern void perror __P((char *));
133# endif
134#endif
135
136extern long int strtol();
137extern long int ftell();
138
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000139char version[] = "xxd 2022-01-14 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140#ifdef WIN32
141char osver[] = " (Win32)";
142#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144#endif
145
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200146#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000147# define BIN_READ(yes) ((yes) ? "rb" : "rt")
148# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
149# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
150# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000151# define PATH_SEP '\\'
152#elif defined(CYGWIN)
153# define BIN_READ(yes) ((yes) ? "rb" : "rt")
154# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
155# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
156# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
157# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000158#else
159# ifdef VMS
160# define BIN_READ(dummy) "r"
161# define BIN_WRITE(dummy) "w"
162# define BIN_CREAT(dummy) O_CREAT
163# define BIN_ASSIGN(fp, dummy) fp
164# define PATH_SEP ']'
165# define FILE_SEP '.'
166# else
167# define BIN_READ(dummy) "r"
168# define BIN_WRITE(dummy) "w"
169# define BIN_CREAT(dummy) O_CREAT
170# define BIN_ASSIGN(fp, dummy) fp
171# define PATH_SEP '/'
172# endif
173#endif
174
175/* open has only to arguments on the Mac */
176#if __MWERKS__
177# define OPEN(name, mode, umask) open(name, mode)
178#else
179# define OPEN(name, mode, umask) open(name, mode, umask)
180#endif
181
182#ifdef AMIGA
183# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
184#else
185# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
186#endif
187
188#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200189# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190# define __P(a) a
191# else
192# define __P(a) ()
193# endif
194#endif
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
197#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100198#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199
200char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
201
202/* the different hextypes known by this program: */
203#define HEX_NORMAL 0
204#define HEX_POSTSCRIPT 1
205#define HEX_CINCLUDE 2
206#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100207#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200209#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
210
Bram Moolenaare0659a62011-04-01 19:14:40 +0200211static char *pname;
212
213 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100214exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000215{
216 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
217 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
218 fprintf(stderr, "Options:\n");
219 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100220 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200221 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
223 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100224 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100225 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226 fprintf(stderr, " -h print this summary.\n");
227 fprintf(stderr, " -i output in C include file style.\n");
228 fprintf(stderr, " -l len stop after <len> octets.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100229 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000230 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
231 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
232 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200233 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000234 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
235#ifdef TRY_SEEK
236 "[+][-]", "(or +: rel.) ");
237#else
238 "", "");
239#endif
240 fprintf(stderr, " -u use upper case hex letters.\n");
241 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
242 exit(1);
243}
244
Bram Moolenaare0659a62011-04-01 19:14:40 +0200245 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100246perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200247{
248 fprintf(stderr, "%s: ", pname);
249 perror(NULL);
250 exit(ret);
251}
252
DungSagaa2ffb432021-10-22 15:55:31 +0100253 static void
254error_exit(int ret, char *msg)
255{
256 fprintf(stderr, "%s: %s\n", pname, msg);
257 exit(ret);
258}
259
DungSagad1d8a592021-11-26 13:59:27 +0000260 static int
261getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000262{
DungSagad1d8a592021-11-26 13:59:27 +0000263 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000264 if (c == EOF && ferror(fpi))
265 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000266 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000267}
268
269 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000270putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000271{
272 if (putc(c, fpo) == EOF)
273 perror_exit(3);
274}
275
276 static void
277fputs_or_die(char *s, FILE *fpo)
278{
279 if (fputs(s, fpo) == EOF)
280 perror_exit(3);
281}
282
DungSaga7e5503c2021-12-01 11:24:52 +0000283/* Use a macro to allow for different arguments. */
284#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000285
286 static void
287fclose_or_die(FILE *fpi, FILE *fpo)
288{
289 if (fclose(fpo) != 0)
290 perror_exit(3);
291 if (fclose(fpi) != 0)
292 perror_exit(2);
293}
294
Bram Moolenaar071d4272004-06-13 20:20:40 +0000295/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000296 * If "c" is a hex digit, return the value.
297 * Otherwise return -1.
298 */
299 static int
300parse_hex_digit(int c)
301{
302 return (c >= '0' && c <= '9') ? c - '0'
303 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
304 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
305 : -1;
306}
307
308/*
309 * Ignore text on "fpi" until end-of-line or end-of-file.
310 * Return the '\n' or EOF character.
311 * When an error is encountered exit with an error message.
312 */
313 static int
314skip_to_eol(FILE *fpi, int c)
315{
316 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000317 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000318 return c;
319}
320
321/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322 * Max. cols binary characters are decoded from the input stream per line.
323 * Two adjacent garbage characters after evaluated data delimit valid data.
324 * Everything up to the next newline is discarded.
325 *
326 * The name is historic and came from 'undo type opt h'.
327 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200328 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100329huntype(
330 FILE *fpi,
331 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100332 int cols,
333 int hextype,
334 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000335{
336 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
337 long have_off = 0, want_off = 0;
338
339 rewind(fpi);
340
341 while ((c = getc(fpi)) != EOF)
342 {
343 if (c == '\r') /* Doze style input file? */
344 continue;
345
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100346 /* Allow multiple spaces. This doesn't work when there is normal text
347 * after the hex codes in the last line that looks like hex, thus only
348 * use it for PostScript format. */
349 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000350 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000351
Bram Moolenaar071d4272004-06-13 20:20:40 +0000352 n3 = n2;
353 n2 = n1;
354
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000355 n1 = parse_hex_digit(c);
356 if (n1 == -1 && ign_garb)
357 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358
359 ign_garb = 0;
360
DungSaga375c35a2021-10-18 13:16:03 +0100361 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000362 {
DungSaga375c35a2021-10-18 13:16:03 +0100363 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 {
DungSaga375c35a2021-10-18 13:16:03 +0100365 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000366 continue;
367 }
DungSaga375c35a2021-10-18 13:16:03 +0100368 want_off = (want_off << 4) | n1;
369 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000370 }
371
372 if (base_off + want_off != have_off)
373 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200374 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100375 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000376#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000377 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378 have_off = base_off + want_off;
379#endif
380 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000381 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000382 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000383 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000384 }
385
386 if (n2 >= 0 && n1 >= 0)
387 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000388 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389 have_off++;
390 want_off++;
391 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100392 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000393 /* skip the rest of the line as garbage */
394 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000396 else if (n1 < 0 && n2 < 0 && n3 < 0)
397 /* already stumbled into garbage, skip line, wait and see */
398 c = skip_to_eol(fpi, c);
399
DungSaga47810462021-10-22 12:55:42 +0100400 if (c == '\n')
401 {
402 if (!hextype)
403 want_off = 0;
404 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405 ign_garb = 1;
406 }
407 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200408 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100409 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000410#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000411 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000412#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000413 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000414 return 0;
415}
416
417/*
418 * Print line l. If nz is false, xxdline regards the line a line of
419 * zeroes. If there are three or more consecutive lines of zeroes,
420 * they are replaced by a single '*' character.
421 *
422 * If the output ends with more than two lines of zeroes, you
423 * should call xxdline again with l being the last line and nz
424 * negative. This ensures that the last line is shown even when
425 * it is all zeroes.
426 *
427 * If nz is always positive, lines are never suppressed.
428 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200429 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100430xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000431{
432 static char z[LLEN+1];
433 static int zero_seen = 0;
434
435 if (!nz && zero_seen == 1)
436 strcpy(z, l);
437
438 if (nz || !zero_seen++)
439 {
440 if (nz)
441 {
442 if (nz < 0)
443 zero_seen--;
444 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000445 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000446 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000447 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000448 }
449 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000450 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000451 if (nz)
452 zero_seen = 0;
453 }
454}
455
456/* This is an EBCDIC to ASCII conversion table */
457/* from a proposed BTL standard April 16, 1979 */
458static unsigned char etoa64[] =
459{
460 0040,0240,0241,0242,0243,0244,0245,0246,
461 0247,0250,0325,0056,0074,0050,0053,0174,
462 0046,0251,0252,0253,0254,0255,0256,0257,
463 0260,0261,0041,0044,0052,0051,0073,0176,
464 0055,0057,0262,0263,0264,0265,0266,0267,
465 0270,0271,0313,0054,0045,0137,0076,0077,
466 0272,0273,0274,0275,0276,0277,0300,0301,
467 0302,0140,0072,0043,0100,0047,0075,0042,
468 0303,0141,0142,0143,0144,0145,0146,0147,
469 0150,0151,0304,0305,0306,0307,0310,0311,
470 0312,0152,0153,0154,0155,0156,0157,0160,
471 0161,0162,0136,0314,0315,0316,0317,0320,
472 0321,0345,0163,0164,0165,0166,0167,0170,
473 0171,0172,0322,0323,0324,0133,0326,0327,
474 0330,0331,0332,0333,0334,0335,0336,0337,
475 0340,0341,0342,0343,0344,0135,0346,0347,
476 0173,0101,0102,0103,0104,0105,0106,0107,
477 0110,0111,0350,0351,0352,0353,0354,0355,
478 0175,0112,0113,0114,0115,0116,0117,0120,
479 0121,0122,0356,0357,0360,0361,0362,0363,
480 0134,0237,0123,0124,0125,0126,0127,0130,
481 0131,0132,0364,0365,0366,0367,0370,0371,
482 0060,0061,0062,0063,0064,0065,0066,0067,
483 0070,0071,0372,0373,0374,0375,0376,0377
484};
485
Bram Moolenaare0659a62011-04-01 19:14:40 +0200486 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100487main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488{
489 FILE *fp, *fpo;
490 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000491 int cols = 0, colsgiven = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200492 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493 int ebcdic = 0;
494 int octspergrp = -1; /* number of octets grouped in output */
495 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100496 long length = -1, n = 0, seekoff = 0;
497 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200498 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200499 char *pp;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100500 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000501
502#ifdef AMIGA
503 /* This program doesn't work when started from the Workbench */
504 if (argc == 0)
505 exit(1);
506#endif
507
508 pname = argv[0];
509 for (pp = pname; *pp; )
510 if (*pp++ == PATH_SEP)
511 pname = pp;
512#ifdef FILE_SEP
513 for (pp = pname; *pp; pp++)
514 if (*pp == FILE_SEP)
515 {
516 *pp = '\0';
517 break;
518 }
519#endif
520
521 while (argc >= 2)
522 {
523 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
524 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
525 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100526 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
528 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
529 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200530 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200531 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 else if (!STRNCMP(pp, "-r", 2)) revert++;
533 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
534 else if (!STRNCMP(pp, "-v", 2))
535 {
536 fprintf(stderr, "%s%s\n", version, osver);
537 exit(0);
538 }
539 else if (!STRNCMP(pp, "-c", 2))
540 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100541 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200542 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100543 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000544 {
545 colsgiven = 1;
546 cols = (int)strtol(pp + 2, NULL, 0);
547 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000548 else
549 {
550 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200551 exit_with_usage();
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000552 colsgiven = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000553 cols = (int)strtol(argv[2], NULL, 0);
554 argv++;
555 argc--;
556 }
557 }
558 else if (!STRNCMP(pp, "-g", 2))
559 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100560 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561 octspergrp = (int)strtol(pp + 2, NULL, 0);
562 else
563 {
564 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200565 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 octspergrp = (int)strtol(argv[2], NULL, 0);
567 argv++;
568 argc--;
569 }
570 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100571 else if (!STRNCMP(pp, "-o", 2))
572 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100573 int reloffset = 0;
574 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100575 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100576 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100577 else
578 {
579 if (!argv[2])
580 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100581
582 if (argv[2][0] == '+')
583 reloffset++;
584 if (argv[2][reloffset] == '-')
585 negoffset++;
586
587 if (negoffset)
588 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
589 else
590 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
591
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100592 argv++;
593 argc--;
594 }
595 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000596 else if (!STRNCMP(pp, "-s", 2))
597 {
598 relseek = 0;
599 negseek = 0;
600 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
601 {
602#ifdef TRY_SEEK
603 if (pp[2] == '+')
604 relseek++;
605 if (pp[2+relseek] == '-')
606 negseek++;
607#endif
608 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
609 }
610 else
611 {
612 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200613 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000614#ifdef TRY_SEEK
615 if (argv[2][0] == '+')
616 relseek++;
617 if (argv[2][relseek] == '-')
618 negseek++;
619#endif
620 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
621 argv++;
622 argc--;
623 }
624 }
625 else if (!STRNCMP(pp, "-l", 2))
626 {
627 if (pp[2] && STRNCMP("en", pp + 2, 2))
628 length = strtol(pp + 2, (char **)NULL, 0);
629 else
630 {
631 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200632 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633 length = strtol(argv[2], (char **)NULL, 0);
634 argv++;
635 argc--;
636 }
637 }
638 else if (!strcmp(pp, "--")) /* end of options */
639 {
640 argv++;
641 argc--;
642 break;
643 }
644 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200645 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000646 else
647 break; /* not an option */
648
649 argv++; /* advance to next argument */
650 argc--;
651 }
652
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000653 if (!colsgiven || (!cols && hextype != HEX_POSTSCRIPT))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 switch (hextype)
655 {
656 case HEX_POSTSCRIPT: cols = 30; break;
657 case HEX_CINCLUDE: cols = 12; break;
658 case HEX_BITS: cols = 6; break;
659 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100660 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661 default: cols = 16; break;
662 }
663
664 if (octspergrp < 0)
665 switch (hextype)
666 {
667 case HEX_BITS: octspergrp = 1; break;
668 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100669 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 case HEX_POSTSCRIPT:
671 case HEX_CINCLUDE:
672 default: octspergrp = 0; break;
673 }
674
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000675 if ((hextype == HEX_POSTSCRIPT && cols < 0) ||
676 (hextype != HEX_POSTSCRIPT && cols < 1) ||
677 ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000678 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000679 {
680 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
681 exit(1);
682 }
683
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100684 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100686 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100687 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688
689 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200690 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691
692 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
693 BIN_ASSIGN(fp = stdin, !revert);
694 else
695 {
696 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
697 {
698 fprintf(stderr,"%s: ", pname);
699 perror(argv[1]);
700 return 2;
701 }
702 }
703
704 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
705 BIN_ASSIGN(fpo = stdout, revert);
706 else
707 {
708 int fd;
709 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
710
711 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
712 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
713 {
714 fprintf(stderr, "%s: ", pname);
715 perror(argv[2]);
716 return 3;
717 }
718 rewind(fpo);
719 }
720
721 if (revert)
722 {
723 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000724 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100725 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000726 negseek ? -seekoff : seekoff);
727 }
728
729 if (seekoff || negseek || !relseek)
730 {
731#ifdef TRY_SEEK
732 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000733 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000734 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000735 e = fseek(fp, negseek ? -seekoff : seekoff,
736 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000738 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 if (e >= 0)
740 seekoff = ftell(fp);
741 else
742#endif
743 {
744 long s = seekoff;
745
746 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000747 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200748 {
DungSaga7e5503c2021-12-01 11:24:52 +0000749 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200750 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000751 }
752 }
753
754 if (hextype == HEX_CINCLUDE)
755 {
756 if (fp != stdin)
757 {
DungSaga7e5503c2021-12-01 11:24:52 +0000758 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : ""));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000760 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
761 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000762 }
763
764 p = 0;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200765 c = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000766 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 {
DungSaga7e5503c2021-12-01 11:24:52 +0000768 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
769 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770 p++;
771 }
772
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000773 if (p)
774 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775
776 if (fp != stdin)
777 {
DungSagad1d8a592021-11-26 13:59:27 +0000778 fputs_or_die("};\n", fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000779 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : ""));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000781 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000782 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 }
784
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000785 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 return 0;
787 }
788
789 if (hextype == HEX_POSTSCRIPT)
790 {
791 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000792 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000794 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
795 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796 n++;
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000797 if (cols > 0 && !--p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000799 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 p = cols;
801 }
802 }
Erik Auerswaldc0a1d372022-01-14 11:58:48 +0000803 if (cols == 0 || p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000804 putc_or_die('\n', fpo);
805 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 return 0;
807 }
808
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100809 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100811 if (hextype != HEX_BITS)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
813 else /* hextype == HEX_BITS */
814 grplen = 8 * octspergrp + 1;
815
DungSagad1d8a592021-11-26 13:59:27 +0000816 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817 {
DungSaga48608b42021-11-24 11:18:07 +0000818 int x;
819
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 if (p == 0)
821 {
DungSaga581f41a2021-11-22 11:57:31 +0000822 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200823 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100824 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 }
DungSaga48608b42021-11-24 11:18:07 +0000826 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
827 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000828 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 {
DungSaga48608b42021-11-24 11:18:07 +0000830 l[c] = hexx[(e >> 4) & 0xf];
DungSaga581f41a2021-11-22 11:57:31 +0000831 l[++c] = hexx[e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 }
833 else /* hextype == HEX_BITS */
834 {
835 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000837 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100839 if (e)
840 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841 if (ebcdic)
842 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000843 /* When changing this update definition of LLEN above. */
DungSaga48608b42021-11-24 11:18:07 +0000844 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p;
845 l[c++] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846#ifdef __MVS__
847 (e >= 64)
848#else
849 (e > 31 && e < 127)
850#endif
851 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 n++;
853 if (++p == cols)
854 {
DungSaga48608b42021-11-24 11:18:07 +0000855 l[c] = '\n';
856 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 xxdline(fpo, l, autoskip ? nonzero : 1);
858 nonzero = 0;
859 p = 0;
860 }
861 }
862 if (p)
863 {
DungSaga48608b42021-11-24 11:18:07 +0000864 l[c] = '\n';
865 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 xxdline(fpo, l, 1);
867 }
868 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000869 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000871 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 return 0;
873}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200874
875/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */