2 Copyright (C) 2001-2003, 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"
31 =item C<static STRING *
32 getchr_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
34 Gets a C<char> out of the C<va_list> in C<obj> and returns it as a
44 getchr_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
46 va_list *arg
= (va_list *)(obj
->data
);
48 /* char promoted to int */
49 char ch
= (char)va_arg(*arg
, int);
51 return string_make(interpreter
, &ch
, 1, "iso-8859-1", 0);
56 =item C<static HUGEINTVAL
57 getint_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
59 Gets an integer out of the C<va_list> in C<obj> and returns it as a
62 C<size> is an C<enum spf_type_t> value which indicates the storage type
70 getint_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
72 va_list * const arg
= (va_list *)(obj
->data
);
76 return (HUGEINTVAL
)(int)va_arg(*arg
, int);
79 /* "'short int' is promoted to 'int' when passed through '...'" */
80 return (HUGEINTVAL
)(short)va_arg(*arg
, int);
83 return (HUGEINTVAL
)(long)va_arg(*arg
, long);
86 return (HUGEINTVAL
)(HUGEINTVAL
)
87 va_arg(*arg
, HUGEINTVAL
);
90 return (HUGEINTVAL
)(INTVAL
)va_arg(*arg
, INTVAL
);
93 return (HUGEINTVAL
)(opcode_t
)va_arg(*arg
, opcode_t
);
96 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
98 return (HUGEINTVAL
)(INTVAL
)
99 (VTABLE_get_integer(interpreter
, pmc
));
102 PANIC("Invalid int type!");
109 =item C<static UHUGEINTVAL
110 getuint_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
112 Gets an unsigned integer out of the C<va_list> in C<obj> and returns it
113 as a Parrot C<STRING>.
115 C<size> is an C<enum spf_type_t> value which indicates the storage type
123 getuint_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
125 va_list * const arg
= (va_list *)(obj
->data
);
129 return (UHUGEINTVAL
)(unsigned int)
130 va_arg(*arg
, unsigned int);
133 /* short int promoted HLAGHLAGHLAGH. See note above */
134 return (UHUGEINTVAL
)(unsigned short)
135 va_arg(*arg
, unsigned int);
138 return (UHUGEINTVAL
)(unsigned long)
139 va_arg(*arg
, unsigned long);
142 return (UHUGEINTVAL
)(UHUGEINTVAL
)
143 va_arg(*arg
, UHUGEINTVAL
);
146 return (UHUGEINTVAL
)(UINTVAL
)va_arg(*arg
, UINTVAL
);
149 return (UHUGEINTVAL
)(opcode_t
)va_arg(*arg
, opcode_t
);
152 PMC
*pmc
= (PMC
*)va_arg(*arg
, PMC
*);
154 return (UHUGEINTVAL
)(UINTVAL
)
155 (VTABLE_get_integer(interpreter
, pmc
));
158 PANIC("Invalid uint type!");
165 =item C<static HUGEFLOATVAL
166 getfloat_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
168 Gets an floating-point number out of the C<va_list> in C<obj> and
169 returns it as a Parrot C<STRING>.
171 C<size> is an C<enum spf_type_t> value which indicates the storage type of
179 getfloat_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
181 va_list * const arg
= (va_list *)(obj
->data
);
185 /* float is promoted to double */
186 return (HUGEFLOATVAL
)(float)va_arg(*arg
, double);
189 return (HUGEFLOATVAL
)(double)va_arg(*arg
, double);
192 return (HUGEFLOATVAL
)(HUGEFLOATVAL
)
193 va_arg(*arg
, HUGEFLOATVAL
);
196 return (HUGEFLOATVAL
)(FLOATVAL
)
197 va_arg(*arg
, FLOATVAL
);
200 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
202 return (HUGEFLOATVAL
)(VTABLE_get_number(interpreter
, pmc
));
205 internal_exception(INVALID_CHARACTER
,
206 "Internal sprintf doesn't recognize size %d for a float",
208 return (HUGEFLOATVAL
)0.0;
214 =item C<static STRING *
215 getstring_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
217 Gets an string out of the C<va_list> in C<obj> and returns it as a
220 C<size> is an C<enum spf_type_t> value which indicates the storage type
228 getstring_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
230 va_list * const arg
= (va_list *)(obj
->data
);
235 const char * const cstr
= (char *)va_arg(*arg
, char *);
237 return cstr2pstr(cstr
);
242 STRING
* const s
= (STRING
*)va_arg(*arg
, STRING
*);
243 return s
? s
: CONST_STRING(interpreter
, "(null)");
249 PMC
* const pmc
= (PMC
*)va_arg(*arg
, PMC
*);
250 STRING
* const s
= VTABLE_get_string(interpreter
, pmc
);
256 internal_exception(INVALID_CHARACTER
,
257 "Internal sprintf doesn't recognize size %d for a string",
265 =item C<static void *
266 getptr_va(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
268 Gets a C<void *> out of the C<va_list> in C<obj> and returns it.
277 getptr_va(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
279 va_list * const arg
= (va_list *)(obj
->data
);
281 return (void *)va_arg(*arg
, void *);
284 SPRINTF_OBJ va_core
= {
285 NULL
, 0, getchr_va
, getint_va
, getuint_va
,
286 getfloat_va
, getstring_va
, getptr_va
297 =item C<static STRING *
298 getchr_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
300 Same as C<getchr_va()> except that a vtable is used to get the value
308 getchr_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
311 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
316 s
= VTABLE_get_string(interpreter
, tmp
);
317 /* XXX string_copy like below? + adjusting bufused */
318 return string_substr(interpreter
, s
, 0, 1, NULL
, 0);
323 =item C<static HUGEINTVAL
324 getint_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
326 Same as C<getint_va()> except that a vtable is used to get the value
334 getint_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
337 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
342 ret
= (HUGEINTVAL
)(VTABLE_get_integer(interpreter
, tmp
));
346 ret
= (HUGEINTVAL
)(short)ret
;
348 /* case SIZE_REG: ret=(HUGEINTVAL)(int)ret; */
351 ret
= (HUGEINTVAL
)(long)ret
;
361 =item C<static UHUGEINTVAL
362 getuint_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
364 Same as C<getuint_va()> except that a vtable is used to get the value
372 getuint_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
375 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
380 ret
= (UHUGEINTVAL
)(VTABLE_get_integer(interpreter
, tmp
));
384 ret
= (UHUGEINTVAL
)(unsigned short)ret
;
386 /* case SIZE_REG: * ret=(UHUGEINTVAL)(unsigned int)ret; * break; */
388 ret
= (UHUGEINTVAL
)(unsigned long)ret
;
398 =item C<static HUGEFLOATVAL
399 getfloat_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
401 Same as C<getfloat_va()> except that a vtable is used to get the value
409 getfloat_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
412 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
417 ret
= (HUGEFLOATVAL
)(VTABLE_get_number(interpreter
, tmp
));
421 ret
= (HUGEFLOATVAL
)(float)ret
;
423 /* case SIZE_REG: * ret=(HUGEFLOATVAL)(double)ret; * break; */
433 =item C<static STRING *
434 getstring_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
436 Same as C<getstring_va()> except that a vtable is used to get the value
444 getstring_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
447 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
452 s
= (STRING
*)(VTABLE_get_string(interpreter
, tmp
));
458 =item C<static void *
459 getptr_pmc(Interp *interpreter, INTVAL size, SPRINTF_OBJ *obj)>
461 Same as C<getptr_va()> except that a vtable is used to get the value
469 getptr_pmc(Interp
*interpreter
, INTVAL size
, SPRINTF_OBJ
*obj
)
471 PMC
* const tmp
= VTABLE_get_pmc_keyed_int(interpreter
,
477 return (void *)(VTABLE_get_integer(interpreter
, tmp
));
480 SPRINTF_OBJ pmc_core
= {
481 NULL
, 0, getchr_pmc
, getint_pmc
, getuint_pmc
,
482 getfloat_pmc
, getstring_pmc
, getptr_pmc
491 F<src/misc.h>, F<src/misc.c>, F<src/spf_render.c>.
495 When I was first working on this implementation of sprintf, I ran into a
496 problem. I wanted to re-use the implementation for a Parrot
497 bytecode-level sprintf, but that couldn't be done, since it used C<va_*>
498 directly. For a while I thought about generating two versions of the
499 source with a Perl script, but that seemed like overkill. Eventually I
500 came across this idea -- pass in a specialized vtable with methods for
501 extracting things from the arglist, whatever it happened to be. This is
506 In the future, it may be deemed desirable to similarly vtable-ize
507 appending things to the string, allowing for faster C<PIO_printf()> &c,
508 as well as a version that writes directly to a C string. However, at
509 this point neither of those is needed.
518 * c-file-style: "parrot"
520 * vim: expandtab shiftwidth=4: