Mercurial > vim
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 |