blob: 42bcdaad70c69750bea8821bfe94aae641f10f7a [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
8 * consequtive lines of zeroes, as unix od does.
9 * -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...
38 * 18.07.96 gcc -Wall @ SunOS4 is now slient.
39 * 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
51 * 16.05.00 Improved MMS file and merege for VMS by Zoltan Arpadffy
52 *
53 * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
54 *
55 * Small changes made afterwards by Bram Moolenaar et al.
56 *
57 * Distribute freely and credit me,
58 * make money and share with me,
59 * lose money and don't ask me.
60 */
Bram Moolenaar362e1a32006-03-06 23:29:24 +000061
62/* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */
63#if _MSC_VER >= 1400
64# define _CRT_SECURE_NO_DEPRECATE
65# define _CRT_NONSTDC_NO_DEPRECATE
66#endif
67
Bram Moolenaar071d4272004-06-13 20:20:40 +000068#include <stdio.h>
69#ifdef VAXC
70# include <file.h>
71#else
72# include <fcntl.h>
73#endif
74#ifdef __TSC__
75# define MSDOS
76#endif
77#if !defined(OS2) && defined(__EMX__)
78# define OS2
79#endif
80#if defined(MSDOS) || defined(WIN32) || defined(OS2) || defined(__BORLANDC__)
81# include <io.h> /* for setmode() */
82#else
83# ifdef UNIX
84# include <unistd.h>
85# endif
86#endif
87#include <stdlib.h>
88#include <string.h> /* for strncmp() */
89#include <ctype.h> /* for isalnum() */
90#if __MWERKS__ && !defined(BEBOX)
91# include <unix.h> /* for fdopen() on MAC */
92#endif
93
94#if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno)
95/* Missing define and prototype grabbed from the BC 4.0 <stdio.h> */
96# define fileno(f) ((f)->fd)
97FILE _FAR *_Cdecl _FARFUNC fdopen(int __handle, char _FAR *__type);
98#endif
99
100
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
138char version[] = "xxd V1.10 27oct98 by Juergen Weigert";
139#ifdef WIN32
140char osver[] = " (Win32)";
141#else
142# ifdef DJGPP
143char osver[] = " (dos 32 bit)";
144# else
145# ifdef MSDOS
146char osver[] = " (dos 16 bit)";
147# else
148char osver[] = "";
149# endif
150# endif
151#endif
152
153#if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
154# define CYGWIN
155#endif
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000156#if defined(MSDOS) || defined(WIN32) || defined(OS2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157# define BIN_READ(yes) ((yes) ? "rb" : "rt")
158# define BIN_WRITE(yes) ((yes) ? "wb" : "wt")
159# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
160# define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT)
Bram Moolenaar12033fb2005-12-16 21:49:31 +0000161# define PATH_SEP '\\'
162#elif defined(CYGWIN)
163# define BIN_READ(yes) ((yes) ? "rb" : "rt")
164# define BIN_WRITE(yes) ((yes) ? "wb" : "w")
165# define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT)
166# define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp))
167# define PATH_SEP '/'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000168#else
169# ifdef VMS
170# define BIN_READ(dummy) "r"
171# define BIN_WRITE(dummy) "w"
172# define BIN_CREAT(dummy) O_CREAT
173# define BIN_ASSIGN(fp, dummy) fp
174# define PATH_SEP ']'
175# define FILE_SEP '.'
176# else
177# define BIN_READ(dummy) "r"
178# define BIN_WRITE(dummy) "w"
179# define BIN_CREAT(dummy) O_CREAT
180# define BIN_ASSIGN(fp, dummy) fp
181# define PATH_SEP '/'
182# endif
183#endif
184
185/* open has only to arguments on the Mac */
186#if __MWERKS__
187# define OPEN(name, mode, umask) open(name, mode)
188#else
189# define OPEN(name, mode, umask) open(name, mode, umask)
190#endif
191
192#ifdef AMIGA
193# define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l)
194#else
195# define STRNCMP(s1, s2, l) strncmp(s1, s2, l)
196#endif
197
198#ifndef __P
199# if defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(OS2) \
200 || defined(__BORLANDC__)
201# define __P(a) a
202# else
203# define __P(a) ()
204# endif
205#endif
206
207/* Let's collect some prototypes */
208/* CodeWarrior is really picky about missing prototypes */
209static void exit_with_usage __P((char *));
210static int huntype __P((FILE *, FILE *, FILE *, char *, int, int, long));
211static void xxdline __P((FILE *, char *, int));
212
213#define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
214#define COLS 256 /* change here, if you ever need more columns */
215#define LLEN (9 + (5*COLS-1)/2 + 2 + COLS)
216
217char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
218
219/* the different hextypes known by this program: */
220#define HEX_NORMAL 0
221#define HEX_POSTSCRIPT 1
222#define HEX_CINCLUDE 2
223#define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
224
225static void
226exit_with_usage(pname)
227char *pname;
228{
229 fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname);
230 fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname);
231 fprintf(stderr, "Options:\n");
232 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
233 fprintf(stderr, " -b binary digit dump (incompatible with -p,-i,-r). Default hex.\n");
234 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
235 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
236 fprintf(stderr, " -g number of octets per group in normal output. Default 2.\n");
237 fprintf(stderr, " -h print this summary.\n");
238 fprintf(stderr, " -i output in C include file style.\n");
239 fprintf(stderr, " -l len stop after <len> octets.\n");
240 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
241 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
242 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
243 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
244#ifdef TRY_SEEK
245 "[+][-]", "(or +: rel.) ");
246#else
247 "", "");
248#endif
249 fprintf(stderr, " -u use upper case hex letters.\n");
250 fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver);
251 exit(1);
252}
253
254/*
255 * Max. cols binary characters are decoded from the input stream per line.
256 * Two adjacent garbage characters after evaluated data delimit valid data.
257 * Everything up to the next newline is discarded.
258 *
259 * The name is historic and came from 'undo type opt h'.
260 */
261static int
262huntype(fpi, fpo, fperr, pname, cols, hextype, base_off)
263FILE *fpi, *fpo, *fperr;
264char *pname;
265int cols, hextype;
266long base_off;
267{
268 int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols;
269 long have_off = 0, want_off = 0;
270
271 rewind(fpi);
272
273 while ((c = getc(fpi)) != EOF)
274 {
275 if (c == '\r') /* Doze style input file? */
276 continue;
277
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000278#if 0 /* this doesn't work when there is normal text after the hex codes in
279 the last line that looks like hex */
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000280 if (c == ' ' || c == '\n' || c == '\t') /* allow multiple spaces */
281 continue;
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000282#endif
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000283
Bram Moolenaar071d4272004-06-13 20:20:40 +0000284 n3 = n2;
285 n2 = n1;
286
287 if (c >= '0' && c <= '9')
288 n1 = c - '0';
289 else if (c >= 'a' && c <= 'f')
290 n1 = c - 'a' + 10;
291 else if (c >= 'A' && c <= 'F')
292 n1 = c - 'A' + 10;
293 else
294 {
295 n1 = -1;
296 if (ign_garb)
297 continue;
298 }
299
300 ign_garb = 0;
301
302 if (p >= cols)
303 {
304 if (!hextype)
305 {
306 if (n1 < 0)
307 {
308 p = 0;
309 continue;
310 }
311 want_off = (want_off << 4) | n1;
312 continue;
313 }
314 else
315 p = 0;
316 }
317
318 if (base_off + want_off != have_off)
319 {
320 fflush(fpo);
321#ifdef TRY_SEEK
322 c = fseek(fpo, base_off + want_off - have_off, 1);
323 if (c >= 0)
324 have_off = base_off + want_off;
325#endif
326 if (base_off + want_off < have_off)
327 {
328 fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname);
329 return 5;
330 }
331 for (; have_off < base_off + want_off; have_off++)
332 putc(0, fpo);
333 }
334
335 if (n2 >= 0 && n1 >= 0)
336 {
337 putc((n2 << 4) | n1, fpo);
338 have_off++;
339 want_off++;
340 n1 = -1;
341 if ((++p >= cols) && !hextype)
342 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000343 /* skip rest of line as garbage */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000344 want_off = 0;
345 while ((c = getc(fpi)) != '\n' && c != EOF)
346 ;
347 ign_garb = 1;
348 }
349 }
350 else if (n1 < 0 && n2 < 0 && n3 < 0)
351 {
352 /* already stumbled into garbage, skip line, wait and see */
353 if (!hextype)
354 want_off = 0;
355 while ((c = getc(fpi)) != '\n' && c != EOF)
356 ;
357 ign_garb = 1;
358 }
359 }
360 fflush(fpo);
361#ifdef TRY_SEEK
362 fseek(fpo, 0L, 2);
363#endif
364 fclose(fpo);
365 fclose(fpi);
366 return 0;
367}
368
369/*
370 * Print line l. If nz is false, xxdline regards the line a line of
371 * zeroes. If there are three or more consecutive lines of zeroes,
372 * they are replaced by a single '*' character.
373 *
374 * If the output ends with more than two lines of zeroes, you
375 * should call xxdline again with l being the last line and nz
376 * negative. This ensures that the last line is shown even when
377 * it is all zeroes.
378 *
379 * If nz is always positive, lines are never suppressed.
380 */
381static void
382xxdline(fp, l, nz)
383FILE *fp;
384char *l;
385int nz;
386{
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)
400 fputs(z, fp);
401 if (zero_seen > 2)
402 fputs("*\n", fp);
403 }
404 if (nz >= 0 || zero_seen > 0)
405 fputs(l, fp);
406 if (nz)
407 zero_seen = 0;
408 }
409}
410
411/* This is an EBCDIC to ASCII conversion table */
412/* from a proposed BTL standard April 16, 1979 */
413static unsigned char etoa64[] =
414{
415 0040,0240,0241,0242,0243,0244,0245,0246,
416 0247,0250,0325,0056,0074,0050,0053,0174,
417 0046,0251,0252,0253,0254,0255,0256,0257,
418 0260,0261,0041,0044,0052,0051,0073,0176,
419 0055,0057,0262,0263,0264,0265,0266,0267,
420 0270,0271,0313,0054,0045,0137,0076,0077,
421 0272,0273,0274,0275,0276,0277,0300,0301,
422 0302,0140,0072,0043,0100,0047,0075,0042,
423 0303,0141,0142,0143,0144,0145,0146,0147,
424 0150,0151,0304,0305,0306,0307,0310,0311,
425 0312,0152,0153,0154,0155,0156,0157,0160,
426 0161,0162,0136,0314,0315,0316,0317,0320,
427 0321,0345,0163,0164,0165,0166,0167,0170,
428 0171,0172,0322,0323,0324,0133,0326,0327,
429 0330,0331,0332,0333,0334,0335,0336,0337,
430 0340,0341,0342,0343,0344,0135,0346,0347,
431 0173,0101,0102,0103,0104,0105,0106,0107,
432 0110,0111,0350,0351,0352,0353,0354,0355,
433 0175,0112,0113,0114,0115,0116,0117,0120,
434 0121,0122,0356,0357,0360,0361,0362,0363,
435 0134,0237,0123,0124,0125,0126,0127,0130,
436 0131,0132,0364,0365,0366,0367,0370,0371,
437 0060,0061,0062,0063,0064,0065,0066,0067,
438 0070,0071,0372,0373,0374,0375,0376,0377
439};
440
441int
442main(argc, argv)
443int argc;
444char *argv[];
445{
446 FILE *fp, *fpo;
447 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
448 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
449 int ebcdic = 0;
450 int octspergrp = -1; /* number of octets grouped in output */
451 int grplen; /* total chars per octet group */
452 long length = -1, n = 0, seekoff = 0;
453 char l[LLEN+1];
454 char *pname, *pp;
455
456#ifdef AMIGA
457 /* This program doesn't work when started from the Workbench */
458 if (argc == 0)
459 exit(1);
460#endif
461
462 pname = argv[0];
463 for (pp = pname; *pp; )
464 if (*pp++ == PATH_SEP)
465 pname = pp;
466#ifdef FILE_SEP
467 for (pp = pname; *pp; pp++)
468 if (*pp == FILE_SEP)
469 {
470 *pp = '\0';
471 break;
472 }
473#endif
474
475 while (argc >= 2)
476 {
477 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
478 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
479 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
480 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
481 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
482 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
483 else if (!STRNCMP(pp, "-r", 2)) revert++;
484 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
485 else if (!STRNCMP(pp, "-v", 2))
486 {
487 fprintf(stderr, "%s%s\n", version, osver);
488 exit(0);
489 }
490 else if (!STRNCMP(pp, "-c", 2))
491 {
492 if (pp[2] && STRNCMP("ols", pp + 2, 3))
493 cols = (int)strtol(pp + 2, NULL, 0);
494 else
495 {
496 if (!argv[2])
497 exit_with_usage(pname);
498 cols = (int)strtol(argv[2], NULL, 0);
499 argv++;
500 argc--;
501 }
502 }
503 else if (!STRNCMP(pp, "-g", 2))
504 {
505 if (pp[2] && STRNCMP("group", pp + 2, 5))
506 octspergrp = (int)strtol(pp + 2, NULL, 0);
507 else
508 {
509 if (!argv[2])
510 exit_with_usage(pname);
511 octspergrp = (int)strtol(argv[2], NULL, 0);
512 argv++;
513 argc--;
514 }
515 }
516 else if (!STRNCMP(pp, "-s", 2))
517 {
518 relseek = 0;
519 negseek = 0;
520 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
521 {
522#ifdef TRY_SEEK
523 if (pp[2] == '+')
524 relseek++;
525 if (pp[2+relseek] == '-')
526 negseek++;
527#endif
528 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
529 }
530 else
531 {
532 if (!argv[2])
533 exit_with_usage(pname);
534#ifdef TRY_SEEK
535 if (argv[2][0] == '+')
536 relseek++;
537 if (argv[2][relseek] == '-')
538 negseek++;
539#endif
540 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
541 argv++;
542 argc--;
543 }
544 }
545 else if (!STRNCMP(pp, "-l", 2))
546 {
547 if (pp[2] && STRNCMP("en", pp + 2, 2))
548 length = strtol(pp + 2, (char **)NULL, 0);
549 else
550 {
551 if (!argv[2])
552 exit_with_usage(pname);
553 length = strtol(argv[2], (char **)NULL, 0);
554 argv++;
555 argc--;
556 }
557 }
558 else if (!strcmp(pp, "--")) /* end of options */
559 {
560 argv++;
561 argc--;
562 break;
563 }
564 else if (pp[0] == '-' && pp[1]) /* unknown option */
565 exit_with_usage(pname);
566 else
567 break; /* not an option */
568
569 argv++; /* advance to next argument */
570 argc--;
571 }
572
573 if (!cols)
574 switch (hextype)
575 {
576 case HEX_POSTSCRIPT: cols = 30; break;
577 case HEX_CINCLUDE: cols = 12; break;
578 case HEX_BITS: cols = 6; break;
579 case HEX_NORMAL:
580 default: cols = 16; break;
581 }
582
583 if (octspergrp < 0)
584 switch (hextype)
585 {
586 case HEX_BITS: octspergrp = 1; break;
587 case HEX_NORMAL: octspergrp = 2; break;
588 case HEX_POSTSCRIPT:
589 case HEX_CINCLUDE:
590 default: octspergrp = 0; break;
591 }
592
593 if (cols < 1 || (!hextype && (cols > COLS)))
594 {
595 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
596 exit(1);
597 }
598
599 if (octspergrp < 1)
600 octspergrp = cols;
601
602 if (argc > 3)
603 exit_with_usage(pname);
604
605 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
606 BIN_ASSIGN(fp = stdin, !revert);
607 else
608 {
609 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
610 {
611 fprintf(stderr,"%s: ", pname);
612 perror(argv[1]);
613 return 2;
614 }
615 }
616
617 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
618 BIN_ASSIGN(fpo = stdout, revert);
619 else
620 {
621 int fd;
622 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
623
624 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
625 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
626 {
627 fprintf(stderr, "%s: ", pname);
628 perror(argv[2]);
629 return 3;
630 }
631 rewind(fpo);
632 }
633
634 if (revert)
635 {
636 if (hextype && (hextype != HEX_POSTSCRIPT))
637 {
638 fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname);
639 return -1;
640 }
641 return huntype(fp, fpo, stderr, pname, cols, hextype,
642 negseek ? -seekoff : seekoff);
643 }
644
645 if (seekoff || negseek || !relseek)
646 {
647#ifdef TRY_SEEK
648 if (relseek)
649 e = fseek(fp, negseek ? -seekoff : seekoff, 1);
650 else
651 e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
652 if (e < 0 && negseek)
653 {
654 fprintf(stderr, "%s: sorry cannot seek.\n", pname);
655 return 4;
656 }
657 if (e >= 0)
658 seekoff = ftell(fp);
659 else
660#endif
661 {
662 long s = seekoff;
663
664 while (s--)
665 (void)getc(fp);
666 }
667 }
668
669 if (hextype == HEX_CINCLUDE)
670 {
671 if (fp != stdin)
672 {
673 fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "");
674 for (e = 0; (c = argv[1][e]) != 0; e++)
675 putc(isalnum(c) ? c : '_', fpo);
676 fputs("[] = {\n", fpo);
677 }
678
679 p = 0;
680 while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
681 {
682 fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
683 (p % cols) ? ", " : ",\n "+2*!p, c);
684 p++;
685 }
686
687 if (p)
688 fputs("\n};\n"+3*(fp == stdin), fpo);
689
690 if (fp != stdin)
691 {
692 fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "");
693 for (e = 0; (c = argv[1][e]) != 0; e++)
694 putc(isalnum(c) ? c : '_', fpo);
695 fprintf(fpo, "_len = %d;\n", p);
696 }
697
698 fclose(fp);
699 fclose(fpo);
700 return 0;
701 }
702
703 if (hextype == HEX_POSTSCRIPT)
704 {
705 p = cols;
706 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
707 {
708 putchar(hexx[(e >> 4) & 0xf]);
709 putchar(hexx[(e ) & 0xf]);
710 n++;
711 if (!--p)
712 {
713 putchar('\n');
714 p = cols;
715 }
716 }
717 if (p < cols)
718 putchar('\n');
719 fclose(fp);
720 fclose(fpo);
721 return 0;
722 }
723
724 /* hextype: HEX_NORMAL or HEX_BITS */
725
726 if (hextype == HEX_NORMAL)
727 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
728 else /* hextype == HEX_BITS */
729 grplen = 8 * octspergrp + 1;
730
731 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
732 {
733 if (p == 0)
734 {
735 sprintf(l, "%07lx: ", n + seekoff);
736 for (c = 9; c < LLEN; l[c++] = ' ');
737 }
738 if (hextype == HEX_NORMAL)
739 {
740 l[c = (9 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
741 l[++c] = hexx[ e & 0xf];
742 }
743 else /* hextype == HEX_BITS */
744 {
745 int i;
746
747 c = (9 + (grplen * p) / octspergrp) - 1;
748 for (i = 7; i >= 0; i--)
749 l[++c] = (e & (1 << i)) ? '1' : '0';
750 }
751 if (ebcdic)
752 e = (e < 64) ? '.' : etoa64[e-64];
753 l[11 + (grplen * cols - 1)/octspergrp + p] =
754#ifdef __MVS__
755 (e >= 64)
756#else
757 (e > 31 && e < 127)
758#endif
759 ? e : '.';
760 if (e)
761 nonzero++;
762 n++;
763 if (++p == cols)
764 {
765 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
766 xxdline(fpo, l, autoskip ? nonzero : 1);
767 nonzero = 0;
768 p = 0;
769 }
770 }
771 if (p)
772 {
773 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
774 xxdline(fpo, l, 1);
775 }
776 else if (autoskip)
777 xxdline(fpo, l, -1); /* last chance to flush out supressed lines */
778
779 fclose(fp);
780 fclose(fpo);
781 return 0;
782}