]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsnprintf.c
07cff341094900ee19407ae5ccc8a83c44b2a7f4
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / stdio / vsnprintf.c
1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7
8 #include "_stdio.h"
9 #include <stdarg.h>
10
11
12 #ifdef __UCLIBC_MJN3_ONLY__
13 #warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case.
14 #endif /* __UCLIBC_MJN3_ONLY__ */
15
16 #ifdef __STDIO_BUFFERS
17 /* NB: we can still have __USE_OLD_VFPRINTF__ defined in this case! */
18
19 int vsnprintf(char *__restrict buf, size_t size,
20                           const char * __restrict format, va_list arg)
21 {
22         FILE f;
23         int rv;
24
25 /*      __STDIO_STREAM_RESET_GCS(&f); */
26 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
27         f.__cookie = &(f.__filedes);
28         f.__gcs.read = NULL;
29         f.__gcs.write = NULL;
30         f.__gcs.seek = NULL;
31         f.__gcs.close = NULL;
32 #endif
33
34         f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES;
35         f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
36
37 #ifdef __UCLIBC_HAS_WCHAR__
38         f.__ungot_width[0] = 0;
39 #endif /* __UCLIBC_HAS_WCHAR__ */
40 #ifdef __STDIO_MBSTATE
41         __INIT_MBSTATE(&(f.__state));
42 #endif /* __STDIO_MBSTATE */
43
44 #if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__)
45         f.__user_locking = 1;           /* Set user locking. */
46         __stdio_init_mutex(&f.__lock);
47 #endif
48         f.__nextopen = NULL;
49
50         if (size > SIZE_MAX - (size_t) buf) {
51                 size = SIZE_MAX - (size_t) buf;
52         }
53
54 /* TODO: this comment seems to be wrong */
55         /* Set these last since __bufputc initialization depends on
56          * __user_locking and only gets set if user locking is on. */
57         f.__bufstart = (unsigned char *) buf;
58         f.__bufend = (unsigned char *) buf + size;
59         __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f);
60         __STDIO_STREAM_DISABLE_GETC(&f);
61         __STDIO_STREAM_ENABLE_PUTC(&f);
62
63 #ifdef __USE_OLD_VFPRINTF__
64         rv = vfprintf(&f, format, arg);
65 #else
66         rv = _vfprintf_internal(&f, format, arg);
67 #endif
68         if (size) {
69                 if (f.__bufpos == f.__bufend) {
70                         --f.__bufpos;
71                 }
72                 *f.__bufpos = 0;
73         }
74         return rv;
75 }
76 libc_hidden_def(vsnprintf)
77
78 #elif defined(__USE_OLD_VFPRINTF__)
79
80 typedef struct {
81         FILE f;
82         unsigned char *bufend;          /* pointer to 1 past end of buffer */
83         unsigned char *bufpos;
84 } __FILE_vsnprintf;
85
86 int vsnprintf(char *__restrict buf, size_t size,
87                           const char * __restrict format, va_list arg)
88 {
89         __FILE_vsnprintf f;
90         int rv;
91
92         f.bufpos = buf;
93
94         if (size > SIZE_MAX - (size_t) buf) {
95                 size = SIZE_MAX - (size_t) buf;
96         }
97         f.bufend = buf + size;
98
99 /*      __STDIO_STREAM_RESET_GCS(&f.f); */
100 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
101         f.f.__cookie = &(f.f.__filedes);
102         f.f.__gcs.read = NULL;
103         f.f.__gcs.write = NULL;
104         f.f.__gcs.seek = NULL;
105         f.f.__gcs.close = NULL;
106 #endif
107
108         f.f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB;
109         f.f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
110
111 #ifdef __UCLIBC_HAS_WCHAR__
112         f.f.__ungot_width[0] = 0;
113 #endif /* __UCLIBC_HAS_WCHAR__ */
114 #ifdef __STDIO_MBSTATE
115         __INIT_MBSTATE(&(f.f.__state));
116 #endif /* __STDIO_MBSTATE */
117
118 #ifdef __UCLIBC_HAS_THREADS__
119         f.f.__user_locking = 1;         /* Set user locking. */
120         __stdio_init_mutex(&f.f.__lock);
121 #endif
122         f.f.__nextopen = NULL;
123
124         rv = vfprintf((FILE *) &f, format, arg);
125         if (size) {
126                 if (f.bufpos == f.bufend) {
127                         --f.bufpos;
128                 }
129                 *f.bufpos = 0;
130         }
131         return rv;
132 }
133 libc_hidden_def(vsnprintf)
134
135 #elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
136
137 typedef struct {
138         size_t pos;
139         size_t len;
140         unsigned char *buf;
141         FILE *fp;
142 } __snpf_cookie;
143
144 #define COOKIE ((__snpf_cookie *) cookie)
145
146 static ssize_t snpf_write(register void *cookie, const char *buf,
147                                                   size_t bufsize)
148 {
149         size_t count;
150         register char *p;
151
152         /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */
153
154         if (COOKIE->len > COOKIE->pos) {
155                 count = COOKIE->len - COOKIE->pos - 1; /* Leave space for nul. */
156                 if (count > bufsize) {
157                         count = bufsize;
158                 }
159
160                 p = COOKIE->buf + COOKIE->pos;
161                 while (count) {
162                         *p++ = *buf++;
163                         --count;
164                 }
165                 *p = 0;
166         }
167
168         COOKIE->pos += bufsize;
169
170         return bufsize;
171 }
172
173 #undef COOKIE
174
175 int vsnprintf(char *__restrict buf, size_t size,
176                           const char * __restrict format, va_list arg)
177 {
178         FILE f;
179         __snpf_cookie cookie;
180         int rv;
181
182         cookie.buf = buf;
183         cookie.len = size;
184         cookie.pos = 0;
185         cookie.fp = &f;
186
187         f.__cookie = &cookie;
188         f.__gcs.write = snpf_write;
189         f.__gcs.read = NULL;
190         f.__gcs.seek = NULL;
191         f.__gcs.close = NULL;
192
193         f.__filedes = -1;                       /* For debugging. */
194         f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
195
196 #ifdef __UCLIBC_HAS_WCHAR__
197         f.__ungot_width[0] = 0;
198 #endif /* __UCLIBC_HAS_WCHAR__ */
199 #ifdef __STDIO_MBSTATE
200         __INIT_MBSTATE(&(f.__state));
201 #endif /* __STDIO_MBSTATE */
202
203         f.__nextopen = NULL;
204
205         rv = _vfprintf_internal(&f, format, arg);
206
207         return rv;
208 }
209 libc_hidden_def(vsnprintf)
210
211 #else
212 #warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf!
213 #ifdef __STDIO_HAS_VSNPRINTF
214 #error WHOA! __STDIO_HAS_VSNPRINTF is defined!
215 #endif
216 #endif