blob: f57d78634d3e5f89668f183ffefa62f25714e941 [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 Moolenaar899dddf2006-03-26 21:06:50 +0000278 if (c == ' ' || c == '\n' || c == '\t') /* allow multiple spaces */
279 continue;
280
Bram Moolenaar071d4272004-06-13 20:20:40 +0000281 n3 = n2;
282 n2 = n1;
283
284 if (c >= '0' && c <= '9')
285 n1 = c - '0';
286 else if (c >= 'a' && c <= 'f')
287 n1 = c - 'a' + 10;
288 else if (c >= 'A' && c <= 'F')
289 n1 = c - 'A' + 10;
290 else
291 {
292 n1 = -1;
293 if (ign_garb)
294 continue;
295 }
296
297 ign_garb = 0;
298
299 if (p >= cols)
300 {
301 if (!hextype)
302 {
303 if (n1 < 0)
304 {
305 p = 0;
306 continue;
307 }
308 want_off = (want_off << 4) | n1;
309 continue;
310 }
311 else
312 p = 0;
313 }
314
315 if (base_off + want_off != have_off)
316 {
317 fflush(fpo);
318#ifdef TRY_SEEK
319 c = fseek(fpo, base_off + want_off - have_off, 1);
320 if (c >= 0)
321 have_off = base_off + want_off;
322#endif
323 if (base_off + want_off < have_off)
324 {
325 fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname);
326 return 5;
327 }
328 for (; have_off < base_off + want_off; have_off++)
329 putc(0, fpo);
330 }
331
332 if (n2 >= 0 && n1 >= 0)
333 {
334 putc((n2 << 4) | n1, fpo);
335 have_off++;
336 want_off++;
337 n1 = -1;
338 if ((++p >= cols) && !hextype)
339 {
Bram Moolenaar899dddf2006-03-26 21:06:50 +0000340 /* skip rest of line as garbage */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000341 want_off = 0;
342 while ((c = getc(fpi)) != '\n' && c != EOF)
343 ;
344 ign_garb = 1;
345 }
346 }
347 else if (n1 < 0 && n2 < 0 && n3 < 0)
348 {
349 /* already stumbled into garbage, skip line, wait and see */
350 if (!hextype)
351 want_off = 0;
352 while ((c = getc(fpi)) != '\n' && c != EOF)
353 ;
354 ign_garb = 1;
355 }
356 }
357 fflush(fpo);
358#ifdef TRY_SEEK
359 fseek(fpo, 0L, 2);
360#endif
361 fclose(fpo);
362 fclose(fpi);
363 return 0;
364}
365
366/*
367 * Print line l. If nz is false, xxdline regards the line a line of
368 * zeroes. If there are three or more consecutive lines of zeroes,
369 * they are replaced by a single '*' character.
370 *
371 * If the output ends with more than two lines of zeroes, you
372 * should call xxdline again with l being the last line and nz
373 * negative. This ensures that the last line is shown even when
374 * it is all zeroes.
375 *
376 * If nz is always positive, lines are never suppressed.
377 */
378static void
379xxdline(fp, l, nz)
380FILE *fp;
381char *l;
382int nz;
383{
384 static char z[LLEN+1];
385 static int zero_seen = 0;
386
387 if (!nz && zero_seen == 1)
388 strcpy(z, l);
389
390 if (nz || !zero_seen++)
391 {
392 if (nz)
393 {
394 if (nz < 0)
395 zero_seen--;
396 if (zero_seen == 2)
397 fputs(z, fp);
398 if (zero_seen > 2)
399 fputs("*\n", fp);
400 }
401 if (nz >= 0 || zero_seen > 0)
402 fputs(l, fp);
403 if (nz)
404 zero_seen = 0;
405 }
406}
407
408/* This is an EBCDIC to ASCII conversion table */
409/* from a proposed BTL standard April 16, 1979 */
410static unsigned char etoa64[] =
411{
412 0040,0240,0241,0242,0243,0244,0245,0246,
413 0247,0250,0325,0056,0074,0050,0053,0174,
414 0046,0251,0252,0253,0254,0255,0256,0257,
415 0260,0261,0041,0044,0052,0051,0073,0176,
416 0055,0057,0262,0263,0264,0265,0266,0267,
417 0270,0271,0313,0054,0045,0137,0076,0077,
418 0272,0273,0274,0275,0276,0277,0300,0301,
419 0302,0140,0072,0043,0100,0047,0075,0042,
420 0303,0141,0142,0143,0144,0145,0146,0147,
421 0150,0151,0304,0305,0306,0307,0310,0311,
422 0312,0152,0153,0154,0155,0156,0157,0160,
423 0161,0162,0136,0314,0315,0316,0317,0320,
424 0321,0345,0163,0164,0165,0166,0167,0170,
425 0171,0172,0322,0323,0324,0133,0326,0327,
426 0330,0331,0332,0333,0334,0335,0336,0337,
427 0340,0341,0342,0343,0344,0135,0346,0347,
428 0173,0101,0102,0103,0104,0105,0106,0107,
429 0110,0111,0350,0351,0352,0353,0354,0355,
430 0175,0112,0113,0114,0115,0116,0117,0120,
431 0121,0122,0356,0357,0360,0361,0362,0363,
432 0134,0237,0123,0124,0125,0126,0127,0130,
433 0131,0132,0364,0365,0366,0367,0370,0371,
434 0060,0061,0062,0063,0064,0065,0066,0067,
435 0070,0071,0372,0373,0374,0375,0376,0377
436};
437
438int
439main(argc, argv)
440int argc;
441char *argv[];
442{
443 FILE *fp, *fpo;
444 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
445 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
446 int ebcdic = 0;
447 int octspergrp = -1; /* number of octets grouped in output */
448 int grplen; /* total chars per octet group */
449 long length = -1, n = 0, seekoff = 0;
450 char l[LLEN+1];
451 char *pname, *pp;
452
453#ifdef AMIGA
454 /* This program doesn't work when started from the Workbench */
455 if (argc == 0)
456 exit(1);
457#endif
458
459 pname = argv[0];
460 for (pp = pname; *pp; )
461 if (*pp++ == PATH_SEP)
462 pname = pp;
463#ifdef FILE_SEP
464 for (pp = pname; *pp; pp++)
465 if (*pp == FILE_SEP)
466 {
467 *pp = '\0';
468 break;
469 }
470#endif
471
472 while (argc >= 2)
473 {
474 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
475 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
476 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
477 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
478 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
479 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
480 else if (!STRNCMP(pp, "-r", 2)) revert++;
481 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
482 else if (!STRNCMP(pp, "-v", 2))
483 {
484 fprintf(stderr, "%s%s\n", version, osver);
485 exit(0);
486 }
487 else if (!STRNCMP(pp, "-c", 2))
488 {
489 if (pp[2] && STRNCMP("ols", pp + 2, 3))
490 cols = (int)strtol(pp + 2, NULL, 0);
491 else
492 {
493 if (!argv[2])
494 exit_with_usage(pname);
495 cols = (int)strtol(argv[2], NULL, 0);
496 argv++;
497 argc--;
498 }
499 }
500 else if (!STRNCMP(pp, "-g", 2))
501 {
502 if (pp[2] && STRNCMP("group", pp + 2, 5))
503 octspergrp = (int)strtol(pp + 2, NULL, 0);
504 else
505 {
506 if (!argv[2])
507 exit_with_usage(pname);
508 octspergrp = (int)strtol(argv[2], NULL, 0);
509 argv++;
510 argc--;
511 }
512 }
513 else if (!STRNCMP(pp, "-s", 2))
514 {
515 relseek = 0;
516 negseek = 0;
517 if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3))
518 {
519#ifdef TRY_SEEK
520 if (pp[2] == '+')
521 relseek++;
522 if (pp[2+relseek] == '-')
523 negseek++;
524#endif
525 seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0);
526 }
527 else
528 {
529 if (!argv[2])
530 exit_with_usage(pname);
531#ifdef TRY_SEEK
532 if (argv[2][0] == '+')
533 relseek++;
534 if (argv[2][relseek] == '-')
535 negseek++;
536#endif
537 seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0);
538 argv++;
539 argc--;
540 }
541 }
542 else if (!STRNCMP(pp, "-l", 2))
543 {
544 if (pp[2] && STRNCMP("en", pp + 2, 2))
545 length = strtol(pp + 2, (char **)NULL, 0);
546 else
547 {
548 if (!argv[2])
549 exit_with_usage(pname);
550 length = strtol(argv[2], (char **)NULL, 0);
551 argv++;
552 argc--;
553 }
554 }
555 else if (!strcmp(pp, "--")) /* end of options */
556 {
557 argv++;
558 argc--;
559 break;
560 }
561 else if (pp[0] == '-' && pp[1]) /* unknown option */
562 exit_with_usage(pname);
563 else
564 break; /* not an option */
565
566 argv++; /* advance to next argument */
567 argc--;
568 }
569
570 if (!cols)
571 switch (hextype)
572 {
573 case HEX_POSTSCRIPT: cols = 30; break;
574 case HEX_CINCLUDE: cols = 12; break;
575 case HEX_BITS: cols = 6; break;
576 case HEX_NORMAL:
577 default: cols = 16; break;
578 }
579
580 if (octspergrp < 0)
581 switch (hextype)
582 {
583 case HEX_BITS: octspergrp = 1; break;
584 case HEX_NORMAL: octspergrp = 2; break;
585 case HEX_POSTSCRIPT:
586 case HEX_CINCLUDE:
587 default: octspergrp = 0; break;
588 }
589
590 if (cols < 1 || (!hextype && (cols > COLS)))
591 {
592 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
593 exit(1);
594 }
595
596 if (octspergrp < 1)
597 octspergrp = cols;
598
599 if (argc > 3)
600 exit_with_usage(pname);
601
602 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
603 BIN_ASSIGN(fp = stdin, !revert);
604 else
605 {
606 if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL)
607 {
608 fprintf(stderr,"%s: ", pname);
609 perror(argv[1]);
610 return 2;
611 }
612 }
613
614 if (argc < 3 || (argv[2][0] == '-' && !argv[2][1]))
615 BIN_ASSIGN(fpo = stdout, revert);
616 else
617 {
618 int fd;
619 int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY);
620
621 if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) ||
622 (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL)
623 {
624 fprintf(stderr, "%s: ", pname);
625 perror(argv[2]);
626 return 3;
627 }
628 rewind(fpo);
629 }
630
631 if (revert)
632 {
633 if (hextype && (hextype != HEX_POSTSCRIPT))
634 {
635 fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname);
636 return -1;
637 }
638 return huntype(fp, fpo, stderr, pname, cols, hextype,
639 negseek ? -seekoff : seekoff);
640 }
641
642 if (seekoff || negseek || !relseek)
643 {
644#ifdef TRY_SEEK
645 if (relseek)
646 e = fseek(fp, negseek ? -seekoff : seekoff, 1);
647 else
648 e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0);
649 if (e < 0 && negseek)
650 {
651 fprintf(stderr, "%s: sorry cannot seek.\n", pname);
652 return 4;
653 }
654 if (e >= 0)
655 seekoff = ftell(fp);
656 else
657#endif
658 {
659 long s = seekoff;
660
661 while (s--)
662 (void)getc(fp);
663 }
664 }
665
666 if (hextype == HEX_CINCLUDE)
667 {
668 if (fp != stdin)
669 {
670 fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "");
671 for (e = 0; (c = argv[1][e]) != 0; e++)
672 putc(isalnum(c) ? c : '_', fpo);
673 fputs("[] = {\n", fpo);
674 }
675
676 p = 0;
677 while ((length < 0 || p < length) && (c = getc(fp)) != EOF)
678 {
679 fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X",
680 (p % cols) ? ", " : ",\n "+2*!p, c);
681 p++;
682 }
683
684 if (p)
685 fputs("\n};\n"+3*(fp == stdin), fpo);
686
687 if (fp != stdin)
688 {
689 fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "");
690 for (e = 0; (c = argv[1][e]) != 0; e++)
691 putc(isalnum(c) ? c : '_', fpo);
692 fprintf(fpo, "_len = %d;\n", p);
693 }
694
695 fclose(fp);
696 fclose(fpo);
697 return 0;
698 }
699
700 if (hextype == HEX_POSTSCRIPT)
701 {
702 p = cols;
703 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
704 {
705 putchar(hexx[(e >> 4) & 0xf]);
706 putchar(hexx[(e ) & 0xf]);
707 n++;
708 if (!--p)
709 {
710 putchar('\n');
711 p = cols;
712 }
713 }
714 if (p < cols)
715 putchar('\n');
716 fclose(fp);
717 fclose(fpo);
718 return 0;
719 }
720
721 /* hextype: HEX_NORMAL or HEX_BITS */
722
723 if (hextype == HEX_NORMAL)
724 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
725 else /* hextype == HEX_BITS */
726 grplen = 8 * octspergrp + 1;
727
728 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
729 {
730 if (p == 0)
731 {
732 sprintf(l, "%07lx: ", n + seekoff);
733 for (c = 9; c < LLEN; l[c++] = ' ');
734 }
735 if (hextype == HEX_NORMAL)
736 {
737 l[c = (9 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
738 l[++c] = hexx[ e & 0xf];
739 }
740 else /* hextype == HEX_BITS */
741 {
742 int i;
743
744 c = (9 + (grplen * p) / octspergrp) - 1;
745 for (i = 7; i >= 0; i--)
746 l[++c] = (e & (1 << i)) ? '1' : '0';
747 }
748 if (ebcdic)
749 e = (e < 64) ? '.' : etoa64[e-64];
750 l[11 + (grplen * cols - 1)/octspergrp + p] =
751#ifdef __MVS__
752 (e >= 64)
753#else
754 (e > 31 && e < 127)
755#endif
756 ? e : '.';
757 if (e)
758 nonzero++;
759 n++;
760 if (++p == cols)
761 {
762 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
763 xxdline(fpo, l, autoskip ? nonzero : 1);
764 nonzero = 0;
765 p = 0;
766 }
767 }
768 if (p)
769 {
770 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
771 xxdline(fpo, l, 1);
772 }
773 else if (autoskip)
774 xxdline(fpo, l, -1); /* last chance to flush out supressed lines */
775
776 fclose(fp);
777 fclose(fpo);
778 return 0;
779}