/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- __snprintf_send
- vsnprintf
- snprintf
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * This file is shared between libc and the kernel, so don't put anything
32 * in here that won't work in both contexts.
33 */
34
35 #ifdef _KERNEL
36 #include <types.h>
37 #include <lib.h>
38
39 #else
40 #include <stdio.h>
41
42 #endif /* _KERNEL */
43
44 #include <stdarg.h>
45
46 /*
47 * Standard C string/IO function: printf into a character buffer.
48 */
49
50
51 /*
52 * Context structure for snprintf: buffer to print into, maximum
53 * length, and index of the next character to write.
54 *
55 * Note that while the length argument to snprintf includes space for
56 * a null terminator, SNP.buflen does not. This is to make something
57 * vaguely reasonable happen if a length of 0 is passed to snprintf.
58 */
59
60 typedef struct {
61 char *buf;
62 size_t buflen;
63 size_t bufpos;
64 } SNP;
65
66 /*
67 * Send function for snprintf. This is the function handed to the
68 * printf guts. It gets called with mydata pointing to the context,
69 * and some string data of length LEN in DATA. DATA is not necessarily
70 * null-terminated.
71 */
72
73 static
74 void
75 __snprintf_send(void *mydata, const char *data, size_t len)
76 {
77 SNP *snp = mydata;
78 unsigned i;
79
80 /* For each character we're sent... */
81 for (i=0; i<len; i++) {
82
83 /* If we aren't past the length, */
84 if (snp->bufpos < snp->buflen) {
85
86 /* store the character */
87 snp->buf[snp->bufpos] = data[i];
88
89 /* and increment the position. */
90 snp->bufpos++;
91 }
92 }
93 }
94
95 /*
96 * The va_list version of snprintf.
97 */
98 int
99 vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
100 {
101 int chars;
102 SNP snp;
103
104 /*
105 * Fill in the context structure.
106 * We set snp.buflen to the number of characters that can be
107 * written (excluding the null terminator) so as not to have
108 * to special-case the possibility that we got passed a length
109 * of zero elsewhere.
110 */
111 snp.buf = buf;
112 if (len==0) {
113 snp.buflen = 0;
114 }
115 else {
116 snp.buflen = len-1;
117 }
118 snp.bufpos = 0;
119
120 /* Call __vprintf to do the actual work. */
121 chars = __vprintf(__snprintf_send, &snp, fmt, ap);
122
123 /*
124 * Add a null terminator. If the length *we were passed* is greater
125 * than zero, we reserved a space in the buffer for the terminator,
126 * so this won't overflow. If the length we were passed is zero,
127 * nothing will have been or should be written anyway, and buf
128 * might even be NULL. (C99 explicitly endorses this possibility.)
129 */
130 if (len > 0) {
131 buf[snp.bufpos] = 0;
132 }
133
134 /*
135 * Return the number of characters __vprintf processed.
136 * According to C99, snprintf should return this number, not
137 * the number of characters actually stored, and should not
138 * return -1 on overflow but only on other errors. (All none
139 * of them since we don't do multibyte characters...)
140 */
141 return chars;
142 }
143
144 /*
145 * snprintf - hand off to vsnprintf.
146 */
147 int
148 snprintf(char *buf, size_t len, const char *fmt, ...)
149 {
150 int chars;
151 va_list ap;
152 va_start(ap, fmt);
153 chars = vsnprintf(buf, len, fmt, ap);
154 va_end(ap);
155 return chars;
156 }
157