Line data Source code
1 : /* od -- dump files in octal and other formats
2 : Copyright (C) 92, 1995-2007 Free Software Foundation, Inc.
3 :
4 : This program is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation, either version 3 of the License, or
7 : (at your option) any later version.
8 :
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 :
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 :
17 : /* Written by Jim Meyering. */
18 :
19 : #include <config.h>
20 :
21 : #include <stdio.h>
22 : #include <assert.h>
23 : #include <getopt.h>
24 : #include <sys/types.h>
25 : #include "system.h"
26 : #include "error.h"
27 : #include "quote.h"
28 : #include "xstrtol.h"
29 :
30 : /* The official name of this program (e.g., no `g' prefix). */
31 : #define PROGRAM_NAME "od"
32 :
33 : #define AUTHORS "Jim Meyering"
34 :
35 : #include <float.h>
36 :
37 : #ifdef HAVE_LONG_DOUBLE
38 : typedef long double LONG_DOUBLE;
39 : #else
40 : typedef double LONG_DOUBLE;
41 : #endif
42 :
43 : /* The default number of input bytes per output line. */
44 : #define DEFAULT_BYTES_PER_BLOCK 16
45 :
46 : /* The number of decimal digits of precision in a float. */
47 : #ifndef FLT_DIG
48 : # define FLT_DIG 7
49 : #endif
50 :
51 : /* The number of decimal digits of precision in a double. */
52 : #ifndef DBL_DIG
53 : # define DBL_DIG 15
54 : #endif
55 :
56 : #if HAVE_UNSIGNED_LONG_LONG_INT
57 : typedef unsigned long long int unsigned_long_long_int;
58 : #else
59 : /* This is just a place-holder to avoid a few `#if' directives.
60 : In this case, the type isn't actually used. */
61 : typedef unsigned long int unsigned_long_long_int;
62 : #endif
63 :
64 : enum size_spec
65 : {
66 : NO_SIZE,
67 : CHAR,
68 : SHORT,
69 : INT,
70 : LONG,
71 : LONG_LONG,
72 : /* FIXME: add INTMAX support, too */
73 : FLOAT_SINGLE,
74 : FLOAT_DOUBLE,
75 : FLOAT_LONG_DOUBLE,
76 : N_SIZE_SPECS
77 : };
78 :
79 : enum output_format
80 : {
81 : SIGNED_DECIMAL,
82 : UNSIGNED_DECIMAL,
83 : OCTAL,
84 : HEXADECIMAL,
85 : FLOATING_POINT,
86 : NAMED_CHARACTER,
87 : CHARACTER
88 : };
89 :
90 : /* The maximum number of bytes needed for a format string,
91 : including the trailing null. */
92 : enum
93 : {
94 : FMT_BYTES_ALLOCATED =
95 : MAX ((sizeof " %0" - 1 + INT_STRLEN_BOUND (int)
96 : + MAX (sizeof "ld",
97 : MAX (sizeof PRIdMAX,
98 : MAX (sizeof PRIoMAX,
99 : MAX (sizeof PRIuMAX,
100 : sizeof PRIxMAX))))),
101 : sizeof " %.Le" + 2 * INT_STRLEN_BOUND (int))
102 : };
103 :
104 : /* Each output format specification (from `-t spec' or from
105 : old-style options) is represented by one of these structures. */
106 : struct tspec
107 : {
108 : enum output_format fmt;
109 : enum size_spec size;
110 : void (*print_function) (size_t, void const *, char const *);
111 : char fmt_string[FMT_BYTES_ALLOCATED];
112 : bool hexl_mode_trailer;
113 : int field_width;
114 : };
115 :
116 : /* The name this program was run with. */
117 : char *program_name;
118 :
119 : /* Convert the number of 8-bit bytes of a binary representation to
120 : the number of characters (digits + sign if the type is signed)
121 : required to represent the same quantity in the specified base/type.
122 : For example, a 32-bit (4-byte) quantity may require a field width
123 : as wide as the following for these types:
124 : 11 unsigned octal
125 : 11 signed decimal
126 : 10 unsigned decimal
127 : 8 unsigned hexadecimal */
128 :
129 : static unsigned int const bytes_to_oct_digits[] =
130 : {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
131 :
132 : static unsigned int const bytes_to_signed_dec_digits[] =
133 : {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
134 :
135 : static unsigned int const bytes_to_unsigned_dec_digits[] =
136 : {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
137 :
138 : static unsigned int const bytes_to_hex_digits[] =
139 : {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
140 :
141 : #define MAX_INTEGRAL_TYPE_SIZE sizeof (unsigned_long_long_int)
142 :
143 : /* It'll be a while before we see integral types wider than 16 bytes,
144 : but if/when it happens, this check will catch it. Without this check,
145 : a wider type would provoke a buffer overrun. */
146 : verify (MAX_INTEGRAL_TYPE_SIZE
147 : < sizeof bytes_to_hex_digits / sizeof *bytes_to_hex_digits);
148 :
149 : /* Make sure the other arrays have the same length. */
150 : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_signed_dec_digits);
151 : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_unsigned_dec_digits);
152 : verify (sizeof bytes_to_oct_digits == sizeof bytes_to_hex_digits);
153 :
154 : /* Convert enum size_spec to the size of the named type. */
155 : static const int width_bytes[] =
156 : {
157 : -1,
158 : sizeof (char),
159 : sizeof (short int),
160 : sizeof (int),
161 : sizeof (long int),
162 : sizeof (unsigned_long_long_int),
163 : sizeof (float),
164 : sizeof (double),
165 : sizeof (LONG_DOUBLE)
166 : };
167 :
168 : /* Ensure that for each member of `enum size_spec' there is an
169 : initializer in the width_bytes array. */
170 : verify (sizeof width_bytes / sizeof width_bytes[0] == N_SIZE_SPECS);
171 :
172 : /* Names for some non-printing characters. */
173 : static const char *const charname[33] =
174 : {
175 : "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
176 : "bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
177 : "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
178 : "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
179 : "sp"
180 : };
181 :
182 : /* Address base (8, 10 or 16). */
183 : static int address_base;
184 :
185 : /* The number of octal digits required to represent the largest
186 : address value. */
187 : #define MAX_ADDRESS_LENGTH \
188 : ((sizeof (uintmax_t) * CHAR_BIT + CHAR_BIT - 1) / 3)
189 :
190 : /* Width of a normal address. */
191 : static int address_pad_len;
192 :
193 : static size_t string_min;
194 : static bool flag_dump_strings;
195 :
196 : /* True if we should recognize the older non-option arguments
197 : that specified at most one file and optional arguments specifying
198 : offset and pseudo-start address. */
199 : static bool traditional;
200 :
201 : /* True if an old-style `pseudo-address' was specified. */
202 : static bool flag_pseudo_start;
203 :
204 : /* The difference between the old-style pseudo starting address and
205 : the number of bytes to skip. */
206 : static uintmax_t pseudo_offset;
207 :
208 : /* Function that accepts an address and an optional following char,
209 : and prints the address and char to stdout. */
210 : static void (*format_address) (uintmax_t, char);
211 :
212 : /* The number of input bytes to skip before formatting and writing. */
213 : static uintmax_t n_bytes_to_skip = 0;
214 :
215 : /* When false, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
216 : input is formatted. */
217 : static bool limit_bytes_to_format = false;
218 :
219 : /* The maximum number of bytes that will be formatted. */
220 : static uintmax_t max_bytes_to_format;
221 :
222 : /* The offset of the first byte after the last byte to be formatted. */
223 : static uintmax_t end_offset;
224 :
225 : /* When true and two or more consecutive blocks are equal, format
226 : only the first block and output an asterisk alone on the following
227 : line to indicate that identical blocks have been elided. */
228 : static bool abbreviate_duplicate_blocks = true;
229 :
230 : /* An array of specs describing how to format each input block. */
231 : static struct tspec *spec;
232 :
233 : /* The number of format specs. */
234 : static size_t n_specs;
235 :
236 : /* The allocated length of SPEC. */
237 : static size_t n_specs_allocated;
238 :
239 : /* The number of input bytes formatted per output line. It must be
240 : a multiple of the least common multiple of the sizes associated with
241 : the specified output types. It should be as large as possible, but
242 : no larger than 16 -- unless specified with the -w option. */
243 : static size_t bytes_per_block;
244 :
245 : /* Human-readable representation of *file_list (for error messages).
246 : It differs from file_list[-1] only when file_list[-1] is "-". */
247 : static char const *input_filename;
248 :
249 : /* A NULL-terminated list of the file-arguments from the command line. */
250 : static char const *const *file_list;
251 :
252 : /* Initializer for file_list if no file-arguments
253 : were specified on the command line. */
254 : static char const *const default_file_list[] = {"-", NULL};
255 :
256 : /* The input stream associated with the current file. */
257 : static FILE *in_stream;
258 :
259 : /* If true, at least one of the files we read was standard input. */
260 : static bool have_read_stdin;
261 :
262 : /* Map the size in bytes to a type identifier. */
263 : static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1];
264 :
265 : #define MAX_FP_TYPE_SIZE sizeof (LONG_DOUBLE)
266 : static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1];
267 :
268 : static char const short_options[] = "A:aBbcDdeFfHhIij:LlN:OoS:st:vw::Xx";
269 :
270 : /* For long options that have no equivalent short option, use a
271 : non-character as a pseudo short option, starting with CHAR_MAX + 1. */
272 : enum
273 : {
274 : TRADITIONAL_OPTION = CHAR_MAX + 1
275 : };
276 :
277 : static struct option const long_options[] =
278 : {
279 : {"skip-bytes", required_argument, NULL, 'j'},
280 : {"address-radix", required_argument, NULL, 'A'},
281 : {"read-bytes", required_argument, NULL, 'N'},
282 : {"format", required_argument, NULL, 't'},
283 : {"output-duplicates", no_argument, NULL, 'v'},
284 : {"strings", optional_argument, NULL, 'S'},
285 : {"traditional", no_argument, NULL, TRADITIONAL_OPTION},
286 : {"width", optional_argument, NULL, 'w'},
287 :
288 : {GETOPT_HELP_OPTION_DECL},
289 : {GETOPT_VERSION_OPTION_DECL},
290 : {NULL, 0, NULL, 0}
291 : };
292 :
293 : void
294 11 : usage (int status)
295 : {
296 11 : if (status != EXIT_SUCCESS)
297 10 : fprintf (stderr, _("Try `%s --help' for more information.\n"),
298 : program_name);
299 : else
300 : {
301 1 : printf (_("\
302 : Usage: %s [OPTION]... [FILE]...\n\
303 : or: %s [-abcdfilosx]... [FILE] [[+]OFFSET[.][b]]\n\
304 : or: %s --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]\n\
305 : "),
306 : program_name, program_name, program_name);
307 1 : fputs (_("\n\
308 : Write an unambiguous representation, octal bytes by default,\n\
309 : of FILE to standard output. With more than one FILE argument,\n\
310 : concatenate them in the listed order to form the input.\n\
311 : With no FILE, or when FILE is -, read standard input.\n\
312 : \n\
313 : "), stdout);
314 1 : fputs (_("\
315 : All arguments to long options are mandatory for short options.\n\
316 : "), stdout);
317 1 : fputs (_("\
318 : -A, --address-radix=RADIX decide how file offsets are printed\n\
319 : -j, --skip-bytes=BYTES skip BYTES input bytes first\n\
320 : "), stdout);
321 1 : fputs (_("\
322 : -N, --read-bytes=BYTES limit dump to BYTES input bytes\n\
323 : -S, --strings[=BYTES] output strings of at least BYTES graphic chars\n\
324 : -t, --format=TYPE select output format or formats\n\
325 : -v, --output-duplicates do not use * to mark line suppression\n\
326 : -w, --width[=BYTES] output BYTES bytes per output line\n\
327 : --traditional accept arguments in traditional form\n\
328 : "), stdout);
329 1 : fputs (HELP_OPTION_DESCRIPTION, stdout);
330 1 : fputs (VERSION_OPTION_DESCRIPTION, stdout);
331 1 : fputs (_("\
332 : \n\
333 : Traditional format specifications may be intermixed; they accumulate:\n\
334 : -a same as -t a, select named characters, ignoring high-order bit\n\
335 : -b same as -t o1, select octal bytes\n\
336 : -c same as -t c, select ASCII characters or backslash escapes\n\
337 : -d same as -t u2, select unsigned decimal 2-byte units\n\
338 : "), stdout);
339 1 : fputs (_("\
340 : -f same as -t fF, select floats\n\
341 : -i same as -t dI, select decimal ints\n\
342 : -l same as -t dL, select decimal longs\n\
343 : -o same as -t o2, select octal 2-byte units\n\
344 : -s same as -t d2, select decimal 2-byte units\n\
345 : -x same as -t x2, select hexadecimal 2-byte units\n\
346 : "), stdout);
347 1 : fputs (_("\
348 : \n\
349 : If first and second call formats both apply, the second format is assumed\n\
350 : if the last operand begins with + or (if there are 2 operands) a digit.\n\
351 : An OFFSET operand means -j OFFSET. LABEL is the pseudo-address\n\
352 : at first byte printed, incremented when dump is progressing.\n\
353 : For OFFSET and LABEL, a 0x or 0X prefix indicates hexadecimal;\n\
354 : suffixes may be . for octal and b for multiply by 512.\n\
355 : "), stdout);
356 1 : fputs (_("\
357 : \n\
358 : TYPE is made up of one or more of these specifications:\n\
359 : \n\
360 : a named character, ignoring high-order bit\n\
361 : c ASCII character or backslash escape\n\
362 : "), stdout);
363 1 : fputs (_("\
364 : d[SIZE] signed decimal, SIZE bytes per integer\n\
365 : f[SIZE] floating point, SIZE bytes per integer\n\
366 : o[SIZE] octal, SIZE bytes per integer\n\
367 : u[SIZE] unsigned decimal, SIZE bytes per integer\n\
368 : x[SIZE] hexadecimal, SIZE bytes per integer\n\
369 : "), stdout);
370 1 : fputs (_("\
371 : \n\
372 : SIZE is a number. For TYPE in doux, SIZE may also be C for\n\
373 : sizeof(char), S for sizeof(short), I for sizeof(int) or L for\n\
374 : sizeof(long). If TYPE is f, SIZE may also be F for sizeof(float), D\n\
375 : for sizeof(double) or L for sizeof(long double).\n\
376 : "), stdout);
377 1 : fputs (_("\
378 : \n\
379 : RADIX is d for decimal, o for octal, x for hexadecimal or n for none.\n\
380 : BYTES is hexadecimal with 0x or 0X prefix, and may have a multiplier suffix:\n\
381 : b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
382 : GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
383 : Adding a z suffix to any type displays printable characters at the end of each\n\
384 : output line. \
385 : "), stdout);
386 1 : fputs (_("\
387 : --string without a number implies 3. --width without a number\n\
388 : implies 32. By default, od uses -A o -t d2 -w16.\n\
389 : "), stdout);
390 1 : emit_bug_reporting_address ();
391 : }
392 11 : exit (status);
393 : }
394 :
395 : /* Define the print functions. */
396 :
397 : static void
398 0 : print_s_char (size_t n_bytes, void const *block, char const *fmt_string)
399 : {
400 0 : signed char const *p = block;
401 : size_t i;
402 0 : for (i = n_bytes / sizeof *p; i != 0; i--)
403 0 : printf (fmt_string, *p++);
404 0 : }
405 :
406 : static void
407 2 : print_char (size_t n_bytes, void const *block, char const *fmt_string)
408 : {
409 2 : unsigned char const *p = block;
410 : size_t i;
411 18 : for (i = n_bytes / sizeof *p; i != 0; i--)
412 16 : printf (fmt_string, *p++);
413 2 : }
414 :
415 : static void
416 1 : print_s_short (size_t n_bytes, void const *block, char const *fmt_string)
417 : {
418 1 : short int const *p = block;
419 : size_t i;
420 5 : for (i = n_bytes / sizeof *p; i != 0; i--)
421 4 : printf (fmt_string, *p++);
422 1 : }
423 :
424 : static void
425 53 : print_short (size_t n_bytes, void const *block, char const *fmt_string)
426 : {
427 53 : unsigned short int const *p = block;
428 : size_t i;
429 274 : for (i = n_bytes / sizeof *p; i != 0; i--)
430 221 : printf (fmt_string, *p++);
431 53 : }
432 :
433 : static void
434 6 : print_int (size_t n_bytes, void const *block, char const *fmt_string)
435 : {
436 6 : unsigned int const *p = block;
437 : size_t i;
438 18 : for (i = n_bytes / sizeof *p; i != 0; i--)
439 12 : printf (fmt_string, *p++);
440 6 : }
441 :
442 : static void
443 0 : print_long (size_t n_bytes, void const *block, char const *fmt_string)
444 : {
445 0 : unsigned long int const *p = block;
446 : size_t i;
447 0 : for (i = n_bytes / sizeof *p; i != 0; i--)
448 0 : printf (fmt_string, *p++);
449 0 : }
450 :
451 : static void
452 5 : print_long_long (size_t n_bytes, void const *block, char const *fmt_string)
453 : {
454 5 : unsigned_long_long_int const *p = block;
455 : size_t i;
456 10 : for (i = n_bytes / sizeof *p; i != 0; i--)
457 5 : printf (fmt_string, *p++);
458 5 : }
459 :
460 : static void
461 2 : print_float (size_t n_bytes, void const *block, char const *fmt_string)
462 : {
463 2 : float const *p = block;
464 : size_t i;
465 6 : for (i = n_bytes / sizeof *p; i != 0; i--)
466 4 : printf (fmt_string, *p++);
467 2 : }
468 :
469 : static void
470 3 : print_double (size_t n_bytes, void const *block, char const *fmt_string)
471 : {
472 3 : double const *p = block;
473 : size_t i;
474 7 : for (i = n_bytes / sizeof *p; i != 0; i--)
475 4 : printf (fmt_string, *p++);
476 3 : }
477 :
478 : #ifdef HAVE_LONG_DOUBLE
479 : static void
480 1 : print_long_double (size_t n_bytes, void const *block, char const *fmt_string)
481 : {
482 1 : long double const *p = block;
483 : size_t i;
484 2 : for (i = n_bytes / sizeof *p; i != 0; i--)
485 1 : printf (fmt_string, *p++);
486 1 : }
487 : #endif
488 :
489 : static void
490 2 : dump_hexl_mode_trailer (size_t n_bytes, const char *block)
491 : {
492 : size_t i;
493 2 : fputs (" >", stdout);
494 26 : for (i = n_bytes; i > 0; i--)
495 : {
496 24 : unsigned char c = *block++;
497 24 : unsigned char c2 = (isprint (c) ? c : '.');
498 24 : putchar (c2);
499 : }
500 2 : putchar ('<');
501 2 : }
502 :
503 : static void
504 7 : print_named_ascii (size_t n_bytes, void const *block,
505 : const char *unused_fmt_string ATTRIBUTE_UNUSED)
506 : {
507 7 : unsigned char const *p = block;
508 : size_t i;
509 63 : for (i = n_bytes; i > 0; i--)
510 : {
511 56 : int masked_c = *p++ & 0x7f;
512 : const char *s;
513 : char buf[5];
514 :
515 56 : if (masked_c == 127)
516 52 : s = "del";
517 4 : else if (masked_c <= 040)
518 2 : s = charname[masked_c];
519 : else
520 : {
521 2 : sprintf (buf, " %c", masked_c);
522 2 : s = buf;
523 : }
524 :
525 56 : printf (" %3s", s);
526 : }
527 7 : }
528 :
529 : static void
530 9 : print_ascii (size_t n_bytes, void const *block,
531 : const char *unused_fmt_string ATTRIBUTE_UNUSED)
532 : {
533 9 : unsigned char const *p = block;
534 : size_t i;
535 81 : for (i = n_bytes; i > 0; i--)
536 : {
537 72 : unsigned char c = *p++;
538 : const char *s;
539 : char buf[5];
540 :
541 72 : switch (c)
542 : {
543 61 : case '\0':
544 61 : s = " \\0";
545 61 : break;
546 :
547 1 : case '\a':
548 1 : s = " \\a";
549 1 : break;
550 :
551 1 : case '\b':
552 1 : s = " \\b";
553 1 : break;
554 :
555 1 : case '\f':
556 1 : s = " \\f";
557 1 : break;
558 :
559 2 : case '\n':
560 2 : s = " \\n";
561 2 : break;
562 :
563 1 : case '\r':
564 1 : s = " \\r";
565 1 : break;
566 :
567 1 : case '\t':
568 1 : s = " \\t";
569 1 : break;
570 :
571 3 : case '\v':
572 3 : s = " \\v";
573 3 : break;
574 :
575 1 : default:
576 1 : sprintf (buf, (isprint (c) ? " %c" : "%03o"), c);
577 1 : s = buf;
578 : }
579 :
580 72 : printf (" %3s", s);
581 : }
582 9 : }
583 :
584 : /* Convert a null-terminated (possibly zero-length) string S to an
585 : unsigned long integer value. If S points to a non-digit set *P to S,
586 : *VAL to 0, and return true. Otherwise, accumulate the integer value of
587 : the string of digits. If the string of digits represents a value
588 : larger than ULONG_MAX, don't modify *VAL or *P and return false.
589 : Otherwise, advance *P to the first non-digit after S, set *VAL to
590 : the result of the conversion and return true. */
591 :
592 : static bool
593 15 : simple_strtoul (const char *s, const char **p, unsigned long int *val)
594 : {
595 : unsigned long int sum;
596 :
597 15 : sum = 0;
598 42 : while (ISDIGIT (*s))
599 : {
600 12 : int c = *s++ - '0';
601 12 : if (sum > (ULONG_MAX - c) / 10)
602 0 : return false;
603 12 : sum = sum * 10 + c;
604 : }
605 15 : *p = s;
606 15 : *val = sum;
607 15 : return true;
608 : }
609 :
610 : /* If S points to a single valid modern od format string, put
611 : a description of that format in *TSPEC, make *NEXT point at the
612 : character following the just-decoded format (if *NEXT is non-NULL),
613 : and return true. If S is not valid, don't modify *NEXT or *TSPEC,
614 : give a diagnostic, and return false. For example, if S were
615 : "d4afL" *NEXT would be set to "afL" and *TSPEC would be
616 : {
617 : fmt = SIGNED_DECIMAL;
618 : size = INT or LONG; (whichever integral_type_size[4] resolves to)
619 : print_function = print_int; (assuming size == INT)
620 : fmt_string = "%011d%c";
621 : }
622 : S_ORIG is solely for reporting errors. It should be the full format
623 : string argument.
624 : */
625 :
626 : static bool
627 137 : decode_one_format (const char *s_orig, const char *s, const char **next,
628 : struct tspec *tspec)
629 : {
630 : enum size_spec size_spec;
631 : unsigned long int size;
632 : enum output_format fmt;
633 : const char *pre_fmt_string;
634 : void (*print_function) (size_t, void const *, char const *);
635 : const char *p;
636 : char c;
637 : int field_width;
638 : int precision;
639 :
640 137 : assert (tspec != NULL);
641 :
642 137 : switch (*s)
643 : {
644 97 : case 'd':
645 : case 'o':
646 : case 'u':
647 : case 'x':
648 97 : c = *s;
649 97 : ++s;
650 97 : switch (*s)
651 : {
652 1 : case 'C':
653 1 : ++s;
654 1 : size = sizeof (char);
655 1 : break;
656 :
657 78 : case 'S':
658 78 : ++s;
659 78 : size = sizeof (short int);
660 78 : break;
661 :
662 1 : case 'I':
663 1 : ++s;
664 1 : size = sizeof (int);
665 1 : break;
666 :
667 5 : case 'L':
668 5 : ++s;
669 5 : size = sizeof (long int);
670 5 : break;
671 :
672 12 : default:
673 12 : if (! simple_strtoul (s, &p, &size))
674 : {
675 : /* The integer at P in S would overflow an unsigned long int.
676 : A digit string that long is sufficiently odd looking
677 : that the following diagnostic is sufficient. */
678 0 : error (0, 0, _("invalid type string %s"), quote (s_orig));
679 0 : return false;
680 : }
681 12 : if (p == s)
682 2 : size = sizeof (int);
683 : else
684 : {
685 10 : if (MAX_INTEGRAL_TYPE_SIZE < size
686 9 : || integral_type_size[size] == NO_SIZE)
687 : {
688 1 : error (0, 0, _("invalid type string %s;\n\
689 : this system doesn't provide a %lu-byte integral type"), quote (s_orig), size);
690 1 : return false;
691 : }
692 9 : s = p;
693 : }
694 11 : break;
695 : }
696 :
697 : #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
698 : ((Spec) == LONG_LONG ? (Max_format) \
699 : : ((Spec) == LONG ? (Long_format) \
700 : : (Min_format))) \
701 :
702 96 : size_spec = integral_type_size[size];
703 :
704 96 : switch (c)
705 : {
706 3 : case 'd':
707 3 : fmt = SIGNED_DECIMAL;
708 8 : sprintf (tspec->fmt_string, " %%%d%s",
709 3 : (field_width = bytes_to_signed_dec_digits[size]),
710 2 : ISPEC_TO_FORMAT (size_spec, "d", "ld", PRIdMAX));
711 3 : break;
712 :
713 83 : case 'o':
714 83 : fmt = OCTAL;
715 248 : sprintf (tspec->fmt_string, " %%0%d%s",
716 83 : (field_width = bytes_to_oct_digits[size]),
717 82 : ISPEC_TO_FORMAT (size_spec, "o", "lo", PRIoMAX));
718 83 : break;
719 :
720 7 : case 'u':
721 7 : fmt = UNSIGNED_DECIMAL;
722 19 : sprintf (tspec->fmt_string, " %%%d%s",
723 7 : (field_width = bytes_to_unsigned_dec_digits[size]),
724 5 : ISPEC_TO_FORMAT (size_spec, "u", "lu", PRIuMAX));
725 7 : break;
726 :
727 3 : case 'x':
728 3 : fmt = HEXADECIMAL;
729 8 : sprintf (tspec->fmt_string, " %%0%d%s",
730 3 : (field_width = bytes_to_hex_digits[size]),
731 2 : ISPEC_TO_FORMAT (size_spec, "x", "lx", PRIxMAX));
732 3 : break;
733 :
734 0 : default:
735 0 : abort ();
736 : }
737 :
738 96 : assert (strlen (tspec->fmt_string) < FMT_BYTES_ALLOCATED);
739 :
740 96 : switch (size_spec)
741 : {
742 2 : case CHAR:
743 2 : print_function = (fmt == SIGNED_DECIMAL
744 : ? print_s_char
745 2 : : print_char);
746 2 : break;
747 :
748 83 : case SHORT:
749 83 : print_function = (fmt == SIGNED_DECIMAL
750 : ? print_s_short
751 83 : : print_short);
752 83 : break;
753 :
754 6 : case INT:
755 6 : print_function = print_int;
756 6 : break;
757 :
758 0 : case LONG:
759 0 : print_function = print_long;
760 0 : break;
761 :
762 5 : case LONG_LONG:
763 5 : print_function = print_long_long;
764 5 : break;
765 :
766 0 : default:
767 0 : abort ();
768 : }
769 96 : break;
770 :
771 7 : case 'f':
772 7 : fmt = FLOATING_POINT;
773 7 : ++s;
774 7 : switch (*s)
775 : {
776 1 : case 'F':
777 1 : ++s;
778 1 : size = sizeof (float);
779 1 : break;
780 :
781 2 : case 'D':
782 2 : ++s;
783 2 : size = sizeof (double);
784 2 : break;
785 :
786 1 : case 'L':
787 1 : ++s;
788 1 : size = sizeof (LONG_DOUBLE);
789 1 : break;
790 :
791 3 : default:
792 3 : if (! simple_strtoul (s, &p, &size))
793 : {
794 : /* The integer at P in S would overflow an unsigned long int.
795 : A digit string that long is sufficiently odd looking
796 : that the following diagnostic is sufficient. */
797 0 : error (0, 0, _("invalid type string %s"), quote (s_orig));
798 0 : return false;
799 : }
800 3 : if (p == s)
801 1 : size = sizeof (double);
802 : else
803 : {
804 2 : if (size > MAX_FP_TYPE_SIZE
805 2 : || fp_type_size[size] == NO_SIZE)
806 : {
807 1 : error (0, 0, _("invalid type string %s;\n\
808 : this system doesn't provide a %lu-byte floating point type"),
809 : quote (s_orig), size);
810 1 : return false;
811 : }
812 1 : s = p;
813 : }
814 2 : break;
815 : }
816 6 : size_spec = fp_type_size[size];
817 :
818 6 : switch (size_spec)
819 : {
820 2 : case FLOAT_SINGLE:
821 2 : print_function = print_float;
822 : /* Don't use %#e; not all systems support it. */
823 2 : pre_fmt_string = " %%%d.%de";
824 2 : precision = FLT_DIG;
825 2 : break;
826 :
827 3 : case FLOAT_DOUBLE:
828 3 : print_function = print_double;
829 3 : pre_fmt_string = " %%%d.%de";
830 3 : precision = DBL_DIG;
831 3 : break;
832 :
833 : #ifdef HAVE_LONG_DOUBLE
834 1 : case FLOAT_LONG_DOUBLE:
835 1 : print_function = print_long_double;
836 1 : pre_fmt_string = " %%%d.%dLe";
837 1 : precision = LDBL_DIG;
838 1 : break;
839 : #endif
840 :
841 0 : default:
842 0 : abort ();
843 : }
844 :
845 6 : field_width = precision + 8;
846 6 : sprintf (tspec->fmt_string, pre_fmt_string, field_width, precision);
847 6 : break;
848 :
849 9 : case 'a':
850 9 : ++s;
851 9 : fmt = NAMED_CHARACTER;
852 9 : size_spec = CHAR;
853 9 : print_function = print_named_ascii;
854 9 : field_width = 3;
855 9 : break;
856 :
857 9 : case 'c':
858 9 : ++s;
859 9 : fmt = CHARACTER;
860 9 : size_spec = CHAR;
861 9 : print_function = print_ascii;
862 9 : field_width = 3;
863 9 : break;
864 :
865 15 : default:
866 30 : error (0, 0, _("invalid character `%c' in type string %s"),
867 15 : *s, quote (s_orig));
868 15 : return false;
869 : }
870 :
871 120 : tspec->size = size_spec;
872 120 : tspec->fmt = fmt;
873 120 : tspec->print_function = print_function;
874 :
875 120 : tspec->field_width = field_width;
876 120 : tspec->hexl_mode_trailer = (*s == 'z');
877 120 : if (tspec->hexl_mode_trailer)
878 2 : s++;
879 :
880 120 : if (next != NULL)
881 120 : *next = s;
882 :
883 120 : return true;
884 : }
885 :
886 : /* Given a list of one or more input filenames FILE_LIST, set the global
887 : file pointer IN_STREAM and the global string INPUT_FILENAME to the
888 : first one that can be successfully opened. Modify FILE_LIST to
889 : reference the next filename in the list. A file name of "-" is
890 : interpreted as standard input. If any file open fails, give an error
891 : message and return false. */
892 :
893 : static bool
894 235 : open_next_file (void)
895 : {
896 235 : bool ok = true;
897 :
898 : do
899 : {
900 257 : input_filename = *file_list;
901 257 : if (input_filename == NULL)
902 112 : return ok;
903 145 : ++file_list;
904 :
905 145 : if (STREQ (input_filename, "-"))
906 : {
907 111 : input_filename = _("standard input");
908 111 : in_stream = stdin;
909 111 : have_read_stdin = true;
910 : if (O_BINARY && ! isatty (STDIN_FILENO))
911 : freopen (NULL, "rb", stdin);
912 : }
913 : else
914 : {
915 34 : in_stream = fopen (input_filename, (O_BINARY ? "rb" : "r"));
916 34 : if (in_stream == NULL)
917 : {
918 22 : error (0, errno, "%s", input_filename);
919 22 : ok = false;
920 : }
921 : }
922 : }
923 145 : while (in_stream == NULL);
924 :
925 123 : if (limit_bytes_to_format & !flag_dump_strings)
926 11 : setvbuf (in_stream, NULL, _IONBF, 0);
927 :
928 123 : return ok;
929 : }
930 :
931 : /* Test whether there have been errors on in_stream, and close it if
932 : it is not standard input. Return false if there has been an error
933 : on in_stream or stdout; return true otherwise. This function will
934 : report more than one error only if both a read and a write error
935 : have occurred. IN_ERRNO, if nonzero, is the error number
936 : corresponding to the most recent action for IN_STREAM. */
937 :
938 : static bool
939 122 : check_and_close (int in_errno)
940 : {
941 122 : bool ok = true;
942 :
943 122 : if (in_stream != NULL)
944 : {
945 122 : if (ferror (in_stream))
946 : {
947 9 : error (0, in_errno, _("%s: read error"), input_filename);
948 9 : if (! STREQ (file_list[-1], "-"))
949 9 : fclose (in_stream);
950 9 : ok = false;
951 : }
952 113 : else if (! STREQ (file_list[-1], "-") && fclose (in_stream) != 0)
953 : {
954 0 : error (0, errno, "%s", input_filename);
955 0 : ok = false;
956 : }
957 :
958 122 : in_stream = NULL;
959 : }
960 :
961 122 : if (ferror (stdout))
962 : {
963 0 : error (0, 0, _("write error"));
964 0 : ok = false;
965 : }
966 :
967 122 : return ok;
968 : }
969 :
970 : /* Decode the modern od format string S. Append the decoded
971 : representation to the global array SPEC, reallocating SPEC if
972 : necessary. Return true if S is valid. */
973 :
974 : static bool
975 136 : decode_format_string (const char *s)
976 : {
977 136 : const char *s_orig = s;
978 136 : assert (s != NULL);
979 :
980 392 : while (*s != '\0')
981 : {
982 : const char *next;
983 :
984 137 : if (n_specs_allocated <= n_specs)
985 137 : spec = X2NREALLOC (spec, &n_specs_allocated);
986 :
987 137 : if (! decode_one_format (s_orig, s, &next, &spec[n_specs]))
988 17 : return false;
989 :
990 120 : assert (s != next);
991 120 : s = next;
992 120 : ++n_specs;
993 : }
994 :
995 119 : return true;
996 : }
997 :
998 : /* Given a list of one or more input filenames FILE_LIST, set the global
999 : file pointer IN_STREAM to position N_SKIP in the concatenation of
1000 : those files. If any file operation fails or if there are fewer than
1001 : N_SKIP bytes in the combined input, give an error message and return
1002 : false. When possible, use seek rather than read operations to
1003 : advance IN_STREAM. */
1004 :
1005 : static bool
1006 104 : skip (uintmax_t n_skip)
1007 : {
1008 104 : bool ok = true;
1009 104 : int in_errno = 0;
1010 :
1011 104 : if (n_skip == 0)
1012 97 : return true;
1013 :
1014 15 : while (in_stream != NULL) /* EOF. */
1015 : {
1016 : struct stat file_stats;
1017 :
1018 : /* First try seeking. For large offsets, this extra work is
1019 : worthwhile. If the offset is below some threshold it may be
1020 : more efficient to move the pointer by reading. There are two
1021 : issues when trying to seek:
1022 : - the file must be seekable.
1023 : - before seeking to the specified position, make sure
1024 : that the new position is in the current file.
1025 : Try to do that by getting file's size using fstat.
1026 : But that will work only for regular files. */
1027 :
1028 7 : if (fstat (fileno (in_stream), &file_stats) == 0)
1029 : {
1030 : /* The st_size field is valid only for regular files
1031 : (and for symbolic links, which cannot occur here).
1032 : If the number of bytes left to skip is larger than
1033 : the size of the current file, we can decrement n_skip
1034 : and go on to the next file. Skip this optimization also
1035 : when st_size is 0, because some kernels report that
1036 : nonempty files in /proc have st_size == 0. */
1037 7 : if (S_ISREG (file_stats.st_mode) && 0 < file_stats.st_size)
1038 : {
1039 4 : if ((uintmax_t) file_stats.st_size < n_skip)
1040 1 : n_skip -= file_stats.st_size;
1041 : else
1042 : {
1043 1 : if (fseeko (in_stream, n_skip, SEEK_CUR) != 0)
1044 : {
1045 0 : in_errno = errno;
1046 0 : ok = false;
1047 : }
1048 1 : n_skip = 0;
1049 : }
1050 : }
1051 :
1052 : /* If it's not a regular file with nonnegative size,
1053 : position the file pointer by reading. */
1054 :
1055 : else
1056 : {
1057 : char buf[BUFSIZ];
1058 5 : size_t n_bytes_read, n_bytes_to_read = BUFSIZ;
1059 :
1060 12 : while (0 < n_skip)
1061 : {
1062 5 : if (n_skip < n_bytes_to_read)
1063 4 : n_bytes_to_read = n_skip;
1064 5 : n_bytes_read = fread (buf, 1, n_bytes_to_read, in_stream);
1065 5 : n_skip -= n_bytes_read;
1066 5 : if (n_bytes_read != n_bytes_to_read)
1067 : {
1068 3 : in_errno = errno;
1069 3 : ok = false;
1070 3 : n_skip = 0;
1071 3 : break;
1072 : }
1073 : }
1074 : }
1075 :
1076 7 : if (n_skip == 0)
1077 6 : break;
1078 : }
1079 :
1080 : else /* cannot fstat() file */
1081 : {
1082 0 : error (0, errno, "%s", input_filename);
1083 0 : ok = false;
1084 : }
1085 :
1086 1 : ok &= check_and_close (in_errno);
1087 :
1088 1 : ok &= open_next_file ();
1089 : }
1090 :
1091 7 : if (n_skip != 0)
1092 1 : error (EXIT_FAILURE, 0, _("cannot skip past end of combined input"));
1093 :
1094 6 : return ok;
1095 : }
1096 :
1097 : static void
1098 2 : format_address_none (uintmax_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
1099 : {
1100 2 : }
1101 :
1102 : static void
1103 200 : format_address_std (uintmax_t address, char c)
1104 : {
1105 : char buf[MAX_ADDRESS_LENGTH + 2];
1106 200 : char *p = buf + sizeof buf;
1107 : char const *pbound;
1108 :
1109 200 : *--p = '\0';
1110 200 : *--p = c;
1111 200 : pbound = p - address_pad_len;
1112 :
1113 : /* Use a special case of the code for each base. This is measurably
1114 : faster than generic code. */
1115 200 : switch (address_base)
1116 : {
1117 390 : case 8:
1118 : do
1119 289 : *--p = '0' + (address & 7);
1120 289 : while ((address >>= 3) != 0);
1121 188 : break;
1122 :
1123 1 : case 10:
1124 : do
1125 5 : *--p = '0' + (address % 10);
1126 5 : while ((address /= 10) != 0);
1127 4 : break;
1128 :
1129 1 : case 16:
1130 : do
1131 9 : *--p = "0123456789abcdef"[address & 15];
1132 9 : while ((address >>= 4) != 0);
1133 8 : break;
1134 : }
1135 :
1136 1503 : while (pbound < p)
1137 1103 : *--p = '0';
1138 :
1139 200 : fputs (p, stdout);
1140 200 : }
1141 :
1142 : static void
1143 0 : format_address_paren (uintmax_t address, char c)
1144 : {
1145 0 : putchar ('(');
1146 0 : format_address_std (address, ')');
1147 0 : if (c)
1148 0 : putchar (c);
1149 0 : }
1150 :
1151 : static void
1152 0 : format_address_label (uintmax_t address, char c)
1153 : {
1154 0 : format_address_std (address, ' ');
1155 0 : format_address_paren (address + pseudo_offset, c);
1156 0 : }
1157 :
1158 : /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
1159 : of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
1160 : CURR_BLOCK in the concatenation of input files, and it is printed
1161 : (optionally) only before the output line associated with the first
1162 : format spec. When duplicate blocks are being abbreviated, the output
1163 : for a sequence of identical input blocks is the output for the first
1164 : block followed by an asterisk alone on a line. It is valid to compare
1165 : the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
1166 : That condition may be false only for the last input block -- and then
1167 : only when it has not been padded to length BYTES_PER_BLOCK. */
1168 :
1169 : static void
1170 90 : write_block (uintmax_t current_offset, size_t n_bytes,
1171 : const char *prev_block, const char *curr_block)
1172 : {
1173 : static bool first = true;
1174 : static bool prev_pair_equal = false;
1175 :
1176 : #define EQUAL_BLOCKS(b1, b2) (memcmp (b1, b2, bytes_per_block) == 0)
1177 :
1178 90 : if (abbreviate_duplicate_blocks
1179 89 : && !first && n_bytes == bytes_per_block
1180 4 : && EQUAL_BLOCKS (prev_block, curr_block))
1181 : {
1182 8 : if (prev_pair_equal)
1183 : {
1184 : /* The two preceding blocks were equal, and the current
1185 : block is the same as the last one, so print nothing. */
1186 : }
1187 : else
1188 : {
1189 2 : printf ("*\n");
1190 2 : prev_pair_equal = true;
1191 : }
1192 : }
1193 : else
1194 : {
1195 : size_t i;
1196 :
1197 86 : prev_pair_equal = false;
1198 175 : for (i = 0; i < n_specs; i++)
1199 : {
1200 89 : if (i == 0)
1201 86 : format_address (current_offset, '\0');
1202 : else
1203 3 : printf ("%*s", address_pad_len, "");
1204 89 : (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
1205 89 : if (spec[i].hexl_mode_trailer)
1206 : {
1207 : /* space-pad out to full line width, then dump the trailer */
1208 2 : int datum_width = width_bytes[spec[i].size];
1209 2 : int blank_fields = (bytes_per_block - n_bytes) / datum_width;
1210 2 : int field_width = spec[i].field_width + 1;
1211 2 : printf ("%*s", blank_fields * field_width, "");
1212 2 : dump_hexl_mode_trailer (n_bytes, curr_block);
1213 : }
1214 89 : putchar ('\n');
1215 : }
1216 : }
1217 90 : first = false;
1218 90 : }
1219 :
1220 : /* Read a single byte into *C from the concatenation of the input files
1221 : named in the global array FILE_LIST. On the first call to this
1222 : function, the global variable IN_STREAM is expected to be an open
1223 : stream associated with the input file INPUT_FILENAME. If IN_STREAM
1224 : is at end-of-file, close it and update the global variables IN_STREAM
1225 : and INPUT_FILENAME so they correspond to the next file in the list.
1226 : Then try to read a byte from the newly opened file. Repeat if
1227 : necessary until EOF is reached for the last file in FILE_LIST, then
1228 : set *C to EOF and return. Subsequent calls do likewise. Return
1229 : true if successful. */
1230 :
1231 : static bool
1232 90 : read_char (int *c)
1233 : {
1234 90 : bool ok = true;
1235 :
1236 90 : *c = EOF;
1237 :
1238 191 : while (in_stream != NULL) /* EOF. */
1239 : {
1240 91 : *c = fgetc (in_stream);
1241 :
1242 91 : if (*c != EOF)
1243 80 : break;
1244 :
1245 11 : ok &= check_and_close (errno);
1246 :
1247 11 : ok &= open_next_file ();
1248 : }
1249 :
1250 90 : return ok;
1251 : }
1252 :
1253 : /* Read N bytes into BLOCK from the concatenation of the input files
1254 : named in the global array FILE_LIST. On the first call to this
1255 : function, the global variable IN_STREAM is expected to be an open
1256 : stream associated with the input file INPUT_FILENAME. If all N
1257 : bytes cannot be read from IN_STREAM, close IN_STREAM and update
1258 : the global variables IN_STREAM and INPUT_FILENAME. Then try to
1259 : read the remaining bytes from the newly opened file. Repeat if
1260 : necessary until EOF is reached for the last file in FILE_LIST.
1261 : On subsequent calls, don't modify BLOCK and return true. Set
1262 : *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1263 : it will be detected through ferror when the stream is about to be
1264 : closed. If there is an error, give a message but continue reading
1265 : as usual and return false. Otherwise return true. */
1266 :
1267 : static bool
1268 102 : read_block (size_t n, char *block, size_t *n_bytes_in_buffer)
1269 : {
1270 102 : bool ok = true;
1271 :
1272 102 : assert (0 < n && n <= bytes_per_block);
1273 :
1274 102 : *n_bytes_in_buffer = 0;
1275 :
1276 102 : if (n == 0)
1277 0 : return true;
1278 :
1279 311 : while (in_stream != NULL) /* EOF. */
1280 : {
1281 : size_t n_needed;
1282 : size_t n_read;
1283 :
1284 120 : n_needed = n - *n_bytes_in_buffer;
1285 120 : n_read = fread (block + *n_bytes_in_buffer, 1, n_needed, in_stream);
1286 :
1287 120 : *n_bytes_in_buffer += n_read;
1288 :
1289 120 : if (n_read == n_needed)
1290 13 : break;
1291 :
1292 107 : ok &= check_and_close (errno);
1293 :
1294 107 : ok &= open_next_file ();
1295 : }
1296 :
1297 102 : return ok;
1298 : }
1299 :
1300 : /* Return the least common multiple of the sizes associated
1301 : with the format specs. */
1302 :
1303 : static int
1304 181 : get_lcm (void)
1305 : {
1306 : size_t i;
1307 181 : int l_c_m = 1;
1308 :
1309 368 : for (i = 0; i < n_specs; i++)
1310 187 : l_c_m = lcm (l_c_m, width_bytes[spec[i].size]);
1311 181 : return l_c_m;
1312 : }
1313 :
1314 : /* If S is a valid traditional offset specification with an optional
1315 : leading '+' return true and set *OFFSET to the offset it denotes. */
1316 :
1317 : static bool
1318 25 : parse_old_offset (const char *s, uintmax_t *offset)
1319 : {
1320 : int radix;
1321 :
1322 25 : if (*s == '\0')
1323 1 : return false;
1324 :
1325 : /* Skip over any leading '+'. */
1326 24 : if (s[0] == '+')
1327 17 : ++s;
1328 :
1329 : /* Determine the radix we'll use to interpret S. If there is a `.',
1330 : it's decimal, otherwise, if the string begins with `0X'or `0x',
1331 : it's hexadecimal, else octal. */
1332 24 : if (strchr (s, '.') != NULL)
1333 8 : radix = 10;
1334 : else
1335 : {
1336 16 : if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1337 2 : radix = 16;
1338 : else
1339 14 : radix = 8;
1340 : }
1341 :
1342 24 : return xstrtoumax (s, NULL, radix, offset, "Bb") == LONGINT_OK;
1343 : }
1344 :
1345 : /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
1346 : formatted block to standard output, and repeat until the specified
1347 : maximum number of bytes has been read or until all input has been
1348 : processed. If the last block read is smaller than BYTES_PER_BLOCK
1349 : and its size is not a multiple of the size associated with a format
1350 : spec, extend the input block with zero bytes until its length is a
1351 : multiple of all format spec sizes. Write the final block. Finally,
1352 : write on a line by itself the offset of the byte after the last byte
1353 : read. Accumulate return values from calls to read_block and
1354 : check_and_close, and if any was false, return false.
1355 : Otherwise, return true. */
1356 :
1357 : static bool
1358 92 : dump (void)
1359 : {
1360 : char *block[2];
1361 : uintmax_t current_offset;
1362 92 : bool idx = false;
1363 92 : bool ok = true;
1364 : size_t n_bytes_read;
1365 :
1366 92 : block[0] = xnmalloc (2, bytes_per_block);
1367 92 : block[1] = block[0] + bytes_per_block;
1368 :
1369 92 : current_offset = n_bytes_to_skip;
1370 :
1371 92 : if (limit_bytes_to_format)
1372 : {
1373 : while (1)
1374 0 : {
1375 : size_t n_needed;
1376 11 : if (current_offset >= end_offset)
1377 : {
1378 2 : n_bytes_read = 0;
1379 2 : break;
1380 : }
1381 9 : n_needed = MIN (end_offset - current_offset,
1382 : (uintmax_t) bytes_per_block);
1383 9 : ok &= read_block (n_needed, block[idx], &n_bytes_read);
1384 9 : if (n_bytes_read < bytes_per_block)
1385 9 : break;
1386 0 : assert (n_bytes_read == bytes_per_block);
1387 0 : write_block (current_offset, n_bytes_read,
1388 0 : block[!idx], block[idx]);
1389 0 : current_offset += n_bytes_read;
1390 0 : idx = !idx;
1391 : }
1392 : }
1393 : else
1394 : {
1395 : while (1)
1396 : {
1397 105 : ok &= read_block (bytes_per_block, block[idx], &n_bytes_read);
1398 93 : if (n_bytes_read < bytes_per_block)
1399 81 : break;
1400 12 : assert (n_bytes_read == bytes_per_block);
1401 24 : write_block (current_offset, n_bytes_read,
1402 12 : block[!idx], block[idx]);
1403 12 : current_offset += n_bytes_read;
1404 12 : idx = !idx;
1405 : }
1406 : }
1407 :
1408 92 : if (n_bytes_read > 0)
1409 : {
1410 : int l_c_m;
1411 : size_t bytes_to_write;
1412 :
1413 78 : l_c_m = get_lcm ();
1414 :
1415 : /* Make bytes_to_write the smallest multiple of l_c_m that
1416 : is at least as large as n_bytes_read. */
1417 78 : bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1418 :
1419 78 : memset (block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1420 156 : write_block (current_offset, bytes_to_write,
1421 78 : block[!idx], block[idx]);
1422 78 : current_offset += n_bytes_read;
1423 : }
1424 :
1425 92 : format_address (current_offset, '\n');
1426 :
1427 92 : if (limit_bytes_to_format && current_offset >= end_offset)
1428 3 : ok &= check_and_close (0);
1429 :
1430 92 : free (block[0]);
1431 :
1432 92 : return ok;
1433 : }
1434 :
1435 : /* STRINGS mode. Find each "string constant" in the input.
1436 : A string constant is a run of at least `string_min' ASCII
1437 : graphic (or formatting) characters terminated by a null.
1438 : Based on a function written by Richard Stallman for a
1439 : traditional version of od. Return true if successful. */
1440 :
1441 : static bool
1442 11 : dump_strings (void)
1443 : {
1444 11 : size_t bufsize = MAX (100, string_min);
1445 11 : char *buf = xmalloc (bufsize);
1446 10 : uintmax_t address = n_bytes_to_skip;
1447 10 : bool ok = true;
1448 :
1449 : while (1)
1450 24 : {
1451 : size_t i;
1452 : int c;
1453 :
1454 : /* See if the next `string_min' chars are all printing chars. */
1455 76 : tryline:
1456 :
1457 76 : if (limit_bytes_to_format
1458 0 : && (end_offset < string_min || end_offset - string_min <= address))
1459 : break;
1460 :
1461 88 : for (i = 0; i < string_min; i++)
1462 : {
1463 59 : ok &= read_char (&c);
1464 59 : address++;
1465 59 : if (c < 0)
1466 : {
1467 7 : free (buf);
1468 17 : return ok;
1469 : }
1470 52 : if (! isprint (c))
1471 : /* Found a non-printing. Try again starting with next char. */
1472 40 : goto tryline;
1473 12 : buf[i] = c;
1474 : }
1475 :
1476 : /* We found a run of `string_min' printable characters.
1477 : Now see if it is terminated with a null byte. */
1478 60 : while (!limit_bytes_to_format || address < end_offset)
1479 : {
1480 31 : if (i == bufsize)
1481 : {
1482 0 : buf = X2REALLOC (buf, &bufsize);
1483 : }
1484 31 : ok &= read_char (&c);
1485 31 : address++;
1486 31 : if (c < 0)
1487 : {
1488 3 : free (buf);
1489 3 : return ok;
1490 : }
1491 28 : if (c == '\0')
1492 24 : break; /* It is; print this string. */
1493 4 : if (! isprint (c))
1494 2 : goto tryline; /* It isn't; give up on this string. */
1495 2 : buf[i++] = c; /* String continues; store it all. */
1496 : }
1497 :
1498 : /* If we get here, the string is all printable and null-terminated,
1499 : so print it. It is all in `buf' and `i' is its length. */
1500 24 : buf[i] = 0;
1501 24 : format_address (address - i - 1, ' ');
1502 :
1503 32 : for (i = 0; (c = buf[i]); i++)
1504 : {
1505 8 : switch (c)
1506 : {
1507 0 : case '\a':
1508 0 : fputs ("\\a", stdout);
1509 0 : break;
1510 :
1511 0 : case '\b':
1512 0 : fputs ("\\b", stdout);
1513 0 : break;
1514 :
1515 0 : case '\f':
1516 0 : fputs ("\\f", stdout);
1517 0 : break;
1518 :
1519 0 : case '\n':
1520 0 : fputs ("\\n", stdout);
1521 0 : break;
1522 :
1523 0 : case '\r':
1524 0 : fputs ("\\r", stdout);
1525 0 : break;
1526 :
1527 0 : case '\t':
1528 0 : fputs ("\\t", stdout);
1529 0 : break;
1530 :
1531 0 : case '\v':
1532 0 : fputs ("\\v", stdout);
1533 0 : break;
1534 :
1535 8 : default:
1536 8 : putc (c, stdout);
1537 : }
1538 : }
1539 24 : putchar ('\n');
1540 : }
1541 :
1542 : /* We reach this point only if we search through
1543 : (max_bytes_to_format - string_min) bytes before reaching EOF. */
1544 :
1545 0 : free (buf);
1546 :
1547 0 : ok &= check_and_close (0);
1548 0 : return ok;
1549 : }
1550 :
1551 : int
1552 156 : main (int argc, char **argv)
1553 : {
1554 : int n_files;
1555 : size_t i;
1556 : int l_c_m;
1557 : size_t desired_width IF_LINT (= 0);
1558 156 : bool modern = false;
1559 156 : bool width_specified = false;
1560 156 : bool ok = true;
1561 : static char const multipliers[] = "bEGKkMmPTYZ0";
1562 :
1563 : /* The old-style `pseudo starting address' to be printed in parentheses
1564 : after any true address. */
1565 : uintmax_t pseudo_start IF_LINT (= 0);
1566 :
1567 : initialize_main (&argc, &argv);
1568 156 : program_name = argv[0];
1569 156 : setlocale (LC_ALL, "");
1570 : bindtextdomain (PACKAGE, LOCALEDIR);
1571 : textdomain (PACKAGE);
1572 :
1573 156 : atexit (close_stdout);
1574 :
1575 1560 : for (i = 0; i <= MAX_INTEGRAL_TYPE_SIZE; i++)
1576 1404 : integral_type_size[i] = NO_SIZE;
1577 :
1578 156 : integral_type_size[sizeof (char)] = CHAR;
1579 156 : integral_type_size[sizeof (short int)] = SHORT;
1580 156 : integral_type_size[sizeof (int)] = INT;
1581 156 : integral_type_size[sizeof (long int)] = LONG;
1582 : #if HAVE_UNSIGNED_LONG_LONG_INT
1583 : /* If `long int' and `long long int' have the same size, it's fine
1584 : to overwrite the entry for `long' with this one. */
1585 156 : integral_type_size[sizeof (unsigned_long_long_int)] = LONG_LONG;
1586 : #endif
1587 :
1588 2808 : for (i = 0; i <= MAX_FP_TYPE_SIZE; i++)
1589 2652 : fp_type_size[i] = NO_SIZE;
1590 :
1591 156 : fp_type_size[sizeof (float)] = FLOAT_SINGLE;
1592 : /* The array entry for `double' is filled in after that for LONG_DOUBLE
1593 : so that if `long double' is the same type or if long double isn't
1594 : supported FLOAT_LONG_DOUBLE will never be used. */
1595 156 : fp_type_size[sizeof (LONG_DOUBLE)] = FLOAT_LONG_DOUBLE;
1596 156 : fp_type_size[sizeof (double)] = FLOAT_DOUBLE;
1597 :
1598 156 : n_specs = 0;
1599 156 : n_specs_allocated = 0;
1600 156 : spec = NULL;
1601 :
1602 156 : format_address = format_address_std;
1603 156 : address_base = 8;
1604 156 : address_pad_len = 7;
1605 156 : flag_dump_strings = false;
1606 :
1607 : for (;;)
1608 100 : {
1609 : uintmax_t tmp;
1610 : enum strtol_error s_err;
1611 256 : int oi = -1;
1612 256 : int c = getopt_long (argc, argv, short_options, long_options, &oi);
1613 256 : if (c == -1)
1614 134 : break;
1615 :
1616 122 : switch (c)
1617 : {
1618 10 : case 'A':
1619 10 : modern = true;
1620 10 : switch (optarg[0])
1621 : {
1622 2 : case 'd':
1623 2 : format_address = format_address_std;
1624 2 : address_base = 10;
1625 2 : address_pad_len = 7;
1626 2 : break;
1627 1 : case 'o':
1628 1 : format_address = format_address_std;
1629 1 : address_base = 8;
1630 1 : address_pad_len = 7;
1631 1 : break;
1632 5 : case 'x':
1633 5 : format_address = format_address_std;
1634 5 : address_base = 16;
1635 5 : address_pad_len = 6;
1636 5 : break;
1637 1 : case 'n':
1638 1 : format_address = format_address_none;
1639 1 : address_pad_len = 0;
1640 1 : break;
1641 1 : default:
1642 1 : error (EXIT_FAILURE, 0,
1643 : _("invalid output address radix `%c'; \
1644 : it must be one character from [doxn]"),
1645 1 : optarg[0]);
1646 0 : break;
1647 : }
1648 9 : break;
1649 :
1650 3 : case 'j':
1651 3 : modern = true;
1652 3 : s_err = xstrtoumax (optarg, NULL, 0, &n_bytes_to_skip, multipliers);
1653 3 : if (s_err != LONGINT_OK)
1654 1 : xstrtol_fatal (s_err, oi, c, long_options, optarg);
1655 2 : break;
1656 :
1657 16 : case 'N':
1658 16 : modern = true;
1659 16 : limit_bytes_to_format = true;
1660 :
1661 16 : s_err = xstrtoumax (optarg, NULL, 0, &max_bytes_to_format,
1662 : multipliers);
1663 16 : if (s_err != LONGINT_OK)
1664 5 : xstrtol_fatal (s_err, oi, c, long_options, optarg);
1665 11 : break;
1666 :
1667 12 : case 'S':
1668 12 : modern = true;
1669 12 : if (optarg == NULL)
1670 7 : string_min = 3;
1671 : else
1672 : {
1673 5 : s_err = xstrtoumax (optarg, NULL, 0, &tmp, multipliers);
1674 5 : if (s_err != LONGINT_OK)
1675 1 : xstrtol_fatal (s_err, oi, c, long_options, optarg);
1676 :
1677 : /* The minimum string length may be no larger than SIZE_MAX,
1678 : since we may allocate a buffer of this size. */
1679 : if (SIZE_MAX < tmp)
1680 : error (EXIT_FAILURE, 0, _("%s is too large"), optarg);
1681 :
1682 4 : string_min = tmp;
1683 : }
1684 11 : flag_dump_strings = true;
1685 11 : break;
1686 :
1687 28 : case 't':
1688 28 : modern = true;
1689 28 : ok &= decode_format_string (optarg);
1690 28 : break;
1691 :
1692 1 : case 'v':
1693 1 : modern = true;
1694 1 : abbreviate_duplicate_blocks = false;
1695 1 : break;
1696 :
1697 4 : case TRADITIONAL_OPTION:
1698 4 : traditional = true;
1699 4 : break;
1700 :
1701 : /* The next several cases map the traditional format
1702 : specification options to the corresponding modern format
1703 : specs. GNU od accepts any combination of old- and
1704 : new-style options. Format specification options accumulate.
1705 : The obsolescent and undocumented formats are compatible
1706 : with FreeBSD 4.10 od. */
1707 :
1708 : #define CASE_OLD_ARG(old_char,new_string) \
1709 : case old_char: \
1710 : ok &= decode_format_string (new_string); \
1711 : break
1712 :
1713 7 : CASE_OLD_ARG ('a', "a");
1714 1 : CASE_OLD_ARG ('b', "o1");
1715 9 : CASE_OLD_ARG ('c', "c");
1716 1 : CASE_OLD_ARG ('D', "u4"); /* obsolescent and undocumented */
1717 1 : CASE_OLD_ARG ('d', "u2");
1718 2 : case 'F': /* obsolescent and undocumented alias */
1719 2 : CASE_OLD_ARG ('e', "fD"); /* obsolescent and undocumented */
1720 1 : CASE_OLD_ARG ('f', "fF");
1721 1 : case 'X': /* obsolescent and undocumented alias */
1722 1 : CASE_OLD_ARG ('H', "x4"); /* obsolescent and undocumented */
1723 1 : CASE_OLD_ARG ('i', "dI");
1724 1 : case 'I': case 'L': /* obsolescent and undocumented aliases */
1725 1 : CASE_OLD_ARG ('l', "dL");
1726 1 : CASE_OLD_ARG ('O', "o4"); /* obsolesent and undocumented */
1727 2 : case 'B': /* obsolescent and undocumented alias */
1728 2 : CASE_OLD_ARG ('o', "o2");
1729 1 : CASE_OLD_ARG ('s', "d2");
1730 1 : case 'h': /* obsolescent and undocumented alias */
1731 1 : CASE_OLD_ARG ('x', "x2");
1732 :
1733 : #undef CASE_OLD_ARG
1734 :
1735 7 : case 'w':
1736 7 : modern = true;
1737 7 : width_specified = true;
1738 7 : if (optarg == NULL)
1739 : {
1740 2 : desired_width = 32;
1741 : }
1742 : else
1743 : {
1744 : uintmax_t w_tmp;
1745 5 : s_err = xstrtoumax (optarg, NULL, 10, &w_tmp, "");
1746 5 : if (s_err != LONGINT_OK)
1747 3 : xstrtol_fatal (s_err, oi, c, long_options, optarg);
1748 : if (SIZE_MAX < w_tmp)
1749 : error (EXIT_FAILURE, 0, _("%s is too large"), optarg);
1750 2 : desired_width = w_tmp;
1751 : }
1752 4 : break;
1753 :
1754 1 : case_GETOPT_HELP_CHAR;
1755 :
1756 1 : case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1757 :
1758 9 : default:
1759 9 : usage (EXIT_FAILURE);
1760 0 : break;
1761 : }
1762 : }
1763 :
1764 134 : if (!ok)
1765 17 : exit (EXIT_FAILURE);
1766 :
1767 117 : if (flag_dump_strings && n_specs > 0)
1768 0 : error (EXIT_FAILURE, 0,
1769 : _("no type may be specified when dumping strings"));
1770 :
1771 117 : n_files = argc - optind;
1772 :
1773 : /* If the --traditional option is used, there may be from
1774 : 0 to 3 remaining command line arguments; handle each case
1775 : separately.
1776 : od [file] [[+]offset[.][b] [[+]label[.][b]]]
1777 : The offset and label have the same syntax.
1778 :
1779 : If --traditional is not given, and if no modern options are
1780 : given, and if the offset begins with + or (if there are two
1781 : operands) a digit, accept only this form, as per POSIX:
1782 : od [file] [[+]offset[.][b]]
1783 : */
1784 :
1785 117 : if (!modern | traditional)
1786 : {
1787 : uintmax_t o1;
1788 : uintmax_t o2;
1789 :
1790 68 : switch (n_files)
1791 : {
1792 18 : case 1:
1793 18 : if ((traditional || argv[optind][0] == '+')
1794 15 : && parse_old_offset (argv[optind], &o1))
1795 : {
1796 4 : n_bytes_to_skip = o1;
1797 4 : --n_files;
1798 4 : ++argv;
1799 : }
1800 18 : break;
1801 :
1802 15 : case 2:
1803 15 : if ((traditional || argv[optind + 1][0] == '+'
1804 10 : || ISDIGIT (argv[optind + 1][0]))
1805 10 : && parse_old_offset (argv[optind + 1], &o2))
1806 : {
1807 4 : if (traditional && parse_old_offset (argv[optind], &o1))
1808 : {
1809 0 : n_bytes_to_skip = o1;
1810 0 : flag_pseudo_start = true;
1811 0 : pseudo_start = o2;
1812 0 : argv += 2;
1813 0 : n_files -= 2;
1814 : }
1815 : else
1816 : {
1817 4 : n_bytes_to_skip = o2;
1818 4 : --n_files;
1819 4 : argv[optind + 1] = argv[optind];
1820 4 : ++argv;
1821 : }
1822 : }
1823 15 : break;
1824 :
1825 7 : case 3:
1826 7 : if (traditional
1827 0 : && parse_old_offset (argv[optind + 1], &o1)
1828 0 : && parse_old_offset (argv[optind + 2], &o2))
1829 : {
1830 0 : n_bytes_to_skip = o1;
1831 0 : flag_pseudo_start = true;
1832 0 : pseudo_start = o2;
1833 0 : argv[optind + 2] = argv[optind];
1834 0 : argv += 2;
1835 0 : n_files -= 2;
1836 : }
1837 7 : break;
1838 : }
1839 :
1840 68 : if (traditional && 1 < n_files)
1841 : {
1842 1 : error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
1843 1 : error (0, 0, "%s\n",
1844 : _("Compatibility mode supports at most one file."));
1845 1 : usage (EXIT_FAILURE);
1846 : }
1847 : }
1848 :
1849 116 : if (flag_pseudo_start)
1850 : {
1851 0 : if (format_address == format_address_none)
1852 : {
1853 0 : address_base = 8;
1854 0 : address_pad_len = 7;
1855 0 : format_address = format_address_paren;
1856 : }
1857 : else
1858 0 : format_address = format_address_label;
1859 : }
1860 :
1861 116 : if (limit_bytes_to_format)
1862 : {
1863 11 : end_offset = n_bytes_to_skip + max_bytes_to_format;
1864 11 : if (end_offset < n_bytes_to_skip)
1865 0 : error (EXIT_FAILURE, 0, _("skip-bytes + read-bytes is too large"));
1866 : }
1867 :
1868 116 : if (n_specs == 0)
1869 78 : decode_format_string ("oS");
1870 :
1871 116 : if (n_files > 0)
1872 : {
1873 : /* Set the global pointer FILE_LIST so that it
1874 : references the first file-argument on the command-line. */
1875 :
1876 46 : file_list = (char const *const *) &argv[optind];
1877 : }
1878 : else
1879 : {
1880 : /* No files were listed on the command line.
1881 : Set the global pointer FILE_LIST so that it
1882 : references the null-terminated list of one name: "-". */
1883 :
1884 70 : file_list = default_file_list;
1885 : }
1886 :
1887 : /* open the first input file */
1888 116 : ok = open_next_file ();
1889 116 : if (in_stream == NULL)
1890 12 : goto cleanup;
1891 :
1892 : /* skip over any unwanted header bytes */
1893 104 : ok &= skip (n_bytes_to_skip);
1894 103 : if (in_stream == NULL)
1895 0 : goto cleanup;
1896 :
1897 103 : pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1898 :
1899 : /* Compute output block length. */
1900 103 : l_c_m = get_lcm ();
1901 :
1902 103 : if (width_specified)
1903 : {
1904 4 : if (desired_width != 0 && desired_width % l_c_m == 0)
1905 3 : bytes_per_block = desired_width;
1906 : else
1907 : {
1908 1 : error (0, 0, _("warning: invalid width %lu; using %d instead"),
1909 : (unsigned long int) desired_width, l_c_m);
1910 1 : bytes_per_block = l_c_m;
1911 : }
1912 : }
1913 : else
1914 : {
1915 99 : if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1916 98 : bytes_per_block = l_c_m * (DEFAULT_BYTES_PER_BLOCK / l_c_m);
1917 : else
1918 1 : bytes_per_block = l_c_m;
1919 : }
1920 :
1921 : #ifdef DEBUG
1922 : for (i = 0; i < n_specs; i++)
1923 : {
1924 : printf (_("%d: fmt=\"%s\" width=%d\n"),
1925 : i, spec[i].fmt_string, width_bytes[spec[i].size]);
1926 : }
1927 : #endif
1928 :
1929 103 : ok &= (flag_dump_strings ? dump_strings () : dump ());
1930 :
1931 114 : cleanup:;
1932 :
1933 114 : if (have_read_stdin && fclose (stdin) == EOF)
1934 0 : error (EXIT_FAILURE, errno, _("standard input"));
1935 :
1936 114 : exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
1937 : }
|