This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
(perl #133654) don't include OUTLIST parameters in the prototype
[perl5.git] / dist / ExtUtils-ParseXS / lib / ExtUtils / ParseXS.pm
1 package ExtUtils::ParseXS;
2 use strict;
3
4 use 5.006001;
5 use Cwd;
6 use Config;
7 use Exporter 'import';
8 use File::Basename;
9 use File::Spec;
10 use Symbol;
11
12 our $VERSION;
13 BEGIN {
14   $VERSION = '3.39';
15   require ExtUtils::ParseXS::Constants; ExtUtils::ParseXS::Constants->VERSION($VERSION);
16   require ExtUtils::ParseXS::CountLines; ExtUtils::ParseXS::CountLines->VERSION($VERSION);
17   require ExtUtils::ParseXS::Utilities; ExtUtils::ParseXS::Utilities->VERSION($VERSION);
18   require ExtUtils::ParseXS::Eval; ExtUtils::ParseXS::Eval->VERSION($VERSION);
19 }
20 $VERSION = eval $VERSION if $VERSION =~ /_/;
21
22 use ExtUtils::ParseXS::Utilities qw(
23   standard_typemap_locations
24   trim_whitespace
25   C_string
26   valid_proto_string
27   process_typemaps
28   map_type
29   standard_XS_defs
30   assign_func_args
31   analyze_preprocessor_statements
32   set_cond
33   Warn
34   current_line_number
35   blurt
36   death
37   check_conditional_preprocessor_statements
38   escape_file_for_line_directive
39   report_typemap_failure
40 );
41
42 our @EXPORT_OK = qw(
43   process_file
44   report_error_count
45 );
46
47 ##############################
48 # A number of "constants"
49
50 our ($C_group_rex, $C_arg);
51 # Group in C (no support for comments or literals)
52 $C_group_rex = qr/ [({\[]
53              (?: (?> [^()\[\]{}]+ ) | (??{ $C_group_rex }) )*
54              [)}\]] /x;
55 # Chunk in C without comma at toplevel (no comments):
56 $C_arg = qr/ (?: (?> [^()\[\]{},"']+ )
57        |   (??{ $C_group_rex })
58        |   " (?: (?> [^\\"]+ )
59          |   \\.
60          )* "        # String literal
61               |   ' (?: (?> [^\\']+ ) | \\. )* ' # Char literal
62        )* /xs;
63
64 # "impossible" keyword (multiple newline)
65 my $END = "!End!\n\n";
66 # Match an XS Keyword
67 my $BLOCK_regexp = '\s*(' . $ExtUtils::ParseXS::Constants::XSKeywordsAlternation . "|$END)\\s*:";
68
69
70
71 sub new {
72   return bless {} => shift;
73 }
74
75 our $Singleton = __PACKAGE__->new;
76
77 sub process_file {
78   my $self;
79   # Allow for $package->process_file(%hash), $obj->process_file, and process_file()
80   if (@_ % 2) {
81     my $invocant = shift;
82     $self = ref($invocant) ? $invocant : $invocant->new;
83   }
84   else {
85     $self = $Singleton;
86   }
87
88   my %options = @_;
89   $self->{ProtoUsed} = exists $options{prototypes};
90
91   # Set defaults.
92   my %args = (
93     argtypes        => 1,
94     csuffix         => '.c',
95     except          => 0,
96     hiertype        => 0,
97     inout           => 1,
98     linenumbers     => 1,
99     optimize        => 1,
100     output          => \*STDOUT,
101     prototypes      => 0,
102     typemap         => [],
103     versioncheck    => 1,
104     FH              => Symbol::gensym(),
105     %options,
106   );
107   $args{except} = $args{except} ? ' TRY' : '';
108
109   # Global Constants
110
111   my ($Is_VMS, $SymSet);
112   if ($^O eq 'VMS') {
113     $Is_VMS = 1;
114     # Establish set of global symbols with max length 28, since xsubpp
115     # will later add the 'XS_' prefix.
116     require ExtUtils::XSSymSet;
117     $SymSet = ExtUtils::XSSymSet->new(28);
118   }
119   @{ $self->{XSStack} } = ({type => 'none'});
120   $self->{InitFileCode} = [ @ExtUtils::ParseXS::Constants::InitFileCode ];
121   $self->{Overload}     = 0; # bool
122   $self->{errors}       = 0; # count
123   $self->{Fallback}     = '&PL_sv_undef';
124
125   # Most of the 1500 lines below uses these globals.  We'll have to
126   # clean this up sometime, probably.  For now, we just pull them out
127   # of %args.  -Ken
128
129   $self->{RetainCplusplusHierarchicalTypes} = $args{hiertype};
130   $self->{WantPrototypes} = $args{prototypes};
131   $self->{WantVersionChk} = $args{versioncheck};
132   $self->{WantLineNumbers} = $args{linenumbers};
133   $self->{IncludedFiles} = {};
134
135   die "Missing required parameter 'filename'" unless $args{filename};
136   $self->{filepathname} = $args{filename};
137   ($self->{dir}, $self->{filename}) =
138     (dirname($args{filename}), basename($args{filename}));
139   $self->{filepathname} =~ s/\\/\\\\/g;
140   $self->{IncludedFiles}->{$args{filename}}++;
141
142   # Open the output file if given as a string.  If they provide some
143   # other kind of reference, trust them that we can print to it.
144   if (not ref $args{output}) {
145     open my($fh), "> $args{output}" or die "Can't create $args{output}: $!";
146     $args{outfile} = $args{output};
147     $args{output} = $fh;
148   }
149
150   # Really, we shouldn't have to chdir() or select() in the first
151   # place.  For now, just save and restore.
152   my $orig_cwd = cwd();
153   my $orig_fh = select();
154
155   chdir($self->{dir});
156   my $pwd = cwd();
157   my $csuffix = $args{csuffix};
158
159   if ($self->{WantLineNumbers}) {
160     my $cfile;
161     if ( $args{outfile} ) {
162       $cfile = $args{outfile};
163     }
164     else {
165       $cfile = $args{filename};
166       $cfile =~ s/\.xs$/$csuffix/i or $cfile .= $csuffix;
167     }
168     tie(*PSEUDO_STDOUT, 'ExtUtils::ParseXS::CountLines', $cfile, $args{output});
169     select PSEUDO_STDOUT;
170   }
171   else {
172     select $args{output};
173   }
174
175   $self->{typemap} = process_typemaps( $args{typemap}, $pwd );
176
177   # Move more settings from parameters to object
178   foreach my $datum ( qw| argtypes except inout optimize | ) {
179     $self->{$datum} = $args{$datum};
180   }
181   $self->{strip_c_func_prefix} = $args{s};
182
183   # Identify the version of xsubpp used
184   print <<EOM;
185 /*
186  * This file was generated automatically by ExtUtils::ParseXS version $VERSION from the
187  * contents of $self->{filename}. Do not edit this file, edit $self->{filename} instead.
188  *
189  *    ANY CHANGES MADE HERE WILL BE LOST!
190  *
191  */
192
193 EOM
194
195
196   print("#line 1 \"" . escape_file_for_line_directive($self->{filepathname}) . "\"\n")
197     if $self->{WantLineNumbers};
198
199   # Open the input file (using $self->{filename} which
200   # is a basename'd $args{filename} due to chdir above)
201   open($self->{FH}, '<', $self->{filename}) or die "cannot open $self->{filename}: $!\n";
202
203   FIRSTMODULE:
204   while (readline($self->{FH})) {
205     if (/^=/) {
206       my $podstartline = $.;
207       do {
208         if (/^=cut\s*$/) {
209           # We can't just write out a /* */ comment, as our embedded
210           # POD might itself be in a comment. We can't put a /**/
211           # comment inside #if 0, as the C standard says that the source
212           # file is decomposed into preprocessing characters in the stage
213           # before preprocessing commands are executed.
214           # I don't want to leave the text as barewords, because the spec
215           # isn't clear whether macros are expanded before or after
216           # preprocessing commands are executed, and someone pathological
217           # may just have defined one of the 3 words as a macro that does
218           # something strange. Multiline strings are illegal in C, so
219           # the "" we write must be a string literal. And they aren't
220           # concatenated until 2 steps later, so we are safe.
221           #     - Nicholas Clark
222           print("#if 0\n  \"Skipped embedded POD.\"\n#endif\n");
223           printf("#line %d \"%s\"\n", $. + 1, escape_file_for_line_directive($self->{filepathname}))
224             if $self->{WantLineNumbers};
225           next FIRSTMODULE;
226         }
227
228       } while (readline($self->{FH}));
229       # At this point $. is at end of file so die won't state the start
230       # of the problem, and as we haven't yet read any lines &death won't
231       # show the correct line in the message either.
232       die ("Error: Unterminated pod in $self->{filename}, line $podstartline\n")
233         unless $self->{lastline};
234     }
235     last if ($self->{Package}, $self->{Prefix}) =
236       /^MODULE\s*=\s*[\w:]+(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
237
238     print $_;
239   }
240   unless (defined $_) {
241     warn "Didn't find a 'MODULE ... PACKAGE ... PREFIX' line\n";
242     exit 0; # Not a fatal error for the caller process
243   }
244
245   print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $self->{WantLineNumbers};
246
247   standard_XS_defs();
248
249   print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $self->{WantLineNumbers};
250
251   $self->{lastline}    = $_;
252   $self->{lastline_no} = $.;
253
254   my $BootCode_ref = [];
255   my $XSS_work_idx = 0;
256   my $cpp_next_tmp = 'XSubPPtmpAAAA';
257  PARAGRAPH:
258   while ($self->fetch_para()) {
259     my $outlist_ref  = [];
260     # Print initial preprocessor statements and blank lines
261     while (@{ $self->{line} } && $self->{line}->[0] !~ /^[^\#]/) {
262       my $ln = shift(@{ $self->{line} });
263       print $ln, "\n";
264       next unless $ln =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
265       my $statement = $+;
266       ( $self, $XSS_work_idx, $BootCode_ref ) =
267         analyze_preprocessor_statements(
268           $self, $statement, $XSS_work_idx, $BootCode_ref
269         );
270     }
271
272     next PARAGRAPH unless @{ $self->{line} };
273
274     if ($XSS_work_idx && !$self->{XSStack}->[$XSS_work_idx]{varname}) {
275       # We are inside an #if, but have not yet #defined its xsubpp variable.
276       print "#define $cpp_next_tmp 1\n\n";
277       push(@{ $self->{InitFileCode} }, "#if $cpp_next_tmp\n");
278       push(@{ $BootCode_ref },     "#if $cpp_next_tmp");
279       $self->{XSStack}->[$XSS_work_idx]{varname} = $cpp_next_tmp++;
280     }
281
282     $self->death(
283       "Code is not inside a function"
284         ." (maybe last function was ended by a blank line "
285         ." followed by a statement on column one?)")
286       if $self->{line}->[0] =~ /^\s/;
287
288     # initialize info arrays
289     foreach my $member (qw(args_match var_types defaults arg_list
290                            argtype_seen in_out lengthof))
291     {
292       $self->{$member} = {};
293     }
294     $self->{proto_arg} = [];
295     $self->{processing_arg_with_types} = 0; # bool
296     $self->{proto_in_this_xsub}        = 0; # counter & bool
297     $self->{scope_in_this_xsub}        = 0; # counter & bool
298     $self->{interface}                 = 0; # bool
299     $self->{interface_macro}           = 'XSINTERFACE_FUNC';
300     $self->{interface_macro_set}       = 'XSINTERFACE_FUNC_SET';
301     $self->{ProtoThisXSUB}             = $self->{WantPrototypes}; # states 0 (none), 1 (yes), 2 (empty prototype)
302     $self->{ScopeThisXSUB}             = 0; # bool
303
304     my $xsreturn = 0;
305
306     $_ = shift(@{ $self->{line} });
307     while (my $kwd = $self->check_keyword("REQUIRE|PROTOTYPES|EXPORT_XSUB_SYMBOLS|FALLBACK|VERSIONCHECK|INCLUDE(?:_COMMAND)?|SCOPE")) {
308       my $method = $kwd . "_handler";
309       $self->$method($_);
310       next PARAGRAPH unless @{ $self->{line} };
311       $_ = shift(@{ $self->{line} });
312     }
313
314     if ($self->check_keyword("BOOT")) {
315       check_conditional_preprocessor_statements($self);
316       push (@{ $BootCode_ref }, "#line $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} }] \""
317                                 . escape_file_for_line_directive($self->{filepathname}) . "\"")
318         if $self->{WantLineNumbers} && $self->{line}->[0] !~ /^\s*#\s*line\b/;
319       push (@{ $BootCode_ref }, @{ $self->{line} }, "");
320       next PARAGRAPH;
321     }
322
323     # extract return type, function name and arguments
324     ($self->{ret_type}) = ExtUtils::Typemaps::tidy_type($_);
325     my $RETVAL_no_return = 1 if $self->{ret_type} =~ s/^NO_OUTPUT\s+//;
326
327     # Allow one-line ANSI-like declaration
328     unshift @{ $self->{line} }, $2
329       if $self->{argtypes}
330         and $self->{ret_type} =~ s/^(.*?\w.*?)\s*\b(\w+\s*\(.*)/$1/s;
331
332     # a function definition needs at least 2 lines
333     $self->blurt("Error: Function definition too short '$self->{ret_type}'"), next PARAGRAPH
334       unless @{ $self->{line} };
335
336     my $externC = 1 if $self->{ret_type} =~ s/^extern "C"\s+//;
337     my $static  = 1 if $self->{ret_type} =~ s/^static\s+//;
338
339     my $func_header = shift(@{ $self->{line} });
340     $self->blurt("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
341       unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s;
342
343     my ($class, $orig_args);
344     ($class, $self->{func_name}, $orig_args) =  ($1, $2, $3);
345     $class = "$4 $class" if $4;
346     ($self->{pname} = $self->{func_name}) =~ s/^($self->{Prefix})?/$self->{Packprefix}/;
347     my $clean_func_name;
348     ($clean_func_name = $self->{func_name}) =~ s/^$self->{Prefix}//;
349     $self->{Full_func_name} = "$self->{Packid}_$clean_func_name";
350     if ($Is_VMS) {
351       $self->{Full_func_name} = $SymSet->addsym( $self->{Full_func_name} );
352     }
353
354     # Check for duplicate function definition
355     for my $tmp (@{ $self->{XSStack} }) {
356       next unless defined $tmp->{functions}{ $self->{Full_func_name} };
357       Warn( $self, "Warning: duplicate function definition '$clean_func_name' detected");
358       last;
359     }
360     $self->{XSStack}->[$XSS_work_idx]{functions}{ $self->{Full_func_name} }++;
361     delete $self->{XsubAliases};
362     delete $self->{XsubAliasValues};
363     %{ $self->{Interfaces} }      = ();
364     @{ $self->{Attributes} }      = ();
365     $self->{DoSetMagic} = 1;
366
367     $orig_args =~ s/\\\s*/ /g;    # process line continuations
368     my @args;
369
370     my (@fake_INPUT_pre);    # For length(s) generated variables
371     my (@fake_INPUT);
372     my $only_C_inlist_ref = {};        # Not in the signature of Perl function
373     if ($self->{argtypes} and $orig_args =~ /\S/) {
374       my $args = "$orig_args ,";
375       use re 'eval';
376       if ($args =~ /^( (??{ $C_arg }) , )* $ /x) {
377         @args = ($args =~ /\G ( (??{ $C_arg }) ) , /xg);
378         no re 'eval';
379         for ( @args ) {
380           s/^\s+//;
381           s/\s+$//;
382           my ($arg, $default) = ($_ =~ m/ ( [^=]* ) ( (?: = .* )? ) /x);
383           my ($pre, $len_name) = ($arg =~ /(.*?) \s*
384                              \b ( \w+ | length\( \s*\w+\s* \) )
385                              \s* $ /x);
386           next unless defined($pre) && length($pre);
387           my $out_type = '';
388           my $inout_var;
389           if ($self->{inout} and s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\b\s*//) {
390             my $type = $1;
391             $out_type = $type if $type ne 'IN';
392             $arg =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\b\s*//;
393             $pre =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\b\s*//;
394           }
395           my $islength;
396           if ($len_name =~ /^length\( \s* (\w+) \s* \)\z/x) {
397             $len_name = "XSauto_length_of_$1";
398             $islength = 1;
399             die "Default value on length() argument: '$_'"
400               if length $default;
401           }
402           if (length $pre or $islength) { # Has a type
403             if ($islength) {
404               push @fake_INPUT_pre, $arg;
405             }
406             else {
407               push @fake_INPUT, $arg;
408             }
409             # warn "pushing '$arg'\n";
410             $self->{argtype_seen}->{$len_name}++;
411             $_ = "$len_name$default"; # Assigns to @args
412           }
413           $only_C_inlist_ref->{$_} = 1 if $out_type eq "OUTLIST" or $islength;
414           push @{ $outlist_ref }, $len_name if $out_type =~ /OUTLIST$/;
415           $self->{in_out}->{$len_name} = $out_type if $out_type;
416         }
417       }
418       else {
419         no re 'eval';
420         @args = split(/\s*,\s*/, $orig_args);
421         Warn( $self, "Warning: cannot parse argument list '$orig_args', fallback to split");
422       }
423     }
424     else {
425       @args = split(/\s*,\s*/, $orig_args);
426       for (@args) {
427         if ($self->{inout} and s/^(IN|IN_OUTLIST|OUTLIST|IN_OUT|OUT)\b\s*//) {
428           my $out_type = $1;
429           next if $out_type eq 'IN';
430           $only_C_inlist_ref->{$_} = 1 if $out_type eq "OUTLIST";
431           if ($out_type =~ /OUTLIST$/) {
432               push @{ $outlist_ref }, undef;
433           }
434           $self->{in_out}->{$_} = $out_type;
435         }
436       }
437     }
438     if (defined($class)) {
439       my $arg0 = ((defined($static) or $self->{func_name} eq 'new')
440           ? "CLASS" : "THIS");
441       unshift(@args, $arg0);
442     }
443     my $extra_args = 0;
444     my @args_num = ();
445     my $num_args = 0;
446     my $report_args = '';
447     my $ellipsis;
448     foreach my $i (0 .. $#args) {
449       if ($args[$i] =~ s/\.\.\.//) {
450         $ellipsis = 1;
451         if ($args[$i] eq '' && $i == $#args) {
452           $report_args .= ", ...";
453           pop(@args);
454           last;
455         }
456       }
457       if ($only_C_inlist_ref->{$args[$i]}) {
458         push @args_num, undef;
459       }
460       else {
461         push @args_num, ++$num_args;
462           $report_args .= ", $args[$i]";
463       }
464       if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {
465         $extra_args++;
466         $args[$i] = $1;
467         $self->{defaults}->{$args[$i]} = $2;
468         $self->{defaults}->{$args[$i]} =~ s/"/\\"/g;
469       }
470       $self->{proto_arg}->[$i+1] = '$' unless $only_C_inlist_ref->{$args[$i]};
471     }
472     my $min_args = $num_args - $extra_args;
473     $report_args =~ s/"/\\"/g;
474     $report_args =~ s/^,\s+//;
475     $self->{func_args} = assign_func_args($self, \@args, $class);
476     @{ $self->{args_match} }{@args} = @args_num;
477
478     my $PPCODE = grep(/^\s*PPCODE\s*:/, @{ $self->{line} });
479     my $CODE = grep(/^\s*CODE\s*:/, @{ $self->{line} });
480     # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)
481     # to set explicit return values.
482     my $EXPLICIT_RETURN = ($CODE &&
483             ("@{ $self->{line} }" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
484
485     $self->{ALIAS}  = grep(/^\s*ALIAS\s*:/,  @{ $self->{line} });
486
487     my $INTERFACE  = grep(/^\s*INTERFACE\s*:/,  @{ $self->{line} });
488
489     $xsreturn = 1 if $EXPLICIT_RETURN;
490
491     $externC = $externC ? qq[extern "C"] : "";
492
493     # print function header
494     print Q(<<"EOF");
495 #$externC
496 #XS_EUPXS(XS_$self->{Full_func_name}); /* prototype to pass -Wmissing-prototypes */
497 #XS_EUPXS(XS_$self->{Full_func_name})
498 #[[
499 #    dVAR; dXSARGS;
500 EOF
501     print Q(<<"EOF") if $self->{ALIAS};
502 #    dXSI32;
503 EOF
504     print Q(<<"EOF") if $INTERFACE;
505 #    dXSFUNCTION($self->{ret_type});
506 EOF
507
508     $self->{cond} = set_cond($ellipsis, $min_args, $num_args);
509
510     print Q(<<"EOF") if $self->{except};
511 #    char errbuf[1024];
512 #    *errbuf = '\\0';
513 EOF
514
515     if($self->{cond}) {
516       print Q(<<"EOF");
517 #    if ($self->{cond})
518 #       croak_xs_usage(cv,  "$report_args");
519 EOF
520     }
521     else {
522     # cv and items likely to be unused
523     print Q(<<"EOF");
524 #    PERL_UNUSED_VAR(cv); /* -W */
525 #    PERL_UNUSED_VAR(items); /* -W */
526 EOF
527     }
528
529     #gcc -Wall: if an xsub has PPCODE is used
530     #it is possible none of ST, XSRETURN or XSprePUSH macros are used
531     #hence 'ax' (setup by dXSARGS) is unused
532     #XXX: could breakup the dXSARGS; into dSP;dMARK;dITEMS
533     #but such a move could break third-party extensions
534     print Q(<<"EOF") if $PPCODE;
535 #    PERL_UNUSED_VAR(ax); /* -Wall */
536 EOF
537
538     print Q(<<"EOF") if $PPCODE;
539 #    SP -= items;
540 EOF
541
542     # Now do a block of some sort.
543
544     $self->{condnum} = 0;
545     $self->{cond} = '';            # last CASE: conditional
546     push(@{ $self->{line} }, "$END:");
547     push(@{ $self->{line_no} }, $self->{line_no}->[-1]);
548     $_ = '';
549     check_conditional_preprocessor_statements();
550     while (@{ $self->{line} }) {
551
552       $self->CASE_handler($_) if $self->check_keyword("CASE");
553       print Q(<<"EOF");
554 #   $self->{except} [[
555 EOF
556
557       # do initialization of input variables
558       $self->{thisdone} = 0;
559       $self->{retvaldone} = 0;
560       $self->{deferred} = "";
561       %{ $self->{arg_list} } = ();
562       $self->{gotRETVAL} = 0;
563       $self->INPUT_handler($_);
564       $self->process_keyword("INPUT|PREINIT|INTERFACE_MACRO|C_ARGS|ALIAS|ATTRS|PROTOTYPE|SCOPE|OVERLOAD");
565
566       print Q(<<"EOF") if $self->{ScopeThisXSUB};
567 #   ENTER;
568 #   [[
569 EOF
570
571       if (!$self->{thisdone} && defined($class)) {
572         if (defined($static) or $self->{func_name} eq 'new') {
573           print "\tchar *";
574           $self->{var_types}->{"CLASS"} = "char *";
575           $self->generate_init( {
576             type          => "char *",
577             num           => 1,
578             var           => "CLASS",
579             printed_name  => undef,
580           } );
581         }
582         else {
583           print "\t" . map_type($self, "$class *");
584           $self->{var_types}->{"THIS"} = "$class *";
585           $self->generate_init( {
586             type          => "$class *",
587             num           => 1,
588             var           => "THIS",
589             printed_name  => undef,
590           } );
591         }
592       }
593
594       # These are set if OUTPUT is found and/or CODE using RETVAL
595       $self->{have_OUTPUT} = $self->{have_CODE_with_RETVAL} = 0;
596
597       my ($wantRETVAL);
598       # do code
599       if (/^\s*NOT_IMPLEMENTED_YET/) {
600         print "\n\tPerl_croak(aTHX_ \"$self->{pname}: not implemented yet\");\n";
601         $_ = '';
602       }
603       else {
604         if ($self->{ret_type} ne "void") {
605           print "\t" . map_type($self, $self->{ret_type}, 'RETVAL') . ";\n"
606             if !$self->{retvaldone};
607           $self->{args_match}->{"RETVAL"} = 0;
608           $self->{var_types}->{"RETVAL"} = $self->{ret_type};
609           my $outputmap = $self->{typemap}->get_outputmap( ctype => $self->{ret_type} );
610           print "\tdXSTARG;\n"
611             if $self->{optimize} and $outputmap and $outputmap->targetable;
612         }
613
614         if (@fake_INPUT or @fake_INPUT_pre) {
615           unshift @{ $self->{line} }, @fake_INPUT_pre, @fake_INPUT, $_;
616           $_ = "";
617           $self->{processing_arg_with_types} = 1;
618           $self->INPUT_handler($_);
619         }
620         print $self->{deferred};
621
622         $self->process_keyword("INIT|ALIAS|ATTRS|PROTOTYPE|INTERFACE_MACRO|INTERFACE|C_ARGS|OVERLOAD");
623
624         if ($self->check_keyword("PPCODE")) {
625           $self->print_section();
626           $self->death("PPCODE must be last thing") if @{ $self->{line} };
627           print "\tLEAVE;\n" if $self->{ScopeThisXSUB};
628           print "\tPUTBACK;\n\treturn;\n";
629         }
630         elsif ($self->check_keyword("CODE")) {
631           my $consumed_code = $self->print_section();
632           if ($consumed_code =~ /\bRETVAL\b/) {
633             $self->{have_CODE_with_RETVAL} = 1;
634           }
635         }
636         elsif (defined($class) and $self->{func_name} eq "DESTROY") {
637           print "\n\t";
638           print "delete THIS;\n";
639         }
640         else {
641           print "\n\t";
642           if ($self->{ret_type} ne "void") {
643             print "RETVAL = ";
644             $wantRETVAL = 1;
645           }
646           if (defined($static)) {
647             if ($self->{func_name} eq 'new') {
648               $self->{func_name} = "$class";
649             }
650             else {
651               print "${class}::";
652             }
653           }
654           elsif (defined($class)) {
655             if ($self->{func_name} eq 'new') {
656               $self->{func_name} .= " $class";
657             }
658             else {
659               print "THIS->";
660             }
661           }
662           my $strip = $self->{strip_c_func_prefix};
663           $self->{func_name} =~ s/^\Q$strip//
664             if defined $strip;
665           $self->{func_name} = 'XSFUNCTION' if $self->{interface};
666           print "$self->{func_name}($self->{func_args});\n";
667         }
668       }
669
670       # do output variables
671       $self->{gotRETVAL} = 0;        # 1 if RETVAL seen in OUTPUT section;
672       undef $self->{RETVAL_code} ;    # code to set RETVAL (from OUTPUT section);
673       # $wantRETVAL set if 'RETVAL =' autogenerated
674       ($wantRETVAL, $self->{ret_type}) = (0, 'void') if $RETVAL_no_return;
675       undef %{ $self->{outargs} };
676
677       $self->process_keyword("POSTCALL|OUTPUT|ALIAS|ATTRS|PROTOTYPE|OVERLOAD");
678
679       # A CODE section with RETVAL, but no OUTPUT? FAIL!
680       if ($self->{have_CODE_with_RETVAL} and not $self->{have_OUTPUT} and $self->{ret_type} ne 'void') {
681         $self->Warn("Warning: Found a 'CODE' section which seems to be using 'RETVAL' but no 'OUTPUT' section.");
682       }
683
684       $self->generate_output( {
685         type        => $self->{var_types}->{$_},
686         num         => $self->{args_match}->{$_},
687         var         => $_,
688         do_setmagic => $self->{DoSetMagic},
689         do_push     => undef,
690       } ) for grep $self->{in_out}->{$_} =~ /OUT$/, sort keys %{ $self->{in_out} };
691
692       my $prepush_done;
693       # all OUTPUT done, so now push the return value on the stack
694       if ($self->{gotRETVAL} && $self->{RETVAL_code}) {
695         print "\t$self->{RETVAL_code}\n";
696       }
697       elsif ($self->{gotRETVAL} || $wantRETVAL) {
698         my $outputmap = $self->{typemap}->get_outputmap( ctype => $self->{ret_type} );
699         my $trgt = $self->{optimize} && $outputmap && $outputmap->targetable;
700         my $var = 'RETVAL';
701         my $type = $self->{ret_type};
702
703         if ($trgt) {
704           my $what = $self->eval_output_typemap_code(
705             qq("$trgt->{what}"),
706             {var => $var, type => $self->{ret_type}}
707           );
708           if (not $trgt->{with_size} and $trgt->{type} eq 'p') { # sv_setpv
709             # PUSHp corresponds to sv_setpvn.  Treat sv_setpv directly
710             print "\tsv_setpv(TARG, $what); XSprePUSH; PUSHTARG;\n";
711             $prepush_done = 1;
712           }
713           else {
714             my $tsize = $trgt->{what_size};
715             $tsize = '' unless defined $tsize;
716             $tsize = $self->eval_output_typemap_code(
717               qq("$tsize"),
718               {var => $var, type => $self->{ret_type}}
719             );
720             print "\tXSprePUSH; PUSH$trgt->{type}($what$tsize);\n";
721             $prepush_done = 1;
722           }
723         }
724         else {
725           # RETVAL almost never needs SvSETMAGIC()
726           $self->generate_output( {
727             type        => $self->{ret_type},
728             num         => 0,
729             var         => 'RETVAL',
730             do_setmagic => 0,
731             do_push     => undef,
732           } );
733         }
734       }
735
736       $xsreturn = 1 if $self->{ret_type} ne "void";
737       my $num = $xsreturn;
738       my $c = @{ $outlist_ref };
739       print "\tXSprePUSH;" if $c and not $prepush_done;
740       print "\tEXTEND(SP,$c);\n" if $c;
741       $xsreturn += $c;
742       $self->generate_output( {
743         type        => $self->{var_types}->{$_},
744         num         => $num++,
745         var         => $_,
746         do_setmagic => 0,
747         do_push     => 1,
748       } ) for @{ $outlist_ref };
749
750       # do cleanup
751       $self->process_keyword("CLEANUP|ALIAS|ATTRS|PROTOTYPE|OVERLOAD");
752
753       print Q(<<"EOF") if $self->{ScopeThisXSUB};
754 #   ]]
755 EOF
756       print Q(<<"EOF") if $self->{ScopeThisXSUB} and not $PPCODE;
757 #   LEAVE;
758 EOF
759
760       # print function trailer
761       print Q(<<"EOF");
762 #    ]]
763 EOF
764       print Q(<<"EOF") if $self->{except};
765 #    BEGHANDLERS
766 #    CATCHALL
767 #    sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
768 #    ENDHANDLERS
769 EOF
770       if ($self->check_keyword("CASE")) {
771         $self->blurt("Error: No 'CASE:' at top of function")
772           unless $self->{condnum};
773         $_ = "CASE: $_";    # Restore CASE: label
774         next;
775       }
776       last if $_ eq "$END:";
777       $self->death(/^$BLOCK_regexp/o ? "Misplaced '$1:'" : "Junk at end of function ($_)");
778     }
779
780     print Q(<<"EOF") if $self->{except};
781 #    if (errbuf[0])
782 #    Perl_croak(aTHX_ errbuf);
783 EOF
784
785     if ($xsreturn) {
786       print Q(<<"EOF") unless $PPCODE;
787 #    XSRETURN($xsreturn);
788 EOF
789     }
790     else {
791       print Q(<<"EOF") unless $PPCODE;
792 #    XSRETURN_EMPTY;
793 EOF
794     }
795
796     print Q(<<"EOF");
797 #]]
798 #
799 EOF
800
801     $self->{proto} = "";
802     unless($self->{ProtoThisXSUB}) {
803       $self->{newXS} = "newXS_deffile";
804       $self->{file} = "";
805     }
806     else {
807     # Build the prototype string for the xsub
808       $self->{newXS} = "newXSproto_portable";
809       $self->{file} = ", file";
810
811       if ($self->{ProtoThisXSUB} eq 2) {
812         # User has specified empty prototype
813       }
814       elsif ($self->{ProtoThisXSUB} eq 1) {
815         my $s = ';';
816         if ($min_args < $num_args)  {
817           $s = '';
818           $self->{proto_arg}->[$min_args] .= ";";
819         }
820         push @{ $self->{proto_arg} }, "$s\@"
821           if $ellipsis;
822
823         $self->{proto} = join ("", grep defined, @{ $self->{proto_arg} } );
824       }
825       else {
826         # User has specified a prototype
827         $self->{proto} = $self->{ProtoThisXSUB};
828       }
829       $self->{proto} = qq{, "$self->{proto}"};
830     }
831
832     if ($self->{XsubAliases} and keys %{ $self->{XsubAliases} }) {
833       $self->{XsubAliases}->{ $self->{pname} } = 0
834         unless defined $self->{XsubAliases}->{ $self->{pname} };
835       foreach my $xname (sort keys %{ $self->{XsubAliases} }) {
836         my $value = $self->{XsubAliases}{$xname};
837         push(@{ $self->{InitFileCode} }, Q(<<"EOF"));
838 #        cv = $self->{newXS}(\"$xname\", XS_$self->{Full_func_name}$self->{file}$self->{proto});
839 #        XSANY.any_i32 = $value;
840 EOF
841       }
842     }
843     elsif (@{ $self->{Attributes} }) {
844       push(@{ $self->{InitFileCode} }, Q(<<"EOF"));
845 #        cv = $self->{newXS}(\"$self->{pname}\", XS_$self->{Full_func_name}$self->{file}$self->{proto});
846 #        apply_attrs_string("$self->{Package}", cv, "@{ $self->{Attributes} }", 0);
847 EOF
848     }
849     elsif ($self->{interface}) {
850       foreach my $yname (sort keys %{ $self->{Interfaces} }) {
851         my $value = $self->{Interfaces}{$yname};
852         $yname = "$self->{Package}\::$yname" unless $yname =~ /::/;
853         push(@{ $self->{InitFileCode} }, Q(<<"EOF"));
854 #        cv = $self->{newXS}(\"$yname\", XS_$self->{Full_func_name}$self->{file}$self->{proto});
855 #        $self->{interface_macro_set}(cv,$value);
856 EOF
857       }
858     }
859     elsif($self->{newXS} eq 'newXS_deffile'){ # work around P5NCI's empty newXS macro
860       push(@{ $self->{InitFileCode} },
861        "        $self->{newXS}(\"$self->{pname}\", XS_$self->{Full_func_name}$self->{file}$self->{proto});\n");
862     }
863     else {
864       push(@{ $self->{InitFileCode} },
865        "        (void)$self->{newXS}(\"$self->{pname}\", XS_$self->{Full_func_name}$self->{file}$self->{proto});\n");
866     }
867   } # END 'PARAGRAPH' 'while' loop
868
869   if ($self->{Overload}) { # make it findable with fetchmethod
870     print Q(<<"EOF");
871 #XS_EUPXS(XS_$self->{Packid}_nil); /* prototype to pass -Wmissing-prototypes */
872 #XS_EUPXS(XS_$self->{Packid}_nil)
873 #{
874 #   dXSARGS;
875 #   PERL_UNUSED_VAR(items);
876 #   XSRETURN_EMPTY;
877 #}
878 #
879 EOF
880     unshift(@{ $self->{InitFileCode} }, <<"MAKE_FETCHMETHOD_WORK");
881     /* Making a sub named "$self->{Package}::()" allows the package */
882     /* to be findable via fetchmethod(), and causes */
883     /* overload::Overloaded("$self->{Package}") to return true. */
884     (void)$self->{newXS}("$self->{Package}::()", XS_$self->{Packid}_nil$self->{file}$self->{proto});
885 MAKE_FETCHMETHOD_WORK
886   }
887
888   # print initialization routine
889
890   print Q(<<"EOF");
891 ##ifdef __cplusplus
892 #extern "C"
893 ##endif
894 EOF
895
896   print Q(<<"EOF");
897 #XS_EXTERNAL(boot_$self->{Module_cname}); /* prototype to pass -Wmissing-prototypes */
898 #XS_EXTERNAL(boot_$self->{Module_cname})
899 #[[
900 ##if PERL_VERSION_LE(5, 21, 5)
901 #    dVAR; dXSARGS;
902 ##else
903 #    dVAR; ${\($self->{WantVersionChk} ?
904      'dXSBOOTARGSXSAPIVERCHK;' : 'dXSBOOTARGSAPIVERCHK;')}
905 ##endif
906 EOF
907
908   #Under 5.8.x and lower, newXS is declared in proto.h as expecting a non-const
909   #file name argument. If the wrong qualifier is used, it causes breakage with
910   #C++ compilers and warnings with recent gcc.
911   #-Wall: if there is no $self->{Full_func_name} there are no xsubs in this .xs
912   #so 'file' is unused
913   print Q(<<"EOF") if $self->{Full_func_name};
914 ##if (PERL_REVISION == 5 && PERL_VERSION < 9)
915 #    char* file = __FILE__;
916 ##else
917 #    const char* file = __FILE__;
918 ##endif
919 #
920 #    PERL_UNUSED_VAR(file);
921 EOF
922
923   print Q("#\n");
924
925   print Q(<<"EOF");
926 #    PERL_UNUSED_VAR(cv); /* -W */
927 #    PERL_UNUSED_VAR(items); /* -W */
928 EOF
929
930   if( $self->{WantVersionChk}){
931     print Q(<<"EOF") ;
932 ##if PERL_VERSION_LE(5, 21, 5)
933 #    XS_VERSION_BOOTCHECK;
934 ##  ifdef XS_APIVERSION_BOOTCHECK
935 #    XS_APIVERSION_BOOTCHECK;
936 ##  endif
937 ##endif
938
939 EOF
940   } else {
941     print Q(<<"EOF") ;
942 ##if PERL_VERSION_LE(5, 21, 5) && defined(XS_APIVERSION_BOOTCHECK)
943 #  XS_APIVERSION_BOOTCHECK;
944 ##endif
945
946 EOF
947   }
948
949   print Q(<<"EOF") if defined $self->{XsubAliases} or defined $self->{interfaces};
950 #    {
951 #        CV * cv;
952 #
953 EOF
954
955   print Q(<<"EOF") if ($self->{Overload});
956 #    /* register the overloading (type 'A') magic */
957 ##if (PERL_REVISION == 5 && PERL_VERSION < 9)
958 #    PL_amagic_generation++;
959 ##endif
960 #    /* The magic for overload gets a GV* via gv_fetchmeth as */
961 #    /* mentioned above, and looks in the SV* slot of it for */
962 #    /* the "fallback" status. */
963 #    sv_setsv(
964 #        get_sv( "$self->{Package}::()", TRUE ),
965 #        $self->{Fallback}
966 #    );
967 EOF
968
969   print @{ $self->{InitFileCode} };
970
971   print Q(<<"EOF") if defined $self->{XsubAliases} or defined $self->{interfaces};
972 #    }
973 EOF
974
975   if (@{ $BootCode_ref }) {
976     print "\n    /* Initialisation Section */\n\n";
977     @{ $self->{line} } = @{ $BootCode_ref };
978     $self->print_section();
979     print "\n    /* End of Initialisation Section */\n\n";
980   }
981
982   print Q(<<'EOF');
983 ##if PERL_VERSION_LE(5, 21, 5)
984 ##  if PERL_VERSION_GE(5, 9, 0)
985 #    if (PL_unitcheckav)
986 #        call_list(PL_scopestack_ix, PL_unitcheckav);
987 ##  endif
988 #    XSRETURN_YES;
989 ##else
990 #    Perl_xs_boot_epilog(aTHX_ ax);
991 ##endif
992 #]]
993 #
994 EOF
995
996   warn("Please specify prototyping behavior for $self->{filename} (see perlxs manual)\n")
997     unless $self->{ProtoUsed};
998
999   chdir($orig_cwd);
1000   select($orig_fh);
1001   untie *PSEUDO_STDOUT if tied *PSEUDO_STDOUT;
1002   close $self->{FH};
1003
1004   return 1;
1005 }
1006
1007 sub report_error_count {
1008   if (@_) {
1009     return $_[0]->{errors}||0;
1010   }
1011   else {
1012     return $Singleton->{errors}||0;
1013   }
1014 }
1015
1016 # Input:  ($self, $_, @{ $self->{line} }) == unparsed input.
1017 # Output: ($_, @{ $self->{line} }) == (rest of line, following lines).
1018 # Return: the matched keyword if found, otherwise 0
1019 sub check_keyword {
1020   my $self = shift;
1021   $_ = shift(@{ $self->{line} }) while !/\S/ && @{ $self->{line} };
1022   s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
1023 }
1024
1025 sub print_section {
1026   my $self = shift;
1027
1028   # the "do" is required for right semantics
1029   do { $_ = shift(@{ $self->{line} }) } while !/\S/ && @{ $self->{line} };
1030
1031   my $consumed_code = '';
1032
1033   print("#line ", $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} } -1], " \"",
1034         escape_file_for_line_directive($self->{filepathname}), "\"\n")
1035     if $self->{WantLineNumbers} && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
1036   for (;  defined($_) && !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1037     print "$_\n";
1038     $consumed_code .= "$_\n";
1039   }
1040   print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $self->{WantLineNumbers};
1041
1042   return $consumed_code;
1043 }
1044
1045 sub merge_section {
1046   my $self = shift;
1047   my $in = '';
1048
1049   while (!/\S/ && @{ $self->{line} }) {
1050     $_ = shift(@{ $self->{line} });
1051   }
1052
1053   for (;  defined($_) && !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1054     $in .= "$_\n";
1055   }
1056   chomp $in;
1057   return $in;
1058 }
1059
1060 sub process_keyword {
1061   my($self, $pattern) = @_;
1062
1063   while (my $kwd = $self->check_keyword($pattern)) {
1064     my $method = $kwd . "_handler";
1065     $self->$method($_);
1066   }
1067 }
1068
1069 sub CASE_handler {
1070   my $self = shift;
1071   $_ = shift;
1072   $self->blurt("Error: 'CASE:' after unconditional 'CASE:'")
1073     if $self->{condnum} && $self->{cond} eq '';
1074   $self->{cond} = $_;
1075   trim_whitespace($self->{cond});
1076   print "   ", ($self->{condnum}++ ? " else" : ""), ($self->{cond} ? " if ($self->{cond})\n" : "\n");
1077   $_ = '';
1078 }
1079
1080 sub INPUT_handler {
1081   my $self = shift;
1082   $_ = shift;
1083   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1084     last if /^\s*NOT_IMPLEMENTED_YET/;
1085     next unless /\S/;        # skip blank lines
1086
1087     trim_whitespace($_);
1088     my $ln = $_;
1089
1090     # remove trailing semicolon if no initialisation
1091     s/\s*;$//g unless /[=;+].*\S/;
1092
1093     # Process the length(foo) declarations
1094     if (s/^([^=]*)\blength\(\s*(\w+)\s*\)\s*$/$1 XSauto_length_of_$2=NO_INIT/x) {
1095       print "\tSTRLEN\tSTRLEN_length_of_$2;\n";
1096       $self->{lengthof}->{$2} = undef;
1097       $self->{deferred} .= "\n\tXSauto_length_of_$2 = STRLEN_length_of_$2;\n";
1098     }
1099
1100     # check for optional initialisation code
1101     my $var_init = '';
1102     $var_init = $1 if s/\s*([=;+].*)$//s;
1103     $var_init =~ s/"/\\"/g;
1104     # *sigh* It's valid to supply explicit input typemaps in the argument list...
1105     my $is_overridden_typemap = $var_init =~ /ST\s*\(|\$arg\b/;
1106
1107     s/\s+/ /g;
1108     my ($var_type, $var_addr, $var_name) = /^(.*?[^&\s])\s*(\&?)\s*\b(\w+)$/s
1109       or $self->blurt("Error: invalid argument declaration '$ln'"), next;
1110
1111     # Check for duplicate definitions
1112     $self->blurt("Error: duplicate definition of argument '$var_name' ignored"), next
1113       if $self->{arg_list}->{$var_name}++
1114         or defined $self->{argtype_seen}->{$var_name} and not $self->{processing_arg_with_types};
1115
1116     $self->{thisdone} |= $var_name eq "THIS";
1117     $self->{retvaldone} |= $var_name eq "RETVAL";
1118     $self->{var_types}->{$var_name} = $var_type;
1119     # XXXX This check is a safeguard against the unfinished conversion of
1120     # generate_init().  When generate_init() is fixed,
1121     # one can use 2-args map_type() unconditionally.
1122     my $printed_name;
1123     if ($var_type =~ / \( \s* \* \s* \) /x) {
1124       # Function pointers are not yet supported with output_init()!
1125       print "\t" . map_type($self, $var_type, $var_name);
1126       $printed_name = 1;
1127     }
1128     else {
1129       print "\t" . map_type($self, $var_type, undef);
1130       $printed_name = 0;
1131     }
1132     $self->{var_num} = $self->{args_match}->{$var_name};
1133
1134     if ($self->{var_num}) {
1135       my $typemap = $self->{typemap}->get_typemap(ctype => $var_type);
1136       $self->report_typemap_failure($self->{typemap}, $var_type, "death")
1137         if not $typemap and not $is_overridden_typemap;
1138       $self->{proto_arg}->[$self->{var_num}] = ($typemap && $typemap->proto) || "\$";
1139     }
1140     $self->{func_args} =~ s/\b($var_name)\b/&$1/ if $var_addr;
1141     if ($var_init =~ /^[=;]\s*NO_INIT\s*;?\s*$/
1142       or $self->{in_out}->{$var_name} and $self->{in_out}->{$var_name} =~ /^OUT/
1143       and $var_init !~ /\S/) {
1144       if ($printed_name) {
1145         print ";\n";
1146       }
1147       else {
1148         print "\t$var_name;\n";
1149       }
1150     }
1151     elsif ($var_init =~ /\S/) {
1152       $self->output_init( {
1153         type          => $var_type,
1154         num           => $self->{var_num},
1155         var           => $var_name,
1156         init          => $var_init,
1157         printed_name  => $printed_name,
1158       } );
1159     }
1160     elsif ($self->{var_num}) {
1161       $self->generate_init( {
1162         type          => $var_type,
1163         num           => $self->{var_num},
1164         var           => $var_name,
1165         printed_name  => $printed_name,
1166       } );
1167     }
1168     else {
1169       print ";\n";
1170     }
1171   }
1172 }
1173
1174 sub OUTPUT_handler {
1175   my $self = shift;
1176   $self->{have_OUTPUT} = 1;
1177
1178   $_ = shift;
1179   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1180     next unless /\S/;
1181     if (/^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) {
1182       $self->{DoSetMagic} = ($1 eq "ENABLE" ? 1 : 0);
1183       next;
1184     }
1185     my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s;
1186     $self->blurt("Error: duplicate OUTPUT argument '$outarg' ignored"), next
1187       if $self->{outargs}->{$outarg}++;
1188     if (!$self->{gotRETVAL} and $outarg eq 'RETVAL') {
1189       # deal with RETVAL last
1190       $self->{RETVAL_code} = $outcode;
1191       $self->{gotRETVAL} = 1;
1192       next;
1193     }
1194     $self->blurt("Error: OUTPUT $outarg not an argument"), next
1195       unless defined($self->{args_match}->{$outarg});
1196     $self->blurt("Error: No input definition for OUTPUT argument '$outarg' - ignored"), next
1197       unless defined $self->{var_types}->{$outarg};
1198     $self->{var_num} = $self->{args_match}->{$outarg};
1199     if ($outcode) {
1200       print "\t$outcode\n";
1201       print "\tSvSETMAGIC(ST(" , $self->{var_num} - 1 , "));\n" if $self->{DoSetMagic};
1202     }
1203     else {
1204       $self->generate_output( {
1205         type        => $self->{var_types}->{$outarg},
1206         num         => $self->{var_num},
1207         var         => $outarg,
1208         do_setmagic => $self->{DoSetMagic},
1209         do_push     => undef,
1210       } );
1211     }
1212     delete $self->{in_out}->{$outarg}     # No need to auto-OUTPUT
1213       if exists $self->{in_out}->{$outarg} and $self->{in_out}->{$outarg} =~ /OUT$/;
1214   }
1215 }
1216
1217 sub C_ARGS_handler {
1218   my $self = shift;
1219   $_ = shift;
1220   my $in = $self->merge_section();
1221
1222   trim_whitespace($in);
1223   $self->{func_args} = $in;
1224 }
1225
1226 sub INTERFACE_MACRO_handler {
1227   my $self = shift;
1228   $_ = shift;
1229   my $in = $self->merge_section();
1230
1231   trim_whitespace($in);
1232   if ($in =~ /\s/) {        # two
1233     ($self->{interface_macro}, $self->{interface_macro_set}) = split ' ', $in;
1234   }
1235   else {
1236     $self->{interface_macro} = $in;
1237     $self->{interface_macro_set} = 'UNKNOWN_CVT'; # catch later
1238   }
1239   $self->{interface} = 1;        # local
1240   $self->{interfaces} = 1;        # global
1241 }
1242
1243 sub INTERFACE_handler {
1244   my $self = shift;
1245   $_ = shift;
1246   my $in = $self->merge_section();
1247
1248   trim_whitespace($in);
1249
1250   foreach (split /[\s,]+/, $in) {
1251     my $iface_name = $_;
1252     $iface_name =~ s/^$self->{Prefix}//;
1253     $self->{Interfaces}->{$iface_name} = $_;
1254   }
1255   print Q(<<"EOF");
1256 #    XSFUNCTION = $self->{interface_macro}($self->{ret_type},cv,XSANY.any_dptr);
1257 EOF
1258   $self->{interface} = 1;        # local
1259   $self->{interfaces} = 1;        # global
1260 }
1261
1262 sub CLEANUP_handler {
1263   my $self = shift;
1264   $self->print_section();
1265 }
1266
1267 sub PREINIT_handler {
1268   my $self = shift;
1269   $self->print_section();
1270 }
1271
1272 sub POSTCALL_handler {
1273   my $self = shift;
1274   $self->print_section();
1275 }
1276
1277 sub INIT_handler {
1278   my $self = shift;
1279   $self->print_section();
1280 }
1281
1282 sub get_aliases {
1283   my $self = shift;
1284   my ($line) = @_;
1285   my ($orig) = $line;
1286
1287   # Parse alias definitions
1288   # format is
1289   #    alias = value alias = value ...
1290
1291   while ($line =~ s/^\s*([\w:]+)\s*=\s*(\w+)\s*//) {
1292     my ($alias, $value) = ($1, $2);
1293     my $orig_alias = $alias;
1294
1295     # check for optional package definition in the alias
1296     $alias = $self->{Packprefix} . $alias if $alias !~ /::/;
1297
1298     # check for duplicate alias name & duplicate value
1299     Warn( $self, "Warning: Ignoring duplicate alias '$orig_alias'")
1300       if defined $self->{XsubAliases}->{$alias};
1301
1302     Warn( $self, "Warning: Aliases '$orig_alias' and '$self->{XsubAliasValues}->{$value}' have identical values")
1303       if $self->{XsubAliasValues}->{$value};
1304
1305     $self->{XsubAliases}->{$alias} = $value;
1306     $self->{XsubAliasValues}->{$value} = $orig_alias;
1307   }
1308
1309   blurt( $self, "Error: Cannot parse ALIAS definitions from '$orig'")
1310     if $line;
1311 }
1312
1313 sub ATTRS_handler {
1314   my $self = shift;
1315   $_ = shift;
1316
1317   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1318     next unless /\S/;
1319     trim_whitespace($_);
1320     push @{ $self->{Attributes} }, $_;
1321   }
1322 }
1323
1324 sub ALIAS_handler {
1325   my $self = shift;
1326   $_ = shift;
1327
1328   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1329     next unless /\S/;
1330     trim_whitespace($_);
1331     $self->get_aliases($_) if $_;
1332   }
1333 }
1334
1335 sub OVERLOAD_handler {
1336   my $self = shift;
1337   $_ = shift;
1338
1339   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1340     next unless /\S/;
1341     trim_whitespace($_);
1342     while ( s/^\s*([\w:"\\)\+\-\*\/\%\<\>\.\&\|\^\!\~\{\}\=]+)\s*//) {
1343       $self->{Overload} = 1 unless $self->{Overload};
1344       my $overload = "$self->{Package}\::(".$1;
1345       push(@{ $self->{InitFileCode} },
1346        "        (void)$self->{newXS}(\"$overload\", XS_$self->{Full_func_name}$self->{file}$self->{proto});\n");
1347     }
1348   }
1349 }
1350
1351 sub FALLBACK_handler {
1352   my ($self, $setting) = @_;
1353
1354   # the rest of the current line should contain either TRUE,
1355   # FALSE or UNDEF
1356
1357   trim_whitespace($setting);
1358   $setting = uc($setting);
1359
1360   my %map = (
1361     TRUE => "&PL_sv_yes", 1 => "&PL_sv_yes",
1362     FALSE => "&PL_sv_no", 0 => "&PL_sv_no",
1363     UNDEF => "&PL_sv_undef",
1364   );
1365
1366   # check for valid FALLBACK value
1367   $self->death("Error: FALLBACK: TRUE/FALSE/UNDEF") unless exists $map{$setting};
1368
1369   $self->{Fallback} = $map{$setting};
1370 }
1371
1372
1373 sub REQUIRE_handler {
1374   # the rest of the current line should contain a version number
1375   my ($self, $ver) = @_;
1376
1377   trim_whitespace($ver);
1378
1379   $self->death("Error: REQUIRE expects a version number")
1380     unless $ver;
1381
1382   # check that the version number is of the form n.n
1383   $self->death("Error: REQUIRE: expected a number, got '$ver'")
1384     unless $ver =~ /^\d+(\.\d*)?/;
1385
1386   $self->death("Error: xsubpp $ver (or better) required--this is only $VERSION.")
1387     unless $VERSION >= $ver;
1388 }
1389
1390 sub VERSIONCHECK_handler {
1391   # the rest of the current line should contain either ENABLE or
1392   # DISABLE
1393   my ($self, $setting) = @_;
1394
1395   trim_whitespace($setting);
1396
1397   # check for ENABLE/DISABLE
1398   $self->death("Error: VERSIONCHECK: ENABLE/DISABLE")
1399     unless $setting =~ /^(ENABLE|DISABLE)/i;
1400
1401   $self->{WantVersionChk} = 1 if $1 eq 'ENABLE';
1402   $self->{WantVersionChk} = 0 if $1 eq 'DISABLE';
1403
1404 }
1405
1406 sub PROTOTYPE_handler {
1407   my $self = shift;
1408   $_ = shift;
1409
1410   my $specified;
1411
1412   $self->death("Error: Only 1 PROTOTYPE definition allowed per xsub")
1413     if $self->{proto_in_this_xsub}++;
1414
1415   for (;  !/^$BLOCK_regexp/o;  $_ = shift(@{ $self->{line} })) {
1416     next unless /\S/;
1417     $specified = 1;
1418     trim_whitespace($_);
1419     if ($_ eq 'DISABLE') {
1420       $self->{ProtoThisXSUB} = 0;
1421     }
1422     elsif ($_ eq 'ENABLE') {
1423       $self->{ProtoThisXSUB} = 1;
1424     }
1425     else {
1426       # remove any whitespace
1427       s/\s+//g;
1428       $self->death("Error: Invalid prototype '$_'")
1429         unless valid_proto_string($_);
1430       $self->{ProtoThisXSUB} = C_string($_);
1431     }
1432   }
1433
1434   # If no prototype specified, then assume empty prototype ""
1435   $self->{ProtoThisXSUB} = 2 unless $specified;
1436
1437   $self->{ProtoUsed} = 1;
1438 }
1439
1440 sub SCOPE_handler {
1441   # Rest of line should be either ENABLE or DISABLE
1442   my ($self, $setting) = @_;
1443
1444   $self->death("Error: Only 1 SCOPE declaration allowed per xsub")
1445     if $self->{scope_in_this_xsub}++;
1446
1447   trim_whitespace($setting);
1448   $self->death("Error: SCOPE: ENABLE/DISABLE")
1449       unless $setting =~ /^(ENABLE|DISABLE)\b/i;
1450   $self->{ScopeThisXSUB} = ( uc($1) eq 'ENABLE' );
1451 }
1452
1453 sub PROTOTYPES_handler {
1454   # the rest of the current line should contain either ENABLE or
1455   # DISABLE
1456   my ($self, $setting) = @_;
1457
1458   trim_whitespace($setting);
1459
1460   # check for ENABLE/DISABLE
1461   $self->death("Error: PROTOTYPES: ENABLE/DISABLE")
1462     unless $setting =~ /^(ENABLE|DISABLE)/i;
1463
1464   $self->{WantPrototypes} = 1 if $1 eq 'ENABLE';
1465   $self->{WantPrototypes} = 0 if $1 eq 'DISABLE';
1466   $self->{ProtoUsed} = 1;
1467 }
1468
1469 sub EXPORT_XSUB_SYMBOLS_handler {
1470   # the rest of the current line should contain either ENABLE or
1471   # DISABLE
1472   my ($self, $setting) = @_;
1473
1474   trim_whitespace($setting);
1475
1476   # check for ENABLE/DISABLE
1477   $self->death("Error: EXPORT_XSUB_SYMBOLS: ENABLE/DISABLE")
1478     unless $setting =~ /^(ENABLE|DISABLE)/i;
1479
1480   my $xs_impl = $1 eq 'ENABLE' ? 'XS_EXTERNAL' : 'XS_INTERNAL';
1481
1482   print Q(<<"EOF");
1483 ##undef XS_EUPXS
1484 ##if defined(PERL_EUPXS_ALWAYS_EXPORT)
1485 ##  define XS_EUPXS(name) XS_EXTERNAL(name)
1486 ##elif defined(PERL_EUPXS_NEVER_EXPORT)
1487 ##  define XS_EUPXS(name) XS_INTERNAL(name)
1488 ##else
1489 ##  define XS_EUPXS(name) $xs_impl(name)
1490 ##endif
1491 EOF
1492 }
1493
1494
1495 sub PushXSStack {
1496   my $self = shift;
1497   my %args = @_;
1498   # Save the current file context.
1499   push(@{ $self->{XSStack} }, {
1500           type            => 'file',
1501           LastLine        => $self->{lastline},
1502           LastLineNo      => $self->{lastline_no},
1503           Line            => $self->{line},
1504           LineNo          => $self->{line_no},
1505           Filename        => $self->{filename},
1506           Filepathname    => $self->{filepathname},
1507           Handle          => $self->{FH},
1508           IsPipe          => scalar($self->{filename} =~ /\|\s*$/),
1509           %args,
1510          });
1511
1512 }
1513
1514 sub INCLUDE_handler {
1515   my $self = shift;
1516   $_ = shift;
1517   # the rest of the current line should contain a valid filename
1518
1519   trim_whitespace($_);
1520
1521   $self->death("INCLUDE: filename missing")
1522     unless $_;
1523
1524   $self->death("INCLUDE: output pipe is illegal")
1525     if /^\s*\|/;
1526
1527   # simple minded recursion detector
1528   $self->death("INCLUDE loop detected")
1529     if $self->{IncludedFiles}->{$_};
1530
1531   ++$self->{IncludedFiles}->{$_} unless /\|\s*$/;
1532
1533   if (/\|\s*$/ && /^\s*perl\s/) {
1534     Warn( $self, "The INCLUDE directive with a command is discouraged." .
1535           " Use INCLUDE_COMMAND instead! In particular using 'perl'" .
1536           " in an 'INCLUDE: ... |' directive is not guaranteed to pick" .
1537           " up the correct perl. The INCLUDE_COMMAND directive allows" .
1538           " the use of \$^X as the currently running perl, see" .
1539           " 'perldoc perlxs' for details.");
1540   }
1541
1542   $self->PushXSStack();
1543
1544   $self->{FH} = Symbol::gensym();
1545
1546   # open the new file
1547   open($self->{FH}, $_) or $self->death("Cannot open '$_': $!");
1548
1549   print Q(<<"EOF");
1550 #
1551 #/* INCLUDE:  Including '$_' from '$self->{filename}' */
1552 #
1553 EOF
1554
1555   $self->{filename} = $_;
1556   $self->{filepathname} = ( $^O =~ /^mswin/i )
1557                           ? qq($self->{dir}/$self->{filename}) # See CPAN RT #61908: gcc doesn't like backslashes on win32?
1558                           : File::Spec->catfile($self->{dir}, $self->{filename});
1559
1560   # Prime the pump by reading the first
1561   # non-blank line
1562
1563   # skip leading blank lines
1564   while (readline($self->{FH})) {
1565     last unless /^\s*$/;
1566   }
1567
1568   $self->{lastline} = $_;
1569   $self->{lastline_no} = $.;
1570 }
1571
1572 sub QuoteArgs {
1573   my $cmd = shift;
1574   my @args = split /\s+/, $cmd;
1575   $cmd = shift @args;
1576   for (@args) {
1577     $_ = q(").$_.q(") if !/^\"/ && length($_) > 0;
1578   }
1579   return join (' ', ($cmd, @args));
1580 }
1581
1582 # code copied from CPAN::HandleConfig::safe_quote
1583 #  - that has doc saying leave if start/finish with same quote, but no code
1584 # given text, will conditionally quote it to protect from shell
1585 {
1586   my ($quote, $use_quote) = $^O eq 'MSWin32'
1587       ? (q{"}, q{"})
1588       : (q{"'}, q{'});
1589   sub _safe_quote {
1590       my ($self, $command) = @_;
1591       # Set up quote/default quote
1592       if (defined($command)
1593           and $command =~ /\s/
1594           and $command !~ /[$quote]/) {
1595           return qq{$use_quote$command$use_quote}
1596       }
1597       return $command;
1598   }
1599 }
1600
1601 sub INCLUDE_COMMAND_handler {
1602   my $self = shift;
1603   $_ = shift;
1604   # the rest of the current line should contain a valid command
1605
1606   trim_whitespace($_);
1607
1608   $_ = QuoteArgs($_) if $^O eq 'VMS';
1609
1610   $self->death("INCLUDE_COMMAND: command missing")
1611     unless $_;
1612
1613   $self->death("INCLUDE_COMMAND: pipes are illegal")
1614     if /^\s*\|/ or /\|\s*$/;
1615
1616   $self->PushXSStack( IsPipe => 1 );
1617
1618   $self->{FH} = Symbol::gensym();
1619
1620   # If $^X is used in INCLUDE_COMMAND, we know it's supposed to be
1621   # the same perl interpreter as we're currently running
1622   my $X = $self->_safe_quote($^X); # quotes if has spaces
1623   s/^\s*\$\^X/$X/;
1624
1625   # open the new file
1626   open ($self->{FH}, "-|", $_)
1627     or $self->death( $self, "Cannot run command '$_' to include its output: $!");
1628
1629   print Q(<<"EOF");
1630 #
1631 #/* INCLUDE_COMMAND:  Including output of '$_' from '$self->{filename}' */
1632 #
1633 EOF
1634
1635   $self->{filename} = $_;
1636   $self->{filepathname} = $self->{filename};
1637   #$self->{filepathname} =~ s/\"/\\"/g; # Fails? See CPAN RT #53938: MinGW Broken after 2.21
1638   $self->{filepathname} =~ s/\\/\\\\/g; # Works according to reporter of #53938
1639
1640   # Prime the pump by reading the first
1641   # non-blank line
1642
1643   # skip leading blank lines
1644   while (readline($self->{FH})) {
1645     last unless /^\s*$/;
1646   }
1647
1648   $self->{lastline} = $_;
1649   $self->{lastline_no} = $.;
1650 }
1651
1652 sub PopFile {
1653   my $self = shift;
1654
1655   return 0 unless $self->{XSStack}->[-1]{type} eq 'file';
1656
1657   my $data     = pop @{ $self->{XSStack} };
1658   my $ThisFile = $self->{filename};
1659   my $isPipe   = $data->{IsPipe};
1660
1661   --$self->{IncludedFiles}->{$self->{filename}}
1662     unless $isPipe;
1663
1664   close $self->{FH};
1665
1666   $self->{FH}         = $data->{Handle};
1667   # $filename is the leafname, which for some reason is used for diagnostic
1668   # messages, whereas $filepathname is the full pathname, and is used for
1669   # #line directives.
1670   $self->{filename}   = $data->{Filename};
1671   $self->{filepathname} = $data->{Filepathname};
1672   $self->{lastline}   = $data->{LastLine};
1673   $self->{lastline_no} = $data->{LastLineNo};
1674   @{ $self->{line} }       = @{ $data->{Line} };
1675   @{ $self->{line_no} }    = @{ $data->{LineNo} };
1676
1677   if ($isPipe and $? ) {
1678     --$self->{lastline_no};
1679     print STDERR "Error reading from pipe '$ThisFile': $! in $self->{filename}, line $self->{lastline_no}\n" ;
1680     exit 1;
1681   }
1682
1683   print Q(<<"EOF");
1684 #
1685 #/* INCLUDE: Returning to '$self->{filename}' from '$ThisFile' */
1686 #
1687 EOF
1688
1689   return 1;
1690 }
1691
1692 sub Q {
1693   my($text) = @_;
1694   $text =~ s/^#//gm;
1695   $text =~ s/\[\[/{/g;
1696   $text =~ s/\]\]/}/g;
1697   $text;
1698 }
1699
1700 # Process "MODULE = Foo ..." lines and update global state accordingly
1701 sub _process_module_xs_line {
1702   my ($self, $module, $pkg, $prefix) = @_;
1703
1704   ($self->{Module_cname} = $module) =~ s/\W/_/g;
1705
1706   $self->{Package} = defined($pkg) ? $pkg : '';
1707   $self->{Prefix}  = quotemeta( defined($prefix) ? $prefix : '' );
1708
1709   ($self->{Packid} = $self->{Package}) =~ tr/:/_/;
1710
1711   $self->{Packprefix} = $self->{Package};
1712   $self->{Packprefix} .= "::" if $self->{Packprefix} ne "";
1713
1714   $self->{lastline} = "";
1715 }
1716
1717 # Skip any embedded POD sections
1718 sub _maybe_skip_pod {
1719   my ($self) = @_;
1720
1721   while ($self->{lastline} =~ /^=/) {
1722     while ($self->{lastline} = readline($self->{FH})) {
1723       last if ($self->{lastline} =~ /^=cut\s*$/);
1724     }
1725     $self->death("Error: Unterminated pod") unless defined $self->{lastline};
1726     $self->{lastline} = readline($self->{FH});
1727     chomp $self->{lastline};
1728     $self->{lastline} =~ s/^\s+$//;
1729   }
1730 }
1731
1732 # This chunk of code strips out (and parses) embedded TYPEMAP blocks
1733 # which support a HEREdoc-alike block syntax.
1734 sub _maybe_parse_typemap_block {
1735   my ($self) = @_;
1736
1737   # This is special cased from the usual paragraph-handler logic
1738   # due to the HEREdoc-ish syntax.
1739   if ($self->{lastline} =~ /^TYPEMAP\s*:\s*<<\s*(?:(["'])(.+?)\1|([^\s'"]+?))\s*;?\s*$/)
1740   {
1741     my $end_marker = quotemeta(defined($1) ? $2 : $3);
1742
1743     # Scan until we find $end_marker alone on a line.
1744     my @tmaplines;
1745     while (1) {
1746       $self->{lastline} = readline($self->{FH});
1747       $self->death("Error: Unterminated TYPEMAP section") if not defined $self->{lastline};
1748       last if $self->{lastline} =~ /^$end_marker\s*$/;
1749       push @tmaplines, $self->{lastline};
1750     }
1751
1752     my $tmap = ExtUtils::Typemaps->new(
1753       string        => join("", @tmaplines),
1754       lineno_offset => 1 + ($self->current_line_number() || 0),
1755       fake_filename => $self->{filename},
1756     );
1757     $self->{typemap}->merge(typemap => $tmap, replace => 1);
1758
1759     $self->{lastline} = "";
1760   }
1761 }
1762
1763 # Read next xsub into @{ $self->{line} } from ($lastline, readline($self->{FH})).
1764 sub fetch_para {
1765   my $self = shift;
1766
1767   # parse paragraph
1768   $self->death("Error: Unterminated '#if/#ifdef/#ifndef'")
1769     if !defined $self->{lastline} && $self->{XSStack}->[-1]{type} eq 'if';
1770   @{ $self->{line} } = ();
1771   @{ $self->{line_no} } = ();
1772   return $self->PopFile() if not defined $self->{lastline}; # EOF
1773
1774   if ($self->{lastline} =~
1775       /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/)
1776   {
1777     $self->_process_module_xs_line($1, $2, $3);
1778   }
1779
1780   for (;;) {
1781     $self->_maybe_skip_pod;
1782
1783     $self->_maybe_parse_typemap_block;
1784
1785     if ($self->{lastline} !~ /^\s*#/ # not a CPP directive
1786         # CPP directives:
1787         #    ANSI:    if ifdef ifndef elif else endif define undef
1788         #        line error pragma
1789         #    gcc:    warning include_next
1790         #   obj-c:    import
1791         #   others:    ident (gcc notes that some cpps have this one)
1792         || $self->{lastline} =~ /^\#[ \t]*
1793                                   (?:
1794                                         (?:if|ifn?def|elif|else|endif|
1795                                            define|undef|pragma|error|
1796                                            warning|line\s+\d+|ident)
1797                                         \b
1798                                       | (?:include(?:_next)?|import)
1799                                         \s* ["<] .* [>"]
1800                                  )
1801                                 /x
1802     )
1803     {
1804       last if $self->{lastline} =~ /^\S/ && @{ $self->{line} } && $self->{line}->[-1] eq "";
1805       push(@{ $self->{line} }, $self->{lastline});
1806       push(@{ $self->{line_no} }, $self->{lastline_no});
1807     }
1808
1809     # Read next line and continuation lines
1810     last unless defined($self->{lastline} = readline($self->{FH}));
1811     $self->{lastline_no} = $.;
1812     my $tmp_line;
1813     $self->{lastline} .= $tmp_line
1814       while ($self->{lastline} =~ /\\$/ && defined($tmp_line = readline($self->{FH})));
1815
1816     chomp $self->{lastline};
1817     $self->{lastline} =~ s/^\s+$//;
1818   }
1819
1820   # Nuke trailing "line" entries until there's one that's not empty
1821   pop(@{ $self->{line} }), pop(@{ $self->{line_no} })
1822     while @{ $self->{line} } && $self->{line}->[-1] eq "";
1823
1824   return 1;
1825 }
1826
1827 sub output_init {
1828   my $self = shift;
1829   my $argsref = shift;
1830
1831   my ($type, $num, $var, $init, $printed_name)
1832     = @{$argsref}{qw(type num var init printed_name)};
1833
1834   # local assign for efficiently passing in to eval_input_typemap_code
1835   local $argsref->{arg} = $num
1836                           ? "ST(" . ($num-1) . ")"
1837                           : "/* not a parameter */";
1838
1839   if ( $init =~ /^=/ ) {
1840     if ($printed_name) {
1841       $self->eval_input_typemap_code(qq/print " $init\\n"/, $argsref);
1842     }
1843     else {
1844       $self->eval_input_typemap_code(qq/print "\\t$var $init\\n"/, $argsref);
1845     }
1846   }
1847   else {
1848     if (  $init =~ s/^\+//  &&  $num  ) {
1849       $self->generate_init( {
1850         type          => $type,
1851         num           => $num,
1852         var           => $var,
1853         printed_name  => $printed_name,
1854       } );
1855     }
1856     elsif ($printed_name) {
1857       print ";\n";
1858       $init =~ s/^;//;
1859     }
1860     else {
1861       $self->eval_input_typemap_code(qq/print "\\t$var;\\n"/, $argsref);
1862       $init =~ s/^;//;
1863     }
1864     $self->{deferred}
1865       .= $self->eval_input_typemap_code(qq/"\\n\\t$init\\n"/, $argsref);
1866   }
1867 }
1868
1869 sub generate_init {
1870   my $self = shift;
1871   my $argsref = shift;
1872
1873   my ($type, $num, $var, $printed_name)
1874     = @{$argsref}{qw(type num var printed_name)};
1875
1876   my $argoff = $num - 1;
1877   my $arg = "ST($argoff)";
1878
1879   my $typemaps = $self->{typemap};
1880
1881   $type = ExtUtils::Typemaps::tidy_type($type);
1882   if (not $typemaps->get_typemap(ctype => $type)) {
1883     $self->report_typemap_failure($typemaps, $type);
1884     return;
1885   }
1886
1887   (my $ntype = $type) =~ s/\s*\*/Ptr/g;
1888   (my $subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
1889
1890   my $typem = $typemaps->get_typemap(ctype => $type);
1891   my $xstype = $typem->xstype;
1892   #this is an optimization from perl 5.0 alpha 6, class check is skipped
1893   #T_REF_IV_REF is missing since it has no untyped analog at the moment
1894   $xstype =~ s/OBJ$/REF/ || $xstype =~ s/^T_REF_IV_PTR$/T_PTRREF/
1895     if $self->{func_name} =~ /DESTROY$/;
1896   if ($xstype eq 'T_PV' and exists $self->{lengthof}->{$var}) {
1897     print "\t$var" unless $printed_name;
1898     print " = ($type)SvPV($arg, STRLEN_length_of_$var);\n";
1899     die "default value not supported with length(NAME) supplied"
1900       if defined $self->{defaults}->{$var};
1901     return;
1902   }
1903   $type =~ tr/:/_/ unless $self->{RetainCplusplusHierarchicalTypes};
1904
1905   my $inputmap = $typemaps->get_inputmap(xstype => $xstype);
1906   if (not defined $inputmap) {
1907     $self->blurt("Error: No INPUT definition for type '$type', typekind '" . $type->xstype . "' found");
1908     return;
1909   }
1910
1911   my $expr = $inputmap->cleaned_code;
1912   # Note: This gruesome bit either needs heavy rethinking or documentation. I vote for the former. --Steffen
1913   if ($expr =~ /DO_ARRAY_ELEM/) {
1914     my $subtypemap  = $typemaps->get_typemap(ctype => $subtype);
1915     if (not $subtypemap) {
1916       $self->report_typemap_failure($typemaps, $subtype);
1917       return;
1918     }
1919
1920     my $subinputmap = $typemaps->get_inputmap(xstype => $subtypemap->xstype);
1921     if (not $subinputmap) {
1922       $self->blurt("Error: No INPUT definition for type '$subtype', typekind '" . $subtypemap->xstype . "' found");
1923       return;
1924     }
1925
1926     my $subexpr = $subinputmap->cleaned_code;
1927     $subexpr =~ s/\$type/\$subtype/g;
1928     $subexpr =~ s/ntype/subtype/g;
1929     $subexpr =~ s/\$arg/ST(ix_$var)/g;
1930     $subexpr =~ s/\n\t/\n\t\t/g;
1931     $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
1932     $subexpr =~ s/\$var/${var}\[ix_$var - $argoff]/;
1933     $expr =~ s/DO_ARRAY_ELEM/$subexpr/;
1934   }
1935   if ($expr =~ m#/\*.*scope.*\*/#i) {  # "scope" in C comments
1936     $self->{ScopeThisXSUB} = 1;
1937   }
1938
1939   my $eval_vars = {
1940     var           => $var,
1941     printed_name  => $printed_name,
1942     type          => $type,
1943     ntype         => $ntype,
1944     subtype       => $subtype,
1945     num           => $num,
1946     arg           => $arg,
1947     argoff        => $argoff,
1948   };
1949
1950   if (defined($self->{defaults}->{$var})) {
1951     $expr =~ s/(\t+)/$1    /g;
1952     $expr =~ s/        /\t/g;
1953     if ($printed_name) {
1954       print ";\n";
1955     }
1956     else {
1957       $self->eval_input_typemap_code(qq/print "\\t$var;\\n"/, $eval_vars);
1958     }
1959     if ($self->{defaults}->{$var} eq 'NO_INIT') {
1960       $self->{deferred} .= $self->eval_input_typemap_code(
1961         qq/"\\n\\tif (items >= $num) {\\n$expr;\\n\\t}\\n"/,
1962         $eval_vars
1963       );
1964     }
1965     else {
1966       $self->{deferred} .= $self->eval_input_typemap_code(
1967         qq/"\\n\\tif (items < $num)\\n\\t    $var = $self->{defaults}->{$var};\\n\\telse {\\n$expr;\\n\\t}\\n"/,
1968         $eval_vars
1969       );
1970     }
1971   }
1972   elsif ($self->{ScopeThisXSUB} or $expr !~ /^\s*\$var =/) {
1973     if ($printed_name) {
1974       print ";\n";
1975     }
1976     else {
1977       $self->eval_input_typemap_code(qq/print "\\t$var;\\n"/, $eval_vars);
1978     }
1979     $self->{deferred}
1980       .= $self->eval_input_typemap_code(qq/"\\n$expr;\\n"/, $eval_vars);
1981   }
1982   else {
1983     die "panic: do not know how to handle this branch for function pointers"
1984       if $printed_name;
1985     $self->eval_input_typemap_code(qq/print "$expr;\\n"/, $eval_vars);
1986   }
1987 }
1988
1989 sub generate_output {
1990   my $self = shift;
1991   my $argsref = shift;
1992   my ($type, $num, $var, $do_setmagic, $do_push)
1993     = @{$argsref}{qw(type num var do_setmagic do_push)};
1994
1995   my $arg = "ST(" . ($num - ($num != 0)) . ")";
1996
1997   my $typemaps = $self->{typemap};
1998
1999   $type = ExtUtils::Typemaps::tidy_type($type);
2000   local $argsref->{type} = $type;
2001
2002   if ($type =~ /^array\(([^,]*),(.*)\)/) {
2003     print "\t$arg = sv_newmortal();\n";
2004     print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1));\n";
2005     print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
2006   }
2007   else {
2008     my $typemap = $typemaps->get_typemap(ctype => $type);
2009     if (not $typemap) {
2010       $self->report_typemap_failure($typemaps, $type);
2011       return;
2012     }
2013
2014     my $outputmap = $typemaps->get_outputmap(xstype => $typemap->xstype);
2015     if (not $outputmap) {
2016       $self->blurt("Error: No OUTPUT definition for type '$type', typekind '" . $typemap->xstype . "' found");
2017       return;
2018     }
2019
2020     (my $ntype = $type) =~ s/\s*\*/Ptr/g;
2021     $ntype =~ s/\(\)//g;
2022     (my $subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
2023
2024     my $eval_vars = {%$argsref, subtype => $subtype, ntype => $ntype, arg => $arg};
2025     my $expr = $outputmap->cleaned_code;
2026     if ($expr =~ /DO_ARRAY_ELEM/) {
2027       my $subtypemap = $typemaps->get_typemap(ctype => $subtype);
2028       if (not $subtypemap) {
2029         $self->report_typemap_failure($typemaps, $subtype);
2030         return;
2031       }
2032
2033       my $suboutputmap = $typemaps->get_outputmap(xstype => $subtypemap->xstype);
2034       if (not $suboutputmap) {
2035         $self->blurt("Error: No OUTPUT definition for type '$subtype', typekind '" . $subtypemap->xstype . "' found");
2036         return;
2037       }
2038
2039       my $subexpr = $suboutputmap->cleaned_code;
2040       $subexpr =~ s/ntype/subtype/g;
2041       $subexpr =~ s/\$arg/ST(ix_$var)/g;
2042       $subexpr =~ s/\$var/${var}\[ix_$var]/g;
2043       $subexpr =~ s/\n\t/\n\t\t/g;
2044       $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
2045       $self->eval_output_typemap_code("print qq\a$expr\a", $eval_vars);
2046       print "\t\tSvSETMAGIC(ST(ix_$var));\n" if $do_setmagic;
2047     }
2048     elsif ($var eq 'RETVAL') {
2049       my $orig_arg = $arg;
2050       my $indent;
2051       my $use_RETVALSV = 1;
2052       my $do_mortal = 0;
2053       my $do_copy_tmp = 1;
2054       my $pre_expr;
2055       local $eval_vars->{arg} = $arg = 'RETVALSV';
2056       my $evalexpr = $self->eval_output_typemap_code("qq\a$expr\a", $eval_vars);
2057
2058       if ($expr =~ /^\t\Q$arg\E = new/) {
2059         # We expect that $arg has refcnt 1, so we need to
2060         # mortalize it.
2061         $do_mortal = 1;
2062       }
2063       # If RETVAL is immortal, don't mortalize it. This code is not perfect:
2064       # It won't detect a func or expression that only returns immortals, for
2065       # example, this RE must be tried before next elsif.
2066       elsif ($evalexpr =~ /^\t\Q$arg\E\s*=\s*(boolSV\(|(&PL_sv_yes|&PL_sv_no|&PL_sv_undef)\s*;)/) {
2067         $do_copy_tmp = 0; #$arg will be a ST(X), no SV* RETVAL, no RETVALSV
2068         $use_RETVALSV = 0;
2069       }
2070       elsif ($evalexpr =~ /^\s*\Q$arg\E\s*=/) {
2071         # We expect that $arg has refcnt >=1, so we need
2072         # to mortalize it!
2073         $use_RETVALSV = 0 if $ntype eq "SVPtr";#reuse SV* RETVAL vs open new block
2074         $do_mortal = 1;
2075       }
2076       else {
2077         # Just hope that the entry would safely write it
2078         # over an already mortalized value. By
2079         # coincidence, something like $arg = &PL_sv_undef
2080         # works too, but should be caught above.
2081         $pre_expr = "RETVALSV = sv_newmortal();\n";
2082         # new mortals don't have set magic
2083         $do_setmagic = 0;
2084       }
2085       if($use_RETVALSV) {
2086         print "\t{\n\t    SV * RETVALSV;\n";
2087         $indent = "\t    ";
2088       } else {
2089         $indent = "\t";
2090       }
2091       print $indent.$pre_expr if $pre_expr;
2092
2093       if($use_RETVALSV) {
2094         #take control of 1 layer of indent, may or may not indent more
2095         $evalexpr =~ s/^(\t|        )/$indent/gm;
2096         #"\t    \t" doesn't draw right in some IDEs
2097         #break down all \t into spaces
2098         $evalexpr =~ s/\t/        /g;
2099         #rebuild back into \t'es, \t==8 spaces, indent==4 spaces
2100         $evalexpr =~ s/        /\t/g;
2101       }
2102       else {
2103         if($do_mortal || $do_setmagic) {
2104         #typemap entry evaled with RETVALSV, if we aren't using RETVALSV replace
2105           $evalexpr =~ s/RETVALSV/RETVAL/g; #all uses with RETVAL for prettier code
2106         }
2107         else { #if no extra boilerplate (no mortal, no set magic) is needed
2108             #after $evalexport, get rid of RETVALSV's visual cluter and change
2109           $evalexpr =~ s/RETVALSV/$orig_arg/g;#the lvalue to ST(X)
2110         }
2111       }
2112       #stop "   RETVAL = RETVAL;" for SVPtr type
2113       print $evalexpr if $evalexpr !~ /^\s*RETVAL = RETVAL;$/;
2114       print $indent.'RETVAL'.($use_RETVALSV ? 'SV':'')
2115             .' = sv_2mortal(RETVAL'.($use_RETVALSV ? 'SV':'').");\n" if $do_mortal;
2116       print $indent.'SvSETMAGIC(RETVAL'.($use_RETVALSV ? 'SV':'').");\n" if $do_setmagic;
2117       #dont do "RETVALSV = boolSV(RETVAL); ST(0) = RETVALSV;", it is visual clutter
2118       print $indent."$orig_arg = RETVAL".($use_RETVALSV ? 'SV':'').";\n"
2119         if $do_mortal || $do_setmagic || $do_copy_tmp;
2120       print "\t}\n" if $use_RETVALSV;
2121     }
2122     elsif ($do_push) {
2123       print "\tPUSHs(sv_newmortal());\n";
2124       local $eval_vars->{arg} = "ST($num)";
2125       $self->eval_output_typemap_code("print qq\a$expr\a", $eval_vars);
2126       print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
2127     }
2128     elsif ($arg =~ /^ST\(\d+\)$/) {
2129       $self->eval_output_typemap_code("print qq\a$expr\a", $eval_vars);
2130       print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
2131     }
2132   }
2133 }
2134
2135
2136 # Just delegates to a clean package.
2137 # Shim to evaluate Perl code in the right variable context
2138 # for typemap code (having things such as $ALIAS set up).
2139 sub eval_output_typemap_code {
2140   my ($self, $code, $other) = @_;
2141   return ExtUtils::ParseXS::Eval::eval_output_typemap_code($self, $code, $other);
2142 }
2143
2144 sub eval_input_typemap_code {
2145   my ($self, $code, $other) = @_;
2146   return ExtUtils::ParseXS::Eval::eval_input_typemap_code($self, $code, $other);
2147 }
2148
2149 1;
2150
2151 # vim: ts=2 sw=2 et: