diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-06 07:46:43 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-06 07:46:43 +0000 |
commit | 286260ca557f70be9a0e96be1fd7fa94abda82a1 (patch) | |
tree | 5f19718f35a34d2a77c8bb7ce320e615c99b0661 /src | |
parent | b05c150fed44d0f8d8843ceaa2b696147b886287 (diff) | |
download | coreutils-286260ca557f70be9a0e96be1fd7fa94abda82a1.tar.xz |
Several changes for POSIX and FreeBSD compatibility.
(COMMON_SHORT_OPTIONS): Add -B, -D, -e, -F, -H, -I, -L, -O, -s, -X.
(long_options, main): --strings is now -S, not -s.
(usage): Reflect the usage changes.
(parse_old_offset): Do not issue a diagnostic on failure;
callers now do this as necessary.
(main): Support POSIX syntax. Remove unused case 0 from getopt_long.
Add support for new short options (many undocumented) for
compatibility with FreeBSD. Remove FIXME for -s; it's now
POSIX-compatible. Default format is now oS, not o2.
Diffstat (limited to 'src')
-rw-r--r-- | src/od.c | 210 |
1 files changed, 102 insertions, 108 deletions
@@ -265,7 +265,7 @@ static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1]; #define MAX_FP_TYPE_SIZE sizeof (LONG_DOUBLE) static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1]; -#define COMMON_SHORT_OPTIONS "A:N:abcdfhij:lot:vx" +#define COMMON_SHORT_OPTIONS "A:aBbcDdeFfHhIij:LlN:OoS:st:vXx" /* For long options that have no equivalent short option, use a non-character as a pseudo short option, starting with CHAR_MAX + 1. */ @@ -281,7 +281,7 @@ static struct option const long_options[] = {"read-bytes", required_argument, NULL, 'N'}, {"format", required_argument, NULL, 't'}, {"output-duplicates", no_argument, NULL, 'v'}, - {"strings", optional_argument, NULL, 's'}, + {"strings", optional_argument, NULL, 'S'}, {"traditional", no_argument, NULL, TRADITIONAL_OPTION}, {"width", optional_argument, NULL, 'w'}, @@ -300,9 +300,10 @@ usage (int status) { printf (_("\ Usage: %s [OPTION]... [FILE]...\n\ - or: %s --traditional [FILE] [[+]OFFSET [[+]LABEL]]\n\ + or: %s [-abcdfilosx]... [FILE] [[+]OFFSET[.][b]]\n\ + or: %s --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]\n\ "), - program_name, program_name); + program_name, program_name, program_name); fputs (_("\n\ Write an unambiguous representation, octal bytes by default,\n\ of FILE to standard output. With more than one FILE argument,\n\ @@ -319,7 +320,7 @@ All arguments to long options are mandatory for short options.\n\ "), stdout); fputs (_("\ -N, --read-bytes=BYTES limit dump to BYTES input bytes\n\ - -s, --strings[=BYTES] output strings of at least BYTES graphic chars\n\ + -S, --strings[=BYTES] output strings of at least BYTES graphic chars\n\ -t, --format=TYPE select output format or formats\n\ -v, --output-duplicates do not use * to mark line suppression\n\ -w, --width[=BYTES] output BYTES bytes per output line\n\ @@ -331,24 +332,26 @@ All arguments to long options are mandatory for short options.\n\ \n\ Traditional format specifications may be intermixed; they accumulate:\n\ -a same as -t a, select named characters\n\ - -b same as -t oC, select octal bytes\n\ + -b same as -t o1, select octal bytes\n\ -c same as -t c, select ASCII characters or backslash escapes\n\ - -d same as -t u2, select unsigned decimal shorts\n\ + -d same as -t u2, select unsigned decimal 2-byte units\n\ "), stdout); fputs (_("\ -f same as -t fF, select floats\n\ - -h same as -t x2, select hexadecimal shorts\n\ - -i same as -t d2, select decimal shorts\n\ - -l same as -t d4, select decimal longs\n\ - -o same as -t o2, select octal shorts\n\ - -x same as -t x2, select hexadecimal shorts\n\ + -i same as -t dI, select decimal ints\n\ + -l same as -t dL, select decimal longs\n\ + -o same as -t o2, select octal 2-byte units\n\ + -s same as -t d2, select decimal 2-byte units\n\ + -x same as -t x2, select hexadecimal 2-byte units\n\ "), stdout); fputs (_("\ \n\ -For older syntax (second call format), OFFSET means -j OFFSET. LABEL\n\ -is the pseudo-address at first byte printed, incremented when dump is\n\ -progressing. For OFFSET and LABEL, a 0x or 0X prefix indicates\n\ -hexadecimal, suffixes may be . for octal and b for multiply by 512.\n\ +If first and second call formats both apply, the second format is assumed\n\ +if the last operand begins with + or (if there are 2 operands) a digit.\n\ +An OFFSET operand means -j OFFSET. LABEL is the pseudo-address\n\ +at first byte printed, incremented when dump is progressing.\n\ +For OFFSET and LABEL, a 0x or 0X prefix indicates hexadecimal;\n\ +suffixes may be . for octal and b for multiply by 512.\n\ \n\ TYPE is made up of one or more of these specifications:\n\ \n\ @@ -1308,7 +1311,6 @@ static bool parse_old_offset (const char *s, uintmax_t *offset) { int radix; - enum strtol_error s_err; if (*s == '\0') return false; @@ -1330,13 +1332,7 @@ parse_old_offset (const char *s, uintmax_t *offset) radix = 8; } - s_err = xstrtoumax (s, NULL, radix, offset, "Bb"); - if (s_err != LONGINT_OK) - { - STRTOL_FAIL_WARN (s, _("old-style offset"), s_err); - return false; - } - return true; + return xstrtoumax (s, NULL, radix, offset, "Bb") == LONGINT_OK; } /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the @@ -1553,11 +1549,12 @@ main (int argc, char **argv) size_t i; int l_c_m; size_t desired_width IF_LINT (= 0); + bool modern = false; bool width_specified = false; bool ok = true; char const *short_options = (posix2_version () < 200112 - ? COMMON_SHORT_OPTIONS "s::w::" - : COMMON_SHORT_OPTIONS "s:w:"); + ? COMMON_SHORT_OPTIONS "w::" + : COMMON_SHORT_OPTIONS "w:"); /* The old-style `pseudo starting address' to be printed in parentheses after any true address. */ @@ -1611,10 +1608,8 @@ main (int argc, char **argv) switch (c) { - case 0: - break; - case 'A': + modern = true; switch (optarg[0]) { case 'd': @@ -1646,12 +1641,14 @@ it must be one character from [doxn]"), break; case 'j': + modern = true; s_err = xstrtoumax (optarg, NULL, 0, &n_bytes_to_skip, "bkm"); if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("skip argument"), s_err); break; case 'N': + modern = true; limit_bytes_to_format = true; s_err = xstrtoumax (optarg, NULL, 0, &max_bytes_to_format, "bkm"); @@ -1659,7 +1656,8 @@ it must be one character from [doxn]"), STRTOL_FATAL_ERROR (optarg, _("limit argument"), s_err); break; - case 's': + case 'S': + modern = true; if (optarg == NULL) string_min = 3; else @@ -1679,10 +1677,12 @@ it must be one character from [doxn]"), break; case 't': + modern = true; ok &= decode_format_string (optarg); break; case 'v': + modern = true; abbreviate_duplicate_blocks = false; break; @@ -1693,7 +1693,9 @@ it must be one character from [doxn]"), /* The next several cases map the traditional format specification options to the corresponding modern format specs. GNU od accepts any combination of old- and - new-style options. Format specification options accumulate. */ + new-style options. Format specification options accumulate. + The obsolescent and undocumented formats are compatible + with FreeBSD 4.10 od. */ #define CASE_OLD_ARG(old_char,new_string) \ case old_char: \ @@ -1701,26 +1703,29 @@ it must be one character from [doxn]"), break CASE_OLD_ARG ('a', "a"); - CASE_OLD_ARG ('b', "oC"); + CASE_OLD_ARG ('b', "o1"); CASE_OLD_ARG ('c', "c"); + CASE_OLD_ARG ('D', "u4"); /* obsolescent and undocumented */ CASE_OLD_ARG ('d', "u2"); + case 'F': /* obsolescent and undocumented alias */ + CASE_OLD_ARG ('e', "fD"); /* obsolescent and undocumented */ CASE_OLD_ARG ('f', "fF"); - CASE_OLD_ARG ('h', "x2"); - CASE_OLD_ARG ('i', "d2"); - CASE_OLD_ARG ('l', "d4"); + case 'X': /* obsolescent and undocumented alias */ + CASE_OLD_ARG ('H', "x4"); /* obsolescent and undocumented */ + CASE_OLD_ARG ('i', "dI"); + case 'I': case 'L': /* obsolescent and undocumented aliases */ + CASE_OLD_ARG ('l', "dL"); + CASE_OLD_ARG ('O', "o4"); /* obsolesent and undocumented */ + case 'B': /* obsolescent and undocumented alias */ CASE_OLD_ARG ('o', "o2"); + CASE_OLD_ARG ('s', "d2"); + case 'h': /* obsolescent and undocumented alias */ CASE_OLD_ARG ('x', "x2"); - /* FIXME: POSIX 1003.1-2001 with XSI requires this: - - CASE_OLD_ARG ('s', "d2"); - - for the traditional syntax, but this conflicts with case - 's' above. */ - #undef CASE_OLD_ARG case 'w': + modern = true; width_specified = true; if (optarg == NULL) { @@ -1761,55 +1766,57 @@ it must be one character from [doxn]"), 0 to 3 remaining command line arguments; handle each case separately. od [file] [[+]offset[.][b] [[+]label[.][b]]] - The offset and pseudo_start have the same syntax. + The offset and label have the same syntax. - FIXME: POSIX 1003.1-2001 with XSI requires support for the - traditional syntax even if --traditional is not given. */ + If --traditional is not given, and if no modern options are + given, and if the offset begins with + or (if there are two + operands) a digit, accept only this form, as per POSIX: + od [file] [[+]offset[.][b]] + */ - if (traditional) + if (!modern | traditional) { - uintmax_t offset; + uintmax_t o1; + uintmax_t o2; - if (n_files == 1) + switch (n_files) { - if (parse_old_offset (argv[optind], &offset)) - { - n_bytes_to_skip = offset; - --n_files; - ++argv; - } - } - else if (n_files == 2) - { - uintmax_t o1, o2; - if (parse_old_offset (argv[optind], &o1) - && parse_old_offset (argv[optind + 1], &o2)) + case 1: + if ((traditional || argv[optind][0] == '+') + && parse_old_offset (argv[optind], &o1)) { n_bytes_to_skip = o1; - flag_pseudo_start = true; - pseudo_start = o2; - argv += 2; - n_files -= 2; - } - else if (parse_old_offset (argv[optind + 1], &o2)) - { - n_bytes_to_skip = o2; --n_files; - argv[optind + 1] = argv[optind]; ++argv; } - else + break; + + case 2: + if ((traditional || argv[optind + 1][0] == '+' + || ISDIGIT (argv[optind + 1][0])) + && parse_old_offset (argv[optind + 1], &o2)) { - error (0, 0, - _("invalid second operand in compatibility mode `%s'"), - argv[optind + 1]); - usage (EXIT_FAILURE); + if (traditional && parse_old_offset (argv[optind], &o1)) + { + n_bytes_to_skip = o1; + flag_pseudo_start = true; + pseudo_start = o2; + argv += 2; + n_files -= 2; + } + else + { + n_bytes_to_skip = o2; + --n_files; + argv[optind + 1] = argv[optind]; + ++argv; + } } - } - else if (n_files == 3) - { - uintmax_t o1, o2; - if (parse_old_offset (argv[optind + 1], &o1) + break; + + case 3: + if (traditional + && parse_old_offset (argv[optind + 1], &o1) && parse_old_offset (argv[optind + 2], &o2)) { n_bytes_to_skip = o1; @@ -1819,32 +1826,28 @@ it must be one character from [doxn]"), argv += 2; n_files -= 2; } - else - { - error (0, 0, - _("in compatibility mode, the last two arguments must be offsets")); - usage (EXIT_FAILURE); - } + break; } - else if (n_files > 3) + + if (traditional && 1 < n_files) { - error (0, 0, _("extra operand %s"), quote (argv[optind + 3])); - fprintf (stderr, "%s\n", - _("Compatibility mode supports at most three operands.")); + error (0, 0, _("extra operand %s"), quote (argv[optind + 1])); + error (0, 0, "%s\n", + _("Compatibility mode supports at most one file.")); usage (EXIT_FAILURE); } + } - if (flag_pseudo_start) + if (flag_pseudo_start) + { + if (format_address == format_address_none) { - if (format_address == format_address_none) - { - address_base = 8; - address_pad_len = 7; - format_address = format_address_paren; - } - else - format_address = format_address_label; + address_base = 8; + address_pad_len = 7; + format_address = format_address_paren; } + else + format_address = format_address_label; } if (limit_bytes_to_format) @@ -1855,16 +1858,7 @@ it must be one character from [doxn]"), } if (n_specs == 0) - { - if (! decode_format_string ("o2")) - { - /* This happens on Cray systems that don't have a 2-byte - integral type. */ - exit (EXIT_FAILURE); - } - - n_specs = 1; - } + decode_format_string ("oS"); if (n_files > 0) { |