bc: propagate fixed arguments into callees

Looks like there is only one "BcProgram" object, &G.prog.

function                                             old     new   delta
bc_program_exec                                     4401    4523    +122
bc_program_execStr                                   579     606     +27
bc_program_read                                      323     342     +19
bc_args                                               83      97     +14
bc_vm_process                                        327     323      -4
bc_num_ulong                                          95      85     -10
dc_main                                               62      48     -14
bc_main                                               62      48     -14
bc_vm_run                                           2317    1923    -394
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/5 up/down: 182/-436)         Total: -254 bytes
   text	   data	    bss	    dec	    hex	filename
 989028	    485	   7296	 996809	  f35c9	busybox_old
 988774	    485	   7296	 996555	  f34cb	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 72afb68..117318b 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -790,7 +790,6 @@
 
 static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx);
 static BcStatus bc_program_reset(BcProgram *p, BcStatus s);
-static BcStatus bc_program_exec(BcProgram *p);
 
 #define BC_FLAG_X (1 << 0)
 #define BC_FLAG_W (1 << 1)
@@ -813,8 +812,6 @@
 #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
 
 struct globals {
-	BcParseInit init;
-	BcParseExpr exp;
 	char sbgn;
 	char send;
 
@@ -1416,14 +1413,13 @@
 	return s;
 }
 
-static void bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files)
+static void bc_args(int argc, char **argv)
 {
 	int i;
-	bool do_exit = false;
 
 	GETOPT_RESET();
 #if ENABLE_FEATURE_BC_LONG_OPTIONS
-	*flags = getopt32long(argv, "xwvsqli",
+	G.flags = getopt32long(argv, "xwvsqli",
 		"extended-register\0" No_argument "x"
 		"warn\0"              No_argument "w"
 		"version\0"           No_argument "v"
@@ -1433,15 +1429,14 @@
 		"interactive\0"       No_argument "i"
 	);
 #else
-	*flags = getopt32(argv, "xwvsqli");
+	G.flags = getopt32(argv, "xwvsqli");
 #endif
 
-	if ((*flags) & BC_FLAG_V) bc_vm_info();
-	if (do_exit) exit(0);
+	if (G.flags & BC_FLAG_V) bc_vm_info();
 	// should not be necessary, getopt32() handles this??
 	//if (argv[optind] && !strcmp(argv[optind], "--")) ++optind;
 
-	for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i);
+	for (i = optind; i < argc; ++i) bc_vec_push(&G.files, argv + i);
 }
 
 static void bc_num_setToZero(BcNum *n, size_t scale)
@@ -5452,8 +5447,10 @@
 	return s;
 }
 
-static BcStatus bc_program_read(BcProgram *p)
+static BcStatus bc_program_read(void)
 {
+	BcProgram *p = &G.prog;
+
 	BcStatus s;
 	BcParse parse;
 	BcVec buf;
@@ -5477,6 +5474,7 @@
 
 	s = bc_parse_text(&parse, buf.v);
 	if (s) goto exec_err;
+/// replace by IS_BC selection
 	s = p->parse_expr(&parse, BC_PARSE_NOREAD);
 	if (s) goto exec_err;
 
@@ -6356,8 +6354,10 @@
 	return s;
 }
 
-static BcStatus bc_program_nquit(BcProgram *p)
+static BcStatus bc_program_nquit(void)
 {
+	BcProgram *p = &G.prog;
+
 	BcStatus s;
 	BcResult *opnd;
 	BcNum *num = NULL;
@@ -6380,9 +6380,11 @@
 	return s;
 }
 
