openacc: Fortran derived-type mapping fix
[platform/upstream/gcc.git] / contrib / make_sunver.pl
index d087578..8a90b1f 100644 (file)
 # A comment with the original pattern and its type is left in the output
 # file to make it easy to understand the matches.
 #
-# It expects a 'nm' with the POSIX '-P' option, but everyone has one of
-# those, right?
+# It uses elfdump when present (native), GNU readelf otherwise.
 # It depends on the GNU version of c++filt, since it must understand the
 # GNU mangling style.
 
-use File::Glob ':glob';
 use FileHandle;
 use IPC::Open2;
 
+# Enforce C locale.
+$ENV{'LC_ALL'} = "C";
+$ENV{'LANG'} = "C";
+
 # Input version script, GNU style.
 my $symvers = shift;
 
@@ -46,33 +48,104 @@ foreach $file (@ARGV) {
     }
 }
 
-# The nm command to use.
-my $nm = $ENV{'NM_FOR_TARGET'} || "nm";
+# We need to detect and ignore hidden symbols.  Solaris nm can only detect
+# this in the harder to parse default output format, and GNU nm not at all,
+# so use elfdump -s in the native case and GNU readelf -s otherwise.
+# GNU objdump -t cannot be used since it produces a variable number of
+# columns.
 
-# Process each symbol.
-open NM,$nm.' -P '.(join ' ',@OBJECTS).'|' or die $!;
-while (<NM>) {
-    my $i;
-    chomp;
+# The path to elfdump.
+my $elfdump = "/usr/ccs/bin/elfdump";
+
+if (-f $elfdump) {
+    open ELFDUMP,$elfdump.' -s '.(join ' ',@OBJECTS).'|' or die $!;
+    my $skip_arsym = 0;
+
+    while (<ELFDUMP>) {
+       chomp;
+
+       # Ignore empty lines.
+       if (/^$/) {
+           # End of archive symbol table, stop skipping.
+           $skip_arsym = 0 if $skip_arsym;
+           next;
+       }
 
-    # nm prints out stuff at the start, ignore it.
-    next if (/^$/);
-    next if (/:$/);
-    # Ignore register (SPARC only), undefined and local symbols.  The
-    # symbol name is optional; Sun nm emits none for local or .bss symbols.
-    next if (/^([^ ]+)?[ \t]+[RUa-z][ \t]+/);
-    # Ignore objects without symbol table.  Message goes to stdout with Sun
-    # nm, while GNU nm emits the corresponding message to stderr.
-    next if (/.* - No symbol table data/);
-
-    # $sym is the name of the symbol.
-    die "unknown nm output $_" if (! /^([^ ]+)[ \t]+[A-Z][ \t]+/);
-    my $sym = $1;
-
-    # Remember symbol.
-    $sym_hash{$sym}++;
+       # Keep skipping until end of archive symbol table.
+       next if ($skip_arsym);
+
+       # Ignore object name header for individual objects and archives.
+       next if (/:$/);
+
+       # Ignore table header lines.
+       next if (/^Symbol Table Section:/);
+       next if (/index.*value.*size/);
+
+       # Start of archive symbol table: start skipping.
+       if (/^Symbol Table: \(archive/) {
+           $skip_arsym = 1;
+           next;
+       }
+
+       # Split table.
+       (undef, undef, undef, undef, $bind, $oth, undef, $shndx, $name) = split;
+
+       # Error out for unknown input.
+       die "unknown input line:\n$_" unless defined($bind);
+
+       # Ignore local symbols.
+       next if ($bind eq "LOCL");
+       # Ignore hidden symbols.
+       next if ($oth eq "H");
+       # Ignore undefined symbols.
+       next if ($shndx eq "UNDEF");
+       # Error out for unhandled cases.
+       if ($bind !~ /^(GLOB|WEAK)/ or $oth ne "D") {
+           die "unhandled symbol:\n$_";
+       }
+
+       # Remember symbol.
+       $sym_hash{$name}++;
+    }
+    close ELFDUMP or die "$elfdump error";
+} else {
+    open READELF, 'readelf -s -W '.(join ' ',@OBJECTS).'|' or die $!;
+    # Process each symbol.
+    while (<READELF>) {
+       chomp;
+
+       # Ignore empty lines.
+       next if (/^$/);
+
+       # Ignore object name header.
+       next if (/^File: .*$/);
+
+       # Ignore table header lines.
+       next if (/^Symbol table.*contains.*:/);
+       next if (/Num:.*Value.*Size/);
+
+       # Split table.
+       (undef, undef, undef, undef, $bind, $vis, $ndx, $name) = split;
+
+       # Error out for unknown input.
+       die "unknown input line:\n$_" unless defined($bind);
+
+       # Ignore local symbols.
+       next if ($bind eq "LOCAL");
+       # Ignore hidden symbols.
+       next if ($vis eq "HIDDEN");
+       # Ignore undefined symbols.
+       next if ($ndx eq "UND");
+       # Error out for unhandled cases.
+       if ($bind !~ /^(GLOBAL|WEAK)/ or $vis ne "DEFAULT") {
+           die "unhandled symbol:\n$_";
+       }
+
+       # Remember symbol.
+       $sym_hash{$name}++;
+    }
+    close READELF or die "readelf error";
 }
-close NM or die "nm error";
 
 ##########
 # The various types of glob patterns.
@@ -87,9 +160,6 @@ my $glob = 'glob';
 # We're currently inside `extern "C++"', which Sun ld doesn't understand.
 my $in_extern = 0;
 
-# We're currently inside a conditional section: just skip it.
-my $in_ifdef = 0;
-
 # The c++filt command to use.  This *must* be GNU c++filt; the Sun Studio
 # c++filt doesn't handle the GNU mangling style.
 my $cxxfilt = $ENV{'CXXFILT'} || "c++filt";
@@ -114,21 +184,12 @@ printf "# Omitted archives with corresponding shared libraries: %s\n",
 print "#\n\n";
 
 while (<F>) {
-    # End of skipped section.
-    if (/^[ \t]*\#endif/) {
-       $in_ifdef = 0;
-       next;
-    }
-
-    # Just skip a conditional section.
-    if ($in_ifdef) { next; }
-
     # Lines of the form '};'
     if (/^([ \t]*)(\}[ \t]*;[ \t]*)$/) {
        $glob = 'glob';
        if ($in_extern) {
            $in_extern--;
-           print "$1##$2";
+           print "$1##$2\n";
        } else {
            print;
        }
@@ -147,15 +208,6 @@ while (<F>) {
        print; next;
     }
 
-    # Special comments that look like C preprocessor conditionals.
-    # Just skip the contents for now.
-    # FIXME: Allow passing in conditionals from the command line to really
-    # control the skipping.
-    if (/^[ \t]*\#ifdef/) {
-       $in_ifdef = 1;
-       next;
-    }
-
     # Comment and blank lines
     if (/^[ \t]*\#/) { print; next; }
     if (/^[ \t]*$/) { print; next; }
@@ -207,9 +259,10 @@ while (<F>) {
     if (/^([ \t]*)([^ \t;{}#]+);?[ \t]*$/) {
        my $ws = $1;
        my $ptn = $2;
-       # Turn the glob into a regex by replacing '*' with '.*'.
+       # Turn the glob into a regex by replacing '*' with '.*', '?' with '.'.
        # Keep $ptn so we can still print the original form.
        ($pattern = $ptn) =~ s/\*/\.\*/g;
+       $pattern =~ s/\?/\./g;
 
        if ($glob eq 'ign') {
            # We're in a local: * section; just continue.