--- /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 #include @@ -57,36 +38,36 @@ #include #include #include +#include -#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 -#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")); }