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