ash: a bunch of trivial simplifications

Also, in a few places made code more reliable wrt large sizeof(int)
and sizeof(arith_t)..

function                                             old     new   delta
sprint_status48                                        -     143    +143
newline_and_flush                                      -      56     +56
showjob                                              365     382     +17
parse_command                                       1440    1443      +3
cmdputs                                              334     332      -2
cmdloop                                              434     429      -5
showjobs                                              70      64      -6
fg_bgcmd                                             296     290      -6
ash_vmsg                                             159     153      -6
ash_main                                            1487    1481      -6
jobscmd                                               94      82     -12
getoptscmd                                           687     632     -55
outcslow                                              56       -     -56
sprint_status                                        156       -    -156
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 2/8 up/down: 219/-310)          Total: -91 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/shell/ash.c b/shell/ash.c
index 42c9125..b34dcc1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -537,11 +537,12 @@
 	INT_ON;
 }
 
+/* Was called outcslow(c,FILE*), but c was always '\n' */
 static void
-outcslow(int c, FILE *dest)
+newline_and_flush(FILE *dest)
 {
 	INT_OFF;
-	putc(c, dest);
+	putc('\n', dest);
 	fflush(dest);
 	INT_ON;
 }
@@ -1202,7 +1203,7 @@
 			fprintf(stderr, "line %d: ", startlinno);
 	}
 	vfprintf(stderr, msg, ap);
-	outcslow('\n', stderr);
+	newline_and_flush(stderr);
 }
 
 /*
@@ -3336,6 +3337,7 @@
 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
+#define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
 
 /*
  * A job structure contains information about a job.  A job is either a
@@ -3850,7 +3852,7 @@
 	psend = jp->ps + jp->nprocs;
 	for (ps = jp->ps + 1; ps < psend; ps++)
 		printf(" | %s", ps->ps_cmd);
-	outcslow('\n', stdout);
+	newline_and_flush(stdout);
 	flush_stdout_stderr();
 }
 
@@ -3910,7 +3912,7 @@
 #endif
 
 static int
-sprint_status(char *s, int status, int sigonly)
+sprint_status48(char *s, int status, int sigonly)
 {
 	int col;
 	int st;
@@ -3935,14 +3937,12 @@
 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
 		col = fmtstr(s, 32, strsignal(st));
 		if (WCOREDUMP(status)) {
-			col += fmtstr(s + col, 16, " (core dumped)");
+			strcpy(s + col, " (core dumped)");
+			col += sizeof(" (core dumped)")-1;
 		}
 	} else if (!sigonly) {
 		st = WEXITSTATUS(status);
-		if (st)
-			col = fmtstr(s, 16, "Done(%d)", st);
-		else
-			col = fmtstr(s, 16, "Done");
+		col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
 	}
  out:
 	return col;
@@ -4031,7 +4031,7 @@
 		char s[48 + 1];
 		int len;
 
-		len = sprint_status(s, status, 1);
+		len = sprint_status48(s, status, 1);
 		if (len) {
 			s[len] = '\n';
 			s[len + 1] = '\0';
@@ -4052,13 +4052,14 @@
 
 #if JOBS
 static void
-showjob(FILE *out, struct job *jp, int mode)
+showjob(struct job *jp, int mode)
 {
 	struct procstat *ps;
 	struct procstat *psend;
 	int col;
 	int indent_col;
-	char s[80];
+	char s[16 + 16 + 48];
+	FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
 
 	ps = jp->ps;
 
@@ -4088,7 +4089,7 @@
 		int status = psend[-1].ps_status;
 		if (jp->state == JOBSTOPPED)
 			status = jp->stopstatus;
-		col += sprint_status(s + col, status, 0);
+		col += sprint_status48(s + col, status, 0);
 	}
 	/* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
 
@@ -4115,7 +4116,7 @@
 				ps->ps_cmd
 		);
 	} while (++ps != psend);
-	outcslow('\n', out);
+	newline_and_flush(out);
 
 	jp->changed = 0;
 
@@ -4130,7 +4131,7 @@
  * statuses have changed since the last call to showjobs.
  */
 static void
