diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-10 20:54:08 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-10 20:54:08 +0000 |
commit | 160d311c8be7efe720a711953c320ead4a7c76ce (patch) | |
tree | 5eed740fa58c057b8b4ae2a3986cb31a3ba26a7b /src | |
parent | e21fadd7aa2c02e14f5b2804250202d4f0965509 (diff) | |
download | coreutils-160d311c8be7efe720a711953c320ead4a7c76ce.tar.xz |
(parse_obsolete_option): Renamed from
parse_obsolescent_option, since the options are obsolete now.
Remove bool *arg; just exit if there's an error. Revamp to follow
POSIX 1003.2-1992 more precisely, to handle cases like "tail -
file" and "tail -10 -- file" correctly when we are conforming to
the older standard.
(main): Adjust to this change.
Diffstat (limited to 'src')
-rw-r--r-- | src/tail.c | 192 |
1 files changed, 70 insertions, 122 deletions
diff --git a/src/tail.c b/src/tail.c index ff7cc553c..53ea0dd59 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1359,147 +1359,107 @@ tail_file (struct File_spec *f, uintmax_t n_units) return ok; } -/* If the command line arguments are of the obsolescent form and the - option string is well-formed, set *OK to true, set *N_UNITS, the - globals COUNT_LINES, FOREVER, and FROM_START, and return true. - Otherwise, if the command line arguments appear to be of the - obsolescent form but the option string is malformed, set *OK to - false, don't modify any other parameter or global variable, and - return true. Otherwise, return false and don't modify any parameter - or global variable. */ +/* If obsolete usage is allowed, and the command line arguments are of + the obsolete form and the option string is well-formed, set + *N_UNITS, the globals COUNT_LINES, FOREVER, and FROM_START, and + return true. If the command line arguments are obviously incorrect + (e.g., because obsolete usage is not allowed and the arguments are + incorrect for non-obsolete usage), report an error and exit. + Otherwise, return false and don't modify any parameter or global + variable. */ static bool -parse_obsolescent_option (int argc, const char *const *argv, - uintmax_t *n_units, bool *ok) +parse_obsolete_option (int argc, char * const *argv, uintmax_t *n_units) { const char *p = argv[1]; - const char *n_string = NULL; + const char *n_string; const char *n_string_end; bool obsolete_usage; - bool t_from_start; - bool t_count_lines; - bool t_forever; + bool t_count_lines = true; + bool t_forever = false; + int len; - /* With the obsolescent form, there is one option string and - (technically) at most one file argument. But we allow two or more - by default. */ - if (argc < 2) + /* With the obsolete form, there is one option string and + at most one file argument, possibly preceded by "--". */ + if (! ((2 <= argc && argc <= 3) || (argc == 4 && STREQ (argv[2], "--")))) return false; obsolete_usage = (posix2_version () < 200112); - /* If P starts with `+' and the POSIX version predates 1003.1-2001, - or if P starts with `-N' (where N is a digit), or `-l', then it - is obsolescent. Return false otherwise. */ - if (! ((p[0] == '+' && obsolete_usage) - || (p[0] == '-' && (p[1] == 'l' || ISDIGIT (p[1]))))) - return false; + switch (*p++) + { + default: + return false; - if (*p == '+') - t_from_start = true; - else if (*p == '-') - t_from_start = false; - else - return false; + case '+': + /* Leading "+" is a file name in the non-obsolete form. */ + if (!obsolete_usage) + return false; - ++p; - if (ISDIGIT (*p)) - { - n_string = p; - do - { - ++p; - } - while (ISDIGIT (*p)); + t_from_start = true; + break; + + case '-': + /* Plain "-" is standard input in the non-obsolete form. */ + if (!obsolete_usage && !*p) + return false; + + /* Plain "-c" is required to be the non-obsolete option. For + plain "-f" POSIX 1003.2-1992 is ambiguous; assume the + non-obsolete form. */ + if ((p[0] == 'c' || p[0] == 'f') && !p[1]) + return false; + + t_from_start = false; + break; } + + n_string = p; + while (ISDIGIT (*p)) + p++; n_string_end = p; - t_count_lines = true; - if (*p == 'c' || *p == 'b') - { - t_count_lines = false; - ++p; - } - else if (*p == 'l') + switch (*p) { - ++p; + case 'c': t_count_lines = false; /* Fall through. */ + case 'l': p++; break; } - t_forever = false; if (*p == 'f') { t_forever = true; ++p; } - if (*p != '\0') - { - /* If (argv[1] begins with a `+' or if it begins with `-' followed - by a digit), but has an invalid suffix character, give a diagnostic - and indicate to caller that this *is* of the obsolescent form, - but that it's an invalid option. */ - if (t_from_start || n_string) - { - error (0, 0, - _("%c: invalid suffix character in obsolescent option"), *p); - *ok = false; - return true; - } + if (*p) + return false; - /* Otherwise, it might be a valid non-obsolescent option like -n. */ - return false; - } + len = n_string_end - n_string; - *ok = true; - if (n_string == NULL) + if (n_string == n_string_end) *n_units = DEFAULT_N_LINES; - else - { - strtol_error s_err; - uintmax_t tmp; - char *end; - - s_err = xstrtoumax (n_string, &end, 10, &tmp, - *n_string_end == 'b' ? "b" : NULL); - if (s_err == LONGINT_OK) - *n_units = tmp; - else - { - /* Extract a NUL-terminated string for the error message. */ - size_t len = n_string_end - n_string; - char *n_string_tmp = xmalloc (len + 1); - - strncpy (n_string_tmp, n_string, len); - n_string_tmp[len] = '\0'; - - error (0, 0, - _("%s: %s is so large that it is not representable"), - n_string_tmp, (t_count_lines - ? _("number of lines") - : _("number of bytes"))); - free (n_string_tmp); - *ok = false; - } - } + else if (xstrtoumax (n_string, NULL, 10, n_units, NULL) != LONGINT_OK) + error (EXIT_FAILURE, 0, _("number `%.*s' too large"), len, n_string); - if (*ok) + if (!obsolete_usage) { - if (! obsolete_usage) + if (len == 0) { - int n_string_len = n_string_end - n_string; - error (0, 0, _("`%s' option is obsolete; use `%s-%c %.*s'"), - argv[1], t_forever ? " -f" : "", t_count_lines ? 'n' : 'c', - n_string_len, n_string); - usage (EXIT_FAILURE); + len = 2; + n_string = "10"; } - - /* Set globals. */ - from_start = t_from_start; - count_lines = t_count_lines; - forever = t_forever; + error (0, 0, _("`%s' option is obsolete; use `%s-%c %.*s'"), + argv[1], t_forever ? "-f " : "", t_count_lines ? 'n' : 'c', + len, n_string); + usage (EXIT_FAILURE); } + /* Set globals. */ + from_start = t_from_start; + count_lines = t_count_lines; + forever = t_forever; + return true; } @@ -1665,22 +1625,10 @@ main (int argc, char **argv) have_read_stdin = false; - { - bool ok; - - if (parse_obsolescent_option (argc, - (const char *const *) argv, - &n_units, &ok)) - { - if (!ok) - exit (EXIT_FAILURE); - optind = 2; - } - else - { - parse_options (argc, argv, &n_units, &header_mode, &sleep_interval); - } - } + if (parse_obsolete_option (argc, argv, &n_units)) + optind = 2; + else + parse_options (argc, argv, &n_units, &header_mode, &sleep_interval); /* To start printing with item N_UNITS from the start of the file, skip N_UNITS - 1 items. `tail -n +0' is actually meaningless, but for Unix |