--- /tmp/p.c Wed Oct 13 18:49:04 2010
+++ printf.c Wed Oct 13 18:47:43 2010
@@ -1,4 +1,5 @@
/*
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -10,10 +11,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -31,22 +28,6 @@
* SUCH DAMAGE.
*/
-#if !defined(BUILTIN) && !defined(SHELL)
-#ifndef lint
-static char const copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-#endif
-
-#ifndef lint
-#if 0
-static char const sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/types.h>
#include <err.h>
@@ -57,36 +38,36 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <locale.h>
-#ifdef SHELL
-#define main printfcmd
-#include "bltin/bltin.h"
-#include "memalloc.h"
-#else
#define warnx1(a, b, c) warnx(a)
#define warnx2(a, b, c) warnx(a, b)
#define warnx3(a, b, c) warnx(a, b, c)
-#endif
-#ifndef BUILTIN
-#include <locale.h>
-#endif
+#define _(x) gettext(x)
-#define PF(f, func) do { \
- char *b = NULL; \
- if (havewidth) \
- if (haveprec) \
- (void)asprintf(&b, f, fieldwidth, precision, func); \
- else \
- (void)asprintf(&b, f, fieldwidth, func); \
- else if (haveprec) \
- (void)asprintf(&b, f, precision, func); \
- else \
- (void)asprintf(&b, f, func); \
- if (b) { \
- (void)fputs(b, stdout); \
- free(b); \
- } \
+#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); \
+ else \
+ (void) asprintf(&b, f, fieldwidth, func); \
+ else if (haveprec) \
+ (void) asprintf(&b, f, precision, func); \
+ else \
+ (void) asprintf(&b, f, func); \
+ if (b) { \
+ (void) fputs(b, stdout); \
+ free(b); \
+ } \
+ if (dollar) \
+ *f = '$'; \
} while (0)
static int asciicode(void);
@@ -98,35 +79,25 @@
static int getnum(intmax_t *, uintmax_t *, int);
static const char
*getstr(void);
-static char *mknum(char *, int);
+static char *mknum(char *, char);
static void usage(void);
+static int myargc;
+static char **myargv;
static char **gargv;
int
-#ifdef BUILTIN
-progprintf(int argc, char *argv[])
-#else
main(int argc, char *argv[])
-#endif
{
size_t len;
- int ch, chopped, end, rval;
+ int chopped, end, rval;
char *format, *fmt, *start;
-#ifndef BUILTIN
- (void) setlocale(LC_NUMERIC, "");
-#endif
- while ((ch = getopt(argc, argv, "")) != -1)
- switch (ch) {
- case '?':
- default:
- usage();
- return (1);
- }
- argc -= optind;
- argv += optind;
+ (void) setlocale(LC_ALL, "");
+ argv++;
+ argc--;
+
if (argc < 1) {
usage();
return (1);
@@ -144,14 +115,21 @@
chopped = escape(fmt, 1, &len); /* backslash interpretation */
rval = end = 0;
gargv = ++argv;
+
for (;;) {
+ char **maxargv = gargv;
+
+ myargv = gargv;
+ for (myargc = 0; gargv[myargc]; myargc++)
+ /* nop */;
start = fmt;
while (fmt < format + len) {
if (fmt[0] == '%') {
- fwrite(start, 1, fmt - start, stdout);
+ (void) fwrite(start, 1,
+ (uintptr_t)fmt - (uintptr_t)start, stdout);
if (fmt[1] == '%') {
/* %% prints a % */
- putchar('%');
+ (void) putchar('%');
fmt += 2;
} else {
fmt = doformat(fmt, &rval);
@@ -162,13 +140,17 @@
start = fmt;
} else
fmt++;
+ if (gargv > maxargv)
+ maxargv = gargv;
}
+ gargv = maxargv;
if (end == 1) {
- warnx1("missing format character", NULL, NULL);
+ warnx1(_("missing format character"), NULL, NULL);
return (1);
}
- fwrite(start, 1, fmt - start, stdout);
+ (void) fwrite(start, 1, (uintptr_t)fmt - (uintptr_t)start,
+ stdout);
if (chopped || !*gargv)
return (rval);
/* Restart at the beginning of the format string. */
@@ -189,6 +171,22 @@
char convch, nextch;
fmt = start + 1;
+
+ /* look for "n$" field index specifier */
+ fmt += strspn(fmt, skip2);
+ if ((*fmt == '$') && (fmt != (start + 1))) {
+ int idx = atoi(start + 1);
+ if (idx <= myargc) {
+ gargv = &myargv[idx - 1];
+ } else {
+ gargv = &myargv[myargc];
+ }
+ start = fmt;
+ fmt++;
+ } else {
+ fmt = start + 1;
+ }
+
/* skip to field width */
fmt += strspn(fmt, skip1);
if (*fmt == '*') {
@@ -219,7 +217,7 @@
} else
haveprec = 0;
if (!*fmt) {
- warnx1("missing format character", NULL, NULL);
+ warnx1(_("missing format character"), NULL, NULL);
return (NULL);
}
@@ -237,7 +235,7 @@
mod_ldbl = 1;
fmt++;
if (!strchr("aAeEfFgG", *fmt)) {
- warnx2("bad modifier L for %%%c", *fmt, NULL);
+ warnx2(_("bad modifier L for %%%c"), *fmt, NULL);
return (NULL);
}
} else {
@@ -253,11 +251,7 @@
char *p;
int getout;
-#ifdef SHELL
- p = savestr(getstr());
-#else
p = strdup(getstr());
-#endif
if (p == NULL) {
warnx2("%s", strerror(ENOMEM), NULL);
return (NULL);
@@ -264,13 +258,11 @@
}
getout = escape(p, 0, &len);
*(fmt - 1) = 's';
+ /*LINTED E_CONST_CONDITION*/
PF(start, p);
*(fmt - 1) = 'b';
-#ifdef SHELL
- ckfree(p);
-#else
free(p);
-#endif
+
if (getout)
return (fmt);
break;
@@ -279,6 +271,7 @@
char p;
p = getchr();
+ /*LINTED E_CONST_CONDITION*/
PF(start, p);
break;
}
@@ -286,6 +279,7 @@
const char *p;
p = getstr();
+ /*LINTED E_CONST_CONDITION*/
PF(start, p);
break;
}
@@ -301,8 +295,10 @@
if (getnum(&val, &uval, signedconv))
*rval = 1;
if (signedconv)
+ /*LINTED E_CONST_CONDITION*/
PF(f, val);
else
+ /*LINTED E_CONST_CONDITION*/
PF(f, uval);
break;
}
@@ -315,13 +311,15 @@
if (getfloating(&p, mod_ldbl))
*rval = 1;
if (mod_ldbl)
+ /*LINTED E_CONST_CONDITION*/
PF(start, p);
else
+ /*LINTED E_CONST_CONDITION*/
PF(start, (double)p);
break;
}
default:
- warnx2("illegal format character %c", convch, NULL);
+ warnx2(_("illegal format character %c"), convch, NULL);
return (NULL);
}
*fmt = nextch;
@@ -329,7 +327,7 @@
}
static char *
-mknum(char *str, int ch)
+mknum(char *str, char ch)
{
static char *copy;
static size_t copy_size;
@@ -339,12 +337,7 @@
len = strlen(str) + 2;
if (len > copy_size) {
newlen = ((len + 1023) >> 10) << 10;
-#ifdef SHELL
- if ((newcopy = ckrealloc(copy, newlen)) == NULL)
-#else
- if ((newcopy = realloc(copy, newlen)) == NULL)
-#endif
- {
+ if ((newcopy = realloc(copy, newlen)) == NULL) {
warnx2("%s", strerror(ENOMEM), NULL);
return (NULL);
}
@@ -352,7 +345,7 @@
copy_size = newlen;
}
- memmove(copy, str, len - 3);
+ (void) memmove(copy, str, len - 3);
copy[len - 3] = 'j';
copy[len - 2] = ch;
copy[len - 1] = '\0';
@@ -362,10 +355,10 @@
static int
escape(char *fmt, int percent, size_t *len)
{
- char *save, *store;
- int value, c;
+ char *save, *store, c;
+ int value;
- for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
+ for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
if (c != '\\') {
*store = c;
continue;
@@ -374,7 +367,7 @@
case '\0': /* EOS, user error */
*store = '\\';
*++store = '\0';
- *len = store - save;
+ *len = (uintptr_t)store - (uintptr_t)save;
return (0);
case '\\': /* backslash */
case '\'': /* single quote */
@@ -388,7 +381,7 @@
break;
case 'c':
*store = '\0';
- *len = store - save;
+ *len = (uintptr_t)store - (uintptr_t)save;
return (1);
case 'f': /* form-feed */
*store = '\f';
@@ -419,7 +412,7 @@
*store++ = '%';
*store = '%';
} else
- *store = value;
+ *store = (char)value;
break;
default:
*store = *fmt;
@@ -427,7 +420,7 @@
}
}
*store = '\0';
- *len = store - save;
+ *len = (uintptr_t)store - (uintptr_t)save;
return (0);
}
@@ -489,15 +482,14 @@
else
*uip = strtoumax(*gargv, &ep, 0);
if (ep == *gargv) {
- warnx2("%s: expected numeric value", *gargv, NULL);
+ warnx2(_("%s: expected numeric value"), *gargv, NULL);
rval = 1;
- }
- else if (*ep != '\0') {
- warnx2("%s: not completely converted", *gargv, NULL);
+ } else if (*ep != '\0') {
+ warnx2(_("%s: not completely converted"), *gargv, NULL);
rval = 1;
}
if (errno == ERANGE) {
- warnx3("%s: %s", *gargv, strerror(ERANGE));
+ warnx3(_("%s: %s"), *gargv, strerror(ERANGE));
rval = 1;
}
++gargv;
@@ -525,10 +517,10 @@
else
*dp = strtod(*gargv, &ep);
if (ep == *gargv) {
- warnx2("%s: expected numeric value", *gargv, NULL);
+ warnx2(_("%s: expected numeric value"), *gargv, NULL);
rval = 1;
} else if (*ep != '\0') {
- warnx2("%s: not completely converted", *gargv, NULL);
+ warnx2(_("%s: not completely converted"), *gargv, NULL);
rval = 1;
}
if (errno == ERANGE) {
@@ -554,5 +546,5 @@
static void
usage(void)
{
- (void)fprintf(stderr, "usage: printf format [arguments ...]\n");
+ (void) fprintf(stderr, _("usage: printf format [arguments ...]\n"));
}