xref: /netbsd-src/sys/lib/libsa/subr_prf.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /*	$NetBSD: subr_prf.c,v 1.9 2003/04/27 11:12:14 tron Exp $	*/
2 
3 /*-
4  * Copyright (c) 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  *	@(#)printf.c	8.1 (Berkeley) 6/11/93
36  */
37 
38 /*
39  * Scaled down version of printf(3).
40  */
41 
42 #include <sys/cdefs.h>
43 #include <sys/types.h>
44 #include <machine/stdarg.h>
45 
46 #include "stand.h"
47 
48 static void kprintn(void (*)(int), u_long, int);
49 static void sputchar(int);
50 static void kdoprnt(void (*)(int), const char *, va_list);
51 
52 static char *sbuf, *ebuf;
53 
54 static void
55 sputchar(int c)
56 {
57 
58 	if (sbuf < ebuf)
59 		*sbuf++ = c;
60 }
61 
62 void
63 vprintf(const char *fmt, va_list ap)
64 {
65 
66 	kdoprnt(putchar, fmt, ap);
67 }
68 
69 int
70 vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
71 {
72 
73 	sbuf = buf;
74 	ebuf = buf + size - 1;
75 	kdoprnt(sputchar, fmt, ap);
76 	*sbuf = '\0';
77 	return (sbuf - buf);
78 }
79 
80 static void
81 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
82 {
83 	char *p;
84 	int ch;
85 	unsigned long ul;
86 	int lflag;
87 
88 	for (;;) {
89 		while ((ch = *fmt++) != '%') {
90 			if (ch == '\0')
91 				return;
92 			put(ch);
93 		}
94 		lflag = 0;
95 reswitch:	switch (ch = *fmt++) {
96 		case 'l':
97 			lflag = 1;
98 			goto reswitch;
99 		case 'c':
100 			ch = va_arg(ap, int);
101 				put(ch & 0x7f);
102 			break;
103 		case 's':
104 			p = va_arg(ap, char *);
105 			while ((ch = *p++))
106 				put(ch);
107 			break;
108 		case 'd':
109 			ul = lflag ?
110 			    va_arg(ap, long) : va_arg(ap, int);
111 			if ((long)ul < 0) {
112 				put('-');
113 				ul = -(long)ul;
114 			}
115 			kprintn(put, ul, 10);
116 			break;
117 		case 'o':
118 			ul = lflag ?
119 			    va_arg(ap, u_long) : va_arg(ap, u_int);
120 			kprintn(put, ul, 8);
121 			break;
122 		case 'u':
123 			ul = lflag ?
124 			    va_arg(ap, u_long) : va_arg(ap, u_int);
125 			kprintn(put, ul, 10);
126 			break;
127 		case 'p':
128 			put('0');
129 			put('x');
130 			lflag = 1;
131 			/* fall through */
132 		case 'x':
133 			ul = lflag ?
134 			    va_arg(ap, u_long) : va_arg(ap, u_int);
135 			kprintn(put, ul, 16);
136 			break;
137 		default:
138 			put('%');
139 			if (lflag)
140 				put('l');
141 			if (ch == '\0')
142 				return;
143 			put(ch);
144 		}
145 	}
146 }
147 
148 static void
149 kprintn(void (*put)(int), unsigned long ul, int base)
150 {
151 					/* hold a long in base 8 */
152 	char *p, buf[(sizeof(long) * NBBY / 3) + 1];
153 
154 	p = buf;
155 	do {
156 		*p++ = "0123456789abcdef"[ul % base];
157 	} while (ul /= base);
158 	do {
159 		put(*--p);
160 	} while (p > buf);
161 }
162