getopt32: fix llist_t options ordering. llist_rev is not unused.
[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         if (c) putchar(c);
870 }
871
872 static void
873 format_address_label(off_t address, char c)
874 {
875         format_address_std(address, ' ');
876         format_address_paren(address + pseudo_offset, c);
877 }
878 #endif
879
880 static void
881 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
882 {
883         fputs("  >", stdout);
884         while (n_bytes--) {
885                 unsigned c = *(unsigned char *) block++;
886                 c = (ISPRINT(c) ? c : '.');
887                 putchar(c);
888         }
889         putchar('<');
890 }
891
892 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
893    of the N_SPEC format specs.  CURRENT_OFFSET is the byte address of
894    CURR_BLOCK in the concatenation of input files, and it is printed
895    (optionally) only before the output line associated with the first
896    format spec.  When duplicate blocks are being abbreviated, the output
897    for a sequence of identical input blocks is the output for the first
898    block followed by an asterisk alone on a line.  It is valid to compare
899    the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
900    That condition may be false only for the last input block -- and then
901    only when it has not been padded to length BYTES_PER_BLOCK.  */
902
903 static void
904 write_block(off_t current_offset, size_t n_bytes,
905                 const char *prev_block, const char *curr_block)
906 {
907         static char first = 1;
908         static char prev_pair_equal = 0;
909         size_t i;
910
911         if (abbreviate_duplicate_blocks
912          && !first
913          && n_bytes == bytes_per_block
914          && memcmp(prev_block, curr_block, bytes_per_block) == 0
915         ) {
916                 if (prev_pair_equal) {
917                         /* The two preceding blocks were equal, and the current
918                            block is the same as the last one, so print nothing.  */
919                 } else {
920                         puts("*");
921                         prev_pair_equal = 1;
922                 }
923         } else {
924                 first = 0;
925                 prev_pair_equal = 0;
926                 for (i = 0; i < n_specs; i++) {
927                         if (i == 0)
928                                 format_address(current_offset, '\0');
929                         else
930                                 printf("%*s", address_pad_len_char - '0', "");
931                         (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
932                         if (spec[i].hexl_mode_trailer) {
933                                 /* space-pad out to full line width, then dump the trailer */
934                                 int datum_width = width_bytes[spec[i].size];
935                                 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
936                                 int field_width = spec[i].field_width + 1;
937                                 printf("%*s", blank_fields * field_width, "");
938                                 dump_hexl_mode_trailer(n_bytes, curr_block);
939                         }
940                         putchar('\n');
941                 }
942         }
943 }
944
945 static void
946 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
947 {
948         assert(0 < n && n <= bytes_per_block);
949
950         *n_bytes_in_buffer = 0;
951
952         if (n == 0)
953                 return;
954
955         while (in_stream != NULL) { /* EOF.  */
956                 size_t n_needed;
957                 size_t n_read;
958
959                 n_needed = n - *n_bytes_in_buffer;
960                 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
961                 *n_bytes_in_buffer += n_read;
962                 if (n_read == n_needed)
963                         break;
964                 /* error check is done in check_and_close */
965                 check_and_close();
966                 open_next_file();
967         }
968 }
969
970 /* Return the least common multiple of the sizes associated
971    with the format specs.  */
972
973 static int
974 get_lcm(void)
975 {
976         size_t i;
977         int l_c_m = 1;
978
979         for (i = 0; i < n_specs; i++)
980                 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
981         return l_c_m;
982 }
983
984 #if ENABLE_GETOPT_LONG
985 /* If S is a valid traditional offset specification with an optional
986    leading '+' return nonzero and set *OFFSET to the offset it denotes.  */
987
988 static int
989 parse_old_offset(const char *s, off_t *offset)
990 {
991         static const struct suffix_mult Bb[] = {
992                 { "B", 1024 },
993                 { "b", 512 },
994                 { NULL, 0 }
995         };
996         char *p;
997         int radix;
998
999         /* Skip over any leading '+'. */
1000         if (s[0] == '+') ++s;
1001
1002         /* Determine the radix we'll use to interpret S.  If there is a '.',
1003          * it's decimal, otherwise, if the string begins with '0X'or '0x',
1004          * it's hexadecimal, else octal.  */
1005         p = strchr(s, '.');
1006         radix = 8;
1007         if (p) {
1008                 p[0] = '\0'; /* cheating */
1009                 radix = 10;
1010         } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1011                 radix = 16;
1012
1013         *offset = xstrtooff_sfx(s, radix, Bb);
1014         if (p) p[0] = '.';
1015
1016         return (*offset >= 0);
1017 }
1018 #endif
1019
1020 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
1021    formatted block to standard output, and repeat until the specified
1022    maximum number of bytes has been read or until all input has been
1023    processed.  If the last block read is smaller than BYTES_PER_BLOCK
1024    and its size is not a multiple of the size associated with a format
1025    spec, extend the input block with zero bytes until its length is a
1026    multiple of all format spec sizes.  Write the final block.  Finally,
1027    write on a line by itself the offset of the byte after the last byte
1028    read.  Accumulate return values from calls to read_block and
1029    check_and_close, and if any was nonzero, return nonzero.
1030    Otherwise, return zero.  */
1031
1032 static void
1033 dump(void)
1034 {
1035         char *block[2];
1036         off_t current_offset;
1037         int idx;
1038         size_t n_bytes_read;
1039
1040         block[0] = xmalloc(2*bytes_per_block);
1041         block[1] = block[0] + bytes_per_block;
1042
1043         current_offset = n_bytes_to_skip;
1044
1045         idx = 0;
1046         if (limit_bytes_to_format) {
1047                 while (1) {
1048                         size_t n_needed;
1049                         if (current_offset >= end_offset) {
1050                                 n_bytes_read = 0;
1051                                 break;
1052                         }
1053                         n_needed = MIN(end_offset - current_offset,
1054                                 (off_t) bytes_per_block);
1055                         read_block(n_needed, block[idx], &n_bytes_read);
1056                         if (n_bytes_read < bytes_per_block)
1057                                 break;
1058                         assert(n_bytes_read == bytes_per_block);
1059                         write_block(current_offset, n_bytes_read,
1060                                block[!idx], block[idx]);
1061                         current_offset += n_bytes_read;
1062                         idx = !idx;
1063                 }
1064         } else {
1065                 while (1) {
1066                         read_block(bytes_per_block, block[idx], &n_bytes_read);
1067                         if (n_bytes_read < bytes_per_block)
1068                                 break;
1069                         assert(n_bytes_read == bytes_per_block);
1070                         write_block(current_offset, n_bytes_read,
1071                                block[!idx], block[idx]);
1072                         current_offset += n_bytes_read;
1073                         idx = !idx;
1074                 }
1075         }
1076
1077         if (n_bytes_read > 0) {
1078                 int l_c_m;
1079                 size_t bytes_to_write;
1080
1081                 l_c_m = get_lcm();
1082
1083                 /* Make bytes_to_write the smallest multiple of l_c_m that
1084                          is at least as large as n_bytes_read.  */
1085                 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1086
1087                 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1088                 write_block(current_offset, bytes_to_write,
1089                                    block[!idx], block[idx]);
1090                 current_offset += n_bytes_read;
1091         }
1092
1093         format_address(current_offset, '\n');
1094
1095         if (limit_bytes_to_format && current_offset >= end_offset)
1096                 check_and_close();
1097
1098         free(block[0]);
1099 }
1100
1101 /* Read a single byte into *C from the concatenation of the input files
1102    named in the global array FILE_LIST.  On the first call to this
1103    function, the global variable IN_STREAM is expected to be an open
1104    stream associated with the input file INPUT_FILENAME.  If IN_STREAM
1105    is at end-of-file, close it and update the global variables IN_STREAM
1106    and INPUT_FILENAME so they correspond to the next file in the list.
1107    Then try to read a byte from the newly opened file.  Repeat if
1108    necessary until EOF is reached for the last file in FILE_LIST, then
1109    set *C to EOF and return.  Subsequent calls do likewise.  The return
1110    value is nonzero if any errors occured, zero otherwise.  */
1111
1112 static void
1113 read_char(int *c)
1114 {
1115         while (in_stream) { /* !EOF */
1116                 *c = fgetc(in_stream);
1117                 if (*c != EOF)
1118                         return;
1119                 check_and_close();
1120                 open_next_file();
1121         }
1122         *c = EOF;
1123 }
1124
1125 /* Read N bytes into BLOCK from the concatenation of the input files
1126    named in the global array FILE_LIST.  On the first call to this
1127    function, the global variable IN_STREAM is expected to be an open
1128    stream associated with the input file INPUT_FILENAME.  If all N
1129    bytes cannot be read from IN_STREAM, close IN_STREAM and update
1130    the global variables IN_STREAM and INPUT_FILENAME.  Then try to
1131    read the remaining bytes from the newly opened file.  Repeat if
1132    necessary until EOF is reached for the last file in FILE_LIST.
1133    On subsequent calls, don't modify BLOCK and return zero.  Set
1134    *N_BYTES_IN_BUFFER to the number of bytes read.  If an error occurs,
1135    it will be detected through ferror when the stream is about to be
1136    closed.  If there is an error, give a message but continue reading
1137    as usual and return nonzero.  Otherwise return zero.  */
1138
1139 /* STRINGS mode.  Find each "string constant" in the input.
1140    A string constant is a run of at least 'string_min' ASCII
1141    graphic (or formatting) characters terminated by a null.
1142    Based on a function written by Richard Stallman for a
1143    traditional version of od.  Return nonzero if an error
1144    occurs.  Otherwise, return zero.  */
1145
1146 static void
1147 dump_strings(void)
1148 {
1149         size_t bufsize = MAX(100, string_min);
1150         char *buf = xmalloc(bufsize);
1151         off_t address = n_bytes_to_skip;
1152
1153         while (1) {
1154                 size_t i;
1155                 int c;
1156
1157                 /* See if the next 'string_min' chars are all printing chars.  */
1158  tryline:
1159                 if (limit_bytes_to_format && (end_offset - string_min <= address))
1160                         break;
1161                 i = 0;
1162                 while (!limit_bytes_to_format || address < end_offset) {
1163                         if (i == bufsize) {
1164                                 bufsize += bufsize/8;
1165                                 buf = xrealloc(buf, bufsize);
1166                         }
1167                         read_char(&c);
1168                         if (c < 0) { /* EOF */
1169                                 free(buf);
1170                                 return;
1171                         }
1172                         address++;
1173                         if (!c)
1174                                 break;
1175                         if (!ISPRINT(c))
1176                                 goto tryline;   /* It isn't; give up on this string.  */
1177                         buf[i++] = c;           /* String continues; store it all.  */
1178                 }
1179
1180                 if (i < string_min)             /* Too short! */
1181                         goto tryline;
1182
1183                 /* If we get here, the string is all printable and null-terminated,
1184                  * so print it.  It is all in 'buf' and 'i' is its length.  */
1185                 buf[i] = 0;
1186                 format_address(address - i - 1, ' ');
1187
1188                 for (i = 0; (c = buf[i]); i++) {
1189                         switch (c) {
1190                         case '\007': fputs("\\a", stdout); break;
1191                         case '\b': fputs("\\b", stdout); break;
1192                         case '\f': fputs("\\f", stdout); break;
1193                         case '\n': fputs("\\n", stdout); break;
1194                         case '\r': fputs("\\r", stdout); break;
1195                         case '\t': fputs("\\t", stdout); break;
1196                         case '\v': fputs("\\v", stdout); break;
1197                         default: putc(c, stdout);
1198                         }
1199                 }
1200                 putchar('\n');
1201         }
1202
1203         /* We reach this point only if we search through
1204            (max_bytes_to_format - string_min) bytes before reaching EOF.  */
1205         free(buf);
1206
1207         check_and_close();
1208 }
1209
1210 int od_main(int argc, char **argv);
1211 int od_main(int argc, char **argv)
1212 {
1213         static const struct suffix_mult bkm[] = {
1214                 { "b", 512 },
1215                 { "k", 1024 },
1216                 { "m", 1024*1024 },
1217                 { NULL, 0 }
1218         };
1219         unsigned opt;
1220         int l_c_m;
1221         /* The old-style 'pseudo starting address' to be printed in parentheses
1222            after any true address.  */
1223         off_t pseudo_start = 0; // only for gcc
1224         enum {
1225                 OPT_A = 1 << 0,
1226                 OPT_N = 1 << 1,
1227                 OPT_a = 1 << 2,
1228                 OPT_b = 1 << 3,
1229                 OPT_c = 1 << 4,
1230                 OPT_d = 1 << 5,
1231                 OPT_f = 1 << 6,
1232                 OPT_h = 1 << 7,
1233                 OPT_i = 1 << 8,
1234                 OPT_j = 1 << 9,
1235                 OPT_l = 1 << 10,
1236                 OPT_o = 1 << 11,
1237                 OPT_t = 1 << 12,
1238                 OPT_v = 1 << 13,
1239                 OPT_x = 1 << 14,
1240                 OPT_s = 1 << 15,
1241                 OPT_S = 1 << 16,
1242                 OPT_w = 1 << 17,
1243                 OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
1244         };
1245 #if ENABLE_GETOPT_LONG
1246         static const struct option long_options[] = {
1247                 { "skip-bytes",    required_argument, NULL, 'j' },
1248                 { "address-radix", required_argument, NULL, 'A' },
1249                 { "read-bytes",    required_argument, NULL, 'N' },
1250                 { "format",        required_argument, NULL, 't' },
1251                 { "output-duplicates", no_argument,   NULL, 'v' },
1252                 { "strings",       optional_argument, NULL, 'S' },
1253                 { "width",         optional_argument, NULL, 'w' },
1254                 { "traditional",   no_argument,       NULL, 0xff },
1255                 { NULL, 0, NULL, 0 }
1256         };
1257 #endif
1258         char *str_A, *str_N, *str_j, *str_S;
1259         char *str_w = NULL;
1260         llist_t *lst_t = NULL;
1261
1262         spec = NULL;
1263         format_address = format_address_std;
1264         address_base_char = 'o';
1265         address_pad_len_char = '7';
1266         flag_dump_strings = 0;
1267
1268         /* Parse command line */
1269         opt_complementary = "t::"; // list
1270 #if ENABLE_GETOPT_LONG
1271         applet_long_options = long_options;
1272 #endif
1273         opt = getopt32(argc, argv, "A:N:abcdfhij:lot:vxsS:"
1274                 "w::", // -w with optional param
1275                 // -S was -s and also had optional parameter
1276                 // but in coreutils 6.3 it was renamed and now has
1277                 // _mandatory_ parameter
1278                 &str_A, &str_N, &str_j, &lst_t, &str_S, &str_w);
1279         argc -= optind;
1280         argv += optind;
1281         if (opt & OPT_A) {
1282                 static const char doxn[] = "doxn";
1283                 static const char doxn_address_base_char[] = {
1284                         'u', 'o', 'x', /* '?' fourth one is not important */
1285                 };
1286                 static const uint8_t doxn_address_pad_len_char[] = {
1287                         '7', '7', '6', /* '?' */
1288                 };
1289                 char *p;
1290                 int pos;
1291                 p = strchr(doxn, str_A[0]);
1292                 if (!p)
1293                         bb_error_msg_and_die("bad output address radix "
1294                                 "'%c' (must be [doxn])", str_A[0]);
1295                 pos = p - doxn;
1296                 if (pos == 3) format_address = format_address_none;
1297                 address_base_char = doxn_address_base_char[pos];
1298                 address_pad_len_char = doxn_address_pad_len_char[pos];
1299         }
1300         if (opt & OPT_N) {
1301                 limit_bytes_to_format = 1;
1302                 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1303         }
1304         if (opt & OPT_a) decode_format_string("a");
1305         if (opt & OPT_b) decode_format_string("oC");
1306         if (opt & OPT_c) decode_format_string("c");
1307         if (opt & OPT_d) decode_format_string("u2");
1308         if (opt & OPT_f) decode_format_string("fF");
1309         if (opt & OPT_h) decode_format_string("x2");
1310         if (opt & OPT_i) decode_format_string("d2");
1311         if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1312         if (opt & OPT_l) decode_format_string("d4");
1313         if (opt & OPT_o) decode_format_string("o2");
1314         //if (opt & OPT_t)...
1315         while (lst_t) {
1316                 decode_format_string(lst_t->data);
1317                 lst_t = lst_t->link;
1318         }
1319         if (opt & OPT_v) abbreviate_duplicate_blocks = 0;
1320         if (opt & OPT_x) decode_format_string("x2");
1321         if (opt & OPT_s) decode_format_string("d2");
1322         if (opt & OPT_S) {
1323                 string_min = 3;
1324                 string_min = xstrtou_sfx(str_S, 0, bkm);
1325                 flag_dump_strings = 1;
1326         }
1327         //if (opt & OPT_w)...
1328         //if (opt & OPT_traditional)...
1329
1330         if (flag_dump_strings && n_specs > 0)
1331                 bb_error_msg_and_die("no type may be specified when dumping strings");
1332
1333         /* If the --traditional option is used, there may be from
1334          * 0 to 3 remaining command line arguments;  handle each case
1335          * separately.
1336          * od [file] [[+]offset[.][b] [[+]label[.][b]]]
1337          * The offset and pseudo_start have the same syntax.
1338          *
1339          * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1340          * traditional syntax even if --traditional is not given.  */
1341
1342 #if ENABLE_GETOPT_LONG
1343         if (opt & OPT_traditional) {
1344                 off_t o1, o2;
1345
1346                 if (argc == 1) {
1347                         if (parse_old_offset(argv[0], &o1)) {
1348                                 n_bytes_to_skip = o1;
1349                                 --argc;
1350                                 ++argv;
1351                         }
1352                 } else if (argc == 2) {
1353                         if (parse_old_offset(argv[0], &o1)
1354                          && parse_old_offset(argv[1], &o2)
1355                         ) {
1356                                 n_bytes_to_skip = o1;
1357                                 flag_pseudo_start = 1;
1358                                 pseudo_start = o2;
1359                                 argv += 2;
1360                                 argc -= 2;
1361                         } else if (parse_old_offset(argv[1], &o2)) {
1362                                 n_bytes_to_skip = o2;
1363                                 --argc;
1364                                 argv[1] = argv[0];
1365                                 ++argv;
1366                         } else {
1367                                 bb_error_msg_and_die("invalid second operand "
1368                                         "in compatibility mode '%s'", argv[1]);
1369                         }
1370                 } else if (argc == 3) {
1371                         if (parse_old_offset(argv[1], &o1)
1372                          && parse_old_offset(argv[2], &o2)
1373                         ) {
1374                                 n_bytes_to_skip = o1;
1375                                 flag_pseudo_start = 1;
1376                                 pseudo_start = o2;
1377                                 argv[2] = argv[0];
1378                                 argv += 2;
1379                                 argc -= 2;
1380                         } else {
1381                                 bb_error_msg_and_die("in compatibility mode "
1382                                         "the last two arguments must be offsets");
1383                         }
1384                 } else if (argc > 3)    {
1385                         bb_error_msg_and_die("compatibility mode supports "
1386                                 "at most three arguments");
1387                 }
1388
1389                 if (flag_pseudo_start) {
1390                         if (format_address == format_address_none) {
1391                                 address_base_char = 'o';
1392                                 address_pad_len_char = '7';
1393                                 format_address = format_address_paren;
1394                         } else
1395                                 format_address = format_address_label;
1396                 }
1397         }
1398 #endif
1399
1400         if (limit_bytes_to_format) {
1401                 end_offset = n_bytes_to_skip + max_bytes_to_format;
1402                 if (end_offset < n_bytes_to_skip)
1403                         bb_error_msg_and_die("skip-bytes + read-bytes is too large");
1404         }
1405
1406         if (n_specs == 0) {
1407                 decode_format_string("o2");
1408                 n_specs = 1;
1409         }
1410
1411         /* If no files were listed on the command line,
1412            set the global pointer FILE_LIST so that it
1413            references the null-terminated list of one name: "-".  */
1414         file_list = default_file_list;
1415         if (argc > 0) {
1416                 /* Set the global pointer FILE_LIST so that it
1417                    references the first file-argument on the command-line.  */
1418                 file_list = (char const *const *) argv;
1419         }
1420
1421         /* open the first input file */
1422         open_next_file();
1423         /* skip over any unwanted header bytes */
1424         skip(n_bytes_to_skip);
1425         if (!in_stream)
1426                 return 1;
1427
1428         pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1429
1430         /* Compute output block length.  */
1431         l_c_m = get_lcm();
1432
1433         if (opt & OPT_w) { /* -w: width */
1434                 bytes_per_block = 32;
1435                 if (str_w)
1436                         bytes_per_block = xatou(str_w);
1437                 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1438                         bb_error_msg("warning: invalid width %zu; using %d instead",
1439                                         bytes_per_block, l_c_m);
1440                         bytes_per_block = l_c_m;
1441                 }
1442         } else {
1443                 bytes_per_block = l_c_m;
1444                 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1445                         bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1446         }
1447
1448 #ifdef DEBUG
1449         for (i = 0; i < n_specs; i++) {
1450                 printf("%d: fmt=\"%s\" width=%d\n",
1451                         i, spec[i].fmt_string, width_bytes[spec[i].size]);
1452         }
1453 #endif
1454
1455         if (flag_dump_strings)
1456                 dump_strings();
1457         else
1458                 dump();
1459
1460         if (fclose(stdin) == EOF)
1461                 bb_perror_msg_and_die(bb_msg_standard_input);
1462
1463         return (ioerror != 0); /* err != 0 - return 1 (failure) */
1464 }