hexl.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* Convert files for Emacs Hexl mode.
  2. Copyright (C) 1989, 2001-2016 Free Software Foundation, Inc.
  3. Author: Keith Gabryelski (according to authors.el)
  4. This file is not considered part of GNU Emacs.
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or (at
  8. your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include <config.h>
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <binary-io.h>
  19. #define DEFAULT_GROUPING 0x01
  20. #define DEFAULT_BASE 16
  21. int base = DEFAULT_BASE;
  22. bool un_flag = false, iso_flag = false, endian = true;
  23. int group_by = DEFAULT_GROUPING;
  24. char *progname;
  25. _Noreturn void usage (void);
  26. int
  27. main (int argc, char **argv)
  28. {
  29. register long address;
  30. char string[18];
  31. FILE *fp;
  32. progname = *argv++; --argc;
  33. /*
  34. ** -hex hex dump
  35. ** -oct Octal dump
  36. ** -group-by-8-bits
  37. ** -group-by-16-bits
  38. ** -group-by-32-bits
  39. ** -group-by-64-bits
  40. ** -iso iso character set.
  41. ** -big-endian Big Endian
  42. ** -little-endian Little Endian
  43. ** -un || -de from hexl format to binary.
  44. ** -- End switch list.
  45. ** <filename> dump filename
  46. ** - (as filename == stdin)
  47. */
  48. while (*argv && *argv[0] == '-' && (*argv)[1])
  49. {
  50. /* A switch! */
  51. if (!strcmp (*argv, "--"))
  52. {
  53. --argc; argv++;
  54. break;
  55. }
  56. else if (!strcmp (*argv, "-un") || !strcmp (*argv, "-de"))
  57. {
  58. un_flag = true;
  59. --argc; argv++;
  60. }
  61. else if (!strcmp (*argv, "-hex"))
  62. {
  63. base = 16;
  64. --argc; argv++;
  65. }
  66. else if (!strcmp (*argv, "-iso"))
  67. {
  68. iso_flag = true;
  69. --argc; argv++;
  70. }
  71. else if (!strcmp (*argv, "-oct"))
  72. {
  73. base = 8;
  74. --argc; argv++;
  75. }
  76. else if (!strcmp (*argv, "-big-endian"))
  77. {
  78. endian = true;
  79. --argc; argv++;
  80. }
  81. else if (!strcmp (*argv, "-little-endian"))
  82. {
  83. endian = false;
  84. --argc; argv++;
  85. }
  86. else if (!strcmp (*argv, "-group-by-8-bits"))
  87. {
  88. group_by = 0x00;
  89. --argc; argv++;
  90. }
  91. else if (!strcmp (*argv, "-group-by-16-bits"))
  92. {
  93. group_by = 0x01;
  94. --argc; argv++;
  95. }
  96. else if (!strcmp (*argv, "-group-by-32-bits"))
  97. {
  98. group_by = 0x03;
  99. --argc; argv++;
  100. }
  101. else if (!strcmp (*argv, "-group-by-64-bits"))
  102. {
  103. group_by = 0x07;
  104. endian = false;
  105. --argc; argv++;
  106. }
  107. else
  108. {
  109. fprintf (stderr, "%s: invalid switch: \"%s\".\n", progname,
  110. *argv);
  111. usage ();
  112. }
  113. }
  114. do
  115. {
  116. if (*argv == NULL)
  117. fp = stdin;
  118. else
  119. {
  120. char *filename = *argv++;
  121. if (!strcmp (filename, "-"))
  122. fp = stdin;
  123. else if ((fp = fopen (filename, "r")) == NULL)
  124. {
  125. perror (filename);
  126. continue;
  127. }
  128. }
  129. if (un_flag)
  130. {
  131. SET_BINARY (fileno (stdout));
  132. for (;;)
  133. {
  134. int i, c = 0, d;
  135. char buf[18];
  136. #define hexchar(x) (isdigit (x) ? x - '0' : x - 'a' + 10)
  137. /* Skip 10 bytes. */
  138. if (fread (buf, 1, 10, fp) != 10)
  139. break;
  140. for (i=0; i < 16; ++i)
  141. {
  142. if ((c = getc (fp)) == ' ' || c == EOF)
  143. break;
  144. d = getc (fp);
  145. c = hexchar (c) * 0x10 + hexchar (d);
  146. putchar (c);
  147. if ((i&group_by) == group_by)
  148. getc (fp);
  149. }
  150. if (c == ' ')
  151. {
  152. while ((c = getc (fp)) != '\n' && c != EOF)
  153. ;
  154. if (c == EOF)
  155. break;
  156. }
  157. else
  158. {
  159. if (i < 16)
  160. break;
  161. /* Skip 18 bytes. */
  162. if (fread (buf, 1, 18, fp) != 18)
  163. break;
  164. }
  165. }
  166. }
  167. else
  168. {
  169. SET_BINARY (fileno (fp));
  170. address = 0;
  171. string[0] = ' ';
  172. string[17] = '\0';
  173. for (;;)
  174. {
  175. register int i, c = 0;
  176. for (i=0; i < 16; ++i)
  177. {
  178. if ((c = getc (fp)) == EOF)
  179. {
  180. if (!i)
  181. break;
  182. fputs (" ", stdout);
  183. string[i+1] = '\0';
  184. }
  185. else
  186. {
  187. if (!i)
  188. printf ("%08lx: ", address + 0ul);
  189. if (iso_flag)
  190. string[i+1] =
  191. (c < 0x20 || (c >= 0x7F && c < 0xa0)) ? '.' :c;
  192. else
  193. string[i+1] = (c < 0x20 || c >= 0x7F) ? '.' : c;
  194. printf ("%02x", c + 0u);
  195. }
  196. if ((i&group_by) == group_by)
  197. putchar (' ');
  198. }
  199. if (i)
  200. puts (string);
  201. if (c == EOF)
  202. break;
  203. address += 0x10;
  204. }
  205. }
  206. if (fp != stdin)
  207. fclose (fp);
  208. } while (*argv != NULL);
  209. return EXIT_SUCCESS;
  210. }
  211. void
  212. usage (void)
  213. {
  214. fprintf (stderr, "usage: %s [-de] [-iso]\n", progname);
  215. exit (EXIT_FAILURE);
  216. }
  217. /* hexl.c ends here */