diff options
Diffstat (limited to 'src/nl.c')
-rw-r--r-- | src/nl.c | 331 |
1 files changed, 152 insertions, 179 deletions
@@ -1,10 +1,10 @@ /* nl -- number lines of files - Copyright (C) 89, 92, 1995-2007 Free Software Foundation, Inc. + Copyright (C) 1989-2016 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -12,9 +12,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + /* Written by Scott Bartram (nancy!scott@uunet.uu.net) Revised by David MacKenzie (djm@gnu.ai.mit.edu) */ @@ -29,14 +28,17 @@ #include <regex.h> #include "error.h" +#include "fadvise.h" #include "linebuffer.h" #include "quote.h" -#include "xstrtol.h" +#include "xdectoint.h" -/* The official name of this program (e.g., no `g' prefix). */ +/* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "nl" -#define AUTHORS "Scott Bartram", "David MacKenzie" +#define AUTHORS \ + proper_name ("Scott Bartram"), \ + proper_name ("David MacKenzie") /* Line-number formats. They are given an int width, an intmax_t value, and a string separator. */ @@ -60,9 +62,6 @@ enum section Header, Body, Footer, Text }; -/* The name this program was run with. */ -char *program_name; - /* Format of body lines (-b). */ static char const *body_type = "t"; @@ -152,7 +151,7 @@ static struct option const longopts[] = {"body-numbering", required_argument, NULL, 'b'}, {"footer-numbering", required_argument, NULL, 'f'}, {"starting-line-number", required_argument, NULL, 'v'}, - {"page-increment", required_argument, NULL, 'i'}, + {"line-increment", required_argument, NULL, 'i'}, {"no-renumber", no_argument, NULL, 'p'}, {"join-blank-lines", required_argument, NULL, 'l'}, {"number-separator", required_argument, NULL, 's'}, @@ -170,22 +169,20 @@ void usage (int status) { if (status != EXIT_SUCCESS) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); + emit_try_help (); else { printf (_("\ Usage: %s [OPTION]... [FILE]...\n\ "), - program_name); + program_name); fputs (_("\ Write each FILE to standard output, with line numbers added.\n\ -With no FILE, or when FILE is -, read standard input.\n\ -\n\ -"), stdout); - fputs (_("\ -Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); + + emit_stdin_note (); + emit_mandatory_arg_note (); + fputs (_("\ -b, --body-numbering=STYLE use STYLE for numbering body lines\n\ -d, --section-delimiter=CC use CC for separating logical pages\n\ @@ -193,14 +190,14 @@ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ -h, --header-numbering=STYLE use STYLE for numbering header lines\n\ - -i, --page-increment=NUMBER line number increment at each line\n\ + -i, --line-increment=NUMBER line number increment at each line\n\ -l, --join-blank-lines=NUMBER group of NUMBER empty lines counted as one\n\ -n, --number-format=FORMAT insert line numbers according to FORMAT\n\ -p, --no-renumber do not reset line numbers at logical pages\n\ -s, --number-separator=STRING add STRING after (possible) line number\n\ "), stdout); fputs (_("\ - -v, --first-page=NUMBER first line number on each logical page\n\ + -v, --starting-line-number=NUMBER first line number on each logical page\n\ -w, --number-width=NUMBER use NUMBER columns for line numbers\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); @@ -226,17 +223,17 @@ FORMAT is one of:\n\ rz right justified, leading zeros\n\ \n\ "), stdout); - printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); + emit_ancillary_info (PROGRAM_NAME); } exit (status); } /* Set the command line flag TYPEP and possibly the regex pointer REGEXP, - according to `optarg'. */ + according to 'optarg'. */ static bool build_type_arg (char const **typep, - struct re_pattern_buffer *regexp, char *fastmap) + struct re_pattern_buffer *regexp, char *fastmap) { char const *errmsg; bool rval = true; @@ -255,10 +252,10 @@ build_type_arg (char const **typep, regexp->fastmap = fastmap; regexp->translate = NULL; re_syntax_options = - RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES; + RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES; errmsg = re_compile_pattern (optarg, strlen (optarg), regexp); if (errmsg) - error (EXIT_FAILURE, 0, "%s", errmsg); + error (EXIT_FAILURE, 0, "%s", (errmsg)); break; default: rval = false; @@ -314,7 +311,7 @@ proc_footer (void) putchar ('\n'); } -/* Process a regular text line in `line_buf'. */ +/* Process a regular text line in 'line_buf'. */ static void proc_text (void) @@ -325,47 +322,47 @@ proc_text (void) { case 'a': if (blank_join > 1) - { - if (1 < line_buf.length || ++blank_lines == blank_join) - { - print_lineno (); - blank_lines = 0; - } - else - fputs (print_no_line_fmt, stdout); - } + { + if (1 < line_buf.length || ++blank_lines == blank_join) + { + print_lineno (); + blank_lines = 0; + } + else + fputs (print_no_line_fmt, stdout); + } else - print_lineno (); + print_lineno (); break; case 't': if (1 < line_buf.length) - print_lineno (); + print_lineno (); else - fputs (print_no_line_fmt, stdout); + fputs (print_no_line_fmt, stdout); break; case 'n': fputs (print_no_line_fmt, stdout); break; case 'p': switch (re_search (current_regex, line_buf.buffer, line_buf.length - 1, - 0, line_buf.length - 1, NULL)) - { - case -2: - error (EXIT_FAILURE, errno, _("error in regular expression search")); - - case -1: - fputs (print_no_line_fmt, stdout); - break; - - default: - print_lineno (); - break; - } + 0, line_buf.length - 1, NULL)) + { + case -2: + error (EXIT_FAILURE, errno, _("error in regular expression search")); + + case -1: + fputs (print_no_line_fmt, stdout); + break; + + default: + print_lineno (); + break; + } } fwrite (line_buf.buffer, sizeof (char), line_buf.length, stdout); } -/* Return the type of line in `line_buf'. */ +/* Return the type of line in 'line_buf'. */ static enum section check_section (void) @@ -394,20 +391,20 @@ process_file (FILE *fp) while (readlinebuffer (&line_buf, fp)) { switch (check_section ()) - { - case Header: - proc_header (); - break; - case Body: - proc_body (); - break; - case Footer: - proc_footer (); - break; - case Text: - proc_text (); - break; - } + { + case Header: + proc_header (); + break; + case Body: + proc_body (); + break; + case Footer: + proc_footer (); + break; + case Text: + proc_text (); + break; + } } } @@ -428,24 +425,26 @@ nl_file (char const *file) { stream = fopen (file, "r"); if (stream == NULL) - { - error (0, errno, "%s", file); - return false; - } + { + error (0, errno, "%s", quotef (file)); + return false; + } } + fadvise (stream, FADVISE_SEQUENTIAL); + process_file (stream); if (ferror (stream)) { - error (0, errno, "%s", file); + error (0, errno, "%s", quotef (file)); return false; } if (STREQ (file, "-")) clearerr (stream); /* Also clear EOF. */ else if (fclose (stream) == EOF) { - error (0, errno, "%s", file); + error (0, errno, "%s", quotef (file)); return false; } return true; @@ -459,7 +458,7 @@ main (int argc, char **argv) bool ok = true; initialize_main (&argc, &argv); - program_name = argv[0]; + set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -469,106 +468,80 @@ main (int argc, char **argv) have_read_stdin = false; while ((c = getopt_long (argc, argv, "h:b:f:v:i:pl:s:w:n:d:", longopts, - NULL)) != -1) + NULL)) != -1) { switch (c) - { - case 'h': - if (! build_type_arg (&header_type, &header_regex, header_fastmap)) - { - error (0, 0, _("invalid header numbering style: %s"), - quote (optarg)); - ok = false; - } - break; - case 'b': - if (! build_type_arg (&body_type, &body_regex, body_fastmap)) - { - error (0, 0, _("invalid body numbering style: %s"), - quote (optarg)); - ok = false; - } - break; - case 'f': - if (! build_type_arg (&footer_type, &footer_regex, footer_fastmap)) - { - error (0, 0, _("invalid footer numbering style: %s"), - quote (optarg)); - ok = false; - } - break; - case 'v': - if (xstrtoimax (optarg, NULL, 10, &starting_line_number, "") - != LONGINT_OK) - { - error (0, 0, _("invalid starting line number: %s"), - quote (optarg)); - ok = false; - } - break; - case 'i': - if (! (xstrtoimax (optarg, NULL, 10, &page_incr, "") == LONGINT_OK - && 0 < page_incr)) - { - error (0, 0, _("invalid line number increment: %s"), - quote (optarg)); - ok = false; - } - break; - case 'p': - reset_numbers = false; - break; - case 'l': - if (! (xstrtoimax (optarg, NULL, 10, &blank_join, "") == LONGINT_OK - && 0 < blank_join)) - { - error (0, 0, _("invalid number of blank lines: %s"), - quote (optarg)); - ok = false; - } - break; - case 's': - separator_str = optarg; - break; - case 'w': - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) - { - error (0, 0, _("invalid line number field width: %s"), - quote (optarg)); - ok = false; - } - else - { - lineno_width = tmp_long; - } - } - break; - case 'n': - if (STREQ (optarg, "ln")) - lineno_format = FORMAT_LEFT; - else if (STREQ (optarg, "rn")) - lineno_format = FORMAT_RIGHT_NOLZ; - else if (STREQ (optarg, "rz")) - lineno_format = FORMAT_RIGHT_LZ; - else - { - error (0, 0, _("invalid line numbering format: %s"), - quote (optarg)); - ok = false; - } - break; - case 'd': - section_del = optarg; - break; - case_GETOPT_HELP_CHAR; - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); - default: - ok = false; - break; - } + { + case 'h': + if (! build_type_arg (&header_type, &header_regex, header_fastmap)) + { + error (0, 0, _("invalid header numbering style: %s"), + quote (optarg)); + ok = false; + } + break; + case 'b': + if (! build_type_arg (&body_type, &body_regex, body_fastmap)) + { + error (0, 0, _("invalid body numbering style: %s"), + quote (optarg)); + ok = false; + } + break; + case 'f': + if (! build_type_arg (&footer_type, &footer_regex, footer_fastmap)) + { + error (0, 0, _("invalid footer numbering style: %s"), + quote (optarg)); + ok = false; + } + break; + case 'v': + starting_line_number = xdectoimax (optarg, INTMAX_MIN, INTMAX_MAX, "", + _("invalid starting line number"), + 0); + break; + case 'i': + page_incr = xdectoimax (optarg, 1, INTMAX_MAX, "", + _("invalid line number increment"), 0); + break; + case 'p': + reset_numbers = false; + break; + case 'l': + blank_join = xdectoimax (optarg, 1, INTMAX_MAX, "", + _("invalid line number of blank lines"), 0); + break; + case 's': + separator_str = optarg; + break; + case 'w': + lineno_width = xdectoimax (optarg, 1, INT_MAX, "", + _("invalid line number field width"), 0); + break; + case 'n': + if (STREQ (optarg, "ln")) + lineno_format = FORMAT_LEFT; + else if (STREQ (optarg, "rn")) + lineno_format = FORMAT_RIGHT_NOLZ; + else if (STREQ (optarg, "rz")) + lineno_format = FORMAT_RIGHT_LZ; + else + { + error (0, 0, _("invalid line numbering format: %s"), + quote (optarg)); + ok = false; + } + break; + case 'd': + section_del = optarg; + break; + case_GETOPT_HELP_CHAR; + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + default: + ok = false; + break; + } } if (!ok) @@ -579,15 +552,15 @@ main (int argc, char **argv) header_del_len = len * 3; header_del = xmalloc (header_del_len + 1); - strcat (strcat (strcpy (header_del, section_del), section_del), section_del); + stpcpy (stpcpy (stpcpy (header_del, section_del), section_del), section_del); body_del_len = len * 2; body_del = xmalloc (body_del_len + 1); - strcat (strcpy (body_del, section_del), section_del); + stpcpy (stpcpy (body_del, section_del), section_del); footer_del_len = len; footer_del = xmalloc (footer_del_len + 1); - strcpy (footer_del, section_del); + stpcpy (footer_del, section_del); /* Initialize the input buffer. */ initbuffer (&line_buf); @@ -613,5 +586,5 @@ main (int argc, char **argv) if (have_read_stdin && fclose (stdin) == EOF) error (EXIT_FAILURE, errno, "-"); - exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); + return ok ? EXIT_SUCCESS : EXIT_FAILURE; } |