Add memtest support.
[syslinux-debian/hramrach.git] / com32 / modules / hexdump.c
blobbc2c70dd82a8c5546a467504dc7f55cee31aafb7
1 #include <stddef.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <console.h>
7 #include <errno.h>
8 #include <syslinux/loadfile.h>
10 /* Macros */
11 #define ROWS_PER_PAGE 24
12 #define COLS_PER_ROW 16
13 #define BYTES_PER_PAGE (ROWS_PER_PAGE * COLS_PER_ROW)
15 /* Functions declarations */
16 static int usage(void);
17 static void eat_stdin(void);
18 static int do_page(void);
19 static void hexdump(const void *memory, size_t bytes);
21 /* Objects */
22 static const char *prog_name;
23 static int opt_page;
24 static int opt_no_buffer;
25 static int opt_extended_ascii;
27 int main(int argc, char **argv)
29 int rc;
30 const char *filename;
31 int i;
32 void *file_data;
33 size_t file_sz;
34 FILE *f;
35 size_t len;
36 const char *cur_pos;
38 /* Assume failure */
39 rc = EXIT_FAILURE;
41 /* Determine the program name, as invoked */
42 if (argc < 1 || !argv || !argv[0]) {
43 fprintf(stderr, "argc or argv failure!\n");
44 goto err_prog_name;
46 prog_name = argv[0];
48 /* Process arguments */
49 filename = NULL;
50 for (i = 1; i < argc; ++i) {
51 if (!argv[i]) {
52 fprintf(stderr, "argc and argv mismatch!\n");
53 goto err_argv;
56 if (!strncmp(argv[i], "--page", sizeof "--page") ||
57 !strncmp(argv[i], "-p", sizeof "-p")) {
58 opt_page = 1;
59 continue;
62 if (!strncmp(argv[i], "--no-buffer", sizeof "--no-buffer")) {
63 opt_no_buffer = 1;
64 continue;
67 if (!strncmp(argv[i], "--extended-ascii", sizeof "--extended-ascii")) {
68 opt_extended_ascii = 1;
69 continue;
72 if (!strncmp(argv[i], "--help", sizeof "--help") ||
73 !strncmp(argv[i], "-h", sizeof "-h") ||
74 !strncmp(argv[i], "-?", sizeof "-?"))
75 return usage();
77 /* Otherwise, interpret as a filename, but only accept one */
78 if (filename)
79 return usage();
80 filename = argv[i];
82 if (!filename)
83 return usage();
84 fprintf(stdout, "Dumping file: %s\n", filename);
86 /* Either fetch the whole file, or just allocate a buffer */
87 f = NULL;
88 if (opt_no_buffer) {
89 errno = 0;
90 if (loadfile(filename, &file_data, &file_sz)) {
91 fprintf(stderr, "Couldn't load file. Error: %d\n", errno);
92 goto err_file_data;
94 } else {
95 file_sz = BYTES_PER_PAGE;
96 file_data = malloc(file_sz);
97 if (!file_data) {
98 fprintf(stderr, "Couldn't allocate file data buffer\n");
99 goto err_file_data;
101 errno = 0;
102 f = fopen(filename, "r");
103 if (!f) {
104 fprintf(stderr, "Couldn't open file. Error: %d\n", errno);
105 goto err_f;
109 /* Dump the data */
110 len = BYTES_PER_PAGE;
111 cur_pos = file_data;
112 do {
113 if (f) {
114 /* Buffered */
115 len = fread(file_data, 1, file_sz, f);
116 cur_pos = file_data;
117 } else {
118 /* Non-buffered */
119 if (file_sz < len)
120 len = file_sz;
122 if (!len)
123 break;
125 hexdump(cur_pos, len);
127 /* Pause, if requested */
128 if (opt_page) {
129 /* The user might choose to quit */
130 if (do_page())
131 break;
134 /* Reduce file_sz for non-buffered mode */
135 if (!f)
136 file_sz -= len;
137 } while (cur_pos += len);
139 rc = EXIT_SUCCESS;
141 if (f)
142 fclose(f);
143 err_f:
145 free(file_data);
146 err_file_data:
148 err_argv:
150 err_prog_name:
152 return rc;
155 static int usage(void)
157 static const char usage[] =
158 "Usage: %s [<option> [...]] <filename> [<option> [...]]\n"
159 "\n"
160 "Options: -p\n"
161 " --page . . . . . . . Pause output every 24 lines\n"
162 " --no-buffer . . . . Load the entire file before dumping\n"
163 " --extended-ascii . . Use extended ASCII chars in dump\n"
164 " -?\n"
165 " -h\n"
166 " --help . . . . . . Display this help\n";
168 fprintf(stderr, usage, prog_name);
169 return EXIT_FAILURE;
172 static void eat_stdin(void)
174 int i;
176 while (1) {
177 i = fgetc(stdin);
178 if (i == EOF || i == '\n')
179 return;
182 static int do_page(void)
184 int i;
186 while (1) {
187 fprintf(stdout, "Continue? [Y|n]: ");
188 i = fgetc(stdin);
189 switch (i) {
190 case 'n':
191 case 'N':
192 eat_stdin();
193 return 1;
195 case EOF:
196 fprintf(stderr, "No response. Continuing...\n");
197 /* Fall through to "yes" */
199 case 'y':
200 case 'Y':
201 eat_stdin();
202 case '\n':
203 return 0;
205 default:
206 fprintf(stderr, "Invalid choice\n");
207 eat_stdin();
212 static void hexdump(const void *memory, size_t bytes)
214 const unsigned char *p, *q;
215 int i;
217 p = memory;
218 while (bytes) {
219 q = p;
220 printf("%p: ", (void *) p);
221 for (i = 0; i < 16 && bytes; ++i) {
222 printf("%02X ", *p);
223 ++p;
224 --bytes;
226 bytes += i;
227 while (i < 16) {
228 printf("XX ");
229 ++i;
231 printf("| ");
232 p = q;
233 for (i = 0; i < 16 && bytes; ++i) {
234 printf("%c", isprint(*p) && !isspace(*p) ? *p : ' ');
235 ++p;
236 --bytes;
238 while (i < 16) {
239 printf(" ");
240 ++i;
242 printf("\n");
244 return;