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