Escape double-quotes in generated #line directives
authorSteffen Mueller <smueller@cpan.org>
Wed, 28 Dec 2011 17:47:49 +0000 (18:47 +0100)
committerSteffen Mueller <smueller@cpan.org>
Wed, 28 Dec 2011 17:48:09 +0000 (18:48 +0100)
 #line directives can be generated from commands. Those may be using
double quotes. That may not be considered friendly by preprocessors when
the result looks anything like this

 #line 123 "perl -e "foo""

Input on whether the following is portable would be appreciated.

 #line 123 "perl -e \"foo\""

gcc is happy with it. I know. The world's not just win32, osx, and linux
with a choice between three compilers.

dist/ExtUtils-ParseXS/Changes
dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS.pm
dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/CountLines.pm
dist/ExtUtils-ParseXS/lib/ExtUtils/ParseXS/Utilities.pm

index 65c37de..f6e810a 100644 (file)
@@ -1,5 +1,8 @@
 Revision history for Perl extension ExtUtils::ParseXS.
 
+3.09 - Thu Dec 28 18:48:00 CET 2011
+  - Escape double quotes of file names/commands in #line directives.
+
 3.08 - Mon Dec 19 18:03:00 CET 2011
   - Silence undefined-value-in-addition warning
     (Nothing serious, just happened sometimes when reporting line numbers for
index a339764..04d750c 100644 (file)
@@ -11,7 +11,7 @@ use Symbol;
 
 our $VERSION;
 BEGIN {
-  $VERSION = '3.08';
+  $VERSION = '3.09';
 }
 use ExtUtils::ParseXS::Constants $VERSION;
 use ExtUtils::ParseXS::CountLines $VERSION;
@@ -36,6 +36,7 @@ use ExtUtils::ParseXS::Utilities qw(
   blurt
   death
   check_conditional_preprocessor_statements
+  escape_file_for_line_directive
 );
 
 our @ISA = qw(Exporter);
@@ -193,7 +194,7 @@ sub process_file {
 EOM
 
 
-  print("#line 1 \"$self->{filepathname}\"\n")
+  print("#line 1 \"" . escape_file_for_line_directive($self->{filepathname}) . "\"\n")
     if $self->{WantLineNumbers};
 
   # Open the input file (using $self->{filename} which
@@ -220,7 +221,7 @@ EOM
           # concatenated until 2 steps later, so we are safe.
           #     - Nicholas Clark
           print("#if 0\n  \"Skipped embedded POD.\"\n#endif\n");
-          printf("#line %d \"$self->{filepathname}\"\n", $. + 1)
+          printf("#line %d \"%s\"\n", $. + 1, escape_file_for_line_directive($self->{filepathname}))
             if $self->{WantLineNumbers};
           next firstmodule
         }
@@ -313,7 +314,8 @@ EOM
 
     if ($self->check_keyword("BOOT")) {
       check_conditional_preprocessor_statements($self);
-      push (@{ $BootCode_ref }, "#line $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} }] \"$self->{filepathname}\"")
+      push (@{ $BootCode_ref }, "#line $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} }] \""
+                                . escape_file_for_line_directive($self->{filepathname}) . "\"")
         if $self->{WantLineNumbers} && $self->{line}->[0] !~ /^\s*#\s*line\b/;
       push (@{ $BootCode_ref }, @{ $self->{line} }, "");
       next PARAGRAPH;
@@ -1012,7 +1014,8 @@ sub print_section {
 
   my $consumed_code = '';
 
-  print("#line ", $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} } -1], " \"$self->{filepathname}\"\n")
+  print("#line ", $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} } -1], " \"",
+        escape_file_for_line_directive($self->{filepathname}), "\"\n")
     if $self->{WantLineNumbers} && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
   for (;  defined($_) && !/^$self->{BLOCK_re}/o;  $_ = shift(@{ $self->{line} })) {
     print "$_\n";
index 0ca9ee2..fd8d532 100644 (file)
@@ -1,13 +1,14 @@
 package ExtUtils::ParseXS::CountLines;
 use strict;
 
-our $VERSION = '3.08';
+our $VERSION = '3.09';
 
 our $SECTION_END_MARKER;
 
 sub TIEHANDLE {
   my ($class, $cfile, $fh) = @_;
   $cfile =~ s/\\/\\\\/g;
+  $cfile =~ s/"/\\"/g;
   $SECTION_END_MARKER = qq{#line --- "$cfile"};
 
   return bless {
index 1209899..b3c7a3c 100644 (file)
@@ -6,7 +6,7 @@ use File::Spec;
 use lib qw( lib );
 use ExtUtils::ParseXS::Constants ();
 
-our $VERSION = '3.08';
+our $VERSION = '3.09';
 
 our (@ISA, @EXPORT_OK);
 @ISA = qw(Exporter);
@@ -28,6 +28,7 @@ our (@ISA, @EXPORT_OK);
   blurt
   death
   check_conditional_preprocessor_statements
+  escape_file_for_line_directive
 );
 
 =head1 NAME
@@ -53,6 +54,7 @@ ExtUtils::ParseXS::Utilities - Subroutines used with ExtUtils::ParseXS
     blurt
     death
     check_conditional_preprocessor_statements
+    escape_file_for_line_directive
   );
 
 =head1 SUBROUTINES
@@ -844,6 +846,35 @@ sub check_conditional_preprocessor_statements {
   }
 }
 
+=head2 C<escape_file_for_line_directive()>
+
+=over 4
+
+=item * Purpose
+
+Escapes a given code source name (typically a file name but can also
+be a command that was read from) so that double-quotes and backslashes are escaped.
+
+=item * Arguments
+
+A string.
+
+=item * Return Value
+
+A string with escapes for double-quotes and backslashes.
+
+=back
+
+=cut
+
+sub escape_file_for_line_directive {
+  my $string = shift;
+  $string =~ s/\\/\\\\/g;
+  $string =~ s/"/\\"/g;
+  return $string;
+}
+
+
 1;
 
 # vim: ts=2 sw=2 et: