rework long option handling. saves ~1.2k
[oweals/busybox.git] / coreutils / od_bloaty.c
index dff7e3f50ee8c909d7798faeec5868ba2aa6712f..335efe7ca93a3ea7bad9d2e1fd1e8c535b25a4bd 100644 (file)
@@ -49,8 +49,7 @@ diff -u -a std bbox >bbox.diff || { echo Different!; sleep 1; }
 
 */
 
-
-#include "busybox.h"
+#include "libbb.h"
 #include <getopt.h>
 
 #define assert(a) ((void)0)
@@ -159,7 +158,7 @@ static const signed char width_bytes[] = {
    initializer in the width_bytes array.  */
 struct dummy {
        int assert_width_bytes_matches_size_spec_decl
-               [sizeof width_bytes / sizeof width_bytes[0] == N_SIZE_SPECS ? 1 : -1];
+               [ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
 };
 
 static size_t string_min;
@@ -490,7 +489,7 @@ print_ascii(size_t n_bytes, const char *block,
 static void
 open_next_file(void)
 {
-       while(1) {
+       while (1) {
                input_filename = *file_list;
                if (!input_filename)
                        return;
@@ -542,7 +541,7 @@ check_and_close(void)
                fmt = SIGNED_DECIMAL;
                size = INT or LONG; (whichever integral_type_size[4] resolves to)
                print_function = print_int; (assuming size == INT)
-               fmt_string = "%011d%c";
+               fmt_string = "%011d%c";
        }
    S_ORIG is solely for reporting errors.  It should be the full format
    string argument. */
@@ -823,7 +822,7 @@ skip(off_t n_skip)
                                n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
                                n_skip -= n_bytes_read;
                                if (n_bytes_read != n_bytes_to_read)
-                                       break; /* EOF on this file or error */
+                                       break; /* EOF on this file or error */
                        }
                }
                if (n_skip == 0)
@@ -845,25 +844,28 @@ format_address_none(off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
 {
 }
 
-static int address_pad_len;
-static char address_fmt[] = "%0*"OFF_FMT"xc";
+static char address_fmt[] = "%0n"OFF_FMT"xc";
 /* Corresponds to 'x' above */
 #define address_base_char address_fmt[sizeof(address_fmt)-3]
+/* Corresponds to 'n' above */
+#define address_pad_len_char address_fmt[2]
 
 static void
 format_address_std(off_t address, char c)
 {
        /* Corresponds to 'c' */
        address_fmt[sizeof(address_fmt)-2] = c;
-       printf(address_fmt, address_pad_len, address);
+       printf(address_fmt, address);
 }
 
+#if ENABLE_GETOPT_LONG
+/* only used with --traditional */
 static void
 format_address_paren(off_t address, char c)
 {
        putchar('(');
        format_address_std(address, ')');
-       putchar(c);
+       if (c) putchar(c);
 }
 
 static void
@@ -872,7 +874,7 @@ format_address_label(off_t address, char c)
        format_address_std(address, ' ');
        format_address_paren(address + pseudo_offset, c);
 }
-
+#endif
 
 static void
 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
@@ -924,7 +926,7 @@ write_block(off_t current_offset, size_t n_bytes,
                        if (i == 0)
                                format_address(current_offset, '\0');
                        else
-                               printf("%*s", address_pad_len, "");
+                               printf("%*s", address_pad_len_char - '0', "");
                        (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
                        if (spec[i].hexl_mode_trailer) {
                                /* space-pad out to full line width, then dump the trailer */
@@ -978,6 +980,7 @@ get_lcm(void)
        return l_c_m;
 }
 
+#if ENABLE_GETOPT_LONG
 /* If S is a valid traditional offset specification with an optional
    leading '+' return nonzero and set *OFFSET to the offset it denotes.  */
 
@@ -1011,6 +1014,7 @@ parse_old_offset(const char *s, off_t *offset)
 
        return (*offset >= 0);
 }
+#endif
 
 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
    formatted block to standard output, and repeat until the specified
@@ -1202,8 +1206,8 @@ dump_strings(void)
        check_and_close();
 }
 
-int
-od_main(int argc, char **argv)
+int od_main(int argc, char **argv);
+int od_main(int argc, char **argv)
 {
        static const struct suffix_mult bkm[] = {
                { "b", 512 },
@@ -1235,19 +1239,20 @@ od_main(int argc, char **argv)
                OPT_s = 1 << 15,
                OPT_S = 1 << 16,
                OPT_w = 1 << 17,
-               OPT_traditional = 1 << 18,
-       };
-       static const struct option long_options[] = {
-               { "skip-bytes",    required_argument, NULL, 'j' },
-               { "address-radix", required_argument, NULL, 'A' },
-               { "read-bytes",    required_argument, NULL, 'N' },
-               { "format",        required_argument, NULL, 't' },
-               { "output-duplicates", no_argument,   NULL, 'v' },
-               { "strings",       optional_argument, NULL, 'S' },
-               { "width",         optional_argument, NULL, 'w' },
-               { "traditional",   no_argument,       NULL, 0xff },
-               { NULL, 0, NULL, 0 }
+               OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
        };
+#if ENABLE_GETOPT_LONG
+       static const char od_longopts[] =
+               "skip-bytes\0"        Required_argument "j"
+               "address-radix\0"     Required_argument "A"
+               "read-bytes\0"        Required_argument "N"
+               "format\0"            Required_argument "t"
+               "output-duplicates\0" No_argument       "v"
+               "strings\0"           Optional_argument "S"
+               "width\0"             Optional_argument "w"
+               "traditional\0"       No_argument       "\xff"
+               "\0";
+#endif
        char *str_A, *str_N, *str_j, *str_S;
        char *str_w = NULL;
        llist_t *lst_t = NULL;
@@ -1255,12 +1260,14 @@ od_main(int argc, char **argv)
        spec = NULL;
        format_address = format_address_std;
        address_base_char = 'o';
-       address_pad_len = 7;
+       address_pad_len_char = '7';
        flag_dump_strings = 0;
 
        /* Parse command line */
        opt_complementary = "t::"; // list
-       applet_long_options = long_options;
+#if ENABLE_GETOPT_LONG
+       applet_long_options = od_longopts;
+#endif
        opt = getopt32(argc, argv, "A:N:abcdfhij:lot:vxsS:"
                "w::", // -w with optional param
                // -S was -s and also had optional parameter
@@ -1271,14 +1278,12 @@ od_main(int argc, char **argv)
        argv += optind;
        if (opt & OPT_A) {
                static const char doxn[] = "doxn";
-               static FN_format_address *const doxn_format_address[] = {
-                       format_address_std,
-                       format_address_std,
-                       format_address_std,
-                       format_address_none,
+               static const char doxn_address_base_char[] = {
+                       'u', 'o', 'x', /* '?' fourth one is not important */
+               };
+               static const uint8_t doxn_address_pad_len_char[] = {
+                       '7', '7', '6', /* '?' */
                };
-               static const char doxn_address_base_char[] = { 'u', 'o', 'x', 'x' };
-               static const uint8_t doxn_address_pad_len[] = { 7, 7, 6, 0 };
                char *p;
                int pos;
                p = strchr(doxn, str_A[0]);
@@ -1286,9 +1291,9 @@ od_main(int argc, char **argv)
                        bb_error_msg_and_die("bad output address radix "
                                "'%c' (must be [doxn])", str_A[0]);
                pos = p - doxn;
-               format_address = doxn_format_address[pos];
+               if (pos == 3) format_address = format_address_none;
                address_base_char = doxn_address_base_char[pos];
-               address_pad_len = doxn_address_pad_len[pos];
+               address_pad_len_char = doxn_address_pad_len_char[pos];
        }
        if (opt & OPT_N) {
                limit_bytes_to_format = 1;
@@ -1305,7 +1310,6 @@ od_main(int argc, char **argv)
        if (opt & OPT_l) decode_format_string("d4");
        if (opt & OPT_o) decode_format_string("o2");
        //if (opt & OPT_t)...
-       lst_t = rev_llist(lst_t);
        while (lst_t) {
                decode_format_string(lst_t->data);
                lst_t = lst_t->link;
@@ -1327,12 +1331,13 @@ od_main(int argc, char **argv)
        /* If the --traditional option is used, there may be from
         * 0 to 3 remaining command line arguments;  handle each case
         * separately.
-        *      od [file] [[+]offset[.][b] [[+]label[.][b]]]
+        * od [file] [[+]offset[.][b] [[+]label[.][b]]]
         * The offset and pseudo_start have the same syntax.
         *
         * FIXME: POSIX 1003.1-2001 with XSI requires support for the
         * traditional syntax even if --traditional is not given.  */
 
+#if ENABLE_GETOPT_LONG
        if (opt & OPT_traditional) {
                off_t o1, o2;
 
@@ -1380,14 +1385,15 @@ od_main(int argc, char **argv)
                }
 
                if (flag_pseudo_start) {
-                       format_address = format_address_label;
                        if (format_address == format_address_none) {
                                address_base_char = 'o';
-                               address_pad_len = 7;
+                               address_pad_len_char = '7';
                                format_address = format_address_paren;
-                       }
+                       } else
+                               format_address = format_address_label;
                }
        }
+#endif
 
        if (limit_bytes_to_format) {
                end_offset = n_bytes_to_skip + max_bytes_to_format;
@@ -1427,7 +1433,7 @@ od_main(int argc, char **argv)
                if (str_w)
                        bytes_per_block = xatou(str_w);
                if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
-                       bb_error_msg("warning: invalid width %u; using %d instead",
+                       bb_error_msg("warning: invalid width %zu; using %d instead",
                                        bytes_per_block, l_c_m);
                        bytes_per_block = l_c_m;
                }