Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 37917 byte(s)
-updated to busybox-1.13.4
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     bb_error_msg("write error");
506     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 816 static const char *
525     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     if (!p) {
549     size = sizeof(int);
550     if (isdigit(s[0])) {
551     size = bb_strtou(s, &end, 0);
552     if (errno == ERANGE
553     || MAX_INTEGRAL_TYPE_SIZE < size
554     || integral_type_size[size] == NO_SIZE
555     ) {
556     bb_error_msg_and_die("invalid type string '%s'; "
557     "%u-byte %s type is not supported",
558     s_orig, size, "integral");
559     }
560     s = end;
561     }
562     } else {
563 niro 816 static const uint8_t CSIL_sizeof[4] = {
564 niro 532 sizeof(char),
565     sizeof(short),
566     sizeof(int),
567     sizeof(long),
568     };
569     size = CSIL_sizeof[p - CSIL];
570 niro 816 s++; /* skip C/S/I/L */
571 niro 532 }
572    
573     #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
574     ((Spec) == LONG_LONG ? (Max_format) \
575     : ((Spec) == LONG ? (Long_format) : (Min_format)))
576    
577     #define FMT_BYTES_ALLOCATED 9
578     size_spec = integral_type_size[size];
579    
580     {
581 niro 816 static const char doux[] ALIGN1 = "doux";
582 niro 532 static const char doux_fmt_letter[][4] = {
583     "lld", "llo", "llu", "llx"
584     };
585     static const enum output_format doux_fmt[] = {
586     SIGNED_DECIMAL,
587     OCTAL,
588     UNSIGNED_DECIMAL,
589     HEXADECIMAL,
590     };
591     static const uint8_t *const doux_bytes_to_XXX[] = {
592     bytes_to_signed_dec_digits,
593     bytes_to_oct_digits,
594     bytes_to_unsigned_dec_digits,
595     bytes_to_hex_digits,
596     };
597     static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
598     " %%%u%s",
599     " %%0%u%s",
600     " %%%u%s",
601     " %%0%u%s",
602     };
603    
604     pos = strchr(doux, c) - doux;
605     fmt = doux_fmt[pos];
606     field_width = doux_bytes_to_XXX[pos][size];
607     p = doux_fmt_letter[pos] + 2;
608     if (size_spec == LONG) p--;
609     if (size_spec == LONG_LONG) p -= 2;
610     fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
611     }
612    
613     switch (size_spec) {
614     case CHAR:
615     print_function = (fmt == SIGNED_DECIMAL
616     ? print_s_char
617     : print_char);
618     break;
619     case SHORT:
620     print_function = (fmt == SIGNED_DECIMAL
621     ? print_s_short
622     : print_short);
623     break;
624     case INT:
625     print_function = print_int;
626     break;
627     case LONG:
628     print_function = print_long;
629     break;
630     default: /* case LONG_LONG: */
631     print_function = print_long_long;
632     break;
633     }
634     break;
635     }
636    
637     case 'f': {
638 niro 816 static const char FDL[] ALIGN1 = "FDL";
639 niro 532
640     fmt = FLOATING_POINT;
641     ++s;
642     p = strchr(FDL, *s);
643     if (!p) {
644     size = sizeof(double);
645     if (isdigit(s[0])) {
646     size = bb_strtou(s, &end, 0);
647     if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
648     || fp_type_size[size] == NO_SIZE
649     ) {
650     bb_error_msg_and_die("invalid type string '%s'; "
651     "%u-byte %s type is not supported",
652     s_orig, size, "floating point");
653     }
654     s = end;
655     }
656     } else {
657     static const uint8_t FDL_sizeof[] = {
658     sizeof(float),
659     sizeof(double),
660     sizeof(longdouble_t),
661     };
662    
663     size = FDL_sizeof[p - FDL];
664     }
665    
666     size_spec = fp_type_size[size];
667    
668     switch (size_spec) {
669     case FLOAT_SINGLE:
670     print_function = print_float;
671     field_width = FLT_DIG + 8;
672     /* Don't use %#e; not all systems support it. */
673     fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
674     break;
675     case FLOAT_DOUBLE:
676     print_function = print_double;
677     field_width = DBL_DIG + 8;
678     fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
679     break;
680     default: /* case FLOAT_LONG_DOUBLE: */
681     print_function = print_long_double;
682     field_width = LDBL_DIG + 8;
683     fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
684     break;
685     }
686     break;
687     }
688    
689     case 'a':
690     ++s;
691     fmt = NAMED_CHARACTER;
692     size_spec = CHAR;
693     print_function = print_named_ascii;
694     field_width = 3;
695     break;
696     case 'c':
697     ++s;
698     fmt = CHARACTER;
699     size_spec = CHAR;
700     print_function = print_ascii;
701     field_width = 3;
702     break;
703     default:
704     bb_error_msg_and_die("invalid character '%c' "
705     "in type string '%s'", *s, s_orig);
706     }
707    
708     tspec->size = size_spec;
709     tspec->fmt = fmt;
710     tspec->print_function = print_function;
711     tspec->fmt_string = fmt_string;
712    
713     tspec->field_width = field_width;
714     tspec->hexl_mode_trailer = (*s == 'z');
715     if (tspec->hexl_mode_trailer)
716     s++;
717    
718 niro 816 return s;
719 niro 532 }
720    
721     /* Decode the modern od format string S. Append the decoded
722     representation to the global array SPEC, reallocating SPEC if
723 niro 816 necessary. */
724 niro 532
725     static void
726     decode_format_string(const char *s)
727     {
728     const char *s_orig = s;
729    
730     while (*s != '\0') {
731     struct tspec tspec;
732     const char *next;
733    
734 niro 816 next = decode_one_format(s_orig, s, &tspec);
735 niro 532
736     assert(s != next);
737     s = next;
738 niro 816 spec = xrealloc_vector(spec, 4, n_specs);
739     memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
740 niro 532 n_specs++;
741     }
742     }
743    
744     /* Given a list of one or more input filenames FILE_LIST, set the global
745     file pointer IN_STREAM to position N_SKIP in the concatenation of
746     those files. If any file operation fails or if there are fewer than
747     N_SKIP bytes in the combined input, give an error message and return
748     nonzero. When possible, use seek rather than read operations to
749     advance IN_STREAM. */
750    
751     static void
752     skip(off_t n_skip)
753     {
754     if (n_skip == 0)
755     return;
756    
757     while (in_stream) { /* !EOF */
758     struct stat file_stats;
759    
760     /* First try seeking. For large offsets, this extra work is
761     worthwhile. If the offset is below some threshold it may be
762     more efficient to move the pointer by reading. There are two
763     issues when trying to seek:
764     - the file must be seekable.
765     - before seeking to the specified position, make sure
766     that the new position is in the current file.
767     Try to do that by getting file's size using fstat.
768     But that will work only for regular files. */
769    
770     /* The st_size field is valid only for regular files
771     (and for symbolic links, which cannot occur here).
772     If the number of bytes left to skip is at least
773     as large as the size of the current file, we can
774     decrement n_skip and go on to the next file. */
775     if (fstat(fileno(in_stream), &file_stats) == 0
776 niro 816 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
777 niro 532 ) {
778     if (file_stats.st_size < n_skip) {
779     n_skip -= file_stats.st_size;
780 niro 816 /* take "check & close / open_next" route */
781 niro 532 } else {
782     if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
783     ioerror = 1;
784     return;
785     }
786     } else {
787 niro 816 /* If it's not a regular file with positive size,
788 niro 532 position the file pointer by reading. */
789 niro 816 char buf[1024];
790     size_t n_bytes_to_read = 1024;
791     size_t n_bytes_read;
792 niro 532
793     while (n_skip > 0) {
794     if (n_skip < n_bytes_to_read)
795     n_bytes_to_read = n_skip;
796     n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
797     n_skip -= n_bytes_read;
798     if (n_bytes_read != n_bytes_to_read)
799 niro 816 break; /* EOF on this file or error */
800 niro 532 }
801     }
802     if (n_skip == 0)
803     return;
804    
805     check_and_close();
806     open_next_file();
807     }
808    
809     if (n_skip)
810     bb_error_msg_and_die("cannot skip past end of combined input");
811     }
812    
813    
814     typedef void FN_format_address(off_t address, char c);
815    
816     static void
817 niro 816 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
818 niro 532 {
819     }
820    
821 niro 816 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
822 niro 532 /* Corresponds to 'x' above */
823     #define address_base_char address_fmt[sizeof(address_fmt)-3]
824     /* Corresponds to 'n' above */
825     #define address_pad_len_char address_fmt[2]
826    
827     static void
828     format_address_std(off_t address, char c)
829     {
830     /* Corresponds to 'c' */
831     address_fmt[sizeof(address_fmt)-2] = c;
832     printf(address_fmt, address);
833     }
834    
835     #if ENABLE_GETOPT_LONG
836     /* only used with --traditional */
837     static void
838     format_address_paren(off_t address, char c)
839     {
840     putchar('(');
841     format_address_std(address, ')');
842     if (c) putchar(c);
843     }
844    
845     static void
846     format_address_label(off_t address, char c)
847     {
848     format_address_std(address, ' ');
849     format_address_paren(address + pseudo_offset, c);
850     }
851     #endif
852    
853     static void
854     dump_hexl_mode_trailer(size_t n_bytes, const char *block)
855     {
856     fputs(" >", stdout);
857     while (n_bytes--) {
858     unsigned c = *(unsigned char *) block++;
859     c = (ISPRINT(c) ? c : '.');
860     putchar(c);
861     }
862     putchar('<');
863     }
864    
865     /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
866     of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
867     CURR_BLOCK in the concatenation of input files, and it is printed
868     (optionally) only before the output line associated with the first
869     format spec. When duplicate blocks are being abbreviated, the output
870     for a sequence of identical input blocks is the output for the first
871     block followed by an asterisk alone on a line. It is valid to compare
872     the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
873     That condition may be false only for the last input block -- and then
874     only when it has not been padded to length BYTES_PER_BLOCK. */
875    
876     static void
877     write_block(off_t current_offset, size_t n_bytes,
878     const char *prev_block, const char *curr_block)
879     {
880     static char first = 1;
881     static char prev_pair_equal = 0;
882     size_t i;
883    
884 niro 816 if (!verbose && !first
885 niro 532 && n_bytes == bytes_per_block
886     && memcmp(prev_block, curr_block, bytes_per_block) == 0
887     ) {
888     if (prev_pair_equal) {
889     /* The two preceding blocks were equal, and the current
890     block is the same as the last one, so print nothing. */
891     } else {
892     puts("*");
893     prev_pair_equal = 1;
894     }
895     } else {
896     first = 0;
897     prev_pair_equal = 0;
898     for (i = 0; i < n_specs; i++) {
899     if (i == 0)
900     format_address(current_offset, '\0');
901     else
902     printf("%*s", address_pad_len_char - '0', "");
903     (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
904     if (spec[i].hexl_mode_trailer) {
905     /* space-pad out to full line width, then dump the trailer */
906     int datum_width = width_bytes[spec[i].size];
907     int blank_fields = (bytes_per_block - n_bytes) / datum_width;
908     int field_width = spec[i].field_width + 1;
909     printf("%*s", blank_fields * field_width, "");
910     dump_hexl_mode_trailer(n_bytes, curr_block);
911     }
912     putchar('\n');
913     }
914     }
915     }
916    
917     static void
918     read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
919     {
920     assert(0 < n && n <= bytes_per_block);
921    
922     *n_bytes_in_buffer = 0;
923    
924     if (n == 0)
925     return;
926    
927     while (in_stream != NULL) { /* EOF. */
928     size_t n_needed;
929     size_t n_read;
930    
931     n_needed = n - *n_bytes_in_buffer;
932     n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
933     *n_bytes_in_buffer += n_read;
934     if (n_read == n_needed)
935     break;
936     /* error check is done in check_and_close */
937     check_and_close();
938     open_next_file();
939     }
940     }
941    
942     /* Return the least common multiple of the sizes associated
943     with the format specs. */
944    
945     static int
946     get_lcm(void)
947     {
948     size_t i;
949     int l_c_m = 1;
950    
951     for (i = 0; i < n_specs; i++)
952     l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
953     return l_c_m;
954     }
955    
956     #if ENABLE_GETOPT_LONG
957     /* If S is a valid traditional offset specification with an optional
958     leading '+' return nonzero and set *OFFSET to the offset it denotes. */
959    
960     static int
961     parse_old_offset(const char *s, off_t *offset)
962     {
963     static const struct suffix_mult Bb[] = {
964     { "B", 1024 },
965     { "b", 512 },
966 niro 816 { }
967 niro 532 };
968     char *p;
969     int radix;
970    
971     /* Skip over any leading '+'. */
972     if (s[0] == '+') ++s;
973    
974     /* Determine the radix we'll use to interpret S. If there is a '.',
975     * it's decimal, otherwise, if the string begins with '0X'or '0x',
976     * it's hexadecimal, else octal. */
977     p = strchr(s, '.');
978     radix = 8;
979     if (p) {
980     p[0] = '\0'; /* cheating */
981     radix = 10;
982     } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
983     radix = 16;
984    
985     *offset = xstrtooff_sfx(s, radix, Bb);
986     if (p) p[0] = '.';
987    
988     return (*offset >= 0);
989     }
990     #endif
991    
992     /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
993     formatted block to standard output, and repeat until the specified
994     maximum number of bytes has been read or until all input has been
995     processed. If the last block read is smaller than BYTES_PER_BLOCK
996     and its size is not a multiple of the size associated with a format
997     spec, extend the input block with zero bytes until its length is a
998     multiple of all format spec sizes. Write the final block. Finally,
999     write on a line by itself the offset of the byte after the last byte
1000 niro 816 read. */
1001 niro 532
1002     static void
1003 niro 816 dump(off_t current_offset, off_t end_offset)
1004 niro 532 {
1005     char *block[2];
1006     int idx;
1007     size_t n_bytes_read;
1008    
1009     block[0] = xmalloc(2*bytes_per_block);
1010     block[1] = block[0] + bytes_per_block;
1011    
1012     idx = 0;
1013     if (limit_bytes_to_format) {
1014     while (1) {
1015     size_t n_needed;
1016     if (current_offset >= end_offset) {
1017     n_bytes_read = 0;
1018     break;
1019     }
1020     n_needed = MIN(end_offset - current_offset,
1021     (off_t) bytes_per_block);
1022     read_block(n_needed, block[idx], &n_bytes_read);
1023     if (n_bytes_read < bytes_per_block)
1024     break;
1025     assert(n_bytes_read == bytes_per_block);
1026     write_block(current_offset, n_bytes_read,
1027     block[!idx], block[idx]);
1028     current_offset += n_bytes_read;
1029     idx = !idx;
1030     }
1031     } else {
1032     while (1) {
1033     read_block(bytes_per_block, block[idx], &n_bytes_read);
1034     if (n_bytes_read < bytes_per_block)
1035     break;
1036     assert(n_bytes_read == bytes_per_block);
1037     write_block(current_offset, n_bytes_read,
1038     block[!idx], block[idx]);
1039     current_offset += n_bytes_read;
1040     idx = !idx;
1041     }
1042     }
1043    
1044     if (n_bytes_read > 0) {
1045     int l_c_m;
1046     size_t bytes_to_write;
1047    
1048     l_c_m = get_lcm();
1049    
1050     /* Make bytes_to_write the smallest multiple of l_c_m that
1051     is at least as large as n_bytes_read. */
1052     bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1053    
1054     memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1055     write_block(current_offset, bytes_to_write,
1056     block[!idx], block[idx]);
1057     current_offset += n_bytes_read;
1058     }
1059    
1060     format_address(current_offset, '\n');
1061    
1062     if (limit_bytes_to_format && current_offset >= end_offset)
1063     check_and_close();
1064    
1065     free(block[0]);
1066     }
1067    
1068     /* Read a single byte into *C from the concatenation of the input files
1069     named in the global array FILE_LIST. On the first call to this
1070     function, the global variable IN_STREAM is expected to be an open
1071     stream associated with the input file INPUT_FILENAME. If IN_STREAM
1072     is at end-of-file, close it and update the global variables IN_STREAM
1073     and INPUT_FILENAME so they correspond to the next file in the list.
1074     Then try to read a byte from the newly opened file. Repeat if
1075     necessary until EOF is reached for the last file in FILE_LIST, then
1076 niro 816 set *C to EOF and return. Subsequent calls do likewise. */
1077 niro 532
1078     static void
1079     read_char(int *c)
1080     {
1081     while (in_stream) { /* !EOF */
1082     *c = fgetc(in_stream);
1083     if (*c != EOF)
1084     return;
1085     check_and_close();
1086     open_next_file();
1087     }
1088     *c = EOF;
1089     }
1090    
1091     /* Read N bytes into BLOCK from the concatenation of the input files
1092     named in the global array FILE_LIST. On the first call to this
1093     function, the global variable IN_STREAM is expected to be an open
1094     stream associated with the input file INPUT_FILENAME. If all N
1095     bytes cannot be read from IN_STREAM, close IN_STREAM and update
1096     the global variables IN_STREAM and INPUT_FILENAME. Then try to
1097     read the remaining bytes from the newly opened file. Repeat if
1098     necessary until EOF is reached for the last file in FILE_LIST.
1099     On subsequent calls, don't modify BLOCK and return zero. Set
1100     *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1101     it will be detected through ferror when the stream is about to be
1102     closed. If there is an error, give a message but continue reading
1103     as usual and return nonzero. Otherwise return zero. */
1104    
1105     /* STRINGS mode. Find each "string constant" in the input.
1106     A string constant is a run of at least 'string_min' ASCII
1107     graphic (or formatting) characters terminated by a null.
1108     Based on a function written by Richard Stallman for a
1109 niro 816 traditional version of od. */
1110 niro 532
1111     static void
1112 niro 816 dump_strings(off_t address, off_t end_offset)
1113 niro 532 {
1114     size_t bufsize = MAX(100, string_min);
1115     char *buf = xmalloc(bufsize);
1116    
1117     while (1) {
1118     size_t i;
1119     int c;
1120    
1121     /* See if the next 'string_min' chars are all printing chars. */
1122     tryline:
1123     if (limit_bytes_to_format && (end_offset - string_min <= address))
1124     break;
1125     i = 0;
1126     while (!limit_bytes_to_format || address < end_offset) {
1127     if (i == bufsize) {
1128     bufsize += bufsize/8;
1129     buf = xrealloc(buf, bufsize);
1130     }
1131     read_char(&c);
1132     if (c < 0) { /* EOF */
1133     free(buf);
1134     return;
1135     }
1136     address++;
1137     if (!c)
1138     break;
1139     if (!ISPRINT(c))
1140     goto tryline; /* It isn't; give up on this string. */
1141     buf[i++] = c; /* String continues; store it all. */
1142     }
1143    
1144     if (i < string_min) /* Too short! */
1145     goto tryline;
1146    
1147 niro 816 /* If we get here, the string is all printable and NUL-terminated,
1148 niro 532 * so print it. It is all in 'buf' and 'i' is its length. */
1149     buf[i] = 0;
1150     format_address(address - i - 1, ' ');
1151    
1152     for (i = 0; (c = buf[i]); i++) {
1153     switch (c) {
1154     case '\007': fputs("\\a", stdout); break;
1155     case '\b': fputs("\\b", stdout); break;
1156     case '\f': fputs("\\f", stdout); break;
1157     case '\n': fputs("\\n", stdout); break;
1158     case '\r': fputs("\\r", stdout); break;
1159     case '\t': fputs("\\t", stdout); break;
1160     case '\v': fputs("\\v", stdout); break;
1161 niro 816 default: putchar(c);
1162 niro 532 }
1163     }
1164     putchar('\n');
1165     }
1166    
1167     /* We reach this point only if we search through
1168     (max_bytes_to_format - string_min) bytes before reaching EOF. */
1169     free(buf);
1170    
1171     check_and_close();
1172     }
1173    
1174 niro 816 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1175     int od_main(int argc, char **argv)
1176 niro 532 {
1177     static const struct suffix_mult bkm[] = {
1178     { "b", 512 },
1179     { "k", 1024 },
1180     { "m", 1024*1024 },
1181 niro 816 { }
1182 niro 532 };
1183     enum {
1184     OPT_A = 1 << 0,
1185     OPT_N = 1 << 1,
1186     OPT_a = 1 << 2,
1187     OPT_b = 1 << 3,
1188     OPT_c = 1 << 4,
1189     OPT_d = 1 << 5,
1190     OPT_f = 1 << 6,
1191     OPT_h = 1 << 7,
1192     OPT_i = 1 << 8,
1193     OPT_j = 1 << 9,
1194     OPT_l = 1 << 10,
1195     OPT_o = 1 << 11,
1196     OPT_t = 1 << 12,
1197     OPT_v = 1 << 13,
1198     OPT_x = 1 << 14,
1199     OPT_s = 1 << 15,
1200     OPT_S = 1 << 16,
1201     OPT_w = 1 << 17,
1202     OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
1203     };
1204     #if ENABLE_GETOPT_LONG
1205 niro 816 static const char od_longopts[] ALIGN1 =
1206     "skip-bytes\0" Required_argument "j"
1207     "address-radix\0" Required_argument "A"
1208     "read-bytes\0" Required_argument "N"
1209     "format\0" Required_argument "t"
1210     "output-duplicates\0" No_argument "v"
1211     "strings\0" Optional_argument "S"
1212     "width\0" Optional_argument "w"
1213     "traditional\0" No_argument "\xff"
1214     ;
1215 niro 532 #endif
1216     char *str_A, *str_N, *str_j, *str_S;
1217     llist_t *lst_t = NULL;
1218 niro 816 unsigned opt;
1219     int l_c_m;
1220     /* The old-style 'pseudo starting address' to be printed in parentheses
1221     after any true address. */
1222     off_t pseudo_start = pseudo_start; // for gcc
1223     /* The number of input bytes to skip before formatting and writing. */
1224     off_t n_bytes_to_skip = 0;
1225     /* The offset of the first byte after the last byte to be formatted. */
1226     off_t end_offset = 0;
1227     /* The maximum number of bytes that will be formatted. */
1228     off_t max_bytes_to_format = 0;
1229 niro 532
1230     spec = NULL;
1231     format_address = format_address_std;
1232     address_base_char = 'o';
1233     address_pad_len_char = '7';
1234 niro 816 /* flag_dump_strings = 0; - already is */
1235 niro 532
1236     /* Parse command line */
1237 niro 816 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1238 niro 532 #if ENABLE_GETOPT_LONG
1239 niro 816 applet_long_options = od_longopts;
1240 niro 532 #endif
1241 niro 816 opt = getopt32(argv, "A:N:abcdfhij:lot:vxsS:"
1242 niro 532 "w::", // -w with optional param
1243     // -S was -s and also had optional parameter
1244     // but in coreutils 6.3 it was renamed and now has
1245     // _mandatory_ parameter
1246 niro 816 &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block);
1247 niro 532 argc -= optind;
1248     argv += optind;
1249     if (opt & OPT_A) {
1250 niro 816 static const char doxn[] ALIGN1 = "doxn";
1251     static const char doxn_address_base_char[] ALIGN1 = {
1252 niro 532 'u', 'o', 'x', /* '?' fourth one is not important */
1253     };
1254 niro 816 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1255 niro 532 '7', '7', '6', /* '?' */
1256     };
1257     char *p;
1258     int pos;
1259     p = strchr(doxn, str_A[0]);
1260     if (!p)
1261     bb_error_msg_and_die("bad output address radix "
1262     "'%c' (must be [doxn])", str_A[0]);
1263     pos = p - doxn;
1264     if (pos == 3) format_address = format_address_none;
1265     address_base_char = doxn_address_base_char[pos];
1266     address_pad_len_char = doxn_address_pad_len_char[pos];
1267     }
1268     if (opt & OPT_N) {
1269     limit_bytes_to_format = 1;
1270     max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1271     }
1272     if (opt & OPT_a) decode_format_string("a");
1273     if (opt & OPT_b) decode_format_string("oC");
1274     if (opt & OPT_c) decode_format_string("c");
1275     if (opt & OPT_d) decode_format_string("u2");
1276     if (opt & OPT_f) decode_format_string("fF");
1277     if (opt & OPT_h) decode_format_string("x2");
1278     if (opt & OPT_i) decode_format_string("d2");
1279     if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1280     if (opt & OPT_l) decode_format_string("d4");
1281     if (opt & OPT_o) decode_format_string("o2");
1282     //if (opt & OPT_t)...
1283     while (lst_t) {
1284 niro 816 decode_format_string(llist_pop(&lst_t));
1285 niro 532 }
1286 niro 816 if (opt & OPT_v) verbose = 1;
1287 niro 532 if (opt & OPT_x) decode_format_string("x2");
1288     if (opt & OPT_s) decode_format_string("d2");
1289     if (opt & OPT_S) {
1290     string_min = 3;
1291     string_min = xstrtou_sfx(str_S, 0, bkm);
1292     flag_dump_strings = 1;
1293     }
1294     //if (opt & OPT_w)...
1295     //if (opt & OPT_traditional)...
1296    
1297     if (flag_dump_strings && n_specs > 0)
1298     bb_error_msg_and_die("no type may be specified when dumping strings");
1299    
1300     /* If the --traditional option is used, there may be from
1301     * 0 to 3 remaining command line arguments; handle each case
1302     * separately.
1303 niro 816 * od [file] [[+]offset[.][b] [[+]label[.][b]]]
1304 niro 532 * The offset and pseudo_start have the same syntax.
1305     *
1306     * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1307     * traditional syntax even if --traditional is not given. */
1308    
1309     #if ENABLE_GETOPT_LONG
1310     if (opt & OPT_traditional) {
1311     off_t o1, o2;
1312    
1313     if (argc == 1) {
1314     if (parse_old_offset(argv[0], &o1)) {
1315     n_bytes_to_skip = o1;
1316     --argc;
1317     ++argv;
1318     }
1319     } else if (argc == 2) {
1320     if (parse_old_offset(argv[0], &o1)
1321     && parse_old_offset(argv[1], &o2)
1322     ) {
1323     n_bytes_to_skip = o1;
1324     flag_pseudo_start = 1;
1325     pseudo_start = o2;
1326     argv += 2;
1327     argc -= 2;
1328     } else if (parse_old_offset(argv[1], &o2)) {
1329     n_bytes_to_skip = o2;
1330     --argc;
1331     argv[1] = argv[0];
1332     ++argv;
1333     } else {
1334     bb_error_msg_and_die("invalid second operand "
1335     "in compatibility mode '%s'", argv[1]);
1336     }
1337     } else if (argc == 3) {
1338     if (parse_old_offset(argv[1], &o1)
1339     && parse_old_offset(argv[2], &o2)
1340     ) {
1341     n_bytes_to_skip = o1;
1342     flag_pseudo_start = 1;
1343     pseudo_start = o2;
1344     argv[2] = argv[0];
1345     argv += 2;
1346     argc -= 2;
1347     } else {
1348     bb_error_msg_and_die("in compatibility mode "
1349     "the last two arguments must be offsets");
1350     }
1351     } else if (argc > 3) {
1352     bb_error_msg_and_die("compatibility mode supports "
1353     "at most three arguments");
1354     }
1355    
1356     if (flag_pseudo_start) {
1357     if (format_address == format_address_none) {
1358     address_base_char = 'o';
1359     address_pad_len_char = '7';
1360     format_address = format_address_paren;
1361     } else
1362     format_address = format_address_label;
1363     }
1364     }
1365     #endif
1366    
1367     if (limit_bytes_to_format) {
1368     end_offset = n_bytes_to_skip + max_bytes_to_format;
1369     if (end_offset < n_bytes_to_skip)
1370     bb_error_msg_and_die("skip-bytes + read-bytes is too large");
1371     }
1372    
1373     if (n_specs == 0) {
1374     decode_format_string("o2");
1375     n_specs = 1;
1376     }
1377    
1378     /* If no files were listed on the command line,
1379     set the global pointer FILE_LIST so that it
1380     references the null-terminated list of one name: "-". */
1381 niro 816 file_list = bb_argv_dash;
1382 niro 532 if (argc > 0) {
1383     /* Set the global pointer FILE_LIST so that it
1384     references the first file-argument on the command-line. */
1385     file_list = (char const *const *) argv;
1386     }
1387    
1388     /* open the first input file */
1389     open_next_file();
1390     /* skip over any unwanted header bytes */
1391     skip(n_bytes_to_skip);
1392     if (!in_stream)
1393 niro 816 return EXIT_FAILURE;
1394 niro 532
1395     pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1396    
1397     /* Compute output block length. */
1398     l_c_m = get_lcm();
1399    
1400     if (opt & OPT_w) { /* -w: width */
1401     if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1402 niro 816 bb_error_msg("warning: invalid width %u; using %d instead",
1403     (unsigned)bytes_per_block, l_c_m);
1404 niro 532 bytes_per_block = l_c_m;
1405     }
1406     } else {
1407     bytes_per_block = l_c_m;
1408     if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1409     bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1410     }
1411    
1412     #ifdef DEBUG
1413     for (i = 0; i < n_specs; i++) {
1414     printf("%d: fmt=\"%s\" width=%d\n",
1415     i, spec[i].fmt_string, width_bytes[spec[i].size]);
1416     }
1417     #endif
1418    
1419     if (flag_dump_strings)
1420 niro 816 dump_strings(n_bytes_to_skip, end_offset);
1421 niro 532 else
1422 niro 816 dump(n_bytes_to_skip, end_offset);
1423 niro 532
1424     if (fclose(stdin) == EOF)
1425     bb_perror_msg_and_die(bb_msg_standard_input);
1426    
1427 niro 816 return ioerror;
1428 niro 532 }