/* expand - convert tabs to spaces This is the expand utility
Copyright (C) 1989-2018 Free Software Foundation, Inc.
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 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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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, see <https://www.gnu.org/licenses/>. */ The GNUv3 license
/* By default, convert all tabs to spaces.
Preserves backspace characters in the output; they decrement the
column count for tab calculations.
The default action is equivalent to -8.
Options:
--tabs=tab1[,tab2[,...]]
-t tab1[,tab2[,...]]
-tab1[,tab2[,...]] If only one tab stop is given, set the tabs tab1
columns apart instead of the default 8. Otherwise,
set the tabs at columns tab1, tab2, etc. (numbered from
0); replace any tabs beyond the tab stops given with
single spaces.
--initial
-i Only convert initial tabs on each line to spaces.
David MacKenzie <djm@gnu.ai.mit.edu> */
#include <config.h> Provides system specific information
#include <stdio.h> Provides standard I/O capability
#include <getopt.h> ...!includes auto-comment...
#include <sys/types.h> Provides system data types
#include "system.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "xstrndup.h" ...!includes auto-comment...
#include "expand-common.h" ...!includes auto-comment...
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "expand" Line 47
#define AUTHORS proper_name ("David MacKenzie") Line 49
static char const shortopts[] = "it:0::1::2::3::4::5::6::7::8::9::"; Line 51
static struct option const longopts[] = Line 53
{
{"tabs", required_argument, NULL, 't'}, Line 55
{"initial", no_argument, NULL, 'i'}, Line 56
{GETOPT_HELP_OPTION_DECL}, Line 57
{GETOPT_VERSION_OPTION_DECL}, Line 58
{NULL, 0, NULL, 0} Line 59
}; Block 1
void Line 62
usage (int status) Line 63
{
if (status != EXIT_SUCCESS) Line 65
emit_try_help (); ...!common auto-comment...
else Line 67
{
printf (_("\ Line 69
Usage: %s [OPTION]... [FILE]...\n\ Line 70
"), Line 71
program_name); Line 72
fputs (_("\ Line 73
Convert tabs in each FILE to spaces, writing to standard output.\n\ Line 74
"), stdout); Line 75
emit_stdin_note (); ...!common auto-comment...
emit_mandatory_arg_note (); ...!common auto-comment...
fputs (_("\ Line 80
-i, --initial do not convert tabs after non blanks\n\ Line 81
-t, --tabs=N have tabs N characters apart, not 8\n\ Line 82
"), stdout); Line 83
emit_tab_list_info (); Line 84
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 85
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 86
emit_ancillary_info (PROGRAM_NAME); Line 87
}
exit (status); Line 89
} Block 2
/* Change tabs to spaces, writing to stdout.
Read each file in 'file_list', in order. */
static void Line 96
expand (void) Line 97
{
/* Input stream. */
FILE *fp = next_file (NULL); Line 100
if (!fp) Line 102
return; Line 103
while (true) Line 105
{
/* Input character, or EOF. */
int c; Line 108
/* If true, perform translations. */
bool convert = true; Line 111
/* The following variables have valid values only when CONVERT
is true: */
/* Column of next input character. */
uintmax_t column = 0; Line 118
/* Index in TAB_LIST of next tab stop to examine. */
size_t tab_index = 0; Line 121
/* Convert a line of text. */
do
{
while ((c = getc (fp)) < 0 && (fp = next_file (fp))) Line 128
continue; Line 129
if (convert) Line 131
{
if (c == '\t') Line 133
{
/* Column the next input tab stop is on. */
uintmax_t next_tab_column; Line 136
bool last_tab IF_LINT (=0); Line 137
next_tab_column = get_next_tab_column (column, &tab_index, Line 139
&last_tab); Line 140
if (last_tab) Line 142
next_tab_column = column + 1; Line 143
if (next_tab_column < column) Line 145
die (EXIT_FAILURE, 0, _("input line is too long")); Line 146
while (++column < next_tab_column) Line 148
if (putchar (' ') < 0) Line 149
die (EXIT_FAILURE, errno, _("write error")); Line 150
c = ' '; Line 152
}
else if (c == '\b') Line 154
{
/* Go back one column, and force recalculation of the
next tab stop. */
column -= !!column; Line 158
tab_index -= !!tab_index; Line 159
}
else Line 161
{
column++; Line 163
if (!column) Line 164
die (EXIT_FAILURE, 0, _("input line is too long")); Line 165
}
convert &= convert_entire_line || !! isblank (c); Line 168
}
if (c < 0) Line 171
return; Line 172
if (putchar (c) < 0) Line 174
die (EXIT_FAILURE, errno, _("write error")); Line 175
}
while (c != '\n'); Line 177
}
}
int
main (int argc, char **argv) Line 182
{
int c; Line 184
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdout); Close stdout on exit (see gnulib)
convert_entire_line = true; Line 193
while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) Line 195
{
switch (c) Line 197
{
case 'i': Line 199
convert_entire_line = false; Line 200
break; Line 201
case 't': Line 203
parse_tab_stops (optarg); Line 204
break; Line 205
case '0': case '1': case '2': case '3': case '4': Line 207
case '5': case '6': case '7': case '8': case '9': Line 208
if (optarg) Line 209
parse_tab_stops (optarg - 1); Line 210
else Line 211
{
char tab_stop[2]; Line 213
tab_stop[0] = c; Line 214
tab_stop[1] = '\0'; Line 215
parse_tab_stops (tab_stop); Line 216
}
break; Line 218
case_GETOPT_HELP_CHAR; Line 220
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 222
default: Line 224
usage (EXIT_FAILURE); Line 225
}
}
finalize_tab_stops (); Line 229
set_file_list ( (optind < argc) ? &argv[optind] : NULL); Line 231
expand (); Line 233
cleanup_file_list_stdin (); Line 235
return exit_status; Line 237
} Block 4