File Coverage

blib/lib/XS/Install/FrozenShit/ParseXS.pm
Criterion Covered Total %
statement 429 814 52.7
branch 125 396 31.5
condition 38 140 27.1
subroutine 27 51 52.9
pod 0 36 0.0
total 619 1437 43.0


line stmt bran cond sub pod time code
1             package
2             XS::Install::FrozenShit::ParseXS;
3 1     1   4 use strict;
  1         2  
  1         27  
4 1     1   3 use warnings;
  1         1  
  1         45  
5              
6             # Note that the pod for this module is separate in ParseXS.pod.
7             #
8             # This module provides the guts for the xsubpp XS-to-C translator utility.
9             # By having it as a module separate from xsubpp, it makes it more efficient
10             # to be used for example by Module::Build without having to shell out to
11             # xsubpp. It also makes it easier to test the individual components.
12             #
13             # The bulk of this file is taken up with the process_file() method which
14             # does the whole job of reading in a .xs file and outputting a .c file.
15             # It in turn relies on fetch_para() to read chunks of lines from the
16             # input, and on a bunch of FOO_handler() methods which process each of the
17             # main XS FOO keywords when encountered.
18             #
19             # The remainder of this file mainly consists of helper functions for the
20             # handlers, and functions to help with outputting stuff.
21             #
22             # Of particular note is the Q() function, which is typically used to
23             # process escaped ("quoted") heredoc text of C code fragments to be
24             # output. It strips an initial '|' preceded by optional spaces, and
25             # converts [[ and ]] to { and }. This allows unmatched braces to be
26             # included in the C fragments without confusing text editors.
27             #
28             # Some other tasks have been moved out to various .pm files under ParseXS:
29             #
30             # ParseXS::CountLines provides tied handle methods for automatically
31             # injecting '#line' directives into output.
32             #
33             # ParseXS::Eval provides methods for evalling typemaps within
34             # an environment where suitable vars like $var and
35             # $arg have been up, but with nothing else in scope.
36             #
37             # ParseXS::Node This and its subclasses provide the nodes
38             # which make up the Abstract Syntax Tree (AST)
39             # generated by the parser. XXX as of Sep 2024, this
40             # is very much a Work In Progress.
41             #
42             # ParseXS::Constants defines a few constants used here, such the regex
43             # patterns used to detect a new XS keyword.
44             #
45             # ParseXS::Utilities provides various private utility methods for
46             # the use of ParseXS, such as analysing C
47             # pre-processor directives.
48             #
49             # Note: when making changes to this module (or to its children), you
50             # can make use of the author/mksnapshot.pl tool to capture before and
51             # after snapshots of all .c files generated from .xs files (e.g. all the
52             # ones generated when building the perl distribution), to make sure that
53             # the only the changes to have appeared are ones which you expected.
54              
55             # 5.8.0 is required for "use fields"
56             # 5.8.3 is required for "use Exporter 'import'"
57 1     1   12 use 5.008003;
  1         3  
58              
59 1     1   3 use Cwd;
  1         1  
  1         46  
60 1     1   4 use Config;
  1         1  
  1         30  
61 1     1   3 use Exporter 'import';
  1         1  
  1         18  
62 1     1   3 use File::Basename;
  1         1  
  1         39  
63 1     1   2 use File::Spec;
  1         2  
  1         11  
64 1     1   3 use Symbol;
  1         1  
  1         133  
65              
66             our $VERSION;
67             BEGIN {
68 1     1   2 $VERSION = '3.57';
69 1         541 require XS::Install::FrozenShit::ParseXS::Constants; XS::Install::FrozenShit::ParseXS::Constants->VERSION($VERSION);
  1         21  
70 1         452 require XS::Install::FrozenShit::ParseXS::CountLines; XS::Install::FrozenShit::ParseXS::CountLines->VERSION($VERSION);
  1         13  
71 1         742 require XS::Install::FrozenShit::ParseXS::Node; XS::Install::FrozenShit::ParseXS::Node->VERSION($VERSION);
  1         13  
72 1         600 require XS::Install::FrozenShit::ParseXS::Utilities; XS::Install::FrozenShit::ParseXS::Utilities->VERSION($VERSION);
  1         25  
73 1         489 require XS::Install::FrozenShit::ParseXS::Eval; XS::Install::FrozenShit::ParseXS::Eval->VERSION($VERSION);
  1         114  
74             }
75             $VERSION = eval $VERSION if $VERSION =~ /_/;
76              
77 1         457 use XS::Install::FrozenShit::ParseXS::Utilities qw(
78             standard_typemap_locations
79             trim_whitespace
80             C_string
81             valid_proto_string
82             process_typemaps
83             map_type
84             standard_XS_defs
85             analyze_preprocessor_statement
86             set_cond
87             Warn
88             WarnHint
89             current_line_number
90             blurt
91             death
92             check_conditional_preprocessor_statements
93             escape_file_for_line_directive
94             report_typemap_failure
95 1     1   5 );
  1         1  
