#!/bin/sh

# Check the consistency of some parts of GPC's documentation.
# Meant to be run by GPC maintainers.
#
# Copyright (C) 2000 Free Software Foundation, Inc.
#
# Author: Frank Heckenbach <frank@pascal.gnu.de>
#
# This file is part of GNU Pascal.
#
# GNU Pascal is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Pascal is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Pascal; see the file COPYING. If not, write to the
# Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.

# This script requires bash. Since bash cannot be assumed to be in
# /bin, /usr/bin or any other certain place, we cannot use it in the
# first line. So we use /bin/sh, which can be assumed to exist. Then
# we check if it's actually bash, and if not, try to re-run the
# script with bash.
if [ x"$BASH" = x ]; then
  if [ x"$RERUN_BASH_TRIED" != x ]; then
    echo "`basename $0`: cannot run, \`bash' is either not bash or a very old version" >&2
    exit 1
  else
    RERUN_BASH_TRIED=1; export RERUN_BASH_TRIED
    exec bash $0 "$@"
    echo "`basename $0`: cannot run bash" >&2
    exit 1
  fi
fi

# Initialization

if [ "x$1" = "x-h" ] || [ "x$1" = "x--help" ]; then
  echo "Usage: `basename $0` [mode]"
  echo "Modes, applying to reference entries:"
  echo "  -d  List all differences (default)"
  echo "  -m  Create menu entries for missing items"
  echo "  -s  Create skeleton nodes for missing items"
  exit
fi

if [ x"$GPC_SRCDIR" = x ]; then
  echo "GPC_SRCDIR must be set" >&2
  exit 1
fi

if [ -e "$GPC_SRCDIR/gcc/p/gpc.c" ]; then
  PDIR=$GPC_SRCDIR/gcc/p
elif [ -e "$GPC_SRCDIR/p/gpc.c" ]; then
  PDIR=$GPC_SRCDIR/p
else
  echo "Invalid GPC_SRCDIR" >&2
  exit 1
fi

# This should work even with a crippled sed...
dir=`echo $0 | sed -e 's,\(.\)/*[^/]*$,\1,'` || exit 1
sed=`$dir/find-sed -s` || exit 1

cd $PDIR || exit 1

if [ x"$TMPDIR" = x ]; then
  TMPDIR=/tmp
fi
TMPFILE=$TMPDIR/check-doc.$$
rm -rf $TMPFILE* || exit 1
touch $TMPFILE-1 $TMPFILE-2 $TMPFILE-3 $TMPFILE-4 || exit 1

# Check that reference entries are sorted alphabetically

if true; then echo "@@ reference checks skipped..." >&2; else #@@

$sed < doc/reference.texi -ne '/^@menu/,/^@end menu/{s/^* //;s/::$//p;}' > $TMPFILE-2 ||
  { echo 'error in sed (1)' >&2; rm -rf $TMPFILE*; exit 1; }

sort -f $TMPFILE-2 > $TMPFILE-1 ||
  { echo 'error in sort (1)' >&2; rm -rf $TMPFILE*; exit 1; }

if ! diff -U1 $TMPFILE-2 $TMPFILE-1; then
  echo 'Reference is not sorted correctly.'
  echo ''
fi

$sed < doc/reference.texi -ne 's/@node //p' > $TMPFILE-3 ||
  { echo 'error in sed (2)' >&2; rm -rf $TMPFILE*; exit 1; }

if ! diff -U1 $TMPFILE-3 $TMPFILE-1; then
  echo 'Reference nodes are not sorted correctly.'
  echo ''
fi

# Check the completeness of reference entries

{
  # Keywords
  $sed < gpc.gperf -ne '/^%%/,$s/,.*//p' ||
    { echo 'error in sed (3)' >&2; rm -rf $TMPFILE*; exit 1; }

  # Keyword combinations that deserve their own reference entry
  echo "and then"
  echo "or else"
  echo "to begin do"
  echo "to end do"
  echo "type of"

  # Built-in interfaces
  echo "StandardError"
  echo "StandardInput"
  echo "StandardOutput"

  # Built-in identifiers
  $sed < util.c -ne '/KItable.*=/,/;$/{/^[ \t]*{[ \t]*"/{s///;s/".*//p;};}' ||
    { echo 'error in sed (4)' >&2; rm -rf $TMPFILE*; exit 1; }
  $sed < util.c -ne '/.*declare_known_id[ \t]*([ \t]*"/{s///;s/".*//p;}' ||
    { echo 'error in sed (5)' >&2; rm -rf $TMPFILE*; exit 1; }
} | sort -fu > $TMPFILE-2 ||
  { echo 'error in sort (2)' >&2; rm -rf $TMPFILE*; exit 1; }

diff -i -U0 $TMPFILE-1 $TMPFILE-2 | grep -v -e '^@@' -e '^---' -e '^+++' > $TMPFILE-3
$sed -ne '/^+/s///p' $TMPFILE-3 > $TMPFILE-1 ||
  { echo 'error in sed (6)' >&2; rm -rf $TMPFILE*; exit 1; }
$sed -ne '/^[^+]/s///p' $TMPFILE-3 > $TMPFILE-2 ||
  { echo 'error in sed (7)' >&2; rm -rf $TMPFILE*; exit 1; }

if [ -s $TMPFILE-2 ]; then
  echo "Superfluous documentation entries:"
  cat $TMPFILE-2
  echo ""
fi

