Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/common/libc/printf/snprintf.c
2093 views
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
158
159