Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.92k stars 549 forks source link

ExtUtils::Constant trying to make empty #defines accessible #6262

Closed p5pRT closed 12 years ago

p5pRT commented 21 years ago

Migrated from rt.perl.org#20636 (status was 'resolved')

Searchable as RT20636$

p5pRT commented 21 years ago

From tassilo.parseval@post.rwth-aachen.de

Created by tassilo.parseval@post.rwth-aachen.de

When creating an extension skeleton using

  h2xs -O -b \ -n Module​::Name header.h

it appears as though ExtUtils​::Constant tries to make symbols exportable that are merely #defined but have no value.

An excerpt from the header I've been using​:

  #ifndef __MPLIB_H   #define __MPLIB_H   #undef __BEGIN_DECLS   #undef __END_DECLS   #ifdef __cplusplus   # define __BEGIN_DECLS extern "C" {   # define __END_DECLS }   #else   # define __BEGIN_DECLS /* empty */   # define __END_DECLS /* empty */   #endif

and from the resulting constant-c.inc​:

  case 'L'​:   if (memEQ(name\, "__END_DECLS"\, 11)) {   /* ^ */   #ifdef __END_DECLS   *iv_return = __END_DECLS;   return PERL_constant_ISIV;   #else   return PERL_constant_NOTDEF;   #endif   }   break;

Running this with 'gcc -E' this is preprocessed into​:

  case 'L'​:   if (memEQ(name\, "__END_DECLS"\, 11)) {  

  *iv_return = ;   return 3 ;

  }   break;

and will render the whole project uncompilable​:

  In file included from Mplib.xs​:9​:   const-c.inc​: In function `constant'​:   const-c.inc​:284​: parse error before `;'   ...

The above problem remains when removing the two offending symbols (__BEGIN_DECLS and __END_DECLS) from the NAMES-list in ExtUtils​::Constant​::WriteConstants() in Makefile.PL.

Perl Info ``` Flags: category=library severity=low Site configuration information for perl v5.8.0: Configured by root at Fri Jul 19 10:50:34 CEST 2002. Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: Platform: osname=linux, osvers=2.4.18, archname=i686-linux uname='linux ethan 2.4.18 #1 tue feb 26 09:52:36 cet 2002 i686 unknown ' config_args='' hint=previous, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='gcc-3.0', ccflags ='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O3', cppflags='-fno-strict-aliasing -I/usr/local/include -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64' ccversion='', gccversion='3.0.4', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='gcc-3.0', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lgdbm -ldbm -ldb -ldl -lm -lc -lcrypt -lutil perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil libc=/lib/libc-2.2.5.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.2.5' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.0: /usr/opt/lib/perl5/5.8.0/i686-linux /usr/opt/lib/perl5/5.8.0 /usr/opt/lib/perl5/site_perl/5.8.0/i686-linux /usr/opt/lib/perl5/site_perl/5.8.0 /usr/opt/lib/perl5/site_perl . Environment for perl v5.8.0: HOME=/home/ethan LANG=C LANGUAGE (unset) LC_CTYPE=de_DE@euro LD_LIBRARY_PATH=:/usr/local/j2sdk1.4.0/jre/lib/i386:/usr/local/pwlib/lib LOGDIR (unset) PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/local/jdk1.3.1/bin:/home/ethan/bin:/usr/games PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 21 years ago

From @nwc10

On Fri\, Jan 31\, 2003 at 08​:02​:16AM -0000\, tassilo.parseval@​post.rwth-aachen.de (via RT) wrote​:

When creating an extension skeleton using

h2xs \-O \-b \<version> \-n Module&#8203;::Name header\.h

it appears as though ExtUtils​::Constant tries to make symbols exportable that are merely #defined but have no value.

The above problem remains when removing the two offending symbols (__BEGIN_DECLS and __END_DECLS) from the NAMES-list in ExtUtils​::Constant​::WriteConstants() in Makefile.PL.

An excerpt from the header I've been using​:

\#ifndef \_\_MPLIB\_H
\#define \_\_MPLIB\_H
\#undef \_\_BEGIN\_DECLS
\#undef \_\_END\_DECLS
\#ifdef \_\_cplusplus
\# define \_\_BEGIN\_DECLS extern "C" \{
\# define \_\_END\_DECLS \}
\#else
\# define \_\_BEGIN\_DECLS /\* empty \*/
\# define \_\_END\_DECLS /\* empty \*/
\#endif

ExtUtils​::Constant is just doing what it's told by h2xs. The real cause will be some sort of bug in h2xs that thinks that those two macros are defined. I suspect it's getting it wrong in the code somewhere near here​:

  # Remove macros which expand to typedefs   print "Typedefs are @​td.\n" if $opt_d;   my %td = map {($_\, $_)} @​td;   # Add some other possible but meaningless values for macros   for my $k (qw(char double float int long short unsigned signed void)) {   $td{"$_$k"} = "$_$k" for (''\, 'signed '\, 'unsigned ');   }   # eval {require 'dumpvar.pl'; :​:dumpValue( [\@​td\, \%td] ); 1} or warn $@​;   my $n = 0;   my %bad_macs;   while (keys %td > $n) {   $n = keys %td;   my ($k\, $v);   while (($k\, $v) = each %seen_define) {   # print("found '$k'=>'$v'\n")\,   $bad_macs{$k} = $td{$k} = $td{$v} if exists $td{$v};   }   }   # Now %bad_macs contains names of bad macros   for my $k (keys %bad_macs) {   delete $const_names{$prefixless{$k}};   print "Ignoring macro $k which expands to a typedef name '$bad_macs{$k}'\n" if $opt_d;   }

Not that I know how to fix it from a superficial look.

Nicholas Clark

p5pRT commented 21 years ago

From nick@ing-simmons.net

Tassilo.Parseval@​Post.Rwth-Aachen.De \perl5\-porters@&#8203;perl\.org writes​:

# New Ticket Created by tassilo.parseval@​post.rwth-aachen.de # Please include the string​: [perl #20636] # in the subject line of all future correspondence about this issue. # \<URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=20636 >

This is a bug report for perl from tassilo.parseval@​post.rwth-aachen.de\, generated with the help of perlbug 1.34 running under perl v5.8.0.

----------------------------------------------------------------- [Please enter your report here]

When creating an extension skeleton using

h2xs -O -b \ -n Module​::Name header.h

it appears as though ExtUtils​::Constant tries to make symbols exportable that are merely #defined but have no value.

An excerpt from the header I've been using​:

#ifndef __MPLIB_H #define __MPLIB_H #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif

and from the resulting constant-c.inc​:

   case 'L'&#8203;:
     if \(memEQ\(name\, "\_\_END\_DECLS"\, 11\)\) \{
     /\*                        ^        \*/

#ifdef __END_DECLS *iv_return = __END_DECLS; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break;

Running this with 'gcc -E' this is preprocessed into​:

   case 'L'&#8203;:
     if \(memEQ\(name\, "\_\_END\_DECLS"\, 11\)\) \{

       \*iv\_return =  ;
       return 3 ;

     \}
     break;

and will render the whole project uncompilable​:

In file included from Mplib.xs​:9​: const-c.inc​: In function `constant'​: const-c.inc​:284​: parse error before `;' ...

The above problem remains when removing the two offending symbols (__BEGIN_DECLS and __END_DECLS) from the NAMES-list in ExtUtils​::Constant​::WriteConstants() in Makefile.PL.

Hmm - this smells like a GCC/cpp bug to me I thought that

#define FOO

Was supposed to set FOO to 1 the fact you have trailing /* empty */ there should not make any difference as comments are equivalent to whitespace.

However I agree h2xs is very naive ...

-- Nick Ing-Simmons http​://www.ni-s.u-net.com/

p5pRT commented 12 years ago

From @jkeenan

On Fri Jan 31 07​:54​:00 2003\, nicholas wrote​:

On Fri\, Jan 31\, 2003 at 08​:02​:16AM -0000\, tassilo.parseval@​post.rwth- aachen.de (via RT) wrote​:

When creating an extension skeleton using

h2xs \-O \-b \<version> \-n Module&#8203;::Name header\.h

it appears as though ExtUtils​::Constant tries to make symbols exportable that are merely #defined but have no value.

The above problem remains when removing the two offending symbols (__BEGIN_DECLS and __END_DECLS) from the NAMES-list in ExtUtils​::Constant​::WriteConstants() in Makefile.PL.

An excerpt from the header I've been using​:

\#ifndef \_\_MPLIB\_H
\#define \_\_MPLIB\_H
\#undef \_\_BEGIN\_DECLS
\#undef \_\_END\_DECLS
\#ifdef \_\_cplusplus
\# define \_\_BEGIN\_DECLS extern "C" \{
\# define \_\_END\_DECLS \}
\#else
\# define \_\_BEGIN\_DECLS /\* empty \*/
\# define \_\_END\_DECLS /\* empty \*/
\#endif

ExtUtils​::Constant is just doing what it's told by h2xs. The real cause will be some sort of bug in h2xs that thinks that those two macros are defined. I suspect it's getting it wrong in the code somewhere near here​:

\# Remove macros which expand to typedefs
print "Typedefs are @&#8203;td\.\\n" if $opt\_d;
my %td = map \{\($\_\, $\_\)\} @&#8203;td;
\# Add some other possible but meaningless values for macros
for my $k \(qw\(char double float int long short unsigned signed

void)) { $td{"$_$k"} = "$_$k" for (''\, 'signed '\, 'unsigned '); } # eval {require 'dumpvar.pl'; :​:dumpValue( [\@​td\, \%td] ); 1} or warn $@​; my $n = 0; my %bad_macs; while (keys %td > $n) { $n = keys %td; my ($k\, $v); while (($k\, $v) = each %seen_define) { # print("found '$k'=>'$v'\n")\, $bad_macs{$k} = $td{$k} = $td{$v} if exists $td{$v}; } } # Now %bad_macs contains names of bad macros for my $k (keys %bad_macs) { delete $const_names{$prefixless{$k}}; print "Ignoring macro $k which expands to a typedef name '$bad_macs{$k}'\n" if $opt_d; }

Not that I know how to fix it from a superficial look.

Nicholas Clark

Another ticket which has been languishing in the "Open" queue for many years. ni-s is no longer with us. Is there someone -- particularly someone familiar with XS -- who could review the issues in this ticket and make a recommendation?

Thank you very much. Jim Keenan

p5pRT commented 12 years ago

From @arc

James E Keenan via RT \perlbug\-followup@&#8203;perl\.org wrote​:

Is there someone -- particularly someone familiar with XS -- who could review the issues in this ticket and make a recommendation?

I believe the attached patch (including tests) fixes this issue.

-- Aaron Crane ** http​://aaroncrane.co.uk/

p5pRT commented 12 years ago

From @arc

0001-perl-20636-Make-h2xs-skip-define-macros-with-empty-r.patch ```diff From efd3a28be28e6cf09635a5d34aa6378da8498ec6 Mon Sep 17 00:00:00 2001 From: Aaron Crane Date: Fri, 28 Sep 2012 14:14:47 +0100 Subject: [PATCH] [perl #20636] Make h2xs skip #define macros with empty rhs Otherwise the generated C code uses such macros in expressions, which causes compilation errors because the macro is expanded to an empty token list. --- lib/h2xs.t | 21 +++++++++++++++++++++ utils/h2xs.PL | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/lib/h2xs.t b/lib/h2xs.t index 6ce37ee..d10ce75 100644 --- a/lib/h2xs.t +++ b/lib/h2xs.t @@ -159,8 +159,10 @@ for (my $i = $#tests; $i > 0; $i-=3) { # 1 test for running it, 1 test for the expected result, and 1 for each file # plus 1 to open and 1 to check for the use in lib/$name.pm and Makefile.PL # And 1 more for our check for "bonus" files, 2 more for ExtUtil::Manifest. + # And 1 more to examine const-c.inc contents in tests that use $header. # use the () to force list context and hence count the number of matches. $total_tests += 9 + (() = $tests[$i] =~ /(Writing)/sg); + $total_tests++ if $tests[$i-2] =~ / \Q$header\E$/; } plan tests => $total_tests; @@ -169,6 +171,8 @@ ok (open (HEADER, ">$header"), "open '$header'"); print HEADER <
catfile($name, 'fallback', 'const-c.inc'); + my ($found, $diag); + if (!open FILE, '<', $const_c) { + $diag = "can't open $const_c: $!"; + } + else { + while () { + next unless /\b Bactrian 2? \b/x; + $found = 1; + last; + } + } + ok (!$found, "generated $const_c has no Bactrian(2)"); + diag ($diag) if defined $diag; + } + foreach my $leaf (File::Spec->catfile('lib', "$name.pm"), 'Makefile.PL') { my $file = File::Spec->catfile($name, $leaf); if (ok (open (FILE, $file), "open $file")) { diff --git a/utils/h2xs.PL b/utils/h2xs.PL index ee4079f..6b2c78f 100644 --- a/utils/h2xs.PL +++ b/utils/h2xs.PL @@ -862,6 +862,10 @@ if( @path_h ){ $rest =~ s!/\*.*?(\*/|\n)|//.*!!g; # Remove comments $rest =~ s/^\s+//; $rest =~ s/\s+$//; + if ($rest eq '') { + print("Skip empty $def\n") if $opt_d; + next defines; + } # Cannot do: (-1) and ((LHANDLE)3) are OK: #print("Skip non-wordy $def => $rest\n"), # next defines if $rest =~ /[^\w\$]/; -- 1.7.12.1 ```
p5pRT commented 12 years ago

From @cpansprout

On Fri Sep 28 06​:22​:04 2012\, perl@​aaroncrane.co.uk wrote​:

James E Keenan via RT \perlbug\-followup@&#8203;perl\.org wrote​:

Is there someone -- particularly someone familiar with XS -- who could review the issues in this ticket and make a recommendation?

I believe the attached patch (including tests) fixes this issue.

Thank you. Applied as dd5f7cf27c9.

--

Father Chrysostomos

p5pRT commented 12 years ago

@cpansprout - Status changed from 'open' to 'resolved'