TYPEMAP

INPUT
T_MAGIC
	{
	SV* arg = $arg;
	MAGIC* magic = SvROK(arg) && SvRMAGICAL(SvRV(arg)) ? mg_findext(SvRV(arg), PERL_MAGIC_ext, NULL) : NULL;
	if (magic)
		$var = ($type)magic->mg_ptr;
	else
		Perl_croak(aTHX_ \"%s object is lacking magic\", \"$ntype\");
	}

T_MAGICEXT
	{
	SV* arg = $arg;
	MAGIC* magic = SvROK(arg) && SvMAGICAL(SvRV(arg)) ? mg_findext(SvRV(arg), PERL_MAGIC_ext, &${type}_magic) : NULL;
	if (magic)
		$var = ($type)magic->mg_ptr;
	else
		Perl_croak(aTHX_ \"%s object is lacking magic\", \"$ntype\");
	}

T_MAGICEXT_BASE
	{
	SV* arg = $arg;
	MAGIC* magic = SvROK(arg) && SvMAGICAL(SvRV(arg)) ? mg_find(SvRV(arg), PERL_MAGIC_ext) : NULL;
	if (magic && magic->mg_virtual)
		$var = ($type)magic->mg_ptr;
	else
		Perl_croak(aTHX_ \"%s object is lacking magic\", \"$ntype\");
	}

T_OPAQUEOBJ
    {
		SV * sv = $arg;
		if (SvROK(sv) && SvPOK(SvRV(sv)) && SvCUR(SvRV(sv)) == sizeof(*$var))
			$var = ($type)SvPV_nolen(SvRV(sv));
		else
			croak(\"%s: %s is not of type %s\", ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]}, \"$var\", \"$ntype\");
    }

T_OPAQUEOBJ_MAYBE
	{
		SV * sv = $arg;
		if (SvOK(sv)) {
			if (SvROK(sv) && SvPOK(SvRV(sv)) && SvCUR(SvRV(sv)) == sizeof(*$var))
				$var = ($type)SvPV_nolen(SvRV(sv));
			else
				croak(\"%s: %s is not of type %s\", ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]}, \"$var\", \"$ntype\");
		} else
			$var = NULL;
	}


OUTPUT
T_MAGIC
	sv_magicext(newSVrv($arg, "$ntype"), NULL, PERL_MAGIC_ext, NULL, (const char*)$var, 0);
T_MAGICEXT
	{
	MAGIC* magic = sv_magicext(newSVrv($arg, "$ntype"), NULL, PERL_MAGIC_ext, &${type}_magic, (const char*)$var, 0);
	magic->mg_flags |= MGf_COPY|MGf_DUP;
	}

T_OPAQUEOBJ
	{
		sv_usepvn(newSVrv($arg, \"$ntype\"), (char*)$var, sizeof(*$var));
		SvREADONLY_on(SvRV($arg));
	}

T_OPAQUEOBJ_MAYBE
	if (SvOK($var)) {
		sv_usepvn(newSVrv($arg, \"$ntype\"), (char*)$var, sizeof(*$var));
		SvREADONLY_on(SvRV($arg));
	}