[git commit] bc: eliminate BC_STATUS_INPUT_EOF

Denys Vlasenko vda.linux at googlemail.com
Wed Dec 5 14:43:35 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=d4744adf35c678554e609a74eeebc7b7603ee25d
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
fflush_and_check                                       -      36     +36
bc_num_a                                             445     456     +11
bc_num_ulong                                          85      95     +10
bc_vm_run                                           1978    1984      +6
bc_num_s                                             246     252      +6
bc_err_msgs                                          192     188      -4
quit                                                  38      32      -6
bc_vm_process                                        139     132      -7
bc_program_reset                                     172     159     -13
bc_parse_create                                      192     175     -17
bc_read_line                                         349     311     -38
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/6 up/down: 69/-85)            Total: -16 bytes
   text	   data	    bss	    dec	    hex	filename
 987844	    485	   7296	 995625	  f3129	busybox_old
 987828	    485	   7296	 995609	  f3119	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/bc.c | 48 +++++++++++++++++++++++++++---------------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/miscutils/bc.c b/miscutils/bc.c
index c3d118417..c819decff 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -171,7 +171,7 @@ typedef enum BcStatus {
 	BC_STATUS_SUCCESS,
 
 //	BC_STATUS_ALLOC_ERR,
-	BC_STATUS_INPUT_EOF,
+//	BC_STATUS_INPUT_EOF,
 	BC_STATUS_BIN_FILE,
 //	BC_STATUS_PATH_IS_DIR,
 
@@ -240,7 +240,7 @@ typedef enum BcStatus {
 static const char *const bc_err_msgs[] = {
 	NULL,
 //	"memory allocation error",
-	"I/O error",
+//	"I/O error",
 	"file is not text:",
 //	"path is a directory:",
 
@@ -875,6 +875,7 @@ struct globals {
 
 	smallint tty;
 	smallint ttyin;
+	smallint eof;
 } FIX_ALIASING;
 #define G (*ptr_to_globals)
 #define INIT_G() do { \
@@ -1121,11 +1122,20 @@ static const char bc_lib[] = {
 };
 #endif // ENABLE_BC
 
+static void fflush_and_check(void)
+{
+	fflush_all();
+	if (ferror(stdout) || ferror(stderr))
+		bb_perror_msg_and_die("output error");
+}
+
 static void quit(void) NORETURN;
 static void quit(void)
 {
-	fflush_all();
-	exit(ferror(stdout) || ferror(stderr));
+	if (ferror(stdin))
+		bb_perror_msg_and_die("input error");
+	fflush_and_check();
+	exit(0);
 }
 
 static void bc_vec_grow(BcVec *v, size_t n)
@@ -1284,7 +1294,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
 
 	bc_vec_npop(vec, vec->len);
 
-	fflush(stdout);
+	fflush_and_check();
 #if ENABLE_FEATURE_BC_SIGNALS
 	if (bb_got_signal) { // ^C was pressed
  intr:
@@ -1297,15 +1307,12 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
 #endif
 	if (G.ttyin && !G_posix)
 		fputs(prompt, stderr);
-	fflush(stderr);
+	fflush_and_check();
 
 #if ENABLE_FEATURE_BC_SIGNALS
 	errno = 0;
 #endif
 	do {
-		if (ferror(stdout) || ferror(stderr))
-			bb_perror_msg_and_die("output error");
-
 		i = fgetc(stdin);
 
 		if (i == EOF) {
@@ -1318,8 +1325,12 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt)
 			}
 #endif
 			if (ferror(stdin))
-				bb_perror_msg_and_die("input error");
-			return BC_STATUS_INPUT_EOF;
+				quit(); // this emits error message
+			G.eof = 1;
+			// Note: EOF does not append '\n', therefore:
+			// printf 'print 123\n' | bc - works
+			// printf 'print 123' | bc   - fails (syntax error)
+			break;
 		}
 
 		c = (signed char) i;
@@ -3627,7 +3638,7 @@ static void bc_parse_create(BcParse *p, size_t func,
 	bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
 
 	p->parse = parse;
-	p->auto_part = (p->nbraces = 0);
+	// p->auto_part = p->nbraces = 0; - already is
 	bc_parse_updateFunc(p, func);
 }
 
@@ -6473,9 +6484,9 @@ static BcStatus bc_program_reset(BcStatus s)
 	if (!s || s == BC_STATUS_EXEC_SIGNAL) {
 		if (!G.ttyin)
 			quit();
-		fflush(stdout);
+		fflush_and_check(); // make sure buffered stdout is printed
 		fputs(bc_program_ready_msg, stderr);
-		fflush(stderr);
+		fflush_and_check();
 		s = BC_STATUS_SUCCESS;
 	}
 
@@ -6910,7 +6921,7 @@ static BcStatus bc_vm_process(const char *text)
 
 	if (BC_PARSE_CAN_EXEC(&G.prs)) {
 		s = bc_program_exec();
-		fflush(stdout);
+		fflush_and_check();
 		if (s)
 			s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0);
 	}
@@ -6961,7 +6972,7 @@ static BcStatus bc_vm_stdin(void)
 	// with a backslash to the parser. The reason for that is because the parser
 	// treats a backslash+newline combo as whitespace, per the bc spec. In that
 	// case, and for strings and comments, the parser will expect more stuff.
-	while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
+	while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) {
 
 		char *string = buf.v;
 
@@ -7012,11 +7023,6 @@ static BcStatus bc_vm_stdin(void)
 
 	if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0);
 
-	// INPUT_EOF will always happen when stdin is
-	// closed. It's not a problem in that case.
-	if (s == BC_STATUS_INPUT_EOF)
-		s = BC_STATUS_SUCCESS;
-
 	if (str)
 		s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f,
 		                G.prs.l.line);


More information about the busybox-cvs mailing list