2 Copyright (C) 2001-2007, The Perl Foundation.
7 src/spf_vtable.c - Parrot sprintf
11 Implements the two families of functions C<Parrot_sprintf> may use to
14 =head2 Var args Functions
24 #include "parrot/parrot.h"
27 #include "spf_vtable.str"
29 /* HEADERIZER HFILE: none */
31 /* HEADERIZER BEGIN: static */
32 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
34 PARROT_CANNOT_RETURN_NULL
35 PARROT_WARN_UNUSED_RESULT
36 static STRING
* getchr_pmc(PARROT_INTERP
,
38 ARGMOD(SPRINTF_OBJ
*obj
))
39 __attribute__nonnull__(1)
40 __attribute__nonnull__(3)
43 PARROT_CANNOT_RETURN_NULL
44 PARROT_WARN_UNUSED_RESULT
45 static STRING
* getchr_va(PARROT_INTERP
,
47 ARGIN(SPRINTF_OBJ
*obj
))
48 __attribute__nonnull__(1)
49 __attribute__nonnull__(3);
51 PARROT_WARN_UNUSED_RESULT
52 static HUGEFLOATVAL
getfloat_pmc(PARROT_INTERP
,
54 ARGIN(SPRINTF_OBJ
*obj
))
55 __attribute__nonnull__(1)
56 __attribute__nonnull__(3);
58 PARROT_WARN_UNUSED_RESULT
59 static HUGEFLOATVAL
getfloat_va(PARROT_INTERP
,
61 ARGIN(SPRINTF_OBJ
*obj
))
62 __attribute__nonnull__(1)
63 __attribute__nonnull__(3);
65 PARROT_WARN_UNUSED_RESULT
66 static HUGEINTVAL
getint_pmc(PARROT_INTERP
,
68 ARGIN(SPRINTF_OBJ
*obj
))
69 __attribute__nonnull__(1)
70 __attribute__nonnull__(3);
72 PARROT_WARN_UNUSED_RESULT
73 static HUGEINTVAL
getint_va(PARROT_INTERP
,
75 ARGIN(SPRINTF_OBJ
*obj
))
76 __attribute__nonnull__(1)
77 __attribute__nonnull__(3);
79 PARROT_WARN_UNUSED_RESULT
80 PARROT_CANNOT_RETURN_NULL
81 static void * getptr_pmc(PARROT_INTERP
,
83 ARGIN(SPRINTF_OBJ
*obj
))
84 __attribute__nonnull__(1)
85 __attribute__nonnull__(3);
87 PARROT_WARN_UNUSED_RESULT
88 PARROT_CAN_RETURN_NULL
89 static void * getptr_va(SHIM_INTERP
,
91 ARGIN(SPRINTF_OBJ
*obj
))
92 __attribute__nonnull__(3);
94 PARROT_WARN_UNUSED_RESULT
95 PARROT_CANNOT_RETURN_NULL
96 static STRING
* getstring_pmc(PARROT_INTERP
,
98 ARGIN(SPRINTF_OBJ
*obj
))
99 __attribute__nonnull__(1)
100 __attribute__nonnull__(3);
102 PARROT_WARN_UNUSED_RESULT
103 PARROT_CANNOT_RETURN_NULL
104 static STRING
* getstring_va(PARROT_INTERP
,
106 ARGIN(SPRINTF_OBJ
*obj
))
107 __attribute__nonnull__(1)
108 __attribute__nonnull__(3);
110 PARROT_WARN_UNUSED_RESULT
111 static UHUGEINTVAL
getuint_pmc(PARROT_INTERP
,
113 ARGIN(SPRINTF_OBJ
*obj
))
114 __attribute__nonnull__(1)
115 __attribute__nonnull__(3);
117 PARROT_WARN_UNUSED_RESULT
118 static UHUGEINTVAL
getuint_va(PARROT_INTERP
,
120 ARGIN(SPRINTF_OBJ
*obj
))
121 __attribute__nonnull__(1)
122 __attribute__nonnull__(3);
124 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
125 /* HEADERIZER END: static */
129 =item C<static STRING * getchr_va>
131 Gets a C<char> out of the C<va_list> in C<obj> and returns it as a
140 PARROT_CANNOT_RETURN_NULL
141 PARROT_WARN_UNUSED_RESULT
143 getchr_va(PARROT_INTERP
, SHIM(INTVAL size
), ARGIN(SPRINTF_OBJ
*obj
))
145 va_list *arg
= (va_list *)(obj
->data
);
147 /* char promoted to int */
148 char ch
= (char)va_arg(*arg
, int);
150 return string_make(interp
, &ch
, 1, "iso-8859-1", 0);
155 =item C<static HUGEINTVAL getint_va>
157 Gets an integer out of the C<va_list> in C<obj> and returns it as a
160 C<size> is an C<enum spf_type_t> value which indicates the storage type
167 PARROT_WARN_UNUSED_RESULT
169 getint_va(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
171 va_list * const arg
= (va_list *)(obj
->data
);
175 return va_arg(*arg
, int);
178 /* "'short int' is promoted to 'int' when passed through '...'" */
179 return (short)va_arg(*arg
, int);
182 return va_arg(*arg
, long);
185 return va_arg(*arg
, HUGEINTVAL
);
188 return va_arg(*arg
, INTVAL
);
191 return va_arg(*arg
, opcode_t
);
194 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
195 return VTABLE_get_integer(interp
, pmc
);
198 PANIC(interp
, "Invalid int type!");
204 =item C<static UHUGEINTVAL getuint_va>
206 Gets an unsigned integer out of the C<va_list> in C<obj> and returns it
207 as a Parrot C<STRING>.
209 C<size> is an C<enum spf_type_t> value which indicates the storage type
216 PARROT_WARN_UNUSED_RESULT
218 getuint_va(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
220 va_list * const arg
= (va_list *)(obj
->data
);
224 return va_arg(*arg
, unsigned int);
227 /* short int promoted HLAGHLAGHLAGH. See note above */
228 return (unsigned short)va_arg(*arg
, unsigned int);
231 return va_arg(*arg
, unsigned long);
234 return va_arg(*arg
, UHUGEINTVAL
);
237 return va_arg(*arg
, UINTVAL
);
240 return va_arg(*arg
, opcode_t
);
243 PMC
* const pmc
= va_arg(*arg
, PMC
*);
244 return (UINTVAL
)VTABLE_get_integer(interp
, pmc
);
247 PANIC(interp
, "Invalid uint type!");
253 =item C<static HUGEFLOATVAL getfloat_va>
255 Gets an floating-point number out of the C<va_list> in C<obj> and
256 returns it as a Parrot C<STRING>.
258 C<size> is an C<enum spf_type_t> value which indicates the storage type of
265 PARROT_WARN_UNUSED_RESULT
267 getfloat_va(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
269 va_list * const arg
= (va_list *)(obj
->data
);
273 /* float is promoted to double */
274 return (HUGEFLOATVAL
)(float)va_arg(*arg
, double);
277 return (HUGEFLOATVAL
)(double)va_arg(*arg
, double);
280 return (HUGEFLOATVAL
)(HUGEFLOATVAL
) va_arg(*arg
, HUGEFLOATVAL
);
283 return (HUGEFLOATVAL
)(FLOATVAL
) va_arg(*arg
, FLOATVAL
);
286 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
288 return (HUGEFLOATVAL
)(VTABLE_get_number(interp
, pmc
));
291 real_exception(interp
, NULL
, INVALID_CHARACTER
,
292 "Internal sprintf doesn't recognize size %d for a float", size
);
298 =item C<static STRING * getstring_va>
300 Gets an string out of the C<va_list> in C<obj> and returns it as a
303 C<size> is an C<enum spf_type_t> value which indicates the storage type
310 PARROT_WARN_UNUSED_RESULT
311 PARROT_CANNOT_RETURN_NULL
313 getstring_va(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
315 va_list * const arg
= (va_list *)(obj
->data
);
320 const char * const cstr
= (char *)va_arg(*arg
, char *);
322 return cstr2pstr(cstr
);
327 STRING
* const s
= (STRING
*)va_arg(*arg
, STRING
*);
328 return s
? s
: CONST_STRING(interp
, "(null)");
334 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
335 STRING
* const s
= VTABLE_get_string(interp
, pmc
);
341 real_exception(interp
, NULL
, INVALID_CHARACTER
,
342 "Internal sprintf doesn't recognize size %d for a string",
349 =item C<static void * getptr_va>
351 Gets a C<void *> out of the C<va_list> in C<obj> and returns it.
359 PARROT_WARN_UNUSED_RESULT
360 PARROT_CAN_RETURN_NULL
362 getptr_va(SHIM_INTERP
, SHIM(INTVAL size
), ARGIN(SPRINTF_OBJ
*obj
))
364 va_list * const arg
= (va_list *)(obj
->data
);
366 return (void *)va_arg(*arg
, void *);
369 const SPRINTF_OBJ va_core
= {
370 NULL
, 0, getchr_va
, getint_va
, getuint_va
,
371 getfloat_va
, getstring_va
, getptr_va
382 =item C<static STRING * getchr_pmc>
384 Same as C<getchr_va()> except that a vtable is used to get the value
391 PARROT_CANNOT_RETURN_NULL
392 PARROT_WARN_UNUSED_RESULT
394 getchr_pmc(PARROT_INTERP
, SHIM(INTVAL size
), ARGMOD(SPRINTF_OBJ
*obj
))
397 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
402 s
= VTABLE_get_string(interp
, tmp
);
403 /* XXX string_copy like below? + adjusting bufused */
404 return string_substr(interp
, s
, 0, 1, NULL
, 0);
409 =item C<static HUGEINTVAL getint_pmc>
411 Same as C<getint_va()> except that a vtable is used to get the value
418 PARROT_WARN_UNUSED_RESULT
420 getint_pmc(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
423 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
428 ret
= VTABLE_get_integer(interp
, tmp
);
434 /* case SIZE_REG: ret=(HUGEINTVAL)(int)ret; break; */
447 =item C<static UHUGEINTVAL getuint_pmc>
449 Same as C<getuint_va()> except that a vtable is used to get the value
456 PARROT_WARN_UNUSED_RESULT
458 getuint_pmc(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
461 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
466 ret
= (UINTVAL
)VTABLE_get_integer(interp
, tmp
);
470 ret
= (unsigned short)ret
;
472 /* case SIZE_REG: * ret=(UHUGEINTVAL)(unsigned int)ret; * break; */
474 ret
= (unsigned long)ret
;
485 =item C<static HUGEFLOATVAL getfloat_pmc>
487 Same as C<getfloat_va()> except that a vtable is used to get the value
494 PARROT_WARN_UNUSED_RESULT
496 getfloat_pmc(PARROT_INTERP
, INTVAL size
, ARGIN(SPRINTF_OBJ
*obj
))
499 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
504 ret
= (HUGEFLOATVAL
)(VTABLE_get_number(interp
, tmp
));
508 ret
= (HUGEFLOATVAL
)(float)ret
;
510 /* case SIZE_REG: * ret=(HUGEFLOATVAL)(double)ret; * break; */
520 =item C<static STRING * getstring_pmc>
522 Same as C<getstring_va()> except that a vtable is used to get the value
529 PARROT_WARN_UNUSED_RESULT
530 PARROT_CANNOT_RETURN_NULL
532 getstring_pmc(PARROT_INTERP
, SHIM(INTVAL size
), ARGIN(SPRINTF_OBJ
*obj
))
535 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
540 s
= (STRING
*)(VTABLE_get_string(interp
, tmp
));
546 =item C<static void * getptr_pmc>
548 Same as C<getptr_va()> except that a vtable is used to get the value
555 PARROT_WARN_UNUSED_RESULT
556 PARROT_CANNOT_RETURN_NULL
558 getptr_pmc(PARROT_INTERP
, SHIM(INTVAL size
), ARGIN(SPRINTF_OBJ
*obj
))
560 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interp
,
561 ((PMC
*)obj
->data
), (obj
->index
));
562 const INTVAL i
= VTABLE_get_integer(interp
, tmp
);
570 SPRINTF_OBJ pmc_core
= {
571 NULL
, 0, getchr_pmc
, getint_pmc
, getuint_pmc
,
572 getfloat_pmc
, getstring_pmc
, getptr_pmc
581 F<src/misc.h>, F<src/misc.c>, F<src/spf_render.c>.
585 When I was first working on this implementation of sprintf, I ran into a
586 problem. I wanted to re-use the implementation for a Parrot
587 bytecode-level sprintf, but that couldn't be done, since it used C<va_*>
588 directly. For a while I thought about generating two versions of the
589 source with a Perl script, but that seemed like overkill. Eventually I
590 came across this idea -- pass in a specialized vtable with methods for
591 extracting things from the arglist, whatever it happened to be. This is
596 In the future, it may be deemed desirable to similarly vtable-ize
597 appending things to the string, allowing for faster C<PIO_printf()> &c,
598 as well as a version that writes directly to a C string. However, at
599 this point neither of those is needed.
608 * c-file-style: "parrot"
610 * vim: expandtab shiftwidth=4: