Eliminate code duplication in time printing, reduce a few static buffers

   text	   data	    bss	    dec	    hex	filename
 238454	    664	  28772	 267890	  41672	strace.before
 238106	    664	  28676	 267446	  414b6	strace

* defs.h: Add TIMESPEC_TEXT_BUFSIZE and TIMEVAL_TEXT_BUFSIZE defines.
Add 'int special' parameter to sprinttv().
* time.c (sprinttv): Add 'int special' parameter, and use it
similarly to 'int special' parameter of printtv_bitness().
(printtv_bitness): Use sprinttv() instead of duplicating its code.
(print_timespec): Use sprint_timespec() instead of duplicating
its code.
* desc.c (decode_select): Use TIMEVAL_TEXT_BUFSIZE instead of 128
when checking remaining buffer size.
* net.c (sys_recvmsg): Use TIMESPEC_TEXT_BUFSIZE instead of 128
for static buffer size.
* stream.c (decode_poll): Use TIMESPEC_TEXT_BUFSIZE instead of 128
when checking remaining buffer size.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/defs.h b/defs.h
index e0b9e51..de5bd4b 100644
--- a/defs.h
+++ b/defs.h
@@ -628,8 +628,10 @@
 extern void printnum_int(struct tcb *, long, const char *);
 extern void printpath(struct tcb *, long);
 extern void printpathn(struct tcb *, long, int);
+#define TIMESPEC_TEXT_BUFSIZE (sizeof(long)*3 * 2 + sizeof("{%u, %u}"))
+#define TIMEVAL_TEXT_BUFSIZE  TIMESPEC_TEXT_BUFSIZE
 extern void printtv_bitness(struct tcb *, long, enum bitness_t, int);
-extern char *sprinttv(struct tcb *, long, enum bitness_t, char *);
+extern char *sprinttv(char *, struct tcb *, long, enum bitness_t, int special);
 extern void print_timespec(struct tcb *, long);
 extern void sprint_timespec(char *, struct tcb *, long);
 #ifdef HAVE_SIGINFO_T
diff --git a/desc.c b/desc.c
index a41514a..8207ba0 100644
--- a/desc.c
+++ b/desc.c
@@ -584,9 +584,9 @@
 #ifdef LINUX
 		/* This contains no useful information on SunOS.  */
 		if (args[4]) {
-			if (outptr < end_outstr - 128) {
+			if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
 				outptr += sprintf(outptr, "%sleft ", sep);
-				outptr = sprinttv(tcp, args[4], bitness, outptr);
+				outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
 			}
 		}
 #endif /* LINUX */
