Fix build with xapian-core < 1.4.10
[xapian.git] / search-xapian / generate-perl-exceptions
blob6d267ca583ca682dde78525d24fc0ea69ac5d739
1 #!/usr/bin/perl -w
2 use strict;
4 # Author: Andreas Marienborg <andreas.marienborg@gmail.com>
5 # Donated as is to xapian project. Use and modify as see fit
7 BEGIN {
8 my $dir = shift || '.';
9 if ($dir eq '--help') {
10 print "Syntax: $0 [<path to srcdir> [<xapian version>]\n\n";
11 print "This script needs to know the source directory to find\n";
12 print "exception_data.pm - by default it looks in '.'.\n";
13 exit 0;
15 push(@INC, $dir);
17 $::version = shift || '';
18 if ($::version =~ /^(\d+)\.(\d+)\,(\d+)/) {
19 $::version = $1 * 1000000 + $2 * 1000 + $3;
20 } else {
21 # Assume 1.4.x if not specified.
22 $::version = 1004000;
26 # We load the exception data from xapian-core.
27 use exception_data qw(@baseclasses @classes %subclasses);
29 # Generate typemaps for Xapian::Error and its subclasses.
30 my $tm = "typemap-errorclasses";
31 open(TM, ">", "$tm.tmp")
32 or die "cannot write '$tm.tmp': $!\n";
34 foreach (@baseclasses, @classes) {
35 my ($classname, $parent, $desc) = split /\t/;
36 print TM "$classname\tO_OBJECT\n";
37 print TM "$classname *\tO_OBJECT\n";
39 close TM;
41 rename "$tm.tmp", $tm
42 or die "Failed to rename '$tm.tmp' to '$tm': $!\n";
44 my $fnm = "Xapian/Error.pm";
45 open F, '>', "$fnm.tmp" or die $!;
47 print F <<'END';
48 package Search::Xapian::Error;
50 =head1 NAME
52 Search::Xapian::Error - Base class for all exceptions in Search::Xapian
54 =head1 DESCRIPTION
56 This is an abstract class in C++, i.e. it cannot be instantiated directly.
57 In Perl there is no such concept, but you should not need to create instances
58 of this class yourself.
60 =head1 METHODS
62 All exception objects have the following methods
64 =head2 get_msg
66 Returns a string with a descriptive error message, useful for outputting
68 =head2 get_type
70 The type of this error (e.g. "DocNotFoundError").
72 =head2 get_context
74 Optional context information, returned as a string
76 =head2 get_error_string
78 Returns any error string from errno or similar associated with this error
80 =cut
82 use 5.006;
83 use strict;
84 use warnings;
86 require DynaLoader;
88 END
90 foreach my $subclass (@{$subclasses{'Error'}}) {
91 print F "use Search::Xapian::$subclass;\n";
94 print F <<'END';
96 our @ISA = qw(DynaLoader);
98 # Preloaded methods go here.
100 # In a new thread, copy objects of this class to unblessed, undef values.
101 sub CLONE_SKIP { 1 }
103 sub new {
104 my $class = shift;
105 my ($self);
106 bless $self, $class;
108 return $self;
114 close F or die $!;
115 rename "$fnm.tmp", "$fnm" or die $!;
117 foreach ('Error', @baseclasses, @classes) {
118 my ($classname, $parent, $full_description) = split /\t/;
120 # XS/CLASSNAME.xs
121 $fnm = "XS/$classname.xs";
122 open F, '>', "$fnm.tmp" or die $!;
124 print F <<"END";
125 MODULE = Search::Xapian\t PACKAGE = Search::Xapian::$classname
127 PROTOTYPES: ENABLE
129 string
130 ${classname}::get_type()
132 string
133 ${classname}::get_msg()
135 string
136 ${classname}::get_context()
138 const char *
139 ${classname}::get_error_string()
141 void
142 ${classname}::DESTROY()
145 if (exists $subclasses{$classname}) {
146 print F "\n";
147 foreach my $subclass (@{$subclasses{$classname}}) {
148 print F "INCLUDE: XS/$subclass.xs\n";
152 close F or die $!;
153 rename "$fnm.tmp", "$fnm" or die $!;
155 next if $classname eq 'Error';
157 $full_description =~ s!^[/ ]\*[*/]?!!mg;
158 $full_description =~ s!\*\/$!!mg; # ! to unconfuse vim
160 my ($heading, $desc) = split('\n\n', $full_description, 2);
161 $desc ||= '';
163 # Xapian/CLASSNAME.pm
164 $fnm = "Xapian/$classname.pm";
165 open F, '>', "$fnm.tmp" or die $!;
167 print F <<"END";
168 package Search::Xapian::$classname;
170 =head1 NAME
172 Search::Xapian::$classname - $heading
174 =head1 DESCRIPTION
176 $desc
177 =cut
179 use 5.006;
180 use strict;
181 use warnings;
183 require DynaLoader;
185 # For compatibility with XS Search::Xapian < 1.2.3 which still threw strings
186 # in some cases.
187 use overload '""' => sub { "Exception: ".\$_[0]->get_msg };
191 if (exists $subclasses{$classname}) {
192 foreach my $subclass (@{$subclasses{$classname}}) {
193 print F "use Search::Xapian::$subclass;\n";
195 print F "\n";
198 print F <<"END";
199 our \@ISA = qw(DynaLoader Search::Xapian::$parent);
204 close F or die $!;
205 rename "$fnm.tmp", "$fnm" or die $!;
208 # write new handle_exception.cc
210 $fnm = "handle_exception.cc";
211 open F, '>', "$fnm.tmp" or die $!;
213 print F <<'END';
214 #include <xapian.h>
216 extern "C" {
217 #include "EXTERN.h"
218 #include "perl.h"
219 #include "XSUB.h"
222 /* handle_exception function
224 * called in catch blocks to croak or rethrow in perl land
227 void handle_exception(void) {
228 try {
229 throw;
232 foreach (reverse @classes) {
233 my ($classname, $parent, $full_description) = split /\t/;
235 print F <<"END";
236 } catch (const Xapian::$classname & error) {
237 SV * errsv = get_sv("\@", TRUE);
238 sv_setref_pv(errsv, "Search::Xapian::$classname", (void *) new Xapian::$classname(error));
239 croak(Nullch);
243 print F <<'END';
244 } catch (const std::exception & error) {
245 croak( "std::exception: %s", error.what());
246 } catch (...) {
247 croak("something terrible happened");
252 close F or die $!;
253 rename "$fnm.tmp", "$fnm" or die $!;