1 /* $NetBSD: printf.c,v 1.6 2009/01/12 08:06:54 tsutsui Exp $ */
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
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
;
49 printf(const char *fmt
, ...)
54 _doprnt(putchar
, fmt
, ap
);
59 vprintf(const char *fmt
, va_list ap
)
62 _doprnt(putchar
, fmt
, ap
);
66 sprintf(char *buf
, const char *fmt
, ...)
71 ebuf
= buf
+ -(size_t)buf
- 1;
73 _doprnt(sputchar
, fmt
, ap
);
79 snprintf(char *buf
, size_t size
, const char *fmt
, ...)
84 ebuf
= buf
+ size
- 1;
86 _doprnt(sputchar
, fmt
, ap
);
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 */
110 while ((i
= *fmt
++) != '\0') {
121 leftjust
= (*fmt
== '-');
124 fill
= (*fmt
== '0') ? *fmt
++ : ' ';
126 fmin
= va_arg(ap
, int);
129 while ('0' <= *fmt
&& *fmt
<= '9')
130 fmin
= fmin
* 10 + *fmt
++ - '0';
137 fmax
= va_arg(ap
, int);
140 while ('0' <= *fmt
&& *fmt
<= '9')
141 fmax
= fmax
* 10 + *fmt
++ - '0';
144 longflag
= (*fmt
== 'l');
147 if ((i
= *fmt
++) == '\0') {
156 str
[0] = va_arg(ap
, int);
163 str
= va_arg(ap
, char *);
169 long l
= va_arg(ap
, long);
170 if (l
< 0) { sign
= '-' ; l
= -l
; }
171 pr_int((unsigned long)l
, 10, str
);
176 pr_int(va_arg(ap
, unsigned long), 10, str
);
180 pr_int(va_arg(ap
, unsigned long), 8, str
);
186 pr_int(va_arg(ap
, unsigned long), 16, str
);
191 pr_int(va_arg(ap
, unsigned long), 16, str
);
195 (*func
)('0'); (*func
)('x');
202 for (i
= 0; str
[i
] != '\0'; i
++)
205 if (fmin
> MAXSTR
|| fmin
< 0)
207 if (fmax
> MAXSTR
|| fmax
< 0)
210 if (fmax
!= 0 || fmin
!= 0) {
211 if (fmax
!= 0 && length
> fmax
)
214 leading
= fmin
- length
;
218 outcnt
+= leading
+ length
;
221 if (sign
== '-' && fill
== '0')
224 for (i
= 0; i
< leading
; i
++) (*func
)(fill
);
225 if (sign
== '-' && fill
== ' ')
227 for (i
= 0; i
< length
; i
++)
230 for (i
= 0; i
< leading
; i
++) (*func
)(fill
);
235 static void pr_int(lval
, base
, s
)
240 char ptmp
[12]; /* unsigned long requires 11 digit in octal form */
243 static const char hexdigit
[] = "0123456789abcdef";
248 *t
++ = hexdigit
[lval
% base
];
249 } while ((lval
/= base
) != 0 && ++i
< sizeof(ptmp
));
250 while ((*s
++ = *--t
) != '\0')