Change 23911 by [EMAIL PROTECTED] on 2005/01/31 18:00:31

        Add simple exception handling macros for XS writers.

Affected files ...

... //depot/perl/MANIFEST#1217 edit
... //depot/perl/XSUB.h#85 edit
... //depot/perl/ext/XS/APItest/APItest.pm#8 edit
... //depot/perl/ext/XS/APItest/APItest.xs#13 edit
... //depot/perl/ext/XS/APItest/t/exception.t#1 add
... //depot/perl/pod/perlguts.pod#125 edit

Differences ...

==== //depot/perl/MANIFEST#1217 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST#1216~23910~   Mon Jan 31 09:46:03 2005
+++ perl/MANIFEST       Mon Jan 31 10:00:31 2005
@@ -915,6 +915,7 @@
 ext/XS/APItest/MANIFEST                XS::APItest extension
 ext/XS/APItest/README          XS::APItest extension
 ext/XS/APItest/t/call.t                XS::APItest extension
+ext/XS/APItest/t/exception.t   XS::APItest extension
 ext/XS/APItest/t/hash.t                XS::APItest extension
 ext/XS/APItest/t/printf.t      XS::APItest extension
 ext/XS/APItest/t/push.t                XS::APItest extension

==== //depot/perl/XSUB.h#85 (text) ====
Index: perl/XSUB.h
--- perl/XSUB.h#84~23824~       Wed Jan 19 10:32:41 2005
+++ perl/XSUB.h Mon Jan 31 10:00:31 2005
@@ -192,6 +192,24 @@
 module's C<XS_VERSION> variable.  This is usually handled automatically by
 C<xsubpp>.  See L<perlxs/"The VERSIONCHECK: Keyword">.
 
+=head1 Simple Exception Handling Macros
+
+=for apidoc Ams||dXCPT
+Set up neccessary local variables for exception handling.
+See L<perlguts/"Exception Handling">.
+
+=for apidoc AmU||XCPT_TRY_START
+Starts a try block.  See L<perlguts/"Exception Handling">.
+
+=for apidoc AmU||XCPT_TRY_END
+Ends a try block.  See L<perlguts/"Exception Handling">.
+
+=for apidoc AmU||XCPT_CATCH
+Introduces a catch block.  See L<perlguts/"Exception Handling">.
+
+=for apidoc Ams||XCPT_RETHROW
+Rethrows a previously caught exception.  See L<perlguts/"Exception Handling">.
+
 =cut
 */
 
@@ -253,6 +271,12 @@
 #else
 #  define XS_VERSION_BOOTCHECK
 #endif