if [ -s $TMPFILE-1 ]; then
  if [ x"$1" = x"-m" ]; then
    $sed -e 's/.*/* &::/' < $TMPFILE-1 ||
      { echo 'error in sed (8)' >&2; rm -rf $TMPFILE*; exit 1; }
  elif [ x"$1" = x"-s" ]; then
    for id in `cat $TMPFILE-1`; do
      cat << EOF
@c ----------------------------------------------------------------------------


@node $id
@unnumberedsec $id
@cindex $id

(Under construction.)

@unnumberedsubsec Syntax

@unnumberedsubsec Description

@unnumberedsubsec Standards

@unnumberedsubsec Example

@unnumberedsubsec See also


EOF
    done
  else
    echo "Missing in documentation:"
    cat $TMPFILE-1
    echo ""
  fi
fi

fi #@@

# Check that all demo programs are referenced

$sed -ne '
  s/@c.*//;
  s/[:;]//g;
  s/@examplehref/:/g;
  s/@xexamplehref/;/g;
  : loop;
  /^[^:;]*:{\([^}]*\)}/{
    s//\1\
      /;
    P;
    s/.*\n//;
    b loop;
  }
  /^[^:;]*;{\([^,}]*\),[^}]*}/{
    s//\1\
      /;
    P;
    s/.*\n//;
    b loop;
  }
' < doc/about.texi > $TMPFILE-1 ||
  { echo 'error in sed (9)' >&2; rm -rf $TMPFILE*; exit 1; }

sort -u < $TMPFILE-1 > $TMPFILE-2 ||
  { echo 'error in sort (3)' >&2; rm -rf $TMPFILE*; exit 1; }

ls demos | grep -v -e '^README$' -e '^hello.pas$' > $TMPFILE-3 ||
  { echo 'error in ls (1)' >&2; rm -rf $TMPFILE*; exit 1; }

diff -U0 $TMPFILE-3 $TMPFILE-2 | grep -v -e '^@@' -e '^---' -e '^+++' > $TMPFILE-4

if [ -s $TMPFILE-4 ]; then
  echo "Difference in demo programs reference in the \`about' chapter:"
  cat $TMPFILE-4
  echo ""
fi

# Check demo program anchors

if grep -n '.@anch' < doc/about.texi > $TMPFILE-2; then
  echo "\`@anch' must be at the beginning of a line:"
  cat $TMPFILE-2
  echo ""
fi

$sed -ne 's/\.pas$//p' < $TMPFILE-1 > $TMPFILE-2 ||
  { echo 'error in sed (10)' >&2; rm -rf $TMPFILE*; exit 1; }

$sed -ne '
  /@c DEMO-START/,/@c DEMO-END/{
    s/@c.*//;
    s/://g;
    s/@anch/:/g;
    : loop;
    /^[^:]*:{\([^,}]*\),[^}]*}/{
      s//\1\
        /;
      P;
      s/.*\n//;
      b loop;
    }
  }
' < doc/about.texi > $TMPFILE-3 ||
  { echo 'error in sed (11)' >&2; rm -rf $TMPFILE*; exit 1; }

diff -U0 $TMPFILE-2 $TMPFILE-3 | grep -v -e '^@@' -e '^---' -e '^+++' > $TMPFILE-4

if [ -s $TMPFILE-4 ]; then
  echo "Demo program anchors in the \`about' chapter don't match:"
  cat $TMPFILE-4
  echo ""
fi

# Extract doc demo programs

rm -rf $TMPFILE  ||
  { rm -rf $TMPFILE*; exit 1; }
mkdir $TMPFILE ||
  { echo 'error in mkdir' >&2; rm -rf $TMPFILE*; exit 1; }
cd $TMPFILE ||
  { echo 'error in cd' >&2; rm -rf $TMPFILE*; exit 1; }

$PDIR/script/extract-doc-demos $PDIR/doc/*.texi ||
  { echo 'error in extract-doc-demos' >&2; cd /; rm -rf $TMPFILE*; exit 1; }

# Check for doc demo program names that are problematic on some file systems

ls > $TMPFILE-1 ||
  { echo 'error in ls (2)' >&2; rm -rf $TMPFILE-1 $TMPFILE-2 $TMPFILE-3; exit 1; }

$sed -e 's/\(.\{0,14\}\).*/\1/' < $TMPFILE-1 | sort > $TMPFILE-2 ||
  { echo 'error in sed (12)' >&2; rm -rf $TMPFILE*; exit 1; }
if [ x"`uniq -d $TMPFILE-2`" != x ]; then
  echo "Doc demo programs matching in the first 14 characters:"
  uniq -d $TMPFILE-2
fi

$sed -e 's/\([^.]\{0,8\}\)[^.]*\(\(\.[^.]\{0,3\}\).*\)\{0,1\}/\1\3/' < $TMPFILE-1 | sort  > $TMPFILE-2 ||
  { echo 'error in sed (13)' >&2; rm -rf $TMPFILE*; exit 1; }
if [ x"`uniq -d $TMPFILE-2`" != x ]; then
  echo "Doc demo programs matching in the first 8+3 characters:"
  uniq -d $TMPFILE-2
fi

# Try to compile all doc demo programs

for file in *.pas; do
  if grep -i "program.*;" $file > /dev/null; then
    gpc --automake -Wall -O2 $file ||
      { echo "error while compiling $file" >&2; }
  fi
done
cd /

rm -rf $TMPFILE* || exit 1
