1 /* expand - convert tabs to spaces
2 * unexpand - convert spaces to tabs
4 * Copyright (C) 89, 91, 1995-2006 Free Software Foundation, Inc.
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 * David MacKenzie <djm@gnu.ai.mit.edu>
11 * -t num --tabs=NUM Convert tabs to num spaces (default 8 spaces).
12 * -i --initial Only convert initial tabs on each line to spaces.
14 * Options for unexpand:
15 * -a --all Convert all blanks, instead of just initial blanks.
16 * -f --first-only Convert only leading sequences of blanks (default).
17 * -t num --tabs=NUM Have tabs num characters apart instead of 8.
19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
21 * Caveat: this versions of expand and unexpand don't accept tab lists.
24 //usage:#define expand_trivial_usage
25 //usage: "[-i] [-t N] [FILE]..."
26 //usage:#define expand_full_usage "\n\n"
27 //usage: "Convert tabs to spaces, writing to stdout\n"
28 //usage: IF_FEATURE_EXPAND_LONG_OPTIONS(
29 //usage: "\n -i,--initial Don't convert tabs after non blanks"
30 //usage: "\n -t,--tabs=N Tabstops every N chars"
32 //usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS(
33 //usage: "\n -i Don't convert tabs after non blanks"
34 //usage: "\n -t Tabstops every N chars"
37 //usage:#define unexpand_trivial_usage
38 //usage: "[-fa][-t N] [FILE]..."
39 //usage:#define unexpand_full_usage "\n\n"
40 //usage: "Convert spaces to tabs, writing to stdout\n"
41 //usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS(
42 //usage: "\n -a,--all Convert all blanks"
43 //usage: "\n -f,--first-only Convert only leading blanks"
44 //usage: "\n -t,--tabs=N Tabstops every N chars"
46 //usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS(
47 //usage: "\n -a Convert all blanks"
48 //usage: "\n -f Convert only leading blanks"
49 //usage: "\n -t N Tabstops every N chars"
62 static void expand(FILE *file
, unsigned tab_size
, unsigned opt
)
66 while ((line
= xmalloc_fgets(file
)) != NULL
) {
71 ptr
= ptr_strbeg
= line
;
72 while ((c
= *ptr
) != '\0') {
73 if ((opt
& OPT_INITIAL
) && !isblank(c
)) {
74 /* not space or tab */
80 # if ENABLE_UNICODE_SUPPORT
83 printable_string(&uni_stat
, ptr_strbeg
);
84 len
= uni_stat
.unicode_width
;
87 len
= ptr
- ptr_strbeg
;
89 len
= tab_size
- (len
% tab_size
);
90 /*while (ptr[1] == '\t') { ptr++; len += tab_size; } - can handle many tabs at once */
91 printf("%s%*s", ptr_strbeg
, len
, "");
96 fputs(ptr_strbeg
, stdout
);
103 static void unexpand(FILE *file
, unsigned tab_size
, unsigned opt
)
107 while ((line
= xmalloc_fgets(file
)) != NULL
) {
115 while (*ptr
== ' ') {
121 column
+= tab_size
- (column
% tab_size
);
126 n
= column
/ tab_size
;
128 len
= column
= column
% tab_size
;
133 if ((opt
& OPT_INITIAL
) && ptr
!= line
) {
134 printf("%*s%s", len
, "", ptr
);
137 n
= strcspn(ptr
, "\t ");
138 printf("%*s%.*s", len
, "", n
, ptr
);
139 # if ENABLE_UNICODE_SUPPORT
145 printable_string(&uni_stat
, ptr
);
146 len
= uni_stat
.unicode_width
;
153 column
= (column
+ len
) % tab_size
;
160 int expand_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
161 int expand_main(int argc UNUSED_PARAM
, char **argv
)
163 /* Default 8 spaces for 1 tab */
164 const char *opt_t
= "8";
168 int exit_status
= EXIT_SUCCESS
;
170 #if ENABLE_FEATURE_EXPAND_LONG_OPTIONS
171 static const char expand_longopts
[] ALIGN1
=
172 /* name, has_arg, val */
173 "initial\0" No_argument
"i"
174 "tabs\0" Required_argument
"t"
177 #if ENABLE_FEATURE_UNEXPAND_LONG_OPTIONS
178 static const char unexpand_longopts
[] ALIGN1
=
179 /* name, has_arg, val */
180 "first-only\0" No_argument
"i"
181 "tabs\0" Required_argument
"t"
182 "all\0" No_argument
"a"
187 if (ENABLE_EXPAND
&& (!ENABLE_UNEXPAND
|| applet_name
[0] == 'e')) {
188 IF_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options
= expand_longopts
);
189 opt
= getopt32(argv
, "it:", &opt_t
);
191 IF_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options
= unexpand_longopts
);
192 /* -t NUM sets also -a */
193 opt_complementary
= "ta";
194 opt
= getopt32(argv
, "ft:a", &opt_t
);
195 /* -f --first-only is the default */
196 if (!(opt
& OPT_ALL
)) opt
|= OPT_INITIAL
;
198 tab_size
= xatou_range(opt_t
, 1, UINT_MAX
);
203 *--argv
= (char*)bb_msg_standard_input
;
206 file
= fopen_or_warn_stdin(*argv
);
208 exit_status
= EXIT_FAILURE
;
212 if (ENABLE_EXPAND
&& (!ENABLE_UNEXPAND
|| applet_name
[0] == 'e'))
213 IF_EXPAND(expand(file
, tab_size
, opt
));
215 IF_UNEXPAND(unexpand(file
, tab_size
, opt
));
217 /* Check and close the file */
218 if (fclose_if_not_stdin(file
)) {
219 bb_simple_perror_msg(*argv
);
220 exit_status
= EXIT_FAILURE
;
222 /* If stdin also clear EOF */
227 /* Now close stdin also */
228 /* (if we didn't read from it, it's a no-op) */
230 bb_perror_msg_and_die(bb_msg_standard_input
);
232 fflush_stdout_and_exit(exit_status
);