Index: src/ops/core.ops =================================================================== --- src/ops/core.ops (revision 41581) +++ src/ops/core.ops (working copy) @@ -1322,7 +1322,8 @@ } op dlfunc(out PMC, invar PMC, in STR, in STR) { - char * const name = Parrot_str_to_cstring(interp, ($3)); + PMC *namebuf = Parrot_str_to_cstring_managed(interp, ($3)); + char * const name = (char *)VTABLE_get_pointer(interp, namebuf); void *dl_handle = NULL; void *ptr = NULL; funcptr_t p; @@ -1350,11 +1351,11 @@ VTABLE_set_pointer_keyed_str(interp, $1, $4, F2DPTR(p)); PObj_get_FLAGS($1) |= PObj_private1_FLAG; } - Parrot_str_free_cstring(name); } op dlvar(out PMC, invar PMC, in STR) { - char * const name = Parrot_str_to_cstring(interp, ($3)); + PMC * const name_buf = Parrot_str_to_cstring_managed(interp, ($3)); + char * const name = (char *)VTABLE_get_pointer(interp, name_buf); void * p = NULL; void *dl_handle = NULL; @@ -1374,7 +1375,6 @@ $1 = pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, $1, p); } - Parrot_str_free_cstring(name); } inline op compreg(in STR, invar PMC) { Index: src/pmc/string.pmc =================================================================== --- src/pmc/string.pmc (revision 41581) +++ src/pmc/string.pmc (working copy) @@ -224,11 +224,11 @@ /* Only allow constant PMCs to embed constant strings */ if (PObj_constant_TEST(SELF) && !PObj_constant_TEST(value)) { - char *copy = Parrot_str_to_cstring(INTERP, value); + PMC *copybuf = Parrot_str_to_cstring_managed(INTERP, value); + char *copy = (char *)VTABLE_get_pointer(interp, copybuf); value = Parrot_str_new_init(INTERP, copy, strlen(copy), PARROT_DEFAULT_ENCODING, PARROT_DEFAULT_CHARSET, PObj_constant_FLAG); - Parrot_str_free_cstring(copy); } SET_ATTR_str_val(INTERP, SELF, value); @@ -716,8 +716,9 @@ enum_class_Integer)); /* TODO verify encoding */ - const STRING *me = VTABLE_get_string(INTERP, SELF); - char *str = Parrot_str_to_cstring(INTERP, me); + PMC *str_buf = Parrot_str_to_cstring_managed(INTERP, + VTABLE_get_string(INTERP, SELF)); + char *str = (char *)VTABLE_get_pointer(interp, str_buf); UINTVAL i = 0; size_t j = 0; size_t len = strlen(str); @@ -748,12 +749,10 @@ if (j < len) { char ch = str[j]; - Parrot_str_free_cstring(str); Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "invalid conversion to int - bad char %c", ch); } - Parrot_str_free_cstring(str); /* TODO: autopromote to BigInt instead of casting away the high bit */ VTABLE_set_integer_native(INTERP, result, (INTVAL)i); RETURN(PMC *result); Index: src/pmc/hash.pmc =================================================================== --- src/pmc/hash.pmc (revision 41581) +++ src/pmc/hash.pmc (working copy) @@ -303,20 +303,19 @@ for (j = 0; j < n; ++j) { STRING * const key = VTABLE_shift_string(INTERP, iter); - char * key_str; - size_t i, str_len; + size_t i; int all_digit = 1; PMC *val; + PMC *key_buf = Parrot_str_to_cstring_managed(INTERP, key); + char *key_str = (char *)VTABLE_get_pointer(interp, key_buf); + size_t str_len = strlen(key_str); - key_str = Parrot_str_to_cstring(INTERP, key); - str_len = strlen(key_str); for (i = 0; i < str_len; ++i) { if (!isdigit((unsigned char)key_str[i])) { all_digit = 0; break; } } - Parrot_str_free_cstring(key_str); if (all_digit) { res = Parrot_str_append(INTERP, res, key); Index: src/pmc/resizablebooleanarray.pmc =================================================================== --- src/pmc/resizablebooleanarray.pmc (revision 41581) +++ src/pmc/resizablebooleanarray.pmc (working copy) @@ -447,13 +447,14 @@ */ VTABLE void thaw(visit_info *info) { - unsigned char *bit_array; IMAGE_IO * const io = info->image_io; const UINTVAL head_pos = VTABLE_shift_integer(INTERP, io); const UINTVAL tail_pos = VTABLE_shift_integer(INTERP, io); STRING * const s = VTABLE_shift_string(INTERP, io); - - bit_array = (unsigned char*)Parrot_str_to_cstring(INTERP, s); + PMC *bit_array_buf = + Parrot_str_to_cstring_managed(INTERP, s); + unsigned char *bit_array = + (unsigned char*) VTABLE_get_pointer(interp, bit_array_buf); SET_ATTR_size(INTERP, SELF, tail_pos); SET_ATTR_resize_threshold(INTERP, SELF, head_pos); SET_ATTR_bit_array(INTERP, SELF, bit_array); Index: src/pmc/nci.pmc =================================================================== --- src/pmc/nci.pmc (revision 41581) +++ src/pmc/nci.pmc (working copy) @@ -209,11 +209,11 @@ /* ensure that the STRING signature is constant */ if (!PObj_constant_TEST(key)) { - char * const key_c = Parrot_str_to_cstring(INTERP, key); + PMC *key_buf = Parrot_str_to_cstring_managed(INTERP, key); + char * const key_c = (char *)VTABLE_get_pointer(interp, key_buf); size_t key_length = Parrot_str_byte_length(interp, key); key = string_make(interp, key_c, key_length, NULL, PObj_constant_FLAG); - Parrot_str_free_cstring(key_c); } nci_info->signature = key; @@ -301,7 +301,6 @@ VTABLE opcode_t *invoke(void *next) { Parrot_NCI_attributes * const nci_info = PARROT_NCI(SELF); nci_sub_t func; - char *sig_str; void *orig_func; PMC *cont; @@ -321,12 +320,14 @@ } if (nci_info->jitted) { + PMC *sig_buf; + char *sig_str; nci_jit_sub_t jit_func = (nci_jit_sub_t) D2FPTR(nci_info->func); /* Parrot_eprintf(interp, "JITTED %S\n", nci_info->signature); */ - sig_str = Parrot_str_to_cstring(interp, nci_info->pcc_params_signature); + sig_buf = Parrot_str_to_cstring_managed(interp, nci_info->pcc_params_signature); + sig_str = (char *)VTABLE_get_pointer(interp, sig_buf); jit_func(INTERP, SELF, sig_str); - Parrot_str_free_cstring(sig_str); } else { if (PObj_flag_TEST(private2, SELF)) { Index: src/pmc/sub.pmc =================================================================== --- src/pmc/sub.pmc (revision 41581) +++ src/pmc/sub.pmc (working copy) @@ -1000,20 +1000,18 @@ static const char types[] = "INSP"; char *p; Parrot_Sub_attributes *sub; - char * const kind = Parrot_str_to_cstring(interp, reg); + PMC *kindbuf = Parrot_str_to_cstring_managed(interp, reg); + char * const kind = (char *)VTABLE_get_pointer(interp, kindbuf); INTVAL regs_used; PMC_get_sub(INTERP, SELF, sub); PARROT_ASSERT(sub->n_regs_used); - if (!*kind || kind[1]) { - Parrot_str_free_cstring(kind); + if (!*kind || kind[1]) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, "illegal register kind '%Ss'", reg); - } p = strchr(types, *kind); - Parrot_str_free_cstring(kind); if (!p) Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, Index: src/datatypes.c =================================================================== --- src/datatypes.c (revision 41581) +++ src/datatypes.c (working copy) @@ -41,18 +41,16 @@ Parrot_get_datatype_enum(PARROT_INTERP, ARGIN(const STRING *type_name)) { ASSERT_ARGS(Parrot_get_datatype_enum) - char * const type = Parrot_str_to_cstring(interp, type_name); + PMC *typebuf = Parrot_str_to_cstring_managed(interp, type_name); + char * const type = (char *)VTABLE_get_pointer(interp, typebuf); int i; for (i = enum_first_type; i < enum_last_type; i++) { if (STREQ(data_types[i - enum_first_type].name, type)) { - Parrot_str_free_cstring(type); return i; } } - Parrot_str_free_cstring(type); - return enum_type_undef; } Index: src/packfile.c =================================================================== --- src/packfile.c (revision 41581) +++ src/packfile.c (working copy) @@ -4695,7 +4695,8 @@ enum_runtime_ft file_type) { ASSERT_ARGS(compile_or_load_file) - char * const filename = Parrot_str_to_cstring(interp, path); + PMC *filenamebuf = Parrot_str_to_cstring_managed(interp, path); + char * const filename = (char *)VTABLE_get_pointer(interp, filenamebuf); INTVAL regs_used[] = { 2, 2, 2, 2 }; /* Arbitrary values */ const int parrot_hll_id = 0; @@ -4706,7 +4707,6 @@ if (file_type == PARROT_RUNTIME_FT_PBC) { PackFile * const pf = PackFile_append_pbc(interp, filename); - Parrot_str_free_cstring(filename); if (!pf) Parrot_ex_throw_from_c_args(interp, NULL, 1, @@ -4723,7 +4723,6 @@ PackFile_ByteCode * const cs = (PackFile_ByteCode *)IMCC_compile_file_s(interp, filename, &err); - Parrot_str_free_cstring(filename); if (cs) do_sub_pragmas(interp, cs, PBC_LOADED, NULL); Index: src/string/api.c =================================================================== --- src/string/api.c (revision 41581) +++ src/string/api.c (working copy) @@ -2426,7 +2426,29 @@ return string_to_cstring_nullable(interp, s); } +/* +=item C + +Returns a PMC containing a C string for the specified Parrot string. Use +(char *) VTABLE_get_pointer to retrieve the C string and never free it, +is managed by the PMC. + +=cut + +*/ + +PARROT_EXPORT +PARROT_CANNOT_RETURN_NULL +PMC * +Parrot_str_to_cstring_managed(PARROT_INTERP, ARGIN(const STRING *s)) +{ + PMC *result = pmc_new(interp, enum_class_ManagedStruct); + char * const cstr = string_to_cstring_nullable(interp, s); + VTABLE_set_pointer(interp, result, cstr); + return result; +} + /* =item C Index: src/call/pcc.c =================================================================== --- src/call/pcc.c (revision 41581) +++ src/call/pcc.c (working copy) @@ -2994,8 +2994,9 @@ /* create the signature string, and the various PMCs that are needed to store all the parameters and parameter counts. */ - char * const signature = Parrot_str_to_cstring(interp, + PMC *signature_buf = Parrot_str_to_cstring_managed(interp, VTABLE_get_string(interp, sig_obj)); + char * const signature = (char *)VTABLE_get_pointer(interp, signature_buf); PMC * const args_sig = temporary_pmc_new(interp, enum_class_FixedIntegerArray); PMC * const results_sig = temporary_pmc_new(interp, @@ -3077,7 +3078,6 @@ interp->current_args = save_current_args; interp->args_signature = save_args_signature; interp->current_object = save_current_object; - Parrot_str_free_cstring(signature); } Index: include/parrot/string_funcs.h =================================================================== --- include/parrot/string_funcs.h (revision 41581) +++ include/parrot/string_funcs.h (working copy) @@ -412,6 +412,12 @@ __attribute__nonnull__(1); PARROT_EXPORT +PARROT_CANNOT_RETURN_NULL +PMC * Parrot_str_to_cstring_managed(PARROT_INTERP, ARGIN(const STRING *s)) + __attribute__nonnull__(1) + __attribute__nonnull__(2); + +PARROT_EXPORT PARROT_WARN_UNUSED_RESULT size_t Parrot_str_to_hashval(PARROT_INTERP, ARGMOD_NULLOK(STRING *s)) __attribute__nonnull__(1) @@ -673,6 +679,9 @@ , PARROT_ASSERT_ARG(s)) #define ASSERT_ARGS_Parrot_str_to_cstring __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp)) +#define ASSERT_ARGS_Parrot_str_to_cstring_managed __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(interp) \ + , PARROT_ASSERT_ARG(s)) #define ASSERT_ARGS_Parrot_str_to_hashval __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp)) #define ASSERT_ARGS_Parrot_str_to_int __attribute__unused__ int _ASSERT_ARGS_CHECK = (\