1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
12 #ifdef __UCLIBC_MJN3_ONLY__
13 #warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case.
14 #endif /* __UCLIBC_MJN3_ONLY__ */
16 #ifdef __STDIO_BUFFERS
17 /* NB: we can still have __USE_OLD_VFPRINTF__ defined in this case! */
19 int vsnprintf(char *__restrict buf
, size_t size
,
20 const char * __restrict format
, va_list arg
)
25 /* __STDIO_STREAM_RESET_GCS(&f); */
26 #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
27 f
.__cookie
= &(f
.__filedes
);
34 f
.__filedes
= __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES
;
35 f
.__modeflags
= (__FLAG_NARROW
|__FLAG_WRITEONLY
|__FLAG_WRITING
);
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 */
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
);
50 if (size
> SIZE_MAX
- (size_t) buf
) {
51 size
= SIZE_MAX
- (size_t) buf
;
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
);
63 #ifdef __USE_OLD_VFPRINTF__
64 rv
= vfprintf(&f
, format
, arg
);
66 rv
= _vfprintf_internal(&f
, format
, arg
);
69 if (f
.__bufpos
== f
.__bufend
) {
76 libc_hidden_def(vsnprintf
)
78 #elif defined(__USE_OLD_VFPRINTF__)
82 unsigned char *bufend
; /* pointer to 1 past end of buffer */
83 unsigned char *bufpos
;
86 int vsnprintf(char *__restrict buf
, size_t size
,
87 const char * __restrict format
, va_list arg
)
94 if (size
> SIZE_MAX
- (size_t) buf
) {
95 size
= SIZE_MAX
- (size_t) buf
;
97 f
.bufend
= buf
+ size
;
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
;
108 f
.f
.__filedes
= __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB
;
109 f
.f
.__modeflags
= (__FLAG_NARROW
|__FLAG_WRITEONLY
|__FLAG_WRITING
);
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 */
118 #ifdef __UCLIBC_HAS_THREADS__
119 f
.f
.__user_locking
= 1; /* Set user locking. */
120 STDIO_INIT_MUTEX(f
.f
.__lock
);
122 f
.f
.__nextopen
= NULL
;
124 rv
= vfprintf((FILE *) &f
, format
, arg
);
126 if (f
.bufpos
== f
.bufend
) {
133 libc_hidden_def(vsnprintf
)
135 #elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
144 #define COOKIE ((__snpf_cookie *) cookie)
146 static ssize_t
snpf_write(register void *cookie
, const char *buf
,
152 /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */
154 if (COOKIE
->len
> COOKIE
->pos
) {
155 count
= COOKIE
->len
- COOKIE
->pos
- 1; /* Leave space for nul. */
156 if (count
> bufsize
) {
160 p
= COOKIE
->buf
+ COOKIE
->pos
;
168 COOKIE
->pos
+= bufsize
;
175 int vsnprintf(char *__restrict buf
, size_t size
,
176 const char * __restrict format
, va_list arg
)
179 __snpf_cookie cookie
;
187 f
.__cookie
= &cookie
;
188 f
.__gcs
.write
= snpf_write
;
191 f
.__gcs
.close
= NULL
;
193 f
.__filedes
= -1; /* For debugging. */
194 f
.__modeflags
= (__FLAG_NARROW
|__FLAG_WRITEONLY
|__FLAG_WRITING
);
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 */
205 rv
= _vfprintf_internal(&f
, format
, arg
);
209 libc_hidden_def(vsnprintf
)
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!