summaryrefslogtreecommitdiff
path: root/src/expand.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-08-24 07:38:04 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-08-24 07:38:04 +0000
commit0d568f76787ee02a96cb6182992afd7d57f3fa08 (patch)
tree7150416fb7b11a64ca268dc749257eaabc8193df /src/expand.c
parentbb5992656315f3d3a4813e35f47403d74d758978 (diff)
downloadcoreutils-0d568f76787ee02a96cb6182992afd7d57f3fa08.tar.gz
coreutils-0d568f76787ee02a96cb6182992afd7d57f3fa08.tar.bz2
coreutils-0d568f76787ee02a96cb6182992afd7d57f3fa08.zip
Revamp to resemble the new unexpand.c better.
(usage): -i does not convert tabs after non-tabs. (add_tab_stop): Renamed from add_tabstop. All uses changed. (parse_tab_stop): Renamed from parse_tabstop. All uses changed. (validate_tab_stop): Renamed from validate_tabstop. All uses changed. (next_file, main): Check fclose against 0, not EOF. (expand): Remove unnecessary casts. Add another loop nesting level, for lines, so that per-line variables are initialized cleanly. Revamp tab checking. Check for write error immediately, rather than just once at the end of the program.
Diffstat (limited to 'src/expand.c')
-rw-r--r--src/expand.c173
1 files changed, 92 insertions, 81 deletions
diff --git a/src/expand.c b/src/expand.c
index 29e333edc..7b4db1a23 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -24,9 +24,9 @@
--tabs=tab1[,tab2[,...]]
-t tab1[,tab2[,...]]
-tab1[,tab2[,...]] If only one tab stop is given, set the tabs tab1
- spaces apart instead of the default 8. Otherwise,
+ columns apart instead of the default 8. Otherwise,
set the tabs at columns tab1, tab2, etc. (numbered from
- 0); replace any tabs beyond the tabstops given with
+ 0); replace any tabs beyond the tab stops given with
single spaces.
--initial
-i Only convert initial tabs on each line to spaces.
@@ -120,7 +120,7 @@ With no FILE, or when FILE is -, read standard input.\n\
Mandatory arguments to long options are mandatory for short options too.\n\
"), stdout);
fputs (_("\
- -i, --initial do not convert TABs after non whitespace\n\
+ -i, --initial do not convert tabs after non blanks\n\
-t, --tabs=NUMBER have tabs NUMBER characters apart, not 8\n\
"), stdout);
fputs (_("\
@@ -136,18 +136,18 @@ Mandatory arguments to long options are mandatory for short options too.\n\
/* Add tab stop TABVAL to the end of `tab_list'. */
static void
-add_tabstop (uintmax_t tabval)
+add_tab_stop (uintmax_t tabval)
{
if (first_free_tab == n_tabs_allocated)
tab_list = x2nrealloc (tab_list, &n_tabs_allocated, sizeof *tab_list);
tab_list[first_free_tab++] = tabval;
}
-/* Add the comma or blank separated list of tabstops STOPS
- to the list of tabstops. */
+/* Add the comma or blank separated list of tab stops STOPS
+ to the list of tab stops. */
static void
-parse_tabstops (char const *stops)
+parse_tab_stops (char const *stops)
{
bool have_tabval = false;
uintmax_t tabval IF_LINT (= 0);
@@ -159,7 +159,7 @@ parse_tabstops (char const *stops)
if (*stops == ',' || ISBLANK (to_uchar (*stops)))
{
if (have_tabval)
- add_tabstop (tabval);
+ add_tab_stop (tabval);
have_tabval = false;
}
else if (ISDIGIT (*stops))
@@ -198,14 +198,14 @@ parse_tabstops (char const *stops)
exit (EXIT_FAILURE);
if (have_tabval)
- add_tabstop (tabval);
+ add_tab_stop (tabval);
}
-/* Check that the list of tabstops TABS, with ENTRIES entries,
+/* Check that the list of tab stops TABS, with ENTRIES entries,
contains only nonzero, ascending values. */
static void
-validate_tabstops (uintmax_t const *tabs, size_t entries)
+validate_tab_stops (uintmax_t const *tabs, size_t entries)
{
uintmax_t prev_tab = 0;
size_t i;
@@ -240,7 +240,7 @@ next_file (FILE *fp)
}
if (fp == stdin)
clearerr (fp); /* Also clear EOF. */
- else if (fclose (fp) == EOF)
+ else if (fclose (fp) != 0)
{
error (0, errno, "%s", prev_file);
exit_status = EXIT_FAILURE;
@@ -273,14 +273,10 @@ next_file (FILE *fp)
static void
expand (void)
{
- FILE *fp; /* Input stream. */
- size_t tab_index = 0; /* Index in `tab_list' of next tabstop. */
- uintmax_t column = 0; /* Column of next char. */
- uintmax_t next_tab_column; /* Column the next tab stop is on. */
- bool convert = true; /* If true, perform translations. */
-
- fp = next_file ((FILE *) NULL);
- if (fp == NULL)
+ /* Input stream. */
+ FILE *fp = next_file (NULL);
+
+ if (!fp)
return;
/* Binary I/O will preserve the original EOL style (DOS/Unix) of files. */
@@ -288,74 +284,89 @@ expand (void)
for (;;)
{
- int c = getc (fp);
- if (c == EOF)
- {
- fp = next_file (fp);
- if (fp)
- {
- SET_BINARY2 (fileno (fp), STDOUT_FILENO);
- continue;
- }
- break;
- }
+ /* Input character, or EOF. */
+ int c;
- if (c == '\n')
- {
- putchar (c);
- tab_index = 0;
- column = 0;
- convert = true;
- }
- else if (c == '\t' && convert)
- {
- if (tab_size == 0)
- {
- /* Do not let tab_index == first_free_tab;
- stop when it is 1 less. */
- while (tab_index < first_free_tab - 1
- && column >= tab_list[tab_index])
- tab_index++;
- next_tab_column = tab_list[tab_index];
- if (tab_index < first_free_tab - 1)
- tab_index++;
- if (column >= next_tab_column)
- next_tab_column = column + 1; /* Ran out of tab stops. */
- }
- else
- {
- next_tab_column = column + tab_size - column % tab_size;
- }
- if (next_tab_column < column)
- error (EXIT_FAILURE, 0, _("input line is too long"));
- while (column < next_tab_column)
- {
- putchar (' ');
- ++column;
- }
- }
- else
+ /* If true, perform translations. */
+ bool convert = true;
+
+
+ /* The following variables have valid values only when CONVERT
+ is true: */
+
+ /* Column of next input character. */
+ uintmax_t column = 0;
+
+ /* Index in TAB_LIST of next tab stop to examine. */
+ size_t tab_index = 0;
+
+
+ /* Convert a line of text. */
+
+ do
{
+ while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
+ SET_BINARY2 (fileno (fp), STDOUT_FILENO);
+
if (convert)
{
- if (c == '\b')
+ if (c == '\t')
+ {
+ /* Column the next input tab stop is on. */
+ uintmax_t next_tab_column;
+
+ if (tab_size)
+ next_tab_column = column + (tab_size - column % tab_size);
+ else
+ for (;;)
+ if (tab_index == first_free_tab)
+ {
+ next_tab_column = column + 1;
+ break;
+ }
+ else
+ {
+ uintmax_t tab = tab_list[tab_index++];
+ if (column < tab)
+ {
+ next_tab_column = tab;
+ break;
+ }
+ }
+
+ if (next_tab_column < column)
+ error (EXIT_FAILURE, 0, _("input line is too long"));
+
+ while (++column < next_tab_column)
+ if (putchar (' ') < 0)
+ error (EXIT_FAILURE, errno, _("write error"));
+
+ c = ' ';
+ }
+ else if (c == '\b')
{
- if (column > 0)
- {
- column--;
- tab_index -= (tab_index != 0);
- }
+ /* Go back one column, and force recalculation of the
+ next tab stop. */
+ column -= !!column;
+ tab_index -= !!tab_index;
}
else
{
- ++column;
- if (column == 0)
+ column++;
+ if (!column)
error (EXIT_FAILURE, 0, _("input line is too long"));
- convert &= convert_entire_line;
}
+
+ convert &= convert_entire_line | ISBLANK (c);
}
- putchar (c);
+
+ if (c < 0)
+ return;
+
+ if (putchar (c) < 0)
+ error (EXIT_FAILURE, errno, _("write error"));
}
+ while (c != '\n');
}
}
@@ -396,11 +407,11 @@ main (int argc, char **argv)
convert_entire_line = false;
break;
case 't':
- parse_tabstops (optarg);
+ parse_tab_stops (optarg);
break;
case ',':
if (have_tabval)
- add_tabstop (tabval);
+ add_tab_stop (tabval);
have_tabval = false;
obsolete_tablist = true;
break;
@@ -425,9 +436,9 @@ main (int argc, char **argv)
}
if (have_tabval)
- add_tabstop (tabval);
+ add_tab_stop (tabval);
- validate_tabstops (tab_list, first_free_tab);
+ validate_tab_stops (tab_list, first_free_tab);
if (first_free_tab == 0)
tab_size = 8;
@@ -440,7 +451,7 @@ main (int argc, char **argv)
expand ();
- if (have_read_stdin && fclose (stdin) == EOF)
+ if (have_read_stdin && fclose (stdin) != 0)
error (EXIT_FAILURE, errno, "-");
exit (exit_status);