Index: /releases/2.9.9/perllib/Polymake/Core/CPlusPlus_config.pm =================================================================== --- /releases/2.9.9/perllib/Polymake/Core/CPlusPlus_config.pm (revision 9831) +++ /releases/2.9.9/perllib/Polymake/Core/CPlusPlus_config.pm (revision 9921) @@ -18,13 +18,13 @@ package Polymake::Core::CPlusPlus; -$nm_util ||= "nm -g"; -$cppfilt_util ||= $^O =~ /bsd/i ? "/usr/local/bin/c++filt" : "c++filt"; -$MAKE ||= $^O =~ /bsd|solaris/i ? "gmake" : "make"; - sub study_name_mangling { + my $custom_handler=shift; local $_; - @to_mangled_defconstr=(); + + $nm_util ||= "nm -g"; + $cppfilt_util ||= $^O =~ /bsd/i ? "/usr/local/bin/c++filt" : "c++filt"; + @to_mangled_defconstr=(); @to_mangled_typeinfo=(); my $file=new Tempfile; open my $cc, ">$file.cc"; @@ -81,11 +81,11 @@ } dbg_print( "test program emitted typenames: @typenames\n" ) if $DebugLevel; open my $nm, "$nm_util $file.exe |" or die "can't run nm utility: $!\n"; - my %mangled; + my (%mangled_defc, %mangled_ti); while (<$nm>) { - if (my ($mangled)=/\s[TW]\s+(\S*PolymakeTest\S*)/) { + if (my ($symbol, $mangled)=/\s([TWV])\s+(\S*PolymakeTest\S*)/) { my $case= $mangled =~ /TestWrap/ ? 3 : $mangled =~ /TestNam/ ? 2 : $mangled =~ /TestGlob/ ? 1 : 0; - next if exists $mangled{$case}; + next if $symbol eq "V" ? exists $mangled_ti{$case} : exists $mangled_defc{$case}; dbg_print( "nm extracted global name $mangled" ) if $DebugLevel; open my $cf, "$cppfilt_util $mangled |" or die "can't run c++filt utility: $!\n"; @@ -109,19 +109,69 @@ to proper utility paths and optional flags if necessary . } - if ($demangled =~ ($case<=2 ? $constructor_re : $wrapped_constructor_re)) { - $mangled{$case}=$mangled; + if ($symbol eq "V") { + if ($demangled =~ ($case<=2 ? $typeinfo_re : $wrapped_typeinfo_re)) { + $mangled_ti{$case}=$mangled; + } elsif ($demangled !~ /typeinfo name /) { + dbg_print( "c++filt returned '$demangled',\n", + "which does not match the expected typeinfo description!" ) if $DebugLevel; + } } else { - dbg_print( "c++filt returned '$demangled',\n", - "which does not match the expected default constructor declaration!" ) if $DebugLevel; + if ($demangled =~ ($case<=2 ? $constructor_re : $wrapped_constructor_re)) { + $mangled_defc{$case}=$mangled; + } else { + dbg_print( "c++filt returned '$demangled',\n", + "which does not match the expected default constructor declaration!" ) if $DebugLevel; + } } } } close $nm; - if (keys(%mangled) != 3) { + if (keys(%mangled_ti) == 3) { + @to_mangled_typeinfo=uniq( map { + my $subst=$typenames[$_==2]; + $mangled_ti{$_} =~ s/$subst/\${&}/; + "s{.*}{$mangled_ti{$_}}"; + } 1..3 ); + + } elsif (keys(%mangled_defc) == 3) { + + $mangled_defc{1} =~ s/$typenames[0]/\${&}/; + push @to_mangled_defconstr, "s{.*}{$mangled_defc{1}}"; + + $_=$mangled_defc{2}; + my $l=length($typenames[1]); + HARD_TRY: + for (my $start=0; $start<$l; ++$start) { + for (my $end=$l; $end>$start; --$end) { + my $part=substr($typenames[1],$start,$end-$start); + if (/\Q$part\E/) { + if ($start>0 || $end<$l) { + my ($add_pre, $add_post)=($`, $'); + my ($rem_pre, $rem_post)=map { /[.{}()\[\]\\?*^\$]/ ? "\\Q$_\\E" : $_ } + (substr($typenames[1],0,$start), substr($typenames[1],$end)); + push @to_mangled_defconstr, "s{^$rem_pre(.*)$rem_post\$}{$add_pre\${1}$add_post}"; + } + undef $_; last HARD_TRY; + } + } + } + if (defined $_) { + warn_print( <<'.' ); +Could not guess the name mangling rule for classes defined in namespaces. +Please invent the suitable regular expression converting the typeinfo name +to the default constructor mangled name and put it in the custom array + @Polymake::Core::CPlusPlus::to_mangled_defconstr +. + } + + $mangled_defc{3} =~ s/$typenames[0]/\${&}/; + push @to_mangled_defconstr, "s{.*}{$mangled_defc{3}}"; + + } else { die <<"." -nm has not extracted the constructor names from the test program binary. +nm has not extracted the symbol names from the test program binary. Possible reason is the incompatibility between nm and $CXX. Please investigate the problem and set the custom variables \$Polymake::Core::CPlusPlus::nm_util and \$Polymake::Core::CPlusPlus::cppfilt_util @@ -129,40 +179,14 @@ . } - $mangled{1} =~ s/$typenames[0]/\${&}/; - push @to_mangled_defconstr, "s{.*}{$mangled{1}}"; - - $_=$mangled{2}; - my $l=length($typenames[1]); -HARD_TRY: - for (my $start=0; $start<$l; ++$start) { - for (my $end=$l; $end>$start; --$end) { - my $part=substr($typenames[1],$start,$end-$start); - if (/\Q$part\E/) { - if ($start>0 || $end<$l) { - my ($add_pre, $add_post)=($`, $'); - my ($rem_pre, $rem_post)=map { /[.{}()\[\]\\?*^\$]/ ? "\\Q$_\\E" : $_ } - (substr($typenames[1],0,$start), substr($typenames[1],$end)); - push @to_mangled_defconstr, "s{^$rem_pre(.*)$rem_post\$}{$add_pre\${1}$add_post}"; - } - undef $_; last HARD_TRY; - } - } - } - if (defined $_) { - warn_print( <<'.' ); -Could not guess the name mangling rule for classes defined in namespaces. -Please invent the suitable regular expression converting the typeinfo name -to the default constructor mangled name and put it in the custom array - @Polymake::Core::CPlusPlus::to_mangled_defconstr -. - } - - $mangled{3} =~ s/$typenames[0]/\${&}/; - push @to_mangled_defconstr, "s{.*}{$mangled{3}}"; -} - -sub allow_parallel_make { + $custom_handler->set($_) for qw($nm_util $cppfilt_util @to_mangled_defconstr @to_mangled_typeinfo); +} + +sub configure_make { + my $custom_handler=shift; + + $MAKE ||= $^O =~ /bsd|solaris/i ? "gmake" : "make"; + my $cnt=0; local $_; if (-f "/proc/cpuinfo") { @@ -207,6 +231,8 @@ } else { $MAKEFLAGS=""; } + + $custom_handler->set($_) for qw($MAKE $MAKEFLAGS); } 1 Index: /releases/2.9.9/perllib/Polymake/Core/CPlusPlus.pm =================================================================== --- /releases/2.9.9/perllib/Polymake/Core/CPlusPlus.pm (revision 9883) +++ /releases/2.9.9/perllib/Polymake/Core/CPlusPlus.pm (revision 9921) @@ -928,7 +928,8 @@ Can't obtain the C++ representation for typeid $typeid. Probably the mangling rules are not guessed correctly. Please investigate and put suitable regular expressions -in the custom array \@Polymake::Core::CPlusPlus::to_mangled_defconstr. +in the custom arrays \@Polymake::Core::CPlusPlus::to_mangled_typeinfo +or \@Polymake::Core::CPlusPlus::to_mangled_defconstr. . }; if (wantarray) { @@ -1310,6 +1311,10 @@ sub compile { my ($self, $app)=@_; + unless ($MAKE) { + require Polymake::Core::CPlusPlus_config; + configure_make($custom_handler); + } my $errfile=new Tempfile; my $debug_flag= $debug && "Debug=y"; warn_print( "Recompiling shared module for application ", $app->name, ", please be patient..." ); @@ -2078,6 +2083,10 @@ } } + unless ($MAKE) { + require Polymake::Core::CPlusPlus_config; + configure_make($custom_handler); + } my $file=new Tempfile; my $so_name=$file->rename.$dl_suffix; RETRY: { @@ -2253,15 +2262,20 @@ package Polymake::Core::CPlusPlus; declare ($from_embedded_rules, $root); -declare (@to_mangled_defconstr, $nm_util, $cppfilt_util, $MAKE, $MAKEFLAGS, %private_wrappers, %wrapper_updated); - +declare (@to_mangled_typeinfo, @to_mangled_defconstr, $nm_util, $cppfilt_util, $MAKE, $MAKEFLAGS, %private_wrappers, %wrapper_updated); + +declare $typeinfo_re=qr{^typeinfo for }; +declare $wrapped_typeinfo_re=qr{^typeinfo for PolymakeTestWrap<(.*)>}; declare $constructor_re=qr{::$id_re (?:\[.*?\])? \(\)$}xo; declare $wrapped_constructor_re=qr{^PolymakeTestWrap<(.*)>::PolymakeTestWrap (?:\[.*?\])? \(\)$}xo; $custom_handler=$Custom->app_handler(undef,__PACKAGE__); +$custom_handler->add('@to_mangled_typeinfo', <<'.', $Customize::state_config); +# Regular expressions deriving the typeinfo mangled name from the class typeinfo name +. $custom_handler->add('@to_mangled_defconstr', <<'.', $Customize::state_config); -# Regular expressions deriving the default constructor mangled name from the class typeinfo +# Regular expressions deriving the default constructor mangled name from the class typeinfo name . $custom_handler->add('$nm_util', <<'.', $Customize::state_config); # Path and optional flags to the nm utility @@ -2281,11 +2295,6 @@ $custom_handler->add('%wrapper_updated', <<'.', $Customize::state_hidden); # Timestamps of last changes made to the automatically generated source code of C++/perl wrappers . -if (!@to_mangled_defconstr) { - require Polymake::Core::CPlusPlus_config; - study_name_mangling(); - allow_parallel_make(); -} $custom_handler->cleanup; @@ -3095,14 +3104,9 @@ ####################################################################################### sub create_private_wrapper_dir { my $src_top=shift; - my $dir; - if ($src_top eq $InstallTop) { - $dir="$UserSettings::dir/wrappers/core"; - } else { - $src_top =~ $filename_re; - my $cnt; - while (-d ($dir="$UserSettings::dir/wrappers/$1".($cnt && ".$cnt"))) { ++$cnt } - } + my ($stem)=$src_top eq $InstallTop ? ("core") : $src_top =~ $filename_re; + my ($dir, $cnt); + while (-d ($dir="$UserSettings::dir/wrappers/$stem".($cnt && ".$cnt"))) { ++$cnt } # FIXME: remove this after some transitional period if (-d "$UserSettings::dir/mirrors") { @@ -3442,6 +3446,10 @@ create_source_dir($native_link); symlink $native_src, $native_link; } + unless ($MAKE) { + require Polymake::Core::CPlusPlus_config; + configure_make($custom_handler); + } my $errfile=new Tempfile; my $debug_flag= $debug && "Debug=y"; my $rc=system("$MAKE -C $private_top/build.$Arch/apps/$app_name all-native $debug_flag $MAKEFLAGS JNI_HEADERS=$jni_headers" . (!$Verbose::cpp && ">/dev/null") . " 2>$errfile.err"); @@ -3456,8 +3464,24 @@ sub demangle { unless (defined $cppf_in) { + unless (@to_mangled_typeinfo || @to_mangled_defconstr) { + require Polymake::Core::CPlusPlus_config; + study_name_mangling($custom_handler); + } require Polymake::Background; ($cppf_out, $cppf_in)=new Background::Pipe($cppfilt_util); + } + + foreach my $rule (@to_mangled_typeinfo) { + local $_=$_[0]; + eval $rule or $@ ? die "syntax error in mangling regex: $@\n" : next; + print $cppf_out $_, "\n"; + $_=readline($cppf_in); + if ($_ =~ $wrapped_typeinfo_re) { + return $1; + } elsif ($_ =~ $typeinfo_re) { + return $'; + } } my $case=0; @@ -3465,12 +3489,13 @@ local $_=$_[0]; eval $rule or $@ ? die "syntax error in mangling regex: $@\n" : next; print $cppf_out $_, "\n"; + $_=readline($cppf_in); if (++$case<=2) { - if (readline($cppf_in) =~ $constructor_re) { + if ($_ =~ $constructor_re) { return $`; } } else { - if (readline($cppf_in) =~ $wrapped_constructor_re) { + if ($_ =~ $wrapped_constructor_re) { return $1; } } @@ -3499,8 +3524,7 @@ use overload '++' => \&incr, 'bool' => \¬_at_end, '${}' => \&deref_to_scalar, '@{}' => \&deref, '%{}' => \&deref, '=' => \&overload_clone_op, - fallback => 0, nomethod => \&missing_op, '""' => sub { "ITERATOR" }; - + fallback => 0, nomethod => \&missing_op, '""' => sub { ¬_at_end ? "ITERATOR" : "VOID ITERATOR" }; #######################################################################################