diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-08-05 15:42:29 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-08-05 18:11:15 +0200 |
commit | 19358cc31317dca4642417066c1445ce00438e18 (patch) | |
tree | 08b922ba5bbfe026432dc814341bc855892f90dd /shell/shell_common.c | |
parent | fd6f295a98956b7f495ba09a56528ef9e0d51398 (diff) | |
download | busybox-w32-19358cc31317dca4642417066c1445ce00438e18.tar.gz busybox-w32-19358cc31317dca4642417066c1445ce00438e18.tar.bz2 busybox-w32-19358cc31317dca4642417066c1445ce00438e18.zip |
ash,hush: fold shell_builtin_read() way-too-many params into a struct param
function old new delta
getoptscmd 587 584 -3
readcmd 240 224 -16
shell_builtin_read 1426 1399 -27
builtin_read 210 182 -28
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-74) Total: -74 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell/shell_common.c')
-rw-r--r-- | shell/shell_common.c | 55 |
1 files changed, 26 insertions, 29 deletions
diff --git a/shell/shell_common.c b/shell/shell_common.c index 0a07296f3..f2bf5ab65 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c | |||
@@ -46,16 +46,7 @@ int FAST_FUNC is_well_formed_var_name(const char *s, char terminator) | |||
46 | //Here we can simply store "VAR=" at buffer start and store read data directly | 46 | //Here we can simply store "VAR=" at buffer start and store read data directly |
47 | //after "=", then pass buffer to setvar() to consume. | 47 | //after "=", then pass buffer to setvar() to consume. |
48 | const char* FAST_FUNC | 48 | const char* FAST_FUNC |
49 | shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | 49 | shell_builtin_read(struct builtin_read_params *params) |
50 | char **argv, | ||
51 | const char *ifs, | ||
52 | int read_flags, | ||
53 | const char *opt_n, | ||
54 | const char *opt_p, | ||
55 | const char *opt_t, | ||
56 | const char *opt_u, | ||
57 | const char *opt_d | ||
58 | ) | ||
59 | { | 50 | { |
60 | struct pollfd pfd[1]; | 51 | struct pollfd pfd[1]; |
61 | #define fd (pfd[0].fd) /* -u FD */ | 52 | #define fd (pfd[0].fd) /* -u FD */ |
@@ -70,9 +61,13 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
70 | int bufpos; /* need to be able to hold -1 */ | 61 | int bufpos; /* need to be able to hold -1 */ |
71 | int startword; | 62 | int startword; |
72 | smallint backslash; | 63 | smallint backslash; |
64 | char **argv; | ||
65 | const char *ifs; | ||
66 | int read_flags; | ||
73 | 67 | ||
74 | errno = err = 0; | 68 | errno = err = 0; |
75 | 69 | ||
70 | argv = params->argv; | ||
76 | pp = argv; | 71 | pp = argv; |
77 | while (*pp) { | 72 | while (*pp) { |
78 | if (!is_well_formed_var_name(*pp, '\0')) { | 73 | if (!is_well_formed_var_name(*pp, '\0')) { |
@@ -84,29 +79,29 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
84 | } | 79 | } |
85 | 80 | ||
86 | nchars = 0; /* if != 0, -n is in effect */ | 81 | nchars = 0; /* if != 0, -n is in effect */ |
87 | if (opt_n) { | 82 | if (params->opt_n) { |
88 | nchars = bb_strtou(opt_n, NULL, 10); | 83 | nchars = bb_strtou(params->opt_n, NULL, 10); |
89 | if (nchars < 0 || errno) | 84 | if (nchars < 0 || errno) |
90 | return "invalid count"; | 85 | return "invalid count"; |
91 | /* note: "-n 0": off (bash 3.2 does this too) */ | 86 | /* note: "-n 0": off (bash 3.2 does this too) */ |
92 | } | 87 | } |
93 | 88 | ||
94 | end_ms = 0; | 89 | end_ms = 0; |
95 | if (opt_t && !ENABLE_FEATURE_SH_READ_FRAC) { | 90 | if (params->opt_t && !ENABLE_FEATURE_SH_READ_FRAC) { |
96 | end_ms = bb_strtou(opt_t, NULL, 10); | 91 | end_ms = bb_strtou(params->opt_t, NULL, 10); |
97 | if (errno) | 92 | if (errno) |
98 | return "invalid timeout"; | 93 | return "invalid timeout"; |
99 | if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ | 94 | if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ |
100 | end_ms = UINT_MAX / 2048; | 95 | end_ms = UINT_MAX / 2048; |
101 | end_ms *= 1000; | 96 | end_ms *= 1000; |
102 | } | 97 | } |
103 | if (opt_t && ENABLE_FEATURE_SH_READ_FRAC) { | 98 | if (params->opt_t && ENABLE_FEATURE_SH_READ_FRAC) { |
104 | /* bash 4.3 (maybe earlier) supports -t N.NNNNNN */ | 99 | /* bash 4.3 (maybe earlier) supports -t N.NNNNNN */ |
105 | char *p; | 100 | char *p; |
106 | /* Eat up to three fractional digits */ | 101 | /* Eat up to three fractional digits */ |
107 | int frac_digits = 3 + 1; | 102 | int frac_digits = 3 + 1; |
108 | 103 | ||
109 | end_ms = bb_strtou(opt_t, &p, 10); | 104 | end_ms = bb_strtou(params->opt_t, &p, 10); |
110 | if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ | 105 | if (end_ms > UINT_MAX / 2048) /* be safely away from overflow */ |
111 | end_ms = UINT_MAX / 2048; | 106 | end_ms = UINT_MAX / 2048; |
112 | 107 | ||
@@ -128,13 +123,13 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
128 | } | 123 | } |
129 | 124 | ||
130 | fd = STDIN_FILENO; | 125 | fd = STDIN_FILENO; |
131 | if (opt_u) { | 126 | if (params->opt_u) { |
132 | fd = bb_strtou(opt_u, NULL, 10); | 127 | fd = bb_strtou(params->opt_u, NULL, 10); |
133 | if (fd < 0 || errno) | 128 | if (fd < 0 || errno) |
134 | return "invalid file descriptor"; | 129 | return "invalid file descriptor"; |
135 | } | 130 | } |
136 | 131 | ||
137 | if (opt_t && end_ms == 0) { | 132 | if (params->opt_t && end_ms == 0) { |
138 | /* "If timeout is 0, read returns immediately, without trying | 133 | /* "If timeout is 0, read returns immediately, without trying |
139 | * to read any data. The exit status is 0 if input is available | 134 | * to read any data. The exit status is 0 if input is available |
140 | * on the specified file descriptor, non-zero otherwise." | 135 | * on the specified file descriptor, non-zero otherwise." |
@@ -147,14 +142,16 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
147 | return (const char *)(uintptr_t)(r <= 0); | 142 | return (const char *)(uintptr_t)(r <= 0); |
148 | } | 143 | } |
149 | 144 | ||
150 | if (opt_p && isatty(fd)) { | 145 | if (params->opt_p && isatty(fd)) { |
151 | fputs(opt_p, stderr); | 146 | fputs(params->opt_p, stderr); |
152 | fflush_all(); | 147 | fflush_all(); |
153 | } | 148 | } |
154 | 149 | ||
150 | ifs = params->ifs; | ||
155 | if (ifs == NULL) | 151 | if (ifs == NULL) |
156 | ifs = defifs; | 152 | ifs = defifs; |
157 | 153 | ||
154 | read_flags = params->read_flags; | ||
158 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { | 155 | if (nchars || (read_flags & BUILTIN_READ_SILENT)) { |
159 | tcgetattr(fd, &tty); | 156 | tcgetattr(fd, &tty); |
160 | old_tty = tty; | 157 | old_tty = tty; |
@@ -181,11 +178,11 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
181 | retval = (const char *)(uintptr_t)0; | 178 | retval = (const char *)(uintptr_t)0; |
182 | startword = 1; | 179 | startword = 1; |
183 | backslash = 0; | 180 | backslash = 0; |
184 | if (opt_t) | 181 | if (params->opt_t) |
185 | end_ms += (unsigned)monotonic_ms(); | 182 | end_ms += (unsigned)monotonic_ms(); |
186 | buffer = NULL; | 183 | buffer = NULL; |
187 | bufpos = 0; | 184 | bufpos = 0; |
188 | delim = opt_d ? *opt_d : '\n'; | 185 | delim = params->opt_d ? params->opt_d[0] : '\n'; |
189 | do { | 186 | do { |
190 | char c; | 187 | char c; |
191 | int timeout; | 188 | int timeout; |
@@ -194,7 +191,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
194 | buffer = xrealloc(buffer, bufpos + 0x101); | 191 | buffer = xrealloc(buffer, bufpos + 0x101); |
195 | 192 | ||
196 | timeout = -1; | 193 | timeout = -1; |
197 | if (opt_t) { | 194 | if (params->opt_t) { |
198 | timeout = end_ms - (unsigned)monotonic_ms(); | 195 | timeout = end_ms - (unsigned)monotonic_ms(); |
199 | /* ^^^^^^^^^^^^^ all values are unsigned, | 196 | /* ^^^^^^^^^^^^^ all values are unsigned, |
200 | * wrapping math is used here, good even if | 197 | * wrapping math is used here, good even if |
@@ -246,7 +243,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
246 | * without variable names (bash compat). | 243 | * without variable names (bash compat). |
247 | * Thus, "read" and "read REPLY" are not the same. | 244 | * Thus, "read" and "read REPLY" are not the same. |
248 | */ | 245 | */ |
249 | if (!opt_d && argv[0]) { | 246 | if (!params->opt_d && argv[0]) { |
250 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */ | 247 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */ |
251 | const char *is_ifs = strchr(ifs, c); | 248 | const char *is_ifs = strchr(ifs, c); |
252 | if (startword && is_ifs) { | 249 | if (startword && is_ifs) { |
@@ -261,7 +258,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
261 | if (argv[1] != NULL && is_ifs) { | 258 | if (argv[1] != NULL && is_ifs) { |
262 | buffer[bufpos] = '\0'; | 259 | buffer[bufpos] = '\0'; |
263 | bufpos = 0; | 260 | bufpos = 0; |
264 | setvar(*argv, buffer); | 261 | params->setvar(*argv, buffer); |
265 | argv++; | 262 | argv++; |
266 | /* can we skip one non-space ifs char? (2: yes) */ | 263 | /* can we skip one non-space ifs char? (2: yes) */ |
267 | startword = isspace(c) ? 2 : 1; | 264 | startword = isspace(c) ? 2 : 1; |
@@ -313,14 +310,14 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), | |||
313 | } | 310 | } |
314 | 311 | ||
315 | /* Use the remainder as a value for the next variable */ | 312 | /* Use the remainder as a value for the next variable */ |
316 | setvar(*argv, buffer); | 313 | params->setvar(*argv, buffer); |
317 | /* Set the rest to "" */ | 314 | /* Set the rest to "" */ |
318 | while (*++argv) | 315 | while (*++argv) |
319 | setvar(*argv, ""); | 316 | params->setvar(*argv, ""); |
320 | } else { | 317 | } else { |
321 | /* Note: no $IFS removal */ | 318 | /* Note: no $IFS removal */ |
322 | buffer[bufpos] = '\0'; | 319 | buffer[bufpos] = '\0'; |
323 | setvar("REPLY", buffer); | 320 | params->setvar("REPLY", buffer); |
324 | } | 321 | } |
325 | 322 | ||
326 | ret: | 323 | ret: |