summaryrefslogtreecommitdiff
path: root/usr/src/common/util
diff options
context:
space:
mode:
authormyers <none@none>2005-11-17 08:46:01 -0800
committermyers <none@none>2005-11-17 08:46:01 -0800
commit186507a7cf6e4b4155e9ef89631777a96633ac0e (patch)
treede8a9df2499f491b06828c59df3dd7ae6b177e48 /usr/src/common/util
parent3dda9c1f98047ea58eaaa9a0fc08c3a0aabbc0c0 (diff)
downloadillumos-joyent-186507a7cf6e4b4155e9ef89631777a96633ac0e.tar.gz
6328449 acpica: create_d2a_subtree makes nodes for ACPI non-devices
6332549 acpica: update to Intel ACPI CA 20050930 source drop 6333936 vsnprintf: vsnprintf doesn't support 'h' or string-precision modifiers 6335392 psm: psm_common.c incorrectly uses ACPI resource end tags
Diffstat (limited to 'usr/src/common/util')
-rw-r--r--usr/src/common/util/string.c157
1 files changed, 122 insertions, 35 deletions
diff --git a/usr/src/common/util/string.c b/usr/src/common/util/string.c
index e7ce13f19f..fe2388925d 100644
--- a/usr/src/common/util/string.c
+++ b/usr/src/common/util/string.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -65,7 +65,9 @@ vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
{
uint64_t ul, tmp;
char *bufp = buf; /* current buffer pointer */
- int pad, width, ells, base, sign, c;
+ int pad, width, base, sign, c, num;
+ int prec, h_count, l_count, dot_count;
+ int pad_count, transfer_count, left_align;
char *digits, *sp, *bs;
char numbuf[65]; /* sufficient for a 64-bit binary value */
va_list args;
@@ -84,28 +86,64 @@ vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
continue;
}
+ width = prec = 0;
+ left_align = base = sign = 0;
+ h_count = l_count = dot_count = 0;
+ pad = ' ';
+ digits = "0123456789abcdef";
+next_fmt:
if ((c = *fmt++) == '\0')
break;
- for (pad = ' '; c == '0'; c = *fmt++)
- pad = '0';
-
- for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
- width = width * 10 + c - '0';
-
- for (ells = 0; c == 'l'; c = *fmt++)
- ells++;
-
- digits = "0123456789abcdef";
-
if (c >= 'A' && c <= 'Z') {
c += 'a' - 'A';
digits = "0123456789ABCDEF";
}
- base = sign = 0;
-
switch (c) {
+ case '-':
+ left_align++;
+ goto next_fmt;
+ case '0':
+ if (dot_count == 0)
+ pad = '0';
+ /*FALLTHROUGH*/
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ num = 0;
+ for (;;) {
+ num = 10 * num + c - '0';
+ c = *fmt;
+ if (c < '0' || c > '9')
+ break;
+ else
+ fmt++;
+ }
+ if (dot_count > 0)
+ prec = num;
+ else
+ width = num;
+
+ goto next_fmt;
+ case '.':
+ dot_count++;
+ goto next_fmt;
+ case '*':
+ width = (int)va_arg(args, int);
+ goto next_fmt;
+ case 'l':
+ l_count++;
+ goto next_fmt;
+ case 'h':
+ h_count++;
+ goto next_fmt;
case 'd':
sign = 1;
/*FALLTHROUGH*/
@@ -113,7 +151,7 @@ vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
base = 10;
break;
case 'p':
- ells = 1;
+ l_count = 1;
/*FALLTHROUGH*/
case 'x':
base = 16;
@@ -122,19 +160,49 @@ vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
base = 8;
break;
case 'b':
- ells = 0;
+ l_count = 0;
base = 1;
break;
case 'c':
- ul = (int64_t)va_arg(args, int);
- ADDCHAR((int)ul & 0xff);
+ c = (char)va_arg(args, char);
+ ADDCHAR(c);
break;
case 's':
sp = va_arg(args, char *);
- if (sp == NULL)
+ if (sp == NULL) {
sp = "<null string>";
- while ((c = *sp++) != 0)
- ADDCHAR(c);
+ /* avoid truncation */
+ prec = strlen(sp);
+ }
+ /*
+ * Handle simple case specially to avoid
+ * performance hit of strlen()
+ */
+ if (prec == 0 && width == 0) {
+ while ((c = *sp++) != 0)
+ ADDCHAR(c);
+ break;
+ }
+ transfer_count = strlen(sp);
+ if (prec > 0) {
+ /* trim string if too long */
+ if (transfer_count > prec)
+ transfer_count = prec;
+ /* widen field if too narrow */
+ if (prec > width)
+ width = prec;
+ }
+ if (width > transfer_count)
+ pad_count = width - transfer_count;
+ else
+ pad_count = 0;
+ while ((!left_align) && (pad_count-- > 0))
+ ADDCHAR(' ');
+ /* ADDCHAR() evaluates arg at most once */
+ while (transfer_count-- > 0)
+ ADDCHAR(*sp++);
+ while ((left_align) && (pad_count-- > 0))
+ ADDCHAR(' ');
break;
case '%':
ADDCHAR('%');
@@ -144,30 +212,49 @@ vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs)
if (base == 0)
continue;
- if (ells == 0)
- ul = (int64_t)va_arg(args, int);
- else if (ells == 1)
- ul = (int64_t)va_arg(args, long);
- else
- ul = (int64_t)va_arg(args, int64_t);
+ if (h_count == 0 && l_count == 0)
+ if (sign)
+ ul = (int64_t)va_arg(args, int);
+ else
+ ul = (int64_t)va_arg(args, unsigned int);
+ else if (l_count > 1)
+ if (sign)
+ ul = (int64_t)va_arg(args, int64_t);
+ else
+ ul = (int64_t)va_arg(args, uint64_t);
+ else if (l_count > 0)
+ if (sign)
+ ul = (int64_t)va_arg(args, long);
+ else
+ ul = (int64_t)va_arg(args, unsigned long);
+ else if (h_count > 1)
+ if (sign)
+ ul = (int64_t)va_arg(args, char);
+ else
+ ul = (int64_t)va_arg(args, unsigned char);
+ else if (h_count > 0)
+ if (sign)
+ ul = (int64_t)va_arg(args, short);
+ else
+ ul = (int64_t)va_arg(args, unsigned short);
if (sign && (int64_t)ul < 0)
ul = -ul;
else
sign = 0;
- if (ells < 8 / sizeof (long))
- ul &= 0xffffffffU;
-
if (c == 'b') {
bs = va_arg(args, char *);
base = *bs++;
}
- tmp = ul;
- do {
- width--;
- } while ((tmp /= base) != 0);
+ /* avoid repeated division if width is 0 */
+ if (width > 0) {
+ tmp = ul;
+ do {
+ width--;
+ } while ((tmp /= base) != 0);
+ }
if (sign && pad == '0')
ADDCHAR('-');