diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-13 19:23:45 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-13 19:24:42 +0100 |
| commit | 82ea67fbfa98cfd6b8b422db764cb8c97fc3ea7b (patch) | |
| tree | f9e67fbed671b7a5474720cf7f2733d1d2c53b1b /miscutils | |
| parent | b7e61e3e4adc774d18b6377cdd6434dd7ce0c2be (diff) | |
| download | busybox-w32-82ea67fbfa98cfd6b8b422db764cb8c97fc3ea7b.tar.gz busybox-w32-82ea67fbfa98cfd6b8b422db764cb8c97fc3ea7b.tar.bz2 busybox-w32-82ea67fbfa98cfd6b8b422db764cb8c97fc3ea7b.zip | |
bc: change bc_read_line() and zbc_vm_stdin() to avoid double buffers
function old new delta
bc_read_line 129 124 -5
bc_vm_run 523 433 -90
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-95) Total: -95 bytes
text data bss dec hex filename
980445 485 7296 988226 f1442 busybox_old
980350 485 7296 988131 f13e3 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/bc.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index bc2947161..7c4dfbb20 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -1226,6 +1226,7 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str) | |||
| 1226 | bc_vec_pushZeroByte(v); | 1226 | bc_vec_pushZeroByte(v); |
| 1227 | } | 1227 | } |
| 1228 | 1228 | ||
| 1229 | #if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING | ||
| 1229 | static void bc_vec_concat(BcVec *v, const char *str) | 1230 | static void bc_vec_concat(BcVec *v, const char *str) |
| 1230 | { | 1231 | { |
| 1231 | size_t len, slen; | 1232 | size_t len, slen; |
| @@ -1240,6 +1241,7 @@ static void bc_vec_concat(BcVec *v, const char *str) | |||
| 1240 | 1241 | ||
| 1241 | v->len = len; | 1242 | v->len = len; |
| 1242 | } | 1243 | } |
| 1244 | #endif | ||
| 1243 | 1245 | ||
| 1244 | static void *bc_vec_item(const BcVec *v, size_t idx) | 1246 | static void *bc_vec_item(const BcVec *v, size_t idx) |
| 1245 | { | 1247 | { |
| @@ -1326,29 +1328,21 @@ static size_t bc_map_index(const BcVec *v, const void *ptr) | |||
| 1326 | } | 1328 | } |
| 1327 | #endif | 1329 | #endif |
| 1328 | 1330 | ||
| 1329 | static int push_input_byte(BcVec *vec, char c) | 1331 | static int bad_input_byte(char c) |
| 1330 | { | 1332 | { |
| 1331 | if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? | 1333 | if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? |
| 1332 | || c > 0x7e | 1334 | || c > 0x7e |
| 1333 | ) { | 1335 | ) { |
| 1334 | // Bad chars on this line, ignore entire line | ||
| 1335 | bc_error_fmt("illegal character 0x%02x", c); | 1336 | bc_error_fmt("illegal character 0x%02x", c); |
| 1336 | return 1; | 1337 | return 1; |
| 1337 | } | 1338 | } |
| 1338 | bc_vec_pushByte(vec, (char)c); | ||
| 1339 | return 0; | 1339 | return 0; |
| 1340 | } | 1340 | } |
| 1341 | 1341 | ||
| 1342 | // Note: it _appends_ data from the stdin to vec. | ||
| 1342 | static void bc_read_line(BcVec *vec) | 1343 | static void bc_read_line(BcVec *vec) |
| 1343 | { | 1344 | { |
| 1344 | bool bad_chars; | 1345 | again: |
| 1345 | |||
| 1346 | do { | ||
| 1347 | int c; | ||
| 1348 | |||
| 1349 | bad_chars = 0; | ||
| 1350 | bc_vec_pop_all(vec); | ||
| 1351 | |||
| 1352 | fflush_and_check(); | 1346 | fflush_and_check(); |
| 1353 | 1347 | ||
| 1354 | #if ENABLE_FEATURE_BC_SIGNALS | 1348 | #if ENABLE_FEATURE_BC_SIGNALS |
| @@ -1359,6 +1353,7 @@ static void bc_read_line(BcVec *vec) | |||
| 1359 | // GNU dc says "Interrupt!" | 1353 | // GNU dc says "Interrupt!" |
| 1360 | fputs("\ninterrupted execution\n", stderr); | 1354 | fputs("\ninterrupted execution\n", stderr); |
| 1361 | } | 1355 | } |
| 1356 | |||
| 1362 | # if ENABLE_FEATURE_EDITING | 1357 | # if ENABLE_FEATURE_EDITING |
| 1363 | if (G_ttyin) { | 1358 | if (G_ttyin) { |
| 1364 | int n, i; | 1359 | int n, i; |
| @@ -1371,15 +1366,20 @@ static void bc_read_line(BcVec *vec) | |||
| 1371 | } | 1366 | } |
| 1372 | i = 0; | 1367 | i = 0; |
| 1373 | for (;;) { | 1368 | for (;;) { |
| 1374 | c = line_buf[i++]; | 1369 | char c = line_buf[i++]; |
| 1375 | if (!c) break; | 1370 | if (!c) break; |
| 1376 | bad_chars |= push_input_byte(vec, c); | 1371 | if (bad_input_byte(c)) goto again; |
| 1377 | } | 1372 | } |
| 1373 | bc_vec_concat(vec, line_buf); | ||
| 1378 | # undef line_buf | 1374 | # undef line_buf |
| 1379 | } else | 1375 | } else |
| 1380 | # endif | 1376 | # endif |
| 1381 | #endif | 1377 | #endif |
| 1382 | { | 1378 | { |
| 1379 | int c; | ||
| 1380 | bool bad_chars = 0; | ||
| 1381 | size_t len = vec->len; | ||
| 1382 | |||
| 1383 | IF_FEATURE_BC_SIGNALS(errno = 0;) | 1383 | IF_FEATURE_BC_SIGNALS(errno = 0;) |
| 1384 | do { | 1384 | do { |
| 1385 | c = fgetc(stdin); | 1385 | c = fgetc(stdin); |
| @@ -1399,10 +1399,15 @@ static void bc_read_line(BcVec *vec) | |||
| 1399 | // printf 'print 123' | bc - fails (syntax error) | 1399 | // printf 'print 123' | bc - fails (syntax error) |
| 1400 | break; | 1400 | break; |
| 1401 | } | 1401 | } |
| 1402 | bad_chars |= push_input_byte(vec, c); | 1402 | bad_chars |= bad_input_byte(c); |
| 1403 | bc_vec_pushByte(vec, (char)c); | ||
| 1403 | } while (c != '\n'); | 1404 | } while (c != '\n'); |
| 1405 | if (bad_chars) { | ||
| 1406 | // Bad chars on this line, ignore entire line | ||
| 1407 | vec->len = len; | ||
| 1408 | goto again; | ||
| 1409 | } | ||
| 1404 | } | 1410 | } |
| 1405 | } while (bad_chars); | ||
| 1406 | 1411 | ||
| 1407 | bc_vec_pushZeroByte(vec); | 1412 | bc_vec_pushZeroByte(vec); |
| 1408 | } | 1413 | } |
| @@ -5374,12 +5379,12 @@ static BC_STATUS zbc_program_read(void) | |||
| 5374 | 5379 | ||
| 5375 | f = bc_program_func(BC_PROG_READ); | 5380 | f = bc_program_func(BC_PROG_READ); |
| 5376 | bc_vec_pop_all(&f->code); | 5381 | bc_vec_pop_all(&f->code); |
| 5377 | bc_char_vec_init(&buf); | ||
| 5378 | 5382 | ||
| 5379 | sv_file = G.prog.file; | 5383 | sv_file = G.prog.file; |
| 5380 | G.prog.file = NULL; | 5384 | G.prog.file = NULL; |
| 5381 | G.in_read = 1; | 5385 | G.in_read = 1; |
| 5382 | 5386 | ||
| 5387 | bc_char_vec_init(&buf); | ||
| 5383 | bc_read_line(&buf); | 5388 | bc_read_line(&buf); |
| 5384 | 5389 | ||
| 5385 | bc_parse_create(&parse, BC_PROG_READ); | 5390 | bc_parse_create(&parse, BC_PROG_READ); |
| @@ -7039,7 +7044,7 @@ err: | |||
| 7039 | static BC_STATUS zbc_vm_stdin(void) | 7044 | static BC_STATUS zbc_vm_stdin(void) |
| 7040 | { | 7045 | { |
| 7041 | BcStatus s; | 7046 | BcStatus s; |
| 7042 | BcVec buf, buffer; | 7047 | BcVec buffer; |
| 7043 | size_t str; | 7048 | size_t str; |
| 7044 | bool comment; | 7049 | bool comment; |
| 7045 | 7050 | ||
| @@ -7047,8 +7052,6 @@ static BC_STATUS zbc_vm_stdin(void) | |||
| 7047 | bc_lex_file(&G.prs.l); | 7052 | bc_lex_file(&G.prs.l); |
| 7048 | 7053 | ||
| 7049 | bc_char_vec_init(&buffer); | 7054 | bc_char_vec_init(&buffer); |
| 7050 | bc_char_vec_init(&buf); | ||
| 7051 | bc_vec_pushZeroByte(&buffer); | ||
| 7052 | 7055 | ||
| 7053 | // This loop is complex because the vm tries not to send any lines that end | 7056 | // This loop is complex because the vm tries not to send any lines that end |
| 7054 | // with a backslash to the parser. The reason for that is because the parser | 7057 | // with a backslash to the parser. The reason for that is because the parser |
| @@ -7058,16 +7061,18 @@ static BC_STATUS zbc_vm_stdin(void) | |||
| 7058 | comment = false; | 7061 | comment = false; |
| 7059 | str = 0; | 7062 | str = 0; |
| 7060 | for (;;) { | 7063 | for (;;) { |
| 7064 | size_t prevlen = buffer.len; | ||
| 7061 | char *string; | 7065 | char *string; |
| 7062 | 7066 | ||
| 7063 | bc_read_line(&buf); | 7067 | bc_read_line(&buffer); |
| 7064 | if (buf.len <= 1) // "" buf means EOF | 7068 | // No more input means EOF |
| 7069 | if (buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) | ||
| 7065 | break; | 7070 | break; |
| 7066 | 7071 | ||
| 7067 | string = buf.v; | 7072 | string = buffer.v + prevlen; |
| 7068 | while (*string) { | 7073 | while (*string) { |
| 7069 | char c = *string; | 7074 | char c = *string; |
| 7070 | if (string == buf.v || string[-1] != '\\') { | 7075 | if (string == buffer.v || string[-1] != '\\') { |
| 7071 | // checking applet type is cheaper than accessing sbgn/send | 7076 | // checking applet type is cheaper than accessing sbgn/send |
| 7072 | if (IS_BC) // bc: sbgn = send = '"' | 7077 | if (IS_BC) // bc: sbgn = send = '"' |
| 7073 | str ^= (c == '"'); | 7078 | str ^= (c == '"'); |
| @@ -7089,17 +7094,20 @@ static BC_STATUS zbc_vm_stdin(void) | |||
| 7089 | string++; | 7094 | string++; |
| 7090 | } | 7095 | } |
| 7091 | } | 7096 | } |
| 7092 | bc_vec_concat(&buffer, buf.v); | 7097 | if (str || comment) { |
| 7093 | if (str || comment) | 7098 | buffer.len--; // backstep over the trailing NUL byte |
| 7094 | continue; | 7099 | continue; |
| 7100 | } | ||
| 7095 | 7101 | ||
| 7096 | // Check for backslash+newline. | 7102 | // Check for backslash+newline. |
| 7097 | // we do not check that last char is '\n' - | 7103 | // we do not check that last char is '\n' - |
| 7098 | // if it is not, then it's EOF, and looping back | 7104 | // if it is not, then it's EOF, and looping back |
| 7099 | // to bc_read_line() will detect it: | 7105 | // to bc_read_line() will detect it: |
| 7100 | string -= 2; | 7106 | string -= 2; |
| 7101 | if (string >= buf.v && *string == '\\') | 7107 | if (string >= buffer.v && *string == '\\') { |
| 7108 | buffer.len--; | ||
| 7102 | continue; | 7109 | continue; |
| 7110 | } | ||
| 7103 | 7111 | ||
| 7104 | s = zbc_vm_process(buffer.v); | 7112 | s = zbc_vm_process(buffer.v); |
| 7105 | if (s) { | 7113 | if (s) { |
| @@ -7121,7 +7129,6 @@ static BC_STATUS zbc_vm_stdin(void) | |||
| 7121 | s = bc_error("comment end could not be found"); | 7129 | s = bc_error("comment end could not be found"); |
| 7122 | } | 7130 | } |
| 7123 | 7131 | ||
| 7124 | bc_vec_free(&buf); | ||
| 7125 | bc_vec_free(&buffer); | 7132 | bc_vec_free(&buffer); |
| 7126 | RETURN_STATUS(s); | 7133 | RETURN_STATUS(s); |
| 7127 | } | 7134 | } |
