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