File Coverage

blib/lib/ExtUtils/ParseXS.pm
Criterion Covered Total %
statement 208 221 94.1
branch 69 90 76.6
condition 18 28 64.2
subroutine 21 22 95.4
pod 3 9 33.3
total 319 370 86.2


line stmt bran cond sub pod time code
1             package ExtUtils::ParseXS;
2 19     19   1852694 use strict;
  19         37  
  19         787  
3 19     19   140 use warnings;
  19         57  
  19         1579  
4              
5             # Note that the pod for this module is separate in ParseXS.pod.
6             #
7             # This module provides the guts for the xsubpp XS-to-C translator utility.
8             # By having it as a module separate from xsubpp, it makes it more efficient
9             # to be used for example by Module::Build without having to shell out to
10             # xsubpp. It also makes it easier to test the individual components.
11             #
12             # The main function in this file is process_file(), which oversees the
13             # whole job of reading in a .xs file, parsing it into an Abstract Syntax
14             # Tree (AST), then walking the tree to generate C code and output it to a
15             # .c file.
16             #
17             # Most of the actual logic is in the ExtUtils::ParseXS::Node::FOO
18             # subclasses, which hold the nodes of the AST. The parse() methods of
19             # these subclasses do a top-down recursive-descent parse of the input
20             # file, building the AST; while the as_code() methods walk the tree,
21             # emitting C code.
22             #
23             # The main parsing loop is contained in the Node::cpp_scope::parse()
24             # method, which in turn relies on fetch_para() to read a paragraph's worth
25             # of lines from the input while stripping out any POD or XS comments. It
26             # is fetch_para() which decides where an XSUB, BOOT or TYPEMAP block ends,
27             # mainly by using a blank line followed by character in column 1 as the
28             # delimiter (except for TYPEMAP, where it looks for the matching EOF-style
29             # string).
30             #
31             # The remainder of this file mainly consists of helper functions and
32             # functions to help with outputting stuff.
33             #
34             # Of particular note is the Q() function, which is typically used to
35             # process escaped ("quoted") heredoc text of C code fragments to be
36             # output. It strips an initial '|' preceded by optional spaces, and
37             # converts [[ and ]] to { and }. This allows unmatched braces to be
38             # included in the C fragments without confusing text editors.
39             #
40             # Some other tasks have been moved out to various .pm files under ParseXS:
41             #
42             # ParseXS::CountLines provides tied handle methods for automatically
43             # injecting '#line' directives into output.
44             #
45             # ParseXS::Eval provides methods for evalling typemaps within
46             # an environment where suitable vars like $var and
47             # $arg have been up, but with nothing else in scope.
48             #
49             # ParseXS::Node This and its subclasses provide the nodes
50             # which make up the Abstract Syntax Tree (AST)
51             # generated by the parser.
52             #
53             # ParseXS::Constants defines a few constants used here, such the regex
54             # patterns used to detect a new XS keyword.
55             #
56             # ParseXS::Utilities provides various private utility methods for
57             # the use of ParseXS, such as analysing C
58             # pre-processor directives.
59             #
60             # Note: when making changes to this module (or to its children), you
61             # can make use of the author/mksnapshot.pl tool to capture before and
62             # after snapshots of all .c files generated from .xs files (e.g. all the
63             # ones generated when building the perl distribution), to make sure that
64             # the only the changes to have appeared are ones which you expected.
65              
66             # 5.8.0 is required for "use fields"
67             # 5.8.3 is required for "use Exporter 'import'"
68 19     19   408 use 5.008003;
  19         77  
69              
70 19     19   103 use Cwd;
  19         53  
  19         1692  
71 19     19   148 use Config;
  19         51  
  19         1061  
72 19     19   101 use Exporter 'import';
  19         31  
  19         801  
73 19     19   99 use File::Basename;
  19         35  
  19         3027  
74 19     19   137 use File::Spec;
  19         40  
  19         660  
75 19     19   7418 use Symbol;
  19         19926  
  19         3400  
