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