-static BcStatus bc_program_execStr(BcProgram *p, char *code, size_t *bgn,
+static BcStatus bc_program_execStr(char *code, size_t *bgn,
                                    bool cond)
 {
+	BcProgram *p = &G.prog;
+
 	BcStatus s = BC_STATUS_SUCCESS;
 	BcResult *r;
 	char **str;
@@ -6451,10 +6453,11 @@
 	f = bc_vec_item(&p->fns, fidx);
 
 	if (f->code.len == 0) {
-
+/// replace by IS_BC selection
 		p->parse_init(&prs, p, fidx);
 		s = bc_parse_text(&prs, *str);
 		if (s) goto err;
+/// replace by IS_BC selection
 		s = p->parse_expr(&prs, BC_PARSE_NOCALL);
 		if (s) goto err;
 
@@ -6511,88 +6514,6 @@
 	return s;
 }
 
-static void bc_program_free(BcProgram *p)
-{
-	bc_num_free(&p->ib);
-	bc_num_free(&p->ob);
-	bc_num_free(&p->hexb);
-#if ENABLE_DC
-	bc_num_free(&p->strmb);
-#endif
-	bc_vec_free(&p->fns);
-	bc_vec_free(&p->fn_map);
-	bc_vec_free(&p->vars);
-	bc_vec_free(&p->var_map);
-	bc_vec_free(&p->arrs);
-	bc_vec_free(&p->arr_map);
-	bc_vec_free(&p->strs);
-	bc_vec_free(&p->consts);
-	bc_vec_free(&p->results);
-	bc_vec_free(&p->stack);
-	bc_num_free(&p->last);
-	bc_num_free(&p->zero);
-	bc_num_free(&p->one);
-}
-
-static void bc_program_init(BcProgram *p, size_t line_len, BcParseInit init,
-                            BcParseExpr expr)
-{
-	size_t idx;
-	BcInstPtr ip;
-
-	memset(p, 0, sizeof(BcProgram));
-	memset(&ip, 0, sizeof(BcInstPtr));
-
-	p->nchars = p->scale = 0;
-	p->len = line_len;
-	p->parse_init = init;
-	p->parse_expr = expr;
-
-	bc_num_init(&p->ib, BC_NUM_DEF_SIZE);
-	bc_num_ten(&p->ib);
-	p->ib_t = 10;
-
-	bc_num_init(&p->ob, BC_NUM_DEF_SIZE);
-	bc_num_ten(&p->ob);
-	p->ob_t = 10;
-
-	bc_num_init(&p->hexb, BC_NUM_DEF_SIZE);
-	bc_num_ten(&p->hexb);
-	p->hexb.num[0] = 6;
-
-#if ENABLE_DC
-	bc_num_init(&p->strmb, BC_NUM_DEF_SIZE);
-	bc_num_ulong2num(&p->strmb, UCHAR_MAX + 1);
-#endif
-
-	bc_num_init(&p->last, BC_NUM_DEF_SIZE);
-	bc_num_zero(&p->last);
-
-	bc_num_init(&p->zero, BC_NUM_DEF_SIZE);
-	bc_num_zero(&p->zero);
-
-	bc_num_init(&p->one, BC_NUM_DEF_SIZE);
-	bc_num_one(&p->one);
-
-	bc_vec_init(&p->fns, sizeof(BcFunc), bc_func_free);
-	bc_map_init(&p->fn_map);
-
-	bc_program_addFunc(p, xstrdup(bc_func_main), &idx);
-	bc_program_addFunc(p, xstrdup(bc_func_read), &idx);
-
-	bc_vec_init(&p->vars, sizeof(BcVec), bc_vec_free);
-	bc_map_init(&p->var_map);
-
-	bc_vec_init(&p->arrs, sizeof(BcVec), bc_vec_free);
-	bc_map_init(&p->arr_map);
-
-	bc_vec_init(&p->strs, sizeof(char *), bc_string_free);
-	bc_vec_init(&p->consts, sizeof(char *), bc_string_free);
-	bc_vec_init(&p->results, sizeof(BcResult), bc_result_free);
-	bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL);
-	bc_vec_push(&p->stack, &ip);
-}
-
 static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx)
 {
 	BcStatus s;
@@ -6652,8 +6573,10 @@
 	return s;
 }
 
-static BcStatus bc_program_exec(BcProgram *p)
+static BcStatus bc_program_exec(void)
 {
+	BcProgram *p = &G.prog;
+
 	BcStatus s = BC_STATUS_SUCCESS;
 	size_t idx;
 	BcResult r, *ptr;
@@ -6731,7 +6654,7 @@
 
 			case BC_INST_READ:
 			{
-				s = bc_program_read(p);
+				s = bc_program_read();
 				break;
 			}
 
@@ -6869,7 +6792,7 @@
 			case BC_INST_EXEC_COND:
 			{
 				cond = inst == BC_INST_EXEC_COND;
-				s = bc_program_execStr(p, code, &ip->idx, cond);
+				s = bc_program_execStr(code, &ip->idx, cond);
 				break;
 			}
 
@@ -6955,7 +6878,7 @@
 
 			case BC_INST_NQUIT:
 			{
-				s = bc_program_nquit(p);
+				s = bc_program_nquit();
 				break;
 			}
 #endif // ENABLE_DC
@@ -7032,7 +6955,7 @@
 			++buf;
 	}
 
-	bc_args((int) v.len, (char **) v.v, &G.flags, &G.files);
+	bc_args((int) v.len, (char **) v.v);
 
 	bc_vec_free(&v);
 }
@@ -7093,7 +7016,7 @@
 	}
 
 	if (BC_PARSE_CAN_EXEC(&G.prs)) {
-		s = bc_program_exec(&G.prog);
+		s = bc_program_exec();
 		if (!s && G.tty) fflush(stdout);
 		if (s && s != BC_STATUS_QUIT)
 			s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0);
@@ -7229,7 +7152,7 @@
 		while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs);
 
 		if (s) return s;
-		s = bc_program_exec(&G.prog);
+		s = bc_program_exec();
 		if (s) return s;
 	}
 #endif
@@ -7246,6 +7169,30 @@
 	return s;
 }
 
