[perl-Cairo] Cairo::Surface: fix the exception conversion in callbacks



commit ca4a5749bf6449347a076f7447912f12dc956c71
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date:   Sun May 16 21:13:43 2010 +0200

    Cairo::Surface: fix the exception conversion in callbacks
    
    The recent fix of the off-by-one error in enum handling revealed a bug
    in the exception conversion from strings to cairo_status_t in the
    read/write callback marshallers.  When you do C<die 'no-memory'>, $@ is
    actually filled with 'no-memory at foo.pl line 23\n'.  The off-by-one
    error meant that this was converted successfully as if it was just
    'no-memory'.  This is not the case anymore, and so we need to strip off
    the location suffix before trying to convert to a cairo_status_t.

 CairoSurface.xs |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)
---
diff --git a/CairoSurface.xs b/CairoSurface.xs
index c146d9a..6b21116 100644
--- a/CairoSurface.xs
+++ b/CairoSurface.xs
@@ -166,6 +166,24 @@ cairo_perl_callback_free (CairoPerlCallback *callback)
 
 /* -------------------------------------------------------------------------- */
 
+/* Caller owns returned SV */
+static SV *
+strip_off_location (SV *error)
+{
+	SV *saved_defsv, *result;
+	saved_defsv = newSVsv (DEFSV);
+	ENTER;
+	SAVETMPS;
+	sv_setsv (DEFSV, error);
+	eval_pv ("s/^([-_\\w]+) .+$/$1/s", FALSE);
+	result = newSVsv (DEFSV);
+	FREETMPS;
+	LEAVE;
+	sv_setsv (DEFSV, saved_defsv);
+	SvREFCNT_dec (saved_defsv);
+	return result;
+}
+
 static cairo_status_t
 write_func_marshaller (void *closure,
                        const unsigned char *data,
@@ -192,7 +210,9 @@ write_func_marshaller (void *closure,
 	SPAGAIN;
 
 	if (SvTRUE (ERRSV)) {
-		status = SvCairoStatus (ERRSV);
+		SV *sv = strip_off_location (ERRSV);
+		status = SvCairoStatus (sv);
+		SvREFCNT_dec (sv);
 	}
 
 	PUTBACK;
@@ -230,7 +250,9 @@ read_func_marshaller (void *closure,
 	SPAGAIN;
 
 	if (SvTRUE (ERRSV)) {
-		status = SvCairoStatus (ERRSV);
+		SV *sv = strip_off_location (ERRSV);
+		status = SvCairoStatus (sv);
+		SvREFCNT_dec (sv);
 	} else {
 		SV *retval = POPs;
 		memcpy (data, SvPV_nolen (retval), sv_len (retval));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]