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