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>
This commit is contained in:
parent
b7e61e3e4a
commit
82ea67fbfa
@ -1226,6 +1226,7 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str)
|
||||
bc_vec_pushZeroByte(v);
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING
|
||||
static void bc_vec_concat(BcVec *v, const char *str)
|
||||
{
|
||||
size_t len, slen;
|
||||
@ -1240,6 +1241,7 @@ static void bc_vec_concat(BcVec *v, const char *str)
|
||||
|
||||
v->len = len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *bc_vec_item(const BcVec *v, size_t idx)
|
||||
{
|
||||
@ -1326,29 +1328,21 @@ static size_t bc_map_index(const BcVec *v, const void *ptr)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int push_input_byte(BcVec *vec, char c)
|
||||
static int bad_input_byte(char c)
|
||||
{
|
||||
if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'?
|
||||
|| c > 0x7e
|
||||
) {
|
||||
// Bad chars on this line, ignore entire line
|
||||
bc_error_fmt("illegal character 0x%02x", c);
|
||||
return 1;
|
||||
}
|
||||
bc_vec_pushByte(vec, (char)c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: it _appends_ data from the stdin to vec.
|
||||
static void bc_read_line(BcVec *vec)
|
||||
{
|
||||
bool bad_chars;
|
||||
|
||||
do {
|
||||
int c;
|
||||
|
||||
bad_chars = 0;
|
||||
bc_vec_pop_all(vec);
|
||||
|
||||
again:
|
||||
fflush_and_check();
|
||||
|
||||
#if ENABLE_FEATURE_BC_SIGNALS
|
||||
@ -1359,6 +1353,7 @@ static void bc_read_line(BcVec *vec)
|
||||
// GNU dc says "Interrupt!"
|
||||
fputs("\ninterrupted execution\n", stderr);
|
||||
}
|
||||
|
||||
# if ENABLE_FEATURE_EDITING
|
||||
if (G_ttyin) {
|
||||
int n, i;
|
||||
@ -1371,15 +1366,20 @@ static void bc_read_line(BcVec *vec)
|
||||
}
|
||||
i = 0;
|
||||
for (;;) {
|
||||
c = line_buf[i++];
|
||||
char c = line_buf[i++];
|
||||
if (!c) break;
|
||||
bad_chars |= push_input_byte(vec, c);
|
||||
if (bad_input_byte(c)) goto again;
|
||||
}
|
||||
bc_vec_concat(vec, line_buf);
|
||||
# undef line_buf
|
||||
} else
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
int c;
|
||||
bool bad_chars = 0;
|
||||
size_t len = vec->len;
|
||||
|
||||
IF_FEATURE_BC_SIGNALS(errno = 0;)
|
||||
do {
|
||||
c = fgetc(stdin);
|
||||
@ -1399,10 +1399,15 @@ static void bc_read_line(BcVec *vec)
|
||||
// printf 'print 123' | bc - fails (syntax error)
|
||||
break;
|
||||
}
|
||||
bad_chars |= push_input_byte(vec, c);
|
||||
bad_chars |= bad_input_byte(c);
|
||||
bc_vec_pushByte(vec, (char)c);
|
||||
} while (c != '\n');
|
||||
if (bad_chars) {
|
||||
// Bad chars on this line, ignore entire line
|
||||
vec->len = len;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
} while (bad_chars);
|
||||
|
||||
bc_vec_pushZeroByte(vec);
|
||||
}
|
||||
@ -5374,12 +5379,12 @@ static BC_STATUS zbc_program_read(void)
|
||||
|
||||
f = bc_program_func(BC_PROG_READ);
|
||||
bc_vec_pop_all(&f->code);
|
||||
bc_char_vec_init(&buf);
|
||||
|
||||
sv_file = G.prog.file;
|
||||
G.prog.file = NULL;
|
||||
G.in_read = 1;
|
||||
|
||||
bc_char_vec_init(&buf);
|
||||
bc_read_line(&buf);
|
||||
|
||||
bc_parse_create(&parse, BC_PROG_READ);
|
||||
@ -7039,7 +7044,7 @@ err:
|
||||
static BC_STATUS zbc_vm_stdin(void)
|
||||
{
|
||||
BcStatus s;
|
||||
BcVec buf, buffer;
|
||||
BcVec buffer;
|
||||
size_t str;
|
||||
bool comment;
|
||||
|
||||
@ -7047,8 +7052,6 @@ static BC_STATUS zbc_vm_stdin(void)
|
||||
bc_lex_file(&G.prs.l);
|
||||
|
||||
bc_char_vec_init(&buffer);
|
||||
bc_char_vec_init(&buf);
|
||||
bc_vec_pushZeroByte(&buffer);
|
||||
|
||||
// This loop is complex because the vm tries not to send any lines that end
|
||||
// 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)
|
||||
comment = false;
|
||||
str = 0;
|
||||
for (;;) {
|
||||
size_t prevlen = buffer.len;
|
||||
char *string;
|
||||
|
||||
bc_read_line(&buf);
|
||||
if (buf.len <= 1) // "" buf means EOF
|
||||
bc_read_line(&buffer);
|
||||
// No more input means EOF
|
||||
if (buffer.len <= prevlen + 1) // (we expect +1 for NUL byte)
|
||||
break;
|
||||
|
||||
string = buf.v;
|
||||
string = buffer.v + prevlen;
|
||||
while (*string) {
|
||||
char c = *string;
|
||||
if (string == buf.v || string[-1] != '\\') {
|
||||
if (string == buffer.v || string[-1] != '\\') {
|
||||
// checking applet type is cheaper than accessing sbgn/send
|
||||
if (IS_BC) // bc: sbgn = send = '"'
|
||||
str ^= (c == '"');
|
||||
@ -7089,17 +7094,20 @@ static BC_STATUS zbc_vm_stdin(void)
|
||||
string++;
|
||||
}
|
||||
}
|
||||
bc_vec_concat(&buffer, buf.v);
|
||||
if (str || comment)
|
||||
if (str || comment) {
|
||||
buffer.len--; // backstep over the trailing NUL byte
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for backslash+newline.
|
||||
// we do not check that last char is '\n' -
|
||||
// if it is not, then it's EOF, and looping back
|
||||
// to bc_read_line() will detect it:
|
||||
string -= 2;
|
||||
if (string >= buf.v && *string == '\\')
|
||||
if (string >= buffer.v && *string == '\\') {
|
||||
buffer.len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
s = zbc_vm_process(buffer.v);
|
||||
if (s) {
|
||||
@ -7121,7 +7129,6 @@ static BC_STATUS zbc_vm_stdin(void)
|
||||
s = bc_error("comment end could not be found");
|
||||
}
|
||||
|
||||
bc_vec_free(&buf);
|
||||
bc_vec_free(&buffer);
|
||||
RETURN_STATUS(s);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user