xxd.c
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:19k
源码类别:

编辑器/阅读器

开发平台:

DOS

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