--- old/usr/src/cmd/printf/printf.c	Fri May  9 12:12:12 2014
+++ new/usr/src/cmd/printf/printf.c	Fri May  9 12:12:12 2014
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -38,6 +39,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <alloca.h>
+#include <ctype.h>
 #include <locale.h>
 #include <note.h>
 
@@ -51,11 +54,6 @@
 
 #define	PF(f, func) do {						\
 	char *b = NULL;							\
-	int dollar = 0;							\
-	if (*f == '$') 	{						\
-		dollar++;						\
-		*f = '%';						\
-	} 								\
 	if (havewidth)							\
 		if (haveprec)						\
 			(void) asprintf(&b, f, fieldwidth, precision, func); \
@@ -69,8 +67,6 @@
 		(void) fputs(b, stdout);				\
 		free(b);						\
 	}								\
-	if (dollar)							\
-		*f = '$';						\
 _NOTE(CONSTCOND) } while (0)
 
 static int	 asciicode(void);
@@ -85,15 +81,18 @@
 static char	*mknum(char *, char);
 static void	 usage(void);
 
+static const char digits[] = "0123456789";
+
 static int  myargc;
 static char **myargv;
 static char **gargv;
+static char **maxargv;
 
 int
 main(int argc, char *argv[])
 {
 	size_t len;
-	int chopped, end, rval;
+	int end, rval;
 	char *format, *fmt, *start;
 
 	(void) setlocale(LC_ALL, "");
@@ -125,12 +124,12 @@
 	 * up the format string.
 	 */
 	fmt = format = *argv;
-	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
+	(void) escape(fmt, 1, &len);	/* backslash interpretation */
 	rval = end = 0;
 	gargv = ++argv;
 
 	for (;;) {
-		char **maxargv = gargv;
+		maxargv = gargv;
 
 		myargv = gargv;
 		for (myargc = 0; gargv[myargc]; myargc++)
@@ -163,7 +162,7 @@
 			return (1);
 		}
 		(void) fwrite(start, 1, PTRDIFF(fmt, start), stdout);
-		if (chopped || !*gargv)
+		if (!*gargv)
 			return (rval);
 		/* Restart at the beginning of the format string. */
 		fmt = format;
@@ -174,57 +173,119 @@
 
 
 static char *
-doformat(char *start, int *rval)
+doformat(char *fmt, int *rval)
 {
 	static const char skip1[] = "#'-+ 0";
-	static const char skip2[] = "0123456789";
-	char *fmt;
 	int fieldwidth, haveprec, havewidth, mod_ldbl, precision;
 	char convch, nextch;
+	char *start;
+	char **fargv;
+	char *dptr;
+	int l;
 
-	fmt = start + 1;
+	start = alloca(strlen(fmt) + 1);
 
+	dptr = start;
+	*dptr++ = '%';
+	*dptr = 0;
+
+	fmt++;
+
 	/* look for "n$" field index specifier */
-	fmt += strspn(fmt, skip2);
-	if ((*fmt == '$') && (fmt != (start + 1))) {
-		int idx = atoi(start + 1);
+	l = strspn(fmt, digits);
+	if ((l > 0) && (fmt[l] == '$')) {
+		int idx = atoi(fmt);
 		if (idx <= myargc) {
 			gargv = &myargv[idx - 1];
 		} else {
 			gargv = &myargv[myargc];
 		}
-		start = fmt;
-		fmt++;
+		if (gargv > maxargv) {
+			maxargv = gargv;
+		}
+		fmt += l + 1;
+
+		/* save format argument */
+		fargv = gargv;
 	} else {
-		fmt = start + 1;
+		fargv = NULL;
 	}
 
 	/* skip to field width */
-	fmt += strspn(fmt, skip1);
+	while (strchr(skip1, *fmt) != NULL) {
+		*dptr++ = *fmt++;
+		*dptr = 0;
+	}
+
+
 	if (*fmt == '*') {
+
+		fmt++;
+		l = strspn(fmt, digits);
+		if ((l > 0) && (fmt[l] == '$')) {
+			int idx = atoi(fmt);
+			if (idx <= myargc) {
+				gargv = &myargv[idx - 1];
+			} else {
+				gargv = &myargv[myargc];
+			}
+			fmt += l + 1;
+		}
+
 		if (getint(&fieldwidth))
 			return (NULL);
+		if (gargv > maxargv) {
+			maxargv = gargv;
+		}
 		havewidth = 1;
-		++fmt;
+
+		*dptr++ = '*';
+		*dptr = 0;
 	} else {
 		havewidth = 0;
 
 		/* skip to possible '.', get following precision */
-		fmt += strspn(fmt, skip2);
+		while (isdigit(*fmt)) {
+			*dptr++ = *fmt++;
+			*dptr = 0;
+		}
 	}
+
 	if (*fmt == '.') {
 		/* precision present? */
-		++fmt;
+		fmt++;
+		*dptr++ = '.';
+
 		if (*fmt == '*') {
+
+			fmt++;
+			l = strspn(fmt, digits);
+			if ((l > 0) && (fmt[l] == '$')) {
+				int idx = atoi(fmt);
+				if (idx <= myargc) {
+					gargv = &myargv[idx - 1];
+				} else {
+					gargv = &myargv[myargc];
+				}
+				fmt += l + 1;
+			}
+
 			if (getint(&precision))
 				return (NULL);
+			if (gargv > maxargv) {
+				maxargv = gargv;
+			}
 			haveprec = 1;
-			++fmt;
+			*dptr++ = '*';
+			*dptr = 0;
 		} else {
 			haveprec = 0;
 
 			/* skip to conversion char */
-			fmt += strspn(fmt, skip2);
+			while (isdigit(*fmt)) {
+				*dptr++ = *fmt++;
+				*dptr = 0;
+			}
 		}
 	} else
 		haveprec = 0;
@@ -232,6 +293,8 @@
 		warnx1(_("missing format character"), NULL, NULL);
 		return (NULL);
 	}
+	*dptr++ = *fmt;
+	*dptr = 0;
 
 	/*
 	 * Look for a length modifier.  POSIX doesn't have these, so
@@ -254,8 +317,14 @@
 		mod_ldbl = 0;
 	}
 
+	/* save the current arg offset, and set to the format arg */
+	if (fargv != NULL) {
+		gargv = fargv;
+	}
+
 	convch = *fmt;
 	nextch = *++fmt;
+
 	*fmt = '\0';
 	switch (convch) {
 	case 'b': {
@@ -269,13 +338,11 @@
 			return (NULL);
 		}
 		getout = escape(p, 0, &len);
-		*(fmt - 1) = 's';
-		PF(start, p);
-		*(fmt - 1) = 'b';
+		(void) fputs(p, stdout);
 		free(p);
 
 		if (getout)
-			return (fmt);
+			exit(*rval);
 		break;
 	}
 	case 'c': {
@@ -328,6 +395,8 @@
 		return (NULL);
 	}
 	*fmt = nextch;
+
+	/* return the gargv to the next element */
 	return (fmt);
 }
 
@@ -385,9 +454,13 @@
 			*store = '\b';
 			break;
 		case 'c':
-			*store = '\0';
-			*len = PTRDIFF(store, save);
-			return (1);
+			if (!percent) {
+				*store = '\0';
+				*len = PTRDIFF(store, save);
+				return (1);
+			}
+			*store = 'c';
+			break;
 		case 'f':		/* form-feed */
 			*store = '\f';
 			break;
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/pkg/manifests/system-test-utiltest.mf	Fri May  9 12:12:12 2014
@@ -0,0 +1,32 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+#
+
+set name=pkg.fmri value=pkg:/system/test/utiltest@$(PKGVERS)
+set name=pkg.description value="Miscellaneous Utility Unit Tests"
+set name=pkg.summary value="Utility Unit Test Suite"
+set name=info.classification \
+    value=org.opensolaris.category.2008:Development/System
+set name=variant.arch value=$(ARCH)
+dir path=opt/util-tests
+dir path=opt/util-tests/bin
+dir path=opt/util-tests/runfiles
+dir path=opt/util-tests/tests
+file path=opt/util-tests/README mode=0444
+file path=opt/util-tests/bin/utiltest mode=0555
+file path=opt/util-tests/runfiles/default.run mode=0444
+file path=opt/util-tests/tests/printf_test mode=0555
+license lic_CDDL license=lic_CDDL
+depend fmri=system/test/testrunner type=require
--- old/usr/src/test/Makefile	Fri May  9 12:12:12 2014
+++ new/usr/src/test/Makefile	Fri May  9 12:12:12 2014
@@ -11,10 +11,11 @@
 
 #
 # Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
 #
 
 .PARALLEL: $(SUBDIRS)
 
-SUBDIRS = os-tests test-runner zfs-tests
+SUBDIRS = os-tests test-runner util-tests zfs-tests
 
 include Makefile.com
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,20 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = cmd runfiles tests doc
+
+include $(SRC)/test/Makefile.com
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/cmd/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,38 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/test/Makefile.com
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+ROOTBIN = $(ROOTOPTPKG)/bin
+
+PROGS = utiltest
+
+CMDS = $(PROGS:%=$(ROOTBIN)/%)
+$(CMDS) := FILEMODE = 0555
+
+all lint clean clobber:
+
+install: $(CMDS)
+
+$(CMDS): $(ROOTBIN)
+
+$(ROOTBIN):
+	$(INS.dir)
+
+$(ROOTBIN)/%: %.ksh
+	$(INS.rename)
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/cmd/utiltest.ksh	Fri May  9 12:12:12 2014
@@ -0,0 +1,61 @@
+#!/usr/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+export MY_TESTS="/opt/util-tests"
+runner="/opt/test-runner/bin/run"
+
+function fail
+{
+	echo $1
+	exit ${2:-1}
+}
+
+function find_runfile
+{
+	typeset distro=
+	if [[ -d /opt/delphix && -h /etc/delphix/version ]]; then
+		distro=delphix
+	elif [[ 0 -ne $(grep -c OpenIndiana /etc/release 2>/dev/null) ]]; then
+		distro=openindiana
+	elif [[ 0 -ne $(grep -c OmniOS /etc/release 2>/dev/null) ]]; then
+		distro=omnios
+	elif [[ -f $MY_TESTS/runfiles/default.run ]]; then
+		# optional catch-all
+		distro=default
+	fi
+
+	[[ -n $distro ]] && echo $MY_TESTS/runfiles/$distro.run
+}
+
+while getopts c: c; do
+	case $c in
+	'c')
+		runfile=$OPTARG
+		[[ -f $runfile ]] || fail "Cannot read file: $runfile"
+		;;
+	esac
+done
+shift $((OPTIND - 1))
+
+[[ -z $runfile ]] && runfile=$(find_runfile)
+[[ -z $runfile ]] && fail "Couldn't determine distro"
+
+$runner -c $runfile
+
+exit $?
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/doc/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,36 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+
+READMES = README
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+
+FILES = $(READMES:%=$(ROOTOPTPKG)/%)
+$(FILES) := FILEMODE = 0444
+
+all: $(READMES)
+
+install: $(ROOTOPTPKG) $(FILES)
+
+clean lint clobber:
+
+$(ROOTOPTPKG):
+	$(INS.dir)
+
+$(ROOTOPTPKG)/%: %
+	$(INS.file)
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/doc/README	Fri May  9 12:12:12 2014
@@ -0,0 +1,65 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+Utils Unit Test Suite README
+
+1. What the Utils Unit Test Suite tests
+2. Building and installing the Utils Unit Test Suite
+3. Running the Utils Unit Test Suite
+4. Test results
+
+--------------------------------------------------------------------------------
+
+1. What the Utils Unit Test Suite tests
+
+The Utils unit test suite is for testing standard shell / POSIX utilities.
+For example utilities such as "printf" are tested.
+
+2. Building and installing the Utils Unit Test Suite
+
+The Utils Unit Test Suite runs under the testrunner framework (which can be
+installed as pkg:/system/test/testrunner). To build both the Utils Unit Test
+Suite and the testrunner without running a full nightly:
+
+	build_machine$ bldenv [-d] <your_env_file>
+	build_machine$ cd $SRC/test
+	build_machine$ dmake install
+	build_machine$ cd $SRC/pkg
+	build_machine$ dmake install
+
+Then set the publisher on the test machine to point to your repository and
+install the Utils Unit Test Suite.
+
+	test_machine# pkg install pkg:/system/test/utiltest
+
+Note, the framework will be installed automatically, as the Utils Unit Test
+Suite depends on it.
+
+3. Running the Utils Unit Test Suite
+
+The pre-requisites for running the OS Unit Test Suite are:
+	- Any user may perform these tests.
+
+Once the pre-requisites are satisfied, simply run the ostest script:
+
+	test_machine$ /opt/util-tests/bin/utiltest
+
+4. Test results
+
+While the OS Unit Test Suite is running, one informational line is printed at
+the end of each test, and a results summary is printed at the end of the run.
+The results summary includes the location of the complete logs, which is of the
+form /var/tmp/test_results/<ISO 8601 date>.
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/runfiles/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,40 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+
+SRCS = default.run
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+RUNFILES = $(ROOTOPTPKG)/runfiles
+
+CMDS = $(SRCS:%=$(RUNFILES)/%)
+$(CMDS) := FILEMODE = 0444
+
+all: $(SRCS)
+
+install: $(CMDS)
+
+clean lint clobber:
+
+$(CMDS): $(RUNFILES) $(SRCS)
+
+$(RUNFILES):
+	$(INS.dir)
+
+$(RUNFILES)/%: %
+	$(INS.file)
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/runfiles/default.run	Fri May  9 12:12:12 2014
@@ -0,0 +1,26 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copryight 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+[DEFAULT]
+pre =
+verbose = False
+quiet = False
+timeout = 60
+post =
+outputdir = /var/tmp/test_results
+
+[/opt/util-tests/tests/printf_test]
+
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/tests/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,19 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+SUBDIRS = printf
+
+include $(SRC)/test/Makefile.com
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/tests/printf/Makefile	Fri May  9 12:12:12 2014
@@ -0,0 +1,38 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+PROG = printf_test
+
+ROOTOPTPKG = $(ROOT)/opt/util-tests
+TESTDIR = $(ROOTOPTPKG)/tests
+
+CMDS = $(PROG:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+all lint clean clobber:
+
+install: all $(CMDS)
+
+$(CMDS): $(TESTDIR) $(PROG).ksh
+
+$(TESTDIR):
+	$(INS.dir)
+
+$(TESTDIR)/%: %.ksh
+	$(INS.rename)
--- /dev/null	Fri May  9 12:12:12 2014
+++ new/usr/src/test/util-tests/tests/printf/printf_test.ksh	Fri May  9 12:12:12 2014
@@ -0,0 +1,193 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+PRINTF=${PRINTF:=/usr/bin/printf}
+
+test_start() {
+	print "TEST STARTING ${1}: ${2}"
+}
+
+test_pass() {
+	print "TEST PASS: ${1}"
+}
+
+test_fail() {
+	print "TEST FAIL: ${1}: ${2}"
+	exit -1
+}
+
+checkrv() {
+	if [[ $? -ne 0 ]]; then
+		test_fail $1 "exit failure"
+	fi
+}
+
+compare() {
+	if [[ "$2" != "$3" ]]; then
+		test_fail $1 "compare mismatch, got [$2] expected [$3]"
+	fi
+}
+
+typeset -A tests=()
+
+
+typeset -A tests[01]=()
+tests[01][desc]="hexadecimal lowercase"
+tests[01][format]='%04x'
+tests[01][args]="255"
+tests[01][result]="00ff"
+
+typeset -A tests[02]=()
+tests[02][desc]="hexadecimal 32-bit" 
+tests[02][format]='%08x'
+tests[02][args]='65537'
+tests[02][result]=00010001
+
+typeset -A tests[03]=()
+tests[03][desc]="multiple arguments"
+tests[03][format]='%d %s '
+tests[03][args]="1 one 2 two 3 three"
+tests[03][result]='1 one 2 two 3 three '
+
+typeset -A tests[04]=()
+tests[04][desc]="variable position parameters"
+tests[04][format]='%2$s %1$d '
+tests[04][args]="1 one 2 two 3 three"
+tests[04][result]='one 1 two 2 three 3 '
+
+typeset -A tests[05]=()
+tests[05][desc]="width"
+tests[05][format]='%10s'
+tests[05][args]="abcdef"
+tests[05][result]='    abcdef'
+
+typeset -A tests[06]=()
+tests[06][desc]="width and precision"
+tests[06][format]='%10.3s'
+tests[06][args]="abcdef"
+tests[06][result]='       abc'
+
+typeset -A tests[07]=()
+tests[07][desc]="variable width and precision"
+tests[07][format]='%*.*s'
+tests[07][args]="10 3 abcdef"
+tests[07][result]='       abc'
+
+typeset -A tests[08]=()
+tests[08][desc]="variable position width and precision"
+tests[08][format]='%2$*1$.*3$s'
+tests[08][args]="10 abcdef 3"
+tests[08][result]='       abc'
+
+typeset -A tests[09]=()
+tests[09][desc]="multi variable position width and precision"
+tests[09][format]='%2$*1$.*3$s'
+tests[09][args]="10 abcdef 3 5 xyz 1"
+tests[09][result]='       abc    x'
+
+typeset -A tests[10]=()
+tests[10][desc]="decimal from hex"
+tests[10][format]='%d '
+tests[10][args]="0x1000 0XA"
+tests[10][result]='4096 10 '
+
+typeset -A tests[11]=()
+tests[11][desc]="negative dec (64-bit)"
+tests[11][format]='%x'
+tests[11][args]="-1"
+tests[11][result]='ffffffffffffffff'
+
+typeset -A tests[12]=()
+tests[12][desc]="float (basic)"
+tests[12][format]='%f'
+tests[12][args]="3.14"
+tests[12][result]='3.140000'
+
+typeset -A tests[12]=()
+tests[12][desc]="float precision"
+tests[12][format]='%.2f'
+tests[12][args]="3.14159"
+tests[12][result]='3.14'
+
+typeset -A tests[13]=()
+tests[13][desc]="left justify"
+tests[13][format]='%-5d'
+tests[13][args]="45"
+tests[13][result]='45   '
+
+typeset -A tests[14]=()
+tests[14][desc]="newlines"
+tests[14][format]='%s\n%s\n%s'
+tests[14][args]="one two three"
+tests[14][result]='one
+two
+three'
+
+typeset -A tests[15]=()
+tests[15][desc]="embedded octal escape"
+tests[15][format]='%s\41%s'
+tests[15][args]="one two"
+tests[15][result]='one!two'
+
+typeset -A tests[16]=()
+tests[16][desc]="backslash string (%b)"
+tests[16][format]='%b'
+tests[16][args]='\0101\0102\0103'
+tests[16][result]='ABC'
+
+typeset -A tests[17]=()
+tests[17][desc]="backslash c in %b"
+tests[17][format]='%b%s'
+tests[17][args]='\0101\cone two'
+tests[17][result]='A'
+
+typeset -A tests[18]=()
+tests[18][desc]="backslash octal in format"
+tests[18][format]='HI\1120K\0112tabbed\11again'
+tests[18][args]=
+tests[18][result]='HIJ0K	2tabbed	again'
+
+typeset -A tests[19]=()
+tests[19][desc]="backslash octal in %b"
+tests[19][format]="%b"
+tests[19][args]='HI\0112K\011tabbed'
+tests[19][result]='HIJK	tabbed'
+
+typeset -A tests[20]=()
+tests[20][desc]="numeric %d and ASCII conversions"
+tests[20][format]='%d '
+tests[20][args]="3 +3 -3 \"3 \"+ '-"
+tests[20][result]='3 3 -3 51 43 45 '
+
+#debug=yes
+
+for i in "${!tests[@]}"; do
+	t=test_$i
+	desc=${tests[$i][desc]}
+	format=${tests[$i][format]}
+	args="${tests[$i][args]}"
+	result=${tests[$i][result]}
+	
+	test_start $t "${tests[$i][desc]}"
+	[[ -n "$debug" ]] && echo $PRINTF "$format" "${args[@]}"
+	comp=$($PRINTF "$format" ${args[@]})
+	checkrv $t 
+	[[ -n "$debug" ]] && echo "got [$comp]"
+	good=$result
+	compare $t "$comp" "$good"
+	test_pass $t
+done
