File Coverage

blib/lib/ExtUtils/Constant/ProxySubs.pm
Criterion Covered Total %
statement 184 193 95.3
branch 80 100 80.0
condition 19 26 73.0
subroutine 11 11 100.0
pod 0 5 0.0
total 294 335 87.7


line stmt bran cond sub pod time code
1             package ExtUtils::Constant::ProxySubs;
2 1     1   13 use strict;
  1         4  
  1         48  
3 1         131 use vars qw($VERSION @ISA %type_to_struct %type_from_struct %type_to_sv
4             %type_to_C_value %type_is_a_problem %type_num_args
5 1     1   6 %type_temporary);
  1         2  
6             $VERSION = '0.24_01';
7             @ISA = 'ExtUtils::Constant::XS';
8              
9             =head1 NAME
10              
11             ExtUtils::Constant::ProxySubs - generate XS ProxySubs code
12              
13             =head1 SYNOPSIS
14              
15             use ExtUtils::Constant qw (WriteConstants);
16             WriteConstants(
17             NAME => 'Package',
18             NAMES => [qw(FOO BAR BAZ)],
19             PROXYSUBS => { autoload => 1 },
20             DEFAULT_TYPE => 'IV',
21             );
22             # Generates easier wrapper code, unusable with 5.6
23              
24             =head1 DESCRIPTION
25              
26             With the PROXYSUBS option to WriteConstants, this module generates
27             better XS code, with 4 optional variants.
28              
29             Each symbol is added as CONSTSUB at BOOT time, as via C
30             {value}>. Undefined names I<(#undef NAME)> will be stored in a
31             special C namespace, because
32             accessing an undefined name should throw a different error "Your
33             vendor has not defined MyPackage macro NAME", and not "Undefined
34             subroutine &MyPackage::NAME".
35              
36             There's no run-time lookup for matching names in the constant
37             function, but there's still AUTOLOAD needed to catch unknown names and
38             a short dispatch for matching types.
39              
40             NOTICE:
41              
42             ExtUtils::Constant::ProxySubs versions older than 0.23_04 creates
43             code usable only >= 5.14. There is no official CPAN version which
44             creates usable code yet. The CPAN maintainers think p5p should sort it
45             out, which they didn't for the last 7 years.
46              
47             =head1 OPTIONS
48              
49             PROXYSUBS can be used with an optional hashref of 4 exclusive options.
50              
51             'autoload', 'croak_on_error' and 'croak_on_read' can not be used together.
52             'push' and 'croak_on_read' cannot be used together.
53              
54             =over 4
55              
56             =item autoload
57              
58             This option generates an XS AUTOLOAD function which dispatches to the
59             XS C function. Only auto-generated C and XS code is needed, no manual
60             addition of C as generated by L.
61              
62             B
63             With 5.6 the error message for undefined macros is not
64             "Your vendor has not defined MyPackage macro NAME", but
65             "Undefined subroutine &MyPackage::NAME"
66              
67             =item push
68              
69             This option keeps a list of all added constants.
70              
71             E.g.
72             NAME => 'MyPackage',
73             PROXYSUBS => { push => 'CONSTNAMES' },
74             will create C<@MyPackage::CONSTNAMES>.
75              
76             =item croak_on_error
77              
78             Errors in run-time name lookup via XS constant is normally handled by
79             AUTOLOAD. With croak_on_error the AUTOLOAD function can be
80             simplified, errors with missing undefined names are thrown directly in
81             the XS Cfunction.
82              
83             The XS caller context might be different to the pure-perl AUTOLOAD
84             context though, identifying the source location of the error.
85              
86             =item croak_on_read
87              
88             Similar to croak_on_error, but much more restrictive. For each
89             variable which should report the "Your vendor has not defined
90             MyPackage macro NAME" error, a magic getter and setter hook is added
91             to throw this error.
92              
93             This option creates code usable only since Perl 5.24, so don't
94             use it with any CPAN module!
95              
96             =back
97              
98             =cut
99              
100 1     1   7 use Carp;
  1         3  
  1         98  
101             require ExtUtils::Constant::XS;
102 1     1   5 use ExtUtils::Constant::Utils qw(C_stringify);
  1         4  
  1         56  
103 1     1   6 use ExtUtils::Constant::XS qw(%XS_TypeSet);
  1         2  
  1         2565  
104              
105             %type_to_struct =
106             (
107             IV => '{const char *name; I32 namelen; IV value;}',
108             NV => '{const char *name; I32 namelen; NV value;}',
109             UV => '{const char *name; I32 namelen; UV value;}',
110             PV => '{const char *name; I32 namelen; const char *value;}',
111             PVN => '{const char *name; I32 namelen; const char *value; STRLEN len;}',
112             YES => '{const char *name; I32 namelen;}',
113             NO => '{const char *name; I32 namelen;}',
114             UNDEF => '{const char *name; I32 namelen;}',
115             '' => '{const char *name; I32 namelen;} ',
116             );
117              
118             %type_from_struct =
119             (
120             IV => sub { $_[0] . '->value' },
121             NV => sub { $_[0] . '->value' },
122             UV => sub { $_[0] . '->value' },
123             PV => sub { $_[0] . '->value' },
124             PVN => sub { $_[0] . '->value', $_[0] . '->len' },
125             YES => sub {},
126             NO => sub {},
127             UNDEF => sub {},
128             '' => sub {},
129             );
130              
131             %type_to_sv =
132             (
133             IV => sub { "newSViv($_[0])" },
134             NV => sub { "newSVnv($_[0])" },
135             UV => sub { "newSVuv($_[0])" },
136             PV => sub { "newSVpv($_[0], 0)" },
137             PVN => sub { "newSVpvn($_[0], $_[1])" },
138             YES => sub { '&PL_sv_yes' },
139             NO => sub { '&PL_sv_no' },
140             UNDEF => sub { '&PL_sv_undef' },
141             '' => sub { '&PL_sv_yes' },
142             SV => sub {"SvREFCNT_inc($_[0])"},
143             );
144              
145             %type_to_C_value =
146             (
147             YES => sub {},
148             NO => sub {},
149             UNDEF => sub {},
150             '' => sub {},
151             );
152              
153             sub type_to_C_value {
154 70     70 0 104 my ($self, $type) = @_;
155 70 100 100 315   327 return $type_to_C_value{$type} || sub {return map {ref $_ ? @$_ : $_} @_};
  315         393  
  315         857  
156             }
157              
158             # TODO - figure out if there is a clean way for the type_to_sv code to
159             # attempt s/sv_2mortal// and if it succeeds tell type_to_sv not to add
160             # SvREFCNT_inc
161             %type_is_a_problem =
162             (
163             # The documentation says *mortal SV*, but we now need a non-mortal copy.
164             SV => 1,
165             );
166              
167             %type_temporary =
168             (
169             SV => ['SV *'],
170             PV => ['const char *'],
171             PVN => ['const char *', 'STRLEN'],
172             );
173             $type_temporary{$_} = [$_] foreach qw(IV UV NV);
174            
175             while (my ($type, $value) = each %XS_TypeSet) {
176             $type_num_args{$type}
177             = defined $value ? ref $value ? scalar @$value : 1 : 0;
178             }
179             $type_num_args{''} = 0;
180              
181             sub partition_names {
182 7     7 0 30 my ($self, $default_type, @items) = @_;
183 7         9 my (%found, @notfound, @trouble);
184              
185 7         23 while (my $item = shift @items) {
186 182         223 my $default = delete $item->{default};
187 182 100       213 if ($default) {
188             # If we find a default value, convert it into a regular item and
189             # append it to the queue of items to process
190 7         36 my $default_item = {%$item};
191 7         26 $default_item->{invert_macro} = 1;
192 7         17 $default_item->{pre} = delete $item->{def_pre};
193 7         17 $default_item->{post} = delete $item->{def_post};
194 7         21 $default_item->{type} = shift @$default;
195 7         22 $default_item->{value} = $default;
196 7         14 push @items, $default_item;
197             } else {
198             # It can be "not found" unless it's the default (invert the macro)
199             # or the "macro" is an empty string (ie no macro)
200             push @notfound, $item unless $item->{invert_macro}
201 175 100 100     476 or !$self->macro_to_ifdef($self->macro_from_item($item));
202             }
203              
204 182 100 66     820 if ($item->{pre} or $item->{post} or $item->{not_constant}
      33        
      33        
205             or $type_is_a_problem{$item->{type}}) {
206 7         26 push @trouble, $item;
207             } else {
208 175         191 push @{$found{$item->{type}}}, $item;
  175         474  
209             }
210             }
211             # use Data::Dumper; print Dumper \%found;
212 7         31 (\%found, \@notfound, \@trouble);
213             }
214              
215             sub boottime_iterator {
216 56     56 0 116 my ($self, $type, $iterator, $hash, $subname, $push) = @_;
217 56         79 my $extractor = $type_from_struct{$type};
218 56 50       99 die "Can't find extractor code for type $type"
219             unless defined $extractor;
220 56         79 my $generator = $type_to_sv{$type};
221 56 50       82 die "Can't find generator code for type $type"
222             unless defined $generator;
223              
224 56         104 my $athx = $self->C_constant_prefix_param();
225              
226 56 100       81 if ($push) {
227 24         77 return sprintf <<"EOBOOT", &$generator(&$extractor($iterator));
228             while ($iterator->name) {
229             he = $subname($athx $hash, $iterator->name,
230             $iterator->namelen, %s);
231             #if PERL_VERSION < 10
232             av_push(push, (SV*)he);
233             #else
234             av_push(push, newSVhek(HeKEY_hek(he)));
235             #endif
236             ++$iterator;
237             }
238             EOBOOT
239             } else {
240 32         110 return sprintf <<"EOBOOT", &$generator(&$extractor($iterator));
241             while ($iterator->name) {
242             (void)$subname($athx $hash, $iterator->name,
243             $iterator->namelen, %s);
244             ++$iterator;
245             }
246             EOBOOT
247             }
248             }
249              
250             sub name_len_value_macro {
251 322     322 0 444 my ($self, $item) = @_;
252 322         412 my $name = $item->{name};
253 322         370 my $value = $item->{value};
254 322 100       535 $value = $item->{name} unless defined $value;
255              
256 322         352 my $namelen = length $name;
257 322 50       561 if ($name =~ tr/\0-\377// != $namelen) {
258             # the hash API signals UTF-8 by passing the length negated.
259 0         0 utf8::encode($name);
260 0         0 $namelen = -length $name;
261             }
262 322         591 $name = C_stringify($name);
263              
264 322         689 my $macro = $self->macro_from_item($item);
265 322         839 ($name, $namelen, $value, $macro);
266             }
267              
268             sub WriteConstants {
269 7     7 0 19 my $self = shift;
270 7         51 my $ARGS = {@_};
271              
272             my ($c_fh, $xs_fh, $c_subname, $default_type, $package)
273 7         27 = @{$ARGS}{qw(C_FH XS_FH C_SUBNAME DEFAULT_TYPE NAME)};
  7         64  
274              
275             my $xs_subname
276 7 50       38 = exists $ARGS->{XS_SUBNAME} ? $ARGS->{XS_SUBNAME} : 'constant';
277              
278 7         16 my $options = $ARGS->{PROXYSUBS};
279 7 100       38 $options = {} unless ref $options;
280 7         21 my $push = $options->{push};
281 7         14 my $explosives = $options->{croak_on_read};
282 7         13 my $croak_on_error = $options->{croak_on_error};
283 7         14 my $autoload = $options->{autoload};
284             {
285 7         11 my $exclusive = 0;
  7         12  
286 7 100       31 ++$exclusive if $explosives;
287 7 100       18 ++$exclusive if $croak_on_error;
288 7 100       16 ++$exclusive if $autoload;
289              
290             # Until someone patches this (with test cases):
291 7 50       26 carp ("PROXYSUBS options 'autoload', 'croak_on_read' and 'croak_on_error' cannot be used together")
292             if $exclusive > 1;
293             }
294             # Strictly this is actually 5.8.9, but it's not well tested there
295 7         32 my $can_do_pcs = $] >= 5.009;
296             # Until someone patches this (with test cases)
297 7 50 66     30 carp ("PROXYSUBS options 'push' and 'croak_on_read' cannot be used together")
298             if $explosives && $push;
299              
300 7 100       20 if ($explosives) {
301 1         20 warn("Code created by PROXYSUBS croak_on_read can only be used with perl >= 5.24.\n",
302             "It is NOT recommended for CPAN modules!\n");
303             }
304              
305             # If anyone is insane enough to suggest a package name containing %
306 7         14 my $package_sprintf_safe = $package;
307 7         24 $package_sprintf_safe =~ s/%/%%/g;
308             # People were actually more insane than thought
309 7 50       26 $package_sprintf_safe =~ s/\x{0}/\\0/g if $] > 5.015006;
310              
311             # All the types we see
312 7         11 my $what = {};
313             # A hash to lookup items with.
314 7         13 my $items = {};
315              
316             my @items = $self->normalise_items ({disable_utf8_duplication => 1},
317             $default_type, $what, $items,
318 7         31 @{$ARGS->{NAMES}});
  7         61  
