blob: c32b9b8fbe2c2101b543acc6ce44f13503d2f678 [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
Yegappan Lakshmananef089f52021-12-31 17:33:47 +000075#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__)
76# define _XOPEN_SOURCE 700 /* for fdopen() */
77#endif
78
Bram Moolenaar071d4272004-06-13 20:20:40 +000079#include <stdio.h>
80#ifdef VAXC
81# include <file.h>
82#else
83# include <fcntl.h>
84#endif
Bram Moolenaareae1b912019-05-09 15:12:55 +020085#if defined(WIN32) || defined(CYGWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000086# include <io.h> /* for setmode() */
87#else
88# ifdef UNIX
89# include <unistd.h>
90# endif
91#endif
92#include <stdlib.h>
93#include <string.h> /* for strncmp() */
94#include <ctype.h> /* for isalnum() */
Bram Moolenaard8c56a02019-01-30 23:02:25 +010095#include <limits.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000096#if __MWERKS__ && !defined(BEBOX)
97# include <unix.h> /* for fdopen() on MAC */
98#endif
99
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100
101/* This corrects the problem of missing prototypes for certain functions
102 * in some GNU installations (e.g. SunOS 4.1.x).
103 * Darren Hiebert <darren@hmi.com> (sparc-sun-sunos4.1.3_U1/2.7.2.2)
104 */
105#if defined(__GNUC__) && defined(__STDC__)
106# ifndef __USE_FIXED_PROTOTYPES__
107# define __USE_FIXED_PROTOTYPES__
108# endif
109#endif
110
111#ifndef __USE_FIXED_PROTOTYPES__
112/*
113 * This is historic and works only if the compiler really has no prototypes:
114 *
115 * Include prototypes for Sun OS 4.x, when using an ANSI compiler.
116 * FILE is defined on OS 4.x, not on 5.x (Solaris).
117 * if __SVR4 is defined (some Solaris versions), don't include this.
118 */
119#if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__)
120# define __P(a) a
121/* excerpt from my sun_stdlib.h */
122extern int fprintf __P((FILE *, char *, ...));
123extern int fputs __P((char *, FILE *));
124extern int _flsbuf __P((unsigned char, FILE *));
125extern int _filbuf __P((FILE *));
126extern int fflush __P((FILE *));
127extern int fclose __P((FILE *));
128extern int fseek __P((FILE *, long, int));
129extern int rewind __P((FILE *));
130
131extern void perror __P((char *));
132# endif
133#endif
134
135extern long int strtol();
136extern long int ftell();
137
DungSaga47810462021-10-22 12:55:42 +0100138char version[] = "xxd 2021-10-22 by Juergen Weigert et al.";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139#ifdef WIN32
140char osver[] = " (Win32)";
141#else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142char osver[] = "";
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143#endif
144
Bram Moolenaara06ecab2016-07-16 14:47:36 +0200145#if defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146# define BIN_READ(yes) ((yes) ? "rb" : "rt")
147# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
148# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
149# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000150# define PATH_SEP '\\'
151#elif defined(CYGWIN)
152# define BIN_READ(yes) ((yes) ? "rb" : "rt")
153# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
154# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
155# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
156# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157#else
158# ifdef VMS
159# define BIN_READ(dummy) "r"
160# define BIN_WRITE(dummy) "w"
161# define BIN_CREAT(dummy) O_CREAT
162# define BIN_ASSIGN(fp, dummy) fp
163# define PATH_SEP ']'
164# define FILE_SEP '.'
165# else
166# define BIN_READ(dummy) "r"
167# define BIN_WRITE(dummy) "w"
168# define BIN_CREAT(dummy) O_CREAT
169# define BIN_ASSIGN(fp, dummy) fp
170# define PATH_SEP '/'
171# endif
172#endif
173
174/* open has only to arguments on the Mac */
175#if __MWERKS__
176# define OPEN(name, mode, umask) open(name, mode)
177#else
178# define OPEN(name, mode, umask) open(name, mode, umask)
179#endif
180
181#ifdef AMIGA
182# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
183#else
184# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
185#endif
186
187#ifndef __P
Bram Moolenaareae1b912019-05-09 15:12:55 +0200188# if defined(__STDC__) || defined(WIN32)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000189# define __P(a) a
190# else
191# define __P(a) ()
192# endif
193#endif
194
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
196#define COLS 256 /* change here, if you ever need more columns */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100197#define LLEN ((2*(int)sizeof(unsigned long)) + 4 + (9*COLS-1) + COLS + 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198
199char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
200
201/* the different hextypes known by this program: */
202#define HEX_NORMAL 0
203#define HEX_POSTSCRIPT 1
204#define HEX_CINCLUDE 2
205#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100206#define HEX_LITTLEENDIAN 4
Bram Moolenaar071d4272004-06-13 20:20:40 +0000207
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200208#define CONDITIONAL_CAPITALIZE(c) (capitalize ? toupper((int)c) : c)
209
Bram Moolenaare0659a62011-04-01 19:14:40 +0200210static char *pname;
211
212 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100213exit_with_usage(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214{
215 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
216 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
217 fprintf(stderr, "Options:\n");
218 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100219 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200220 fprintf(stderr, " -C capitalize variable names in C include file style (-i).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
222 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100223 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
Atsushi SUGAWARA34a36482021-10-17 16:09:08 +0100224 fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225 fprintf(stderr, " -h print this summary.\n");
226 fprintf(stderr, " -i output in C include file style.\n");
227 fprintf(stderr, " -l len stop after <len> octets.\n");
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100228 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000229 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
230 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
231 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
Bram Moolenaar363d6142020-05-30 20:50:25 +0200232 fprintf(stderr, " -d show offset in decimal instead of hex.\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
234#ifdef TRY_SEEK
235 "[+][-]", "(or +: rel.) ");
236#else
237 "", "");
238#endif
239 fprintf(stderr, " -u use upper case hex letters.\n");
240 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
241 exit(1);
242}
243
Bram Moolenaare0659a62011-04-01 19:14:40 +0200244 static void
DungSagaa2ffb432021-10-22 15:55:31 +0100245perror_exit(int ret)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200246{
247 fprintf(stderr, "%s: ", pname);
248 perror(NULL);
249 exit(ret);
250}
251
DungSagaa2ffb432021-10-22 15:55:31 +0100252 static void
253error_exit(int ret, char *msg)
254{
255 fprintf(stderr, "%s: %s\n", pname, msg);
256 exit(ret);
257}
258
DungSagad1d8a592021-11-26 13:59:27 +0000259 static int
260getc_or_die(FILE *fpi)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000261{
DungSagad1d8a592021-11-26 13:59:27 +0000262 int c = getc(fpi);
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000263 if (c == EOF && ferror(fpi))
264 perror_exit(2);
DungSagad1d8a592021-11-26 13:59:27 +0000265 return c;
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000266}
267
268 static void
Bram Moolenaar71b36202021-11-25 13:26:19 +0000269putc_or_die(int c, FILE *fpo)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000270{
271 if (putc(c, fpo) == EOF)
272 perror_exit(3);
273}
274
275 static void
276fputs_or_die(char *s, FILE *fpo)
277{
278 if (fputs(s, fpo) == EOF)
279 perror_exit(3);
280}
281
DungSaga7e5503c2021-12-01 11:24:52 +0000282/* Use a macro to allow for different arguments. */
283#define FPRINTF_OR_DIE(args) if (fprintf args < 0) perror_exit(3)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000284
285 static void
286fclose_or_die(FILE *fpi, FILE *fpo)
287{
288 if (fclose(fpo) != 0)
289 perror_exit(3);
290 if (fclose(fpi) != 0)
291 perror_exit(2);
292}
293
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294/*
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000295 * If "c" is a hex digit, return the value.
296 * Otherwise return -1.
297 */
298 static int
299parse_hex_digit(int c)
300{
301 return (c >= '0' && c <= '9') ? c - '0'
302 : (c >= 'a' && c <= 'f') ? c - 'a' + 10
303 : (c >= 'A' && c <= 'F') ? c - 'A' + 10
304 : -1;
305}
306
307/*
308 * Ignore text on "fpi" until end-of-line or end-of-file.
309 * Return the '\n' or EOF character.
310 * When an error is encountered exit with an error message.
311 */
312 static int
313skip_to_eol(FILE *fpi, int c)
314{
315 while (c != '\n' && c != EOF)
DungSagad1d8a592021-11-26 13:59:27 +0000316 c = getc_or_die(fpi);
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000317 return c;
318}
319
320/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000321 * Max. cols binary characters are decoded from the input stream per line.
322 * Two adjacent garbage characters after evaluated data delimit valid data.
323 * Everything up to the next newline is discarded.
324 *
325 * The name is historic and came from 'undo type opt h'.
326 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200327 static int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100328huntype(
329 FILE *fpi,
330 FILE *fpo,
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100331 int cols,
332 int hextype,
333 long base_off)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000334{
335 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
336 long have_off = 0, want_off = 0;
337
338 rewind(fpi);
339
340 while ((c = getc(fpi)) != EOF)
341 {
342 if (c == '\r') /* Doze style input file? */
343 continue;
344
Bram Moolenaar8a33e742010-02-17 18:28:41 +0100345 /* Allow multiple spaces. This doesn't work when there is normal text
346 * after the hex codes in the last line that looks like hex, thus only
347 * use it for PostScript format. */
348 if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t'))
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000349 continue;
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000350
Bram Moolenaar071d4272004-06-13 20:20:40 +0000351 n3 = n2;
352 n2 = n1;
353
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000354 n1 = parse_hex_digit(c);
355 if (n1 == -1 && ign_garb)
356 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000357
358 ign_garb = 0;
359
DungSaga375c35a2021-10-18 13:16:03 +0100360 if (!hextype && (p >= cols))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361 {
DungSaga375c35a2021-10-18 13:16:03 +0100362 if (n1 < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000363 {
DungSaga375c35a2021-10-18 13:16:03 +0100364 p = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000365 continue;
366 }
DungSaga375c35a2021-10-18 13:16:03 +0100367 want_off = (want_off << 4) | n1;
368 continue;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000369 }
370
371 if (base_off + want_off != have_off)
372 {
Bram Moolenaare0659a62011-04-01 19:14:40 +0200373 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100374 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000375#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000376 if (fseek(fpo, base_off + want_off - have_off, SEEK_CUR) >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377 have_off = base_off + want_off;
378#endif
379 if (base_off + want_off < have_off)
DungSaga7e5503c2021-12-01 11:24:52 +0000380 error_exit(5, "Sorry, cannot seek backwards.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000381 for (; have_off < base_off + want_off; have_off++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000382 putc_or_die(0, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383 }
384
385 if (n2 >= 0 && n1 >= 0)
386 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000387 putc_or_die((n2 << 4) | n1, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 have_off++;
389 want_off++;
390 n1 = -1;
DungSaga375c35a2021-10-18 13:16:03 +0100391 if (!hextype && (++p >= cols))
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000392 /* skip the rest of the line as garbage */
393 c = skip_to_eol(fpi, c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000394 }
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000395 else if (n1 < 0 && n2 < 0 && n3 < 0)
396 /* already stumbled into garbage, skip line, wait and see */
397 c = skip_to_eol(fpi, c);
398
DungSaga47810462021-10-22 12:55:42 +0100399 if (c == '\n')
400 {
401 if (!hextype)
402 want_off = 0;
403 p = cols;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404 ign_garb = 1;
405 }
406 }
Bram Moolenaare0659a62011-04-01 19:14:40 +0200407 if (fflush(fpo) != 0)
DungSagaa2ffb432021-10-22 15:55:31 +0100408 perror_exit(3);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000409#ifdef TRY_SEEK
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000410 fseek(fpo, 0L, SEEK_END);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000411#endif
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000412 fclose_or_die(fpi, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000413 return 0;
414}
415
416/*
417 * Print line l. If nz is false, xxdline regards the line a line of
418 * zeroes. If there are three or more consecutive lines of zeroes,
419 * they are replaced by a single '*' character.
420 *
421 * If the output ends with more than two lines of zeroes, you
422 * should call xxdline again with l being the last line and nz
423 * negative. This ensures that the last line is shown even when
424 * it is all zeroes.
425 *
426 * If nz is always positive, lines are never suppressed.
427 */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200428 static void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100429xxdline(FILE *fp, char *l, int nz)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430{
431 static char z[LLEN+1];
432 static int zero_seen = 0;
433
434 if (!nz && zero_seen == 1)
435 strcpy(z, l);
436
437 if (nz || !zero_seen++)
438 {
439 if (nz)
440 {
441 if (nz < 0)
442 zero_seen--;
443 if (zero_seen == 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000444 fputs_or_die(z, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000445 if (zero_seen > 2)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000446 fputs_or_die("*\n", fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000447 }
448 if (nz >= 0 || zero_seen > 0)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000449 fputs_or_die(l, fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000450 if (nz)
451 zero_seen = 0;
452 }
453}
454
455/* This is an EBCDIC to ASCII conversion table */
456/* from a proposed BTL standard April 16, 1979 */
457static unsigned char etoa64[] =
458{
459 0040,0240,0241,0242,0243,0244,0245,0246,
460 0247,0250,0325,0056,0074,0050,0053,0174,
461 0046,0251,0252,0253,0254,0255,0256,0257,
462 0260,0261,0041,0044,0052,0051,0073,0176,
463 0055,0057,0262,0263,0264,0265,0266,0267,
464 0270,0271,0313,0054,0045,0137,0076,0077,
465 0272,0273,0274,0275,0276,0277,0300,0301,
466 0302,0140,0072,0043,0100,0047,0075,0042,
467 0303,0141,0142,0143,0144,0145,0146,0147,
468 0150,0151,0304,0305,0306,0307,0310,0311,
469 0312,0152,0153,0154,0155,0156,0157,0160,
470 0161,0162,0136,0314,0315,0316,0317,0320,
471 0321,0345,0163,0164,0165,0166,0167,0170,
472 0171,0172,0322,0323,0324,0133,0326,0327,
473 0330,0331,0332,0333,0334,0335,0336,0337,
474 0340,0341,0342,0343,0344,0135,0346,0347,
475 0173,0101,0102,0103,0104,0105,0106,0107,
476 0110,0111,0350,0351,0352,0353,0354,0355,
477 0175,0112,0113,0114,0115,0116,0117,0120,
478 0121,0122,0356,0357,0360,0361,0362,0363,
479 0134,0237,0123,0124,0125,0126,0127,0130,
480 0131,0132,0364,0365,0366,0367,0370,0371,
481 0060,0061,0062,0063,0064,0065,0066,0067,
482 0070,0071,0372,0373,0374,0375,0376,0377
483};
484
Bram Moolenaare0659a62011-04-01 19:14:40 +0200485 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100486main(int argc, char *argv[])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000487{
488 FILE *fp, *fpo;
489 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200490 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
491 int capitalize = 0, decimal_offset = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492 int ebcdic = 0;
493 int octspergrp = -1; /* number of octets grouped in output */
494 int grplen; /* total chars per octet group */
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100495 long length = -1, n = 0, seekoff = 0;
496 unsigned long displayoff = 0;
Bram Moolenaard9462e32011-04-11 21:35:11 +0200497 static char l[LLEN+1]; /* static because it may be too big for stack */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200498 char *pp;
Bram Moolenaaraf703582019-01-31 11:00:42 +0100499 int addrlen = 9;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000500
501#ifdef AMIGA
502 /* This program doesn't work when started from the Workbench */
503 if (argc == 0)
504 exit(1);
505#endif
506
507 pname = argv[0];
508 for (pp = pname; *pp; )
509 if (*pp++ == PATH_SEP)
510 pname = pp;
511#ifdef FILE_SEP
512 for (pp = pname; *pp; pp++)
513 if (*pp == FILE_SEP)
514 {
515 *pp = '\0';
516 break;
517 }
518#endif
519
520 while (argc >= 2)
521 {
522 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
523 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
524 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100525 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
527 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
528 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
Bram Moolenaar8b31a6f2018-04-03 12:17:25 +0200529 else if (!STRNCMP(pp, "-C", 2)) capitalize = 1;
Bram Moolenaar363d6142020-05-30 20:50:25 +0200530 else if (!STRNCMP(pp, "-d", 2)) decimal_offset = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531 else if (!STRNCMP(pp, "-r", 2)) revert++;
532 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
533 else if (!STRNCMP(pp, "-v", 2))
534 {
535 fprintf(stderr, "%s%s\n", version, osver);
536 exit(0);
537 }
538 else if (!STRNCMP(pp, "-c", 2))
539 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100540 if (pp[2] && !STRNCMP("apitalize", pp + 2, 9))
Bram Moolenaar79cf7c02018-04-03 14:21:16 +0200541 capitalize = 1;
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100542 else if (pp[2] && STRNCMP("ols", pp + 2, 3))
543 cols = (int)strtol(pp + 2, NULL, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000544 else
545 {
546 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200547 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000548 cols = (int)strtol(argv[2], NULL, 0);
549 argv++;
550 argc--;
551 }
552 }
553 else if (!STRNCMP(pp, "-g", 2))
554 {
Bram Moolenaar970f5d32019-01-25 21:52:17 +0100555 if (pp[2] && STRNCMP("roup", pp + 2, 4))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000556 octspergrp = (int)strtol(pp + 2, NULL, 0);
557 else
558 {
559 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200560 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561 octspergrp = (int)strtol(argv[2], NULL, 0);
562 argv++;
563 argc--;
564 }
565 }
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100566 else if (!STRNCMP(pp, "-o", 2))
567 {
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100568 int reloffset = 0;
569 int negoffset = 0;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100570 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100571 displayoff = strtoul(pp + 2, NULL, 0);
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100572 else
573 {
574 if (!argv[2])
575 exit_with_usage();
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100576
577 if (argv[2][0] == '+')
578 reloffset++;
579 if (argv[2][reloffset] == '-')
580 negoffset++;
581
582 if (negoffset)
583 displayoff = ULONG_MAX - strtoul(argv[2] + reloffset+negoffset, NULL, 0) + 1;
584 else
585 displayoff = strtoul(argv[2] + reloffset+negoffset, NULL, 0);
586
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100587 argv++;
588 argc--;
589 }
590 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591 else if (!STRNCMP(pp, "-s", 2))
592 {
593 relseek = 0;
594 negseek = 0;
595 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
596 {
597#ifdef TRY_SEEK
598 if (pp[2] == '+')
599 relseek++;
600 if (pp[2+relseek] == '-')
601 negseek++;
602#endif
603 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
604 }
605 else
606 {
607 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200608 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609#ifdef TRY_SEEK
610 if (argv[2][0] == '+')
611 relseek++;
612 if (argv[2][relseek] == '-')
613 negseek++;
614#endif
615 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
616 argv++;
617 argc--;
618 }
619 }
620 else if (!STRNCMP(pp, "-l", 2))
621 {
622 if (pp[2] && STRNCMP("en", pp + 2, 2))
623 length = strtol(pp + 2, (char **)NULL, 0);
624 else
625 {
626 if (!argv[2])
Bram Moolenaare0659a62011-04-01 19:14:40 +0200627 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628 length = strtol(argv[2], (char **)NULL, 0);
629 argv++;
630 argc--;
631 }
632 }
633 else if (!strcmp(pp, "--")) /* end of options */
634 {
635 argv++;
636 argc--;
637 break;
638 }
639 else if (pp[0] == '-' && pp[1]) /* unknown option */
Bram Moolenaare0659a62011-04-01 19:14:40 +0200640 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000641 else
642 break; /* not an option */
643
644 argv++; /* advance to next argument */
645 argc--;
646 }
647
648 if (!cols)
649 switch (hextype)
650 {
651 case HEX_POSTSCRIPT: cols = 30; break;
652 case HEX_CINCLUDE: cols = 12; break;
653 case HEX_BITS: cols = 6; break;
654 case HEX_NORMAL:
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100655 case HEX_LITTLEENDIAN:
Bram Moolenaar071d4272004-06-13 20:20:40 +0000656 default: cols = 16; break;
657 }
658
659 if (octspergrp < 0)
660 switch (hextype)
661 {
662 case HEX_BITS: octspergrp = 1; break;
663 case HEX_NORMAL: octspergrp = 2; break;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100664 case HEX_LITTLEENDIAN: octspergrp = 4; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 case HEX_POSTSCRIPT:
666 case HEX_CINCLUDE:
667 default: octspergrp = 0; break;
668 }
669
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100670 if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000671 && (cols > COLS)))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 {
673 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
674 exit(1);
675 }
676
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100677 if (octspergrp < 1 || octspergrp > cols)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 octspergrp = cols;
Bram Moolenaar4dcdf292015-03-05 17:51:15 +0100679 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
DungSagaa2ffb432021-10-22 15:55:31 +0100680 error_exit(1, "number of octets per group must be a power of 2 with -e.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681
682 if (argc > 3)
Bram Moolenaare0659a62011-04-01 19:14:40 +0200683 exit_with_usage();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000684
685 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
686 BIN_ASSIGN(fp = stdin, !revert);
687 else
688 {
689 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
690 {
691 fprintf(stderr,"%s: ", pname);
692 perror(argv[1]);
693 return 2;
694 }
695 }
696
697 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
698 BIN_ASSIGN(fpo = stdout, revert);
699 else
700 {
701 int fd;
702 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
703
704 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
705 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
706 {
707 fprintf(stderr, "%s: ", pname);
708 perror(argv[2]);
709 return 3;
710 }
711 rewind(fpo);
712 }
713
714 if (revert)
715 {
716 if (hextype && (hextype != HEX_POSTSCRIPT))
DungSaga7e5503c2021-12-01 11:24:52 +0000717 error_exit(-1, "Sorry, cannot revert this type of hexdump");
DungSagaa2ffb432021-10-22 15:55:31 +0100718 return huntype(fp, fpo, cols, hextype,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719 negseek ? -seekoff : seekoff);
720 }
721
722 if (seekoff || negseek || !relseek)
723 {
724#ifdef TRY_SEEK
725 if (relseek)
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000726 e = fseek(fp, negseek ? -seekoff : seekoff, SEEK_CUR);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727 else
Bram Moolenaar786e05b2021-11-14 13:46:05 +0000728 e = fseek(fp, negseek ? -seekoff : seekoff,
729 negseek ? SEEK_END : SEEK_SET);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730 if (e < 0 && negseek)
DungSaga7e5503c2021-12-01 11:24:52 +0000731 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000732 if (e >= 0)
733 seekoff = ftell(fp);
734 else
735#endif
736 {
737 long s = seekoff;
738
739 while (s--)
DungSaga7e5503c2021-12-01 11:24:52 +0000740 if (getc_or_die(fp) == EOF)
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200741 {
DungSaga7e5503c2021-12-01 11:24:52 +0000742 error_exit(4, "Sorry, cannot seek.");
Bram Moolenaar10d77eb2011-04-02 14:44:55 +0200743 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000744 }
745 }
746
747 if (hextype == HEX_CINCLUDE)
748 {
749 if (fp != stdin)
750 {
DungSaga7e5503c2021-12-01 11:24:52 +0000751 FPRINTF_OR_DIE((fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : ""));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000753 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
754 fputs_or_die("[] = {\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755 }
756
757 p = 0;
Bram Moolenaare0659a62011-04-01 19:14:40 +0200758 c = 0;
DungSagad1d8a592021-11-26 13:59:27 +0000759 while ((length < 0 || p < length) && (c = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 {
DungSaga7e5503c2021-12-01 11:24:52 +0000761 FPRINTF_OR_DIE((fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
762 (p % cols) ? ", " : (!p ? " " : ",\n "), c));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000763 p++;
764 }
765
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000766 if (p)
767 fputs_or_die("\n", fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768
769 if (fp != stdin)
770 {
DungSagad1d8a592021-11-26 13:59:27 +0000771 fputs_or_die("};\n", fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000772 FPRINTF_OR_DIE((fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : ""));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773 for (e = 0; (c = argv[1][e]) != 0; e++)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000774 putc_or_die(isalnum(c) ? CONDITIONAL_CAPITALIZE(c) : '_', fpo);
DungSaga7e5503c2021-12-01 11:24:52 +0000775 FPRINTF_OR_DIE((fpo, "_%s = %d;\n", capitalize ? "LEN" : "len", p));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000776 }
777
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000778 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 return 0;
780 }
781
782 if (hextype == HEX_POSTSCRIPT)
783 {
784 p = cols;
DungSagad1d8a592021-11-26 13:59:27 +0000785 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000787 putc_or_die(hexx[(e >> 4) & 0xf], fpo);
788 putc_or_die(hexx[e & 0xf], fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 n++;
790 if (!--p)
791 {
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000792 putc_or_die('\n', fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 p = cols;
794 }
795 }
796 if (p < cols)
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000797 putc_or_die('\n', fpo);
798 fclose_or_die(fp, fpo);
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
DungSagad1d8a592021-11-26 13:59:27 +0000809 while ((length < 0 || n < length) && (e = getc_or_die(fp)) != EOF)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 {
DungSaga48608b42021-11-24 11:18:07 +0000811 int x;
812
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 if (p == 0)
814 {
DungSaga581f41a2021-11-22 11:57:31 +0000815 addrlen = sprintf(l, decimal_offset ? "%08ld:" : "%08lx:",
Bram Moolenaar363d6142020-05-30 20:50:25 +0200816 ((unsigned long)(n + seekoff + displayoff)));
Bram Moolenaard8c56a02019-01-30 23:02:25 +0100817 for (c = addrlen; c < LLEN; l[c++] = ' ');
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 }
DungSaga48608b42021-11-24 11:18:07 +0000819 x = hextype == HEX_LITTLEENDIAN ? p ^ (octspergrp-1) : p;
820 c = addrlen + 1 + (grplen * x) / octspergrp;
DungSaga581f41a2021-11-22 11:57:31 +0000821 if (hextype == HEX_NORMAL || hextype == HEX_LITTLEENDIAN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822 {
DungSaga48608b42021-11-24 11:18:07 +0000823 l[c] = hexx[(e >> 4) & 0xf];
DungSaga581f41a2021-11-22 11:57:31 +0000824 l[++c] = hexx[e & 0xf];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 }
826 else /* hextype == HEX_BITS */
827 {
828 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 for (i = 7; i >= 0; i--)
DungSaga48608b42021-11-24 11:18:07 +0000830 l[c++] = (e & (1 << i)) ? '1' : '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831 }
Bram Moolenaar085346f2018-02-24 18:30:55 +0100832 if (e)
833 nonzero++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 if (ebcdic)
835 e = (e < 64) ? '.' : etoa64[e-64];
Bram Moolenaare9c3bcd2007-12-03 20:32:43 +0000836 /* When changing this update definition of LLEN above. */
DungSaga48608b42021-11-24 11:18:07 +0000837 c = addrlen + 3 + (grplen * cols - 1)/octspergrp + p;
838 l[c++] =
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839#ifdef __MVS__
840 (e >= 64)
841#else
842 (e > 31 && e < 127)
843#endif
844 ? e : '.';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 n++;
846 if (++p == cols)
847 {
DungSaga48608b42021-11-24 11:18:07 +0000848 l[c] = '\n';
849 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000850 xxdline(fpo, l, autoskip ? nonzero : 1);
851 nonzero = 0;
852 p = 0;
853 }
854 }
855 if (p)
856 {
DungSaga48608b42021-11-24 11:18:07 +0000857 l[c] = '\n';
858 l[++c] = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 xxdline(fpo, l, 1);
860 }
861 else if (autoskip)
Bram Moolenaar82038d72007-05-10 17:15:45 +0000862 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863
Bram Moolenaar8af87bd2021-11-25 11:16:50 +0000864 fclose_or_die(fp, fpo);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 return 0;
866}
Bram Moolenaare0659a62011-04-01 19:14:40 +0200867
868/* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */