comparison src/xxd/xxd.c @ 6655:6c94cedccda4 v7.4.652

updated for version 7.4.652 Problem: Xxd lacks a few features. Solution: Use 8 characters for the file position. Add the -e and -o arguments. (Vadim Vygonets)
author Bram Moolenaar <bram@vim.org>
date Thu, 05 Mar 2015 17:51:15 +0100
parents 0a379dea13c9
children 7b35ee02b3c5
comparison
equal deleted inserted replaced
6654:9ca07709d626 6655:6c94cedccda4
49 * option -b added: 01000101 binary output in normal format. 49 * option -b added: 01000101 binary output in normal format.
50 * 16.05.00 Added VAXC changes by Stephen P. Wall 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 51 * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy
52 * 2011 March Better error handling by Florian Zumbiehl. 52 * 2011 March Better error handling by Florian Zumbiehl.
53 * 2011 April Formatting by Bram Moolenaar 53 * 2011 April Formatting by Bram Moolenaar
54 * 08.06.2013 Little-endian hexdump (-e) and offset (-o) by Vadim Vygonets.
54 * 55 *
55 * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de) 56 * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de)
56 * 57 *
57 * Small changes made afterwards by Bram Moolenaar et al. 58 * Small changes made afterwards by Bram Moolenaar et al.
58 * 59 *
214 static int huntype __P((FILE *, FILE *, FILE *, int, int, long)); 215 static int huntype __P((FILE *, FILE *, FILE *, int, int, long));
215 static void xxdline __P((FILE *, char *, int)); 216 static void xxdline __P((FILE *, char *, int));
216 217
217 #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */ 218 #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */
218 #define COLS 256 /* change here, if you ever need more columns */ 219 #define COLS 256 /* change here, if you ever need more columns */
219 #define LLEN (11 + (9*COLS-1)/1 + COLS + 2) 220 #define LLEN (12 + (9*COLS-1) + COLS + 2)
220 221
221 char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa; 222 char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
222 223
223 /* the different hextypes known by this program: */ 224 /* the different hextypes known by this program: */
224 #define HEX_NORMAL 0 225 #define HEX_NORMAL 0
225 #define HEX_POSTSCRIPT 1 226 #define HEX_POSTSCRIPT 1
226 #define HEX_CINCLUDE 2 227 #define HEX_CINCLUDE 2
227 #define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */ 228 #define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */
229 #define HEX_LITTLEENDIAN 4
228 230
229 static char *pname; 231 static char *pname;
230 232
231 static void 233 static void
232 exit_with_usage() 234 exit_with_usage()
236 fprintf(stderr, "Options:\n"); 238 fprintf(stderr, "Options:\n");
237 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n"); 239 fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n");
238 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n"); 240 fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n");
239 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n"); 241 fprintf(stderr, " -c cols format <cols> octets per line. Default 16 (-i: 12, -ps: 30).\n");
240 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n"); 242 fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n");
241 fprintf(stderr, " -g number of octets per group in normal output. Default 2.\n"); 243 fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n");
244 fprintf(stderr, " -g number of octets per group in normal output. Default 2 (-e: 4).\n");
242 fprintf(stderr, " -h print this summary.\n"); 245 fprintf(stderr, " -h print this summary.\n");
243 fprintf(stderr, " -i output in C include file style.\n"); 246 fprintf(stderr, " -i output in C include file style.\n");
244 fprintf(stderr, " -l len stop after <len> octets.\n"); 247 fprintf(stderr, " -l len stop after <len> octets.\n");
248 fprintf(stderr, " -o off add <off> to the displayed file position.\n");
245 fprintf(stderr, " -ps output in postscript plain hexdump style.\n"); 249 fprintf(stderr, " -ps output in postscript plain hexdump style.\n");
246 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n"); 250 fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n");
247 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n"); 251 fprintf(stderr, " -r -s off revert with <off> added to file positions found in hexdump.\n");
248 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n", 252 fprintf(stderr, " -s %sseek start at <seek> bytes abs. %sinfile offset.\n",
249 #ifdef TRY_SEEK 253 #ifdef TRY_SEEK
473 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0; 477 int c, e, p = 0, relseek = 1, negseek = 0, revert = 0;
474 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL; 478 int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL;
475 int ebcdic = 0; 479 int ebcdic = 0;
476 int octspergrp = -1; /* number of octets grouped in output */ 480 int octspergrp = -1; /* number of octets grouped in output */
477 int grplen; /* total chars per octet group */ 481 int grplen; /* total chars per octet group */
478 long length = -1, n = 0, seekoff = 0; 482 long length = -1, n = 0, seekoff = 0, displayoff = 0;
479 static char l[LLEN+1]; /* static because it may be too big for stack */ 483 static char l[LLEN+1]; /* static because it may be too big for stack */
480 char *pp; 484 char *pp;
481 485
482 #ifdef AMIGA 486 #ifdef AMIGA
483 /* This program doesn't work when started from the Workbench */ 487 /* This program doesn't work when started from the Workbench */
501 while (argc >= 2) 505 while (argc >= 2)
502 { 506 {
503 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]); 507 pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]);
504 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip; 508 if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip;
505 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS; 509 else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS;
510 else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN;
506 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16; 511 else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16;
507 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT; 512 else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT;
508 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE; 513 else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE;
509 else if (!STRNCMP(pp, "-r", 2)) revert++; 514 else if (!STRNCMP(pp, "-r", 2)) revert++;
510 else if (!STRNCMP(pp, "-E", 2)) ebcdic++; 515 else if (!STRNCMP(pp, "-E", 2)) ebcdic++;
533 else 538 else
534 { 539 {
535 if (!argv[2]) 540 if (!argv[2])
536 exit_with_usage(); 541 exit_with_usage();
537 octspergrp = (int)strtol(argv[2], NULL, 0); 542 octspergrp = (int)strtol(argv[2], NULL, 0);
543 argv++;
544 argc--;
545 }
546 }
547 else if (!STRNCMP(pp, "-o", 2))
548 {
549 if (pp[2] && STRNCMP("ffset", pp + 2, 5))
550 displayoff = (int)strtol(pp + 2, NULL, 0);
551 else
552 {
553 if (!argv[2])
554 exit_with_usage();
555 displayoff = (int)strtol(argv[2], NULL, 0);
538 argv++; 556 argv++;
539 argc--; 557 argc--;
540 } 558 }
541 } 559 }
542 else if (!STRNCMP(pp, "-s", 2)) 560 else if (!STRNCMP(pp, "-s", 2))
601 { 619 {
602 case HEX_POSTSCRIPT: cols = 30; break; 620 case HEX_POSTSCRIPT: cols = 30; break;
603 case HEX_CINCLUDE: cols = 12; break; 621 case HEX_CINCLUDE: cols = 12; break;
604 case HEX_BITS: cols = 6; break; 622 case HEX_BITS: cols = 6; break;
605 case HEX_NORMAL: 623 case HEX_NORMAL:
624 case HEX_LITTLEENDIAN:
606 default: cols = 16; break; 625 default: cols = 16; break;
607 } 626 }
608 627
609 if (octspergrp < 0) 628 if (octspergrp < 0)
610 switch (hextype) 629 switch (hextype)
611 { 630 {
612 case HEX_BITS: octspergrp = 1; break; 631 case HEX_BITS: octspergrp = 1; break;
613 case HEX_NORMAL: octspergrp = 2; break; 632 case HEX_NORMAL: octspergrp = 2; break;
633 case HEX_LITTLEENDIAN: octspergrp = 4; break;
614 case HEX_POSTSCRIPT: 634 case HEX_POSTSCRIPT:
615 case HEX_CINCLUDE: 635 case HEX_CINCLUDE:
616 default: octspergrp = 0; break; 636 default: octspergrp = 0; break;
617 } 637 }
618 638
619 if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS) 639 if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN)
620 && (cols > COLS))) 640 && (cols > COLS)))
621 { 641 {
622 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS); 642 fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
623 exit(1); 643 exit(1);
624 } 644 }
625 645
626 if (octspergrp < 1) 646 if (octspergrp < 1 || octspergrp > cols)
627 octspergrp = cols; 647 octspergrp = cols;
648 else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1)))
649 {
650 fprintf(stderr,
651 "%s: number of octets per group must be a power of 2 with -e.\n",
652 pname);
653 exit(1);
654 }
628 655
629 if (argc > 3) 656 if (argc > 3)
630 exit_with_usage(); 657 exit_with_usage();
631 658
632 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1])) 659 if (argc == 1 || (argv[1][0] == '-' && !argv[1][1]))
779 if (fclose(fpo)) 806 if (fclose(fpo))
780 die(3); 807 die(3);
781 return 0; 808 return 0;
782 } 809 }
783 810
784 /* hextype: HEX_NORMAL or HEX_BITS */ 811 /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */
785 812
786 if (hextype == HEX_NORMAL) 813 if (hextype != HEX_BITS)
787 grplen = octspergrp + octspergrp + 1; /* chars per octet group */ 814 grplen = octspergrp + octspergrp + 1; /* chars per octet group */
788 else /* hextype == HEX_BITS */ 815 else /* hextype == HEX_BITS */
789 grplen = 8 * octspergrp + 1; 816 grplen = 8 * octspergrp + 1;
790 817
791 e = 0; 818 e = 0;
792 while ((length < 0 || n < length) && (e = getc(fp)) != EOF) 819 while ((length < 0 || n < length) && (e = getc(fp)) != EOF)
793 { 820 {
794 if (p == 0) 821 if (p == 0)
795 { 822 {
796 sprintf(l, "%07lx: ", n + seekoff); 823 sprintf(l, "%08lx:",
824 ((unsigned long)(n + seekoff + displayoff)) & 0xffffffff);
797 for (c = 9; c < LLEN; l[c++] = ' '); 825 for (c = 9; c < LLEN; l[c++] = ' ');
798 } 826 }
799 if (hextype == HEX_NORMAL) 827 if (hextype == HEX_NORMAL)
800 { 828 {
801 l[c = (9 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf]; 829 l[c = (10 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf];
802 l[++c] = hexx[ e & 0xf]; 830 l[++c] = hexx[ e & 0xf];
831 }
832 else if (hextype == HEX_LITTLEENDIAN)
833 {
834 int x = p ^ (octspergrp-1);
835 l[c = (10 + (grplen * x) / octspergrp)] = hexx[(e >> 4) & 0xf];
836 l[++c] = hexx[ e & 0xf];
803 } 837 }
804 else /* hextype == HEX_BITS */ 838 else /* hextype == HEX_BITS */
805 { 839 {
806 int i; 840 int i;
807 841
808 c = (9 + (grplen * p) / octspergrp) - 1; 842 c = (10 + (grplen * p) / octspergrp) - 1;
809 for (i = 7; i >= 0; i--) 843 for (i = 7; i >= 0; i--)
810 l[++c] = (e & (1 << i)) ? '1' : '0'; 844 l[++c] = (e & (1 << i)) ? '1' : '0';
811 } 845 }
812 if (ebcdic) 846 if (ebcdic)
813 e = (e < 64) ? '.' : etoa64[e-64]; 847 e = (e < 64) ? '.' : etoa64[e-64];
814 /* When changing this update definition of LLEN above. */ 848 /* When changing this update definition of LLEN above. */
815 l[11 + (grplen * cols - 1)/octspergrp + p] = 849 l[12 + (grplen * cols - 1)/octspergrp + p] =
816 #ifdef __MVS__ 850 #ifdef __MVS__
817 (e >= 64) 851 (e >= 64)
818 #else 852 #else
819 (e > 31 && e < 127) 853 (e > 31 && e < 127)
820 #endif 854 #endif
822 if (e) 856 if (e)
823 nonzero++; 857 nonzero++;
824 n++; 858 n++;
825 if (++p == cols) 859 if (++p == cols)
826 { 860 {
827 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0'; 861 l[c = (12 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
828 xxdline(fpo, l, autoskip ? nonzero : 1); 862 xxdline(fpo, l, autoskip ? nonzero : 1);
829 nonzero = 0; 863 nonzero = 0;
830 p = 0; 864 p = 0;
831 } 865 }
832 } 866 }
833 if (e == EOF && ferror(fp)) 867 if (e == EOF && ferror(fp))
834 die(2); 868 die(2);
835 if (p) 869 if (p)
836 { 870 {
837 l[c = (11 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0'; 871 l[c = (12 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0';
838 xxdline(fpo, l, 1); 872 xxdline(fpo, l, 1);
839 } 873 }
840 else if (autoskip) 874 else if (autoskip)
841 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */ 875 xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */
842 876