1 /*
2 Copyright (C) 2001-2014, Parrot Foundation.
3 
4 =head1 NAME
5 
6 src/string/sprintf.c - sprintf API routines
7 
8 =head1 DESCRIPTION
9 
10 This file implements the sprintf family of API routines. These routines
11 take different forms, but all redirect to a common generalized formatting
12 algorithm in F<src/spf_render.c> with a specialized vtables in
13 F<src/spf_vtable.c> to handle argument extraction.
14 
15 =head2 Functions
16 
17 The naming convention used is:
18 
19 =over 4
20 
21 =item C<Parrot_v?n?sprintf>
22 
23 A (nearly) drop-in replacement for v?n?sprintf.
24 
25 =item  C<Parrot_v?sprintf_c>
26 
27 Takes a C-string format, returns a Parrot string.
28 
29 =item  C<Parrot_v?sprintf_s>
30 
31 Takes a Parrot string format, returns a Parrot string.
32 
33 So the C<_> means "returns Parrot string" and the other letter indicates
34 the type for the format.
35 
36 =cut
37 
38 */
39 
40 #include "parrot/parrot.h"
41 #include "spf_private.h"
42 
43 /* HEADERIZER HFILE: include/parrot/string_funcs.h */
44 
45 /*
46 
47 =item C<STRING * Parrot_vsprintf_s(PARROT_INTERP, STRING *pat, va_list args)>
48 
49 Almost all the other sprintf variants in this file are implemented in
50 terms of this function (see C<Parrot_psprintf()> for the exception). It
51 in turn calls C<Parrot_sprintf_format()> (see F<src/string/spf_render.c>).
52 
53 =cut
54 
55 */
56 
57 PARROT_EXPORT
58 PARROT_WARN_UNUSED_RESULT
59 PARROT_CANNOT_RETURN_NULL
60 STRING *
Parrot_vsprintf_s(PARROT_INTERP,ARGIN (STRING * pat),va_list args)61 Parrot_vsprintf_s(PARROT_INTERP, ARGIN(STRING *pat), va_list args)
62 {
63     ASSERT_ARGS(Parrot_vsprintf_s)
64     SPRINTF_OBJ obj = va_core;
65     obj.data = PARROT_VA_TO_VAPTR(args);
66 
67     return Parrot_sprintf_format(interp, pat, &obj);
68 }
69 
70 /*
71 
72 =item C<STRING * Parrot_vsprintf_c(PARROT_INTERP, ARGIN_FORMAT(const char *pat),
73 va_list args)>
74 
75 C string version of C<Parrot_vsprintf_s()>.
76 
77 =cut
78 
79 */
80 
81 PARROT_EXPORT
82 PARROT_CANNOT_RETURN_NULL
83 PARROT_WARN_UNUSED_RESULT
84 STRING *
Parrot_vsprintf_c(PARROT_INTERP,ARGIN_FORMAT (const char * pat),va_list args)85 Parrot_vsprintf_c(PARROT_INTERP, ARGIN_FORMAT(const char *pat), va_list args)
86 {
87     ASSERT_ARGS(Parrot_vsprintf_c)
88     STRING * const realpat = Parrot_str_new_init(interp, pat, strlen(pat),
89             Parrot_default_encoding_ptr, PObj_external_FLAG);
90 
91     STRING * const ret = Parrot_vsprintf_s(interp, realpat, args);
92 
93     return ret;
94 }
95 
96 /*
97 
98 =item C<void Parrot_vsnprintf(PARROT_INTERP, char *targ, size_t len,
99 ARGIN_FORMAT(const char *pat), va_list args)>
100 
101 Similar to C<Parrot_vsprintf()> but with an option to specify the length
102 (C<len>) of the returned C string.
103 
104 If len is zero, then C<targ> is unchanged.
105 
106 =cut
107 
108 */
109 
110 PARROT_EXPORT
111 void
Parrot_vsnprintf(PARROT_INTERP,ARGMOD (char * targ),size_t len,ARGIN_FORMAT (const char * pat),va_list args)112 Parrot_vsnprintf(PARROT_INTERP, ARGMOD(char *targ),
113                  size_t len, ARGIN_FORMAT(const char *pat), va_list args)
114 {
115     ASSERT_ARGS(Parrot_vsnprintf)
116 
117     if (len == 0)
118         return;
119     --len;
120     if (len) {
121         const STRING * const ret = Parrot_vsprintf_c(interp, pat, args);
122         /* string_transcode(interp, ret, NULL, NULL, &ret); */
123 
124         char     * const str_ret = Parrot_str_to_cstring(interp, ret);
125         const    size_t  str_len = strlen(str_ret);
126         if (len > str_len) {
127             len = str_len;
128         }
129 
130         if (len)
131             memcpy(targ, str_ret, len);
132         Parrot_str_free_cstring(str_ret);
133     }
134     targ[len] = 0;
135 }
136 
137 /*
138 
139 =item C<STRING * Parrot_sprintf_s(PARROT_INTERP, STRING *pat, ...)>
140 
141 Calls C<Parrot_vsprintf_s()> with the C<va_list> obtained from C<...>.
142 
143 =cut
144 
145 */
146 
147 PARROT_EXPORT
148 PARROT_WARN_UNUSED_RESULT
149 PARROT_CANNOT_RETURN_NULL
150 STRING *
Parrot_sprintf_s(PARROT_INTERP,ARGIN (STRING * pat),...)151 Parrot_sprintf_s(PARROT_INTERP, ARGIN(STRING *pat), ...)
152 {
153     ASSERT_ARGS(Parrot_sprintf_s)
154     STRING *ret;
155     va_list args;
156 
157     va_start(args, pat);
158     ret = Parrot_vsprintf_s(interp, pat, args);
159     va_end(args);
160 
161     return ret;
162 }
163 
164 /*
165 
166 =item C<STRING * Parrot_sprintf_c(PARROT_INTERP, ARGIN_FORMAT(const char *pat),
167 ...)>
168 
169 C string version of C<Parrot_sprintf_s()>.
170 
171 =cut
172 
173 */
174 
175 PARROT_EXPORT
176 PARROT_WARN_UNUSED_RESULT
177 PARROT_CANNOT_RETURN_NULL
178 STRING *
Parrot_sprintf_c(PARROT_INTERP,ARGIN_FORMAT (const char * pat),...)179 Parrot_sprintf_c(PARROT_INTERP, ARGIN_FORMAT(const char *pat), ...)
180 {
181     ASSERT_ARGS(Parrot_sprintf_c)
182     STRING *ret;
183     va_list args;
184 
185     va_start(args, pat);
186     ret = Parrot_vsprintf_c(interp, pat, args);
187     va_end(args);
188 
189     return ret;
190 }
191 
192 /*
193 
194 =item C<void Parrot_snprintf(PARROT_INTERP, char *targ, size_t len,
195 ARGIN_FORMAT(const char *pat), ...)>
196 
197 Similar to C<Parrot_sprintf()> but with an option to specify the length
198 (C<len>) of the returned C string.
199 
200 =cut
201 
202 */
203 
204 PARROT_EXPORT
205 void
Parrot_snprintf(PARROT_INTERP,ARGOUT (char * targ),size_t len,ARGIN_FORMAT (const char * pat),...)206 Parrot_snprintf(PARROT_INTERP, ARGOUT(char *targ), size_t len,
207                 ARGIN_FORMAT(const char *pat), ...)
208 {
209     ASSERT_ARGS(Parrot_snprintf)
210     va_list args;
211 
212     va_start(args, pat);
213 
214     Parrot_vsnprintf(interp, targ, len, pat, args);
215 
216     va_end(args);
217 }
218 
219 /*
220 
221 =item C<STRING * Parrot_psprintf(PARROT_INTERP, STRING *pat, PMC *ary)>
222 
223 Calls C<Parrot_sprintf_format()> with the insertion arguments in an
224 C<Array> PMC.
225 
226 =cut
227 
228 */
229 
230 PARROT_EXPORT
231 PARROT_WARN_UNUSED_RESULT
232 PARROT_CANNOT_RETURN_NULL
233 STRING *
Parrot_psprintf(PARROT_INTERP,ARGIN (STRING * pat),ARGOUT (PMC * ary))234 Parrot_psprintf(PARROT_INTERP, ARGIN(STRING *pat), ARGOUT(PMC *ary))
235 {
236     ASSERT_ARGS(Parrot_psprintf)
237     SPRINTF_OBJ obj = pmc_core;
238     obj.data = ary;
239 
240     return Parrot_sprintf_format(interp, pat, &obj);
241 }
242 
243 /*
244 
245 =item C<int Parrot_secret_snprintf(char *buffer, size_t len, ARGIN_FORMAT(const
246 char *format), ...)>
247 
248 A simulation of C<snprintf> for systems that do not support it.
249 
250 =cut
251 
252 */
253 
254 
255 PARROT_EXPORT
256 PARROT_IGNORABLE_RESULT
257 int
Parrot_secret_snprintf(ARGOUT (char * buffer),SHIM (size_t len),ARGIN_FORMAT (const char * format),...)258 Parrot_secret_snprintf(ARGOUT(char *buffer), SHIM(size_t len),
259                        ARGIN_FORMAT(const char *format), ...)
260 {
261     ASSERT_ARGS(Parrot_secret_snprintf)
262     int retval;
263     va_list ap;
264     va_start(ap, format);
265     retval = vsprintf(buffer, format, ap);
266     va_end(ap);
267 
268     return retval;
269 }
270 
271 /*
272 
273 =item C<int Parrot_vfprintf(PARROT_INTERP, Parrot_PMC pio, ARGIN_FORMAT(const
274 char *s), va_list args)>
275 
276 Writes a C string format with a varargs list to a PIO.
277 
278 =item C<int Parrot_fprintf(PARROT_INTERP, Parrot_PMC pio, ARGIN_FORMAT(const
279 char *s), ...)>
280 
281 Writes a C string format with varargs to a PIO.
282 
283 =item C<int Parrot_printf(NULLOK_INTERP, ARGIN_FORMAT(const char *s), ...)>
284 
285 Writes a C string format with varargs to C<stdout>
286 
287 =item C<int Parrot_eprintf(NULLOK_INTERP, ARGIN_FORMAT(const char *s), ...)>
288 
289 Writes a C string format with varargs to C<stderr>.
290 
291 =cut
292 
293 */
294 
295 PARROT_EXPORT
296 int
Parrot_vfprintf(PARROT_INTERP,ARGIN (Parrot_PMC pio),ARGIN_FORMAT (const char * s),va_list args)297 Parrot_vfprintf(PARROT_INTERP, ARGIN(Parrot_PMC pio),
298         ARGIN_FORMAT(const char *s), va_list args)
299 {
300     ASSERT_ARGS(Parrot_vfprintf)
301 
302     STRING * str = Parrot_vsprintf_c(interp, s, args);
303     return Parrot_io_write_s(interp, pio, str);
304 }
305 
306 PARROT_EXPORT
307 int
Parrot_fprintf(PARROT_INTERP,ARGIN (Parrot_PMC pio),ARGIN_FORMAT (const char * s),...)308 Parrot_fprintf(PARROT_INTERP, ARGIN(Parrot_PMC pio),
309         ARGIN_FORMAT(const char *s), ...)
310 {
311     ASSERT_ARGS(Parrot_fprintf)
312     va_list args;
313     INTVAL retval;
314 
315     va_start(args, s);
316     retval = Parrot_vfprintf(interp, pio, s, args);
317     va_end(args);
318 
319     return retval;
320 }
321 
322 PARROT_EXPORT
323 int
Parrot_printf(NULLOK_INTERP,ARGIN_FORMAT (const char * s),...)324 Parrot_printf(NULLOK_INTERP, ARGIN_FORMAT(const char *s), ...)
325 {
326     ASSERT_ARGS(Parrot_printf)
327     va_list args;
328     INTVAL retval;
329     va_start(args, s);
330 
331     if (interp)
332         retval = Parrot_vfprintf(interp, Parrot_io_STDOUT(interp), s, args);
333     else
334         retval = vfprintf(stdout, s, args);
335     va_end(args);
336 
337     return retval;
338 }
339 
340 PARROT_EXPORT
341 int
Parrot_eprintf(NULLOK_INTERP,ARGIN_FORMAT (const char * s),...)342 Parrot_eprintf(NULLOK_INTERP, ARGIN_FORMAT(const char *s), ...)
343 {
344     ASSERT_ARGS(Parrot_eprintf)
345     va_list args;
346     INTVAL retval;
347 
348     va_start(args, s);
349 
350     if (interp)
351         retval = Parrot_vfprintf(interp, Parrot_io_STDERR(interp), s, args);
352     else
353         retval = vfprintf(stderr, s, args);
354 
355     va_end(args);
356 
357     return retval;
358 }
359 
360 /*
361 
362 =back
363 
364 =head1 SEE ALSO
365 
366 F<src/string/spf_vtable.c>, F<src/string/spf_render.c>, F<include/parrot/misc.h>
367 
368 =cut
369 
370 */
371 
372 
373 /*
374  * Local variables:
375  *   c-file-style: "parrot"
376  * End:
377  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
378  */
379