+#if ENABLE_FEATURE_CLEAN_UP
+static void bc_program_free(BcProgram *p)
+{
+	bc_num_free(&p->ib);
+	bc_num_free(&p->ob);
+	bc_num_free(&p->hexb);
+# if ENABLE_DC
+	bc_num_free(&p->strmb);
+# endif
+	bc_vec_free(&p->fns);
+	bc_vec_free(&p->fn_map);
+	bc_vec_free(&p->vars);
+	bc_vec_free(&p->var_map);
+	bc_vec_free(&p->arrs);
+	bc_vec_free(&p->arr_map);
+	bc_vec_free(&p->strs);
+	bc_vec_free(&p->consts);
+	bc_vec_free(&p->results);
+	bc_vec_free(&p->stack);
+	bc_num_free(&p->last);
+	bc_num_free(&p->zero);
+	bc_num_free(&p->one);
+}
+
 static void bc_vm_free(void)
 {
 	bc_vec_free(&G.files);
@@ -7253,9 +7200,74 @@
 	bc_parse_free(&G.prs);
 	free(G.env_args);
 }
+#endif
+
+static void bc_program_init(size_t line_len)
+{
+	size_t idx;
+	BcInstPtr ip;
+
+	/* memset(&G.prog, 0, sizeof(G.prog)); - already is */
+	memset(&ip, 0, sizeof(BcInstPtr));
+
+	/* G.prog.nchars = G.prog.scale = 0; - already is */
+	G.prog.len = line_len;
+	if (IS_BC) {
+		G.prog.parse_init = bc_parse_init;
+		G.prog.parse_expr = bc_parse_expression;
+	} else {
+		G.prog.parse_init = dc_parse_init;
+		G.prog.parse_expr = dc_parse_expr;
+	}
+
+	bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE);
+	bc_num_ten(&G.prog.ib);
+	G.prog.ib_t = 10;
+
+	bc_num_init(&G.prog.ob, BC_NUM_DEF_SIZE);
+	bc_num_ten(&G.prog.ob);
+	G.prog.ob_t = 10;
+
+	bc_num_init(&G.prog.hexb, BC_NUM_DEF_SIZE);
+	bc_num_ten(&G.prog.hexb);
+	G.prog.hexb.num[0] = 6;
+
+#if ENABLE_DC
+	bc_num_init(&G.prog.strmb, BC_NUM_DEF_SIZE);
+	bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1);
+#endif
+
+	bc_num_init(&G.prog.last, BC_NUM_DEF_SIZE);
+	bc_num_zero(&G.prog.last);
+
+	bc_num_init(&G.prog.zero, BC_NUM_DEF_SIZE);
+	bc_num_zero(&G.prog.zero);
+
+	bc_num_init(&G.prog.one, BC_NUM_DEF_SIZE);
+	bc_num_one(&G.prog.one);
+
+	bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free);
+	bc_map_init(&G.prog.fn_map);
+
+	bc_program_addFunc(&G.prog, xstrdup(bc_func_main), &idx);
+	bc_program_addFunc(&G.prog, xstrdup(bc_func_read), &idx);
+
+	bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free);
+	bc_map_init(&G.prog.var_map);
+
+	bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free);
+	bc_map_init(&G.prog.arr_map);
+
+	bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);
+	bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);
+	bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
+	bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL);
+	bc_vec_push(&G.prog.stack, &ip);
+}
 
 static void bc_vm_init(const char *env_len)
 {
+	BcParseInit init;
 	size_t len = bc_vm_envLen(env_len);
 
 #if ENABLE_FEATURE_BC_SIGNALS
@@ -7265,12 +7277,16 @@
 	bc_vec_init(&G.files, sizeof(char *), NULL);
 
 	if (IS_BC) {
-		G.flags |= BC_FLAG_S * (getenv("POSIXLY_CORRECT") != NULL);
+		if (getenv("POSIXLY_CORRECT"))
+			G.flags |= BC_FLAG_S;
 		bc_vm_envArgs();
+		init = bc_parse_init;
+	} else {
+		init = dc_parse_init;
 	}
 
-	bc_program_init(&G.prog, len, G.init, G.exp);
-	G.init(&G.prs, &G.prog, BC_PROG_MAIN);
+	bc_program_init(len);
+	init(&G.prs, &G.prog, BC_PROG_MAIN);
 }
 
 static BcStatus bc_vm_run(int argc, char *argv[],
@@ -7279,7 +7295,7 @@
 	BcStatus st;
 
 	bc_vm_init(env_len);
-	bc_args(argc, argv, &G.flags, &G.files);
+	bc_args(argc, argv);
 
 	G.ttyin = isatty(0);
 	G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1);
@@ -7287,7 +7303,9 @@
 	if (G.ttyin && !(G.flags & BC_FLAG_Q)) bc_vm_info();
 	st = bc_vm_exec();
 
+#if ENABLE_FEATURE_CLEAN_UP
 	bc_vm_free();
+#endif
 	return st;
 }
 
@@ -7296,8 +7314,6 @@
 int bc_main(int argc, char **argv)
 {
 	INIT_G();
-	G.init = bc_parse_init;
-	G.exp = bc_parse_expression;
 	G.sbgn = G.send = '"';
 
 	return bc_vm_run(argc, argv, "BC_LINE_LENGTH");
@@ -7309,8 +7325,6 @@
 int dc_main(int argc, char **argv)
 {
 	INIT_G();
-	G.init = dc_parse_init;
-	G.exp = dc_parse_expr;
 	G.sbgn = '[';
 	G.send = ']';