PARROT_WARN_UNUSED_RESULT INTVAL encoding_is_cclass(PARROT_INTERP, INTVAL flags, ARGIN(const STRING *src), UINTVAL offset) { ASSERT_ARGS(encoding_is_cclass) UINTVAL codepoint; if (offset >= src->strlen) return 0; codepoint = STRING_ord(interp, src, offset); if (codepoint >= 256) return u_iscclass(interp, codepoint, flags) != 0; return (Parrot_iso_8859_1_typetable[codepoint] & flags) ? 1 : 0; }
PARROT_EXPORT PARROT_WARN_UNUSED_RESULT INTVAL Parrot_io_parse_open_flags(PARROT_INTERP, ARGIN(const STRING *mode_str)) { ASSERT_ARGS(Parrot_io_parse_open_flags) INTVAL i, mode_len; INTVAL flags = 0; if (STRING_IS_NULL(mode_str)) return PIO_F_READ; mode_len = Parrot_str_byte_length(interp, mode_str); for (i = 0; i < mode_len; ++i) { const INTVAL s = STRING_ord(interp, mode_str, i); switch (s) { case 'r': flags |= PIO_F_READ; break; case 'w': flags |= PIO_F_WRITE; if (!(flags & PIO_F_APPEND)) /* don't truncate if appending */ flags |= PIO_F_TRUNC; break; case 'a': flags |= PIO_F_APPEND; flags |= PIO_F_WRITE; if ((flags & PIO_F_TRUNC)) /* don't truncate if appending */ flags &= ~PIO_F_TRUNC; break; case 'p': flags |= PIO_F_PIPE; break; case 'b': flags |= PIO_F_BINARY; break; default: break; } } return flags; }
PARROT_EXPORT PARROT_CANNOT_RETURN_NULL PARROT_WARN_UNUSED_RESULT PMC* Parrot_make_cb(PARROT_INTERP, ARGMOD(PMC* sub), ARGIN(PMC* user_data), ARGIN(STRING *cb_signature)) { ASSERT_ARGS(Parrot_make_cb) PMC *cb, *cb_sig; int type = 0; STRING *sc; /* * we stuff all the information into the user_data PMC and pass that * on to the external sub */ PMC * const interp_pmc = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, (INTVAL) IGLOBALS_INTERPRETER); if (default_interp == NULL) default_interp = interp; /* be sure __LINE__ is consistent */ sc = CONST_STRING(interp, "_interpreter"); Parrot_pmc_setprop(interp, user_data, sc, interp_pmc); sc = CONST_STRING(interp, "_sub"); Parrot_pmc_setprop(interp, user_data, sc, sub); /* only ASCII signatures are supported */ if (STRING_length(cb_signature) == 3) { /* Callback return type ignored */ if (STRING_ord(interp, cb_signature, 1) == 'U') { type = 'D'; } else { if (STRING_ord(interp, cb_signature, 2) == 'U') { type = 'C'; } } } if (type != 'C' && type != 'D') Parrot_ex_throw_from_c_args(interp, NULL, 1, "unhandled signature '%Ss' in make_cb", cb_signature); cb_sig = Parrot_pmc_new(interp, enum_class_String); VTABLE_set_string_native(interp, cb_sig, cb_signature); sc = CONST_STRING(interp, "_signature"); Parrot_pmc_setprop(interp, user_data, sc, cb_sig); /* * We are going to be passing the user_data PMC to external code, but * it may go out of scope until the callback is called -- we don't know * for certain as we don't know when the callback will be called. * Therefore, to prevent the PMC from being destroyed by a GC sweep, * we need to anchor it. * */ Parrot_pmc_gc_register(interp, user_data); /* * Finally, the external lib awaits a function pointer. * Create a PMC that points to Parrot_callback_C (or _D); * it can be passed on with signature 'p'. */ cb = Parrot_pmc_new(interp, enum_class_UnManagedStruct); /* * Currently, we handle only 2 types: * _C ... user_data is 2nd parameter * _D ... user_data is 1st parameter */ if (type == 'C') VTABLE_set_pointer(interp, cb, F2DPTR(Parrot_callback_C)); else VTABLE_set_pointer(interp, cb, F2DPTR(Parrot_callback_D)); Parrot_pmc_gc_register(interp, cb); return cb; }
PARROT_EXPORT void Parrot_run_callback(PARROT_INTERP, ARGMOD(PMC* user_data), ARGIN(void* external_data)) { ASSERT_ARGS(Parrot_run_callback) PMC *signature; PMC *sub; STRING *sig_str; INTVAL ch; char pasm_sig[5]; INTVAL i_param; PMC *p_param; void *param = NULL; /* avoid -Ox warning */ STRING *sc; sc = CONST_STRING(interp, "_sub"); sub = Parrot_pmc_getprop(interp, user_data, sc); sc = CONST_STRING(interp, "_signature"); signature = Parrot_pmc_getprop(interp, user_data, sc); sig_str = VTABLE_get_string(interp, signature); pasm_sig[0] = 'P'; ch = STRING_ord(interp, sig_str, 1); if (ch == 'U') /* user_data Z in pdd16 */ ch = STRING_ord(interp, sig_str, 2); /* ch is now type of external data */ switch (ch) { case 'v': pasm_sig[1] = 'v'; break; case 'l': /* FIXME: issue #742 */ i_param = (INTVAL)(long)(INTVAL) external_data; goto case_I; case 'i': /* FIXME: issue #742 */ i_param = (INTVAL)(int)(INTVAL) external_data; goto case_I; case 's': /* FIXME: issue #742 */ i_param = (INTVAL)(short)(INTVAL) external_data; goto case_I; case 'c': /* FIXME: issue #742 */ i_param = (INTVAL)(char)(INTVAL) external_data; case_I: pasm_sig[1] = 'I'; param = (void*) i_param; break; case 'p': /* created a UnManagedStruct */ p_param = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, p_param, external_data); pasm_sig[1] = 'P'; param = (void*) p_param; break; case 't': pasm_sig[1] = 'S'; param = Parrot_str_new(interp, (const char*)external_data, 0); break; default: Parrot_ex_throw_from_c_args(interp, NULL, 1, "unhandled signature char '%c' in run_cb", ch); } pasm_sig[2] = '-'; pasm_sig[3] = '>'; /* no return value supported yet */ pasm_sig[4] = '\0'; Parrot_ext_call(interp, sub, pasm_sig, user_data, param); }