#! /bin/sh

# Script to test that all the symbols of a shared object are as expected.

set -e

LANG=C # Ensure stable ordering of `sort` output
export LANG

if [ "$1" = "" -o "$2" = "" ] ; then
  echo "Usage: $0 <so_dir> <manifest_dir>" >&2
  exit 1
fi

input_dir="$1"
manifest_dir="$2"

sed=sed
grep=grep
# Helpers for Solaris
if [ -f /usr/bin/gsed ] ; then
  sed=/usr/bin/gsed
fi
if [ -f /usr/bin/ggrep ] ; then
  grep=/usr/bin/ggrep
fi

nm="nm -B -D"
if [ "`uname -s`" = "Linux" ]; then
  nm="$nm --with-symbol-versions"
elif [ "`uname -s`" = "SunOS" ]; then
  nm="nm -p -h -D -g"
elif [ "`uname -s`" = "Darwin" ]; then
  nm="nm -B -g"
fi

supports_versions=1
if [ "`uname -s`" = "Darwin" ]; then
  supports_versions=0
elif [ "`uname -s`" = "FreeBSD" ]; then
  # Highly annoyingly, FreeBSD's nm doesn't show symbol versions, so we just
  # skip checking it.
  supports_versions=0
elif [ "`uname -s`" = "SunOS" ]; then
  # Similarly for Solaris.
  supports_versions=0
fi

so_ext=so
so_mangling() { cat; }
if [ "`uname -s`" = "Darwin" ]; then
  so_ext=dylib
  so_mangling()
    {
    sed -E -e 's/_([_0-9a-zA-Z]+)$/\1/g'
    }
fi

for so_name in "libpcre2-8" "libpcre2-16" "libpcre2-32" "libpcre2-posix"; do
  expected_file="$manifest_dir/manifest-$so_name.so"
  so_file="$input_dir/$so_name.$so_ext"
  base=`basename $expected_file`

  $nm "$so_file" | \
    $sed -E -e 's/^[0-9a-fA-F]* *//g' | \
    $grep -E -v '^[Uw] ' | \
    $grep -E -v '^A PCRE2_' | \
    $grep -E -v ' (_init|_fini)$' | \
    $grep -E -v ' (_end|_DYNAMIC|_GLOBAL_OFFSET_TABLE_|_PROCEDURE_LINKAGE_TABLE_|_edata|_etext)$' | \
    so_mangling | \
    sort \
    > "$base.actual"

  if [ $supports_versions -eq 0 ]; then
    $sed -E -e 's/@.*$//' "$expected_file" \
      > "$base.expected"
  else
    cp "$expected_file" "$base.expected"
  fi

  if ! diff -u "$base.expected" "$base.actual"; then
    echo "Shared object contents for $so_file differ from expected"

    echo "===Actual==="
    cat "$base.actual"
    echo "===End==="

    exit 1
  fi

  echo "Shared object contents for $so_file match expected"
  rm -f "$base.expected" "$base.actual"

done