diff --git a/net.c b/net.c
index 4e8df10..67acfb8 100644
--- a/net.c
+++ b/net.c
@@ -1753,12 +1753,16 @@
 int
 sys_recvmmsg(struct tcb *tcp)
 {
-	static char str[128];
-	if (entering(tcp)) {
+	/* +5 chars are for "left " prefix */
+	static char str[5 + TIMESPEC_TEXT_BUFSIZE];
 
+	if (entering(tcp)) {
 		tprintf("%ld, ", tcp->u_arg[0]);
 		if (verbose(tcp)) {
 			sprint_timespec(str, tcp, tcp->u_arg[4]);
+			/* Abusing tcp->auxstr as temp storage.
+			 * Will be used and freed on syscall exit.
+			 */
 			tcp->auxstr = strdup(str);
 		} else {
 			tprintf("%#lx, %ld, ", tcp->u_arg[1], tcp->u_arg[2]);
@@ -1790,8 +1794,7 @@
 		if (!verbose(tcp))
 			return 0;
 		/* timeout on exit */
-		strcpy(str, "left ");
-		sprint_timespec(str + strlen(str), tcp, tcp->u_arg[4]);
+		sprint_timespec(stpcpy(str, "left "), tcp, tcp->u_arg[4]);
 		tcp->auxstr = str;
 		return RVAL_STR;
 	}
diff --git a/stream.c b/stream.c
index 56f07c6..d946b22 100644
--- a/stream.c
+++ b/stream.c
@@ -404,7 +404,7 @@
 
 		*outptr = '\0';
 		if (pts) {
-			if (outptr < end_outstr - 128) {
+			if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) {
 				outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
 				sprint_timespec(outptr, tcp, pts);
 			}
diff --git a/time.c b/time.c
index daceeaa..875d224 100644
--- a/time.c
+++ b/time.c
@@ -66,54 +66,13 @@
 void
 printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
 {
-	if (addr == 0)
-		tprints("NULL");
-	else if (!verbose(tcp))
-		tprintf("%#lx", addr);
-	else {
-		int rc;
-
-		if (bitness == BITNESS_32
-#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
-		    || personality_wordsize[current_personality] == 4
-#endif
-			)
-		{
-			struct timeval32 tv;
-
-			rc = umove(tcp, addr, &tv);
-			if (rc >= 0) {
-				if (special && tv.tv_sec == 0 &&
-				    tv.tv_usec == UTIME_NOW)
-					tprints("UTIME_NOW");
-				else if (special && tv.tv_sec == 0 &&
-					 tv.tv_usec == UTIME_OMIT)
-					tprints("UTIME_OMIT");
-				else
-					tprint_timeval32(tcp, &tv);
-			}
-		} else {
-			struct timeval tv;
-
-			rc = umove(tcp, addr, &tv);
-			if (rc >= 0) {
-				if (special && tv.tv_sec == 0 &&
-				    tv.tv_usec == UTIME_NOW)
-					tprints("UTIME_NOW");
-				else if (special && tv.tv_sec == 0 &&
-					 tv.tv_usec == UTIME_OMIT)
-					tprints("UTIME_OMIT");
-				else
-					tprint_timeval(tcp, &tv);
-			}
-		}
-		if (rc < 0)
-			tprints("{...}");
-	}
+	char buf[TIMEVAL_TEXT_BUFSIZE];
+	sprinttv(buf, tcp, addr, bitness, special);
+	tprints(buf);
 }
 
 char *
-sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
+sprinttv(char *buf, struct tcb *tcp, long addr, enum bitness_t bitness, int special)
 {
 	int rc;
 
@@ -132,56 +91,46 @@
 		struct timeval32 tv;
 
 		rc = umove(tcp, addr, &tv);
-		if (rc >= 0)
+		if (rc >= 0) {
+			if (special && tv.tv_sec == 0) {
+				if (tv.tv_usec == UTIME_NOW)
+					return stpcpy(buf, "UTIME_NOW");
+				if (tv.tv_usec == UTIME_OMIT)
+					return stpcpy(buf, "UTIME_OMIT");
+			}
 			return buf + sprintf(buf, "{%u, %u}",
 				tv.tv_sec, tv.tv_usec);
+		}
 	} else {
 		struct timeval tv;
 
 		rc = umove(tcp, addr, &tv);
-		if (rc >= 0)
+		if (rc >= 0) {
+			if (special && tv.tv_sec == 0) {
+				if (tv.tv_usec == UTIME_NOW)
+					return stpcpy(buf, "UTIME_NOW");
+				if (tv.tv_usec == UTIME_OMIT)
+					return stpcpy(buf, "UTIME_OMIT");
+			}
 			return buf + sprintf(buf, "{%lu, %lu}",
 				(unsigned long) tv.tv_sec,
 				(unsigned long) tv.tv_usec);
+		}
 	}
 
 	return stpcpy(buf, "{...}");
 }
 
-void print_timespec(struct tcb *tcp, long addr)
+void
+print_timespec(struct tcb *tcp, long addr)
 {
-	if (addr == 0)
-		tprints("NULL");
-	else if (!verbose(tcp))
-		tprintf("%#lx", addr);
-	else {
-		int rc;
-
-#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
-		if (personality_wordsize[current_personality] == 4) {
-			struct timeval32 tv;
-
-			rc = umove(tcp, addr, &tv);
-			if (rc >= 0)
-				tprintf("{%u, %u}",
-					tv.tv_sec, tv.tv_usec);
-		} else
-#endif
-		{
-			struct timespec ts;
-
-			rc = umove(tcp, addr, &ts);
-			if (rc >= 0)
-				tprintf("{%lu, %lu}",
-					(unsigned long) ts.tv_sec,
-					(unsigned long) ts.tv_nsec);
-		}
-		if (rc < 0)
-			tprints("{...}");
-	}
+	char buf[TIMESPEC_TEXT_BUFSIZE];
+	sprint_timespec(buf, tcp, addr);
+	tprints(buf);
 }
 
-void sprint_timespec(char *buf, struct tcb *tcp, long addr)
+void
+sprint_timespec(char *buf, struct tcb *tcp, long addr)
 {
 	if (addr == 0)
 		strcpy(buf, "NULL");