summaryrefslogtreecommitdiff
path: root/src/nl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nl.c')
-rw-r--r--src/nl.c331
1 files changed, 152 insertions, 179 deletions
diff --git a/src/nl.c b/src/nl.c
index 04c8118..a4a48bc 100644
--- a/src/nl.c
+++ b/src/nl.c
@@ -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;
}