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