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