As usual, I forgot "svn del"...
[oweals/busybox.git] / coreutils / od_bloaty.c
1 /* od -- dump files in octal and other formats
2    Copyright (C) 92, 1995-2004 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 /* Written by Jim Meyering.  */
19
20 /* Busyboxed by Denis Vlasenko
21 ** Based on od.c from coreutils-5.2.1
22 ** Top bloat sources:
23 ** get_lcm               111
24 ** print_ascii           145
25 ** format_address_std    159
26 ** check_and_close       160
27 ** open_next_file        170
28 ** write_block           368
29 ** decode_format_string 1169
30 ** od_main              2623
31 ** TODO: get rid of getopt()
32 */
33
34 #include "busybox.h"
35 #include <getopt.h>
36
37 #define assert(a) ((void)0)
38 #define ISPRINT(c) ((c)>=' ')
39
40 typedef long double longdouble_t;
41 typedef unsigned long long ulonglong_t;
42 #define xstrtoumax_sfx xstrtoul_sfx
43 #define xstrtoumax_range_sfx xstrtoul_range_sfx
44
45 /* The default number of input bytes per output line.  */
46 #define DEFAULT_BYTES_PER_BLOCK 16
47
48 /* The number of decimal digits of precision in a float.  */
49 #ifndef FLT_DIG
50 # define FLT_DIG 7
51 #endif
52
53 /* The number of decimal digits of precision in a double.  */
54 #ifndef DBL_DIG
55 # define DBL_DIG 15
56 #endif
57
58 /* The number of decimal digits of precision in a long double.  */
59 #ifndef LDBL_DIG
60 # define LDBL_DIG DBL_DIG
61 #endif
62
63 enum size_spec {
64         NO_SIZE,
65         CHAR,
66         SHORT,
67         INT,
68         LONG,
69         LONG_LONG,
70         /* FIXME: add INTMAX support, too */
71         FLOAT_SINGLE,
72         FLOAT_DOUBLE,
73         FLOAT_LONG_DOUBLE,
74         N_SIZE_SPECS
75 };
76
77 enum output_format {
78         SIGNED_DECIMAL,
79         UNSIGNED_DECIMAL,
80         OCTAL,
81         HEXADECIMAL,
82         FLOATING_POINT,
83         NAMED_CHARACTER,
84         CHARACTER
85 };
86
87 /* Each output format specification (from '-t spec' or from
88    old-style options) is represented by one of these structures.  */
89 struct tspec {
90         enum output_format fmt;
91         enum size_spec size;
92         void (*print_function) (size_t, const char *, const char *);
93         char *fmt_string;
94         int hexl_mode_trailer;
95         int field_width;
96 };
97
98 /* Convert the number of 8-bit bytes of a binary representation to
99    the number of characters (digits + sign if the type is signed)
100    required to represent the same quantity in the specified base/type.
101    For example, a 32-bit (4-byte) quantity may require a field width
102    as wide as the following for these types:
103    11   unsigned octal
104    11   signed decimal
105    10   unsigned decimal
106    8    unsigned hexadecimal  */
107
108 static const unsigned char bytes_to_oct_digits[] =
109 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
110
111 static const unsigned char bytes_to_signed_dec_digits[] =
112 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
113
114 static const unsigned char bytes_to_unsigned_dec_digits[] =
115 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
116
117 static const unsigned char bytes_to_hex_digits[] =
118 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
119
120 /* Convert enum size_spec to the size of the named type.  */
121 static const signed char width_bytes[] = {
122         -1,
123         sizeof(char),
124         sizeof(short),
125         sizeof(int),
126         sizeof(long),
127         sizeof(ulonglong_t),
128         sizeof(float),
129         sizeof(double),
130         sizeof(longdouble_t)
131 };
132
133 /* Ensure that for each member of 'enum size_spec' there is an
134    initializer in the width_bytes array.  */
135 struct dummy {
136         int assert_width_bytes_matches_size_spec_decl
137                 [sizeof width_bytes / sizeof width_bytes[0] == N_SIZE_SPECS ? 1 : -1];
138 };
139
140 /* Names for some non-printing characters.  */
141 static const char charname[33][4] = {
142         "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
143         "bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
144         "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
145         "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
146         "sp"
147 };
148
149 /* Address base (8, 10 or 16).  */
150 static int address_base;
151
152 /* The number of octal digits required to represent the largest
153          address value.  */
154 #define MAX_ADDRESS_LENGTH \
155         ((sizeof(uintmax_t) * CHAR_BIT + CHAR_BIT - 1) / 3)
156
157 /* Width of a normal address.  */
158 static int address_pad_len;
159
160 static size_t string_min;
161 static int flag_dump_strings;
162
163 /* Non-zero if we should recognize the older non-option arguments
164    that specified at most one file and optional arguments specifying
165    offset and pseudo-start address.  */
166 static int traditional;
167
168 /* Non-zero if an old-style 'pseudo-address' was specified.  */
169 static int flag_pseudo_start;
170
171 /* The difference between the old-style pseudo starting address and
172    the number of bytes to skip.  */
173 static uintmax_t pseudo_offset;
174
175 /* Function that accepts an address and an optional following char,
176    and prints the address and char to stdout.  */
177 static void (*format_address) (uintmax_t, char);
178
179 /* The number of input bytes to skip before formatting and writing.  */
180 static uintmax_t n_bytes_to_skip; // = 0;
181
182 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
183    input is formatted.  */
184 static int limit_bytes_to_format; // = 0;
185
186 /* The maximum number of bytes that will be formatted.  */
187 static uintmax_t max_bytes_to_format;
188
189 /* The offset of the first byte after the last byte to be formatted.  */
190 static uintmax_t end_offset;
191
192 /* When nonzero and two or more consecutive blocks are equal, format
193    only the first block and output an asterisk alone on the following
194    line to indicate that identical blocks have been elided.  */
195 static int abbreviate_duplicate_blocks = 1;
196
197 /* An array of specs describing how to format each input block.  */
198 static struct tspec *spec;
199
200 /* The number of format specs.  */
201 static size_t n_specs;
202
203 /* The number of input bytes formatted per output line.  It must be
204    a multiple of the least common multiple of the sizes associated with
205    the specified output types.  It should be as large as possible, but
206    no larger than 16 -- unless specified with the -w option.  */
207 static size_t bytes_per_block;
208
209 /* Human-readable representation of *file_list (for error messages).
210    It differs from *file_list only when *file_list is "-".  */
211 static char const *input_filename;
212
213 /* A NULL-terminated list of the file-arguments from the command line.  */
214 static char const *const *file_list;
215
216 /* Initializer for file_list if no file-arguments
217    were specified on the command line.  */
218 static char const *const default_file_list[] = {"-", NULL};
219
220 /* The input stream associated with the current file.  */
221 static FILE *in_stream;
222
223 /* If nonzero, at least one of the files we read was standard input.  */
224 static int have_read_stdin;
225
226 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
227 static unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1];
228
229 #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
230 static unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1];
231
232
233 /* For long options that have no equivalent short option, use a
234    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
235 enum {
236         TRADITIONAL_OPTION = CHAR_MAX + 1
237 };
238
239
240 static unsigned
241 gcd(unsigned u, unsigned v)
242 {
243         unsigned t;
244         while (v != 0) {
245                 t = u % v;
246                 u = v;
247                 v = t;
248         }
249         return u;
250 }
251
252 /* Compute the least common multiple of U and V.  */
253 static unsigned
254 lcm(unsigned u, unsigned v) {
255         unsigned t = gcd(u, v);
256         if (t == 0)
257                 return 0;
258         return u * v / t;
259 }
260
261 static void
262 print_s_char(size_t n_bytes, const char *block, const char *fmt_string)
263 {
264         size_t i;
265         for (i = n_bytes; i > 0; i--) {
266                 int tmp = (unsigned) *(unsigned char *) block;
267                 if (tmp > SCHAR_MAX)
268                         tmp -= SCHAR_MAX - SCHAR_MIN + 1;
269                 assert(tmp <= SCHAR_MAX);
270                 printf(fmt_string, tmp);
271                 block += sizeof(unsigned char);
272         }
273 }
274
275 static void
276 print_char(size_t n_bytes, const char *block, const char *fmt_string)
277 {
278         size_t i;
279         for (i = n_bytes; i > 0; i--) {
280                 unsigned tmp = *(unsigned char *) block;
281                 printf(fmt_string, tmp);
282                 block += sizeof(unsigned char);
283         }
284 }
285
286 static void
287 print_s_short(size_t n_bytes, const char *block, const char *fmt_string)
288 {
289         size_t i;
290         for (i = n_bytes / sizeof(unsigned short); i > 0; i--) {
291                 int tmp = (unsigned) *(unsigned short *) block;
292                 if (tmp > SHRT_MAX)
293                         tmp -= SHRT_MAX - SHRT_MIN + 1;
294                 assert(tmp <= SHRT_MAX);
295                 printf(fmt_string, tmp);
296                 block += sizeof(unsigned short);
297         }
298 }
299
300 static void
301 print_short(size_t n_bytes, const char *block, const char *fmt_string)
302 {
303         size_t i;
304         for (i = n_bytes / sizeof(unsigned short); i > 0; i--) {
305                 unsigned tmp = *(unsigned short *) block;
306                 printf(fmt_string, tmp);
307                 block += sizeof(unsigned short);
308         }
309 }
310
311 static void
312 print_int(size_t n_bytes, const char *block, const char *fmt_string)
313 {
314         size_t i;
315         for (i = n_bytes / sizeof(unsigned); i > 0; i--) {
316                 unsigned tmp = *(unsigned *) block;
317                 printf(fmt_string, tmp);
318                 block += sizeof(unsigned);
319         }
320 }
321
322 static void
323 print_long(size_t n_bytes, const char *block, const char *fmt_string)
324 {
325         size_t i;
326         for (i = n_bytes / sizeof(unsigned long); i > 0; i--) {
327                 unsigned long tmp = *(unsigned long *) block;
328                 printf(fmt_string, tmp);
329                 block += sizeof(unsigned long);
330         }
331 }
332
333 static void
334 print_long_long(size_t n_bytes, const char *block, const char *fmt_string)
335 {
336         size_t i;
337         for (i = n_bytes / sizeof(ulonglong_t); i > 0; i--) {
338                 ulonglong_t tmp = *(ulonglong_t *) block;
339                 printf(fmt_string, tmp);
340                 block += sizeof(ulonglong_t);
341         }
342 }
343
344 static void
345 print_float(size_t n_bytes, const char *block, const char *fmt_string)
346 {
347         size_t i;
348         for (i = n_bytes / sizeof(float); i > 0; i--) {
349                 float tmp = *(float *) block;
350                 printf(fmt_string, tmp);
351                 block += sizeof(float);
352         }
353 }
354
355 static void
356 print_double(size_t n_bytes, const char *block, const char *fmt_string)
357 {
358         size_t i;
359         for (i = n_bytes / sizeof(double); i > 0; i--) {
360                 double tmp = *(double *) block;
361                 printf(fmt_string, tmp);
362                 block += sizeof(double);
363         }
364 }
365
366 static void
367 print_long_double(size_t n_bytes, const char *block, const char *fmt_string)
368 {
369         size_t i;
370         for (i = n_bytes / sizeof(longdouble_t); i > 0; i--) {
371                 longdouble_t tmp = *(longdouble_t *) block;
372                 printf(fmt_string, tmp);
373                 block += sizeof(longdouble_t);
374         }
375 }
376
377 static void
378 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
379 {
380         size_t i;
381         fputs("  >", stdout);
382         for (i = n_bytes; i > 0; i--) {
383                 unsigned c = *(unsigned char *) block;
384                 unsigned c2 = (ISPRINT(c) ? c : '.');
385                 putchar(c2);
386                 block += sizeof(unsigned char);
387         }
388         putchar('<');
389 }
390
391 static void
392 print_named_ascii(size_t n_bytes, const char *block,
393                 const char *unused_fmt_string ATTRIBUTE_UNUSED)
394 {
395         size_t i;
396         for (i = n_bytes; i > 0; i--) {
397                 unsigned c = *(unsigned char *) block;
398                 unsigned masked_c = (0x7f & c);
399                 const char *s;
400                 char buf[5];
401
402                 if (masked_c == 127)
403                         s = "del";
404                 else if (masked_c <= 040)
405                         s = charname[masked_c];
406                 else {
407                         sprintf(buf, "  %c", masked_c);
408                         s = buf;
409                 }
410
411                 printf(" %3s", s);
412                 block += sizeof(unsigned char);
413         }
414 }
415
416 static void
417 print_ascii(size_t n_bytes, const char *block,
418                 const char *unused_fmt_string ATTRIBUTE_UNUSED)
419 {
420         size_t i;
421         for (i = n_bytes; i > 0; i--) {
422                 unsigned c = *(unsigned char *) block;
423                 const char *s;
424                 char buf[5];
425
426                 switch (c) {
427                 case '\0':
428                         s = " \\0";
429                         break;
430                 case '\007':
431                         s = " \\a";
432                         break;
433                 case '\b':
434                         s = " \\b";
435                         break;
436                 case '\f':
437                         s = " \\f";
438                         break;
439                 case '\n':
440                         s = " \\n";
441                         break;
442                 case '\r':
443                         s = " \\r";
444                         break;
445                 case '\t':
446                         s = " \\t";
447                         break;
448                 case '\v':
449                         s = " \\v";
450                         break;
451                 default:
452                         sprintf(buf, (ISPRINT(c) ? "  %c" : "%03o"), c);
453                         s = (const char *) buf;
454                 }
455
456                 printf(" %3s", s);
457                 block += sizeof(unsigned char);
458         }
459 }
460
461 /* If S points to a single valid modern od format string, put
462    a description of that format in *TSPEC, make *NEXT point at the
463    character following the just-decoded format (if *NEXT is non-NULL),
464    and return zero.  If S is not valid, don't modify *NEXT or *TSPEC,
465    give a diagnostic, and return nonzero.  For example, if S were
466    "d4afL" *NEXT would be set to "afL" and *TSPEC would be
467         {
468                 fmt = SIGNED_DECIMAL;
469                 size = INT or LONG; (whichever integral_type_size[4] resolves to)
470                 print_function = print_int; (assuming size == INT)
471                 fmt_string = "%011d%c";
472         }
473    S_ORIG is solely for reporting errors.  It should be the full format
474    string argument.
475    */
476
477 static int
478 decode_one_format(const char *s_orig, const char *s, const char **next,
479                                            struct tspec *tspec)
480 {
481         enum size_spec size_spec;
482         unsigned long size;
483         enum output_format fmt;
484         const char *pre_fmt_string;
485         char *end;
486         char *fmt_string;
487         void (*print_function) (size_t, const char *, const char *);
488         unsigned c;
489         unsigned field_width = 0;
490
491         assert(tspec != NULL);
492
493         switch (*s) {
494         case 'd':
495         case 'o':
496         case 'u':
497         case 'x':
498                 c = *s;
499                 ++s;
500                 switch (*s) {
501                 case 'C':
502                         ++s;
503                         size = sizeof(char);
504                         break;
505                 case 'S':
506                         ++s;
507                         size = sizeof(short);
508                         break;
509                 case 'I':
510                         ++s;
511                         size = sizeof(int);
512                         break;
513                 case 'L':
514                         ++s;
515                         size = sizeof(long);
516                         break;
517                 default:
518                         size = sizeof(int);
519                         if (isdigit(s[0])) {
520                                 size = strtoul(s, &end, 0);
521                                 if (end[0] || MAX_INTEGRAL_TYPE_SIZE < size
522                                  || integral_type_size[size] == NO_SIZE
523                                 ) {
524                                         bb_error_msg("invalid type string '%s'; "
525                                                 "%lu-byte integral type is not spported", s_orig, size);
526                                         return 1;
527                                 }
528                                 s = end;
529                         }
530                         break;
531                 }
532
533 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
534         ((Spec) == LONG_LONG ? (Max_format) \
535         : ((Spec) == LONG ? (Long_format) : (Min_format)))
536
537 #define FMT_BYTES_ALLOCATED 9
538                 fmt_string = xmalloc(FMT_BYTES_ALLOCATED);
539
540                 size_spec = integral_type_size[size];
541
542                 switch (c) {
543                 case 'd':
544                         fmt = SIGNED_DECIMAL;
545                         sprintf(fmt_string, " %%%u%s",
546                            (field_width = bytes_to_signed_dec_digits[size]),
547                            ISPEC_TO_FORMAT(size_spec, "d", "ld", PRIdMAX));
548                         break;
549                 case 'o':
550                         fmt = OCTAL;
551                         sprintf(fmt_string, " %%0%u%s",
552                            (field_width = bytes_to_oct_digits[size]),
553                            ISPEC_TO_FORMAT(size_spec, "o", "lo", PRIoMAX));
554                         break;
555                 case 'u':
556                         fmt = UNSIGNED_DECIMAL;
557                         sprintf(fmt_string, " %%%u%s",
558                            (field_width = bytes_to_unsigned_dec_digits[size]),
559                            ISPEC_TO_FORMAT(size_spec, "u", "lu", PRIuMAX));
560                         break;
561                 case 'x':
562                         fmt = HEXADECIMAL;
563                         sprintf(fmt_string, " %%0%u%s",
564                            (field_width = bytes_to_hex_digits[size]),
565                            ISPEC_TO_FORMAT(size_spec, "x", "lx", PRIxMAX));
566                         break;
567                 default:
568                         abort();
569                 }
570
571                 assert(strlen(fmt_string) < FMT_BYTES_ALLOCATED);
572
573                 switch (size_spec) {
574                 case CHAR:
575                         print_function = (fmt == SIGNED_DECIMAL
576                                     ? print_s_char
577                                     : print_char);
578                         break;
579                 case SHORT:
580                         print_function = (fmt == SIGNED_DECIMAL
581                                     ? print_s_short
582                                     : print_short);
583                         break;
584                 case INT:
585                         print_function = print_int;
586                         break;
587                 case LONG:
588                         print_function = print_long;
589                         break;
590                 case LONG_LONG:
591                         print_function = print_long_long;
592                         break;
593                 default:
594                         abort();
595                 }
596                 break;
597
598         case 'f':
599                 fmt = FLOATING_POINT;
600                 ++s;
601                 switch (*s) {
602                 case 'F':
603                         ++s;
604                         size = sizeof(float);
605                         break;
606                 case 'D':
607                         ++s;
608                         size = sizeof(double);
609                         break;
610                 case 'L':
611                         ++s;
612                         size = sizeof(longdouble_t);
613                         break;
614                 default:
615                         size = sizeof(double);
616                         if (isdigit(s[0])) {
617                                 size = strtoul(s, &end, 0);
618                                 if (end[0] || size > MAX_FP_TYPE_SIZE
619                                  || fp_type_size[size] == NO_SIZE
620                                 ) {
621                                         bb_error_msg("invalid type string '%s'; "
622                                                 "%lu-byte floating point type is not supported", s_orig, size);
623                                         return 1;
624                                 }
625                                 s = end;
626                         }
627                         break;
628                 }
629                 size_spec = fp_type_size[size];
630
631                 switch (size_spec) {
632                 case FLOAT_SINGLE:
633                         print_function = print_float;
634                         /* Don't use %#e; not all systems support it.  */
635                         pre_fmt_string = " %%%d.%de";
636                         fmt_string = xmalloc(strlen(pre_fmt_string));
637                         sprintf(fmt_string, pre_fmt_string,
638                                 (field_width = FLT_DIG + 8), FLT_DIG);
639                         break;
640                 case FLOAT_DOUBLE:
641                         print_function = print_double;
642                         pre_fmt_string = " %%%d.%de";
643                         fmt_string = xmalloc(strlen(pre_fmt_string));
644                         sprintf(fmt_string, pre_fmt_string,
645                                 (field_width = DBL_DIG + 8), DBL_DIG);
646                         break;
647                 case FLOAT_LONG_DOUBLE:
648                         print_function = print_long_double;
649                         pre_fmt_string = " %%%d.%dLe";
650                         fmt_string = xmalloc(strlen(pre_fmt_string));
651                         sprintf(fmt_string, pre_fmt_string,
652                                 (field_width = LDBL_DIG + 8), LDBL_DIG);
653                         break;
654                 default:
655                         abort();
656                 }
657                 break;
658
659         case 'a':
660                 ++s;
661                 fmt = NAMED_CHARACTER;
662                 size_spec = CHAR;
663                 fmt_string = NULL;
664                 print_function = print_named_ascii;
665                 field_width = 3;
666                 break;
667         case 'c':
668                 ++s;
669                 fmt = CHARACTER;
670                 size_spec = CHAR;
671                 fmt_string = NULL;
672                 print_function = print_ascii;
673                 field_width = 3;
674                 break;
675         default:
676                 bb_error_msg("invalid character '%c' in type string '%s'", *s, s_orig);
677                 return 1;
678         }
679
680         tspec->size = size_spec;
681         tspec->fmt = fmt;
682         tspec->print_function = print_function;
683         tspec->fmt_string = fmt_string;
684
685         tspec->field_width = field_width;
686         tspec->hexl_mode_trailer = (*s == 'z');
687         if (tspec->hexl_mode_trailer)
688                 s++;
689
690         if (next != NULL)
691                 *next = s;
692
693         return 0;
694 }
695
696 /* Given a list of one or more input filenames FILE_LIST, set the global
697    file pointer IN_STREAM and the global string INPUT_FILENAME to the
698    first one that can be successfully opened. Modify FILE_LIST to
699    reference the next filename in the list.  A file name of "-" is
700    interpreted as standard input.  If any file open fails, give an error
701    message and return nonzero.  */
702
703 static int
704 open_next_file(void)
705 {
706         int err = 0;
707
708         do {
709                 input_filename = *file_list;
710                 if (input_filename == NULL)
711                         return err;
712                 ++file_list;
713
714                 if (input_filename[0] == '-' && !input_filename[1]) {
715                                 input_filename = "standard input";
716                                 in_stream = stdin;
717                                 have_read_stdin = 1;
718                 } else {
719                         in_stream = fopen(input_filename, "r");
720                         if (in_stream == NULL) {
721                                 bb_perror_msg("%s", input_filename);
722                                 err = 1;
723                         }
724                 }
725         } while (in_stream == NULL);
726
727         if (limit_bytes_to_format && !flag_dump_strings)
728                 setbuf(in_stream, NULL);
729
730         return err;
731 }
732
733 /* Test whether there have been errors on in_stream, and close it if
734    it is not standard input.  Return nonzero if there has been an error
735    on in_stream or stdout; return zero otherwise.  This function will
736    report more than one error only if both a read and a write error
737    have occurred.  IN_ERRNO, if nonzero, is the error number
738    corresponding to the most recent action for IN_STREAM.  */
739
740 static int
741 check_and_close(int in_errno)
742 {
743         int err = 0;
744
745         if (in_stream != NULL) {
746                 if (ferror(in_stream))  {
747                         bb_error_msg("%s: read error", input_filename);
748                         if (in_stream != stdin)
749                                 fclose(in_stream);
750                         err = 1;
751                 } else if (in_stream != stdin && fclose(in_stream) == EOF) {
752                         bb_perror_msg("%s", input_filename);
753                         err = 1;
754                 }
755                 in_stream = NULL;
756         }
757
758         if (ferror(stdout)) {
759                 bb_error_msg("write error");
760                 err = 1;
761         }
762
763         return err;
764 }
765
766 /* Decode the modern od format string S.  Append the decoded
767    representation to the global array SPEC, reallocating SPEC if
768    necessary.  Return zero if S is valid, nonzero otherwise.  */
769
770 static int
771 decode_format_string(const char *s)
772 {
773         const char *s_orig = s;
774         assert(s != NULL);
775
776         while (*s != '\0') {
777                 struct tspec tspec;
778                 const char *next;
779
780                 if (decode_one_format(s_orig, s, &next, &tspec))
781                         return 1;
782
783                 assert(s != next);
784                 s = next;
785                 n_specs++;
786                 spec = xrealloc(spec, n_specs * sizeof(*spec));
787                 memcpy(&spec[n_specs-1], &tspec, sizeof *spec);
788         }
789
790         return 0;
791 }
792
793 /* Given a list of one or more input filenames FILE_LIST, set the global
794    file pointer IN_STREAM to position N_SKIP in the concatenation of
795    those files.  If any file operation fails or if there are fewer than
796    N_SKIP bytes in the combined input, give an error message and return
797    nonzero.  When possible, use seek rather than read operations to
798    advance IN_STREAM.  */
799
800 static int
801 skip(uintmax_t n_skip)
802 {
803         int err = 0;
804         int in_errno = 0;
805
806         if (n_skip == 0)
807                 return 0;
808
809         while (in_stream != NULL) { /* EOF */
810                 struct stat file_stats;
811
812                 /* First try seeking.  For large offsets, this extra work is
813                    worthwhile.  If the offset is below some threshold it may be
814                    more efficient to move the pointer by reading.  There are two
815                    issues when trying to seek:
816                         - the file must be seekable.
817                         - before seeking to the specified position, make sure
818                           that the new position is in the current file.
819                           Try to do that by getting file's size using fstat.
820                           But that will work only for regular files.  */
821
822                 if (fstat(fileno(in_stream), &file_stats) == 0) {
823                         /* The st_size field is valid only for regular files
824                            (and for symbolic links, which cannot occur here).
825                            If the number of bytes left to skip is at least
826                            as large as the size of the current file, we can
827                            decrement n_skip and go on to the next file.  */
828
829                         if (S_ISREG(file_stats.st_mode) && 0 <= file_stats.st_size) {
830                                 if ((uintmax_t) file_stats.st_size <= n_skip)
831                                         n_skip -= file_stats.st_size;
832                                 else {
833                                         if (fseeko(in_stream, n_skip, SEEK_CUR) != 0) {
834                                                 in_errno = errno;
835                                                 err = 1;
836                                         }
837                                         n_skip = 0;
838                                 }
839                         } else {
840
841                                 /* If it's not a regular file with nonnegative size,
842                                    position the file pointer by reading.  */
843                                 char buf[BUFSIZ];
844                                 size_t n_bytes_read, n_bytes_to_read = BUFSIZ;
845
846                                 while (0 < n_skip) {
847                                         if (n_skip < n_bytes_to_read)
848                                                 n_bytes_to_read = n_skip;
849                                         n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
850                                         n_skip -= n_bytes_read;
851                                         if (n_bytes_read != n_bytes_to_read) {
852                                                 in_errno = errno;
853                                                 err = 1;
854                                                 n_skip = 0;
855                                                 break;
856                                         }
857                                 }
858                         }
859                         if (n_skip == 0)
860                                 break;
861                 } else {  /* cannot fstat() file */
862                         bb_perror_msg("%s", input_filename);
863                         err = 1;
864                 }
865
866                 err |= check_and_close(in_errno);
867                 err |= open_next_file();
868         }
869
870         if (n_skip != 0)
871                 bb_error_msg_and_die("cannot skip past end of combined input");
872         return err;
873 }
874
875 static void
876 format_address_none(uintmax_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
877 {
878 }
879
880 static void
881 format_address_std(uintmax_t address, char c)
882 {
883         char buf[MAX_ADDRESS_LENGTH + 2];
884         char *p = buf + sizeof(buf)-1;
885         char const *pbound;
886
887         *p = '\0';
888         *--p = c;
889         pbound = p - address_pad_len;
890
891         do {
892                 *--p = "0123456789abcdef"[address % address_base];
893                 address /= address_base;
894         } while (address);
895
896         while (pbound < p)
897                 *--p = '0';
898         fputs(p, stdout);
899 }
900
901 static void
902 format_address_paren(uintmax_t address, char c)
903 {
904         putchar('(');
905         format_address_std(address, ')');
906         putchar(c);
907 }
908
909 static void
910 format_address_label(uintmax_t address, char c)
911 {
912         format_address_std(address, ' ');
913         format_address_paren(address + pseudo_offset, c);
914 }
915
916 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
917    of the N_SPEC format specs.  CURRENT_OFFSET is the byte address of
918    CURR_BLOCK in the concatenation of input files, and it is printed
919    (optionally) only before the output line associated with the first
920    format spec.  When duplicate blocks are being abbreviated, the output
921    for a sequence of identical input blocks is the output for the first
922    block followed by an asterisk alone on a line.  It is valid to compare
923    the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
924    That condition may be false only for the last input block -- and then
925    only when it has not been padded to length BYTES_PER_BLOCK.  */
926
927 static void
928 write_block(uintmax_t current_offset, size_t n_bytes,
929                 const char *prev_block, const char *curr_block)
930 {
931         static int first = 1;
932         static int prev_pair_equal = 0;
933
934         if (abbreviate_duplicate_blocks
935          && !first
936          && n_bytes == bytes_per_block
937          && memcmp(prev_block, curr_block, bytes_per_block) == 0
938         ) {
939                 if (prev_pair_equal) {
940                         /* The two preceding blocks were equal, and the current
941                            block is the same as the last one, so print nothing.  */
942                 } else {
943                         puts("*");
944                         prev_pair_equal = 1;
945                 }
946         } else {
947                 size_t i;
948
949                 prev_pair_equal = 0;
950                 for (i = 0; i < n_specs; i++) {
951                         if (i == 0)
952                                 format_address(current_offset, '\0');
953                         else
954                                 printf("%*s", address_pad_len, "");
955                         (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
956                         if (spec[i].hexl_mode_trailer) {
957                                 /* space-pad out to full line width, then dump the trailer */
958                                 int datum_width = width_bytes[spec[i].size];
959                                 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
960                                 int field_width = spec[i].field_width + 1;
961                                 printf("%*s", blank_fields * field_width, "");
962                                 dump_hexl_mode_trailer(n_bytes, curr_block);
963                         }
964                         putchar('\n');
965                 }
966         }
967         first = 0;
968 }
969
970 /* Read a single byte into *C from the concatenation of the input files
971    named in the global array FILE_LIST.  On the first call to this
972    function, the global variable IN_STREAM is expected to be an open
973    stream associated with the input file INPUT_FILENAME.  If IN_STREAM
974    is at end-of-file, close it and update the global variables IN_STREAM
975    and INPUT_FILENAME so they correspond to the next file in the list.
976    Then try to read a byte from the newly opened file.  Repeat if
977    necessary until EOF is reached for the last file in FILE_LIST, then
978    set *C to EOF and return.  Subsequent calls do likewise.  The return
979    value is nonzero if any errors occured, zero otherwise.  */
980
981 static int
982 read_char(int *c)
983 {
984         int err = 0;
985
986         *c = EOF;
987
988         while (in_stream != NULL) { /* EOF.  */
989                 *c = fgetc(in_stream);
990                 if (*c != EOF)
991                         break;
992                 err |= check_and_close(errno);
993                 err |= open_next_file();
994         }
995
996         return err;
997 }
998
999 /* Read N bytes into BLOCK from the concatenation of the input files
1000    named in the global array FILE_LIST.  On the first call to this
1001    function, the global variable IN_STREAM is expected to be an open
1002    stream associated with the input file INPUT_FILENAME.  If all N
1003    bytes cannot be read from IN_STREAM, close IN_STREAM and update
1004    the global variables IN_STREAM and INPUT_FILENAME.  Then try to
1005    read the remaining bytes from the newly opened file.  Repeat if
1006    necessary until EOF is reached for the last file in FILE_LIST.
1007    On subsequent calls, don't modify BLOCK and return zero.  Set
1008    *N_BYTES_IN_BUFFER to the number of bytes read.  If an error occurs,
1009    it will be detected through ferror when the stream is about to be
1010    closed.  If there is an error, give a message but continue reading
1011    as usual and return nonzero.  Otherwise return zero.  */
1012
1013 static int
1014 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
1015 {
1016         int err = 0;
1017
1018         assert(0 < n && n <= bytes_per_block);
1019
1020         *n_bytes_in_buffer = 0;
1021
1022         if (n == 0)
1023                 return 0;
1024
1025         while (in_stream != NULL) { /* EOF.  */
1026                 size_t n_needed;
1027                 size_t n_read;
1028
1029                 n_needed = n - *n_bytes_in_buffer;
1030                 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
1031                 *n_bytes_in_buffer += n_read;
1032                 if (n_read == n_needed)
1033                         break;
1034                 err |= check_and_close(errno);
1035                 err |= open_next_file();
1036         }
1037
1038         return err;
1039 }
1040
1041 /* Return the least common multiple of the sizes associated
1042    with the format specs.  */
1043
1044 static int
1045 get_lcm(void)
1046 {
1047         size_t i;
1048         int l_c_m = 1;
1049
1050         for (i = 0; i < n_specs; i++)
1051                 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
1052         return l_c_m;
1053 }
1054
1055 /* If S is a valid traditional offset specification with an optional
1056    leading '+' return nonzero and set *OFFSET to the offset it denotes.  */
1057
1058 static int
1059 parse_old_offset(const char *s, uintmax_t *offset)
1060 {
1061         static const struct suffix_mult Bb[] = {
1062                 { "B", 1024 },
1063                 { "b", 512 },
1064                 { NULL, 0 }
1065         };
1066
1067         int radix;
1068
1069         if (*s == '\0')
1070                 return 0;
1071
1072         /* Skip over any leading '+'. */
1073         if (s[0] == '+')
1074                 ++s;
1075
1076         /* Determine the radix we'll use to interpret S.  If there is a '.',
1077                  it's decimal, otherwise, if the string begins with '0X'or '0x',
1078                  it's hexadecimal, else octal.  */
1079         if (strchr(s, '.') != NULL)
1080                 radix = 10;
1081         else {
1082                 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1083                         radix = 16;
1084                 else
1085                         radix = 8;
1086         }
1087
1088         *offset = xstrtoumax_sfx(s, radix, Bb);
1089         return 1;
1090 }
1091
1092 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
1093    formatted block to standard output, and repeat until the specified
1094    maximum number of bytes has been read or until all input has been
1095    processed.  If the last block read is smaller than BYTES_PER_BLOCK
1096    and its size is not a multiple of the size associated with a format
1097    spec, extend the input block with zero bytes until its length is a
1098    multiple of all format spec sizes.  Write the final block.  Finally,
1099    write on a line by itself the offset of the byte after the last byte
1100    read.  Accumulate return values from calls to read_block and
1101    check_and_close, and if any was nonzero, return nonzero.
1102    Otherwise, return zero.  */
1103
1104 static int
1105 dump(void)
1106 {
1107         char *block[2];
1108         uintmax_t current_offset;
1109         int idx;
1110         int err;
1111         size_t n_bytes_read;
1112
1113         block[0] = xmalloc(2*bytes_per_block);
1114         block[1] = block[0] + bytes_per_block;
1115
1116         current_offset = n_bytes_to_skip;
1117
1118         idx = 0;
1119         err = 0;
1120         if (limit_bytes_to_format) {
1121                 while (1) {
1122                         size_t n_needed;
1123                         if (current_offset >= end_offset) {
1124                                 n_bytes_read = 0;
1125                                 break;
1126                         }
1127                         n_needed = MIN(end_offset - current_offset,
1128                                 (uintmax_t) bytes_per_block);
1129                         err |= read_block(n_needed, block[idx], &n_bytes_read);
1130                         if (n_bytes_read < bytes_per_block)
1131                                 break;
1132                         assert(n_bytes_read == bytes_per_block);
1133                         write_block(current_offset, n_bytes_read,
1134                                block[!idx], block[idx]);
1135                         current_offset += n_bytes_read;
1136                         idx = !idx;
1137                 }
1138         } else {
1139                 while (1) {
1140                         err |= read_block(bytes_per_block, block[idx], &n_bytes_read);
1141                         if (n_bytes_read < bytes_per_block)
1142                                 break;
1143                         assert(n_bytes_read == bytes_per_block);
1144                         write_block(current_offset, n_bytes_read,
1145                                block[!idx], block[idx]);
1146                         current_offset += n_bytes_read;
1147                         idx = !idx;
1148                 }
1149         }
1150
1151         if (n_bytes_read > 0) {
1152                 int l_c_m;
1153                 size_t bytes_to_write;
1154
1155                 l_c_m = get_lcm();
1156
1157                 /* Make bytes_to_write the smallest multiple of l_c_m that
1158                          is at least as large as n_bytes_read.  */
1159                 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1160
1161                 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1162                 write_block(current_offset, bytes_to_write,
1163                                    block[!idx], block[idx]);
1164                 current_offset += n_bytes_read;
1165         }
1166
1167         format_address(current_offset, '\n');
1168
1169         if (limit_bytes_to_format && current_offset >= end_offset)
1170                 err |= check_and_close(0);
1171
1172         free(block[0]);
1173
1174         return err;
1175 }
1176
1177 /* STRINGS mode.  Find each "string constant" in the input.
1178    A string constant is a run of at least 'string_min' ASCII
1179    graphic (or formatting) characters terminated by a null.
1180    Based on a function written by Richard Stallman for a
1181    traditional version of od.  Return nonzero if an error
1182    occurs.  Otherwise, return zero.  */
1183
1184 static int
1185 dump_strings(void)
1186 {
1187         size_t bufsize = MAX(100, string_min);
1188         char *buf = xmalloc(bufsize);
1189         uintmax_t address = n_bytes_to_skip;
1190         int err;
1191
1192         err = 0;
1193         while (1) {
1194                 size_t i;
1195                 int c;
1196
1197                 /* See if the next 'string_min' chars are all printing chars.  */
1198         tryline:
1199
1200                 if (limit_bytes_to_format
1201                  && (end_offset < string_min || end_offset - string_min <= address)
1202                 ) {
1203                         break;
1204                 }
1205
1206                 for (i = 0; i < string_min; i++) {
1207                         err |= read_char(&c);
1208                         address++;
1209                         if (c < 0) {
1210                                 free(buf);
1211                                 return err;
1212                         }
1213                         if (!ISPRINT(c))
1214                                 /* Found a non-printing.  Try again starting with next char.  */
1215                                 goto tryline;
1216                         buf[i] = c;
1217                 }
1218
1219                 /* We found a run of 'string_min' printable characters.
1220                          Now see if it is terminated with a null byte.  */
1221                 while (!limit_bytes_to_format || address < end_offset) {
1222                         if (i == bufsize) {
1223                                 bufsize *= 2;
1224                                 buf = xrealloc(buf, bufsize * sizeof(*buf));
1225                         }
1226                         err |= read_char(&c);
1227                         address++;
1228                         if (c < 0) {
1229                                 free(buf);
1230                                 return err;
1231                         }
1232                         if (c == '\0')
1233                                 break;          /* It is; print this string.  */
1234                         if (!ISPRINT(c))
1235                                 goto tryline;   /* It isn't; give up on this string.  */
1236                         buf[i++] = c;           /* String continues; store it all.  */
1237                 }
1238
1239                 /* If we get here, the string is all printable and null-terminated,
1240                          so print it.  It is all in 'buf' and 'i' is its length.  */
1241                 buf[i] = 0;
1242                 format_address(address - i - 1, ' ');
1243
1244                 for (i = 0; (c = buf[i]); i++) {
1245                         switch (c) {
1246                         case '\007':
1247                                 fputs("\\a", stdout);
1248                                 break;
1249
1250                         case '\b':
1251                                 fputs("\\b", stdout);
1252                                 break;
1253
1254                         case '\f':
1255                                 fputs("\\f", stdout);
1256                                 break;
1257
1258                         case '\n':
1259                                 fputs("\\n", stdout);
1260                                 break;
1261
1262                         case '\r':
1263                                 fputs("\\r", stdout);
1264                                 break;
1265
1266                         case '\t':
1267                                 fputs("\\t", stdout);
1268                                 break;
1269
1270                         case '\v':
1271                                 fputs("\\v", stdout);
1272                                 break;
1273
1274                         default:
1275                                 putc(c, stdout);
1276                         }
1277                 }
1278                 putchar('\n');
1279         }
1280
1281         /* We reach this point only if we search through
1282            (max_bytes_to_format - string_min) bytes before reaching EOF.  */
1283
1284         free(buf);
1285
1286         err |= check_and_close(0);
1287         return err;
1288 }
1289
1290 int
1291 od_main(int argc, char **argv)
1292 {
1293         static const struct suffix_mult bkm[] = {
1294                 { "b", 512 },
1295                 { "k", 1024 },
1296                 { "m", 1024*1024 },
1297                 { NULL, 0 }
1298         };
1299         static const struct option long_options[] = {
1300                 { "skip-bytes", required_argument, NULL, 'j' },
1301                 { "address-radix", required_argument, NULL, 'A' },
1302                 { "read-bytes", required_argument, NULL, 'N' },
1303                 { "format", required_argument, NULL, 't' },
1304                 { "output-duplicates", no_argument, NULL, 'v' },
1305                 { "strings", optional_argument, NULL, 's' },
1306                 { "traditional", no_argument, NULL, TRADITIONAL_OPTION },
1307                 { "width", optional_argument, NULL, 'w' },
1308                 { NULL, 0, NULL, 0 }
1309         };
1310
1311         int c;
1312         int n_files;
1313         int l_c_m;
1314         size_t desired_width = 0; // only for gcc
1315         int width_specified = 0;
1316         int n_failed_decodes = 0;
1317         int err;
1318
1319         /* The old-style 'pseudo starting address' to be printed in parentheses
1320            after any true address.  */
1321         uintmax_t pseudo_start = 0; // only for gcc
1322
1323         err = 0;
1324
1325         integral_type_size[sizeof(char)] = CHAR;
1326         integral_type_size[sizeof(short)] = SHORT;
1327         integral_type_size[sizeof(int)] = INT;
1328         integral_type_size[sizeof(long)] = LONG;
1329         /* If 'long' and 'long long' have the same size, it's fine
1330            to overwrite the entry for 'long' with this one.  */
1331         integral_type_size[sizeof(ulonglong_t)] = LONG_LONG;
1332
1333         fp_type_size[sizeof(float)] = FLOAT_SINGLE;
1334         /* The array entry for 'double' is filled in after that for longdouble_t
1335            so that if 'long double' is the same type or if long double isn't
1336            supported FLOAT_LONG_DOUBLE will never be used.  */
1337         fp_type_size[sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE;
1338         fp_type_size[sizeof(double)] = FLOAT_DOUBLE;
1339
1340         spec = NULL;
1341
1342         format_address = format_address_std;
1343         address_base = 8;
1344         address_pad_len = 7;
1345         flag_dump_strings = 0;
1346
1347         while ((c = getopt_long(argc, argv, "A:N:abcdfhij:lot:vxs:w:", long_options, NULL)) != -1)      {
1348                 switch (c) {
1349                 case 0:
1350                         break;
1351                 case 'A':
1352                         switch (optarg[0]) {
1353                         case 'd':
1354                                 format_address = format_address_std;
1355                                 address_base = 10;
1356                                 address_pad_len = 7;
1357                                 break;
1358                         case 'o':
1359                                 format_address = format_address_std;
1360                                 address_base = 8;
1361                                 address_pad_len = 7;
1362                                 break;
1363                         case 'x':
1364                                 format_address = format_address_std;
1365                                 address_base = 16;
1366                                 address_pad_len = 6;
1367                                 break;
1368                         case 'n':
1369                                 format_address = format_address_none;
1370                                 address_pad_len = 0;
1371                                 break;
1372                         default:
1373                                 bb_error_msg_and_die("bad output address radix '%c' "
1374                                         "(must be [doxn])", optarg[0]);
1375                                 break;
1376                         }
1377                         break;
1378
1379                 case 'j':
1380                         n_bytes_to_skip = xstrtoumax_sfx(optarg, 0, bkm);
1381                         break;
1382                 case 'N':
1383                         limit_bytes_to_format = 1;
1384
1385                         max_bytes_to_format = xstrtoumax_sfx(optarg, 0, bkm);
1386                         break;
1387                 case 's':
1388                         if (optarg == NULL)
1389                                 string_min = 3;
1390                         else {
1391                                 string_min = xstrtoumax_range_sfx(optarg, 0, 0, SIZE_MAX, bkm);
1392                         }
1393                         flag_dump_strings = 1;
1394                         break;
1395                 case 't':
1396                         if (decode_format_string(optarg))
1397                                 ++n_failed_decodes;
1398                         break;
1399                 case 'v':
1400                         abbreviate_duplicate_blocks = 0;
1401                         break;
1402                 case TRADITIONAL_OPTION:
1403                         traditional = 1;
1404                         break;
1405
1406                         /* The next several cases map the traditional format
1407                            specification options to the corresponding modern format
1408                            specs.  GNU od accepts any combination of old- and
1409                            new-style options.  Format specification options accumulate.  */
1410
1411 #define CASE_OLD_ARG(old_char,new_string) \
1412                 case old_char: \
1413                         if (decode_format_string(new_string)) \
1414                                 ++n_failed_decodes; \
1415                         break
1416
1417                 CASE_OLD_ARG('a', "a");
1418                 CASE_OLD_ARG('b', "oC");
1419                 CASE_OLD_ARG('c', "c");
1420                 CASE_OLD_ARG('d', "u2");
1421                 CASE_OLD_ARG('f', "fF");
1422                 CASE_OLD_ARG('h', "x2");
1423                 CASE_OLD_ARG('i', "d2");
1424                 CASE_OLD_ARG('l', "d4");
1425                 CASE_OLD_ARG('o', "o2");
1426                 CASE_OLD_ARG('x', "x2");
1427
1428                 /* FIXME: POSIX 1003.1-2001 with XSI requires this:
1429                 CASE_OLD_ARG('s', "d2");
1430                    for the traditional syntax, but this conflicts with case
1431                    's' above. */
1432
1433 #undef CASE_OLD_ARG
1434
1435                 case 'w':
1436                         width_specified = 1;
1437                         desired_width = 32;
1438                         if (optarg)
1439                                 desired_width = xatoul_range(optarg, 0, SIZE_MAX);
1440                         break;
1441                 default:
1442                         bb_show_usage();
1443                         break;
1444                 }
1445         }
1446
1447         if (n_failed_decodes > 0)
1448                 exit(EXIT_FAILURE);
1449
1450         if (flag_dump_strings && n_specs > 0)
1451                 bb_error_msg_and_die("no type may be specified when dumping strings");
1452
1453         n_files = argc - optind;
1454
1455         /* If the --traditional option is used, there may be from
1456                  0 to 3 remaining command line arguments;  handle each case
1457                  separately.
1458                                 od [file] [[+]offset[.][b] [[+]label[.][b]]]
1459                  The offset and pseudo_start have the same syntax.
1460
1461                  FIXME: POSIX 1003.1-2001 with XSI requires support for the
1462                  traditional syntax even if --traditional is not given.  */
1463
1464         if (traditional) {
1465                 uintmax_t offset;
1466
1467                 if (n_files == 1) {
1468                         if (parse_old_offset(argv[optind], &offset)) {
1469                                 n_bytes_to_skip = offset;
1470                                 --n_files;
1471                                 ++argv;
1472                         }
1473                 } else if (n_files == 2) {
1474                         uintmax_t o1, o2;
1475
1476                         if (parse_old_offset(argv[optind], &o1)
1477                         && parse_old_offset(argv[optind + 1], &o2)
1478                         ) {
1479                                 n_bytes_to_skip = o1;
1480                                 flag_pseudo_start = 1;
1481                                 pseudo_start = o2;
1482                                 argv += 2;
1483                                 n_files -= 2;
1484                         } else if (parse_old_offset(argv[optind + 1], &o2)) {
1485                                 n_bytes_to_skip = o2;
1486                                 --n_files;
1487                                 argv[optind + 1] = argv[optind];
1488                                 ++argv;
1489                         } else {
1490                                 bb_error_msg_and_die("invalid second operand "
1491                                         "in compatibility mode '%s'", argv[optind + 1]);
1492                         }
1493                 } else if (n_files == 3) {
1494                         uintmax_t o1, o2;
1495                         if (parse_old_offset(argv[optind + 1], &o1)
1496                         && parse_old_offset(argv[optind + 2], &o2)
1497                         ) {
1498                                 n_bytes_to_skip = o1;
1499                                 flag_pseudo_start = 1;
1500                                 pseudo_start = o2;
1501                                 argv[optind + 2] = argv[optind];
1502                                 argv += 2;
1503                                 n_files -= 2;
1504                         } else {
1505                                 bb_error_msg_and_die("in compatibility mode "
1506                                         "the last two arguments must be offsets");
1507                         }
1508                 } else if (n_files > 3) {
1509                         bb_error_msg_and_die("compatibility mode supports "
1510                                 "at most three arguments");
1511                 }
1512
1513                 if (flag_pseudo_start) {
1514                         if (format_address == format_address_none) {
1515                                 address_base = 8;
1516                                 address_pad_len = 7;
1517                                 format_address = format_address_paren;
1518                         } else
1519                                 format_address = format_address_label;
1520                 }
1521         }
1522
1523         if (limit_bytes_to_format) {
1524                 end_offset = n_bytes_to_skip + max_bytes_to_format;
1525                 if (end_offset < n_bytes_to_skip)
1526                         bb_error_msg_and_die("skip-bytes + read-bytes is too large");
1527         }
1528
1529         if (n_specs == 0) {
1530                 if (decode_format_string("o2")) {
1531                         /* This happens on Cray systems that don't have a 2-byte
1532                            integral type.  */
1533                         exit(EXIT_FAILURE);
1534                 }
1535                 n_specs = 1;
1536         }
1537
1538         if (n_files > 0) {
1539                 /* Set the global pointer FILE_LIST so that it
1540                    references the first file-argument on the command-line.  */
1541                 file_list = (char const *const *) &argv[optind];
1542         } else {
1543                 /* No files were listed on the command line.
1544                    Set the global pointer FILE_LIST so that it
1545                    references the null-terminated list of one name: "-".  */
1546                 file_list = default_file_list;
1547         }
1548
1549         /* open the first input file */
1550         err |= open_next_file();
1551         if (in_stream == NULL)
1552                 goto cleanup;
1553
1554         /* skip over any unwanted header bytes */
1555         err |= skip(n_bytes_to_skip);
1556         if (in_stream == NULL)
1557                 goto cleanup;
1558
1559         pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1560
1561         /* Compute output block length.  */
1562         l_c_m = get_lcm();
1563
1564         if (width_specified) {
1565                 if (desired_width != 0 && desired_width % l_c_m == 0)
1566                         bytes_per_block = desired_width;
1567                 else {
1568                         bb_error_msg("warning: invalid width %lu; using %d instead",
1569                                         (unsigned long) desired_width, l_c_m);
1570                         bytes_per_block = l_c_m;
1571                 }
1572         } else {
1573                 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1574                         bytes_per_block = l_c_m * (DEFAULT_BYTES_PER_BLOCK / l_c_m);
1575                 else
1576                         bytes_per_block = l_c_m;
1577         }
1578
1579 #ifdef DEBUG
1580         for (i = 0; i < n_specs; i++) {
1581                 printf("%d: fmt=\"%s\" width=%d\n",
1582                         i, spec[i].fmt_string, width_bytes[spec[i].size]);
1583         }
1584 #endif
1585
1586         err |= (flag_dump_strings ? dump_strings() : dump());
1587
1588 cleanup:
1589
1590         if (have_read_stdin && fclose(stdin) == EOF)
1591                 bb_perror_msg_and_die("standard input");
1592
1593         exit(err == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
1594 }