76              
77             our $VERSION;
78             BEGIN {
79 19     19   69 $VERSION = '3.61';
80 19         9146 require ExtUtils::ParseXS::Constants; ExtUtils::ParseXS::Constants->VERSION($VERSION);
  19         410  
81 19         9661 require ExtUtils::ParseXS::CountLines; ExtUtils::ParseXS::CountLines->VERSION($VERSION);
  19         390  
82 19         24962 require ExtUtils::ParseXS::Node; ExtUtils::ParseXS::Node->VERSION($VERSION);
  19         425  
83 19         13516 require ExtUtils::ParseXS::Utilities; ExtUtils::ParseXS::Utilities->VERSION($VERSION);
  19         423  
84 19         10997 require ExtUtils::ParseXS::Eval; ExtUtils::ParseXS::Eval->VERSION($VERSION);
  19         2315  
85             }
86             $VERSION = eval $VERSION if $VERSION =~ /_/;
87              
88 19         8888 use ExtUtils::ParseXS::Utilities qw(
89             trim_whitespace
90             C_string
91             valid_proto_string
92             process_typemaps
93             map_type
94             set_cond
95             Warn
96             WarnHint
97             current_line_number
98             blurt
99             death
100             escape_file_for_line_directive
101             report_typemap_failure
102 19     19   169 );
  19         104  
