Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
100 7u83 1
/* 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
 *	       consecutive 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
 *	    (azc10@yahoo.com)
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 merge 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
 
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
 
68
#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)
97
FILE   _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 */
122
extern int fprintf __P((FILE *, char *, ...));
123
extern int fputs   __P((char *, FILE *));
124
extern int _flsbuf __P((unsigned char, FILE *));
125
extern int _filbuf __P((FILE *));
126
extern int fflush  __P((FILE *));
127
extern int fclose  __P((FILE *));
128
extern int fseek   __P((FILE *, long, int));
129
extern int rewind  __P((FILE *));
130
 
131
extern void perror __P((char *));
132
# endif
133
#endif
134
 
135
extern long int strtol();
136
extern long int ftell();
137
 
138
char version[] = "xxd V1.10 27oct98 by Juergen Weigert";
139
#ifdef WIN32
140
char osver[] = " (Win32)";
141
#else
142
# ifdef DJGPP
143
char osver[] = " (dos 32 bit)";
144
# else
145
#  ifdef MSDOS
146
char osver[] = " (dos 16 bit)";
147
#  else
148
char osver[] = "";
149
#  endif
150
# endif
151
#endif
152
 
153
#if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__))
154
# define CYGWIN
155
#endif
156
#if defined(MSDOS) || defined(WIN32) || defined(OS2)
157
# 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)
161
# 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 '/'
168
#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 */
209
static void exit_with_usage __P((char *));
210
static int huntype __P((FILE *, FILE *, FILE *, char *, int, int, long));
211
static 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
 
217
char 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
 
225
static void
226
exit_with_usage(pname)
227
char *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
 */
261
static int
262
huntype(fpi, fpo, fperr, pname, cols, hextype, base_off)
263
FILE *fpi, *fpo, *fperr;
264
char *pname;
265
int cols, hextype;
266
long 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
#if 0	/* this doesn't work when there is normal text after the hex codes in
279
	   the last line that looks like hex */
280
      if (c == ' ' || c == '\n' || c == '\t')  /* allow multiple spaces */
281
	continue;
282
#endif
283
 
284
      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
	    {
343
	      /* skip rest of line as garbage */
344
	      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
 */
381
static void
382
xxdline(fp, l, nz)
383
FILE *fp;
384
char *l;
385
int 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 */
413
static 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
 
441
int
442
main(argc, argv)
443
int argc;
444
char *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 suppressed lines */
778
 
779
  fclose(fp);
780
  fclose(fpo);
781
  return 0;
782
}