319              
320             # Partition the values by type. Also include any defaults in here
321             # Everything that doesn't have a default needs alternative code for
322             # "I'm missing"
323             # And everything that has pre or post code ends up in a private block
324 7         47 my ($found, $notfound, $trouble)
325             = $self->partition_names($default_type, @items);
326              
327 7         47 my $pthx = $self->C_constant_prefix_param_definition();
328 7         33 my $athx = $self->C_constant_prefix_param();
329 7         49 my $symbol_table = C_stringify($package) . '::';
330 7 100       31 $push = C_stringify($package . '::' . $push) if $push;
331 7 50       32 my $cast_CONSTSUB = $] < 5.010 ? '(char *)' : '';
332              
333 7         35 print $c_fh $self->header();
334 7         74 print $c_fh <<'EOC';
335              
336             /* 5.6 */
337             #ifndef C_ARRAY_LENGTH
338             #define C_ARRAY_LENGTH(x) (sizeof(x)/sizeof((x)[0]))
339             #endif
340             EOC
341 7 100       45 if ($explosives) {
342 1         5 print $c_fh <<'EOC';
343             /* 5.8 */
344             #ifndef PERL_UNUSED_ARG
345             #define PERL_UNUSED_ARG(x)
346             #endif
347             #ifndef NORETURN_FUNCTION_END
348             #define NORETURN_FUNCTION_END
349             #endif
350             EOC
351             }
352 7 100 100     35 if ($autoload || $croak_on_error) {
353 4         11 print $c_fh <<'EOC';
354              
355             /* This allows slightly more efficient code on !USE_ITHREADS: */
356             #ifdef USE_ITHREADS
357             # define COP_FILE(c) CopFILE(c)
358             # define COP_FILE_F "s"
359             #else
360             # define COP_FILE(c) CopFILESV(c)
361             # define COP_FILE_F SVf
362             #endif
363             EOC
364             }
365              
366 7 100       40 my $return_type = $push ? 'HE *' : 'void';
367              
368 7         30 print $c_fh <<"EOADD";
369              
370             static $return_type
371             ${c_subname}_add_symbol($pthx HV *hash, const char *name, I32 namelen, SV *value) {
372             EOADD
373 7 50       57 if (!$can_do_pcs) {
374 0         0 print $c_fh <<'EO_NOPCS';
375             HE *he = NULL;
376             if (namelen) {
377             EO_NOPCS
378             } else {
379 7         19 print $c_fh <<"EO_PCS";
380             #if PERL_VERSION < 10
381             SV **he = hv_fetch(hash, name, namelen, TRUE);
382             #else
383             HE *he = (HE*) hv_common_key_len(hash, name, namelen, HV_FETCH_LVALUE, NULL,
384             0);
385             #endif
386             SV *sv;
387              
388             if (!he) {
389             croak("Couldn't add key '%s' to %%$package_sprintf_safe\::",
390             name);
391             }
392             #if PERL_VERSION < 10
393             sv = *he;
394             #else
395             sv = HeVAL(he);
396             #endif
397             if (SvOK(sv) || SvTYPE(sv) == SVt_PVGV) {
398             /* Someone has been here before us - have to make a real sub. */
399             EO_PCS
400             }
401             # This piece of code is common to both
402 7         38 print $c_fh <<"EOADD";
403             newCONSTSUB(hash, ${cast_CONSTSUB}name, value);
404             EOADD
405 7 50       38 if ($can_do_pcs) {
406 7         19 print $c_fh <<'EO_PCS';
407             } else {
408             SvUPGRADE(sv, SVt_RV);
409             SvRV_set(sv, value);
410             SvROK_on(sv);
411             SvREADONLY_on(value);
412             }
413             EO_PCS
414             } else {
415 0         0 print $c_fh <<'EO_NOPCS';
416             }
417             EO_NOPCS
418             }
419 7 100       43 print $c_fh " return (HE *)he;\n" if $push;
420 7         21 print $c_fh <<'EOADD';
421             }
422              
423             EOADD
424              
425 7 100       36 print $c_fh $explosives ? <<"EXPLODE" : "\n";
426              
427             static int
428             Im_sorry_Dave(pTHX_ SV *sv, MAGIC *mg)
429             {
430             PERL_UNUSED_ARG(mg);
431             croak("Your vendor has not defined $package_sprintf_safe macro %" SVf
432             " used", sv);
433             NORETURN_FUNCTION_END;
434             }
435              
436             static MGVTBL not_defined_vtbl = {
437             Im_sorry_Dave, /* get - I'm afraid I can't do that */
438             Im_sorry_Dave, /* set */
439             0, /* len */
440             0, /* clear */
441             0, /* free */
442             #if PERL_VERSION > 6
443             0, /* copy */
444             0, /* dup */
445             #if (PERL_VERSION > 8) || (PERL_VERSION == 8 && PERL_SUBVERSION == 9)
446             0, /* local */
447             #endif
448             #endif
449             };
450              
451             EXPLODE
452              
453             {
454 7         30 my $key = $symbol_table;
  7         22  
455             # Just seems tidier (and slightly more space efficient) not to have keys
456             # such as Fcntl::
457 7         44 $key =~ s/::$//;
458 7         12 my $key_len = length $key;
459              
460 7 100       40 print $c_fh <<"MISSING" unless $explosives;
461              
462             #ifndef SYMBIAN
463              
464             /* Store a hash of all symbols missing from the package. To avoid trampling on
465             the package namespace (uninvited) put each package's hash in our namespace.
466             To avoid creating lots of typeblogs and symbol tables for sub-packages, put
467             each package's hash into one hash in our namespace. */
468              
469             static HV *
470             get_missing_hash(pTHX) {
471             HV *const parent
472             = get_hv("ExtUtils::Constant::ProxySubs::Missing", GVf_MULTI);
473             /* We could make a hash of hashes directly, but this would confuse anything
474             at Perl space that looks at us, and as we're visible in Perl space,
475             best to play nice. */
476             SV *const *const ref = hv_fetch(parent, "$key", $key_len, TRUE);
477             HV *new_hv;
478              
479             if (!ref)
480             return NULL;
481              
482             if (SvROK(*ref))
483             return (HV*) SvRV(*ref);
484              
485             new_hv = newHV();
486             SvUPGRADE(*ref, SVt_RV);
487             SvRV_set(*ref, (SV *)new_hv);
488             SvROK_on(*ref);
489             return new_hv;
490             }
491              
492             #endif
493              
494             MISSING
495              
496             }
497              
498 7         61 print $xs_fh <<"EOBOOT";
499             BOOT:
500             {
501             #if defined(dTHX) && !defined(PERL_NO_GET_CONTEXT)
502             dTHX;
503             #endif
504             HV *symbol_table = get_hv("$symbol_table", GV_ADD);
505             EOBOOT
506 7 100       40 if ($push) {
507             # silence cperl-only Used once warnings
508 3         50 print $xs_fh <<"EOC";
509             #ifndef USE_CPERL
510             AV *push = get_av(\"$push\", GV_ADD);
511             #else
512             AV *push = get_av(\"$push\", GV_ADD|GV_ADDMULTI);
513             #endif
514             HE *he;
515             EOC
516             }
517              
518 7         27 my %iterator;
519              
520             $found->{''}
521 7         19 = [map {{%$_, type=>'', invert_macro => 1}} @$notfound];
  140         420  
522              
523 7         50 foreach my $type (sort keys %$found) {
524 63         364 my $struct = $type_to_struct{$type};
525 63         106 my $type_to_value = $self->type_to_C_value($type);
526 63         110 my $number_of_args = $type_num_args{$type};
527 63 50       95 die "Can't find structure definition for type $type"
528             unless defined $struct;
529              
530 63 100       123 my $lc_type = $type ? lc($type) : 'notfound';
531 63         94 my $struct_type = $lc_type . '_s';
532 63         81 my $array_name = 'values_for_' . $lc_type;
533 63         113 $iterator{$type} = 'value_for_' . $lc_type;
534             # Give the notfound struct file scope. The others are scoped within the
535             # BOOT block
536 63 100       87 my $struct_fh = $type ? $xs_fh : $c_fh;
537              
538 63         163 print $c_fh "struct $struct_type $struct; /* $type */\n";
539              
540 63         429 print $struct_fh <<"EOBOOT";
541              
542             static const struct $struct_type $array_name\[] =
543             {
544             EOBOOT
545              
546              
547 63         249 foreach my $item (@{$found->{$type}}) {
  63         115  
548 315         1499 my ($name, $namelen, $value, $macro)
549             = $self->name_len_value_macro($item);
550              
551 315         578 my $ifdef = $self->macro_to_ifdef($macro);
552 315 50 66     579 if (!$ifdef && $item->{invert_macro}) {
553 0         0 carp("Attempting to supply a default for '$name' which has no conditional macro");
554 0         0 next;
555             }
556 315 100       458 if ($item->{invert_macro}) {
557 147         297 print $struct_fh $self->macro_to_ifndef($macro);
558 147 100       768 print $struct_fh
559             " /* This is the default value: */\n" if $type;
560             } else {
561 168         344 print $struct_fh $ifdef;
562             }
563             # skip undef type ''
564 315         1071 print $struct_fh " { ";
565 315 100       1250 if (defined &$type_to_value($value)) {
566 154         254 print $struct_fh join (', ', "\"$name\"", $namelen,
567             &$type_to_value($value));
568             } else {
569 161         385 print $struct_fh join (', ', "\"$name\"", $namelen);
570             }
571 315         1479 print $struct_fh " },\n",
572             $self->macro_to_endif($macro);
573             }
574              
575             # Terminate the list with a NULL
576 63         408 print $struct_fh " { NULL, 0", (", 0" x $number_of_args),
577             " }\n };\n";
578              
579 63 100       394 print $xs_fh <<"EOBOOT" if $type;
580             const struct $struct_type *$iterator{$type} = $array_name;
581             EOBOOT
582             }
583              
584 7         98 delete $found->{''};
585              
586 7         19 my $add_symbol_subname = $c_subname . '_add_symbol';
587 7         47 foreach my $type (sort keys %$found) {
588 56         400 print $xs_fh $self->boottime_iterator($type, $iterator{$type},
589             'symbol_table',
590             $add_symbol_subname, $push);
591             }
592              
593 7         54 print $xs_fh <<'EOBOOT';
594             if (C_ARRAY_LENGTH(values_for_notfound) > 1) {
595             EOBOOT
596              
597 7 100       46 print $xs_fh <<"EOBOOT" unless $explosives;
598             #ifndef SYMBIAN
599             HV *const ${c_subname}_missing = get_missing_hash(aTHX);
600             #endif
601             EOBOOT
602              
603 7         31 print $xs_fh <<'EOBOOT';
604             const struct notfound_s *value_for_notfound = values_for_notfound;
605             do {
606             EOBOOT
607              
608 7 100       62 print $xs_fh $explosives ? <<"EXPLODE" : << "DONT";
609             SV *tripwire = newSV(0);
610            
611             sv_magicext(tripwire, 0, PERL_MAGIC_ext, ¬_defined_vtbl, 0, 0);
612             SvPV_set(tripwire, (char *)value_for_notfound->name);
613             if (value_for_notfound->namelen >= 0) {
614             SvCUR_set(tripwire, value_for_notfound->namelen);
615             } else {
616             SvCUR_set(tripwire, -value_for_notfound->namelen);
617             SvUTF8_on(tripwire);
618             }
619             SvPOKp_on(tripwire);
620             SvREADONLY_on(tripwire);
621             assert(SvLEN(tripwire) == 0);
622              
623             $add_symbol_subname($athx symbol_table, value_for_notfound->name,
624             value_for_notfound->namelen, tripwire);
625             EXPLODE
626              
627             SV *sv;
628             #ifndef SYMBIAN
629             HEK *hek;
630             #endif
631             /* Need to add prototypes, else parsing will vary by platform. */
632             #if PERL_VERSION < 10
633             SV **he = hv_fetch(symbol_table,
634             value_for_notfound->name,
635             value_for_notfound->namelen,
636             TRUE);
637             #else
638             HE *he = (HE*) hv_common_key_len(symbol_table,
639             value_for_notfound->name,
640             value_for_notfound->namelen,
641             HV_FETCH_LVALUE, NULL, 0);
642             #endif
643             if (!he) {
644             croak("Couldn't add key '%s' to %%$package_sprintf_safe\::",
645             value_for_notfound->name);
646             }
647             #if PERL_VERSION < 10
648             sv = *he;
649             #else
650             sv = HeVAL(he);
651             #endif
652             if (!SvOK(sv) && SvTYPE(sv) != SVt_PVGV) {
653             #if 0
654             CV *cv;
655             /* 5.6 needs a proper const sub? */
656             newCONSTSUB(symbol_table, (char *)value_for_notfound->name,
657             &PL_sv_undef);
658             cv = GvCV(sv);
659             #elif PERL_VERSION < 8
660             /* empty typeglob as NULL sv? */
661             #elif PERL_VERSION < 10
662             sv_upgrade(sv, SVt_PV);
663             sv_setpvn(sv, "", 0);
664             #else
665             /* Nothing was here before, so mark a prototype of "" */
666             sv_setpvn(sv, "", 0);
667             #endif
668             } else if (SvPOK(sv) && SvCUR(sv) == 0) {
669             /* There is already a prototype of "" - do nothing */
670             } else {
671             /* Someone has been here before us - have to make a real
672             typeglob. */
673             /* It turns out to be incredibly hard to deal with all the
674             corner cases of sub foo (); and reporting errors correctly,
675             so lets cheat a bit. Start with a constant subroutine */
676             CV *cv;
677             #if PERL_VERSION > 6
678             cv =
679             #endif
680             newCONSTSUB(symbol_table,
681             (char *)value_for_notfound->name,
682             &PL_sv_yes);
683             #if PERL_VERSION < 8
684             cv = GvCV(sv);
685             #endif
686             /* and then turn it into a non constant declaration only. */
687             #if PERL_VERSION > 6
688             SvREFCNT_dec(CvXSUBANY(cv).any_ptr);
689             CvCONST_off(cv);
690             #endif
691             CvXSUB(cv) = NULL;
692             CvXSUBANY(cv).any_ptr = NULL;
693             }
694             #ifndef SYMBIAN
695             # if PERL_VERSION < 10
696             if (!hv_store(${c_subname}_missing,
697             value_for_notfound->name,
698             value_for_notfound->namelen,
699             &PL_sv_yes, 0))
700             # else
701             hek = HeKEY_hek(he);
702             if (!hv_common(${c_subname}_missing, NULL, HEK_KEY(hek),
703             HEK_LEN(hek), HEK_FLAGS(hek), HV_FETCH_ISSTORE,
704             &PL_sv_yes, HEK_HASH(hek)))
705             # endif
706             croak("Couldn't add key '%s' to missing_hash",
707             value_for_notfound->name);
708             #endif
709             DONT
710              
711 7 100       67 if ($push) {
712 3         7 print $xs_fh <<'EOC';
713             #if PERL_VERSION < 10
714             av_push(push, sv);
715             #else
716             av_push(push, newSVhek(hek));
717             #endif
718             EOC
719             }
720 7         44 print $xs_fh <<"EOBOOT";
721             } while ((++value_for_notfound)->name);
722             }
723             EOBOOT
724              
725 7         48 foreach my $item (@$trouble) {
726 7         16 my ($name, $namelen, $value, $macro)
727             = $self->name_len_value_macro($item);
728 7         15 my $ifdef = $self->macro_to_ifdef($macro);
729 7         15 my $type = $item->{type};
730 7         16 my $type_to_value = $self->type_to_C_value($type);
731              
732 7         22 print $xs_fh $ifdef;
733 7 50       41 if ($item->{invert_macro}) {
734 0 0       0 print $xs_fh
735             " /* This is the default value: */\n" if $type;
736 0         0 print $xs_fh "#else\n";
737             }
738 7         13 my $generator = $type_to_sv{$type};
739 7 50       14 die "Can't find generator code for type $type"
740             unless defined $generator;
741              
742 7         15 print $xs_fh " {\n";
743             # We need to use a temporary value because some really troublesome
744             # items use C pre processor directives in their values, and in turn
745             # these don't fit nicely in the macro-ised generator functions
746 7         28 my $counter = 0;
747             printf $xs_fh " %s temp%d;\n", $_, $counter++
748 7         11 foreach @{$type_temporary{$type}};
  7         35  
749              
750 7 50       98 print $xs_fh " $item->{pre}\n" if $item->{pre};
751              
752             # And because the code in pre might be both declarations and
753             # statements, we can't declare and assign to the temporaries in one.
754 7         38 $counter = 0;
755             printf $xs_fh " temp%d = %s;\n", $counter++, $_
756 7         18 foreach &$type_to_value($value);
757              
758 7         66 my @tempvarnames = map {sprintf 'temp%d', $_} 0 .. $counter - 1;
  7         29  
759 7         30 printf $xs_fh <<"EOBOOT", $name, &$generator(@tempvarnames);
760             ${c_subname}_add_symbol($athx symbol_table, "%s",
761             $namelen, %s);
762             EOBOOT
763 7 50       46 print $xs_fh " $item->{post}\n" if $item->{post};
764 7         15 print $xs_fh " }\n";
765              
766 7         64 print $xs_fh $self->macro_to_endif($macro);
767             }
768              
769 7 50       61 if ($] >= 5.009) {
770 7         16 print $xs_fh <
771             /* As we've been creating subroutines, we better invalidate any cached
772             methods */
773             mro_method_changed_in(symbol_table);
774             }
775             EOBOOT
776             } else {
777 0         0 print $xs_fh <
778             /* As we've been creating subroutines, we better invalidate any cached
779             methods */
780             ++PL_sub_generation;
781             }
782             EOBOOT
783             }
784              
785 7 50       49 return if !defined $xs_subname;
786              
787 7 100 100     32 if ($croak_on_error || $autoload) {
788 4 100       17 print $xs_fh $croak_on_error ? <<"EOC" : <<"EOA";
789              
790             void
791             $xs_subname(sv)
792             INPUT:
793             SV * sv;
794             PREINIT:
795             #ifdef caller_cx
796             const PERL_CONTEXT *cx = caller_cx(0, NULL);
797             /* cx is NULL if we've been called from the top level. PL_curcop isn't
798             ideal, but it's much cheaper than other ways of not going SEGV. */
799             const COP *cop = cx ? cx->blk_oldcop : PL_curcop;
800             #else
801             const COP *cop = PL_curcop;
802             #endif
803             EOC
804              
805             void
806             AUTOLOAD()
807             PROTOTYPE: DISABLE
808             PREINIT:
809             #if PERL_VERSION < 10
810             SV *sv = sv_2mortal(newSVpvn(SvPVX(cv), SvCUR(cv)));
811             #else
812             SV *sv = newSVpvn_flags(SvPVX(cv), SvCUR(cv), SVs_TEMP | SvUTF8(cv));
813             #endif
814             const COP *cop = PL_curcop;
815             EOA
816 4         45 print $xs_fh <<"EOC";
817             PPCODE:
818             #ifndef SYMBIAN
819             /* It's not obvious how to calculate this at C pre-processor time.
820             However, any compiler optimiser worth its salt should be able to
821             remove the dead code, and hopefully the now-obviously-unused static
822             function too. */
823             HV *${c_subname}_missing = (C_ARRAY_LENGTH(values_for_notfound) > 1)
824             ? get_missing_hash(aTHX) : NULL;
825             if ((C_ARRAY_LENGTH(values_for_notfound) > 1)
826             ? hv_exists_ent(${c_subname}_missing, sv, 0) : 0) {
827             croak("Your vendor has not defined $package_sprintf_safe macro %" SVf
828             ", used at %" COP_FILE_F " line %" UVuf "\\n",
829             sv, COP_FILE(cop), (UV)CopLINE(cop));
830             } else
831             #endif
832             {
833             croak("%" SVf " is not a valid $package_sprintf_safe macro at %"
834             COP_FILE_F " line %" UVuf "\\n",
835             sv, COP_FILE(cop), (UV)CopLINE(cop));
836             }
837             EOC
838             } else {
839 3 100       17 print $xs_fh $explosives ? <<"EXPLODE" : <<"DONT";
840              
841             void
842             $xs_subname(sv)
843             INPUT:
844             SV * sv;
845             PPCODE:
846             sv = newSVpvf("Your vendor has not defined $package_sprintf_safe macro %" SVf
847             ", used", sv);
848             PUSHs(sv_2mortal(sv));
849             EXPLODE
850              
851             void
852             $xs_subname(sv)
853             INPUT:
854             SV * sv;
855             PPCODE:
856             #ifndef SYMBIAN
857             /* It's not obvious how to calculate this at C pre-processor time.
858             However, any compiler optimiser worth its salt should be able to
859             remove the dead code, and hopefully the now-obviously-unused static
860             function too. */
861             HV *${c_subname}_missing = (C_ARRAY_LENGTH(values_for_notfound) > 1)
862             ? get_missing_hash(aTHX) : NULL;
863             if ((C_ARRAY_LENGTH(values_for_notfound) > 1)
864             ? hv_exists_ent(${c_subname}_missing, sv, 0) : 0) {
865             sv = newSVpvf("Your vendor has not defined $package_sprintf_safe macro %" SVf
866             ", used", sv);
867             } else
868             #endif
869             {
870             sv = newSVpvf("%" SVf " is not a valid $package_sprintf_safe macro",
871             sv);
872             }
873             PUSHs(sv_2mortal(sv));
874             DONT
875             }
876             }
877              
878             1;
879             __END__