ExtUtils-ParseXS
view release on metacpan or search on metacpan
lib/ExtUtils/ParseXS/Node.pm view on Meta::CPAN
# CPP condition keyword just ends that scope. Our
# (recursive) caller will handle processing any further
# branches if it's an elif/else rather than endif
return 1
}
# So it's an 'if'/'ifdef' etc node. Start a new
# Node::cpp_scope sub-parse to handle that branch and then any
# other branches of the same conditional.
while (1) {
# For each iteration, parse the next branch in a new scope
my $scope = ExtUtils::ParseXS::Node::cpp_scope->new(
{type => 'if'});
$scope->parse($pxs)
or next;
# Sub-parsing of that branch should have terminated
# at an elif/endif line rather than falling off the
# end of the file
my $last = $scope->{kids}[-1];
unless (
defined $last
&& $last->isa(
'ExtUtils::ParseXS::Node::global_cpp_line')
&& $last->{is_cond}
&& !$last->{is_if}
) {
$pxs->death( "Error: Unterminated '#$node->{directive}'"
. " from line $node->{line_no}")
}
# Move the CPP line which terminated the branch from
# the end of the inner scope to the current scope
pop @{$scope->{kids}};
push @{$self->{kids}}, $scope, $last;
if (grep { ref($_) !~ /::global_cpp_line$/ }
@{$scope->{kids}} )
{
# the inner scope has some content, so needs
# a '#define XSubPPtmpAAAA 1'-style guard
$scope->{guard_name} = $pxs->{cpp_next_tmp_define}++;
}
# any more branches to process of current if?
last if $last->{is_endif};
} # while 1
next;
}
my $file_scoped_keywords =
"BOOT|REQUIRE|PROTOTYPES|EXPORT_XSUB_SYMBOLS|FALLBACK"
. "|VERSIONCHECK|INCLUDE|INCLUDE_COMMAND|SCOPE|TYPEMAP";
# Die if the next line is indented: all file-scoped things (CPP,
# keywords, XSUB starts) are supposed to start on column 1
# (although see the comment below about multiple parse_keywords()
# iterations sneaking in indented keywords).
#
if ($pxs->{line}[0] =~ /^\s/) {
# Try to customise the error message based around why this
# line is indented, to better hint to the user what the
# problem is.
if ($pxs->{line}[0] =~ /^\s+($file_scoped_keywords)\s*:/) {
$pxs->death(
"Error: file-scoped keywords should not be indented");
}
# The text of the error message is based around a common reason
# for an indented line to appear in file scope: this is due to an
# XSUB being prematurely truncated by fetch_para(). For example in
# the code below, the coder wants the foo and bar lines to both be
# part of the same CODE block. But the XS parser sees the blank
# line followed by the '#ifdef' on column 1 as terminating the
# current XSUB. So the bar() line is treated as being in file
# scope and dies because it is indented.
#
# |int f()
# | CODE:
# | foo();
# |
# |#ifdef USE_BAR
# | bar();
# |#endif
$pxs->deathHint(
"Error: file-scoped directives must not be indented",
$self->Q(<<EOF))
|If this line is supposed to be part of an XSUB rather than being
|file-scoped, then it is possible that your XSUB has a blank line
|followed by a line starting at column 1 which is being misinterpreted
|as the end of the current XSUB.
EOF
}
# The SCOPE keyword can appear both in file scope (just before an
# XSUB) and as an XSUB keyword. This field maintains the state of the
# former: reset it at the start of processing any file-scoped
# keywords just before the XSUB (i.e. without any blank lines, e.g.
# SCOPE: ENABLE
# int
# foo(...)
# These semantics may not be particularly sensible, but they maintain
# backwards compatibility for now.
$pxs->{file_SCOPE_enabled} = 0;
# Process file-scoped keywords
#
# This loop repeatedly: skips any blank lines and then calls
# the relevant Node::FOO::parse() method if it finds any of the
# file-scoped keywords in the passed pattern.
#
# Note: due to the looping within parse_keywords() rather than
# looping here, only the first keyword in a contiguous block
# gets the 'start at column 1' check above enforced.
( run in 1.527 second using v1.01-cache-2.11-cpan-71847e10f99 )