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