+
+#define dXCPT             dJMPENV; int rEtV = 0
+#define XCPT_TRY_START    JMPENV_PUSH(rEtV); if (rEtV == 0)
+#define XCPT_TRY_END      JMPENV_POP;
+#define XCPT_CATCH        if (rEtV != 0)
+#define XCPT_RETHROW      JMPENV_JUMP(rEtV)
 
 /* 
    The DBM_setFilter & DBM_ckFilter macros are only used by 

==== //depot/perl/ext/XS/APItest/APItest.pm#8 (text) ====
Index: perl/ext/XS/APItest/APItest.pm
--- perl/ext/XS/APItest/APItest.pm#7~23203~     Sat Aug  7 08:10:40 2004
+++ perl/ext/XS/APItest/APItest.pm      Mon Jan 31 10:00:31 2005
@@ -19,6 +19,7 @@
                  call_sv call_pv call_method eval_sv eval_pv require_pv
                  G_SCALAR G_ARRAY G_VOID G_DISCARD G_EVAL G_NOARGS
                  G_KEEPERR G_NODEBUG G_METHOD
+                 exception
 );
 
 # from cop.h 

==== //depot/perl/ext/XS/APItest/APItest.xs#13 (text) ====
Index: perl/ext/XS/APItest/APItest.xs
--- perl/ext/XS/APItest/APItest.xs#12~23203~    Sat Aug  7 08:10:40 2004
+++ perl/ext/XS/APItest/APItest.xs      Mon Jan 31 10:00:31 2005
@@ -2,6 +2,32 @@
 #include "perl.h"
 #include "XSUB.h"
 
+static void throws_exception(int throw_e)
+{
+  if (throw_e)
+    croak("boo\n");
+}
+
+static int exception(int throw_e)
+{
+  dTHR;
+  dXCPT;
+  SV *caught = get_sv("XS::APItest::exception_caught", 0);
+
+  XCPT_TRY_START {
+    throws_exception(throw_e);
+  } XCPT_TRY_END
+
+  XCPT_CATCH
+  {
+    sv_setiv(caught, 1);
+    XCPT_RETHROW;
+  }
+
+  sv_setiv(caught, 0);
+
+  return 42;
+}
 
 MODULE = XS::APItest:Hash              PACKAGE = XS::APItest::Hash
 
@@ -329,6 +355,9 @@
        PUTBACK;
        require_pv(pv);
 
-
-
+int
+exception(throw_e)
+    int throw_e
+    OUTPUT:
+        RETVAL
 

==== //depot/perl/ext/XS/APItest/t/exception.t#1 (text) ====
Index: perl/ext/XS/APItest/t/exception.t
--- /dev/null   Tue May  5 13:32:27 1998
+++ perl/ext/XS/APItest/t/exception.t   Mon Jan 31 10:00:31 2005
@@ -0,0 +1,33 @@
+BEGIN {
+    chdir 't' if -d 't';
+    @INC = '../lib';
+    push @INC, "::lib:$MacPerl::Architecture:" if $^O eq 'MacOS';
+    require Config; import Config;
+    if ($Config{'extensions'} !~ /\bXS\/APItest\b/) {
+        print "1..0 # Skip: XS::APItest was not built\n";
+        exit 0;
+    }
+}
+
+use Test::More tests => 8;
+
+BEGIN { use_ok('XS::APItest') };
+
+#########################
+
+my $rv;
+
+$XS::APItest::exception_caught = undef;
+
+$rv = eval { exception(0) };
+is($@, '');
+ok(defined $rv);
+is($rv, 42);
+is($XS::APItest::exception_caught, 0);
+
+$XS::APItest::exception_caught = undef;
+
+$rv = eval { exception(1) };
+is($@, "boo\n");
+ok(not defined $rv);
+is($XS::APItest::exception_caught, 1);

==== //depot/perl/pod/perlguts.pod#125 (text) ====
Index: perl/pod/perlguts.pod
--- perl/pod/perlguts.pod#124~23712~    Thu Dec 30 10:29:02 2004
+++ perl/pod/perlguts.pod       Mon Jan 31 10:00:31 2005
@@ -2260,6 +2260,34 @@
         AV *av = ...;
         UV  uv = PTR2UV(av);
 
+=head2 Exception Handling
+
+There are a couple of macros to do very basic exception handling in
+XS modules. You can use these macros if you call code that may croak,
+but you need to do some cleanup before giving control back to Perl.
+For example:
+
+        dXCPT;    /* set up neccessary variables */
+
+        XCPT_TRY_START {
+          code_that_may_croak();
+        } XCPT_TRY_END
+
+        XCPT_CATCH
+        {
+          /* do cleanup here */
+          XCPT_RETHROW;
+        }
+
+Note that you always have to rethrow an exception that has been
+caught. Using these macros, it is not possible to just catch the
+exception and ignore it. If you have to ignore the exception, you
+have to use the C<call_*> function.
+
+The advantage of using the above macros is that you don't have
+to setup an extra function for C<call_*>, and that using these
+macros is faster than using C<call_*>.
+
 =head2 Source Documentation
 
 There's an effort going on to document the internal functions and
End of Patch.

Reply via email to