Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / sandpoint / stand / netboot / printf.c
blob18364cbe8817b07a2f9fdd6a7fadaf4eebd86496
1 /* $NetBSD: printf.c,v 1.6 2009/01/12 08:06:54 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * printf -- format and write output using 'func' to write characters
36 #include <sys/types.h>
37 #include <machine/stdarg.h>
38 #include <lib/libsa/stand.h>
40 #define MAXSTR 80
42 static int _doprnt(void (*)(int), const char *, va_list);
43 static void pr_int(unsigned long, int, char *);
44 static void sputchar(int);
46 static char *sbuf, *ebuf;
48 void
49 printf(const char *fmt, ...)
51 va_list ap;
53 va_start(ap, fmt);
54 _doprnt(putchar, fmt, ap);
55 va_end(ap);
58 void
59 vprintf(const char *fmt, va_list ap)
62 _doprnt(putchar, fmt, ap);
65 int
66 sprintf(char *buf, const char *fmt, ...)
68 va_list ap;
70 sbuf = buf;
71 ebuf = buf + -(size_t)buf - 1;
72 va_start(ap, fmt);
73 _doprnt(sputchar, fmt, ap);
74 *sbuf = '\0';
75 return (sbuf - buf);
78 int
79 snprintf(char *buf, size_t size, const char *fmt, ...)
81 va_list ap;
83 sbuf = buf;
84 ebuf = buf + size - 1;
85 va_start(ap, fmt);
86 _doprnt(sputchar, fmt, ap);
87 *sbuf = '\0';
88 return (sbuf - buf);
91 static int
92 _doprnt(func, fmt, ap)
93 void (*func)(int); /* Function to put a character */
94 const char *fmt; /* Format string for pr_int/pr_float */
95 va_list ap; /* Arguments to pr_int/pr_float */
97 int i;
98 char *str;
99 char string[20];
100 int length;
101 int leftjust;
102 int longflag;
103 int fmax, fmin;
104 int leading;
105 int outcnt;
106 char fill;
107 char sign;
109 outcnt = 0;
110 while ((i = *fmt++) != '\0') {
111 if (i != '%') {
112 (*func)(i);
113 outcnt += 1;
114 continue;
116 if (*fmt == '%') {
117 (*func)(*fmt++);
118 outcnt += 1;
119 continue;
121 leftjust = (*fmt == '-');
122 if (leftjust)
123 fmt++;
124 fill = (*fmt == '0') ? *fmt++ : ' ';
125 if (*fmt == '*')
126 fmin = va_arg(ap, int);
127 else {
128 fmin = 0;
129 while ('0' <= *fmt && *fmt <= '9')
130 fmin = fmin * 10 + *fmt++ - '0';
132 if (*fmt != '.')
133 fmax = 0;
134 else {
135 fmt++;
136 if (*fmt == '*')
137 fmax = va_arg(ap, int);
138 else {
139 fmax = 0;
140 while ('0' <= *fmt && *fmt <= '9')
141 fmax = fmax * 10 + *fmt++ - '0';
144 longflag = (*fmt == 'l');
145 if (longflag)
146 fmt++;
147 if ((i = *fmt++) == '\0') {
148 (*func)('%');
149 outcnt += 1;
150 break;
152 str = string;
153 sign = ' ';
154 switch (i) {
155 case 'c':
156 str[0] = va_arg(ap, int);
157 str[1] = '\0';
158 fmax = 0;
159 fill = ' ';
160 break;
162 case 's':
163 str = va_arg(ap, char *);
164 fill = ' ';
165 break;
167 case 'd':
169 long l = va_arg(ap, long);
170 if (l < 0) { sign = '-' ; l = -l; }
171 pr_int((unsigned long)l, 10, str);
173 break;
175 case 'u':
176 pr_int(va_arg(ap, unsigned long), 10, str);
177 break;
179 case 'o':
180 pr_int(va_arg(ap, unsigned long), 8, str);
181 fmax = 0;
182 break;
184 case 'X':
185 case 'x':
186 pr_int(va_arg(ap, unsigned long), 16, str);
187 fmax = 0;
188 break;
190 case 'p':
191 pr_int(va_arg(ap, unsigned long), 16, str);
192 fill = '0';
193 fmin = 8;
194 fmax = 0;
195 (*func)('0'); (*func)('x');
196 outcnt += 2;
197 break;
198 default:
199 (*func)(i);
200 break;
202 for (i = 0; str[i] != '\0'; i++)
204 length = i;
205 if (fmin > MAXSTR || fmin < 0)
206 fmin = 0;
207 if (fmax > MAXSTR || fmax < 0)
208 fmax = 0;
209 leading = 0;
210 if (fmax != 0 || fmin != 0) {
211 if (fmax != 0 && length > fmax)
212 length = fmax;
213 if (fmin != 0)
214 leading = fmin - length;
215 if (sign == '-')
216 --leading;
218 outcnt += leading + length;
219 if (sign == '-')
220 outcnt += 1;
221 if (sign == '-' && fill == '0')
222 (*func)(sign);
223 if (leftjust == 0)
224 for (i = 0; i < leading; i++) (*func)(fill);
225 if (sign == '-' && fill == ' ')
226 (*func)(sign);
227 for (i = 0; i < length; i++)
228 (*func)(str[i]);
229 if (leftjust != 0)
230 for (i = 0; i < leading; i++) (*func)(fill);
232 return outcnt;
235 static void pr_int(lval, base, s)
236 unsigned long lval;
237 int base;
238 char *s;
240 char ptmp[12]; /* unsigned long requires 11 digit in octal form */
241 int i;
242 char *t = ptmp;
243 static const char hexdigit[] = "0123456789abcdef";
245 i = 1;
246 *t++ = '\0';
247 do {
248 *t++ = hexdigit[lval % base];
249 } while ((lval /= base) != 0 && ++i < sizeof(ptmp));
250 while ((*s++ = *--t) != '\0')
254 static void
255 sputchar(int c)
258 if (sbuf < ebuf)
259 *sbuf++ = c;