xref: /freebsd-13.1/usr.bin/printf/printf.c (revision 9b50d902)
1*9b50d902SRodney W. Grimes /*
2*9b50d902SRodney W. Grimes  * Copyright (c) 1989, 1993
3*9b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4*9b50d902SRodney W. Grimes  *
5*9b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
6*9b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
7*9b50d902SRodney W. Grimes  * are met:
8*9b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
9*9b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
10*9b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
11*9b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
12*9b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
13*9b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
14*9b50d902SRodney W. Grimes  *    must display the following acknowledgement:
15*9b50d902SRodney W. Grimes  *	This product includes software developed by the University of
16*9b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
17*9b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
18*9b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
19*9b50d902SRodney W. Grimes  *    without specific prior written permission.
20*9b50d902SRodney W. Grimes  *
21*9b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*9b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*9b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*9b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*9b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*9b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*9b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*9b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*9b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*9b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*9b50d902SRodney W. Grimes  * SUCH DAMAGE.
32*9b50d902SRodney W. Grimes  */
33*9b50d902SRodney W. Grimes 
34*9b50d902SRodney W. Grimes #if !defined(BUILTIN) && !defined(SHELL)
35*9b50d902SRodney W. Grimes #ifndef lint
36*9b50d902SRodney W. Grimes static char copyright[] =
37*9b50d902SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\
38*9b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
39*9b50d902SRodney W. Grimes #endif /* not lint */
40*9b50d902SRodney W. Grimes #endif
41*9b50d902SRodney W. Grimes 
42*9b50d902SRodney W. Grimes #ifndef lint
43*9b50d902SRodney W. Grimes static char sccsid[] = "@(#)printf.c	8.1 (Berkeley) 7/20/93";
44*9b50d902SRodney W. Grimes #endif /* not lint */
45*9b50d902SRodney W. Grimes 
46*9b50d902SRodney W. Grimes #include <sys/types.h>
47*9b50d902SRodney W. Grimes 
48*9b50d902SRodney W. Grimes #include <err.h>
49*9b50d902SRodney W. Grimes #include <errno.h>
50*9b50d902SRodney W. Grimes #include <limits.h>
51*9b50d902SRodney W. Grimes #ifdef SHELL
52*9b50d902SRodney W. Grimes #define	EOF	-1
53*9b50d902SRodney W. Grimes #else
54*9b50d902SRodney W. Grimes #include <stdio.h>
55*9b50d902SRodney W. Grimes #endif
56*9b50d902SRodney W. Grimes #include <stdlib.h>
57*9b50d902SRodney W. Grimes #include <string.h>
58*9b50d902SRodney W. Grimes 
59*9b50d902SRodney W. Grimes /*
60*9b50d902SRodney W. Grimes  * XXX
61*9b50d902SRodney W. Grimes  * This *has* to go away.  TK.
62*9b50d902SRodney W. Grimes  */
63*9b50d902SRodney W. Grimes #ifdef SHELL
64*9b50d902SRodney W. Grimes #define main printfcmd
65*9b50d902SRodney W. Grimes #define warnx(a, b, c) {						\
66*9b50d902SRodney W. Grimes 	char buf[64];							\
67*9b50d902SRodney W. Grimes 	(void)sprintf(buf, sizeof(buf), a, b, c);			\
68*9b50d902SRodney W. Grimes 	error(buf);							\
69*9b50d902SRodney W. Grimes }
70*9b50d902SRodney W. Grimes #include "../../bin/sh/bltin/bltin.h"
71*9b50d902SRodney W. Grimes #endif
72*9b50d902SRodney W. Grimes 
73*9b50d902SRodney W. Grimes #define PF(f, func) { \
74*9b50d902SRodney W. Grimes 	if (fieldwidth) \
75*9b50d902SRodney W. Grimes 		if (precision) \
76*9b50d902SRodney W. Grimes 			(void)printf(f, fieldwidth, precision, func); \
77*9b50d902SRodney W. Grimes 		else \
78*9b50d902SRodney W. Grimes 			(void)printf(f, fieldwidth, func); \
79*9b50d902SRodney W. Grimes 	else if (precision) \
80*9b50d902SRodney W. Grimes 		(void)printf(f, precision, func); \
81*9b50d902SRodney W. Grimes 	else \
82*9b50d902SRodney W. Grimes 		(void)printf(f, func); \
83*9b50d902SRodney W. Grimes }
84*9b50d902SRodney W. Grimes 
85*9b50d902SRodney W. Grimes static int	 asciicode __P((void));
86*9b50d902SRodney W. Grimes static void	 escape __P((char *));
87*9b50d902SRodney W. Grimes static int	 getchr __P((void));
88*9b50d902SRodney W. Grimes static double	 getdouble __P((void));
89*9b50d902SRodney W. Grimes static int	 getint __P((int *));
90*9b50d902SRodney W. Grimes static int	 getlong __P((long *));
91*9b50d902SRodney W. Grimes static char	*getstr __P((void));
92*9b50d902SRodney W. Grimes static char	*mklong __P((char *, int));
93*9b50d902SRodney W. Grimes static void	 usage __P((void));
94*9b50d902SRodney W. Grimes 
95*9b50d902SRodney W. Grimes static char **gargv;
96*9b50d902SRodney W. Grimes 
97*9b50d902SRodney W. Grimes int
98*9b50d902SRodney W. Grimes #ifdef BUILTIN
99*9b50d902SRodney W. Grimes progprintf(argc, argv)
100*9b50d902SRodney W. Grimes #else
101*9b50d902SRodney W. Grimes main(argc, argv)
102*9b50d902SRodney W. Grimes #endif
103*9b50d902SRodney W. Grimes 	int argc;
104*9b50d902SRodney W. Grimes 	char *argv[];
105*9b50d902SRodney W. Grimes {
106*9b50d902SRodney W. Grimes 	extern int optind;
107*9b50d902SRodney W. Grimes 	static char *skip1, *skip2;
108*9b50d902SRodney W. Grimes 	int ch, end, fieldwidth, precision;
109*9b50d902SRodney W. Grimes 	char convch, nextch, *format, *fmt, *start;
110*9b50d902SRodney W. Grimes 
111*9b50d902SRodney W. Grimes 	while ((ch = getopt(argc, argv, "")) != EOF)
112*9b50d902SRodney W. Grimes 		switch (ch) {
113*9b50d902SRodney W. Grimes 		case '?':
114*9b50d902SRodney W. Grimes 		default:
115*9b50d902SRodney W. Grimes 			usage();
116*9b50d902SRodney W. Grimes 			return (1);
117*9b50d902SRodney W. Grimes 		}
118*9b50d902SRodney W. Grimes 	argc -= optind;
119*9b50d902SRodney W. Grimes 	argv += optind;
120*9b50d902SRodney W. Grimes 
121*9b50d902SRodney W. Grimes 	if (argc < 1) {
122*9b50d902SRodney W. Grimes 		usage();
123*9b50d902SRodney W. Grimes 		return (1);
124*9b50d902SRodney W. Grimes 	}
125*9b50d902SRodney W. Grimes 
126*9b50d902SRodney W. Grimes 	/*
127*9b50d902SRodney W. Grimes 	 * Basic algorithm is to scan the format string for conversion
128*9b50d902SRodney W. Grimes 	 * specifications -- once one is found, find out if the field
129*9b50d902SRodney W. Grimes 	 * width or precision is a '*'; if it is, gather up value.  Note,
130*9b50d902SRodney W. Grimes 	 * format strings are reused as necessary to use up the provided
131*9b50d902SRodney W. Grimes 	 * arguments, arguments of zero/null string are provided to use
132*9b50d902SRodney W. Grimes 	 * up the format string.
133*9b50d902SRodney W. Grimes 	 */
134*9b50d902SRodney W. Grimes 	skip1 = "#-+ 0";
135*9b50d902SRodney W. Grimes 	skip2 = "*0123456789";
136*9b50d902SRodney W. Grimes 
137*9b50d902SRodney W. Grimes 	escape(fmt = format = *argv);		/* backslash interpretation */
138*9b50d902SRodney W. Grimes 	gargv = ++argv;
139*9b50d902SRodney W. Grimes 	for (;;) {
140*9b50d902SRodney W. Grimes 		end = 0;
141*9b50d902SRodney W. Grimes 		/* find next format specification */
142*9b50d902SRodney W. Grimes next:		for (start = fmt;; ++fmt) {
143*9b50d902SRodney W. Grimes 			if (!*fmt) {
144*9b50d902SRodney W. Grimes 				/* avoid infinite loop */
145*9b50d902SRodney W. Grimes 				if (end == 1) {
146*9b50d902SRodney W. Grimes 					warnx("missing format character",
147*9b50d902SRodney W. Grimes 					    NULL, NULL);
148*9b50d902SRodney W. Grimes 					return (1);
149*9b50d902SRodney W. Grimes 				}
150*9b50d902SRodney W. Grimes 				end = 1;
151*9b50d902SRodney W. Grimes 				if (fmt > start)
152*9b50d902SRodney W. Grimes 					(void)printf("%s", start);
153*9b50d902SRodney W. Grimes 				if (!*gargv)
154*9b50d902SRodney W. Grimes 					return (0);
155*9b50d902SRodney W. Grimes 				fmt = format;
156*9b50d902SRodney W. Grimes 				goto next;
157*9b50d902SRodney W. Grimes 			}
158*9b50d902SRodney W. Grimes 			/* %% prints a % */
159*9b50d902SRodney W. Grimes 			if (*fmt == '%') {
160*9b50d902SRodney W. Grimes 				if (*++fmt != '%')
161*9b50d902SRodney W. Grimes 					break;
162*9b50d902SRodney W. Grimes 				*fmt++ = '\0';
163*9b50d902SRodney W. Grimes 				(void)printf("%s", start);
164*9b50d902SRodney W. Grimes 				goto next;
165*9b50d902SRodney W. Grimes 			}
166*9b50d902SRodney W. Grimes 		}
167*9b50d902SRodney W. Grimes 
168*9b50d902SRodney W. Grimes 		/* skip to field width */
169*9b50d902SRodney W. Grimes 		for (; strchr(skip1, *fmt); ++fmt);
170*9b50d902SRodney W. Grimes 		if (*fmt == '*') {
171*9b50d902SRodney W. Grimes 			if (getint(&fieldwidth))
172*9b50d902SRodney W. Grimes 				return (1);
173*9b50d902SRodney W. Grimes 		} else
174*9b50d902SRodney W. Grimes 			fieldwidth = 0;
175*9b50d902SRodney W. Grimes 
176*9b50d902SRodney W. Grimes 		/* skip to possible '.', get following precision */
177*9b50d902SRodney W. Grimes 		for (; strchr(skip2, *fmt); ++fmt);
178*9b50d902SRodney W. Grimes 		if (*fmt == '.')
179*9b50d902SRodney W. Grimes 			++fmt;
180*9b50d902SRodney W. Grimes 		if (*fmt == '*') {
181*9b50d902SRodney W. Grimes 			if (getint(&precision))
182*9b50d902SRodney W. Grimes 				return (1);
183*9b50d902SRodney W. Grimes 		} else
184*9b50d902SRodney W. Grimes 			precision = 0;
185*9b50d902SRodney W. Grimes 
186*9b50d902SRodney W. Grimes 		/* skip to conversion char */
187*9b50d902SRodney W. Grimes 		for (; strchr(skip2, *fmt); ++fmt);
188*9b50d902SRodney W. Grimes 		if (!*fmt) {
189*9b50d902SRodney W. Grimes 			warnx("missing format character", NULL, NULL);
190*9b50d902SRodney W. Grimes 			return (1);
191*9b50d902SRodney W. Grimes 		}
192*9b50d902SRodney W. Grimes 
193*9b50d902SRodney W. Grimes 		convch = *fmt;
194*9b50d902SRodney W. Grimes 		nextch = *++fmt;
195*9b50d902SRodney W. Grimes 		*fmt = '\0';
196*9b50d902SRodney W. Grimes 		switch(convch) {
197*9b50d902SRodney W. Grimes 		case 'c': {
198*9b50d902SRodney W. Grimes 			char p;
199*9b50d902SRodney W. Grimes 
200*9b50d902SRodney W. Grimes 			p = getchr();
201*9b50d902SRodney W. Grimes 			PF(start, p);
202*9b50d902SRodney W. Grimes 			break;
203*9b50d902SRodney W. Grimes 		}
204*9b50d902SRodney W. Grimes 		case 's': {
205*9b50d902SRodney W. Grimes 			char *p;
206*9b50d902SRodney W. Grimes 
207*9b50d902SRodney W. Grimes 			p = getstr();
208*9b50d902SRodney W. Grimes 			PF(start, p);
209*9b50d902SRodney W. Grimes 			break;
210*9b50d902SRodney W. Grimes 		}
211*9b50d902SRodney W. Grimes 		case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
212*9b50d902SRodney W. Grimes 			long p;
213*9b50d902SRodney W. Grimes 			char *f;
214*9b50d902SRodney W. Grimes 
215*9b50d902SRodney W. Grimes 			if ((f = mklong(start, convch)) == NULL)
216*9b50d902SRodney W. Grimes 				return (1);
217*9b50d902SRodney W. Grimes 			if (getlong(&p))
218*9b50d902SRodney W. Grimes 				return (1);
219*9b50d902SRodney W. Grimes 			PF(f, p);
220*9b50d902SRodney W. Grimes 			break;
221*9b50d902SRodney W. Grimes 		}
222*9b50d902SRodney W. Grimes 		case 'e': case 'E': case 'f': case 'g': case 'G': {
223*9b50d902SRodney W. Grimes 			double p;
224*9b50d902SRodney W. Grimes 
225*9b50d902SRodney W. Grimes 			p = getdouble();
226*9b50d902SRodney W. Grimes 			PF(start, p);
227*9b50d902SRodney W. Grimes 			break;
228*9b50d902SRodney W. Grimes 		}
229*9b50d902SRodney W. Grimes 		default:
230*9b50d902SRodney W. Grimes 			warnx("illegal format character", NULL, NULL);
231*9b50d902SRodney W. Grimes 			return (1);
232*9b50d902SRodney W. Grimes 		}
233*9b50d902SRodney W. Grimes 		*fmt = nextch;
234*9b50d902SRodney W. Grimes 	}
235*9b50d902SRodney W. Grimes 	/* NOTREACHED */
236*9b50d902SRodney W. Grimes }
237*9b50d902SRodney W. Grimes 
238*9b50d902SRodney W. Grimes static char *
239*9b50d902SRodney W. Grimes mklong(str, ch)
240*9b50d902SRodney W. Grimes 	char *str;
241*9b50d902SRodney W. Grimes 	int ch;
242*9b50d902SRodney W. Grimes {
243*9b50d902SRodney W. Grimes 	static char copy[64];
244*9b50d902SRodney W. Grimes 	int len;
245*9b50d902SRodney W. Grimes 
246*9b50d902SRodney W. Grimes 	len = strlen(str) + 2;
247*9b50d902SRodney W. Grimes 	memmove(copy, str, len - 3);
248*9b50d902SRodney W. Grimes 	copy[len - 3] = 'l';
249*9b50d902SRodney W. Grimes 	copy[len - 2] = ch;
250*9b50d902SRodney W. Grimes 	copy[len - 1] = '\0';
251*9b50d902SRodney W. Grimes 	return (copy);
252*9b50d902SRodney W. Grimes }
253*9b50d902SRodney W. Grimes 
254*9b50d902SRodney W. Grimes static void
255*9b50d902SRodney W. Grimes escape(fmt)
256*9b50d902SRodney W. Grimes 	register char *fmt;
257*9b50d902SRodney W. Grimes {
258*9b50d902SRodney W. Grimes 	register char *store;
259*9b50d902SRodney W. Grimes 	register int value, c;
260*9b50d902SRodney W. Grimes 
261*9b50d902SRodney W. Grimes 	for (store = fmt; c = *fmt; ++fmt, ++store) {
262*9b50d902SRodney W. Grimes 		if (c != '\\') {
263*9b50d902SRodney W. Grimes 			*store = c;
264*9b50d902SRodney W. Grimes 			continue;
265*9b50d902SRodney W. Grimes 		}
266*9b50d902SRodney W. Grimes 		switch (*++fmt) {
267*9b50d902SRodney W. Grimes 		case '\0':		/* EOS, user error */
268*9b50d902SRodney W. Grimes 			*store = '\\';
269*9b50d902SRodney W. Grimes 			*++store = '\0';
270*9b50d902SRodney W. Grimes 			return;
271*9b50d902SRodney W. Grimes 		case '\\':		/* backslash */
272*9b50d902SRodney W. Grimes 		case '\'':		/* single quote */
273*9b50d902SRodney W. Grimes 			*store = *fmt;
274*9b50d902SRodney W. Grimes 			break;
275*9b50d902SRodney W. Grimes 		case 'a':		/* bell/alert */
276*9b50d902SRodney W. Grimes 			*store = '\7';
277*9b50d902SRodney W. Grimes 			break;
278*9b50d902SRodney W. Grimes 		case 'b':		/* backspace */
279*9b50d902SRodney W. Grimes 			*store = '\b';
280*9b50d902SRodney W. Grimes 			break;
281*9b50d902SRodney W. Grimes 		case 'f':		/* form-feed */
282*9b50d902SRodney W. Grimes 			*store = '\f';
283*9b50d902SRodney W. Grimes 			break;
284*9b50d902SRodney W. Grimes 		case 'n':		/* newline */
285*9b50d902SRodney W. Grimes 			*store = '\n';
286*9b50d902SRodney W. Grimes 			break;
287*9b50d902SRodney W. Grimes 		case 'r':		/* carriage-return */
288*9b50d902SRodney W. Grimes 			*store = '\r';
289*9b50d902SRodney W. Grimes 			break;
290*9b50d902SRodney W. Grimes 		case 't':		/* horizontal tab */
291*9b50d902SRodney W. Grimes 			*store = '\t';
292*9b50d902SRodney W. Grimes 			break;
293*9b50d902SRodney W. Grimes 		case 'v':		/* vertical tab */
294*9b50d902SRodney W. Grimes 			*store = '\13';
295*9b50d902SRodney W. Grimes 			break;
296*9b50d902SRodney W. Grimes 					/* octal constant */
297*9b50d902SRodney W. Grimes 		case '0': case '1': case '2': case '3':
298*9b50d902SRodney W. Grimes 		case '4': case '5': case '6': case '7':
299*9b50d902SRodney W. Grimes 			for (c = 3, value = 0;
300*9b50d902SRodney W. Grimes 			    c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
301*9b50d902SRodney W. Grimes 				value <<= 3;
302*9b50d902SRodney W. Grimes 				value += *fmt - '0';
303*9b50d902SRodney W. Grimes 			}
304*9b50d902SRodney W. Grimes 			--fmt;
305*9b50d902SRodney W. Grimes 			*store = value;
306*9b50d902SRodney W. Grimes 			break;
307*9b50d902SRodney W. Grimes 		default:
308*9b50d902SRodney W. Grimes 			*store = *fmt;
309*9b50d902SRodney W. Grimes 			break;
310*9b50d902SRodney W. Grimes 		}
311*9b50d902SRodney W. Grimes 	}
312*9b50d902SRodney W. Grimes 	*store = '\0';
313*9b50d902SRodney W. Grimes }
314*9b50d902SRodney W. Grimes 
315*9b50d902SRodney W. Grimes static int
316*9b50d902SRodney W. Grimes getchr()
317*9b50d902SRodney W. Grimes {
318*9b50d902SRodney W. Grimes 	if (!*gargv)
319*9b50d902SRodney W. Grimes 		return ('\0');
320*9b50d902SRodney W. Grimes 	return ((int)**gargv++);
321*9b50d902SRodney W. Grimes }
322*9b50d902SRodney W. Grimes 
323*9b50d902SRodney W. Grimes static char *
324*9b50d902SRodney W. Grimes getstr()
325*9b50d902SRodney W. Grimes {
326*9b50d902SRodney W. Grimes 	if (!*gargv)
327*9b50d902SRodney W. Grimes 		return ("");
328*9b50d902SRodney W. Grimes 	return (*gargv++);
329*9b50d902SRodney W. Grimes }
330*9b50d902SRodney W. Grimes 
331*9b50d902SRodney W. Grimes static char *Number = "+-.0123456789";
332*9b50d902SRodney W. Grimes static int
333*9b50d902SRodney W. Grimes getint(ip)
334*9b50d902SRodney W. Grimes 	int *ip;
335*9b50d902SRodney W. Grimes {
336*9b50d902SRodney W. Grimes 	long val;
337*9b50d902SRodney W. Grimes 
338*9b50d902SRodney W. Grimes 	if (getlong(&val))
339*9b50d902SRodney W. Grimes 		return (1);
340*9b50d902SRodney W. Grimes 	if (val > INT_MAX) {
341*9b50d902SRodney W. Grimes 		warnx("%s: %s", *gargv, strerror(ERANGE));
342*9b50d902SRodney W. Grimes 		return (1);
343*9b50d902SRodney W. Grimes 	}
344*9b50d902SRodney W. Grimes 	*ip = val;
345*9b50d902SRodney W. Grimes 	return (0);
346*9b50d902SRodney W. Grimes }
347*9b50d902SRodney W. Grimes 
348*9b50d902SRodney W. Grimes static int
349*9b50d902SRodney W. Grimes getlong(lp)
350*9b50d902SRodney W. Grimes 	long *lp;
351*9b50d902SRodney W. Grimes {
352*9b50d902SRodney W. Grimes 	long val;
353*9b50d902SRodney W. Grimes 	char *ep;
354*9b50d902SRodney W. Grimes 
355*9b50d902SRodney W. Grimes 	if (!*gargv) {
356*9b50d902SRodney W. Grimes 		*lp = 0;
357*9b50d902SRodney W. Grimes 		return (0);
358*9b50d902SRodney W. Grimes 	}
359*9b50d902SRodney W. Grimes 	if (strchr(Number, **gargv)) {
360*9b50d902SRodney W. Grimes 		errno = 0;
361*9b50d902SRodney W. Grimes 		val = strtol(*gargv, &ep, 0);
362*9b50d902SRodney W. Grimes 		if (*ep != '\0') {
363*9b50d902SRodney W. Grimes 			warnx("%s: illegal number", *gargv, NULL);
364*9b50d902SRodney W. Grimes 			return (1);
365*9b50d902SRodney W. Grimes 		}
366*9b50d902SRodney W. Grimes 		if (errno == ERANGE)
367*9b50d902SRodney W. Grimes 			if (val == LONG_MAX) {
368*9b50d902SRodney W. Grimes 				warnx("%s: %s", *gargv, strerror(ERANGE));
369*9b50d902SRodney W. Grimes 				return (1);
370*9b50d902SRodney W. Grimes 			}
371*9b50d902SRodney W. Grimes 			if (val == LONG_MIN) {
372*9b50d902SRodney W. Grimes 				warnx("%s: %s", *gargv, strerror(ERANGE));
373*9b50d902SRodney W. Grimes 				return (1);
374*9b50d902SRodney W. Grimes 			}
375*9b50d902SRodney W. Grimes 
376*9b50d902SRodney W. Grimes 		*lp = val;
377*9b50d902SRodney W. Grimes 		++gargv;
378*9b50d902SRodney W. Grimes 		return (0);
379*9b50d902SRodney W. Grimes 	}
380*9b50d902SRodney W. Grimes 	*lp =  (long)asciicode();
381*9b50d902SRodney W. Grimes 	return (0);
382*9b50d902SRodney W. Grimes }
383*9b50d902SRodney W. Grimes 
384*9b50d902SRodney W. Grimes static double
385*9b50d902SRodney W. Grimes getdouble()
386*9b50d902SRodney W. Grimes {
387*9b50d902SRodney W. Grimes 	if (!*gargv)
388*9b50d902SRodney W. Grimes 		return ((double)0);
389*9b50d902SRodney W. Grimes 	if (strchr(Number, **gargv))
390*9b50d902SRodney W. Grimes 		return (atof(*gargv++));
391*9b50d902SRodney W. Grimes 	return ((double)asciicode());
392*9b50d902SRodney W. Grimes }
393*9b50d902SRodney W. Grimes 
394*9b50d902SRodney W. Grimes static int
395*9b50d902SRodney W. Grimes asciicode()
396*9b50d902SRodney W. Grimes {
397*9b50d902SRodney W. Grimes 	register int ch;
398*9b50d902SRodney W. Grimes 
399*9b50d902SRodney W. Grimes 	ch = **gargv;
400*9b50d902SRodney W. Grimes 	if (ch == '\'' || ch == '"')
401*9b50d902SRodney W. Grimes 		ch = (*gargv)[1];
402*9b50d902SRodney W. Grimes 	++gargv;
403*9b50d902SRodney W. Grimes 	return (ch);
404*9b50d902SRodney W. Grimes }
405*9b50d902SRodney W. Grimes 
406*9b50d902SRodney W. Grimes static void
407*9b50d902SRodney W. Grimes usage()
408*9b50d902SRodney W. Grimes {
409*9b50d902SRodney W. Grimes 	(void)fprintf(stderr, "usage: printf format [arg ...]\n");
410*9b50d902SRodney W. Grimes }
411