source: MondoRescue/branches/3.3/mindi-busybox/coreutils/expand.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 5.7 KB
RevLine 
[1765]1/* expand - convert tabs to spaces
2 * unexpand - convert spaces to tabs
3 *
4 * Copyright (C) 89, 91, 1995-2006 Free Software Foundation, Inc.
5 *
[2725]6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[1765]7 *
8 * David MacKenzie <djm@gnu.ai.mit.edu>
9 *
10 * Options for expand:
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.
13 *
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.
18 *
19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
20 *
21 * Caveat: this versions of expand and unexpand don't accept tab lists.
22 */
[3232]23
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"
31//usage: )
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"
35//usage: )
36
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"
45//usage: )
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"
50//usage: )
51
[1765]52#include "libbb.h"
[2725]53#include "unicode.h"
[1765]54
55enum {
56 OPT_INITIAL = 1 << 0,
57 OPT_TABS = 1 << 1,
58 OPT_ALL = 1 << 2,
59};
60
61#if ENABLE_EXPAND
62static void expand(FILE *file, unsigned tab_size, unsigned opt)
63{
64 char *line;
65
[2725]66 while ((line = xmalloc_fgets(file)) != NULL) {
67 unsigned char c;
68 char *ptr;
69 char *ptr_strbeg;
[1765]70
[2725]71 ptr = ptr_strbeg = line;
72 while ((c = *ptr) != '\0') {
73 if ((opt & OPT_INITIAL) && !isblank(c)) {
74 /* not space or tab */
75 break;
76 }
77 if (c == '\t') {
78 unsigned len;
79 *ptr = '\0';
80# if ENABLE_UNICODE_SUPPORT
[3621]81 len = unicode_strwidth(ptr_strbeg);
[2725]82# else
83 len = ptr - ptr_strbeg;
84# endif
85 len = tab_size - (len % tab_size);
86 /*while (ptr[1] == '\t') { ptr++; len += tab_size; } - can handle many tabs at once */
87 printf("%s%*s", ptr_strbeg, len, "");
88 ptr_strbeg = ptr + 1;
[1765]89 }
[2725]90 ptr++;
[1765]91 }
[2725]92 fputs(ptr_strbeg, stdout);
93 free(line);
[1765]94 }
95}
96#endif
97
98#if ENABLE_UNEXPAND
[2725]99static void unexpand(FILE *file, unsigned tab_size, unsigned opt)
[1765]100{
101 char *line;
102
103 while ((line = xmalloc_fgets(file)) != NULL) {
[2725]104 char *ptr = line;
105 unsigned column = 0;
106
107 while (*ptr) {
108 unsigned n;
109 unsigned len = 0;
110
111 while (*ptr == ' ') {
112 ptr++;
113 len++;
[1765]114 }
[2725]115 column += len;
116 if (*ptr == '\t') {
117 column += tab_size - (column % tab_size);
118 ptr++;
119 continue;
[1765]120 }
[2725]121
122 n = column / tab_size;
123 if (n) {
124 len = column = column % tab_size;
125 while (n--)
126 putchar('\t');
127 }
128
129 if ((opt & OPT_INITIAL) && ptr != line) {
130 printf("%*s%s", len, "", ptr);
131 break;
132 }
133 n = strcspn(ptr, "\t ");
134 printf("%*s%.*s", len, "", n, ptr);
135# if ENABLE_UNICODE_SUPPORT
136 {
[3621]137 char c = ptr[n];
[2725]138 ptr[n] = '\0';
[3621]139 len = unicode_strwidth(ptr);
[2725]140 ptr[n] = c;
141 }
142# else
143 len = n;
144# endif
145 ptr += n;
146 column = (column + len) % tab_size;
[1765]147 }
[2725]148 free(line);
[1765]149 }
150}
151#endif
152
[2725]153int expand_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
154int expand_main(int argc UNUSED_PARAM, char **argv)
[1765]155{
156 /* Default 8 spaces for 1 tab */
157 const char *opt_t = "8";
158 FILE *file;
159 unsigned tab_size;
160 unsigned opt;
161 int exit_status = EXIT_SUCCESS;
162
163#if ENABLE_FEATURE_EXPAND_LONG_OPTIONS
164 static const char expand_longopts[] ALIGN1 =
165 /* name, has_arg, val */
166 "initial\0" No_argument "i"
167 "tabs\0" Required_argument "t"
168 ;
169#endif
170#if ENABLE_FEATURE_UNEXPAND_LONG_OPTIONS
171 static const char unexpand_longopts[] ALIGN1 =
172 /* name, has_arg, val */
173 "first-only\0" No_argument "i"
174 "tabs\0" Required_argument "t"
175 "all\0" No_argument "a"
176 ;
177#endif
[2725]178 init_unicode();
[1765]179
180 if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e')) {
[2725]181 IF_FEATURE_EXPAND_LONG_OPTIONS(applet_long_options = expand_longopts);
[1765]182 opt = getopt32(argv, "it:", &opt_t);
[2725]183 } else {
184 IF_FEATURE_UNEXPAND_LONG_OPTIONS(applet_long_options = unexpand_longopts);
[1765]185 /* -t NUM sets also -a */
186 opt_complementary = "ta";
187 opt = getopt32(argv, "ft:a", &opt_t);
188 /* -f --first-only is the default */
189 if (!(opt & OPT_ALL)) opt |= OPT_INITIAL;
190 }
191 tab_size = xatou_range(opt_t, 1, UINT_MAX);
192
193 argv += optind;
194
195 if (!*argv) {
196 *--argv = (char*)bb_msg_standard_input;
197 }
198 do {
[2725]199 file = fopen_or_warn_stdin(*argv);
200 if (!file) {
201 exit_status = EXIT_FAILURE;
202 continue;
[1765]203 }
204
205 if (ENABLE_EXPAND && (!ENABLE_UNEXPAND || applet_name[0] == 'e'))
[2725]206 IF_EXPAND(expand(file, tab_size, opt));
207 else
208 IF_UNEXPAND(unexpand(file, tab_size, opt));
[1765]209
210 /* Check and close the file */
[2725]211 if (fclose_if_not_stdin(file)) {
212 bb_simple_perror_msg(*argv);
[1765]213 exit_status = EXIT_FAILURE;
214 }
215 /* If stdin also clear EOF */
216 if (file == stdin)
217 clearerr(file);
218 } while (*++argv);
219
220 /* Now close stdin also */
221 /* (if we didn't read from it, it's a no-op) */
222 if (fclose(stdin))
223 bb_perror_msg_and_die(bb_msg_standard_input);
224
225 fflush_stdout_and_exit(exit_status);
226}
Note: See TracBrowser for help on using the repository browser.