Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 17  Line 17 
17    
18  /* Written by Jim Meyering.  */  /* Written by Jim Meyering.  */
19    
20  /* Busyboxed by Denis Vlasenko  /* Busyboxed by Denys Vlasenko
21    
22  Based on od.c from coreutils-5.2.1  Based on od.c from coreutils-5.2.1
23  Top bloat sources:  Top bloat sources:
# Line 49  diff -u -a std bbox >bbox.diff || { echo Line 49  diff -u -a std bbox >bbox.diff || { echo
49    
50  */  */
51    
52    #include "libbb.h"
 #include "busybox.h"  
 #include <getopt.h>  
53    
54  #define assert(a) ((void)0)  #define assert(a) ((void)0)
55    
# Line 130  struct tspec { Line 128  struct tspec {
128     10 unsigned decimal     10 unsigned decimal
129     8 unsigned hexadecimal  */     8 unsigned hexadecimal  */
130    
131  static const uint8_t bytes_to_oct_digits[] =  static const uint8_t bytes_to_oct_digits[] ALIGN1 =
132  {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};  {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
133    
134  static const uint8_t bytes_to_signed_dec_digits[] =  static const uint8_t bytes_to_signed_dec_digits[] ALIGN1 =
135  {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};  {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
136    
137  static const uint8_t bytes_to_unsigned_dec_digits[] =  static const uint8_t bytes_to_unsigned_dec_digits[] ALIGN1 =
138  {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};  {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
139    
140  static const uint8_t bytes_to_hex_digits[] =  static const uint8_t bytes_to_hex_digits[] ALIGN1 =
141  {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};  {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.  */  /* Convert enum size_spec to the size of the named type.  */
144  static const signed char width_bytes[] = {  static const signed char width_bytes[] ALIGN1 = {
145   -1,   -1,
146   sizeof(char),   sizeof(char),
147   sizeof(short),   sizeof(short),
# Line 154  static const signed char width_bytes[] = Line 152  static const signed char width_bytes[] =
152   sizeof(double),   sizeof(double),
153   sizeof(longdouble_t)   sizeof(longdouble_t)
154  };  };
   
155  /* Ensure that for each member of 'enum size_spec' there is an  /* Ensure that for each member of 'enum size_spec' there is an
156     initializer in the width_bytes array.  */     initializer in the width_bytes array.  */
157  struct dummy {  struct ERR_width_bytes_has_bad_size {
158   int assert_width_bytes_matches_size_spec_decl   char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
  [sizeof width_bytes / sizeof width_bytes[0] == N_SIZE_SPECS ? 1 : -1];  
159  };  };
160    
161    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  static size_t string_min;  static size_t string_min;
 static int flag_dump_strings;  
172    
173  /* Non-zero if an old-style 'pseudo-address' was specified.  */  /* An array of specs describing how to format each input block.  */
174  static int flag_pseudo_start;  static size_t n_specs;
175    static struct tspec *spec;
176    
177    /* 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  /* The difference between the old-style pseudo starting address and  /* The difference between the old-style pseudo starting address and
181     the number of bytes to skip.  */     the number of bytes to skip.  */
182  static off_t pseudo_offset;  static off_t pseudo_offset;
   
 /* Function that accepts an address and an optional following char,  
    and prints the address and char to stdout.  */  
 static void (*format_address) (off_t, char);  
   
 /* The number of input bytes to skip before formatting and writing.  */  
 static off_t n_bytes_to_skip; // = 0;  
   
183  /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all  /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
184     input is formatted.  */     input is formatted.  */
 static int limit_bytes_to_format; // = 0;  
   
 /* The maximum number of bytes that will be formatted.  */  
 static off_t max_bytes_to_format;  
   
 /* The offset of the first byte after the last byte to be formatted.  */  
 static off_t end_offset;  
   
 /* When nonzero and two or more consecutive blocks are equal, format  
    only the first block and output an asterisk alone on the following  
    line to indicate that identical blocks have been elided.  */  
 static int abbreviate_duplicate_blocks = 1;  
   
 /* An array of specs describing how to format each input block.  */  
 static size_t n_specs;  
 static struct tspec *spec;  
185    
186  /* The number of input bytes formatted per output line.  It must be  /* 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     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     the specified output types.  It should be as large as possible, but
189     no larger than 16 -- unless specified with the -w option.  */     no larger than 16 -- unless specified with the -w option.  */
190  static size_t bytes_per_block;  static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
   
 /* Human-readable representation of *file_list (for error messages).  
    It differs from *file_list only when *file_list is "-".  */  
 static char const *input_filename;  
191    
192  /* A NULL-terminated list of the file-arguments from the command line.  */  /* A NULL-terminated list of the file-arguments from the command line.  */
193  static char const *const *file_list;  static const char *const *file_list;
   
 /* Initializer for file_list if no file-arguments  
    were specified on the command line.  */  
 static char const *const default_file_list[] = { "-", NULL };  
194    
195  /* The input stream associated with the current file.  */  /* The input stream associated with the current file.  */
196  static FILE *in_stream;  static FILE *in_stream;
197    
 static int ioerror;  
   
198  #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)  #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
199  static unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] = {  static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
200   [sizeof(char)] = CHAR,   [sizeof(char)] = CHAR,
201  #if USHRT_MAX != UCHAR_MAX  #if USHRT_MAX != UCHAR_MAX
202   [sizeof(short)] = SHORT,   [sizeof(short)] = SHORT,
# Line 238  static unsigned char integral_type_size[ Line 213  static unsigned char integral_type_size[
213  };  };
214    
215  #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)  #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
216  static unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] = {  static const unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
217   /* gcc seems to allow repeated indexes. Last one stays */   /* gcc seems to allow repeated indexes. Last one stays */
218   [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,   [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
219   [sizeof(double)] = FLOAT_DOUBLE,   [sizeof(double)] = FLOAT_DOUBLE,
220   [sizeof(float)] = FLOAT_SINGLE,   [sizeof(float)] = FLOAT_SINGLE
221  };  };
222    
223    
# Line 384  print_long_double(size_t n_bytes, const Line 359  print_long_double(size_t n_bytes, const
359  }  }
360    
361  /* print_[named]_ascii are optimized for speed.  /* print_[named]_ascii are optimized for speed.
362   * Remember, someday you may want to pump gigabytes thru this thing.   * Remember, someday you may want to pump gigabytes through this thing.
363   * Saving a dozen of .text bytes here is counter-productive */   * Saving a dozen of .text bytes here is counter-productive */
364    
365  static void  static void
366  print_named_ascii(size_t n_bytes, const char *block,  print_named_ascii(size_t n_bytes, const char *block,
367   const char *unused_fmt_string ATTRIBUTE_UNUSED)   const char *unused_fmt_string UNUSED_PARAM)
368  {  {
369   /* Names for some non-printing characters.  */   /* Names for some non-printing characters.  */
370   static const char charname[33][3] = {   static const char charname[33][3] ALIGN1 = {
371   "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",   "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
372   " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",   " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
373   "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",   "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
# Line 429  print_named_ascii(size_t n_bytes, const Line 404  print_named_ascii(size_t n_bytes, const
404    
405  static void  static void
406  print_ascii(size_t n_bytes, const char *block,  print_ascii(size_t n_bytes, const char *block,
407   const char *unused_fmt_string ATTRIBUTE_UNUSED)   const char *unused_fmt_string UNUSED_PARAM)
408  {  {
409   // buf[N] pos:  01234 56789   // buf[N] pos:  01234 56789
410   char buf[12] = "   x\0 0xx\0";   char buf[12] = "   x\0 0xx\0";
# Line 491  static void Line 466  static void
466  open_next_file(void)  open_next_file(void)
467  {  {
468   while (1) {   while (1) {
469   input_filename = *file_list;   if (!*file_list)
  if (!input_filename)  
470   return;   return;
471   file_list++;   in_stream = fopen_or_warn_stdin(*file_list++);
  in_stream = fopen_or_warn_stdin(input_filename);  
472   if (in_stream) {   if (in_stream) {
  if (in_stream == stdin)  
  input_filename = bb_msg_standard_input;  
473   break;   break;
474   }   }
475   ioerror = 1;   ioerror = 1;
# Line 520  check_and_close(void) Line 491  check_and_close(void)
491  {  {
492   if (in_stream) {   if (in_stream) {
493   if (ferror(in_stream)) {   if (ferror(in_stream)) {
494   bb_error_msg("%s: read error", input_filename);   bb_error_msg("%s: read error", (in_stream == stdin)
495     ? bb_msg_standard_input
496     : file_list[-1]
497     );
498   ioerror = 1;   ioerror = 1;
499   }   }
500   fclose_if_not_stdin(in_stream);   fclose_if_not_stdin(in_stream);
# Line 534  check_and_close(void) Line 508  check_and_close(void)
508  }  }
509    
510  /* If S points to a single valid modern od format string, put  /* If S points to a single valid modern od format string, put
511     a description of that format in *TSPEC, make *NEXT point at the     a description of that format in *TSPEC, return pointer to
512     character following the just-decoded format (if *NEXT is non-NULL),     character following the just-decoded format.
513     and return zero.  For example, if S were "d4afL"     For example, if S were "d4afL", we will return a rtp to "afL"
514     *NEXT would be set to "afL" and *TSPEC would be     and *TSPEC would be
515   {   {
516   fmt = SIGNED_DECIMAL;   fmt = SIGNED_DECIMAL;
517   size = INT or LONG; (whichever integral_type_size[4] resolves to)   size = INT or LONG; (whichever integral_type_size[4] resolves to)
518   print_function = print_int; (assuming size == INT)   print_function = print_int; (assuming size == INT)
519     fmt_string = "%011d%c";   fmt_string = "%011d%c";
520   }   }
521     S_ORIG is solely for reporting errors.  It should be the full format     S_ORIG is solely for reporting errors.  It should be the full format
522     string argument. */     string argument. */
523    
524  static void  static const char *
525  decode_one_format(const char *s_orig, const char *s, const char **next,  decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
    struct tspec *tspec)  
526  {  {
527   enum size_spec size_spec;   enum size_spec size_spec;
528   unsigned size;   unsigned size;
# Line 562  decode_one_format(const char *s_orig, co Line 535  decode_one_format(const char *s_orig, co
535   unsigned field_width = 0;   unsigned field_width = 0;
536   int pos;   int pos;
537    
  assert(tspec != NULL);  
538    
539   switch (*s) {   switch (*s) {
540   case 'd':   case 'd':
541   case 'o':   case 'o':
542   case 'u':   case 'u':
543   case 'x': {   case 'x': {
544   static const char CSIL[] = "CSIL";   static const char CSIL[] ALIGN1 = "CSIL";
545    
546   c = *s++;   c = *s++;
547   p = strchr(CSIL, *s);   p = strchr(CSIL, *s);
# Line 588  decode_one_format(const char *s_orig, co Line 560  decode_one_format(const char *s_orig, co
560   s = end;   s = end;
561   }   }
562   } else {   } else {
563   static const uint8_t CSIL_sizeof[] = {   static const uint8_t CSIL_sizeof[4] = {
564   sizeof(char),   sizeof(char),
565   sizeof(short),   sizeof(short),
566   sizeof(int),   sizeof(int),
567   sizeof(long),   sizeof(long),
568   };   };
569   size = CSIL_sizeof[p - CSIL];   size = CSIL_sizeof[p - CSIL];
570     s++; /* skip C/S/I/L */
571   }   }
572    
573  #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \  #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
# Line 605  decode_one_format(const char *s_orig, co Line 578  decode_one_format(const char *s_orig, co
578   size_spec = integral_type_size[size];   size_spec = integral_type_size[size];
579    
580   {   {
581   static const char doux[] = "doux";   static const char doux[] ALIGN1 = "doux";
582   static const char doux_fmt_letter[][4] = {   static const char doux_fmt_letter[][4] = {
583   "lld", "llo", "llu", "llx"   "lld", "llo", "llu", "llx"
584   };   };
# Line 662  decode_one_format(const char *s_orig, co Line 635  decode_one_format(const char *s_orig, co
635   }   }
636    
637   case 'f': {   case 'f': {
638   static const char FDL[] = "FDL";   static const char FDL[] ALIGN1 = "FDL";
639    
640   fmt = FLOATING_POINT;   fmt = FLOATING_POINT;
641   ++s;   ++s;
# Line 742  decode_one_format(const char *s_orig, co Line 715  decode_one_format(const char *s_orig, co
715   if (tspec->hexl_mode_trailer)   if (tspec->hexl_mode_trailer)
716   s++;   s++;
717    
718   if (next != NULL)   return s;
  *next = s;  
719  }  }
720    
721  /* Decode the modern od format string S.  Append the decoded  /* Decode the modern od format string S.  Append the decoded
722     representation to the global array SPEC, reallocating SPEC if     representation to the global array SPEC, reallocating SPEC if
723     necessary.  Return zero if S is valid, nonzero otherwise.  */     necessary.  */
724    
725  static void  static void
726  decode_format_string(const char *s)  decode_format_string(const char *s)
# Line 759  decode_format_string(const char *s) Line 731  decode_format_string(const char *s)
731   struct tspec tspec;   struct tspec tspec;
732   const char *next;   const char *next;
733    
734   decode_one_format(s_orig, s, &next, &tspec);   next = decode_one_format(s_orig, s, &tspec);
735    
736   assert(s != next);   assert(s != next);
737   s = next;   s = next;
738     spec = xrealloc_vector(spec, 4, n_specs);
739     memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
740   n_specs++;   n_specs++;
  spec = xrealloc(spec, n_specs * sizeof(*spec));  
  memcpy(&spec[n_specs-1], &tspec, sizeof *spec);  
741   }   }
742  }  }
743    
# Line 801  skip(off_t n_skip) Line 773  skip(off_t n_skip)
773     as large as the size of the current file, we can     as large as the size of the current file, we can
774     decrement n_skip and go on to the next file.  */     decrement n_skip and go on to the next file.  */
775   if (fstat(fileno(in_stream), &file_stats) == 0   if (fstat(fileno(in_stream), &file_stats) == 0
776   && S_ISREG(file_stats.st_mode) && file_stats.st_size >= 0   && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
777   ) {   ) {
778   if (file_stats.st_size < n_skip) {   if (file_stats.st_size < n_skip) {
779   n_skip -= file_stats.st_size;   n_skip -= file_stats.st_size;
780   /* take check&close / open_next route */   /* take "check & close / open_next" route */
781   } else {   } else {
782   if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)   if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
783   ioerror = 1;   ioerror = 1;
784   return;   return;
785   }   }
786   } else {   } else {
787   /* If it's not a regular file with nonnegative size,   /* If it's not a regular file with positive size,
788     position the file pointer by reading.  */     position the file pointer by reading.  */
789   char buf[BUFSIZ];   char buf[1024];
790   size_t n_bytes_read, n_bytes_to_read = BUFSIZ;   size_t n_bytes_to_read = 1024;
791     size_t n_bytes_read;
792    
793   while (n_skip > 0) {   while (n_skip > 0) {
794   if (n_skip < n_bytes_to_read)   if (n_skip < n_bytes_to_read)
# Line 823  skip(off_t n_skip) Line 796  skip(off_t n_skip)
796   n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);   n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
797   n_skip -= n_bytes_read;   n_skip -= n_bytes_read;
798   if (n_bytes_read != n_bytes_to_read)   if (n_bytes_read != n_bytes_to_read)
799       break; /* EOF on this file or error */   break; /* EOF on this file or error */
800   }   }
801   }   }
802   if (n_skip == 0)   if (n_skip == 0)
# Line 841  skip(off_t n_skip) Line 814  skip(off_t n_skip)
814  typedef void FN_format_address(off_t address, char c);  typedef void FN_format_address(off_t address, char c);
815    
816  static void  static void
817  format_address_none(off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)  format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
818  {  {
819  }  }
820    
821  static char address_fmt[] = "%0n"OFF_FMT"xc";  static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
822  /* Corresponds to 'x' above */  /* Corresponds to 'x' above */
823  #define address_base_char address_fmt[sizeof(address_fmt)-3]  #define address_base_char address_fmt[sizeof(address_fmt)-3]
824  /* Corresponds to 'n' above */  /* Corresponds to 'n' above */
# Line 908  write_block(off_t current_offset, size_t Line 881  write_block(off_t current_offset, size_t
881   static char prev_pair_equal = 0;   static char prev_pair_equal = 0;
882   size_t i;   size_t i;
883    
884   if (abbreviate_duplicate_blocks   if (!verbose && !first
  && !first  
885   && n_bytes == bytes_per_block   && n_bytes == bytes_per_block
886   && memcmp(prev_block, curr_block, bytes_per_block) == 0   && memcmp(prev_block, curr_block, bytes_per_block) == 0
887   ) {   ) {
# Line 991  parse_old_offset(const char *s, off_t *o Line 963  parse_old_offset(const char *s, off_t *o
963   static const struct suffix_mult Bb[] = {   static const struct suffix_mult Bb[] = {
964   { "B", 1024 },   { "B", 1024 },
965   { "b", 512 },   { "b", 512 },
966   { NULL, 0 }   { }
967   };   };
968   char *p;   char *p;
969   int radix;   int radix;
# Line 1025  parse_old_offset(const char *s, off_t *o Line 997  parse_old_offset(const char *s, off_t *o
997     spec, extend the input block with zero bytes until its length is a     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,     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     write on a line by itself the offset of the byte after the last byte
1000     read.  Accumulate return values from calls to read_block and     read.  */
    check_and_close, and if any was nonzero, return nonzero.  
    Otherwise, return zero.  */  
1001    
1002  static void  static void
1003  dump(void)  dump(off_t current_offset, off_t end_offset)
1004  {  {
1005   char *block[2];   char *block[2];
  off_t current_offset;  
1006   int idx;   int idx;
1007   size_t n_bytes_read;   size_t n_bytes_read;
1008    
1009   block[0] = xmalloc(2*bytes_per_block);   block[0] = xmalloc(2*bytes_per_block);
1010   block[1] = block[0] + bytes_per_block;   block[1] = block[0] + bytes_per_block;
1011    
  current_offset = n_bytes_to_skip;  
   
1012   idx = 0;   idx = 0;
1013   if (limit_bytes_to_format) {   if (limit_bytes_to_format) {
1014   while (1) {   while (1) {
# Line 1106  dump(void) Line 1073  dump(void)
1073     and INPUT_FILENAME so they correspond to the next file in the list.     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     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     necessary until EOF is reached for the last file in FILE_LIST, then
1076     set *C to EOF and return.  Subsequent calls do likewise.  The return     set *C to EOF and return.  Subsequent calls do likewise.  */
    value is nonzero if any errors occured, zero otherwise.  */  
1077    
1078  static void  static void
1079  read_char(int *c)  read_char(int *c)
# Line 1140  read_char(int *c) Line 1106  read_char(int *c)
1106     A string constant is a run of at least 'string_min' ASCII     A string constant is a run of at least 'string_min' ASCII
1107     graphic (or formatting) characters terminated by a null.     graphic (or formatting) characters terminated by a null.
1108     Based on a function written by Richard Stallman for a     Based on a function written by Richard Stallman for a
1109     traditional version of od.  Return nonzero if an error     traditional version of od.  */
    occurs.  Otherwise, return zero.  */  
1110    
1111  static void  static void
1112  dump_strings(void)  dump_strings(off_t address, off_t end_offset)
1113  {  {
1114   size_t bufsize = MAX(100, string_min);   size_t bufsize = MAX(100, string_min);
1115   char *buf = xmalloc(bufsize);   char *buf = xmalloc(bufsize);
  off_t address = n_bytes_to_skip;  
1116    
1117   while (1) {   while (1) {
1118   size_t i;   size_t i;
# Line 1180  dump_strings(void) Line 1144  dump_strings(void)
1144   if (i < string_min) /* Too short! */   if (i < string_min) /* Too short! */
1145   goto tryline;   goto tryline;
1146    
1147   /* If we get here, the string is all printable and null-terminated,   /* If we get here, the string is all printable and NUL-terminated,
1148   * so print it.  It is all in 'buf' and 'i' is its length.  */   * so print it.  It is all in 'buf' and 'i' is its length.  */
1149   buf[i] = 0;   buf[i] = 0;
1150   format_address(address - i - 1, ' ');   format_address(address - i - 1, ' ');
# Line 1194  dump_strings(void) Line 1158  dump_strings(void)
1158   case '\r': fputs("\\r", stdout); break;   case '\r': fputs("\\r", stdout); break;
1159   case '\t': fputs("\\t", stdout); break;   case '\t': fputs("\\t", stdout); break;
1160   case '\v': fputs("\\v", stdout); break;   case '\v': fputs("\\v", stdout); break;
1161   default: putc(c, stdout);   default: putchar(c);
1162   }   }
1163   }   }
1164   putchar('\n');   putchar('\n');
# Line 1207  dump_strings(void) Line 1171  dump_strings(void)
1171   check_and_close();   check_and_close();
1172  }  }
1173    
1174  int  int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1175  od_main(int argc, char **argv)  int od_main(int argc, char **argv)
1176  {  {
1177   static const struct suffix_mult bkm[] = {   static const struct suffix_mult bkm[] = {
1178   { "b", 512 },   { "b", 512 },
1179   { "k", 1024 },   { "k", 1024 },
1180   { "m", 1024*1024 },   { "m", 1024*1024 },
1181   { NULL, 0 }   { }
1182   };   };
  unsigned opt;  
  int l_c_m;  
  /* The old-style 'pseudo starting address' to be printed in parentheses  
    after any true address.  */  
  off_t pseudo_start = 0; // only for gcc  
1183   enum {   enum {
1184   OPT_A = 1 << 0,   OPT_A = 1 << 0,
1185   OPT_N = 1 << 1,   OPT_N = 1 << 1,
# Line 1243  od_main(int argc, char **argv) Line 1202  od_main(int argc, char **argv)
1202   OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,   OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
1203   };   };
1204  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
1205   static const struct option long_options[] = {   static const char od_longopts[] ALIGN1 =
1206   { "skip-bytes",    required_argument, NULL, 'j' },   "skip-bytes\0"        Required_argument "j"
1207   { "address-radix", required_argument, NULL, 'A' },   "address-radix\0"     Required_argument "A"
1208   { "read-bytes",    required_argument, NULL, 'N' },   "read-bytes\0"        Required_argument "N"
1209   { "format",        required_argument, NULL, 't' },   "format\0"            Required_argument "t"
1210   { "output-duplicates", no_argument,   NULL, 'v' },   "output-duplicates\0" No_argument       "v"
1211   { "strings",       optional_argument, NULL, 'S' },   "strings\0"           Optional_argument "S"
1212   { "width",         optional_argument, NULL, 'w' },   "width\0"             Optional_argument "w"
1213   { "traditional",   no_argument,       NULL, 0xff },   "traditional\0"       No_argument       "\xff"
1214   { NULL, 0, NULL, 0 }   ;
  };  
1215  #endif  #endif
1216   char *str_A, *str_N, *str_j, *str_S;   char *str_A, *str_N, *str_j, *str_S;
  char *str_w = NULL;  
1217   llist_t *lst_t = NULL;   llist_t *lst_t = NULL;
1218     unsigned opt;
1219     int l_c_m;
1220     /* The old-style 'pseudo starting address' to be printed in parentheses
1221       after any true address.  */
1222     off_t pseudo_start = 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    
1230   spec = NULL;   spec = NULL;
1231   format_address = format_address_std;   format_address = format_address_std;
1232   address_base_char = 'o';   address_base_char = 'o';
1233   address_pad_len_char = '7';   address_pad_len_char = '7';
1234   flag_dump_strings = 0;   /* flag_dump_strings = 0; - already is */
1235    
1236   /* Parse command line */   /* Parse command line */
1237   opt_complementary = "t::"; // list   opt_complementary = "w+:t::"; /* -w N, -t is a list */
1238  #if ENABLE_GETOPT_LONG  #if ENABLE_GETOPT_LONG
1239   applet_long_options = long_options;   applet_long_options = od_longopts;
1240  #endif  #endif
1241   opt = getopt32(argc, argv, "A:N:abcdfhij:lot:vxsS:"   opt = getopt32(argv, "A:N:abcdfhij:lot:vxsS:"
1242   "w::", // -w with optional param   "w::", // -w with optional param
1243   // -S was -s and also had optional parameter   // -S was -s and also had optional parameter
1244   // but in coreutils 6.3 it was renamed and now has   // but in coreutils 6.3 it was renamed and now has
1245   // _mandatory_ parameter   // _mandatory_ parameter
1246   &str_A, &str_N, &str_j, &lst_t, &str_S, &str_w);   &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block);
1247   argc -= optind;   argc -= optind;
1248   argv += optind;   argv += optind;
1249   if (opt & OPT_A) {   if (opt & OPT_A) {
1250   static const char doxn[] = "doxn";   static const char doxn[] ALIGN1 = "doxn";
1251   static const char doxn_address_base_char[] = {   static const char doxn_address_base_char[] ALIGN1 = {
1252   'u', 'o', 'x', /* '?' fourth one is not important */   'u', 'o', 'x', /* '?' fourth one is not important */
1253   };   };
1254   static const uint8_t doxn_address_pad_len_char[] = {   static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1255   '7', '7', '6', /* '?' */   '7', '7', '6', /* '?' */
1256   };   };
1257   char *p;   char *p;
# Line 1312  od_main(int argc, char **argv) Line 1280  od_main(int argc, char **argv)
1280   if (opt & OPT_l) decode_format_string("d4");   if (opt & OPT_l) decode_format_string("d4");
1281   if (opt & OPT_o) decode_format_string("o2");   if (opt & OPT_o) decode_format_string("o2");
1282   //if (opt & OPT_t)...   //if (opt & OPT_t)...
  lst_t = rev_llist(lst_t);  
1283   while (lst_t) {   while (lst_t) {
1284   decode_format_string(lst_t->data);   decode_format_string(llist_pop(&lst_t));
  lst_t = lst_t->link;  
1285   }   }
1286   if (opt & OPT_v) abbreviate_duplicate_blocks = 0;   if (opt & OPT_v) verbose = 1;
1287   if (opt & OPT_x) decode_format_string("x2");   if (opt & OPT_x) decode_format_string("x2");
1288   if (opt & OPT_s) decode_format_string("d2");   if (opt & OPT_s) decode_format_string("d2");
1289   if (opt & OPT_S) {   if (opt & OPT_S) {
# Line 1334  od_main(int argc, char **argv) Line 1300  od_main(int argc, char **argv)
1300   /* If the --traditional option is used, there may be from   /* If the --traditional option is used, there may be from
1301   * 0 to 3 remaining command line arguments;  handle each case   * 0 to 3 remaining command line arguments;  handle each case
1302   * separately.   * separately.
1303   * od [file] [[+]offset[.][b] [[+]label[.][b]]]   * od [file] [[+]offset[.][b] [[+]label[.][b]]]
1304   * The offset and pseudo_start have the same syntax.   * The offset and pseudo_start have the same syntax.
1305   *   *
1306   * FIXME: POSIX 1003.1-2001 with XSI requires support for the   * FIXME: POSIX 1003.1-2001 with XSI requires support for the
# Line 1412  od_main(int argc, char **argv) Line 1378  od_main(int argc, char **argv)
1378   /* If no files were listed on the command line,   /* If no files were listed on the command line,
1379     set the global pointer FILE_LIST so that it     set the global pointer FILE_LIST so that it
1380     references the null-terminated list of one name: "-".  */     references the null-terminated list of one name: "-".  */
1381   file_list = default_file_list;   file_list = bb_argv_dash;
1382   if (argc > 0) {   if (argc > 0) {
1383   /* Set the global pointer FILE_LIST so that it   /* Set the global pointer FILE_LIST so that it
1384     references the first file-argument on the command-line.  */     references the first file-argument on the command-line.  */
# Line 1424  od_main(int argc, char **argv) Line 1390  od_main(int argc, char **argv)
1390   /* skip over any unwanted header bytes */   /* skip over any unwanted header bytes */
1391   skip(n_bytes_to_skip);   skip(n_bytes_to_skip);
1392   if (!in_stream)   if (!in_stream)
1393   return 1;   return EXIT_FAILURE;
1394    
1395   pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);   pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1396    
# Line 1432  od_main(int argc, char **argv) Line 1398  od_main(int argc, char **argv)
1398   l_c_m = get_lcm();   l_c_m = get_lcm();
1399    
1400   if (opt & OPT_w) { /* -w: width */   if (opt & OPT_w) { /* -w: width */
  bytes_per_block = 32;  
  if (str_w)  
  bytes_per_block = xatou(str_w);  
1401   if (!bytes_per_block || bytes_per_block % l_c_m != 0) {   if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1402   bb_error_msg("warning: invalid width %zu; using %d instead",   bb_error_msg("warning: invalid width %u; using %d instead",
1403   bytes_per_block, l_c_m);   (unsigned)bytes_per_block, l_c_m);
1404   bytes_per_block = l_c_m;   bytes_per_block = l_c_m;
1405   }   }
1406   } else {   } else {
# Line 1454  od_main(int argc, char **argv) Line 1417  od_main(int argc, char **argv)
1417  #endif  #endif
1418    
1419   if (flag_dump_strings)   if (flag_dump_strings)
1420   dump_strings();   dump_strings(n_bytes_to_skip, end_offset);
1421   else   else
1422   dump();   dump(n_bytes_to_skip, end_offset);
1423    
1424   if (fclose(stdin) == EOF)   if (fclose(stdin) == EOF)
1425   bb_perror_msg_and_die(bb_msg_standard_input);   bb_perror_msg_and_die(bb_msg_standard_input);
1426    
1427   return (ioerror != 0); /* err != 0 - return 1 (failure) */   return ioerror;
1428  }  }

Legend:
Removed from v.532  
changed lines
  Added in v.816