Skip to content

Commit d86a388

Browse files
committed
ParseXS: refactor: add Node::TYPEMAP
(This commit is part of a series which will extend the AST parse tree from just representing individual XSUBs to representing the whole XS file.) Add a new node type, ExtUtils::ParseXS::Node::TYPEMAP. this (mostly) regularises the treatment of a TYPEMAP line, now handled in the usual way by parse_keywords(), rather than being processed solely within fetch_para(). fetch_para() does still need to do *some* processing: it has to read the TYPEMAP line, extract out the <<EOF bit, and use that to read lines up until the matchhing 'EOF'. It then returns these lines (including the initial TYPEMAP line) as a paragraph which is then handled as a normal file-scoped keyword. With this commit, fetch_para() becomes closer to its official job of just returning the next useful chunk of lines, rather than having hidden side effects too. This commit is supposed to have no changes in behaviour, but there *might* be some edge cases that I haven't thought of.
1 parent 264963f commit d86a388

File tree

2 files changed

+70
-40
lines changed

2 files changed

+70
-40
lines changed

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS.pm

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -525,43 +525,6 @@ sub _maybe_skip_pod {
525525
}
526526

527527

528-
# Strip out and parse embedded TYPEMAP blocks (which use a HEREdoc-alike
529-
# block syntax).
530-
531-
sub _maybe_parse_typemap_block {
532-
my ExtUtils::ParseXS $self = shift;
533-
534-
# This is special cased from the usual paragraph-handler logic
535-
# due to the HEREdoc-ish syntax.
536-
return unless $self->{lastline} =~ /^TYPEMAP\s*:/;
537-
538-
$self->{lastline} =~ /^TYPEMAP\s*:\s*<<\s*(?:(["'])(.+?)\1|([^\s'"]+?))\s*;?\s*$/
539-
or $self->death("Error: unparseable TYPEMAP line: '$self->{lastline}'");
540-
541-
542-
543-
my $end_marker = quotemeta(defined($1) ? $2 : $3);
544-
545-
# Scan until we find $end_marker alone on a line.
546-
my @tmaplines;
547-
while (1) {
548-
$self->{lastline} = readline($self->{in_fh});
549-
$self->death("Error: Unterminated TYPEMAP section") if not defined $self->{lastline};
550-
last if $self->{lastline} =~ /^$end_marker\s*$/;
551-
push @tmaplines, $self->{lastline};
552-
}
553-
554-
my $tmap = ExtUtils::Typemaps->new(
555-
string => join("", @tmaplines),
556-
lineno_offset => 1 + ($self->current_line_number() || 0),
557-
fake_filename => $self->{in_filename},
558-
);
559-
$self->{typemaps_object}->merge(typemap => $tmap, replace => 1);
560-
561-
$self->{lastline} = "";
562-
}
563-
564-
565528
# fetch_para(): private helper method for process_file().
566529
#
567530
# Read in all the lines associated with the next XSUB, or associated with
@@ -672,7 +635,35 @@ sub fetch_para {
672635
for (;;) {
673636
$self->_maybe_skip_pod;
674637

675-
$self->_maybe_parse_typemap_block;
638+
# if present, extract out a TYPEMAP block as a paragraph
639+
if ($self->{lastline} =~ /^TYPEMAP\s*:/) {
640+
641+
# Return what we have already and process this line on the
642+
# next call; that way something like a previous BOOT: won't
643+
# run on into the TYPEMAP: lines
644+
return 1 if @{$self->{line}};
645+
646+
$self->{lastline} =~
647+
/^TYPEMAP\s*:\s*<<\s*(?:(["'])(.+?)\1|([^\s'"]+?))\s*;?\s*$/
648+
or $self->death("Error: unparseable TYPEMAP line: '$self->{lastline}'");
649+
650+
my $end_marker = quotemeta(defined($1) ? $2 : $3);
651+
652+
# Scan until we find $end_marker alone on a line.
653+
my $last;
654+
while (1) {
655+
unless ($last) {
656+
push @{$self->{line}}, $self->{lastline};
657+
push @{$self->{line_no}}, $.;
658+
}
659+
$self->{lastline} = readline($self->{in_fh});
660+
last if $last;
661+
$self->death("Error: Unterminated TYPEMAP section")
662+
unless defined $self->{lastline};
663+
$last = $self->{lastline} =~ /^$end_marker\s*$/;
664+
}
665+
return 1;
666+
}
676667

677668
my $final;
678669

dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Node.pm

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,6 @@ sub parse {
10581058

10591059
PARAGRAPH:
10601060
while ( ($pxs->{line} && @{$pxs->{line}}) || $pxs->fetch_para()) {
1061-
10621061
if ( !defined($self->{line_no})
10631062
&& defined $pxs->{line_no}[0]
10641063
) {
@@ -1191,7 +1190,7 @@ sub parse {
11911190
undef, undef, # xsub and xbody: not needed for non XSUB keywords
11921191
undef, # implies process as many keywords as possible
11931192
"BOOT|REQUIRE|PROTOTYPES|EXPORT_XSUB_SYMBOLS|FALLBACK"
1194-
. "|VERSIONCHECK|INCLUDE|INCLUDE_COMMAND|SCOPE",
1193+
. "|VERSIONCHECK|INCLUDE|INCLUDE_COMMAND|SCOPE|TYPEMAP",
11951194
$keywords_flag_MODULE,
11961195
);
11971196

@@ -1376,6 +1375,46 @@ sub as_boot_code {
13761375
return [], \@lines;
13771376
}
13781377

1378+
# ======================================================================
1379+
1380+
package ExtUtils::ParseXS::Node::TYPEMAP;
1381+
1382+
# Process the lines associated with the TYPEMAP keyword
1383+
#
1384+
# fetch_para() will have already processed the <<EOF logic
1385+
# and read all the lines up to, but not including, the EOF line.
1386+
1387+
BEGIN { $build_subclass->(
1388+
'lines', # Array ref of all lines making up the TYPEMAP section
1389+
)};
1390+
1391+
1392+
# Feed all the lines to ExtUtils::Typemaps.
1393+
1394+
sub parse {
1395+
my __PACKAGE__ $self = shift;
1396+
my ExtUtils::ParseXS $pxs = shift;
1397+
1398+
$self->SUPER::parse($pxs); # set file/line_no
1399+
1400+
shift @{$pxs->{line}}; # skip the 'TYPEMAP:' line
1401+
1402+
# Suck in all remaining lines
1403+
$self->{lines} = $pxs->{line};
1404+
$pxs->{line} = [];
1405+
1406+
my $tmap = ExtUtils::Typemaps->new(
1407+
string => join("", @{$self->{lines}}),
1408+
lineno_offset => 1 + ($pxs->current_line_number() || 0),
1409+
fake_filename => $pxs->{in_filename},
1410+
);
1411+
1412+
$pxs->{typemaps_object}->merge(typemap => $tmap, replace => 1);
1413+
1414+
1;
1415+
}
1416+
1417+
13791418
# ======================================================================
13801419

13811420
package ExtUtils::ParseXS::Node::pre_boot;

0 commit comments

Comments
 (0)