diff options
-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 | } |