96              
97             our @EXPORT_OK = qw(
98             process_file
99             report_error_count
100             errors
101             );
102              
103             ##############################
104             # A number of "constants"
105             our $DIE_ON_ERROR;
106              
107             our $AUTHOR_WARNINGS;
108             $AUTHOR_WARNINGS = ($ENV{AUTHOR_WARNINGS} || 0)
109             unless defined $AUTHOR_WARNINGS;
110              
111             # "impossible" keyword (multiple newline)
112             my $END = "!End!\n\n";
113             # Match an XS Keyword
114             my $BLOCK_regexp = '\s*(' . $XS::Install::FrozenShit::ParseXS::Constants::XSKeywordsAlternation . "|$END)\\s*:";
115              
116              
117             # All the valid fields of an XS::Install::FrozenShit::ParseXS hash object. The 'use
118             # fields' enables compile-time or run-time errors if code attempts to
119             # use a key which isn't listed here.
120              
121             my $USING_FIELDS;
122              
123             BEGIN {
124 1     1   28 my @fields = (
125              
126             # I/O:
127              
128             'dir', # The directory component of the main input file:
129             # we will normally chdir() to this directory.
130              
131             'in_pathname', # The full pathname of the current input file.
132             'in_filename', # The filename of the current input file.
133             'in_fh', # The filehandle of the current input file.
134              
135             'IncludedFiles', # Bool hash of INCLUDEd filenames (plus main file).
136              
137             'line', # Array of lines recently read in and being processed.
138             # Typically one XSUB's worth of lines.
139             'line_no', # Array of line nums corresponding to @{$self->{line}}.
140              
141             'lastline', # The contents of the line most recently read in
142             # but not yet processed.
143             'lastline_no', # The line number of lastline.
144              
145              
146             # File-scoped configuration state:
147              
148             'config_RetainCplusplusHierarchicalTypes', # Bool: "-hiertype" switch
149             # value: it stops the typemap code doing
150             # $type =~ tr/:/_/.
151              
152             'config_WantLineNumbers', # Bool: (default true): "-nolinenumbers"
153             # switch not present: causes '#line NNN' lines to
154             # be emitted.
155              
156             'config_die_on_error',# Bool: make death() call die() rather than exit().
157             # It is set initially from the die_on_error option
158             # or from the $XS::Install::FrozenShit::ParseXS::DIE_ON_ERROR global.
159              
160             'config_author_warnings', # Bool: enables some warnings only useful to
161             # ParseXS.pm's authors rather than module creators.
162             # Set from Options or $AUTHOR_WARNINGS env var.
163              
164             'config_strip_c_func_prefix', # The discouraged -strip=... switch.
165              
166             'config_allow_argtypes', # Bool: (default true): "-noargtypes" switch not
167             # present. Enables ANSI-like arg types to be
168             # included in the XSUB signature.
169              
170             'config_allow_inout', # Bool: (default true): "-noinout" switch not present.
171             # Enables processing of IN/OUT/etc arg modifiers.
172              
173             'config_allow_exceptions', # Bool: (default false): the '-except' switch
174             # present.
175              
176             'config_optimize', # Bool: (default true): "-nooptimize" switch not
177             # present. Enables optimizations (currently just
178             # the TARG one).
179              
180              
181             # File-scoped parsing state:
182              
183             'typemaps_object', # An XS::Install::FrozenShit::Typemaps object: the result of
184             # reading in the standard (or other) typemap.
185              
186             'error_count', # Num: count of number of errors seen so far.
187              
188             'XS_parse_stack', # Array of hashes: nested INCLUDE and #if states.
189              
190             'XS_parse_stack_top_if_idx', # Index of the current top-most '#if' on the
191             # XS_parse_stack. Note that it's not necessarily
192             # the top element of the stack, since that also
193             # includes elements for each INCLUDE etc.
194              
195             'MODULE_cname', # MODULE canonical name (i.e. after s/\W/_/g).
196             'PACKAGE_name', # PACKAGE name.
197             'PACKAGE_C_name', # Ditto, but with tr/:/_/.
198             'PACKAGE_class', # Ditto, but with '::' appended.
199             'PREFIX_pattern', # PREFIX value, but after quotemeta().
200              
201             'map_overloaded_package_to_C_package', # Hash: for every PACKAGE which
202             # has at least one overloaded XSUB, add a
203             # (package name => package C name) entry.
204              
205             'map_package_to_fallback_string', # Hash: for every package, maps it to
206             # the overload fallback state for that package (if
207             # specified). Each value is one of the strings
208             # "&PL_sv_yes", "&PL_sv_no", "&PL_sv_undef".
209              
210             'proto_behaviour_specified', # Bool: prototype behaviour has been
211             # specified by the -prototypes switch and/or
212             # PROTOTYPE(S) keywords, so no need to warn.
213              
214             'PROTOTYPES_value', # Bool: most recent PROTOTYPES: value. Defaults to
215             # the value of the "-prototypes" switch.
216              
217             'VERSIONCHECK_value', # Bool: most recent VERSIONCHECK: value. Defaults
218             # to the value of the "-noversioncheck" switch.
219              
220             'seen_INTERFACE_or_MACRO', # Bool: at least one INTERFACE/INTERFACE_MACRO
221             # has been seen somewhere.
222              
223              
224             # File-scoped code-emitting state:
225              
226             'bootcode_early', # Array of code lines to emit early in boot XSUB:
227             # typically newXS() calls
228              
229             'bootcode_later', # Array of code lines to emit later on in boot XSUB:
230             # typically lines from a BOOT: XS file section
231              
232              
233             # Per-XSUB parsing state:
234              
235             'xsub_seen_NO_OUTPUT', # Bool: XSUB declared as NO_OUTPUT
236              
237             'xsub_seen_extern_C', # Bool: XSUB return type is 'extern "C" ...'
238              
239             'xsub_seen_static', # Bool: XSUB return type is 'static ...'
240              
241             'xsub_seen_PPCODE', # Bool: XSUB has PPCODE (peek-ahead)
242              
243             'xsub_seen_CODE', # Bool: XSUB has CODE (peek-ahead)
244              
245             'xsub_seen_INTERFACE', # Bool: XSUB has INTERFACE (peek-ahead)
246              
247             'xsub_seen_PROTOTYPE', # Bool: PROTOTYPE keyword seen (for dup warning)
248            
249             'xsub_seen_SCOPE', # Bool: SCOPE keyword seen (for dup warning).
250            
251             'xsub_seen_ALIAS', # Bool: ALIAS keyword seen in this XSUB.
252              
253             'xsub_seen_INTERFACE_or_MACRO',# Bool: INTERFACE or INTERFACE_MACRO
254             # seen in this XSUB.
255            
256             'xsub_interface_macro', # Str: current interface extraction macro.
257            
258             'xsub_interface_macro_set', # Str: current interface setting macro.
259            
260             'xsub_prototype', # Str: is set to either the global PROTOTYPES
261             # values (0 or 1), or to what's been
262             # overridden for this XSUB with PROTOTYPE
263             # "0": DISABLE
264             # "1": ENABLE
265             # "2": empty prototype
266             # other: a specific prototype.
267              
268             'xsub_SCOPE_enabled', # Bool: SCOPE ENABLEd
269              
270             'xsub_return_type', # Return type of the XSUB (whitespace-tidied).
271              
272             'xsub_class', # Str: the class part of the XSUB's
273             # function name (if any). May include
274             # 'const' prefix.
275              
276             'xsub_sig', # Node::Sig object holding all the info
277             # about the XSUB's signature and INPUT
278             # lines
279              
280             'xsub_func_name', # The name of this XSUB eg 'f'
281             'xsub_func_full_perl_name', # its full Perl function name eg. 'Foo::Bar::f'
282             'xsub_func_full_C_name', # its full C function name eg 'Foo__Bar__f'
283              
284             'xsub_CASE_condition', # Most recent CASE string.
285              
286             'xsub_CASE_condition_count', # number of CASE keywords encountered.
287             # Zero indicates none encountered yet.
288              
289             'xsub_map_overload_name_to_seen', # Hash: maps each overload method name
290             # (such as '<=>') to a boolean indicating
291             # whether that method has been listed by
292             # OVERLOAD (for duplicate spotting).
293            
294             'xsub_map_interface_name_short_to_original', # Hash: for each INTERFACE
295             # name, map the short (PREFIX removed) name
296             # to the original name.
297              
298             'xsub_attributes', # Array of strings: all ATTRIBUTE keywords
299             # (possibly multiple space-separated
300             # keywords per string).
301              
302             'xsub_seen_RETVAL_in_CODE', # Have seen 'RETVAL' within a CODE block.
303              
304             'xsub_map_alias_name_to_value', # Hash: maps ALIAS name to value.
305              
306             'xsub_map_alias_value_to_name_seen_hash', # Hash of hash of bools:
307             # indicates which alias names have been
308             # used for each value.
309              
310             'xsub_alias_clash_hinted', # Bool: an ALIAS warning-hint has been emitted.
311              
312              
313             # Per-XSUB OUTPUT section parsing state:
314              
315             'xsub_SETMAGIC_state', # Bool: most recent value of SETMAGIC in an
316             # OUTPUT section.
317              
318             # Per-XSUB code-emitting state:
319              
320             'xsub_deferred_code_lines', # A multi-line string containing lines of
321             # code to be emitted *after* all INPUT and
322             # PREINIT keywords have been processed.
323              
324             'xsub_stack_was_reset', # An XSprePUSH was emitted, so return values
325             # should be PUSHed rather than just set.
326              
327             'xsub_targ_declared_early', # A wide-scoped dXSTARG was emitted early
328             'xsub_targ_used', # The TARG has already been used
329              
330             );
331              
332             # do 'use fields', except: fields needs Hash::Util which is XS, which
333             # needs us. So only 'use fields' on systems where Hash::Util has already
334             # been built.
335 1 50       88 if (eval 'require Hash::Util; 1;') {
336 1         2 require fields;
337 1         2 $USING_FIELDS = 1;
338 1         5 fields->import(@fields);
339             }
340             }
341              
342              
343             sub new {
344             my XS::Install::FrozenShit::ParseXS $self = shift;
345             unless (ref $self) {
346             if ($USING_FIELDS) {
347             $self = fields::new($self);
348             }
349             else {
350             $self = bless {} => $self;
351             }
352             }
353             return $self;
354             }
355              
356             our $Singleton = __PACKAGE__->new;
357              
358              
359             # The big method which does all the input parsing and output generation
360              
361             sub process_file {
362 1     1 0 8 my XS::Install::FrozenShit::ParseXS $self;
363             # Allow for $package->process_file(%hash), $obj->process_file, and process_file()
364 1 50       6 if (@_ % 2) {
365 1         3 my $invocant = shift;
366 1 50       4 $self = ref($invocant) ? $invocant : $invocant->new;
367             }
368             else {
369 0         0 $self = $Singleton;
370             }
371              
372 1         3 my %Options;
373              
374             {
375 1         2 my %opts = @_;
  1         27  
376 1         4 $self->{proto_behaviour_specified} = exists $opts{prototypes};
377              
378             # Set defaults.
379 1         9 %Options = (
380             argtypes => 1,
381             csuffix => '.c',
382             except => 0,
383             hiertype => 0,
384             inout => 1,
385             linenumbers => 1,
386             optimize => 1,
387             output => \*STDOUT,
388             prototypes => 0,
389             typemap => [],
390             versioncheck => 1,
391             in_fh => Symbol::gensym(),
392             die_on_error => $DIE_ON_ERROR, # if true we die() and not exit()
393             # after errors
394             author_warnings => $AUTHOR_WARNINGS,
395             %opts,
396             );
397             }
398              
399             # Global Constants
400              
401 1         140 my ($Is_VMS, $VMS_SymSet);
402              
403 1 50       12 if ($^O eq 'VMS') {
404 0         0 $Is_VMS = 1;
405             # Establish set of global symbols with max length 28, since xsubpp
406             # will later add the 'XS_' prefix.
407 0         0 require ExtUtils::XSSymSet;
408 0         0 $VMS_SymSet = ExtUtils::XSSymSet->new(28);
409             }
410              
411             # XS_parse_stack is an array of hashes. Each hash records the current
412             # state when a new file is INCLUDEd, or when within a (possibly nested)
413             # file-scoped #if / #ifdef.
414             # The 'type' field of each hash is either 'file' for INCLUDE, or 'if'
415             # for within an #if / #endif.
416 1         5 @{ $self->{XS_parse_stack} } = ({type => 'none'});
  1         5  
417              
418 1         4 $self->{bootcode_early} = [];
419 1         3 $self->{bootcode_later} = [];
420              
421             # hash of package name => package C name
422 1         3 $self->{map_overloaded_package_to_C_package} = {};
423             # hashref of package name => fallback setting
424 1         3 $self->{map_package_to_fallback_string} = {};
425 1         4 $self->{error_count} = 0; # count
426              
427             # Most of the 1500 lines below uses these globals. We'll have to
428             # clean this up sometime, probably. For now, we just pull them out
429             # of %Options. -Ken
430              
431 1         3 $self->{config_RetainCplusplusHierarchicalTypes} = $Options{hiertype};
432 1         4 $self->{PROTOTYPES_value} = $Options{prototypes};
433 1         3 $self->{VERSIONCHECK_value} = $Options{versioncheck};
434 1         3 $self->{config_WantLineNumbers} = $Options{linenumbers};
435 1         3 $self->{IncludedFiles} = {};
436              
437 1         4 $self->{config_die_on_error} = $Options{die_on_error};
438 1         3 $self->{config_author_warnings} = $Options{author_warnings};
439              
440 1 50       4 die "Missing required parameter 'filename'" unless $Options{filename};
441              
442              
443             # allow a string ref to be passed as an in-place filehandle
444 1 50       5 if (ref $Options{filename}) {
445 0         0 my $f = '(input)';
446 0         0 $self->{in_pathname} = $f;
447 0         0 $self->{in_filename} = $f;
448 0         0 $self->{dir} = '.';
449 0         0 $self->{IncludedFiles}->{$f}++;
450 0 0       0 $Options{outfile} = '(output)' unless $Options{outfile};
451             }
452             else {
453             ($self->{dir}, $self->{in_filename}) =
454 1         107 (dirname($Options{filename}), basename($Options{filename}));
455 1         5 $self->{in_pathname} = $Options{filename};
456 1         4 $self->{in_pathname} =~ s/\\/\\\\/g;
457 1         5 $self->{IncludedFiles}->{$Options{filename}}++;
458             }
459              
460             # Open the output file if given as a string. If they provide some
461             # other kind of reference, trust them that we can print to it.
462 1 50       5 if (not ref $Options{output}) {
463 0 0       0 open my($fh), "> $Options{output}" or die "Can't create $Options{output}: $!";
464 0         0 $Options{outfile} = $Options{output};
465 0         0 $Options{output} = $fh;
466             }
467              
468             # Really, we shouldn't have to chdir() or select() in the first
469             # place. For now, just save and restore.
470 1         7898 my $orig_cwd = cwd();
471 1         25 my $orig_fh = select();
472              
473 1         28 chdir($self->{dir});
474 1         5042 my $pwd = cwd();
475              
476 1 50       30 if ($self->{config_WantLineNumbers}) {
477 1         12 my $csuffix = $Options{csuffix};
478 1         6 my $cfile;
479 1 50       15 if ( $Options{outfile} ) {
480 0         0 $cfile = $Options{outfile};
481             }
482             else {
483 1         7 $cfile = $Options{filename};
484 1 50       29 $cfile =~ s/\.xs$/$csuffix/i or $cfile .= $csuffix;
485             }
486 1         52 tie(*PSEUDO_STDOUT, 'XS::Install::FrozenShit::ParseXS::CountLines', $cfile, $Options{output});
487 1         8 select PSEUDO_STDOUT;
488             }
489             else {
490 0         0 select $Options{output};
491             }
492              
493 1         20 $self->{typemaps_object} = process_typemaps( $Options{typemap}, $pwd );
494              
495 1         5 $self->{config_strip_c_func_prefix} = $Options{s};
496 1         5 $self->{config_allow_argtypes} = $Options{argtypes};
497 1         4 $self->{config_allow_inout} = $Options{inout};
498 1         5 $self->{config_allow_exceptions} = $Options{except};
499 1         4 $self->{config_optimize} = $Options{optimize};
500              
501             # Identify the version of xsubpp used
502 1         55 print <
503             /*
504             * This file was generated automatically by XS::Install::FrozenShit::ParseXS version $VERSION from the
505             * contents of $self->{in_filename}. Do not edit this file, edit $self->{in_filename} instead.
506             *
507             * ANY CHANGES MADE HERE WILL BE LOST!
508             *
509             */
510              
511             EOM
512              
513              
514             print("#line 1 \"" . escape_file_for_line_directive($self->{in_pathname}) . "\"\n")
515 1 50       24 if $self->{config_WantLineNumbers};
516              
517             # Open the input file (using $self->{in_filename} which
518             # is a basename'd $Options{filename} due to chdir above)
519             {
520 1         3 my $fn = $self->{in_filename};
  1         4  
521 1         3 my $opfn = $Options{filename};
522 1 50       5 $fn = $opfn if ref $opfn; # allow string ref as a source of file
523 1 50       76 open($self->{in_fh}, '<', $fn)
524             or die "cannot open $self->{in_filename}: $!\n";
525             }
526              
527             # ----------------------------------------------------------------
528             # Process the first (C language) half of the XS file, up until the first
529             # MODULE: line
530             # ----------------------------------------------------------------
531              
532             FIRSTMODULE:
533 1         49 while (readline($self->{in_fh})) {
534 223 50       559 if (/^=/) {
535 0         0 my $podstartline = $.;
536             do {
537 0 0       0 if (/^=cut\s*$/) {
538             # We can't just write out a /* */ comment, as our embedded
539             # POD might itself be in a comment. We can't put a /**/
540             # comment inside #if 0, as the C standard says that the source
541             # file is decomposed into preprocessing characters in the stage
542             # before preprocessing commands are executed.
543             # I don't want to leave the text as barewords, because the spec
544             # isn't clear whether macros are expanded before or after
545             # preprocessing commands are executed, and someone pathological
546             # may just have defined one of the 3 words as a macro that does
547             # something strange. Multiline strings are illegal in C, so
548             # the "" we write must be a string literal. And they aren't
549             # concatenated until 2 steps later, so we are safe.
550             # - Nicholas Clark
551 0         0 print("#if 0\n \"Skipped embedded POD.\"\n#endif\n");
552             printf("#line %d \"%s\"\n", $. + 1, escape_file_for_line_directive($self->{in_pathname}))
553 0 0       0 if $self->{config_WantLineNumbers};
554 0         0 next FIRSTMODULE;
555             }
556              
557 0         0 } while (readline($self->{in_fh}));
558              
559             # At this point $. is at end of file so die won't state the start
560             # of the problem, and as we haven't yet read any lines &death won't
561             # show the correct line in the message either.
562             die ("Error: Unterminated pod in $self->{in_filename}, line $podstartline\n")
563 0 0       0 unless $self->{lastline};
564             }
565              
566 223 100       648 last if ($self->{PACKAGE_name}, $self->{PREFIX_pattern}) =
567             /^MODULE\s*=\s*[\w:]+(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
568              
569 222         542 print $_;
570             }
571              
572 1 50       6 unless (defined $_) {
573 0         0 warn "Didn't find a 'MODULE ... PACKAGE ... PREFIX' line\n";
574 0         0 exit 0; # Not a fatal error for the caller process
575             }
576              
577             print 'XS::Install::FrozenShit::ParseXS::CountLines'->end_marker, "\n"
578 1 50       22 if $self->{config_WantLineNumbers};
579              
580 1         13 standard_XS_defs();
581              
582             print 'XS::Install::FrozenShit::ParseXS::CountLines'->end_marker, "\n"
583 1 50       9 if $self->{config_WantLineNumbers};
584              
585 1         5 $self->{lastline} = $_;
586 1         17 $self->{lastline_no} = $.;
587              
588 1         5 $self->{XS_parse_stack_top_if_idx} = 0;
589              
590 1         5 my $cpp_next_tmp_define = 'XSubPPtmpAAAA';
591              
592              
593             # ----------------------------------------------------------------
594             # Main loop: for each iteration, read in a paragraph's worth of XSUB
595             # definition or XS/CPP directives into @{ $self->{line} }, then (over
596             # the course of a thousand lines of code) try to interpret those lines.
597             # ----------------------------------------------------------------
598              
599             PARAGRAPH:
600 1         15 while ($self->fetch_para()) {
601             # Process and emit any initial C-preprocessor lines and blank
602             # lines. Also, keep track of #if/#else/#endif nesting, updating:
603             # $self->{XS_parse_stack}
604             # $self->{XS_parse_stack_top_if_idx}
605             # $self->{bootcode_early}
606             # $self->{bootcode_later}
607              
608 9   66     19 while (@{ $self->{line} } && $self->{line}->[0] !~ /^[^\#]/) {
  9         163  
609 0         0 my $ln = shift(@{ $self->{line} });
  0         0  
610 0         0 print $ln, "\n";
611 0 0       0 next unless $ln =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
612 0         0 my $statement = $+;
613             # update global tracking of #if/#else etc
614 0         0 $self->analyze_preprocessor_statement($statement);
615             }
616              
617 9 100       17 next PARAGRAPH unless @{ $self->{line} };
  9         33  
618              
619 7 50 33     25 if ( $self->{XS_parse_stack_top_if_idx}
620             && !$self->{XS_parse_stack}->[$self->{XS_parse_stack_top_if_idx}]{varname})
621             {
622             # We are inside an #if, but have not yet #defined its xsubpp variable.
623             #
624             # At the start of every '#if ...' which is external to an XSUB,
625             # we emit '#define XSubPPtmpXXXX 1', for increasing XXXX.
626             # Later, when emitting initialisation code in places like a boot
627             # block, it can then be made conditional via, e.g.
628             # #if XSubPPtmpXXXX
629             # newXS(...);
630             # #endif
631             # So that only the defined XSUBs get added to the symbol table.
632 0         0 print "#define $cpp_next_tmp_define 1\n\n";
633 0         0 push(@{ $self->{bootcode_early} }, "#if $cpp_next_tmp_define\n");
  0         0  
634 0         0 push(@{ $self->{bootcode_later} }, "#if $cpp_next_tmp_define\n");
  0         0  
635             $self->{XS_parse_stack}->[$self->{XS_parse_stack_top_if_idx}]{varname}
636 0         0 = $cpp_next_tmp_define++;
637             }
638              
639             # This will die on something like
640             #
641             # | CODE:
642             # | foo();
643             # |
644             # |#define X
645             # | bar();
646             #
647             # due to the define starting at column 1 and being preceded by a blank
648             # line: so the define and bar() aren't parsed as part of the CODE
649             # block.
650              
651             $self->death(
652             "Code is not inside a function"
653             ." (maybe last function was ended by a blank line "
654             ." followed by a statement on column one?)")
655 7 50       76 if $self->{line}->[0] =~ /^\s/;
656              
657             # Initialize some per-XSUB instance variables:
658              
659 7         70 $self->{xsub_seen_PROTOTYPE} = 0;
660 7         17 $self->{xsub_seen_SCOPE} = 0;
661 7         12 $self->{xsub_seen_INTERFACE_or_MACRO} = 0;
662 7         18 $self->{xsub_interface_macro} = 'XSINTERFACE_FUNC';
663 7         14 $self->{xsub_interface_macro_set} = 'XSINTERFACE_FUNC_SET';
664 7         20 $self->{xsub_prototype} = $self->{PROTOTYPES_value};
665 7         14 $self->{xsub_SCOPE_enabled} = 0;
666 7         22 $self->{xsub_map_overload_name_to_seen} = {};
667 7         15 $self->{xsub_seen_NO_OUTPUT} = 0;
668 7         13 $self->{xsub_seen_extern_C} = 0;
669 7         13 $self->{xsub_seen_static} = 0;
670 7         15 $self->{xsub_seen_PPCODE} = 0;
671 7         13 $self->{xsub_seen_CODE} = 0;
672 7         15 $self->{xsub_seen_INTERFACE} = 0;
673 7         15 $self->{xsub_class} = undef;
674 7         122 $self->{xsub_sig} = undef;
675              
676             # used for emitting XSRETURN($XSRETURN_count) if > 0, or XSRETURN_EMPTY
677 7         17 my $XSRETURN_count = 0;
678              
679              
680             # Process next line
681              
682 7         14 $_ = shift(@{ $self->{line} });
  7         74  
683              
684             # ----------------------------------------------------------------
685             # Process file-scoped keywords
686             # ----------------------------------------------------------------
687              
688             # Note that MODULE and TYPEMAP will already have been processed by
689             # fetch_para().
690             #
691             # This loop repeatedly: skips any blank lines and then calls
692             # $self->FOO_handler() if it finds any of the file-scoped keywords
693             # in the passed pattern. $_ is updated and is available to the
694             # handlers.
695             #
696             # Each of the handlers acts on just the current line, apart from the
697             # INCLUDE ones, which open a new file and skip any leading blank
698             # lines.
699              
700 7         35 while (my $kwd = $self->check_keyword("REQUIRE|PROTOTYPES|EXPORT_XSUB_SYMBOLS|FALLBACK|VERSIONCHECK|INCLUDE(?:_COMMAND)?|SCOPE")) {
701 2         8 my $method = $kwd . "_handler";
702 2         17 $self->$method($_);
703 2 50       4 next PARAGRAPH unless @{ $self->{line} };
  2         20  
704 0         0 $_ = shift(@{ $self->{line} });
  0         0  
705             }
706              
707 5 100       25 if ($self->check_keyword("BOOT")) {
708 1         8 $self->BOOT_handler();
709             # BOOT: is a file-scoped keyword which consumes all the lines
710             # following it in the current paragraph (as opposed to just until
711             # the next keyword, like CODE: etc).
712 1         8 next PARAGRAPH;
713             }
714              
715             # ----------------------------------------------------------------
716             # Process the presumed start of an XSUB
717             # ----------------------------------------------------------------
718              
719             # Whitespace-tidy the line containing the return type plus possibly
720             # the function name and arguments too (The latter was probably an
721             # unintended side-effect of later allowing the return type and
722             # function to be on the same line.)
723 4         43 ($self->{xsub_return_type}) = XS::Install::FrozenShit::Typemaps::tidy_type($_);
724              
725             $self->{xsub_seen_NO_OUTPUT} = 1
726 4 50       18 if $self->{xsub_return_type} =~ s/^NO_OUTPUT\s+//;
727              
728             # Allow one-line declarations. This splits a single line like:
729             # int foo(....)
730             # into the two lines:
731             # int
732             # foo(...)
733             # Note that this splits both K&R-style 'foo(a, b)' and ANSI-style
734             # 'foo(int a, int b)'. I don't know whether the former was intentional.
735             # As of 5.40.0, the docs don't suggest that a 1-line K&R is legal. Was
736             # added by 11416672a16, first appeared in 5.6.0.
737             #
738             # NB: $self->{config_allow_argtypes} is false if xsubpp was invoked
739             # with -noargtypes
740              
741 0         0 unshift @{ $self->{line} }, $2
742             if $self->{config_allow_argtypes}
743 4 50 33     39 and $self->{xsub_return_type} =~ s/^(.*?\w.*?)\s*\b(\w+\s*\(.*)/$1/s;
744              
745             # a function definition needs at least 2 lines
746             $self->blurt("Error: Function definition too short '$self->{xsub_return_type}'"), next PARAGRAPH
747 4 50       8 unless @{ $self->{line} };
  4         16  
748              
749             $self->{xsub_seen_extern_C} = 1
750 4 50       15 if $self->{xsub_return_type} =~ s/^extern "C"\s+//;
751             $self->{xsub_seen_static} = 1
752 4 50       14 if $self->{xsub_return_type} =~ s/^static\s+//;
753              
754             my XS::Install::FrozenShit::ParseXS::Node::Sig $sig
755             = $self->{xsub_sig}
756 4         52 = XS::Install::FrozenShit::ParseXS::Node::Sig->new();
757              
758             {
759 4         8 my $func_header = shift(@{ $self->{line} });
  4         7  
  4         62  
760              
761             # Decompose the function declaration: match a line like
762             # Some::Class::foo_bar( args ) const ;
763             # ----------- ------- ---- ----- --
764             # $1 $2 $3 $4 $5
765             #
766             # where everything except $2 and $3 are optional and the 'const'
767             # is for C++ functions.
768              
769 4 50       115 $self->blurt("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
770             unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s;
771              
772             ($self->{xsub_class}, $self->{xsub_func_name}, $sig->{sig_text})
773 4         44 = ($1, $2, $3);
774              
775 4 50       18 $self->{xsub_class} = "$4 $self->{xsub_class}" if $4;
776              
777 4 50 33     18 if ($self->{xsub_seen_static}
778             and !defined $self->{xsub_class})
779             {
780 0         0 $self->Warn( "Ignoring 'static' type modifier:"
781             . " only valid with an XSUB name which includes a class");
782 0         0 $self->{xsub_seen_static} = 0;
783             }
784              
785 4         101 ($self->{xsub_func_full_perl_name} = $self->{xsub_func_name}) =~
786             s/^($self->{PREFIX_pattern})?/$self->{PACKAGE_class}/;
787              
788 4         63 my $clean_func_name;
789 4         38 ($clean_func_name = $self->{xsub_func_name}) =~ s/^$self->{PREFIX_pattern}//;
790 4         15 $self->{xsub_func_full_C_name} = "$self->{PACKAGE_C_name}_$clean_func_name";
791 4 50       36 if ($Is_VMS) {
792 0         0 $self->{xsub_func_full_C_name} = $VMS_SymSet->addsym( $self->{xsub_func_full_C_name} );
793             }
794              
795             # At this point, supposing that the input so far was:
796             #
797             # MODULE = ... PACKAGE = BAR::BAZ PREFIX = foo_
798             # int
799             # Some::Class::foo_bar( args ) const ;
800             #
801             # we should have:
802             #
803             # $self->{xsub_class} 'const Some::Class'
804             # $self->{xsub_func_name} 'foo_bar'
805             # $self->{xsub_func_full_perl_name} 'BAR::BAZ::bar'
806             # $self->{xsub_func_full_C_name} 'BAR__BAZ_bar';
807             #
808             # $sig->{sig_text} 'param1, param2, param3'
809              
810              
811             # Check for a duplicate function definition, but ignoring multiple
812             # definitions within the branches of an #if/#else/#endif
813 4         9 for my $tmp (@{ $self->{XS_parse_stack} }) {
  4         20  
814 4 50       26 next unless defined $tmp->{functions}{ $self->{xsub_func_full_C_name} };
815 0         0 Warn( $self, "Warning: duplicate function definition '$clean_func_name' detected");
816 0         0 last;
817             }
818             }
819              
820             # mark C function name as used
821 4         19 $self->{XS_parse_stack}->[$self->{XS_parse_stack_top_if_idx}]{functions}{ $self->{xsub_func_full_C_name} }++;
822              
823             # initialise more per-XSUB state
824 4         11 delete $self->{xsub_map_alias_name_to_value}; # ALIAS: ...
825 4         7 delete $self->{xsub_map_alias_value_to_name_seen_hash};
826             # INTERFACE: foo bar
827 4         9 %{ $self->{xsub_map_interface_name_short_to_original} } = ();
  4         29  
828 4         9 @{ $self->{xsub_attributes} } = (); # ATTRS: lvalue method
  4         56  
829 4         13 $self->{xsub_SETMAGIC_state} = 1; # SETMAGIC: ENABLE
830              
831             # ----------------------------------------------------------------
832             # Process the XSUB's signature.
833             #
834             # Split $self->{xsub_sub}{sig_text} into parameters, parse them,
835             # and store them as Node::Param objects within the Node::Sig object.
836              
837 4         29 $sig->parse($self);
838              
839             # ----------------------------------------------------------------
840             # Peek ahead into the body of the XSUB looking for various conditions
841             # that are needed to be known early.
842             # ----------------------------------------------------------------
843              
844 4         8 $self->{xsub_seen_ALIAS} = grep(/^\s*ALIAS\s*:/, @{ $self->{line} });
  4         85  
845              
846 4         19 $self->{xsub_seen_PPCODE} = !!grep(/^\s*PPCODE\s*:/, @{$self->{line}});
  4         31  
847 4         9 $self->{xsub_seen_CODE} = !!grep(/^\s*CODE\s*:/, @{$self->{line}});
  4         38  
848 4         9 $self->{xsub_seen_INTERFACE}= !!grep(/^\s*INTERFACE\s*:/, @{$self->{line}});
  4         55  
849              
850             # Horrible 'void' return arg count hack.
851             #
852             # Until about 1996, xsubpp always emitted 'XSRETURN(1)', even for a
853             # void XSUB. This was fixed for CODE-less void XSUBs simply by
854             # actually honouring the 'void' type and emitting 'XSRETURN_EMPTY'
855             # instead. However, for CODE blocks, the documentation had already
856             # endorsed a coding style along the lines of
857             #
858             # void
859             # foo(...)
860             # CODE:
861             # ST(0) = sv_newmortal();
862             #
863             # i.e. the XSUB returns an SV even when the return type is 'void'.
864             # In 2024 there is still lots of code of this style out in the wild,
865             # even in the distros bundled with perl.
866             #
867             # So honouring the void type here breaks lots of existing code. Thus
868             # this hack specifically looks for: void XSUBs with a CODE block that
869             # appears to put stuff on the stack via 'ST(n)=' or 'XST_m()', and if
870             # so, emits 'XSRETURN(1)' rather than the 'XSRETURN_EMPTY' implied by
871             # the 'void' return type.
872             #
873             # XXX this searches the whole XSUB, not just the CODE: section
874             {
875             my $EXPLICIT_RETURN = ($self->{xsub_seen_CODE} &&
876 4   66     20 ("@{ $self->{line} }" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
877 4 50       16 $XSRETURN_count = 1 if $EXPLICIT_RETURN;
878             }
879              
880              
881             # ----------------------------------------------------------------
882             # Emit initial C code for the XSUB
883             # ----------------------------------------------------------------
884              
885             {
886 4 50       9 my $extern = $self->{xsub_seen_extern_C} ? qq[extern "C"] : "";
  4         9  
  4         13  
887              
888             # Emit function header
889 4         25 print Q(<<"EOF");
890             |$extern
891             |XS_EUPXS(XS_$self->{xsub_func_full_C_name}); /* prototype to pass -Wmissing-prototypes */
892             |XS_EUPXS(XS_$self->{xsub_func_full_C_name})
893             |[[
894             | dVAR; dXSARGS;
895             EOF
896             }
897              
898 4 50       19 print Q(<<"EOF") if $self->{xsub_seen_ALIAS};
899             | dXSI32;
900             EOF
901              
902 4 50       28 print Q(<<"EOF") if $self->{xsub_seen_INTERFACE};
903             | dXSFUNCTION($self->{xsub_return_type});
904             EOF
905              
906              
907             {
908             # the code to emit to determine whether the correct number of argument
909             # have been passed
910 4         9 my $condition_code =
911             set_cond($sig->{seen_ellipsis}, $self->{xsub_sig}{min_args},
912 4         35 $self->{xsub_sig}{nargs});
913              
914 4 50       15 print Q(<<"EOF") if $self->{config_allow_exceptions}; # "-except" cmd line switch
915             | char errbuf[1024];
916             | *errbuf = '\\0';
917             EOF
918              
919 4 50       10 if ($condition_code) {
920 4         27 my $p = $self->{xsub_sig}->usage_string();
921 4         13 $p =~ s/"/\\"/g;
922 4         19 print Q(<<"EOF");
923             | if ($condition_code)
924             | croak_xs_usage(cv, "$p");
925             EOF
926             }
927             else {
928             # cv and items likely to be unused
929 0         0 print Q(<<"EOF");
930             | PERL_UNUSED_VAR(cv); /* -W */
931             | PERL_UNUSED_VAR(items); /* -W */
932             EOF
933             }
934             }
935              
936             # gcc -Wall: if an XSUB has PPCODE, it is possible that none of ST,
937             # XSRETURN or XSprePUSH macros are used. Hence 'ax' (setup by
938             # dXSARGS) is unused.
939             # XXX: could breakup the dXSARGS; into dSP;dMARK;dITEMS
940             # but such a move could break third-party extensions
941 4 100       20 print Q(<<"EOF") if $self->{xsub_seen_PPCODE};
942             | PERL_UNUSED_VAR(ax); /* -Wall */
943             EOF
944              
945 4 100       16 print Q(<<"EOF") if $self->{xsub_seen_PPCODE};
946             | SP -= items;
947             EOF
948              
949             # ----------------------------------------------------------------
950             # Now prepare to process the various keyword lines/blocks of an XSUB
951             # body
952             # ----------------------------------------------------------------
953              
954             # Initialise any CASE: state
955 4         12 $self->{xsub_CASE_condition_count} = 0;
956 4         9 $self->{xsub_CASE_condition} = ''; # last CASE: conditional
957              
958             # Append a fake EOF-keyword line
959 4         8 push(@{ $self->{line} }, "$END:");
  4         19  
960 4         8 push(@{ $self->{line_no} }, $self->{line_no}->[-1]);
  4         14  
961              
962 4         10 $_ = '';
963              
964             # Check all the @{ $self->{line}} lines for balance: all the
965             # #if, #else, #endif etc within the XSUB should balance out.
966 4         20 check_conditional_preprocessor_statements();
967              
968             # Save a deep copy the params created from parsing the signature.
969             # See the comments below starting "For each CASE" for details.
970              
971 4         24 $self->{xsub_sig}{orig_params} = [];
972 4         8 for (@{$self->{xsub_sig}{params}}) {
  4         14  
973 8         13 push @{$self->{xsub_sig}{orig_params}},
  8         42  
974             XS::Install::FrozenShit::ParseXS::Node::Param->new($_);
975             }
976              
977             # ----------------------------------------------------------------
978             # Each iteration of this loop will process 1 optional CASE: line,
979             # followed by all the other blocks. In the absence of a CASE: line,
980             # this loop is only iterated once.
981             # ----------------------------------------------------------------
982              
983 4         9 while (@{ $self->{line} }) {
  4         17  
984              
985             # For a 'CASE: foo' line, emit an 'else if (foo)' style line of C.
986             # Note that each CASE: can precede multiple keyword blocks.
987 4 50       14 $self->CASE_handler($_) if $self->check_keyword("CASE");
988              
989             # For each CASE, start with a fresh set of params based on the
990             # original parsing of the XSUB's signature. This is because each set
991             # of INPUT/OUTPUT blocks associated with each CASE may update the
992             # param objects in a different way.
993             #
994             # Note that $self->{xsub_sig}{names} provides a second set of
995             # references to most of these param objects; so the object hashes
996             # themselves must be preserved, and merely their contents emptied
997             # and repopulated each time. Hence also why creating the orig_params
998             # snapshot above must be a deep copy.
999             #
1000             # XXX This is bit of a temporary hack.
1001              
1002 4         16 for my $i (0.. @{$self->{xsub_sig}{orig_params}} - 1) {
  4         26  
1003 8         21 my $op = $self->{xsub_sig}{orig_params}[$i];
1004 8         43 my $p = $self->{xsub_sig}{params}[$i];
1005 8         29 %$p = ();
1006 8         49 my @keys = sort keys %$op;
1007 8         48 @$p{@keys} = @$op{@keys};
1008             }
1009              
1010             # ----------------------------------------------------------------
1011             # Handle all the XSUB parts which generate declarations
1012             # ----------------------------------------------------------------
1013              
1014             # Emit opening brace. With cmd-line switch "-except", prefix it
1015             # with 'TRY'
1016             {
1017 4 50       9 my $try = $self->{config_allow_exceptions} ? ' TRY' : '';
  4         15  
1018 4         20 print Q(<<"EOF");
1019             | $try [[
1020             EOF
1021             }
1022              
1023             # First, initialize variables manipulated by INPUT_handler().
1024 4         15 $self->{xsub_deferred_code_lines} = ""; # lines to be emitted after
1025             # PREINIT/INPUT
1026              
1027 4         12 $self->{xsub_stack_was_reset} = 0; # XSprePUSH not yet emitted
1028 4         9 $self->{xsub_targ_declared_early} = 0; # dXSTARG not yet emitted
1029 4         8 $self->{xsub_targ_used} = 0; # TARG hasn't yet been used
1030              
1031             # Process any implicit INPUT section.
1032 4         30 $self->INPUT_handler($_);
1033              
1034             # keywords which can appear anywhere in an XSUB
1035 4         16 my $generic_xsub_keys =
1036             $XS::Install::FrozenShit::ParseXS::Constants::generic_xsub_keywords_alt;
1037              
1038             # Process as many keyword lines/blocks as can be found which match
1039             # the pattern. At this stage it's looking for (possibly multiple)
1040             # INPUT and/or PREINIT blocks, plus any generic XSUB keywords.
1041 4         23 $self->process_keywords(
1042             "C_ARGS|INPUT|INTERFACE_MACRO|PREINIT|SCOPE|$generic_xsub_keys");
1043              
1044 4 50       22 print Q(<<"EOF") if $self->{xsub_SCOPE_enabled};
1045             | ENTER;
1046             | [[
1047             EOF
1048              
1049             # Emit any 'char * CLASS' or 'Foo::Bar *THIS' declaration if needed
1050              
1051 4         10 for my $param (grep $_->{is_synthetic}, @{$self->{xsub_sig}{params}}) {
  4         26  
1052 2         11 $param->as_code($self);
1053             }
1054              
1055             # This set later if CODE is using RETVAL
1056 4         12 $self->{xsub_seen_RETVAL_in_CODE} = 0;
1057              
1058             # $implicit_OUTPUT_RETVAL (bool) indicates that a bodiless XSUB has
1059             # a non-void return value, so needs to return RETVAL; or to put it
1060             # another way, it indicates an implicit "OUTPUT:\n\tRETVAL".
1061 4         14 my $implicit_OUTPUT_RETVAL;
1062              
1063             # do code
1064 4 50       15 if (/^\s*NOT_IMPLEMENTED_YET/) {
1065 0         0 print "\n\tPerl_croak(aTHX_ \"$self->{xsub_func_full_perl_name}: not implemented yet\");\n";
1066 0         0 $_ = '';
1067             }
1068             else {
1069              
1070             # Do any variable declarations associated with having a return value
1071 4 100       14 if ($self->{xsub_return_type} ne "void") {
1072              
1073             # Emit an early dXSTARG for backwards-compatibility reasons.
1074             # Recent code emits a dXSTARG in a tighter scope and under
1075             # additional circumstances, but some XS code relies on TARG
1076             # having been declared. So continue to declare it early under
1077             # the original circumstances.
1078 2         19 my $outputmap = $self->{typemaps_object}->get_outputmap( ctype => $self->{xsub_return_type} );
1079              
1080 2 50 33     25 if ( $self->{config_optimize}
      33        
1081             and $outputmap
1082             and $outputmap->targetable_legacy)
1083             {
1084 0         0 $self->{xsub_targ_declared_early} = 1;
1085 0         0 print "\tdXSTARG;\n"
1086             }
1087             }
1088              
1089             # Process any parameters which were declared with a type
1090             # or length(foo). Do the length() ones first.
1091              
1092 4         10 for my $param (
1093             grep $_->{is_ansi},
1094             (
1095 4         21 grep( $_->{is_length}, @{$self->{xsub_sig}{params}} ),
1096 4         31 grep(! $_->{is_length}, @{$self->{xsub_sig}{params}} ),
1097             )
1098             )
1099             {
1100             # These check() calls really ought to come earlier, but this
1101             # matches older behaviour for now (when ANSI params were
1102             # injected into the src as fake INPUT lines at the *end*).
1103 6 50       23 $param->check($self)
1104             or next;
1105 6         23 $param->as_code($self);
1106             }
1107              
1108             # ----------------------------------------------------------------
1109             # All C variable declarations have now been emitted. It's now time
1110             # to emit any code which goes before the main body (i.e. the CODE:
1111             # etc or the implicit call to the wrapped function).
1112             # ----------------------------------------------------------------
1113              
1114             # Emit any code which has been deferred until all declarations
1115             # have been done. This is typically INPUT typemaps which don't
1116             # start with a simple '$var =' and so would not have been emitted
1117             # at the variable declaration stage.
1118 4         20 print $self->{xsub_deferred_code_lines};
1119              
1120             # Process as many keyword lines/blocks as can be found which match
1121             # the pattern. At this stage it's looking for (possibly multiple)
1122             # INIT blocks, plus any generic XSUB keywords.
1123 4         23 $self->process_keywords(
1124             "C_ARGS|INIT|INTERFACE|INTERFACE_MACRO|$generic_xsub_keys");
1125              
1126             # ----------------------------------------------------------------
1127             # Time to emit the main body of the XSUB. Either the real code
1128             # from a CODE: or PPCODE: block, or the implicit call to the
1129             # wrapped function
1130             # ----------------------------------------------------------------
1131              
1132 4 100 0     27 if ($self->check_keyword("PPCODE")) {
    50          
    0          
1133             # Handle PPCODE: just emit the code block and then code to do
1134             # PUTBACK and return. The user of PPCODE is supposed to have
1135             # done all the return stack manipulation themselves.
1136             # Note that PPCODE blocks often include a XSRETURN(1) or
1137             # similar, so any final code we emit after that is in danger of
1138             # triggering a "statement is unreachable" warning.
1139              
1140 2         13 $self->print_section();
1141 2 50       4 $self->death("PPCODE must be last thing") if @{ $self->{line} };
  2         11  
1142              
1143 2 50       9 print "\tLEAVE;\n" if $self->{xsub_SCOPE_enabled};
1144              
1145             # Suppress "statement is unreachable" warning on HPUX
1146 2 50       11 print "#if defined(__HP_cc) || defined(__HP_aCC)\n",
1147             "#pragma diag_suppress 2111\n",
1148             "#endif\n"
1149             if $^O eq "hpux";
1150              
1151 2         7 print "\tPUTBACK;\n\treturn;\n";
1152              
1153             # Suppress "statement is unreachable" warning on HPUX
1154 2 50       11 print "#if defined(__HP_cc) || defined(__HP_aCC)\n",
1155             "#pragma diag_default 2111\n",
1156             "#endif\n"
1157             if $^O eq "hpux";
1158              
1159             }
1160             elsif ($self->check_keyword("CODE")) {
1161             # Handle CODE: just emit the code block and check if it
1162             # includes "RETVAL". This check is for later use to warn if
1163             # RETVAL is used but no OUTPUT block is present.
1164             # Ignore if its only being used in an 'ignore this var'
1165             # situation
1166 2         17 my $consumed_code = $self->print_section();
1167 2 50 33     31 if ( $consumed_code =~ /\bRETVAL\b/
1168             && $consumed_code !~ /\b\QPERL_UNUSED_VAR(RETVAL)/
1169             ) {
1170 2         9 $self->{xsub_seen_RETVAL_in_CODE} = 1;
1171             }
1172              
1173             }
1174             elsif ( defined($self->{xsub_class})
1175             and $self->{xsub_func_name} eq "DESTROY")
1176             {
1177             # Emit a default body for a C++ DESTROY method: "delete THIS;"
1178 0         0 print "\n\t";
1179 0         0 print "delete THIS;\n";
1180              
1181             }
1182             else {
1183             # Emit a default body: this will be a call to the function being
1184             # wrapped. Typically:
1185             # RETVAL = foo(args);
1186             # with the function name being appropriately modified when it's
1187             # a C++ new() method etc.
1188              
1189 0         0 print "\n\t";
1190              
1191 0 0       0 if ($self->{xsub_return_type} ne "void") {
1192 0         0 print "RETVAL = ";
1193             # There's usually an implied 'OUTPUT: RETVAL' in bodiless XSUBs
1194 0 0       0 $implicit_OUTPUT_RETVAL = 1 unless $self->{xsub_seen_NO_OUTPUT};
1195             }
1196              
1197 0 0       0 if (defined($self->{xsub_class})) {
1198 0 0       0 if ($self->{xsub_seen_static}) {
1199             # it has a return type of 'static foo'
1200 0 0       0 if ($self->{xsub_func_name} eq 'new') {
1201 0         0 $self->{xsub_func_name} = "$self->{xsub_class}";
1202             }
1203             else {
1204 0         0 print "$self->{xsub_class}::";
1205             }
1206             }
1207             else {
1208 0 0       0 if ($self->{xsub_func_name} eq 'new') {
1209 0         0 $self->{xsub_func_name} .= " $self->{xsub_class}";
1210             }
1211             else {
1212 0         0 print "THIS->";
1213             }
1214             }
1215             }
1216              
1217             # Handle "xsubpp -s=strip_prefix" hack
1218 0         0 my $strip = $self->{config_strip_c_func_prefix};
1219 0 0       0 $self->{xsub_func_name} =~ s/^\Q$strip//
1220             if defined $strip;
1221              
1222             $self->{xsub_func_name} = 'XSFUNCTION'
1223 0 0       0 if $self->{xsub_seen_INTERFACE_or_MACRO};
1224              
1225 0         0 my $sig = $self->{xsub_sig};
1226 0         0 my $args = $sig->{auto_function_sig_override}; # C_ARGS
1227 0 0       0 $args = $sig->C_func_signature($self)
1228             unless defined $args;
1229 0         0 print "$self->{xsub_func_name}($args);\n";
1230              
1231             } # End: PPCODE: or CODE: or a default body
1232              
1233             } # End: else NOT_IMPLEMENTED_YET
1234              
1235             # ----------------------------------------------------------------
1236             # Main body of function has now been emitted.
1237             # Next, process any POSTCALL or OUTPUT blocks,
1238             # plus some post-processing of OUTPUT.
1239             # ----------------------------------------------------------------
1240              
1241             # Process as many keyword lines/blocks as can be found which match
1242             # the pattern.
1243             # XXX POSTCALL is documented to precede OUTPUT, but here we allow
1244             # them in any order and multiplicity.
1245 4         27 $self->process_keywords("OUTPUT|POSTCALL|$generic_xsub_keys");
1246              
1247             {
1248 4         14 my $retval = $self->{xsub_sig}{names}{RETVAL};
  4         44  
1249              
1250             # A CODE section using RETVAL must also have an OUTPUT entry
1251 4 50 33     35 if ( $self->{xsub_seen_RETVAL_in_CODE}
      66        
      33        
1252             and not ($retval && $retval->{in_output})
1253             and $self->{xsub_return_type} ne 'void')
1254             {
1255 0         0 $self->Warn("Warning: Found a 'CODE' section which seems to be using 'RETVAL' but no 'OUTPUT' section.");
1256             }
1257              
1258             # Process any OUT vars: i.e. vars that are declared OUT in
1259             # the XSUB's signature rather than in an OUTPUT section.
1260              
1261 4         57 for my $param (
1262             grep {
1263             defined $_->{in_out}
1264             && $_->{in_out} =~ /OUT$/
1265             && !$_->{in_output}
1266 8 50 33     38 }
1267 4         20 @{ $self->{xsub_sig}{params}})
1268             {
1269 0         0 $param->as_output_code($self);
1270             }
1271              
1272             # If there are any OUTLIST vars to be pushed, first extend the
1273             # stack, to fit all OUTLIST vars + RETVAL
1274             my $outlist_count = grep { defined $_->{in_out}
1275 8 50       26 && $_->{in_out} =~ /OUTLIST$/
1276             }
1277 4         8 @{$self->{xsub_sig}{params}};
  4         13  
1278 4 50       11 if ($outlist_count) {
1279 0         0 my $ext = $outlist_count;
1280 0 0 0     0 ++$ext if ($retval && $retval->{in_output}) || $implicit_OUTPUT_RETVAL;
      0        
1281 0         0 print "\tXSprePUSH;\n";
1282             # XSprePUSH resets SP to the base of the stack frame; must PUSH
1283             # any return values
1284 0         0 $self->{xsub_stack_was_reset} = 1;
1285              
1286             # The entersub will gave been called with at least a GV or CV on
1287             # the stack in addition to at least min_args args, so only need
1288             # to extend if we're returning more than that.
1289             print "\tEXTEND(SP,$ext);\n"
1290 0 0       0 if $ext > $self->{xsub_sig}{min_args} + 1;
1291             }
1292              
1293             # ----------------------------------------------------------------
1294             # All OUTPUT done; now handle an implicit or deferred RETVAL.
1295             # OUTPUT_handler() will have skipped any RETVAL line.
1296             # Also, $implicit_OUTPUT_RETVAL indicates that an implicit RETVAL
1297             # should be generated, due to a non-void CODE-less XSUB.
1298             # ----------------------------------------------------------------
1299              
1300 4 100 66     33 if (($retval && $retval->{in_output}) || $implicit_OUTPUT_RETVAL) {
      66        
1301             # emit a deferred RETVAL from OUTPUT or implicit RETVAL
1302 2         31 $retval->as_output_code($self);
1303             }
1304              
1305             $XSRETURN_count = 1 if $self->{xsub_return_type} ne "void"
1306 4 100 66     32 && !$self->{xsub_seen_NO_OUTPUT};
1307 4         9 my $num = $XSRETURN_count;
1308 4         8 $XSRETURN_count += $outlist_count;
1309              
1310             # Now that RETVAL is on the stack, also push any OUTLIST vars too
1311 4         8 for my $param (grep { defined $_->{in_out}
1312 8 50       31 && $_->{in_out} =~ /OUTLIST$/
1313             }
1314 4         18 @{$self->{xsub_sig}{params}}
1315             ) {
1316 0         0 $param->as_output_code($self, $num++);
1317             }
1318             }
1319              
1320              
1321             # ----------------------------------------------------------------
1322             # All RETVAL processing has been done.
1323             # Next, process any CLEANUP blocks,
1324             # ----------------------------------------------------------------
1325              
1326             # Process as many keyword lines/blocks as can be found which match
1327             # the pattern.
1328 4         70 $self->process_keywords("CLEANUP|$generic_xsub_keys");
1329              
1330             # ----------------------------------------------------------------
1331             # Emit function trailers
1332             # ----------------------------------------------------------------
1333              
1334 4 50       50 print Q(<<"EOF") if $self->{xsub_SCOPE_enabled};
1335             | ]]
1336             EOF
1337              
1338 4 50 33     19 print Q(<<"EOF") if $self->{xsub_SCOPE_enabled} and not $self->{xsub_seen_PPCODE};
1339             | LEAVE;
1340             EOF
1341              
1342 4         17 print Q(<<"EOF");
1343             | ]]
1344             EOF
1345              
1346 4 50       19 print Q(<<"EOF") if $self->{config_allow_exceptions};
1347             | BEGHANDLERS
1348             | CATCHALL
1349             | sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
1350             | ENDHANDLERS
1351             EOF
1352              
1353 4 50       16 if ($self->check_keyword("CASE")) {
1354             $self->blurt("Error: No 'CASE:' at top of function")
1355 0 0       0 unless $self->{xsub_CASE_condition_count};
1356 0         0 $_ = "CASE: $_"; # Restore CASE: label
1357 0         0 next;
1358             }
1359              
1360 4 50       30 last if $_ eq "$END:";
1361              
1362 0 0       0 $self->death(/^$BLOCK_regexp/o ? "Misplaced '$1:'" : "Junk at end of function ($_)");
1363              
1364             } # end while (@{ $self->{line} })
1365              
1366              
1367             # ----------------------------------------------------------------
1368             # All of the body of the XSUB (including all CASE variants) has now
1369             # been processed. Now emit any XSRETURN or similar, plus any closing
1370             # bracket.
1371             # ----------------------------------------------------------------
1372              
1373 4 50       16 print Q(<<"EOF") if $self->{config_allow_exceptions};
1374             | if (errbuf[0])
1375             | Perl_croak(aTHX_ errbuf);
1376             EOF
1377              
1378             # Emit XSRETURN(N) or XSRETURN_EMPTY. It's possible that the user's
1379             # CODE section rolled its own return, so this code may be
1380             # unreachable. So suppress any compiler warnings.
1381             # XXX Currently this is just for HP. Make more generic??
1382              
1383             # Suppress "statement is unreachable" warning on HPUX
1384 4 50       27 print "#if defined(__HP_cc) || defined(__HP_aCC)\n",
1385             "#pragma diag_suppress 2128\n",
1386             "#endif\n"
1387             if $^O eq "hpux";
1388              
1389 4 100       14 if ($XSRETURN_count) {
1390 2 50       15 print Q(<<"EOF") unless $self->{xsub_seen_PPCODE};
1391             | XSRETURN($XSRETURN_count);
1392             EOF
1393             }
1394             else {
1395 2 50       8 print Q(<<"EOF") unless $self->{xsub_seen_PPCODE};
1396             | XSRETURN_EMPTY;
1397             EOF
1398             }
1399              
1400             # Suppress "statement is unreachable" warning on HPUX
1401 4 50       16 print "#if defined(__HP_cc) || defined(__HP_aCC)\n",
1402             "#pragma diag_default 2128\n",
1403             "#endif\n"
1404             if $^O eq "hpux";
1405              
1406             # Emit final closing bracket for the XSUB.
1407 4         63 print Q(<<"EOF");
1408             |]]
1409             |
1410             EOF
1411              
1412             # ----------------------------------------------------------------
1413             # Generate (but don't yet emit - push to $self->{bootcode_early}) the
1414             # boot code for the XSUB, including newXS() call(s) plus any
1415             # additional boot stuff like handling attributes or storing an alias
1416             # index in the XSUB's CV.
1417             # ----------------------------------------------------------------
1418              
1419             {
1420             # Depending on whether the XSUB has a prototype, work out how to
1421             # invoke one of the newXS() function variants. Set these:
1422             #
1423 4         11 my $newXS; # the newXS() variant to be called in the boot section
  4         14  
1424             my $file_arg; # an extra ', file' arg to be passed to newXS call
1425 4         0 my $proto_arg; # an extra e.g. ', "$@"' arg to be passed to newXS call
1426              
1427 4         9 $proto_arg = "";
1428              
1429 4 50       16 unless($self->{xsub_prototype}) {
1430             # no prototype
1431 4         10 $newXS = "newXS_deffile";
1432 4         8 $file_arg = "";
1433             }
1434             else {
1435             # needs prototype
1436 0         0 $newXS = "newXSproto_portable";
1437 0         0 $file_arg = ", file";
1438              
1439 0 0       0 if ($self->{xsub_prototype} eq 2) {
    0          
1440             # User has specified an empty prototype
1441             }
1442             elsif ($self->{xsub_prototype} eq 1) {
1443             # Protoype enabled, but to be auto-generated by us
1444 0         0 $proto_arg = $self->{xsub_sig}->proto_string();
1445 0         0 $proto_arg =~ s{\\}{\\\\}g; # escape backslashes
1446             }
1447             else {
1448             # User has manually specified a prototype
1449 0         0 $proto_arg = $self->{xsub_prototype};
1450             }
1451              
1452 0         0 $proto_arg = qq{, "$proto_arg"};
1453             }
1454              
1455             # Now use those values to append suitable newXS() and other code
1456             # into @{ $self->{bootcode_early} }, for later insertion into the
1457             # boot sub.
1458              
1459 4 50 33     19 if ( $self->{xsub_map_alias_name_to_value}
    50          
    50          
    50          
1460 0         0 and keys %{ $self->{xsub_map_alias_name_to_value} })
1461             {
1462             # For the main XSUB and for each alias name, generate a newXS() call
1463             # and 'XSANY.any_i32 = ix' line.
1464              
1465             # Make the main name one of the aliases if it isn't already
1466             $self->{xsub_map_alias_name_to_value}->{ $self->{xsub_func_full_perl_name} } = 0
1467 0 0       0 unless defined $self->{xsub_map_alias_name_to_value}->{ $self->{xsub_func_full_perl_name} };
1468              
1469 0         0 foreach my $xname (sort keys %{ $self->{xsub_map_alias_name_to_value} }) {
  0         0  
1470 0         0 my $value = $self->{xsub_map_alias_name_to_value}{$xname};
1471 0         0 push(@{ $self->{bootcode_early} }, Q(<<"EOF"));
  0         0  
1472             | cv = $newXS(\"$xname\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);
1473             | XSANY.any_i32 = $value;
1474             EOF
1475             }
1476             }
1477 4         24 elsif (@{ $self->{xsub_attributes} }) {
1478             # Generate a standard newXS() call, plus a single call to
1479             # apply_attrs_string() call with the string of attributes.
1480 0         0 push(@{ $self->{bootcode_early} }, Q(<<"EOF"));
  0         0  
1481             | cv = $newXS(\"$self->{xsub_func_full_perl_name}\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);
1482 0         0 | apply_attrs_string("$self->{PACKAGE_name}", cv, "@{ $self->{xsub_attributes} }", 0);
1483             EOF
1484             }
1485             elsif ($self->{xsub_seen_INTERFACE_or_MACRO}) {
1486             # For each interface name, generate both a newXS() and
1487             # XSINTERFACE_FUNC_SET() call.
1488 0         0 foreach my $yname (sort keys
1489 0         0 %{ $self->{xsub_map_interface_name_short_to_original} })
1490             {
1491 0         0 my $value = $self->{xsub_map_interface_name_short_to_original}{$yname};
1492 0 0       0 $yname = "$self->{PACKAGE_name}\::$yname" unless $yname =~ /::/;
1493 0         0 push(@{ $self->{bootcode_early} }, Q(<<"EOF"));
  0         0  
1494             | cv = $newXS(\"$yname\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);
1495             | $self->{xsub_interface_macro_set}(cv,$value);
1496             EOF
1497             }
1498             }
1499             elsif ($newXS eq 'newXS_deffile'){
1500             # Modified default: generate a standard newXS() call; but
1501             # work around the CPAN 'P5NCI' distribution doing:
1502             # #undef newXS
1503             # #define newXS ;
1504             # by omitting the initial (void).
1505             # XXX DAPM 2024:
1506             # this branch was originally: "elsif ($newXS eq 'newXS')"
1507             # but when the standard name for the newXS variant changed in
1508             # xsubpp, it was changed here too. So this branch no longer actually
1509             # handles a workaround for '#define newXS ;'. I also don't
1510             # understand how just omitting the '(void)' fixed the problem.
1511 4         27 push(@{ $self->{bootcode_early} },
  4         23  
1512             " $newXS(\"$self->{xsub_func_full_perl_name}\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);\n");
1513             }
1514             else {
1515             # Default: generate a standard newXS() call
1516 0         0 push(@{ $self->{bootcode_early} },
  0         0  
1517             " (void)$newXS(\"$self->{xsub_func_full_perl_name}\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);\n");
1518             }
1519              
1520             # For every overload operator, generate an additional newXS()
1521             # call to add an alias such as "Foo::(<=>" for this XSUB.
1522              
1523 4         10 for my $operator (sort keys %{ $self->{xsub_map_overload_name_to_seen} })
  4         35  
1524             {
1525             $self->{map_overloaded_package_to_C_package}->{$self->{PACKAGE_name}}
1526 0         0 = $self->{PACKAGE_C_name};
1527 0         0 my $overload = "$self->{PACKAGE_name}\::($operator";
1528 0         0 push(@{ $self->{bootcode_early} },
  0         0  
1529             " (void)$newXS(\"$overload\", XS_$self->{xsub_func_full_C_name}$file_arg$proto_arg);\n");
1530             }
1531              
1532             }
1533              
1534             } # END 'PARAGRAPH' 'while' loop
1535              
1536              
1537             # ----------------------------------------------------------------
1538             # End of main loop and at EOF: all paragraphs (and thus XSUBs) have now
1539             # been read in and processed. Do any final post-processing.
1540             # ----------------------------------------------------------------
1541              
1542             # Process any overloading.
1543             #
1544             # For each package FOO which has had at least one overloaded method
1545             # specified:
1546             # - create a stub XSUB in that package called nil;
1547             # - generate code to be added to the boot XSUB which links that XSUB
1548             # to the symbol table entry *{"FOO::()"}. This mimics the action in
1549             # overload::import() which creates the stub method as a quick way to
1550             # check whether an object is overloaded (including via inheritance),
1551             # by doing $self->can('()').
1552             # - Further down, we add a ${"FOO:()"} scalar containing the value of
1553             # 'fallback' (or undef if not specified).
1554             #
1555             # XXX In 5.18.0, this arrangement was changed in overload.pm, but hasn't
1556             # been updated here. The *() glob was being used for two different
1557             # purposes: a sub to do a quick check of overloadability, and a scalar
1558             # to indicate what 'fallback' value was specified (even if it wasn't
1559             # specified). The commits:
1560             # v5.16.0-87-g50853fa94f
1561             # v5.16.0-190-g3866ea3be5
1562             # v5.17.1-219-g79c9643d87
1563             # changed this so that overloadability is checked by &((, while fallback
1564             # is checked by $() (and not present unless specified by 'fallback'
1565             # as opposed to the always being present, but sometimes undef).
1566             # Except that, in the presence of fallback, &() is added too for
1567             # backcompat reasons (which I don't fully understand - DAPM).
1568             # See overload.pm's import() and OVERLOAD() methods for more detail.
1569             #
1570             # So this code needs updating to match.
1571              
1572 1         2 for my $package (sort keys %{ $self->{map_overloaded_package_to_C_package} })
  1         7  
1573             {
1574             # make them findable with fetchmethod
1575 0         0 my $packid = $self->{map_overloaded_package_to_C_package}->{$package};
1576 0         0 print Q(<<"EOF");
1577             |XS_EUPXS(XS_${packid}_nil); /* prototype to pass -Wmissing-prototypes */
1578             |XS_EUPXS(XS_${packid}_nil)
1579             |{
1580             | dXSARGS;
1581             | PERL_UNUSED_VAR(items);
1582             | XSRETURN_EMPTY;
1583             |}
1584             |
1585             EOF
1586              
1587 0         0 unshift(@{ $self->{bootcode_early} }, Q(<<"EOF"));
  0         0  
1588             | /* Making a sub named "${package}::()" allows the package */
1589             | /* to be findable via fetchmethod(), and causes */
1590             | /* overload::Overloaded("$package") to return true. */
1591             | (void)newXS_deffile("${package}::()", XS_${packid}_nil);
1592             EOF
1593             }
1594              
1595              
1596             # ----------------------------------------------------------------
1597             # Emit the boot XSUB initialization routine
1598             # ----------------------------------------------------------------
1599              
1600 1         4 print Q(<<"EOF");
1601             |#ifdef __cplusplus
1602             |extern "C" [[
1603             |#endif
1604             EOF
1605              
1606 1         6 print Q(<<"EOF");
1607             |XS_EXTERNAL(boot_$self->{MODULE_cname}); /* prototype to pass -Wmissing-prototypes */
1608             |XS_EXTERNAL(boot_$self->{MODULE_cname})
1609             |[[
1610             |#if PERL_VERSION_LE(5, 21, 5)
1611             | dVAR; dXSARGS;
1612             |#else
1613 1 50       11 | dVAR; ${\($self->{VERSIONCHECK_value} ? 'dXSBOOTARGSXSAPIVERCHK;' : 'dXSBOOTARGSAPIVERCHK;')}
1614             |#endif
1615             EOF
1616              
1617             # Declare a 'file' var for passing to newXS() and variants.
1618             #
1619             # If there is no $self->{xsub_func_full_C_name} then there are no xsubs
1620             # in this .xs so 'file' is unused, so silence warnings.
1621             #
1622             # 'file' can also be unused in other circumstances: in particular,
1623             # newXS_deffile() doesn't take a file parameter. So suppress any
1624             # 'unused var' warning always.
1625             #
1626             # Give it the correct 'const'ness: Under 5.8.x and lower, newXS() is
1627             # declared in proto.h as expecting a non-const file name argument. If
1628             # the wrong qualifier is used, it causes breakage with C++ compilers and
1629             # warnings with recent gcc.
1630              
1631 1 50       9 print Q(<<"EOF") if $self->{xsub_func_full_C_name};
1632             |#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */
1633             | char* file = __FILE__;
1634             |#else
1635             | const char* file = __FILE__;
1636             |#endif
1637             |
1638             | PERL_UNUSED_VAR(file);
1639             EOF
1640              
1641             # Emit assorted declarations
1642              
1643 1         5 print Q(<<"EOF");
1644             |
1645             | PERL_UNUSED_VAR(cv); /* -W */
1646             | PERL_UNUSED_VAR(items); /* -W */
1647             EOF
1648              
1649 1 50       7 if ($self->{VERSIONCHECK_value}) {
1650 1         5 print Q(<<"EOF") ;
1651             |#if PERL_VERSION_LE(5, 21, 5)
1652             | XS_VERSION_BOOTCHECK;
1653             |# ifdef XS_APIVERSION_BOOTCHECK
1654             | XS_APIVERSION_BOOTCHECK;
1655             |# endif
1656             |#endif
1657             |
1658             EOF
1659              
1660             } else {
1661 0         0 print Q(<<"EOF") ;
1662             |#if PERL_VERSION_LE(5, 21, 5) && defined(XS_APIVERSION_BOOTCHECK)
1663             | XS_APIVERSION_BOOTCHECK;
1664             |#endif
1665             |
1666             EOF
1667              
1668             }
1669              
1670             # Declare a 'cv' var within a scope small enough to be visible just to
1671             # newXS() calls which need to do further processing of the cv: in
1672             # particular, when emitting one of:
1673             # XSANY.any_i32 = $value;
1674             # XSINTERFACE_FUNC_SET(cv, $value);
1675              
1676 1 50 33     22 if ( defined $self->{xsub_map_alias_name_to_value}
1677             or defined $self->{seen_INTERFACE_or_MACRO})
1678             {
1679 0         0 print Q(<<"EOF");
1680             | [[
1681             | CV * cv;
1682             |
1683             EOF
1684             }
1685              
1686             # More overload stuff
1687              
1688 1 50       3 if (keys %{ $self->{map_overloaded_package_to_C_package} }) {
  1         6  
1689             # Emit just once if any overloads:
1690             # Before 5.10, PL_amagic_generation used to need setting to at least a
1691             # non-zero value to tell perl that any overloading was present.
1692 0         0 print Q(<<"EOF");
1693             | /* register the overloading (type 'A') magic */
1694             |#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */
1695             | PL_amagic_generation++;
1696             |#endif
1697             EOF
1698              
1699 0         0 for my $package (sort keys %{ $self->{map_overloaded_package_to_C_package} }) {
  0         0  
1700             # Emit once for each package with overloads:
1701             # Set ${'Foo::()'} to the fallback value for each overloaded
1702             # package 'Foo' (or undef if not specified).
1703             # But see the 'XXX' comments above about fallback and $().
1704 0   0     0 my $fallback = $self->{map_package_to_fallback_string}->{$package}
1705             || "&PL_sv_undef";
1706 0         0 print Q(<<"EOF");
1707             | /* The magic for overload gets a GV* via gv_fetchmeth as */
1708             | /* mentioned above, and looks in the SV* slot of it for */
1709             | /* the "fallback" status. */
1710             | sv_setsv(
1711             | get_sv( "${package}::()", TRUE ),
1712             | $fallback
1713             | );
1714             EOF
1715              
1716             }
1717             }
1718              
1719             # Emit any boot code associated with newXS().
1720              
1721 1         2 print @{ $self->{bootcode_early} };
  1         6  
1722              
1723             # Emit closing scope for the 'CV *cv' declaration
1724              
1725 1 50 33     17 if ( defined $self->{xsub_map_alias_name_to_value}
1726             or defined $self->{seen_INTERFACE_or_MACRO})
1727             {
1728 0         0 print Q(<<"EOF");
1729             | ]]
1730             EOF
1731             }
1732              
1733             # Emit any lines derived from BOOT: sections. By putting the lines back
1734             # into $self->{line} and passing them through print_section(),
1735             # a trailing '#line' may be emitted to effect the change back to the
1736             # current foo.c line from the foo.xs part where the BOOT: code was.
1737              
1738 1 50       2 if (@{ $self->{bootcode_later} }) {
  1         5  
1739 1         4 print "\n /* Initialisation Section */\n\n";
1740 1         3 print @{$self->{bootcode_later}};
  1         6  
1741             print 'XS::Install::FrozenShit::ParseXS::CountLines'->end_marker, "\n"
1742 1 50       9 if $self->{config_WantLineNumbers};
1743 1         4 print "\n /* End of Initialisation Section */\n\n";
1744             }
1745              
1746             # Emit code to call any UNITCHECK blocks and return true. Since 5.22,
1747             # this is been put into a separate function.
1748 1         5 print Q(<<'EOF');
1749             |#if PERL_VERSION_LE(5, 21, 5)
1750             |# if PERL_VERSION_GE(5, 9, 0)
1751             | if (PL_unitcheckav)
1752             | call_list(PL_scopestack_ix, PL_unitcheckav);
1753             |# endif
1754             | XSRETURN_YES;
1755             |#else
1756             | Perl_xs_boot_epilog(aTHX_ ax);
1757             |#endif
1758             |]]
1759             |
1760             |#ifdef __cplusplus
1761             |]]
1762             |#endif
1763             EOF
1764              
1765             warn("Please specify prototyping behavior for $self->{in_filename} (see perlxs manual)\n")
1766 1 50       8 unless $self->{proto_behaviour_specified};
1767              
1768 1         29 chdir($orig_cwd);
1769 1         18 select($orig_fh);
1770 1 50       9 untie *PSEUDO_STDOUT if tied *PSEUDO_STDOUT;
1771 1         20 close $self->{in_fh};
1772              
1773 1         58 return 1;
1774             }
1775              
1776              
1777             sub report_error_count {
1778 1 50   1 0 166 if (@_) {
1779 1   50     37 return $_[0]->{error_count}||0;
1780             }
1781             else {
1782 0   0     0 return $Singleton->{error_count}||0;
1783             }
1784             }
1785             *errors = \&report_error_count;
1786              
1787              
1788             # $self->check_keyword("FOO|BAR")
1789             #
1790             # Return a keyword if the next non-blank line matches one of the passed
1791             # keywords, or return undef otherwise.
1792             #
1793             # Expects $_ to be set to the current line. Skip any initial blank lines,
1794             # (consuming @{$self->{line}} and updating $_).
1795             #
1796             # Then if it matches FOO: etc, strip the keyword and any comment from the
1797             # line (leaving any argument in $_) and return the keyword. Return false
1798             # otherwise.
1799              
1800             sub check_keyword {
1801 44     44 0 109 my XS::Install::FrozenShit::ParseXS $self = shift;
1802             # skip blank lines
1803 44   66     254 $_ = shift(@{ $self->{line} }) while !/\S/ && @{ $self->{line} };
  4         20  
  4         28  
1804              
1805 44 100       5367 s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
1806             }
1807              
1808              
1809             # Emit, verbatim(ish), all the lines up till the next directive.
1810             # Typically used for sections that have blocks of code, like CODE. Return
1811             # a string which contains all the lines of code emitted except for the
1812             # extra '#line' type stuff.
1813              
1814             sub print_section {
1815 4     4 0 9 my XS::Install::FrozenShit::ParseXS $self = shift;
1816              
1817             # Strip leading blank lines. The "do" is required for the right semantics
1818 4   33     8 do { $_ = shift(@{ $self->{line} }) } while !/\S/ && @{ $self->{line} };
  0         0  
  4         8  
  4         42  
1819              
1820 4         15 my $consumed_code = '';
1821              
1822             # Add a '#line' if needed. The XSubPPtmp test is a bit of a hack - it
1823             # skips synthetic blocks added to boot etc which may not have line
1824             # numbers.
1825 4         13 print("#line ", $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} } -1], " \"",
  4         33  
1826             escape_file_for_line_directive($self->{in_pathname}), "\"\n")
1827             if $self->{config_WantLineNumbers}
1828 4 50 33     52 && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
      33        
1829              
1830             # Emit lines until the next directive
1831 4   66     296 for (; defined($_) && !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  28         204  
1832 28         100 print "$_\n";
1833 28         72 $consumed_code .= "$_\n";
1834             }
1835              
1836             # Emit a "restoring" '#line'
1837             print 'XS::Install::FrozenShit::ParseXS::CountLines'->end_marker, "\n"
1838 4 50       26 if $self->{config_WantLineNumbers};
1839              
1840 4         15 return $consumed_code;
1841             }
1842              
1843              
1844             # Consume, concatenate and return (as a single string), all the lines up
1845             # until the next directive (including $_ as the first line).
1846              
1847             sub merge_section {
1848 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
1849 0         0 my $in = '';
1850              
1851             # skip blank lines
1852 0   0     0 while (!/\S/ && @{ $self->{line} }) {
  0         0  
1853 0         0 $_ = shift(@{ $self->{line} });
  0         0  
1854             }
1855              
1856 0   0     0 for (; defined($_) && !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  0         0  
1857 0         0 $in .= "$_\n";
1858             }
1859 0         0 chomp $in;
1860 0         0 return $in;
1861             }
1862              
1863              
1864             # Process as many keyword lines/blocks as can be found which match the
1865             # pattern, by calling the FOO_handler() method for each keyword.
1866              
1867             sub process_keywords {
1868 16     16 0 32 my XS::Install::FrozenShit::ParseXS $self = shift;
1869 16         85 my ($pattern) = @_;
1870              
1871 16         55 while (my $kwd = $self->check_keyword($pattern)) {
1872 2         7 my $method = $kwd . "_handler";
1873 2         21 $self->$method($_); # $_ contains the rest of the line after KEYWORD:
1874             }
1875             }
1876              
1877              
1878             # Handle BOOT: keyword.
1879             # Save all the remaining lines in the paragraph to the bootcode_later
1880             # array, and prepend a '#line' if necessary.
1881              
1882             sub BOOT_handler {
1883 1     1 0 2 my XS::Install::FrozenShit::ParseXS $self = shift;
1884              
1885             # Check all the @{ $self->{line}} lines for balance: all the
1886             # #if, #else, #endif etc within the BOOT should balance out.
1887 1         8 $self->check_conditional_preprocessor_statements();
1888              
1889             # prepend a '#line' directive if needed
1890 1 50 33     24 if ( $self->{config_WantLineNumbers}
1891             && $self->{line}->[0] !~ /^\s*#\s*line\b/)
1892             {
1893 1         22 push @{ $self->{bootcode_later} },
1894             sprintf "#line %d \"%s\"\n",
1895 1         4 $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} }],
  1         7  
1896 1         3 escape_file_for_line_directive($self->{in_pathname});
1897             }
1898              
1899             # Save all the BOOT lines plus trailing empty line to be emitted later.
1900 1         3 push @{ $self->{bootcode_later} }, "$_\n" for @{ $self->{line} }, "";
  1         186  
  7         28  
1901             }
1902              
1903              
1904             # Handle CASE: keyword.
1905             # Extract the condition on the CASE: line and emit a suitable
1906             # 'else if (condition)' style line of C
1907              
1908             sub CASE_handler {
1909 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
1910 0         0 $_ = shift;
1911             $self->blurt("Error: 'CASE:' after unconditional 'CASE:'")
1912             if $self->{xsub_CASE_condition_count}
1913 0 0 0     0 && $self->{xsub_CASE_condition} eq '';
1914              
1915 0         0 $self->{xsub_CASE_condition} = $_;
1916 0         0 trim_whitespace($self->{xsub_CASE_condition});
1917             print " ",
1918             ($self->{xsub_CASE_condition_count}++ ? " else" : ""),
1919             ($self->{xsub_CASE_condition}
1920 0 0       0 ? " if ($self->{xsub_CASE_condition})\n"
    0          
1921             : "\n"
1922             );
1923 0         0 $_ = '';
1924             }
1925              
1926              
1927             # ST(): helper function for the various INPUT / OUTPUT code emitting
1928             # parts. Generate an "ST(n)" string. This is normally just:
1929             #
1930             # "ST(". $num - 1 . ")"
1931             #
1932             # except that in input processing it is legal to have a parameter with a
1933             # typemap override, but where the parameter isn't in the signature. People
1934             # misuse this to declare other variables which should really be in a
1935             # PREINIT section:
1936             #
1937             # int
1938             # foo(a)
1939             # int a
1940             # int b = 0
1941             #
1942             # The '= 0' will be interpreted as a local typemap entry, so $arg etc
1943             # will be populated and the "typemap" evalled, So $num is undef, but we
1944             # shouldn't emit a warning when generating "ST(N-1)".
1945             #
1946             sub ST {
1947 8     8 0 22 my ($self, $num) = @_;
1948 8 100       38 return "ST(" . ($num-1) . ")" if defined $num;
1949 2         14 return '/* not a parameter */';
1950             }
1951              
1952              
1953             # INPUT_handler(): handle an explicit INPUT: block, or any implicit INPUT
1954             # block which can follow an xsub signature or CASE keyword.
1955              
1956             sub INPUT_handler {
1957             my XS::Install::FrozenShit::ParseXS $self = shift;
1958             $_ = shift;
1959              
1960             # In this loop: process each line until the next keyword or end of
1961             # paragraph.
1962              
1963             for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
1964             # treat NOT_IMPLEMENTED_YET as another block separator, in addition to
1965             # $BLOCK_regexp.
1966             last if /^\s*NOT_IMPLEMENTED_YET/;
1967             next unless /\S/; # skip blank lines
1968              
1969             trim_whitespace($_);
1970             my $ln = $_; # keep original line for error messages
1971              
1972             # remove any trailing semicolon, except for initialisations
1973             s/\s*;$//g unless /[=;+].*\S/;
1974              
1975             # Extract optional initialisation code (which overrides the
1976             # normal typemap), such as 'int foo = ($type)SvIV($arg)'
1977             my $var_init = '';
1978             my $init_op;
1979             ($init_op, $var_init) = ($1, $2) if s/\s* ([=;+]) \s* (.*) $//xs;
1980              
1981             s/\s+/ /g;
1982              
1983             # Split 'char * &foo' into ('char *', '&', 'foo')
1984             # skip to next INPUT line if not valid.
1985             #
1986             # Note that this pattern has a very liberal sense of what is "valid",
1987             # since we don't fully parse C types. For example:
1988             #
1989             # int foo(a)
1990             # int a XYZ
1991             #
1992             # would be interpreted as an "alien" (i.e. not in the signature)
1993             # variable called "XYZ", with a type of "int a". And because it's
1994             # alien the initialiser is skipped, so 'int a' is never looked up in
1995             # a typemap, so we don't detect anything wrong. Later on, the C
1996             # compiler is likely to trip over on the emitted declaration
1997             # however:
1998             # int a XYZ;
1999              
2000             my ($var_type, $var_addr, $var_name) =
2001             /^
2002             ( .*? [^&\s] ) # type
2003             \s*
2004             (\&?) # addr
2005             \s* \b
2006             (\w+ | length\(\w+\)) # name or length(name)
2007             $
2008             /xs
2009             or $self->blurt("Error: invalid parameter declaration '$ln'"), next;
2010              
2011             # length(s) is only allowed in the XSUB's signature.
2012             if ($var_name =~ /^length\((\w+)\)$/) {
2013             $self->blurt("Error: length() not permitted in INPUT section");
2014             next;
2015             }
2016              
2017             my ($var_num, $is_alien);
2018              
2019             my XS::Install::FrozenShit::ParseXS::Node::Param $param
2020             = $self->{xsub_sig}{names}{$var_name};
2021              
2022              
2023             if (defined $param) {
2024             # The var appeared in the signature too.
2025              
2026             # Check for duplicate definitions of a particular parameter name.
2027             # This can be either because it has appeared in multiple INPUT
2028             # lines, or because the type was already defined in the signature,
2029             # and thus shouldn't be defined again. The exception to this are
2030             # synthetic params like THIS, which are assigned a provisional type
2031             # which can be overridden.
2032             if ( $param->{in_input}
2033             or (!$param->{is_synthetic} and defined $param->{type})
2034             ) {
2035             $self->blurt(
2036             "Error: duplicate definition of parameter '$var_name' ignored");
2037             next;
2038             }
2039              
2040             if ($var_name eq 'RETVAL' and $param->{is_synthetic}) {
2041             # Convert a synthetic RETVAL into a real parameter
2042             delete $param->{is_synthetic};
2043             delete $param->{no_init};
2044             if (! defined $param->{arg_num}) {
2045             # if has arg_num, RETVAL has appeared in signature but with no
2046             # type, and has already been moved to the correct position;
2047             # otherwise, it's an alien var that didn't appear in the
2048             # signature; move to the correct position.
2049             @{$self->{xsub_sig}{params}} =
2050             grep $_ != $param, @{$self->{xsub_sig}{params}};
2051             push @{$self->{xsub_sig}{params}}, $param;
2052             $is_alien = 1;
2053             $param->{is_alien} = 1;
2054             }
2055             }
2056              
2057             $param->{in_input} = 1;
2058             $var_num = $param->{arg_num};
2059             }
2060             else {
2061             # The var is in an INPUT line, but not in signature. Treat it as a
2062             # general var declaration (which really should have been in a
2063             # PREINIT section). Legal but nasty: flag is as 'alien'
2064             $is_alien = 1;
2065             $param = XS::Install::FrozenShit::ParseXS::Node::Param->new({
2066             var => $var_name,
2067             is_alien => 1,
2068             });
2069              
2070             push @{$self->{xsub_sig}{params}}, $param;
2071             $self->{xsub_sig}{names}{$var_name} = $param;
2072             }
2073              
2074             # Parse the initialisation part of the INPUT line (if any)
2075              
2076             my ($init, $defer);
2077             my $no_init = $param->{no_init}; # may have had OUT in signature
2078              
2079             if (!$no_init && defined $init_op) {
2080             # Emit the init code based on overridden $var_init, which was
2081             # preceded by /[=;+]/ which has been extracted into $init_op
2082              
2083             if ( $init_op =~ /^[=;]$/
2084             and $var_init =~ /^NO_INIT\s*;?\s*$/
2085             ) {
2086             # NO_INIT: skip initialisation
2087             $no_init = 1;
2088             }
2089             elsif ($init_op eq '=') {
2090             # Overridden typemap, such as '= ($type)SvUV($arg)'
2091             $var_init =~ s/;\s*$//;
2092             $init = $var_init,
2093             }
2094             else {
2095             # "; extra code" or "+ extra code" :
2096             # append the extra code (after passing through eval) after all the
2097             # INPUT and PREINIT blocks have been processed, indirectly using
2098             # the $self->{xsub_deferred_code_lines} mechanism.
2099             # In addition, for '+', also generate the normal initialisation
2100             # code from the standard typemap - assuming that it's a real
2101             # parameter that appears in the signature as well as the INPUT
2102             # line.
2103             $no_init = !($init_op eq '+' && !$is_alien);
2104             # But in either case, add the deferred code
2105             $defer = $var_init;
2106             }
2107             }
2108             else {
2109             # no initialiser: emit var and init code based on typemap entry,
2110             # unless: it's alien (so no stack arg to bind to it)
2111             $no_init = 1 if $is_alien;
2112             }
2113              
2114             %$param = (
2115             %$param,
2116             type => $var_type,
2117             arg_num => $var_num,
2118             var => $var_name,
2119             defer => $defer,
2120             init => $init,
2121             init_op => $init_op,
2122             no_init => $no_init,
2123             is_addr => !!$var_addr,
2124             );
2125              
2126             $param->check($self)
2127             or next;
2128              
2129             # Emit "type var" declaration and possibly various forms of
2130             # initialiser code.
2131              
2132             # Synthetic params like THIS will be emitted later - they
2133             # are treated like ANSI params, except the type can overridden
2134             # within an INPUT statement
2135             next if $param->{is_synthetic};
2136              
2137             $param->as_code($self);
2138              
2139             } # foreach line in INPUT block
2140             }
2141              
2142              
2143             # Process the lines following the OUTPUT: keyword.
2144              
2145             sub OUTPUT_handler {
2146 2     2 0 5 my XS::Install::FrozenShit::ParseXS $self = shift;
2147              
2148 2         5 $_ = shift;
2149              
2150             # In this loop: process each line until the next keyword or end of
2151             # paragraph
2152              
2153 2         218 for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  4         38  
2154 4 100       24 next unless /\S/; # skip blank lines
2155              
2156 2 50       8 if (/^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) {
2157 0 0       0 $self->{xsub_SETMAGIC_state} = ($1 eq "ENABLE" ? 1 : 0);
2158 0         0 next;
2159             }
2160              
2161             # Expect lines of the two forms
2162             # SomeVar
2163             # SomeVar sv_setsv(....);
2164             #
2165 2         18 my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s;
2166              
2167             my XS::Install::FrozenShit::ParseXS::Node::Param $param =
2168 2         10 $self->{xsub_sig}{names}{$outarg};
2169              
2170 2 50 33     19 if ($param && $param->{in_output}) {
2171 0         0 $self->blurt("Error: duplicate OUTPUT parameter '$outarg' ignored");
2172 0         0 next;
2173             }
2174              
2175 2 50 33     16 if ($outarg eq "RETVAL" and $self->{xsub_seen_NO_OUTPUT}) {
2176 0         0 $self->blurt("Error: can't use RETVAL in OUTPUT when NO_OUTPUT declared");
2177 0         0 next;
2178             }
2179              
2180 2 50 33     19 if ( !$param # no such param or, for RETVAL, RETVAL was void
      33        
2181             # not bound to an arg which can be updated
2182             or $outarg ne "RETVAL" && !$param->{arg_num})
2183             {
2184 0         0 $self->blurt("Error: OUTPUT $outarg not a parameter");
2185 0         0 next;
2186             }
2187              
2188              
2189 2         6 $param->{in_output} = 1;
2190             $param->{do_setmagic} = $outarg eq 'RETVAL'
2191             ? 0 # RETVAL never needs magic setting
2192 2 50       10 : $self->{xsub_SETMAGIC_state};
2193 2 50       6 $param->{output_code} = $outcode if length $outcode;
2194              
2195 2 50       6 if ($outarg eq 'RETVAL') {
2196             # Postpone processing the RETVAL line to last (it's left to the
2197             # caller to finish).
2198 2         6 next;
2199             }
2200              
2201 0         0 $param->as_output_code($self);
2202             } # foreach line in OUTPUT block
2203             }
2204              
2205              
2206             # Set $sig->{auto_function_sig_override} to the concatenation of all
2207             # the following lines (including $_).
2208              
2209             sub C_ARGS_handler {
2210 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2211 0         0 $_ = shift;
2212 0         0 my $in = $self->merge_section();
2213              
2214 0         0 trim_whitespace($in);
2215 0         0 $self->{xsub_sig}{auto_function_sig_override} = $in;
2216             }
2217              
2218              
2219             # Concatenate the following lines (including $_), then split into
2220             # one or two macros names.
2221              
2222             sub INTERFACE_MACRO_handler {
2223 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2224 0         0 $_ = shift;
2225 0         0 my $in = $self->merge_section();
2226              
2227 0         0 trim_whitespace($in);
2228 0 0       0 if ($in =~ /\s/) { # two
2229             ($self->{xsub_interface_macro}, $self->{xsub_interface_macro_set})
2230 0         0 = split ' ', $in;
2231             }
2232             else {
2233 0         0 $self->{xsub_interface_macro} = $in;
2234 0         0 $self->{xsub_interface_macro_set} = 'UNKNOWN_CVT'; # catch later
2235             }
2236 0         0 $self->{xsub_seen_INTERFACE_or_MACRO} = 1; # local
2237 0         0 $self->{seen_INTERFACE_or_MACRO} = 1; # global
2238             }
2239              
2240              
2241             sub INTERFACE_handler {
2242 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2243 0         0 $_ = shift;
2244 0         0 my $in = $self->merge_section();
2245              
2246 0         0 trim_whitespace($in);
2247              
2248 0         0 foreach (split /[\s,]+/, $in) {
2249 0         0 my $iface_name = $_;
2250 0         0 $iface_name =~ s/^$self->{PREFIX_pattern}//;
2251 0         0 $self->{xsub_map_interface_name_short_to_original}->{$iface_name} = $_;
2252             }
2253 0         0 print Q(<<"EOF");
2254             | XSFUNCTION = $self->{xsub_interface_macro}($self->{xsub_return_type},cv,XSANY.any_dptr);
2255             EOF
2256 0         0 $self->{xsub_seen_INTERFACE_or_MACRO} = 1; # local
2257 0         0 $self->{seen_INTERFACE_or_MACRO} = 1; # global
2258             }
2259              
2260              
2261             sub CLEANUP_handler {
2262 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2263 0         0 $self->print_section();
2264             }
2265              
2266              
2267             sub PREINIT_handler {
2268 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2269 0         0 $self->print_section();
2270             }
2271              
2272              
2273             sub POSTCALL_handler {
2274 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2275 0         0 $self->print_section();
2276             }
2277              
2278              
2279             sub INIT_handler {
2280 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2281 0         0 $self->print_section();
2282             }
2283              
2284              
2285             # Process a line from an ALIAS: block
2286             #
2287             # Each line can have zero or more definitions, separated by white space.
2288             # Each definition is of one of the forms:
2289             #
2290             # name = value
2291             # name => other_name
2292             #
2293             # where 'value' is a positive integer (or C macro) and the names are
2294             # simple or qualified perl function names. E.g.
2295             #
2296             # foo = 1 Bar::foo = 2 Bar::baz => Bar::foo
2297             #
2298             # Updates:
2299             # $self->{xsub_map_alias_name_to_value}->{$alias} = $value;
2300             # $self->{xsub_map_alias_value_to_name_seen_hash}->{$value}{$alias}++;
2301              
2302             sub get_aliases {
2303 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2304 0         0 my ($line) = @_;
2305 0         0 my ($orig) = $line;
2306              
2307             # we use this later for symbolic aliases
2308 0         0 my $fname = $self->{PACKAGE_class} . $self->{xsub_func_name};
2309              
2310 0         0 while ($line =~ s/^\s*([\w:]+)\s*=(>?)\s*([\w:]+)\s*//) {
2311 0         0 my ($alias, $is_symbolic, $value) = ($1, $2, $3);
2312 0         0 my $orig_alias = $alias;
2313              
2314 0 0 0     0 blurt( $self, "Error: In alias definition for '$alias' the value may not"
2315             . " contain ':' unless it is symbolic.")
2316             if !$is_symbolic and $value=~/:/;
2317              
2318             # check for optional package definition in the alias
2319 0 0       0 $alias = $self->{PACKAGE_class} . $alias if $alias !~ /::/;
2320              
2321 0 0       0 if ($is_symbolic) {
2322 0         0 my $orig_value = $value;
2323 0 0       0 $value = $self->{PACKAGE_class} . $value if $value !~ /::/;
2324 0 0       0 if (defined $self->{xsub_map_alias_name_to_value}->{$value}) {
    0          
2325 0         0 $value = $self->{xsub_map_alias_name_to_value}->{$value};
2326             } elsif ($value eq $fname) {
2327 0         0 $value = 0;
2328             } else {
2329 0         0 blurt( $self, "Error: Unknown alias '$value' in symbolic definition for '$orig_alias'");
2330             }
2331             }
2332              
2333             # check for duplicate alias name & duplicate value
2334 0         0 my $prev_value = $self->{xsub_map_alias_name_to_value}->{$alias};
2335 0 0       0 if (defined $prev_value) {
2336 0 0       0 if ($prev_value eq $value) {
2337 0         0 Warn( $self, "Warning: Ignoring duplicate alias '$orig_alias'")
2338             } else {
2339 0         0 Warn( $self, "Warning: Conflicting duplicate alias '$orig_alias'"
2340             . " changes definition from '$prev_value' to '$value'");
2341 0         0 delete $self->{xsub_map_alias_value_to_name_seen_hash}->{$prev_value}{$alias};
2342             }
2343             }
2344              
2345             # Check and see if this alias results in two aliases having the same
2346             # value, we only check non-symbolic definitions as the whole point of
2347             # symbolic definitions is to say we want to duplicate the value and
2348             # it is NOT a mistake.
2349 0 0       0 unless ($is_symbolic) {
2350 0 0       0 my @keys= sort keys %{$self->{xsub_map_alias_value_to_name_seen_hash}->{$value}||{}};
  0         0  
2351             # deal with an alias of 0, which might not be in the aliases
2352             # dataset yet as 0 is the default for the base function ($fname)
2353             push @keys, $fname
2354 0 0 0     0 if $value eq "0" and !defined $self->{xsub_map_alias_name_to_value}{$fname};
2355 0 0 0     0 if (@keys and $self->{config_author_warnings}) {
2356             # We do not warn about value collisions unless author_warnings
2357             # are enabled. They aren't helpful to a module consumer, only
2358             # the module author.
2359 0         0 @keys= map { "'$_'" }
2360 0         0 map { my $copy= $_;
  0         0  
2361 0         0 $copy=~s/^$self->{PACKAGE_class}//;
2362 0         0 $copy
2363             } @keys;
2364             WarnHint( $self,
2365             "Warning: Aliases '$orig_alias' and "
2366             . join(", ", @keys)
2367             . " have identical values of $value"
2368             . ( $value eq "0"
2369             ? " - the base function"
2370             : "" ),
2371 0 0       0 !$self->{xsub_alias_clash_hinted}++
    0          
2372             ? "If this is deliberate use a symbolic alias instead."
2373             : undef
2374             );
2375             }
2376             }
2377              
2378 0         0 $self->{xsub_map_alias_name_to_value}->{$alias} = $value;
2379 0         0 $self->{xsub_map_alias_value_to_name_seen_hash}->{$value}{$alias}++;
2380             }
2381              
2382 0 0       0 blurt( $self, "Error: Cannot parse ALIAS definitions from '$orig'")
2383             if $line;
2384             }
2385              
2386              
2387             # Read each lines's worth of attributes into a string that is pushed
2388             # to the {xsub_attributes} array. Note that it doesn't matter that multiple
2389             # space-separated attributes on the same line are stored as a single
2390             # string; later, all the attribute lines are joined together into a single
2391             # string to pass to apply_attrs_string().
2392              
2393             sub ATTRS_handler {
2394 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2395 0         0 $_ = shift;
2396              
2397 0         0 for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  0         0  
2398 0 0       0 next unless /\S/;
2399 0         0 trim_whitespace($_);
2400 0         0 push @{ $self->{xsub_attributes} }, $_;
  0         0  
2401             }
2402             }
2403              
2404              
2405             # Process the line(s) following the ALIAS: keyword
2406              
2407             sub ALIAS_handler {
2408 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2409 0         0 $_ = shift;
2410              
2411             # Consume and process alias lines until the next directive.
2412 0         0 for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  0         0  
2413 0 0       0 next unless /\S/;
2414 0         0 trim_whitespace($_);
2415 0 0       0 $self->get_aliases($_) if $_;
2416             }
2417             }
2418              
2419              
2420             # Add all overload method names, like 'cmp', '<=>', etc, (possibly
2421             # multiple ones per line) until the next keyword line, as 'seen' keys to
2422             # the $self->{xsub_map_overload_name_to_seen} hash.
2423              
2424             sub OVERLOAD_handler {
2425 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2426 0         0 $_ = shift;
2427              
2428 0         0 for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  0         0  
2429 0 0       0 next unless /\S/;
2430 0         0 trim_whitespace($_);
2431 0         0 while ( s/^\s*([\w:"\\)\+\-\*\/\%\<\>\.\&\|\^\!\~\{\}\=]+)\s*//) {
2432 0         0 $self->{xsub_map_overload_name_to_seen}->{$1} = 1;
2433             }
2434             }
2435             }
2436              
2437              
2438             sub FALLBACK_handler {
2439 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2440 0         0 my ($setting) = @_;
2441              
2442             # the rest of the current line should contain either TRUE,
2443             # FALSE or UNDEF
2444              
2445 0         0 trim_whitespace($setting);
2446 0         0 $setting = uc($setting);
2447              
2448 0         0 my %map = (
2449             TRUE => "&PL_sv_yes", 1 => "&PL_sv_yes",
2450             FALSE => "&PL_sv_no", 0 => "&PL_sv_no",
2451             UNDEF => "&PL_sv_undef",
2452             );
2453              
2454             # check for valid FALLBACK value
2455 0 0       0 $self->death("Error: FALLBACK: TRUE/FALSE/UNDEF") unless exists $map{$setting};
2456              
2457             $self->{map_package_to_fallback_string}->{$self->{PACKAGE_name}}
2458 0         0 = $map{$setting};
2459             }
2460              
2461              
2462             sub REQUIRE_handler {
2463 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2464             # the rest of the current line should contain a version number
2465 0         0 my ($ver) = @_;
2466              
2467 0         0 trim_whitespace($ver);
2468              
2469 0 0       0 $self->death("Error: REQUIRE expects a version number")
2470             unless $ver;
2471              
2472             # check that the version number is of the form n.n
2473 0 0       0 $self->death("Error: REQUIRE: expected a number, got '$ver'")
2474             unless $ver =~ /^\d+(\.\d*)?/;
2475              
2476 0 0       0 $self->death("Error: xsubpp $ver (or better) required--this is only $VERSION.")
2477             unless $VERSION >= $ver;
2478             }
2479              
2480              
2481             sub VERSIONCHECK_handler {
2482 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2483             # the rest of the current line should contain either ENABLE or
2484             # DISABLE
2485 0         0 my ($setting) = @_;
2486              
2487 0         0 trim_whitespace($setting);
2488              
2489             # check for ENABLE/DISABLE
2490 0 0       0 $self->death("Error: VERSIONCHECK: ENABLE/DISABLE")
2491             unless $setting =~ /^(ENABLE|DISABLE)/i;
2492              
2493 0 0       0 $self->{VERSIONCHECK_value} = 1 if $1 eq 'ENABLE';
2494 0 0       0 $self->{VERSIONCHECK_value} = 0 if $1 eq 'DISABLE';
2495              
2496             }
2497              
2498              
2499             # PROTOTYPE: Process one or more lines of the form
2500             # DISABLE
2501             # ENABLE
2502             # $$@ # a literal prototype
2503             #
2504             #
2505             # It's probably a design flaw that more than one entry can be processed.
2506              
2507             sub PROTOTYPE_handler {
2508 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2509 0         0 $_ = shift;
2510              
2511 0         0 my $specified;
2512              
2513             $self->death("Error: Only 1 PROTOTYPE definition allowed per xsub")
2514 0 0       0 if $self->{xsub_seen_PROTOTYPE}++;
2515              
2516 0         0 for (; !/^$BLOCK_regexp/o; $_ = shift(@{ $self->{line} })) {
  0         0  
2517 0 0       0 next unless /\S/;
2518 0         0 $specified = 1;
2519 0         0 trim_whitespace($_);
2520 0 0       0 if ($_ eq 'DISABLE') {
    0          
2521 0         0 $self->{xsub_prototype} = 0;
2522             }
2523             elsif ($_ eq 'ENABLE') {
2524 0         0 $self->{xsub_prototype} = 1;
2525             }
2526             else {
2527             # remove any whitespace
2528 0         0 s/\s+//g;
2529 0 0       0 $self->death("Error: Invalid prototype '$_'")
2530             unless valid_proto_string($_);
2531 0         0 $self->{xsub_prototype} = C_string($_);
2532             }
2533             }
2534              
2535             # If no prototype specified, then assume empty prototype ""
2536 0 0       0 $self->{xsub_prototype} = 2 unless $specified;
2537              
2538 0         0 $self->{proto_behaviour_specified} = 1;
2539             }
2540              
2541              
2542             # Set $self->{xsub_SCOPE_enabled} to a boolean value based on DISABLE/ENABLE.
2543              
2544             sub SCOPE_handler {
2545 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2546             # Rest of line should be either ENABLE or DISABLE
2547 0         0 my ($setting) = @_;
2548              
2549             $self->death("Error: Only 1 SCOPE declaration allowed per xsub")
2550 0 0       0 if $self->{xsub_seen_SCOPE}++;
2551              
2552 0         0 trim_whitespace($setting);
2553 0 0       0 $self->death("Error: SCOPE: ENABLE/DISABLE")
2554             unless $setting =~ /^(ENABLE|DISABLE)\b/i;
2555 0         0 $self->{xsub_SCOPE_enabled} = ( uc($1) eq 'ENABLE' );
2556             }
2557              
2558              
2559             sub PROTOTYPES_handler {
2560 2     2 0 5 my XS::Install::FrozenShit::ParseXS $self = shift;
2561             # the rest of the current line should contain either ENABLE or
2562             # DISABLE
2563 2         5 my ($setting) = @_;
2564              
2565 2         14 trim_whitespace($setting);
2566              
2567             # check for ENABLE/DISABLE
2568 2 50       24 $self->death("Error: PROTOTYPES: ENABLE/DISABLE")
2569             unless $setting =~ /^(ENABLE|DISABLE)/i;
2570              
2571 2 50       9 $self->{PROTOTYPES_value} = 1 if $1 eq 'ENABLE';
2572 2 50       14 $self->{PROTOTYPES_value} = 0 if $1 eq 'DISABLE';
2573 2         11 $self->{proto_behaviour_specified} = 1;
2574             }
2575              
2576              
2577             sub EXPORT_XSUB_SYMBOLS_handler {
2578 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2579             # the rest of the current line should contain either ENABLE or
2580             # DISABLE
2581 0         0 my ($setting) = @_;
2582              
2583 0         0 trim_whitespace($setting);
2584              
2585             # check for ENABLE/DISABLE
2586 0 0       0 $self->death("Error: EXPORT_XSUB_SYMBOLS: ENABLE/DISABLE")
2587             unless $setting =~ /^(ENABLE|DISABLE)/i;
2588              
2589 0 0       0 my $xs_impl = $1 eq 'ENABLE' ? 'XS_EXTERNAL' : 'XS_INTERNAL';
2590              
2591 0         0 print Q(<<"EOF");
2592             |#undef XS_EUPXS
2593             |#if defined(PERL_EUPXS_ALWAYS_EXPORT)
2594             |# define XS_EUPXS(name) XS_EXTERNAL(name)
2595             |#elif defined(PERL_EUPXS_NEVER_EXPORT)
2596             |# define XS_EUPXS(name) XS_INTERNAL(name)
2597             |#else
2598             |# define XS_EUPXS(name) $xs_impl(name)
2599             |#endif
2600             EOF
2601             }
2602              
2603              
2604             # Push an entry on the @{ $self->{XS_parse_stack} } array containing the
2605             # current file state, in preparation for INCLUDEing a new file. (Note that
2606             # it doesn't handle type => 'if' style entries, only file entries.)
2607              
2608             sub push_parse_stack {
2609 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2610 0         0 my %args = @_;
2611             # Save the current file context.
2612 0         0 push(@{ $self->{XS_parse_stack} }, {
2613             type => 'file',
2614             LastLine => $self->{lastline},
2615             LastLineNo => $self->{lastline_no},
2616             Line => $self->{line},
2617             LineNo => $self->{line_no},
2618             Filename => $self->{in_filename},
2619             Filepathname => $self->{in_pathname},
2620             Handle => $self->{in_fh},
2621 0         0 IsPipe => scalar($self->{in_filename} =~ /\|\s*$/),
2622             %args,
2623             });
2624              
2625             }
2626              
2627              
2628             sub INCLUDE_handler {
2629 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2630 0         0 $_ = shift;
2631             # the rest of the current line should contain a valid filename
2632              
2633 0         0 trim_whitespace($_);
2634              
2635 0 0       0 $self->death("INCLUDE: filename missing")
2636             unless $_;
2637              
2638 0 0       0 $self->death("INCLUDE: output pipe is illegal")
2639             if /^\s*\|/;
2640              
2641             # simple minded recursion detector
2642             $self->death("INCLUDE loop detected")
2643 0 0       0 if $self->{IncludedFiles}->{$_};
2644              
2645 0 0       0 ++$self->{IncludedFiles}->{$_} unless /\|\s*$/;
2646              
2647 0 0 0     0 if (/\|\s*$/ && /^\s*perl\s/) {
2648 0         0 Warn( $self, "The INCLUDE directive with a command is discouraged." .
2649             " Use INCLUDE_COMMAND instead! In particular using 'perl'" .
2650             " in an 'INCLUDE: ... |' directive is not guaranteed to pick" .
2651             " up the correct perl. The INCLUDE_COMMAND directive allows" .
2652             " the use of \$^X as the currently running perl, see" .
2653             " 'perldoc perlxs' for details.");
2654             }
2655              
2656 0         0 $self->push_parse_stack();
2657              
2658 0         0 $self->{in_fh} = Symbol::gensym();
2659              
2660             # open the new file
2661 0 0       0 open($self->{in_fh}, $_) or $self->death("Cannot open '$_': $!");
2662              
2663 0         0 print Q(<<"EOF");
2664             |
2665             |/* INCLUDE: Including '$_' from '$self->{in_filename}' */
2666             |
2667             EOF
2668              
2669 0         0 $self->{in_filename} = $_;
2670             $self->{in_pathname} = ( $^O =~ /^mswin/i )
2671             # See CPAN RT #61908: gcc doesn't like
2672             # backslashes on win32?
2673             ? qq($self->{dir}/$self->{in_filename})
2674 0 0       0 : File::Spec->catfile($self->{dir}, $self->{in_filename});
2675              
2676             # Prime the pump by reading the first
2677             # non-blank line
2678              
2679             # skip leading blank lines
2680 0         0 while (readline($self->{in_fh})) {
2681 0 0       0 last unless /^\s*$/;
2682             }
2683              
2684 0         0 $self->{lastline} = $_;
2685 0         0 $self->{lastline_no} = $.;
2686             }
2687              
2688              
2689             # Quote a command-line to be suitable for VMS
2690              
2691             sub QuoteArgs {
2692 0     0 0 0 my $cmd = shift;
2693 0         0 my @args = split /\s+/, $cmd;
2694 0         0 $cmd = shift @args;
2695 0         0 for (@args) {
2696 0 0 0     0 $_ = q(").$_.q(") if !/^\"/ && length($_) > 0;
2697             }
2698 0         0 return join (' ', ($cmd, @args));
2699             }
2700              
2701              
2702             # _safe_quote(): quote an executable pathname which includes spaces.
2703             #
2704             # This code was copied from CPAN::HandleConfig::safe_quote:
2705             # that has doc saying leave if start/finish with same quote, but no code
2706             # given text, will conditionally quote it to protect from shell
2707              
2708             {
2709             my ($quote, $use_quote) = $^O eq 'MSWin32'
2710             ? (q{"}, q{"})
2711             : (q{"'}, q{'});
2712             sub _safe_quote {
2713 0     0   0 my ($self, $command) = @_;
2714             # Set up quote/default quote
2715 0 0 0     0 if (defined($command)
      0        
2716             and $command =~ /\s/
2717             and $command !~ /[$quote]/) {
2718 0         0 return qq{$use_quote$command$use_quote}
2719             }
2720 0         0 return $command;
2721             }
2722             }
2723              
2724              
2725             sub INCLUDE_COMMAND_handler {
2726 0     0 0 0 my XS::Install::FrozenShit::ParseXS $self = shift;
2727 0         0 $_ = shift;
2728             # the rest of the current line should contain a valid command
2729              
2730 0         0 trim_whitespace($_);
2731              
2732 0 0       0 $_ = QuoteArgs($_) if $^O eq 'VMS';
2733              
2734 0 0       0 $self->death("INCLUDE_COMMAND: command missing")
2735             unless $_;
2736              
2737 0 0 0     0 $self->death("INCLUDE_COMMAND: pipes are illegal")
2738             if /^\s*\|/ or /\|\s*$/;
2739              
2740 0         0 $self->push_parse_stack( IsPipe => 1 );
2741              
2742 0         0 $self->{in_fh} = Symbol::gensym();
2743              
2744             # If $^X is used in INCLUDE_COMMAND, we know it's supposed to be
2745             # the same perl interpreter as we're currently running
2746 0         0 my $X = $self->_safe_quote($^X); # quotes if has spaces
2747 0         0 s/^\s*\$\^X/$X/;
2748              
2749             # open the new file
2750 0 0       0 open ($self->{in_fh}, "-|", $_)
2751             or $self->death( $self, "Cannot run command '$_' to include its output: $!");
2752              
2753 0         0 print Q(<<"EOF");
2754             |
2755             |/* INCLUDE_COMMAND: Including output of '$_' from '$self->{in_filename}' */
2756             |
2757             EOF
2758              
2759 0         0 $self->{in_filename} = $_;
2760 0         0 $self->{in_pathname} = $self->{in_filename};
2761             #$self->{in_pathname} =~ s/\"/\\"/g; # Fails? See CPAN RT #53938: MinGW Broken after 2.21
2762 0         0 $self->{in_pathname} =~ s/\\/\\\\/g; # Works according to reporter of #53938
2763              
2764             # Prime the pump by reading the first
2765             # non-blank line
2766              
2767             # skip leading blank lines
2768 0         0 while (readline($self->{in_fh})) {
2769 0 0       0 last unless /^\s*$/;
2770             }
2771              
2772 0         0 $self->{lastline} = $_;
2773 0         0 $self->{lastline_no} = $.;
2774             }
2775              
2776              
2777             # Pop the type => 'file' entry off the top of the @{ $self->{XS_parse_stack} }
2778             # array following the end of processing an INCLUDEd file, and restore the
2779             # former state.
2780              
2781             sub PopFile {
2782 1     1 0 2 my XS::Install::FrozenShit::ParseXS $self = shift;
2783              
2784 1 50       31 return 0 unless $self->{XS_parse_stack}->[-1]{type} eq 'file';
2785              
2786 0         0 my $data = pop @{ $self->{XS_parse_stack} };
  0         0  
2787 0         0 my $ThisFile = $self->{in_filename};
2788 0         0 my $isPipe = $data->{IsPipe};
2789              
2790             --$self->{IncludedFiles}->{$self->{in_filename}}
2791 0 0       0 unless $isPipe;
2792              
2793 0         0 close $self->{in_fh};
2794              
2795 0         0 $self->{in_fh} = $data->{Handle};
2796             # $in_filename is the leafname, which for some reason is used for diagnostic
2797             # messages, whereas $in_pathname is the full pathname, and is used for
2798             # #line directives.
2799 0         0 $self->{in_filename} = $data->{Filename};
2800 0         0 $self->{in_pathname} = $data->{Filepathname};
2801 0         0 $self->{lastline} = $data->{LastLine};
2802 0         0 $self->{lastline_no} = $data->{LastLineNo};
2803 0         0 @{ $self->{line} } = @{ $data->{Line} };
  0         0  
  0         0  
2804 0         0 @{ $self->{line_no} } = @{ $data->{LineNo} };
  0         0  
  0         0  
2805              
2806 0 0 0     0 if ($isPipe and $? ) {
2807 0         0 --$self->{lastline_no};
2808 0         0 print STDERR "Error reading from pipe '$ThisFile': $! in $self->{in_filename}, line $self->{lastline_no}\n" ;
2809 0         0 exit 1;
2810             }
2811              
2812 0         0 print Q(<<"EOF");
2813             |
2814             |/* INCLUDE: Returning to '$self->{in_filename}' from '$ThisFile' */
2815             |
2816             EOF
2817              
2818 0         0 return 1;
2819             }
2820              
2821              
2822             # Unescape a string (typically a heredoc):
2823             # - strip leading ' |' (any number of leading spaces)
2824             # - and replace [[ and ]]
2825             # with { and }
2826             # so that text editors don't see a bare { or } when bouncing around doing
2827             # brace level matching.
2828              
2829             sub Q {
2830 32     32 0 100 my ($text) = @_;
2831 32         175 my @lines = split /^/, $text;
2832 32         55 my $first;
2833 32         73 for (@lines) {
2834 92 50       511 unless (s/^(\s*)\|//) {
2835 0         0 die "Internal error: no leading '|' in Q() string:\n$_\n";
2836             }
2837 92         236 my $pre = $1;
2838 92 50       219 die "Internal error: leading tab char in Q() string:\n$_\n"
2839             if $pre =~ /\t/;
2840              
2841 92 100       189 if (defined $first) {
2842 60 50       145 die "Internal error: leading indents in Q() string don't match:\n$_\n"
2843             if $pre ne $first;
2844             }
2845             else {
2846 32         70 $first = $pre;
2847             }
2848             }
2849 32         97 $text = join "", @lines;
2850              
2851 32         90 $text =~ s/\[\[/{/g;
2852 32         84 $text =~ s/\]\]/}/g;
2853 32         293 $text;
2854             }
2855              
2856              
2857             # Process "MODULE = Foo ..." lines and update global state accordingly
2858              
2859             sub _process_module_xs_line {
2860             my XS::Install::FrozenShit::ParseXS $self = shift;
2861             my ($module, $pkg, $prefix) = @_;
2862              
2863             ($self->{MODULE_cname} = $module) =~ s/\W/_/g;
2864              
2865             $self->{PACKAGE_name} = defined($pkg) ? $pkg : '';
2866             $self->{PREFIX_pattern} = quotemeta( defined($prefix) ? $prefix : '' );
2867              
2868             ($self->{PACKAGE_C_name} = $self->{PACKAGE_name}) =~ tr/:/_/;
2869              
2870             $self->{PACKAGE_class} = $self->{PACKAGE_name};
2871             $self->{PACKAGE_class} .= "::" if $self->{PACKAGE_class} ne "";
2872              
2873             $self->{lastline} = "";
2874             }
2875              
2876              
2877             # Skip any embedded POD sections, reading in lines from {in_fh} as necessary.
2878              
2879             sub _maybe_skip_pod {
2880 60     60   112 my XS::Install::FrozenShit::ParseXS $self = shift;
2881              
2882 60         185 while ($self->{lastline} =~ /^=/) {
2883 0         0 while ($self->{lastline} = readline($self->{in_fh})) {
2884 0 0       0 last if ($self->{lastline} =~ /^=cut\s*$/);
2885             }
2886 0 0       0 $self->death("Error: Unterminated pod") unless defined $self->{lastline};
2887 0         0 $self->{lastline} = readline($self->{in_fh});
2888 0         0 chomp $self->{lastline};
2889 0         0 $self->{lastline} =~ s/^\s+$//;
2890             }
2891             }
2892              
2893              
2894             # Strip out and parse embedded TYPEMAP blocks (which use a HEREdoc-alike
2895             # block syntax).
2896              
2897             sub _maybe_parse_typemap_block {
2898 60     60   151 my XS::Install::FrozenShit::ParseXS $self = shift;
2899              
2900             # This is special cased from the usual paragraph-handler logic
2901             # due to the HEREdoc-ish syntax.
2902 60 50       315 if ($self->{lastline} =~ /^TYPEMAP\s*:\s*<<\s*(?:(["'])(.+?)\1|([^\s'"]+?))\s*;?\s*$/)
2903             {
2904 0 0       0 my $end_marker = quotemeta(defined($1) ? $2 : $3);
2905              
2906             # Scan until we find $end_marker alone on a line.
2907 0         0 my @tmaplines;
2908 0         0 while (1) {
2909 0         0 $self->{lastline} = readline($self->{in_fh});
2910 0 0       0 $self->death("Error: Unterminated TYPEMAP section") if not defined $self->{lastline};
2911 0 0       0 last if $self->{lastline} =~ /^$end_marker\s*$/;
2912 0         0 push @tmaplines, $self->{lastline};
2913             }
2914              
2915             my $tmap = XS::Install::FrozenShit::Typemaps->new(
2916             string => join("", @tmaplines),
2917             lineno_offset => 1 + ($self->current_line_number() || 0),
2918             fake_filename => $self->{in_filename},
2919 0   0     0 );
2920 0         0 $self->{typemaps_object}->merge(typemap => $tmap, replace => 1);
2921              
2922 0         0 $self->{lastline} = "";
2923             }
2924             }
2925              
2926              
2927             # fetch_para(): private helper method for process_file().
2928             #
2929             # Read in all the lines associated with the next XSUB, or associated with
2930             # the next contiguous block of file-scoped XS or CPP directives.
2931             #
2932             # More precisely, read lines (and their line numbers) up to (but not
2933             # including) the start of the next XSUB or similar, into:
2934             #
2935             # @{ $self->{line} }
2936             # @{ $self->{line_no} }
2937             #
2938             # It assumes that $self->{lastline} contains the next line to process,
2939             # and that further lines can be read from $self->{in_fh} as necessary.
2940             #
2941             # Multiple lines which are read in that end in '\' are concatenated
2942             # together into a single line, whose line number is set to
2943             # their first line. The two characters '\' and '\n' are kept in the
2944             # concatenated string.
2945             #
2946             # On return, it leaves the first unprocessed line in $self->{lastline}:
2947             # typically the first line of the next XSUB. At EOF, lastline will be
2948             # left undef.
2949             #
2950             # In general, it stops just before the first line which matches /^\S/ and
2951             # which was preceded by a blank line. This line is often the start of the
2952             # next XSUB (but there is no guarantee of that).
2953             #
2954             # For example, given these lines:
2955             #
2956             # | ....
2957             # | stuff
2958             # | [blank line]
2959             # |PROTOTYPES: ENABLED
2960             # |#define FOO 1
2961             # |SCOPE: ENABLE
2962             # |#define BAR 1
2963             # | [blank line]
2964             # |int
2965             # |foo(...)
2966             # | ....
2967             #
2968             # then the first call will return everything up to 'stuff' inclusive
2969             # (perhaps it's the last line of an XSUB). The next call will return four
2970             # lines containing the XS directives and CPP definitions. The directives
2971             # are not interpreted or processed by this function; they're just returned
2972             # as unprocessed text for the caller to interpret. A third call will read
2973             # in the XSUB starting at 'int'.
2974             #
2975             # Note that fetch_para() knows almost nothing about C or XS syntax and
2976             # keywords, and just blindly reads in lines until it finds a suitable
2977             # place to break. It generally relies on the caller to handle most of the
2978             # syntax and semantics and error reporting. For example, the block of four
2979             # lines above from 'PROTOTYPES' onwards isn't valid XS, but is blindly
2980             # returned by fetch_para().
2981             #
2982             # It often returns zero lines - the caller will have to handle this.
2983             #
2984             # There are a few exceptions where certain lines starting in column 1
2985             # *are* interpreted by this function (and conversely where /\\$/ *isn't*
2986             # processed):
2987             #
2988             # POD: Discard all lines between /^='/../^=cut/, then continue.
2989             #
2990             # MODULE: If this appears as the first line, it is processed and
2991             # discarded, then line reading continues.
2992             #
2993             # TYPEMAP: Process a 'heredoc' typemap, discard all processed lines,
2994             # then continue.
2995             #
2996             # /^\s*#/ Discard such lines unless they look like a CPP directive,
2997             # on the assumption that they are code comments. Then, in
2998             # particular:
2999             #
3000             # #if etc: For anything which is part of a CPP conditional: if it
3001             # is external to the current chunk of code (e.g. an #endif
3002             # which isn't matched by an earlier #if/ifdef/ifndef within
3003             # the current chunk) then processing stops before that line.
3004             #
3005             # Nested if/elsif/else's etc within the chunk are passed
3006             # through and processing continues. An #if/ifdef/ifdef on the
3007             # first line is treated as external and is returned as a
3008             # single line.
3009             #
3010             # It is assumed the caller will handle any processing or
3011             # nesting of external conditionals.
3012             #
3013             # CPP directives (like #define) which aren't concerned with
3014             # conditions are just passed through.
3015             #
3016             # It removes any trailing blank lines from the list of returned lines.
3017              
3018              
3019             sub fetch_para {
3020             my XS::Install::FrozenShit::ParseXS $self = shift;
3021              
3022             # unmatched #if at EOF
3023             $self->death("Error: Unterminated '#if/#ifdef/#ifndef'")
3024             if !defined $self->{lastline} && $self->{XS_parse_stack}->[-1]{type} eq 'if';
3025              
3026             @{ $self->{line} } = ();
3027             @{ $self->{line_no} } = ();
3028             return $self->PopFile() if not defined $self->{lastline}; # EOF
3029              
3030             if ($self->{lastline} =~
3031             /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/)
3032             {
3033             $self->_process_module_xs_line($1, $2, $3);
3034             }
3035              
3036             # count how many #ifdef levels we see in this paragraph
3037             # decrementing when we see an endif. if we see an elsif
3038             # or endif without a corresponding #ifdef then we don't
3039             # consider it part of this paragraph.
3040             my $if_level = 0;
3041              
3042             for (;;) {
3043             $self->_maybe_skip_pod;
3044              
3045             $self->_maybe_parse_typemap_block;
3046              
3047             my $final;
3048              
3049             # Process this line unless it looks like a '#', comment
3050              
3051             if ($self->{lastline} !~ /^\s*#/ # not a CPP directive
3052             # CPP directives:
3053             # ANSI: if ifdef ifndef elif else endif define undef
3054             # line error pragma
3055             # gcc: warning include_next
3056             # obj-c: import
3057             # others: ident (gcc notes that some cpps have this one)
3058             || $self->{lastline} =~ /^\#[ \t]*
3059             (?:
3060             (?:if|ifn?def|elif|else|endif|elifn?def|
3061             define|undef|pragma|error|
3062             warning|line\s+\d+|ident)
3063             \b
3064             | (?:include(?:_next)?|import)
3065             \s* ["<] .* [>"]
3066             )
3067             /x
3068             )
3069             {
3070             # Blank line followed by char in column 1. Start of next XSUB?
3071             last if $self->{lastline} =~ /^\S/
3072             && @{ $self->{line} }
3073             && $self->{line}->[-1] eq "";
3074              
3075             # processes CPP conditionals
3076             if ($self->{lastline}
3077             =~/^#[ \t]*(if|ifn?def|elif|else|endif|elifn?def)\b/)
3078             {
3079             my $type = $1;
3080             if ($type =~ /^if/) { # if, ifdef, ifndef
3081             if (@{$self->{line}}) {
3082             # increment level
3083             $if_level++;
3084             } else {
3085             $final = 1;
3086             }
3087             } elsif ($type eq "endif") {
3088             if ($if_level) { # are we in an if that was started in this paragraph?
3089             $if_level--; # yep- so decrement to end this if block
3090             } else {
3091             $final = 1;
3092             }
3093             } elsif (!$if_level) {
3094             # not in an #ifdef from this paragraph, thus
3095             # this directive should not be part of this paragraph.
3096             $final = 1;
3097             }
3098             }
3099              
3100             if ($final and @{$self->{line}}) {
3101             return 1;
3102             }
3103              
3104             push(@{ $self->{line} }, $self->{lastline});
3105             push(@{ $self->{line_no} }, $self->{lastline_no});
3106             } # end of processing non-comment lines
3107              
3108             # Read next line and continuation lines
3109             last unless defined($self->{lastline} = readline($self->{in_fh}));
3110             $self->{lastline_no} = $.;
3111             my $tmp_line;
3112             $self->{lastline} .= $tmp_line
3113             while ($self->{lastline} =~ /\\$/ && defined($tmp_line = readline($self->{in_fh})));
3114              
3115             chomp $self->{lastline};
3116             $self->{lastline} =~ s/^\s+$//;
3117             if ($final) {
3118             last;
3119             }
3120             } # end for (;;)
3121              
3122             # Nuke trailing "line" entries until there's one that's not empty
3123             pop(@{ $self->{line} }), pop(@{ $self->{line_no} })
3124             while @{ $self->{line} } && $self->{line}->[-1] eq "";
3125              
3126             return 1;
3127             }
3128              
3129              
3130             # These two subs just delegate to a method in a clean package, where there
3131             # are as few lexical variables in scope as possible and the ones which are
3132             # accessible (such as $arg) are the ones documented to be available when
3133             # eval()ing (in double-quoted context) the initialiser on an INPUT or
3134             # OUTPUT line such as 'int foo = SvIV($arg)'
3135              
3136             sub eval_output_typemap_code {
3137 2     2 0 4 my XS::Install::FrozenShit::ParseXS $self = shift;
3138 2         6 my ($code, $other) = @_;
3139 2         11 return XS::Install::FrozenShit::ParseXS::Eval::eval_output_typemap_code($self, $code, $other);
3140             }
3141              
3142             sub eval_input_typemap_code {
3143 4     4 0 11 my XS::Install::FrozenShit::ParseXS $self = shift;
3144 4         10 my ($code, $other) = @_;
3145 4         25 return XS::Install::FrozenShit::ParseXS::Eval::eval_input_typemap_code($self, $code, $other);
3146             }
3147              
3148             1;
3149              
3150             # vim: ts=2 sw=2 et: