hexl.c 4.7 KB

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