103              
104             our @EXPORT_OK = qw(
105             process_file
106             report_error_count
107             errors
108             );
109              
110             ##############################
111             # A number of "constants"
112             our $DIE_ON_ERROR;
113              
114             our $AUTHOR_WARNINGS;
115             $AUTHOR_WARNINGS = ($ENV{AUTHOR_WARNINGS} || 0)
116             unless defined $AUTHOR_WARNINGS;
117              
118             # Match an XS Keyword
119             our $BLOCK_regexp = '\s*(' . $ExtUtils::ParseXS::Constants::XSKeywordsAlternation . ")\\s*:";
120              
121              
122             # All the valid fields of an ExtUtils::ParseXS hash object. The 'use
123             # fields' enables compile-time or run-time errors if code attempts to
124             # use a key which isn't listed here.
125              
126             my $USING_FIELDS;
127              
128             BEGIN {
129 19     19   274 my @fields = (
130              
131             # I/O:
132              
133             'dir', # The directory component of the main input file:
134             # we will normally chdir() to this directory.
135              
136             'in_pathname', # The full pathname of the current input file.
137             'in_filename', # The filename of the current input file.
138             'in_fh', # The filehandle of the current input file.
139              
140             'IncludedFiles', # Bool hash of INCLUDEd filenames (plus main file).
141              
142             'line', # Array of lines recently read in and being processed.
143             # Typically one XSUB's worth of lines.
144             'line_no', # Array of line nums corresponding to @{$self->{line}}.
145              
146             'lastline', # The contents of the line most recently read in
147             # but not yet processed.
148             'lastline_no', # The line number of lastline.
149              
150              
151             # File-scoped configuration state:
152              
153             'config_RetainCplusplusHierarchicalTypes', # Bool: "-hiertype" switch
154             # value: it stops the typemap code doing
155             # $type =~ tr/:/_/.
156              
157             'config_WantLineNumbers', # Bool: (default true): "-nolinenumbers"
158             # switch not present: causes '#line NNN' lines to
159             # be emitted.
160              
161             'config_die_on_error',# Bool: make death() call die() rather than exit().
162             # It is set initially from the die_on_error option
163             # or from the $ExtUtils::ParseXS::DIE_ON_ERROR global.
164              
165             'config_author_warnings', # Bool: enables some warnings only useful to
166             # ParseXS.pm's authors rather than module creators.
167             # Set from Options or $AUTHOR_WARNINGS env var.
168              
169             'config_strip_c_func_prefix', # The discouraged -strip=... switch.
170              
171             'config_allow_argtypes', # Bool: (default true): "-noargtypes" switch not
172             # present. Enables ANSI-like arg types to be
173             # included in the XSUB signature.
174              
175             'config_allow_inout', # Bool: (default true): "-noinout" switch not present.
176             # Enables processing of IN/OUT/etc arg modifiers.
177              
178             'config_allow_exceptions', # Bool: (default false): the '-except' switch
179             # present.
180              
181             'config_optimize', # Bool: (default true): "-nooptimize" switch not
182             # present. Enables optimizations (currently just
183             # the TARG one).
184              
185              
186             # File-scoped parsing state:
187              
188             'AST', # the Node::XS_file object representing the AST
189             # tree for the whole XS file
190              
191             'typemaps_object', # An ExtUtils::Typemaps object: the result of
192             # reading in the standard (or other) typemap.
193              
194             'error_count', # Num: count of number of errors seen so far.
195              
196             'cpp_next_tmp_define',# the next string like XSubPPtmpAAAA
197             # to use as CPP defines for distringuishing
198             # similar calls to newXS() etc
199              
200             'MODULE_cname', # MODULE canonical name (i.e. after s/\W/_/g).
201             'PACKAGE_name', # PACKAGE name.
202             'PACKAGE_C_name', # Ditto, but with tr/:/_/.
203             'PACKAGE_class', # Ditto, but with '::' appended.
204             'PREFIX_pattern', # PREFIX value, but after quotemeta().
205              
206             'map_overloaded_package_to_C_package', # Hash: for every PACKAGE which
207             # has at least one overloaded XSUB, add a
208             # (package name => package C name) entry.
209              
210             'map_package_to_fallback_string', # Hash: for every package, maps it to
211             # the overload fallback state for that package (if
212             # specified). Each value is one of the strings
213             # "TRUE", "FALSE", "UNDEF".
214              
215             'proto_behaviour_specified', # Bool: prototype behaviour has been
216             # specified by the -prototypes switch and/or
217             # PROTOTYPE(S) keywords, so no need to warn.
218              
219             'PROTOTYPES_value', # Bool: most recent PROTOTYPES: value. Defaults to
220             # the value of the "-prototypes" switch.
221              
222             'VERSIONCHECK_value', # Bool: most recent VERSIONCHECK: value. Defaults
223             # to the value of the "-noversioncheck" switch.
224              
225             'seen_an_XSUB', # Bool: at least one XSUB has been encountered
226              
227             # File-scoped code-emitting state:
228              
229             'need_boot_cv', # must declare 'cv' within the boot function
230              
231             # Per-XSUB parsing state:
232              
233             'file_SCOPE_enabled', # Bool: the current state of the file-scope
234             # (as opposed to
235             # XSUB-scope) SCOPE keyword
236             );
237              
238             # do 'use fields', except: fields needs Hash::Util which is XS, which
239             # needs us. So only 'use fields' on systems where Hash::Util has already
240             # been built.
241 19 50       1831 if (eval 'require Hash::Util; 1;') {
242 19         83 require fields;
243 19         37 $USING_FIELDS = 1;
244 19         123 fields->import(@fields);
245             }
246             }
247              
248              
249             sub new {
250 333     333 1 2508307 my ExtUtils::ParseXS $self = shift;
251 333 50       2563 unless (ref $self) {
252 333 50       1183 if ($USING_FIELDS) {
253 333         1909 $self = fields::new($self);
254             }
255             else {
256 0         0 $self = bless {} => $self;
257             }
258             }
259 333         90165 return $self;
260             }
261              
262             our $Singleton = __PACKAGE__->new;
263              
264              
265             # The big method which does all the input parsing and output generation
266              
267             sub process_file {
268 316     316 1 189404 my ExtUtils::ParseXS $self;
269             # Allow for $package->process_file(%hash), $obj->process_file, and process_file()
270 316 100       2496 if (@_ % 2) {
271 315         715 my $invocant = shift;
272 315 100       1333 $self = ref($invocant) ? $invocant : $invocant->new;
273             }
274             else {
275 1         3 $self = $Singleton;
276             }
277              
278 316         727 my %Options;
279              
280             {
281 316         573 my %opts = @_;
  316         2788  
282 316         1572 $self->{proto_behaviour_specified} = exists $opts{prototypes};
283              
284             # Set defaults.
285 316         5272 %Options = (
286             argtypes => 1,
287             csuffix => '.c',
288             except => 0,
289             hiertype => 0,
290             inout => 1,
291             linenumbers => 1,
292             optimize => 1,
293             output => \*STDOUT,
294             prototypes => 0,
295             typemap => [],
296             versioncheck => 1,
297             in_fh => Symbol::gensym(),
298             die_on_error => $DIE_ON_ERROR, # if true we die() and not exit()
299             # after errors
300             author_warnings => $AUTHOR_WARNINGS,
301             %opts,
302             );
303             }
304              
305             # Global Constants
306              
307 316         21564 our ($Is_VMS, $VMS_SymSet);
308              
309 316 50       3040 if ($^O eq 'VMS') {
310 0         0 $Is_VMS = 1;
311             # Establish set of global symbols with max length 28, since xsubpp
312             # will later add the 'XS_' prefix.
313 0         0 require ExtUtils::XSSymSet;
314 0         0 $ExtUtils::ParseXS::VMS_SymSet = ExtUtils::XSSymSet->new(28);
315             }
316              
317             # Most of the parser uses these globals. We'll have to clean this up
318             # sometime, probably. For now, we just pull them out of %Options. -Ken
319              
320 316         1471 $self->{config_RetainCplusplusHierarchicalTypes} = $Options{hiertype};
321 316         1372 $self->{PROTOTYPES_value} = $Options{prototypes};
322 316         1021 $self->{VERSIONCHECK_value} = $Options{versioncheck};
323 316         903 $self->{config_WantLineNumbers} = $Options{linenumbers};
324 316         897 $self->{IncludedFiles} = {};
325              
326 316         1039 $self->{config_die_on_error} = $Options{die_on_error};
327 316         985 $self->{config_author_warnings} = $Options{author_warnings};
328              
329 316 50       1482 die "Missing required parameter 'filename'" unless $Options{filename};
330              
331              
332             # allow a string ref to be passed as an in-place filehandle
333 316 100       1520 if (ref $Options{filename}) {
334 302         820 my $f = '(input)';
335 302         955 $self->{in_pathname} = $f;
336 302         994 $self->{in_filename} = $f;
337 302         1019 $self->{dir} = '.';
338 302         1377 $self->{IncludedFiles}->{$f}++;
339 302 50       2302 $Options{outfile} = '(output)' unless $Options{outfile};
340             }
341             else {
342             ($self->{dir}, $self->{in_filename}) =
343 14         1515 (dirname($Options{filename}), basename($Options{filename}));
344 14         61 $self->{in_pathname} = $Options{filename};
345 14         48 $self->{in_pathname} =~ s/\\/\\\\/g;
346 14         60 $self->{IncludedFiles}->{$Options{filename}}++;
347             }
348              
349             # Open the output file if given as a string. If they provide some
350             # other kind of reference, trust them that we can print to it.
351 316 100       1278 if (not ref $Options{output}) {
352 4 50       1356 open my($fh), "> $Options{output}" or die "Can't create $Options{output}: $!";
353 4         35 $Options{outfile} = $Options{output};
354 4         15 $Options{output} = $fh;
355             }
356              
357             # Really, we shouldn't have to chdir() or select() in the first
358             # place. For now, just save and restore.
359 316         3112480 my $orig_cwd = cwd();
360 316         6429 my $orig_fh = select();
361              
362 316         6203 chdir($self->{dir});
363 316         2786240 my $pwd = cwd();
364              
365 316 100       5416 if ($self->{config_WantLineNumbers}) {
366 314         2907 my $csuffix = $Options{csuffix};
367 314         623 my $cfile;
368 314 100       2268 if ( $Options{outfile} ) {
369 305         2731 $cfile = $Options{outfile};
370             }
371             else {
372 9         62 $cfile = $Options{filename};
373 9 50       209 $cfile =~ s/\.xs$/$csuffix/i or $cfile .= $csuffix;
374             }
375 314         19315 tie(*PSEUDO_STDOUT, 'ExtUtils::ParseXS::CountLines', $cfile, $Options{output});
376 314         6296 select PSEUDO_STDOUT;
377             }
378             else {
379 2         46 select $Options{output};
380             }
381              
382 316         6784 $self->{typemaps_object} = process_typemaps( $Options{typemap}, $pwd );
383              
384 316         1979 $self->{config_strip_c_func_prefix} = $Options{s};
385 316         1369 $self->{config_allow_argtypes} = $Options{argtypes};
386 316         1278 $self->{config_allow_inout} = $Options{inout};
387 316         1366 $self->{config_allow_exceptions} = $Options{except};
388 316         1615 $self->{config_optimize} = $Options{optimize};
389              
390              
391             # Open the input file (using $self->{in_filename} which
392             # is a basename'd $Options{filename} due to chdir above)
393             {
394 316         777 my $fn = $self->{in_filename};
  316         1436  
395 316         1366 my $opfn = $Options{filename};
396 316 100       6534 $fn = $opfn if ref $opfn; # allow string ref as a source of file
397 316 50       10545 open($self->{in_fh}, '<', $fn)
398             or die "cannot open $self->{in_filename}: $!\n";
399             }
400              
401 316         9800 my $AST = $self->{AST} = ExtUtils::ParseXS::Node::XS_file->new();
402 316 50       5500 $AST->parse($self)
403             or $self->death("Failed to parse XS file\n");
404 285         1432 $AST->as_code($self);
405              
406 283         12207 chdir($orig_cwd);
407 283         3535 select($orig_fh);
408 283 100       2147 untie *PSEUDO_STDOUT if tied *PSEUDO_STDOUT;
409 283         4130 close $self->{in_fh};
410              
411 283         16352 return 1;
412             }
413              
414              
415             sub report_error_count {
416 2 100   2 1 1553514 if (@_) {
417 1   50     7 return $_[0]->{error_count}||0;
418             }
419             else {
420 1   50     36 return $Singleton->{error_count}||0;
421             }
422             }
423             *errors = \&report_error_count;
424              
425              
426             # ST(): helper function for the various INPUT / OUTPUT code emitting
427             # parts. Generate an "ST(n)" string. This is normally just:
428             #
429             # "ST(". $num - 1 . ")"
430             #
431             # except that in input processing it is legal to have a parameter with a
432             # typemap override, but where the parameter isn't in the signature. People
433             # misuse this to declare other variables which should really be in a
434             # PREINIT section:
435             #
436             # int
437             # foo(a)
438             # int a
439             # int b = 0
440             #
441             # The '= 0' will be interpreted as a local typemap entry, so $arg etc
442             # will be populated and the "typemap" evalled, So $num is undef, but we
443             # shouldn't emit a warning when generating "ST(N-1)".
444             #
445             sub ST {
446 1554     1554 0 3644 my ($self, $num) = @_;
447 1554 100       7273 return "ST(" . ($num-1) . ")" if defined $num;
448 526         1642 return '/* not a parameter */';
449             }
450              
451              
452             # Quote a command-line to be suitable for VMS
453              
454             sub QuoteArgs {
455 0     0 0 0 my $cmd = shift;
456 0         0 my @args = split /\s+/, $cmd;
457 0         0 $cmd = shift @args;
458 0         0 for (@args) {
459 0 0 0     0 $_ = q(").$_.q(") if !/^\"/ && length($_) > 0;
460             }
461 0         0 return join (' ', ($cmd, @args));
462             }
463              
464              
465             # _safe_quote(): quote an executable pathname which includes spaces.
466             #
467             # This code was copied from CPAN::HandleConfig::safe_quote:
468             # that has doc saying leave if start/finish with same quote, but no code
469             # given text, will conditionally quote it to protect from shell
470              
471             {
472             my ($quote, $use_quote) = $^O eq 'MSWin32'
473             ? (q{"}, q{"})
474             : (q{"'}, q{'});
475             sub _safe_quote {
476 1     1   3 my ($self, $command) = @_;
477             # Set up quote/default quote
478 1 50 33     9 if (defined($command)
      33        
479             and $command =~ /\s/
480             and $command !~ /[$quote]/) {
481 0         0 return qq{$use_quote$command$use_quote}
482             }
483 1         4 return $command;
484             }
485             }
486              
487              
488             # Unescape a string (typically a heredoc):
489             # - strip leading ' |' (any number of leading spaces)
490             # - and replace [[ and ]]
491             # with { and }
492             # so that text editors don't see a bare { or } when bouncing around doing
493             # brace level matching.
494              
495             sub Q {
496 3188     3188 0 178641 my ($text) = @_;
497 3188         31793 my @lines = split /^/, $text;
498 3188         4910 my $first;
499 3188         5985 for (@lines) {
500 61272 50       202785 unless (s/^(\s*)\|//) {
501 0         0 die "Internal error: no leading '|' in Q() string:\n$_\n";
502             }
503 61272         111609 my $pre = $1;
504 61272 50       118284 die "Internal error: leading tab char in Q() string:\n$_\n"
505             if $pre =~ /\t/;
506              
507 61272 100       97231 if (defined $first) {
508 58085 50       114996 die "Internal error: leading indents in Q() string don't match:\n$_\n"
509             if $pre ne $first;
510             }
511             else {
512 3187         6332 $first = $pre;
513             }
514             }
515 3188         22650 $text = join "", @lines;
516              
517 3188         6891 $text =~ s/\[\[/{/g;
518 3188         5305 $text =~ s/\]\]/}/g;
519 3188         29012 $text;
520             }
521              
522              
523             # fetch_para(): private helper method for Node::cpp_scope::parse().
524             #
525             # Read in all the lines associated with the next XSUB, BOOT or TYPEMAP,
526             # or associated with the next contiguous block of file-scoped XS or
527             # C-preprocessor directives. The caller relies on the paragraph
528             # demarcation to indicate the end of the XSUB, TYPEMAP or BOOT. For other
529             # types of line, it doesn't matter how they are split.
530             #
531             # More precisely, it reads lines (and their line numbers) up to (but not
532             # including) the start of the next XSUB or similar, into:
533             #
534             # @{ $self->{line} }
535             # @{ $self->{line_no} }
536             #
537             # It skips lines which contain POD or XS comments.
538             #
539             # It assumes that, on entry, $self->{lastline} contains the next line to
540             # process, and that further lines can be read from $self->{in_fh} as
541             # necessary. On return, it leaves the first unprocessed line in
542             # $self->{lastline}: typically the first line of the next XSUB. At EOF,
543             # lastline will be left undef and fetch_para() returns false.
544             #
545             # Multiple lines which are read in that end in '\' are concatenated
546             # together into a single line, whose line number is set to
547             # their first line. The two characters '\' and '\n' are kept in the
548             # concatenated string.
549             #
550             # In general, it stops just before the first line which matches /^\S/ and
551             # which was preceded by a blank line. This line is often the start of the
552             # next XSUB (but there is no guarantee of that).
553             #
554             # For example, given these lines:
555             #
556             # | ....
557             # | stuff
558             # | [blank line]
559             # |PROTOTYPES: ENABLE
560             # |#define FOO 1
561             # |PHASER DISCOMBOBULARISE
562             # |#define BAR 1
563             # | [blank line]
564             # |int
565             # |foo(...)
566             # | ....
567             #
568             # then the first call will return everything up to 'stuff' inclusive
569             # (perhaps it's the last line of an XSUB). The next call will return four
570             # lines containing the XS directives and CPP definitions. The directives
571             # are not interpreted or processed by this function; they're just returned
572             # as unprocessed text for the caller to interpret. A third call will read
573             # in the XSUB starting at 'int'.
574             #
575             # Note that fetch_para() knows almost nothing about C or XS syntax and
576             # keywords, and just blindly reads in lines until it finds a suitable
577             # place to break. It generally relies on the caller to handle most of the
578             # syntax and semantics and error reporting. For example, the block of four
579             # lines above from 'PROTOTYPES:' onwards isn't valid XS, but is blindly
580             # returned by fetch_para().
581             #
582             # It often returns zero lines - the caller will have to handle this.
583             #
584             # The following items are handled specially by fetch_para().
585             #
586             # POD: Discard all lines between /^='/../^=cut/, then continue.
587             #
588             # #comment Discard any line starting with /^\s*#/ which doesn't look
589             # like a C preprocessor directive,
590             #
591             # TYPEMAP: Return the typemap 'heredoc' lines as a paragraph, but with
592             # the final line (e.g. "EOF") missing. Line continuations,
593             # i.e. '\' aren't processed.
594             #
595             # BOOT: BOOT is NOT handled specially; the normal rules for ending
596             # a paragraph will determine where the BOOT code ends.
597             #
598             # #if etc: C preprocessor conditional directives are analysed to
599             # determine whether they are internal or external to the
600             # current paragraph. This allows XSUBs and similar to be
601             # closely cuddled by #if/#endif etc without needing to be
602             # separated by a blank line. Typically, any such directives
603             # immediately preceding an XSUB will be returned as one-line
604             # paragraphs.
605             #
606             # Note that this CPP-line analysis is completely independent
607             # of a similar analysis done in Node::cpp_scope::parse(),
608             # which is concerned with splitting the tree into separate
609             # sections where multiple XSUBs with the same name can appear.
610             #
611             # CPP directives (like #define) which aren't concerned with
612             # conditions are just passed through without any analysis.
613             #
614             # It removes any trailing blank lines from the list of returned lines.
615              
616              
617             sub fetch_para {
618 1574     1574 0 3543 my ExtUtils::ParseXS $self = shift;
619              
620 1574 100       5741 return 0 if not defined $self->{lastline}; # EOF
621              
622 1286         2328 @{ $self->{line} } = ();
  1286         2906  
623 1286         2060 @{ $self->{line_no} } = ();
  1286         4166  
624              
625 1286         2207 my $if_level = 0; # current depth of #if/#endif nesting
626              
627             # Main loop: for each iteration, process the current line,
628             # then maybe read in the next line and continue. Handle some special
629             # cases like POD in their own little loop which may read multiple
630             # lines.
631              
632 1286         2464 for (;;) {
633              
634 3946         5348 my $final; # if true, end loop after reading in the next line
635              
636              
637             # Skip an embedded POD section
638              
639 3946 100       11072 if ($self->{lastline} =~ /^=/) {
640 3         48 while ($self->{lastline} = readline($self->{in_fh})) {
641 6 100       78 last if ($self->{lastline} =~ /^=cut\s*$/);
642             }
643             $self->death("Error: Unterminated pod")
644 3 50       37 unless defined $self->{lastline};
645 3         31 goto read_next_line;
646             }
647              
648              
649             # If present, extract out a TYPEMAP block as a paragraph
650 3943 100       11286 if ($self->{lastline} =~ /^TYPEMAP\s*:/) {
651              
652             # Return what we have already and process this line on the
653             # next call; that way something like a previous BOOT: won't
654             # run on into the TYPEMAP: lines
655 294 100       921 last if @{$self->{line}};
  294         1990  
656              
657             $self->{lastline} =~
658 147 100       1909 /^TYPEMAP\s*:\s*<<\s*(?:(["'])(.+?)\1|([^\s'"]+?))\s*;?\s*$/
659             or $self->death("Error: unparseable TYPEMAP line: '$self->{lastline}'");
660              
661 146 100       2288 my $end_marker = quotemeta(defined($1) ? $2 : $3);
662              
663             # Add the 'TYPEMAP:' line
664 146         423 push @{$self->{line}}, $self->{lastline};
  146         805  
665 146         312 push @{$self->{line_no}}, $.;
  146         599  
666              
667             # Accumulate lines until we find $end_marker alone on a line.
668 146         1122 while ($self->{lastline} = readline($self->{in_fh})) {
669 1824 100       8646 last if $self->{lastline} =~ /^$end_marker\s*$/;
670 1679         2704 chomp $self->{lastline};
671 1679         2291 push @{$self->{line}}, $self->{lastline};
  1679         3651  
672 1679         2389 push @{$self->{line_no}}, $.;
  1679         5839  
673             }
674             $self->death("Error: Unterminated TYPEMAP section")
675 146 100       737 unless defined $self->{lastline};
676 145         301 $final = 1;
677 145         2074 goto read_next_line;
678             }
679              
680              
681             # Strip code comment lines
682              
683 3649 100 100     11175 if ($self->{lastline} =~ /^\s*#/
684             # CPP directives:
685             # ANSI: if ifdef ifndef elif else endif define undef
686             # line error pragma
687             # gcc: warning include_next
688             # obj-c: import
689             # others: ident (gcc notes that some cpps have this one)
690             && $self->{lastline} !~ /^\#[ \t]*
691             (?:
692             (?:if|ifn?def|elif|else|endif|elifn?def|
693             define|undef|pragma|error|
694             warning|line\s+\d+|ident)
695             \b
696             | (?:include(?:_next)?|import)
697             \s* ["<] .* [>"]
698             )
699             /x
700             ) {
701             # A line starting with # but not a CPP directive?
702             # Must be a code comment. Skip it.
703 3         70 goto read_next_line;
704             }
705              
706              
707             # Blank line followed by char in column 1. Start of next XSUB?
708              
709             last if $self->{lastline} =~ /^\S/
710 2108         10927 && @{ $self->{line} }
711 3646 100 100     14022 && $self->{line}->[-1] eq "";
      100        
712              
713              
714             # Must be a general line (e.g. file-scoped keyword or CPP directive):
715             # process it.
716              
717             # Analyse a CPP conditional line and if appropriate, make this line
718             # the last line of the current paragraph, or the first line of the
719             # next paragraph.
720              
721 3006 100       7352 if ($self->{lastline}
722             =~/^#[ \t]*(if|ifn?def|elif|else|endif|elifn?def)\b/)
723             {
724             # Allow a CPP conditional to directly precede or follow an XSUB
725             # without the usual required blank line, e.g.
726             #
727             # #if X
728             # void foo()
729             # CODE:
730             # ...
731             # # if Y
732             # ...
733             # # endif
734             # ...
735             # #else
736             # ...
737             #
738             # This is achieved by keeping track of CPP conditional nesting, to
739             # determine whether the conditional (e.g. the #else above) is part
740             # of the current paragraph, or is paired with something outside it.
741             # In this example, the #if Y / #endif are internal to the paragraph,
742             # while the #else is external and therefore indicates the end of the
743             # current paragraph and so we should stop, even though "\n\n\S"
744             # hasn't been encountered.
745             #
746             # Similarly we stop at the external '#if X', although here it is
747             # trickier to distinguish internal from external. For #if's, we
748             # achieve this by stopping if the #if is the first line in the
749             # putative paragraph; otherwise treat it as internal.
750              
751 52         255 my $type = $1;
752              
753 52 100       109 if (!@{$self->{line}}) {
  52         245  
754             # Treat a conditional starting the paragraph as a one-line
755             # paragraph
756 43         112 $final = 1;
757             }
758             else {
759             # Handle conditionals appearing in, or just after, an XSUB
760              
761 9 50       56 $if_level++ if $type =~ /^if/; # if, ifdef, ifndef
762             # If we're in a conditional that didn't start in this paragraph,
763             # return everything up to, but not including, this line, which
764             # will instead form the first line of the *next* paragraph
765 9 50       86 return 1 if !$if_level;
766 0 0       0 $if_level-- if $type eq "endif";
767             }
768             }
769              
770 2997         4410 push(@{ $self->{line} }, $self->{lastline});
  2997         7472  
771 2997         4409 push(@{ $self->{line_no} }, $self->{lastline_no});
  2997         7010  
772              
773              
774             read_next_line:
775             # Read next line and any continuation lines into $self->{lastline_no},
776             # ready for the next iteration, or if $final, to be ready for the next
777             # call to fetch_para().
778              
779 3148 100       19828 last unless defined($self->{lastline} = readline($self->{in_fh}));
780 2838         6380 $self->{lastline_no} = $.;
781 2838         7521 my $tmp_line;
782             $self->{lastline} .= $tmp_line
783 2838   66     8628 while ($self->{lastline} =~ /\\$/ && defined($tmp_line = readline($self->{in_fh})));
784              
785 2838         4914 chomp $self->{lastline};
786 2838         7289 $self->{lastline} =~ s/^\s+$//;
787 2838 100       8774 if ($final) {
788 178         471 last;
789             }
790             } # end for (;;)
791              
792             # Nuke trailing "line" entries until there's one that's not empty
793 821         2056 pop(@{ $self->{line} }), pop(@{ $self->{line_no} })
  821         2236  
794 1275   100     2414 while @{ $self->{line} } && $self->{line}->[-1] eq "";
  2096         8593  
795              
796 1275         6003 return 1;
797             }
798              
799              
800             # These two subs just delegate to a method in a clean package, where there
801             # are as few lexical variables in scope as possible and the ones which are
802             # accessible (such as $arg) are the ones documented to be available when
803             # eval()ing (in double-quoted context) the initialiser on an INPUT or
804             # OUTPUT line such as 'int foo = SvIV($arg)'
805              
806             sub eval_output_typemap_code {
807 245     245 0 502 my ExtUtils::ParseXS $self = shift;
808 245         619 my ($code, $other) = @_;
809 245         962 return ExtUtils::ParseXS::Eval::eval_output_typemap_code($self, $code, $other);
810             }
811              
812             sub eval_input_typemap_code {
813 382     382 0 737 my ExtUtils::ParseXS $self = shift;
814 382         810 my ($code, $other) = @_;
815 382         1360 return ExtUtils::ParseXS::Eval::eval_input_typemap_code($self, $code, $other);
816             }
817              
818             1;
819              
820             # vim: ts=2 sw=2 et: