1216417Sdelphij/*- 21590Srgrimes * Copyright (c) 1989, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 29219153Sjilles/* 30219153Sjilles * Important: This file is used both as a standalone program /usr/bin/printf 31219153Sjilles * and as a builtin for /bin/sh (#define SHELL). 32219153Sjilles */ 331590Srgrimes 34216310Sjilles#ifndef SHELL 351590Srgrimes#ifndef lint 3620409Sstevestatic char const copyright[] = 371590Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 381590Srgrimes The Regents of the University of California. All rights reserved.\n"; 391590Srgrimes#endif /* not lint */ 401590Srgrimes#endif 411590Srgrimes 421590Srgrimes#ifndef lint 4365429Simp#if 0 4420409Sstevestatic char const sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93"; 4565429Simp#endif 4659435Scracauerstatic const char rcsid[] = 4759435Scracauer "$FreeBSD$"; 481590Srgrimes#endif /* not lint */ 491590Srgrimes 501590Srgrimes#include <sys/types.h> 511590Srgrimes 521590Srgrimes#include <err.h> 531590Srgrimes#include <errno.h> 54148721Sstefanf#include <inttypes.h> 551590Srgrimes#include <limits.h> 56216417Sdelphij#include <locale.h> 571590Srgrimes#include <stdio.h> 581590Srgrimes#include <stdlib.h> 591590Srgrimes#include <string.h> 6027966Ssteve#include <unistd.h> 61222418Sjilles#include <wchar.h> 621590Srgrimes 631590Srgrimes#ifdef SHELL 64265160Spfg#define main printfcmd 6512730Sjoerg#include "bltin/bltin.h" 66215520Sjilles#include "error.h" 67240541Sjilles#include "options.h" 681590Srgrimes#endif 691590Srgrimes 70265160Spfg#define PF(f, func) do { \ 71230027Spfg char *b = NULL; \ 72230027Spfg if (havewidth) \ 73230027Spfg if (haveprec) \ 7418613Speter (void)asprintf(&b, f, fieldwidth, precision, func); \ 75230027Spfg else \ 76230027Spfg (void)asprintf(&b, f, fieldwidth, func); \ 77230027Spfg else if (haveprec) \ 78230027Spfg (void)asprintf(&b, f, precision, func); \ 79230027Spfg else \ 80230027Spfg (void)asprintf(&b, f, func); \ 81230027Spfg if (b) { \ 82230027Spfg (void)fputs(b, stdout); \ 83230027Spfg free(b); \ 84230027Spfg } \ 8595409Stjr} while (0) 861590Srgrimes 8792921Simpstatic int asciicode(void); 88215520Sjillesstatic char *printf_doformat(char *, int *); 89145078Sstefanfstatic int escape(char *, int, size_t *); 9092921Simpstatic int getchr(void); 91143906Sdasstatic int getfloating(long double *, int); 9292921Simpstatic int getint(int *); 93148721Sstefanfstatic int getnum(intmax_t *, uintmax_t *, int); 9495409Stjrstatic const char 9595409Stjr *getstr(void); 96216418Sdelphijstatic char *mknum(char *, char); 9792921Simpstatic void usage(void); 981590Srgrimes 991590Srgrimesstatic char **gargv; 1001590Srgrimes 1011590Srgrimesint 102102944Sdwmalonemain(int argc, char *argv[]) 1031590Srgrimes{ 104145078Sstefanf size_t len; 105240541Sjilles int chopped, end, rval; 106145061Sstefanf char *format, *fmt, *start; 107240541Sjilles#ifndef SHELL 108240541Sjilles int ch; 1091590Srgrimes 110216424Sdelphij (void) setlocale(LC_ALL, ""); 11172304Sache#endif 112240541Sjilles 113215520Sjilles#ifdef SHELL 114240541Sjilles nextopt(""); 115240541Sjilles argc -= argptr - argv; 116240541Sjilles argv = argptr; 117240541Sjilles#else 118216447Sdelphij while ((ch = getopt(argc, argv, "")) != -1) 119216447Sdelphij switch (ch) { 120216447Sdelphij case '?': 121216447Sdelphij default: 122216447Sdelphij usage(); 123216447Sdelphij return (1); 124216447Sdelphij } 125216447Sdelphij argc -= optind; 126216447Sdelphij argv += optind; 127240541Sjilles#endif 1281590Srgrimes 1291590Srgrimes if (argc < 1) { 1301590Srgrimes usage(); 131216439Sdelphij return (1); 1321590Srgrimes } 1331590Srgrimes 134215520Sjilles#ifdef SHELL 135215520Sjilles INTOFF; 136215520Sjilles#endif 1371590Srgrimes /* 1381590Srgrimes * Basic algorithm is to scan the format string for conversion 1391590Srgrimes * specifications -- once one is found, find out if the field 1401590Srgrimes * width or precision is a '*'; if it is, gather up value. Note, 1411590Srgrimes * format strings are reused as necessary to use up the provided 1421590Srgrimes * arguments, arguments of zero/null string are provided to use 1431590Srgrimes * up the format string. 1441590Srgrimes */ 145145078Sstefanf fmt = format = *argv; 146145078Sstefanf chopped = escape(fmt, 1, &len); /* backslash interpretation */ 147145061Sstefanf rval = end = 0; 1481590Srgrimes gargv = ++argv; 1491590Srgrimes for (;;) { 150145061Sstefanf start = fmt; 151145078Sstefanf while (fmt < format + len) { 152145061Sstefanf if (fmt[0] == '%') { 153145061Sstefanf fwrite(start, 1, fmt - start, stdout); 154145061Sstefanf if (fmt[1] == '%') { 155145061Sstefanf /* %% prints a % */ 156145061Sstefanf putchar('%'); 157145061Sstefanf fmt += 2; 158145061Sstefanf } else { 159215520Sjilles fmt = printf_doformat(fmt, &rval); 160215520Sjilles if (fmt == NULL) { 161215520Sjilles#ifdef SHELL 162215520Sjilles INTON; 163215520Sjilles#endif 164145061Sstefanf return (1); 165215520Sjilles } 166145061Sstefanf end = 0; 16795300Sjmallett } 168145061Sstefanf start = fmt; 169145061Sstefanf } else 17098420Stjr fmt++; 1711590Srgrimes } 1721590Srgrimes 173145061Sstefanf if (end == 1) { 174216606Sjilles warnx("missing format character"); 175215520Sjilles#ifdef SHELL 176215520Sjilles INTON; 177215520Sjilles#endif 178145061Sstefanf return (1); 179145061Sstefanf } 180145061Sstefanf fwrite(start, 1, fmt - start, stdout); 181215520Sjilles if (chopped || !*gargv) { 182215520Sjilles#ifdef SHELL 183215520Sjilles INTON; 184215520Sjilles#endif 185145061Sstefanf return (rval); 186215520Sjilles } 187145061Sstefanf /* Restart at the beginning of the format string. */ 188145061Sstefanf fmt = format; 189145061Sstefanf end = 1; 190145061Sstefanf } 191145061Sstefanf /* NOTREACHED */ 192145061Sstefanf} 193145061Sstefanf 194145061Sstefanf 195145061Sstefanfstatic char * 196215520Sjillesprintf_doformat(char *start, int *rval) 197145061Sstefanf{ 198145061Sstefanf static const char skip1[] = "#'-+ 0"; 199145061Sstefanf static const char skip2[] = "0123456789"; 200145061Sstefanf char *fmt; 201145061Sstefanf int fieldwidth, haveprec, havewidth, mod_ldbl, precision; 202145061Sstefanf char convch, nextch; 203145061Sstefanf 204145061Sstefanf fmt = start + 1; 205145061Sstefanf /* skip to field width */ 206145061Sstefanf fmt += strspn(fmt, skip1); 207145061Sstefanf if (*fmt == '*') { 208145061Sstefanf if (getint(&fieldwidth)) 209145061Sstefanf return (NULL); 210145061Sstefanf havewidth = 1; 211145061Sstefanf ++fmt; 212145061Sstefanf } else { 213145061Sstefanf havewidth = 0; 214145061Sstefanf 215145061Sstefanf /* skip to possible '.', get following precision */ 216145061Sstefanf fmt += strspn(fmt, skip2); 217145061Sstefanf } 218145061Sstefanf if (*fmt == '.') { 219145061Sstefanf /* precision present? */ 220145061Sstefanf ++fmt; 2211590Srgrimes if (*fmt == '*') { 222145061Sstefanf if (getint(&precision)) 223145061Sstefanf return (NULL); 224145061Sstefanf haveprec = 1; 2258323Sjoerg ++fmt; 2268323Sjoerg } else { 227145061Sstefanf haveprec = 0; 2281590Srgrimes 229145061Sstefanf /* skip to conversion char */ 230144902Sstefanf fmt += strspn(fmt, skip2); 2318323Sjoerg } 232145061Sstefanf } else 233145061Sstefanf haveprec = 0; 234145061Sstefanf if (!*fmt) { 235216606Sjilles warnx("missing format character"); 236145061Sstefanf return (NULL); 237145061Sstefanf } 2388323Sjoerg 239145061Sstefanf /* 240145061Sstefanf * Look for a length modifier. POSIX doesn't have these, so 241145061Sstefanf * we only support them for floating-point conversions, which 242145061Sstefanf * are extensions. This is useful because the L modifier can 243145061Sstefanf * be used to gain extra range and precision, while omitting 244145061Sstefanf * it is more likely to produce consistent results on different 245145061Sstefanf * architectures. This is not so important for integers 246145061Sstefanf * because overflow is the only bad thing that can happen to 247145061Sstefanf * them, but consider the command printf %a 1.1 248145061Sstefanf */ 249145061Sstefanf if (*fmt == 'L') { 250145061Sstefanf mod_ldbl = 1; 251145061Sstefanf fmt++; 252145061Sstefanf if (!strchr("aAeEfFgG", *fmt)) { 253216606Sjilles warnx("bad modifier L for %%%c", *fmt); 254145061Sstefanf return (NULL); 2551590Srgrimes } 256145061Sstefanf } else { 257145061Sstefanf mod_ldbl = 0; 258145061Sstefanf } 2591590Srgrimes 260145061Sstefanf convch = *fmt; 261145061Sstefanf nextch = *++fmt; 262145061Sstefanf *fmt = '\0'; 263145061Sstefanf switch (convch) { 264145061Sstefanf case 'b': { 265145078Sstefanf size_t len; 266145061Sstefanf char *p; 267145061Sstefanf int getout; 268143906Sdas 269145061Sstefanf p = strdup(getstr()); 270145061Sstefanf if (p == NULL) { 271216606Sjilles warnx("%s", strerror(ENOMEM)); 272145061Sstefanf return (NULL); 273145061Sstefanf } 274145078Sstefanf getout = escape(p, 0, &len); 275145061Sstefanf *(fmt - 1) = 's'; 276145061Sstefanf PF(start, p); 277145061Sstefanf *(fmt - 1) = 'b'; 278145061Sstefanf free(p); 279145061Sstefanf if (getout) 280145061Sstefanf return (fmt); 281145061Sstefanf break; 282145061Sstefanf } 283145061Sstefanf case 'c': { 284145061Sstefanf char p; 2851590Srgrimes 286145061Sstefanf p = getchr(); 287145061Sstefanf PF(start, p); 288145061Sstefanf break; 289145061Sstefanf } 290145061Sstefanf case 's': { 291145061Sstefanf const char *p; 2921590Srgrimes 293145061Sstefanf p = getstr(); 294145061Sstefanf PF(start, p); 295145061Sstefanf break; 296145061Sstefanf } 297145061Sstefanf case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { 298145061Sstefanf char *f; 299148721Sstefanf intmax_t val; 300148721Sstefanf uintmax_t uval; 301145061Sstefanf int signedconv; 3028874Srgrimes 303145061Sstefanf signedconv = (convch == 'd' || convch == 'i'); 304148721Sstefanf if ((f = mknum(start, convch)) == NULL) 305145061Sstefanf return (NULL); 306148721Sstefanf if (getnum(&val, &uval, signedconv)) 307145061Sstefanf *rval = 1; 308145061Sstefanf if (signedconv) 309145061Sstefanf PF(f, val); 310145061Sstefanf else 311145061Sstefanf PF(f, uval); 312145061Sstefanf break; 313145061Sstefanf } 314145061Sstefanf case 'e': case 'E': 315145061Sstefanf case 'f': case 'F': 316145061Sstefanf case 'g': case 'G': 317145061Sstefanf case 'a': case 'A': { 318145061Sstefanf long double p; 3191590Srgrimes 320145061Sstefanf if (getfloating(&p, mod_ldbl)) 321145061Sstefanf *rval = 1; 322145061Sstefanf if (mod_ldbl) 323145061Sstefanf PF(start, p); 324145061Sstefanf else 325145061Sstefanf PF(start, (double)p); 326145061Sstefanf break; 3271590Srgrimes } 328145061Sstefanf default: 329216606Sjilles warnx("illegal format character %c", convch); 330145061Sstefanf return (NULL); 331145061Sstefanf } 332145061Sstefanf *fmt = nextch; 333145061Sstefanf return (fmt); 3341590Srgrimes} 3351590Srgrimes 3361590Srgrimesstatic char * 337216418Sdelphijmknum(char *str, char ch) 3381590Srgrimes{ 33970256Sben static char *copy; 34070256Sben static size_t copy_size; 34195409Stjr char *newcopy; 34270256Sben size_t len, newlen; 3431590Srgrimes 3441590Srgrimes len = strlen(str) + 2; 34570256Sben if (len > copy_size) { 34670256Sben newlen = ((len + 1023) >> 10) << 10; 34770256Sben if ((newcopy = realloc(copy, newlen)) == NULL) 34895409Stjr { 349216606Sjilles warnx("%s", strerror(ENOMEM)); 35070256Sben return (NULL); 35195409Stjr } 35270256Sben copy = newcopy; 35370256Sben copy_size = newlen; 35470256Sben } 35562928Sse 3561590Srgrimes memmove(copy, str, len - 3); 357148721Sstefanf copy[len - 3] = 'j'; 3581590Srgrimes copy[len - 2] = ch; 3591590Srgrimes copy[len - 1] = '\0'; 3601590Srgrimes return (copy); 3611590Srgrimes} 3621590Srgrimes 36395300Sjmallettstatic int 364145078Sstefanfescape(char *fmt, int percent, size_t *len) 3651590Srgrimes{ 366230027Spfg char *save, *store, c; 367230027Spfg int value; 3681590Srgrimes 369230027Spfg for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) { 3701590Srgrimes if (c != '\\') { 3711590Srgrimes *store = c; 3721590Srgrimes continue; 3731590Srgrimes } 3741590Srgrimes switch (*++fmt) { 3751590Srgrimes case '\0': /* EOS, user error */ 3761590Srgrimes *store = '\\'; 3771590Srgrimes *++store = '\0'; 378145078Sstefanf *len = store - save; 37995300Sjmallett return (0); 3801590Srgrimes case '\\': /* backslash */ 3811590Srgrimes case '\'': /* single quote */ 3821590Srgrimes *store = *fmt; 3831590Srgrimes break; 3841590Srgrimes case 'a': /* bell/alert */ 385145074Sstefanf *store = '\a'; 3861590Srgrimes break; 3871590Srgrimes case 'b': /* backspace */ 3881590Srgrimes *store = '\b'; 3891590Srgrimes break; 39095300Sjmallett case 'c': 39195300Sjmallett *store = '\0'; 392145078Sstefanf *len = store - save; 39395300Sjmallett return (1); 3941590Srgrimes case 'f': /* form-feed */ 3951590Srgrimes *store = '\f'; 3961590Srgrimes break; 3971590Srgrimes case 'n': /* newline */ 3981590Srgrimes *store = '\n'; 3991590Srgrimes break; 4001590Srgrimes case 'r': /* carriage-return */ 4011590Srgrimes *store = '\r'; 4021590Srgrimes break; 4031590Srgrimes case 't': /* horizontal tab */ 4041590Srgrimes *store = '\t'; 4051590Srgrimes break; 4061590Srgrimes case 'v': /* vertical tab */ 407145074Sstefanf *store = '\v'; 4081590Srgrimes break; 4091590Srgrimes /* octal constant */ 4101590Srgrimes case '0': case '1': case '2': case '3': 4111590Srgrimes case '4': case '5': case '6': case '7': 412181153Sdas c = (!percent && *fmt == '0') ? 4 : 3; 413181153Sdas for (value = 0; 4141590Srgrimes c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) { 4151590Srgrimes value <<= 3; 4161590Srgrimes value += *fmt - '0'; 4171590Srgrimes } 4181590Srgrimes --fmt; 41998426Stjr if (percent && value == '%') { 42098419Stjr *store++ = '%'; 42198419Stjr *store = '%'; 42298419Stjr } else 423230027Spfg *store = (char)value; 4241590Srgrimes break; 4251590Srgrimes default: 4261590Srgrimes *store = *fmt; 4271590Srgrimes break; 4281590Srgrimes } 4291590Srgrimes } 4301590Srgrimes *store = '\0'; 431145078Sstefanf *len = store - save; 43295300Sjmallett return (0); 4331590Srgrimes} 4341590Srgrimes 4351590Srgrimesstatic int 436102944Sdwmalonegetchr(void) 4371590Srgrimes{ 4381590Srgrimes if (!*gargv) 4391590Srgrimes return ('\0'); 4401590Srgrimes return ((int)**gargv++); 4411590Srgrimes} 4421590Srgrimes 44387298Sdwmalonestatic const char * 444102944Sdwmalonegetstr(void) 4451590Srgrimes{ 4461590Srgrimes if (!*gargv) 4471590Srgrimes return (""); 4481590Srgrimes return (*gargv++); 4491590Srgrimes} 4501590Srgrimes 4511590Srgrimesstatic int 452102944Sdwmalonegetint(int *ip) 4531590Srgrimes{ 454148721Sstefanf intmax_t val; 455148721Sstefanf uintmax_t uval; 45695409Stjr int rval; 4571590Srgrimes 458148721Sstefanf if (getnum(&val, &uval, 1)) 4591590Srgrimes return (1); 46095409Stjr rval = 0; 46195409Stjr if (val < INT_MIN || val > INT_MAX) { 462216606Sjilles warnx("%s: %s", *gargv, strerror(ERANGE)); 46395409Stjr rval = 1; 46495409Stjr } 46562928Sse *ip = (int)val; 46695409Stjr return (rval); 4671590Srgrimes} 4681590Srgrimes 4691590Srgrimesstatic int 470148721Sstefanfgetnum(intmax_t *ip, uintmax_t *uip, int signedconv) 4711590Srgrimes{ 4721590Srgrimes char *ep; 47395409Stjr int rval; 4741590Srgrimes 4751590Srgrimes if (!*gargv) { 476244407Seadler *ip = *uip = 0; 4771590Srgrimes return (0); 4781590Srgrimes } 47995300Sjmallett if (**gargv == '"' || **gargv == '\'') { 48095409Stjr if (signedconv) 481148721Sstefanf *ip = asciicode(); 48295409Stjr else 483148721Sstefanf *uip = asciicode(); 4841590Srgrimes return (0); 4851590Srgrimes } 48695409Stjr rval = 0; 48795300Sjmallett errno = 0; 48895409Stjr if (signedconv) 489148721Sstefanf *ip = strtoimax(*gargv, &ep, 0); 49095409Stjr else 491148721Sstefanf *uip = strtoumax(*gargv, &ep, 0); 49295409Stjr if (ep == *gargv) { 493216606Sjilles warnx("%s: expected numeric value", *gargv); 49495409Stjr rval = 1; 49595409Stjr } 49695409Stjr else if (*ep != '\0') { 497216606Sjilles warnx("%s: not completely converted", *gargv); 49895409Stjr rval = 1; 49995409Stjr } 50095409Stjr if (errno == ERANGE) { 501216606Sjilles warnx("%s: %s", *gargv, strerror(ERANGE)); 50295409Stjr rval = 1; 50395409Stjr } 50495300Sjmallett ++gargv; 50595409Stjr return (rval); 5061590Srgrimes} 5071590Srgrimes 50895409Stjrstatic int 509143906Sdasgetfloating(long double *dp, int mod_ldbl) 5101590Srgrimes{ 51195300Sjmallett char *ep; 51295409Stjr int rval; 51395300Sjmallett 514145027Sstefanf if (!*gargv) { 515145027Sstefanf *dp = 0.0; 51695409Stjr return (0); 517145027Sstefanf } 51895300Sjmallett if (**gargv == '"' || **gargv == '\'') { 51995409Stjr *dp = asciicode(); 52095409Stjr return (0); 52195300Sjmallett } 522126729Scperciva rval = 0; 52395300Sjmallett errno = 0; 524143906Sdas if (mod_ldbl) 525143906Sdas *dp = strtold(*gargv, &ep); 526143906Sdas else 527143906Sdas *dp = strtod(*gargv, &ep); 52895409Stjr if (ep == *gargv) { 529216606Sjilles warnx("%s: expected numeric value", *gargv); 53095409Stjr rval = 1; 53195409Stjr } else if (*ep != '\0') { 532216606Sjilles warnx("%s: not completely converted", *gargv); 53395409Stjr rval = 1; 53495409Stjr } 53595409Stjr if (errno == ERANGE) { 536216606Sjilles warnx("%s: %s", *gargv, strerror(ERANGE)); 53795409Stjr rval = 1; 53895409Stjr } 53995300Sjmallett ++gargv; 54095409Stjr return (rval); 5411590Srgrimes} 5421590Srgrimes 5431590Srgrimesstatic int 544102944Sdwmaloneasciicode(void) 5451590Srgrimes{ 546102944Sdwmalone int ch; 547222418Sjilles wchar_t wch; 548222418Sjilles mbstate_t mbs; 5491590Srgrimes 550222418Sjilles ch = (unsigned char)**gargv; 551222418Sjilles if (ch == '\'' || ch == '"') { 552222418Sjilles memset(&mbs, 0, sizeof(mbs)); 553222418Sjilles switch (mbrtowc(&wch, *gargv + 1, MB_LEN_MAX, &mbs)) { 554222418Sjilles case (size_t)-2: 555222418Sjilles case (size_t)-1: 556222418Sjilles wch = (unsigned char)gargv[0][1]; 557222418Sjilles break; 558222418Sjilles case 0: 559222418Sjilles wch = 0; 560222418Sjilles break; 561222418Sjilles } 562222418Sjilles ch = wch; 563222418Sjilles } 5641590Srgrimes ++gargv; 5651590Srgrimes return (ch); 5661590Srgrimes} 5671590Srgrimes 5681590Srgrimesstatic void 569102944Sdwmaloneusage(void) 5701590Srgrimes{ 571146466Sru (void)fprintf(stderr, "usage: printf format [arguments ...]\n"); 5721590Srgrimes} 573