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:
		@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user