eval 'exec perl "$0" "$1"'
  if $running_under_some_shell;
use File::Find 'find';

# Build a (sorted) VI(M) tags file including GP functions
#
$src=$ARGV[0] || "$ENV{HOME}/PARI/src";
$tmptags="$src/tags.tmp";

# Case sensitive?
$tags = $^O eq 'os2' ? "$src/ctags" : "$src/tags";

@tags = ""; $old = "";
@files = (); find \&filter_c, $src;

# Note that shell uses a different logic than perl,
# so the following `&&' correspond to `||' in shell.
# Assume ctags outputs sorted tags (e.g Exuberant Ctags)
system('exuberant-ctags', '-f', $tmptags, @files)
       && system('ctags-exuberant', '-f', $tmptags, @files)
       && system('ctags', '-dT', '-o', $tmptags, @files) # gctags
       && system('ctags', '-f', $tmptags, @files)
       && die("ctags failed");

getnames("$src/gp/gp_init.h");
getnames("$src/language/init.h");
geterrs("$src/language/errmsg.c");
open(T,"$tmptags");
for (sort(@gp))
{
  ($a, $b) = split(/#/);
  if ($a eq $old) { push(@tags,"$b$rest\n"); next; }
  $old = $a;
  while(<T>)
  {
    push(@tags,$_);
    if (/^$a(.*)/) { $rest="$1"; push(@tags,"$b$rest\n"); last; }
  }
}
while(<T>) { push(@tags,$_); }
close(T);

open(OUT,">$tags");
print OUT sort(@tags);
unlink $tmptags;

sub getnames
{
  open(A,$_[0]);
  while (<A>)
  {
    if (/^entree functions_/../^$/)
    {
      push(@gp,"$2#$1") if (/[^"]*"([^"]*)".*\(void\*\) *([^,]*)/);
    }
  }
  close(A);
}

sub geterrs
{
  my $f = $_[0];
  open(A,$f);
  while (<A>)
  {
    if (m,/(\*\s*\w+\s*\*)/,)
    {
      $e = $pat = $1;
      $e =~ s/\W*(\w+)\W*/$1/;
      push(@tags, "$e\t$f\t/$pat\n");
    }
  }
  close(A);
}

sub filter_c {
  return unless /\.[chy]\Z/ && -f;
  return if (/(tune|kerntest|parse)\.c/);
  push @files, "$File::Find::name";
}