-showjobs(FILE *out, int mode)
+showjobs(int mode)
 {
 	struct job *jp;
 
@@ -4142,7 +4143,7 @@
 
 	for (jp = curjob; jp; jp = jp->prev_job) {
 		if (!(mode & SHOW_CHANGED) || jp->changed) {
-			showjob(out, jp, mode);
+			showjob(jp, mode);
 		}
 	}
 }
@@ -4163,10 +4164,10 @@
 	argv = argptr;
 	if (*argv) {
 		do
-			showjob(stdout, getjob(*argv, 0), mode);
+			showjob(getjob(*argv, 0), mode);
 		while (*++argv);
 	} else {
-		showjobs(stdout, mode);
+		showjobs(mode);
 	}
 
 	return 0;
@@ -5572,8 +5573,8 @@
 {
 	int len;
 
-	expdest = makestrspace(32, expdest);
-	len = fmtstr(expdest, 32, ARITH_FMT, num);
+	expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
+	len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
 	STADJUST(len, expdest);
 	return len;
 }
@@ -10352,9 +10353,11 @@
 	char c = '?';
 	int done = 0;
 	int err = 0;
-	char s[12];
+	char sbuf[2];
 	char **optnext;
 
+	sbuf[1] = '\0';
+
 	if (*param_optind < 1)
 		return 1;
 	optnext = optfirst + *param_optind - 1;
@@ -10381,9 +10384,9 @@
 	for (q = optstr; *q != c;) {
 		if (*q == '\0') {
 			if (optstr[0] == ':') {
-				s[0] = c;
-				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
+				sbuf[0] = c;
+				/*sbuf[1] = '\0'; - already is */
+				err |= setvarsafe("OPTARG", sbuf, 0);
 			} else {
 				fprintf(stderr, "Illegal option -%c\n", c);
 				unsetvar("OPTARG");
@@ -10398,9 +10401,9 @@
 	if (*++q == ':') {
 		if (*p == '\0' && (p = *optnext) == NULL) {
 			if (optstr[0] == ':') {
-				s[0] = c;
-				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
+				sbuf[0] = c;
+				/*sbuf[1] = '\0'; - already is */
+				err |= setvarsafe("OPTARG", sbuf, 0);
 				c = ':';
 			} else {
 				fprintf(stderr, "No arg for -%c option\n", c);
@@ -10419,11 +10422,10 @@
  out:
 	*optoff = p ? p - *(optnext - 1) : -1;
 	*param_optind = optnext - optfirst + 1;
-	fmtstr(s, sizeof(s), "%d", *param_optind);
-	err |= setvarsafe("OPTIND", s, VNOFUNC);
-	s[0] = c;
-	s[1] = '\0';
-	err |= setvarsafe(optvar, s, 0);
+	err |= setvarsafe("OPTIND", itoa(*param_optind), VNOFUNC);
+	sbuf[0] = c;
+	/*sbuf[1] = '\0'; - already is */
+	err |= setvarsafe(optvar, sbuf, 0);
 	if (err) {
 		*param_optind = 1;
 		*optoff = -1;
@@ -12119,7 +12121,7 @@
 		setstackmark(&smark);
 #if JOBS
 		if (doing_jobctl)
-			showjobs(stderr, SHOW_CHANGED);
+			showjobs(SHOW_CHANGED|SHOW_STDERR);
 #endif
 		inter = 0;
 		if (iflag && top) {
@@ -13143,7 +13145,7 @@
 			exitshell();
 		}
 		if (e == EXINT) {
-			outcslow('\n', stderr);
+			newline_and_flush(stderr);
 		}
 
 		popstackmark(&smark);