Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/od_bloaty.c

Parent Directory Parent Directory | Revision Log Revision Log


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