SPASS-3.7/0000777000374100037200000000000011340746541007267 500000000000000SPASS-3.7/aclocal.m40000644000374100037200000010135611340746526011054 00000000000000# generated automatically by aclocal 1.10.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(AC_AUTOCONF_VERSION, [2.61],, [m4_warning([this file was generated for autoconf 2.61. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.10' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.10.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.10.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 13 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.60])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/ac_prog_perl_version.m4]) SPASS-3.7/LICENCE0000644000374100037200000000301211320345367010163 00000000000000Copyright 1996-2010 Max Planck Institute for Informatics. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MAX PLANCK INSTITUTE FOR INFORMATICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the Max Planck Institute for Informatics. SPASS-3.7/m4/0000777000374100037200000000000011340746537007614 500000000000000SPASS-3.7/m4/install-sh0000755000374100037200000003246411340746531011537 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2006-12-25.00 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: SPASS-3.7/m4/texinfo.tex0000644000374100037200000105275711340746531011741 00000000000000% texinfo.tex -- TeX macros to handle Texinfo files. % % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % \def\texinfoversion{2007-12-02.17} % % Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 2007, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, % 2007 Free Software Foundation, Inc. % % This texinfo.tex file 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 3 of the % License, or (at your option) any later version. % % This texinfo.tex file 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 this program. If not, see . % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without % restriction. (This has been our intent since Texinfo was invented.) % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: % http://www.gnu.org/software/texinfo/ (the Texinfo home page), or % ftp://tug.org/tex/texinfo.tex % (and all CTAN mirrors, see http://www.ctan.org). % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % % Send bug reports to bug-texinfo@gnu.org. Please include including a % complete document in each bug report with which we can reproduce the % problem. Patches are, of course, greatly appreciated. % % To process a Texinfo manual with TeX, it's most reliable to use the % texi2dvi shell script that comes with the distribution. For a simple % manual foo.texi, however, you can get away with this: % tex foo.texi % texindex foo.?? % tex foo.texi % tex foo.texi % dvips foo.dvi -o # or whatever; this makes foo.ps. % The extra TeX runs get the cross-reference information correct. % Sometimes one run after texindex suffices, and sometimes you need more % than two; texi2dvi does it as many times as necessary. % % It is possible to adapt texinfo.tex for other languages, to some % extent. You can get the existing language-specific files from the % full Texinfo distribution. % % The GNU Texinfo home page is http://www.gnu.org/software/texinfo. \message{Loading texinfo [version \texinfoversion]:} % If in a .fmt file, print the version number % and turn on active characters that we couldn't do earlier because % they might have appeared in the input file name. \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. % For @tex, we can use \tabalign. \let\+ = \relax % Save some plain tex macros whose names we will redefine. \let\ptexb=\b \let\ptexbullet=\bullet \let\ptexc=\c \let\ptexcomma=\, \let\ptexdot=\. \let\ptexdots=\dots \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! \let\ptexfootnote=\footnote \let\ptexgtr=> \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexnewwrite\newwrite \let\ptexnoindent=\noindent \let\ptexplus=+ \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J % Use TeX 3.0's \inputlineno to get the line number, for better error % messages, but if we're using an old version of TeX, don't do anything. % \ifx\inputlineno\thisisundefined \let\linenumber = \empty % Pre-3.0. \else \def\linenumber{l.\the\inputlineno:\space} \fi % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi \ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi \ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi \ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi \ifx\putwordof\undefined \gdef\putwordof{of}\fi \ifx\putwordon\undefined \gdef\putwordon{on}\fi \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi \ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi \ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi % \ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi \ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi \ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi \ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi \ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi \ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi \ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi \ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi \ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi \ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi \ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi \ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi % \ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi \ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi \ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi % Since the category of space is not known, we have to be careful. \chardef\spacecat = 10 \def\spaceisspace{\catcode`\ =\spacecat} % sometimes characters are active, so we need control sequences. \chardef\colonChar = `\: \chardef\commaChar = `\, \chardef\dashChar = `\- \chardef\dotChar = `\. \chardef\exclamChar= `\! \chardef\lquoteChar= `\` \chardef\questChar = `\? \chardef\rquoteChar= `\' \chardef\semiChar = `\; \chardef\underChar = `\_ % Ignore a token. % \def\gobble#1{} % The following is used inside several \edef's. \def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. \hyphenation{ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script ap-pen-dix bit-map bit-maps data-base data-bases eshell fall-ing half-way long-est man-u-script man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces spell-ing spell-ings stand-alone strong-est time-stamp time-stamps which-ever white-space wide-spread wrap-around } % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight % For a final copy, take out the rectangles % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % \def\finalout{\overfullrule=0pt} % @| inserts a changebar to the left of the current line. It should % surround any changed text. This approach does *not* work if the % change spans more than two lines of output. To handle that, we would % have adopt a much more difficult approach (putting marks into the main % vertical list for the beginning and end of each change). % \def\|{% % \vadjust can only be used in horizontal mode. \leavevmode % % Append this vertical mode material after the current line in the output. \vadjust{% % We want to insert a rule with the height and depth of the current % leading; that is exactly what \strutbox is supposed to record. \vskip-\baselineskip % % \vadjust-items are inserted at the left edge of the type. So % the \llap here moves out into the left-hand margin. \llap{% % % For a thicker or thinner bar, change the `1pt'. \vrule height\baselineskip width1pt % % This is the space between the bar and the text. \hskip 12pt }% }% } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make % some effort to order the tracing commands to reduce output in the log % file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% \def\loggingall{% \tracingstats2 \tracingpages1 \tracinglostchars2 % 2 gives us more in etex \tracingparagraphs1 \tracingoutput1 \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen \ifx\eTeXversion\undefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 \tracingnesting2 \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex \errorcontextlines16 }% % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % \def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount \removelastskip\penalty-50\smallskip\fi\fi} \def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi\fi} \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} % For @cropmarks command. % Do @cropmarks to get crop marks. % \newif\ifcropmarks \let\cropmarks = \cropmarkstrue % % Dimensions to add cropmarks at corners. % Added by P. A. MacKay, 12 Nov. 1986 % \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines \newdimen\cornerlong \cornerlong=1pc \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Output a mark which sets \thischapter, \thissection and \thiscolor. % We dump everything together because we only have one kind of mark. % This works because we only use \botmark / \topmark, not \firstmark. % % A mark contains a subexpression of the \ifcase ... \fi construct. % \get*marks macros below extract the needed part using \ifcase. % % Another complication is to let the user choose whether \thischapter % (\thissection) refers to the chapter (section) in effect at the top % of a page, or that at the bottom of a page. The solution is % described on page 260 of The TeXbook. It involves outputting two % marks for the sectioning macros, one before the section break, and % one after. I won't pretend I can describe this better than DEK... \def\domark{% \toks0=\expandafter{\lastchapterdefs}% \toks2=\expandafter{\lastsectiondefs}% \toks4=\expandafter{\prevchapterdefs}% \toks6=\expandafter{\prevsectiondefs}% \toks8=\expandafter{\lastcolordefs}% \mark{% \the\toks0 \the\toks2 \noexpand\or \the\toks4 \the\toks6 \noexpand\else \the\toks8 }% } % \topmark doesn't work for the very first chapter (after the title % page or the contents), so we use \firstmark there -- this gets us % the mark with the chapter defs, unless the user sneaks in, e.g., % @setcolor (or @url, or @link, etc.) between @contents and the very % first @chapter. \def\gettopheadingmarks{% \ifcase0\topmark\fi \ifx\thischapter\empty \ifcase0\firstmark\fi \fi } \def\getbottomheadingmarks{\ifcase1\botmark\fi} \def\getcolormarks{\ifcase2\topmark\fi} % Avoid "undefined control sequence" errors. \def\lastchapterdefs{} \def\lastsectiondefs{} \def\prevchapterdefs{} \def\prevsectiondefs{} \def\lastcolordefs{} % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} \newbox\headlinebox \newbox\footlinebox % \onepageout takes a vbox as an argument. Note that \pagecontents % does insertions, but you have to call it yourself. \def\onepageout#1{% \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if % the page break happens to be in the middle of an example. % We don't want .vr (or whatever) entries like this: % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} % "\acronym" won't work when it's read back in; % it needs to be % {\code {{\tt \backslashcurfont }acronym} \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize \vskip-\topandbottommargin \vtop to0pt{% \line{\ewtop\hfil\ewtop}% \nointerlineskip \line{% \vbox{\moveleft\cornerthick\nstop}% \hfill \vbox{\moveright\cornerthick\nstop}% }% \vss}% \vskip\topandbottommargin \line\bgroup \hfil % center the page within the outer (page) hsize. \ifodd\pageno\hskip\bindingoffset\fi \vbox\bgroup \fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. % (We lessened \vsize for it in \oddfootingyyy.) % The \baselineskip=24pt in plain's \makefootline has no effect. \vskip 24pt \unvbox\footlinebox \fi % \ifcropmarks \egroup % end of \vbox\bgroup \hfil\egroup % end of (centering) \line\bgroup \vskip\topandbottommargin plus1fill minus1fill \boxmaxdepth = \cornerthick \vbox to0pt{\vss \line{% \vbox{\moveleft\cornerthick\nsbot}% \hfill \vbox{\moveright\cornerthick\nsbot}% }% \nointerlineskip \line{\ewbot\hfil\ewbot}% }% \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox }% end of group with \indexdummies \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi \dimen@=\dp#1\relax \unvbox#1\relax \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } % Here are the rules for the cropmarks. Note that they are % offset so that the space between them is truly \outerhsize or \outervsize % (P. A. MacKay, 12 November, 1986) % \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} \def\nstop{\vbox {\hrule height\cornerthick depth\cornerlong width\cornerthick}} \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} \def\nsbot{\vbox {\hrule height\cornerlong depth\cornerthick width\cornerthick}} % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% \def\argtorun{#2}% \begingroup \obeylines \spaceisspace #1% \parseargline\empty% Insert the \empty token, see \finishparsearg below. } {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. \argremovecomment #1\comment\ArgTerm% }% } % First remove any @comment, then any @c comment. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} % Each occurence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo % This space token undergoes the same procedure and is eventually removed % by \finishparsearg. % \def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} \def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: \let\temp\finishparsearg \else \let\temp\argcheckspaces \fi % Put the space token in: \temp#1 #3\ArgTerm } % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \argtorun. % (Similarily, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % \def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} % % Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % favourite TeX trick. --kasal, 16nov03 \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } \def\doparseargdef#1#2{% \def#2{\parsearg#1}% \def#1##1% } % Several utility definitions with active space: { \obeyspaces \gdef\obeyedspace{ } % Make each space character in the input produce a normal interword % space in the output. Don't allow a line break at this space, as this % is used only in environments like @example, where each line of input % should produce a line of output anyway. % \gdef\sepspaces{\obeyspaces\let =\tie} % If an index command is used in an @example environment, any spaces % therein should become regular spaces in the raw index file, not the % expansion of \tie (\leavevmode \penalty \@M \ ). \gdef\unsepspaces{\let =\space} } \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} % Define the framework for environments in texinfo.tex. It's used like this: % % \envdef\foo{...} % \def\Efoo{...} % % It's the responsibility of \envdef to insert \begingroup before the % actual body; @end closes the group after calling \Efoo. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they % are not treated as enviroments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) % At runtime, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty % ... but they get defined via ``\envdef\foo{...}'': \long\def\envdef#1#2{\def#1{\startenvironment#1#2}} \def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} % Check whether we're in the right environment: \def\checkenv#1{% \def\temp{#1}% \ifx\thisenv\temp \else \badenverr \fi } % Evironment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, not \inenvironment\thisenv}% } \def\inenvironment#1{% \ifx#1\empty out of any environment% \else in environment \expandafter\string#1% \fi } % @end foo executes the definition of \Efoo. % But first, it executes a specialized version of \checkenv % \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup \fi } \newhelp\EMsimple{Press RETURN to continue.} %% Simple single-character @ commands % @@ prints an @ % Kludge this until the fonts are right (grr). \def\@{{\tt\char64}} % This is turned off because it was never documented % and you can use @w{...} around a quote to suppress ligatures. %% Define @` and @' to be the same as ` and ' %% but suppressing ligatures. %\def\`{{`}} %\def\'{{'}} % Used to generate quoted braces. \def\mylbrace {{\tt\char123}} \def\myrbrace {{\tt\char125}} \let\{=\mylbrace \let\}=\myrbrace \begingroup % Definitions to produce \{ and \} commands for indices, % and @{ and @} for the aux/toc files. \catcode`\{ = \other \catcode`\} = \other \catcode`\[ = 1 \catcode`\] = 2 \catcode`\! = 0 \catcode`\\ = \other !gdef!lbracecmd[\{]% !gdef!rbracecmd[\}]% !gdef!lbraceatcmd[@{]% !gdef!rbraceatcmd[@}]% !endgroup % @comma{} to avoid , parsing problems. \let\comma = , % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \c \let\dotaccent = \. \def\ringaccent#1{{\accent23 #1}} \let\tieaccent = \t \let\ubaraccent = \b \let\udotaccent = \d % Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} \def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} \def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} \def\jmacro{j} \def\dotless#1{% \def\temp{#1}% \ifx\temp\imacro \ptexi \else\ifx\temp\jmacro \j \else \errmessage{@dotless can be used only with i or j}% \fi\fi } % The \TeX{} logo, as in plain, but resetting the spacing so that a % period following counts as ending a sentence. (Idea found in latex.) % \edef\TeX{\TeX \spacefactor=1000 } % @LaTeX{} logo. Not quite the same results as the definition in % latex.ltx, since we use a different font for the raised A; it's most % convenient for us to use an explicitly smaller font, rather than using % the \scriptstyle font (since we don't reset \scriptstyle and % \scriptscriptstyle). % \def\LaTeX{% L\kern-.36em {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% \kern-.15em \TeX } % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and % since \penalty is valid in vertical mode, we'd end up putting the % penalty on the vertical list instead of in the new paragraph. {\catcode`@ = 11 % Avoid using \@M directly, because that causes trouble % if the definition is written into an index file. \global\let\tiepenalty = \@M \gdef\tie{\leavevmode\penalty\tiepenalty\ } } % @: forces normal size whitespace following. \def\:{\spacefactor=1000 } % @* forces a line break. \def\*{\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. \def\.{.\spacefactor=\endofsentencespacefactor\space} % @! is an end-of-sentence bang. \def\!{!\spacefactor=\endofsentencespacefactor\space} % @? is an end-of-sentence query. \def\?{?\spacefactor=\endofsentencespacefactor\space} % @frenchspacing on|off says whether to put extra space after punctuation. % \def\onword{on} \def\offword{off} % \parseargdef\frenchspacing{% \def\temp{#1}% \ifx\temp\onword \plainfrenchspacing \else\ifx\temp\offword \plainnonfrenchspacing \else \errhelp = \EMsimple \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% \fi\fi } % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would % produce a whole line of output instead of starting the paragraph. \def\w#1{\leavevmode\hbox{#1}} % @group ... @end group forces ... to be all on one page, by enclosing % it in a TeX vbox. We use \vtop instead of \vbox to construct the box % to keep its height that of a normal line. According to the rules for % \topskip (p.114 of the TeXbook), the glue inserted is % max (\topskip - \ht (first item), 0). If that height is large, % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % % Another complication is that the group might be very large. This can % cause the glue on the previous page to be unduly stretched, because it % does not have much material. In this case, it's better to add an % explicit \vfill so that the extra space is at the bottom. The % threshold for doing this is if the group is more than \vfilllimit % percent of a page (\vfilllimit can be changed inside of @tex). % \newbox\groupbox \def\vfilllimit{0.7} % \envdef\group{% \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi \startsavinginserts % \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after % the `@group' to put extra space in the output. Since @group % should appear on a line by itself (according to the Texinfo % manual), we don't worry about eating any user text. \comment } % % The \vtop produces a box with normal height and large depth; thus, TeX puts % \baselineskip glue before it, and (when the next line of text is done) % \lineskip glue after it. Thus, space below is not quite equal to space % above. But it's pretty close. \def\Egroup{% % To get correct interline space between the last line of the group % and the first line afterwards, we have to propagate \prevdepth. \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). \dimen2 = \pageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 \ifdim \pagetotal < \vfilllimit\pageheight \page \fi \fi \box\groupbox \prevdepth = \dimen1 \checkinserts } % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % \newhelp\groupinvalidhelp{% group can only be used in environments such as @example,^^J% where each line of input produces a line of output.} % @need space-in-mils % forces a page break if there is not space-in-mils remaining. \newdimen\mil \mil=0.001in % Old definition--didn't work. %\parseargdef\need{\par % %% This method tries to make TeX break the page naturally %% if the depth of the box does not fit. %{\baselineskip=0pt% %\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak %\prevdepth=-1000pt %}} \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % % If the @need value is less than one line space, it's useless. \dimen0 = #1\mil \dimen2 = \ht\strutbox \advance\dimen2 by \dp\strutbox \ifdim\dimen0 > \dimen2 % % Do a \strut just to make the height of this box be normal, so the % normal leading is inserted relative to the preceding line. % And a page break here is fine. \vtop to #1\mil{\strut\vfil}% % % TeX does not even consider page breaks if a penalty added to the % main vertical list is 10000 or more. But in order to see if the % empty box we just added fits on the page, we must make it consider % page breaks. On the other hand, we don't want to actually break the % page after the empty box. So we use a penalty of 9999. % % There is an extremely small chance that TeX will actually break the % page at this \penalty, if there are no other feasible breakpoints in % sight. (If the user is using lots of big @group commands, which % almost-but-not-quite fill up a page, TeX will have a hard time doing % good page breaking, for example.) However, I could not construct an % example where a page broke at this \penalty; if it happens in a real % document, then we can reconsider our strategy. \penalty9999 % % Back up by the size of the box, whether we did a page break or not. \kern -#1\mil % % Do not allow a page break right after this kern. \nobreak \fi } % @br forces paragraph break (and is undocumented). \let\br = \par % @page forces the start of a new page. % \def\page{\par\vfill\supereject} % @exdent text.... % outputs text on separate line in roman font, starting at standard page margin % This records the amount of indent in the innermost environment. % That's how much \exdent should take out. \newskip\exdentamount % This defn is used inside fill environments such as @defun. \parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. \parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount \leftline{\hskip\leftskip{\rm#1}}}} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion % class. WHICH is `l' or `r'. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} % \def\doinmargin#1#2{\strut\vadjust{% \nobreak \kern-\strutdepth \vtop to \strutdepth{% \baselineskip=\strutdepth \vss % if you have multiple lines of stuff to put here, you'll need to % make the vbox yourself of the appropriate size. \ifx#1l% \llap{\ignorespaces #2\hskip\inmarginspacing}% \else \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% \fi \null }% }} \def\inleftmargin{\doinmargin l} \def\inrightmargin{\doinmargin r} % % @inmargin{TEXT [, RIGHT-TEXT]} % (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; % else use TEXT for both). % \def\inmargin#1{\parseinmargin #1,,\finish} \def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \def\lefttext{#1}% have both texts \def\righttext{#2}% \else \def\lefttext{#1}% have only one text \def\righttext{#1}% \fi % \ifodd\pageno \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin \else \def\temp{\inleftmargin\lefttext}% \fi \temp } % @include file insert text of that file as input. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% \makevalueexpandable \def\temp{\input #1 }% \expandafter }\temp \popthisfilestack } \def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other \catcode`_=\other \catcode`|=\other \catcode`<=\other \catcode`>=\other \catcode`+=\other \catcode`-=\other } \def\pushthisfilestack{% \expandafter\pushthisfilestackX\popthisfilestack\StackTerm } \def\pushthisfilestackX{% \expandafter\pushthisfilestackY\thisfile\StackTerm } \def\pushthisfilestackY #1\StackTerm #2\StackTerm {% \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% } \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} \def\thisfile{} % @center line % outputs that line, centered. % \parseargdef\center{% \ifhmode \let\next\centerH \else \let\next\centerV \fi \next{\hfil \ignorespaces#1\unskip \hfil}% } \def\centerH#1{% {% \hfil\break \advance\hsize by -\leftskip \advance\hsize by -\rightskip \line{#1}% \break }% } \def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} \let\c=\comment % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. % NCHARS can also be the word `asis' or `none'. % We cannot feasibly implement @paragraphindent asis, though. % \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % \parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \defaultparindent = 0pt \else \defaultparindent = #1em \fi \fi \parindent = \defaultparindent } % @exampleindent NCHARS % We'll use ems for NCHARS like @paragraphindent. % It seems @exampleindent asis isn't necessary, but % I preserve it to make it similar to @paragraphindent. \parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \lispnarrowing = 0pt \else \lispnarrowing = #1em \fi \fi } % @firstparagraphindent WORD % If WORD is `none', then suppress indentation of the first paragraph % after a section heading. If WORD is `insert', then do indent at such % paragraphs. % % The paragraph indentation is suppressed or not by calling % \suppressfirstparagraphindent, which the sectioning commands do. % We switch the definition of this back and forth according to WORD. % By default, we suppress indentation. % \def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} \def\insertword{insert} % \parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent \else\ifx\temp\insertword \let\suppressfirstparagraphindent = \relax \else \errhelp = \EMsimple \errmessage{Unknown @firstparagraphindent option `\temp'}% \fi\fi } % Here is how we actually suppress indentation. Redefine \everypar to % \kern backwards by \parindent, and then reset itself to empty. % % We also make \indent itself not actually do anything until the next % paragraph. % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% \restorefirstparagraphindent \indent }% \gdef\noindent{% \restorefirstparagraphindent \noindent }% \global\everypar = {% \kern -\parindent \restorefirstparagraphindent }% } \gdef\restorefirstparagraphindent{% \global \let \indent = \ptexindent \global \let \noindent = \ptexnoindent \global \everypar = {}% } % @asis just yields its argument. Used with @table, for example. % \def\asis#1{#1} % @math outputs its argument in math mode. % % One complication: _ usually means subscripts, but it could also mean % an actual _ character, as in @math{@var{some_variable} + 1}. So make % _ active, and distinguish by seeing if the current family is \slfam, % which is what @var uses. { \catcode`\_ = \active \gdef\mathunderscore{% \catcode`\_=\active \def_{\ifnum\fam=\slfam \_\else\sb\fi}% } } % Another complication: we want \\ (and @\) to output a \ character. % FYI, plain.tex uses \\ as a temporary control sequence (why?), but % this is not advertised and we don't care. Texinfo does not % otherwise define @\. % % The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% \tex \mathunderscore \let\\ = \mathbackslash \mathactive $\finishmath } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % Some active characters (such as <) are spaced differently in math. % We have to reset their definitions in case the @math was an argument % to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active \catcode`< = \active \catcode`> = \active \catcode`+ = \active \gdef\mathactive{% \let^ = \ptexhat \let< = \ptexless \let> = \ptexgtr \let+ = \ptexplus } } % @bullet and @minus need the same treatment as @math, just above. \def\bullet{$\ptexbullet$} \def\minus{$-$} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in the cm % typewriter fonts as three actual period characters; on the other hand, % in other typewriter fonts three periods are wider than 1.5em. So do % whichever is larger. % \def\dots{% \leavevmode \setbox0=\hbox{...}% get width of three periods \ifdim\wd0 > 1.5em \dimen0 = \wd0 \else \dimen0 = 1.5em \fi \hbox to \dimen0{% \hskip 0pt plus.25fil .\hskip 0pt plus1fil .\hskip 0pt plus1fil .\hskip 0pt plus.5fil }% } % @enddots{} is an end-of-sentence ellipsis. % \def\enddots{% \dots \spacefactor=\endofsentencespacefactor } % @comma{} is so commas can be inserted into text without messing up % Texinfo's parsing. % \let\comma = , % @refill is a no-op. \let\refill=\relax % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate (before @setfilename). % \newif\iflinks \linkstrue % by default we want the aux files. \let\novalidate = \linksfalse % @setfilename is done at the beginning of every texinfo file. % So open here the files we need to have open while reading the input. % This makes it possible to make a .fmt file for texinfo. \def\setfilename{% \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks \tryauxfile % Open the new aux file. TeX will close it automatically at exit. \immediate\openout\auxfile=\jobname.aux \fi % \openindices needs to do some work in any case. \openindices \let\setfilename=\comment % Ignore extra @setfilename cmds. % % If texinfo.cnf is present on the system, read it. % Useful for site-wide @afourpaper, etc. \openin 1 texinfo.cnf \ifeof 1 \else \input texinfo.cnf \fi \closein 1 % \comment % Ignore the actual filename. } % Called from \setfilename. % \def\openindices{% \newindex{cp}% \newcodeindex{fn}% \newcodeindex{vr}% \newcodeindex{tp}% \newcodeindex{ky}% \newcodeindex{pg}% } % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \message{pdf,} % adobe `portable' document format \newcount\tempnum \newcount\lnkcount \newtoks\filename \newcount\filenamelength \newcount\pgn \newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD \newbox\boxA \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as \undefined, % borrowed from ifpdf.sty. \ifx\pdfoutput\undefined \else \ifx\pdfoutput\relax \else \ifcase\pdfoutput \else \pdftrue \fi \fi \fi % PDF uses PostScript string constants for the names of xref targets, % for display in the outlines, and in other places. Thus, we have to % double any backslashes. Otherwise, a name like "\node" will be % interpreted as a newline (\n), followed by o, d, e. Not good. % http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html % (and related messages, the final outcome is that it is up to the TeX % user to double the backslashes and otherwise make the string valid, so % that's what we do). % double active backslashes. % {\catcode`\@=0 \catcode`\\=\active @gdef@activebackslashdouble{% @catcode`@\=@active @let\=@doublebackslash} } % To handle parens, we must adopt a different approach, since parens are % not active characters. hyperref.dtx (which has the same problem as % us) handles it with this amazing macro to replace tokens, with minor % changes for Texinfo. It is included here under the GPL by permission % from the author, Heiko Oberdiek. % % #1 is the tokens to replace. % #2 is the replacement. % #3 is the control sequence with the string. % \def\HyPsdSubst#1#2#3{% \def\HyPsdReplace##1#1##2\END{% ##1% \ifx\\##2\\% \else #2% \HyReturnAfterFi{% \HyPsdReplace##2\END }% \fi }% \xdef#3{\expandafter\HyPsdReplace#3#1\END}% } \long\def\HyReturnAfterFi#1\fi{\fi#1} % #1 is a control sequence in which to do the replacements. \def\backslashparens#1{% \xdef#1{#1}% redefine it as its expansion; the definition is simply % \lastnode when called from \setref -> \pdfmkdest. \HyPsdSubst{(}{\realbackslash(}{#1}% \HyPsdSubst{)}{\realbackslash)}{#1}% } \newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images with PDF output, and none of those formats could be found. (.eps cannot be supported due to the design of the PDF format; use regular TeX (DVI output) for that.)} \ifpdf % % Color manipulation macros based on pdfcolor.tex. \def\cmykDarkRed{0.28 1 1 0.35} \def\cmykBlack{0 0 0 1} % \def\pdfsetcolor#1{\pdfliteral{#1 k}} % Set color, and create a mark which defines \thiscolor accordingly, % so that \makeheadline knows which color to restore. \def\setcolor#1{% \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% \domark \pdfsetcolor{#1}% } % \def\maincolor{\cmykBlack} \pdfsetcolor{\maincolor} \edef\thiscolor{\maincolor} \def\lastcolordefs{} % \def\makefootline{% \baselineskip24pt \line{\pdfsetcolor{\maincolor}\the\footline}% } % \def\makeheadline{% \vbox to 0pt{% \vskip-22.5pt \line{% \vbox to8.5pt{}% % Extract \thiscolor definition from the marks. \getcolormarks % Typeset the headline with \maincolor, then restore the color. \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% }% \vss }% \nointerlineskip } % % \pdfcatalog{/PageMode /UseOutlines} % % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). \def\dopdfimage#1#2#3{% \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% % % pdftex (and the PDF format) support .png, .jpg, .pdf (among % others). Let's try in that order. \let\pdfimgext=\empty \begingroup \openin 1 #1.png \ifeof 1 \openin 1 #1.jpg \ifeof 1 \openin 1 #1.jpeg \ifeof 1 \openin 1 #1.JPG \ifeof 1 \openin 1 #1.pdf \ifeof 1 \errhelp = \nopdfimagehelp \errmessage{Could not find image file #1 for pdf}% \else \gdef\pdfimgext{pdf}% \fi \else \gdef\pdfimgext{JPG}% \fi \else \gdef\pdfimgext{jpeg}% \fi \else \gdef\pdfimgext{jpg}% \fi \else \gdef\pdfimgext{png}% \fi \closein 1 \endgroup % % without \immediate, pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi \ifdim \wd0 >0pt width \imagewidth \fi \ifdim \wd2 >0pt height \imageheight \fi \ifnum\pdftexversion<13 #1.\pdfimgext \else {#1.\pdfimgext}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} % \def\pdfmkdest#1{{% % We have to set dummies so commands such as @code, and characters % such as \, aren't expanded when present in a section title. \indexnofonts \turnoffactive \activebackslashdouble \makevalueexpandable \def\pdfdestname{#1}% \backslashparens\pdfdestname \safewhatsit{\pdfdest name{\pdfdestname} xyz}% }} % % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % % by default, use a color that is dark enough to print on paper as % nearly black, but still distinguishable for online viewing. \def\urlcolor{\cmykDarkRed} \def\linkcolor{\cmykDarkRed} \def\endlink{\setcolor{\maincolor}\pdfendlink} % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% \else \csname#1\endcsname \fi} \def\advancenumber#1{\tempnum=\expnumber{#1}\relax \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % % #1 is the section text, which is what will be displayed in the % outline by the pdf viewer. #2 is the pdf expression for the number % of subentries (or empty, for subsubsections). #3 is the node text, % which might be empty if this toc entry had no corresponding node. % #4 is the page number % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worth the trouble, since most documents are normally structured. \def\pdfoutlinedest{#3}% \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}% \else % Doubled backslashes in the name. {\activebackslashdouble \xdef\pdfoutlinedest{#3}% \backslashparens\pdfoutlinedest}% \fi % % Also double the backslashes in the display string. {\activebackslashdouble \xdef\pdfoutlinetext{#1}% \backslashparens\pdfoutlinetext}% % \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% } % \def\pdfmakeoutlines{% \begingroup % Thanh's hack / proper braces in bookmarks \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace % % Read toc silently, to get counts of subentries for \pdfoutline. \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% \def\thissecnum{0}% \def\thissubsecnum{0}% }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% \def\thissubsecnum{0}% }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% \def\thissubsecnum{##2}% }% \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% \def\thischapnum{0}% \def\thissecnum{0}% \def\thissubsecnum{0}% % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. \def\appentry{\numchapentry}% \def\appsecentry{\numsecentry}% \def\appsubsecentry{\numsubsecentry}% \def\appsubsubsecentry{\numsubsubsecentry}% \def\unnchapentry{\numchapentry}% \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of % subentries, which we calculated on our first read of the .toc above. % % We use the node names as the destinations. \def\numchapentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \def\numsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \def\numsubsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, % since the encoding is unknown. For example, the eogonek from % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % % xx to do this right, we have to translate 8-bit characters to % their "best" equivalent, based on the @documentencoding. Right % now, I guess we'll just let the pdf reader have its way. \indexnofonts \setupdatafile \catcode`\\=\active \otherbackslash \input \tocreadfilename \endgroup } % \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces \ifx\p\space\else\addtokens{\filename}{\PP}% \advance\filenamelength by 1 \fi \fi \nextsp} \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi % make a live url in pdf output. \def\pdfurl#1{% \begingroup % it seems we really need yet another set of dummies; have not % tried to figure out what each command should do in the context % of @url. for now, just make @/ a no-op, that's the only one % people have actually reported a problem with. % \normalturnoffactive \def\@{@}% \let\/=\empty \makevalueexpandable \leavevmode\setcolor{\urlcolor}% \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} \def\maketoks{% \expandafter\poptoks\the\toksA|ENDTOKS|\relax \ifx\first0\adn0 \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 \else \ifnum0=\countA\else\makelink\fi \ifx\first.\let\next=\done\else \let\next=\maketoks \addtokens{\toksB}{\the\toksD} \ifx\first,\addtokens{\toksB}{\space}\fi \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next} \def\makelink{\addtokens{\toksB}% {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \setcolor{\linkcolor}#1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax \let\setcolor = \gobble \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput \message{fonts,} % Change the current font style to #1, remembering it in \curfontstyle. % For now, we do not accumulate font styles: @b{@i{foo}} prints foo in % italics, not bold italics. % \def\setfontstyle#1{% \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. \csname ten#1\endcsname % change the current font } % Select #1 fonts with the current style. % \def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} \def\tt{\fam=\ttfam \setfontstyle{tt}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam \def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} % Default leading. \newdimen\textleading \textleading = 13.2pt % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. % \def\lineskipfactor{.08333} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % % can get a sort of poor man's double spacing by redefining this. \def\baselinefactor{1} % \def\setleading#1{% \dimen0 = #1\relax \normalbaselineskip = \baselinefactor\dimen0 \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% \vrule width0pt height\strutheightpercent\baselineskip depth \strutdepthpercent \baselineskip }% } % PDF CMaps. See also LaTeX's t1.cmap. % % do nothing with this by default. \expandafter\let\csname cmapOT1\endcsname\gobble \expandafter\let\csname cmapOT1IT\endcsname\gobble \expandafter\let\csname cmapOT1TT\endcsname\gobble % if we are producing pdf, and we have \pdffontattr, then define cmaps. % (\pdffontattr was introduced many years ago, but people still run % older pdftex's; it's easy to conditionalize, so we do.) \ifpdf \ifx\pdffontattr\undefined \else \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1-0) %%Title: (TeX-OT1-0 TeX OT1 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1) /Supplement 0 >> def /CMapName /TeX-OT1-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <23> <26> <0023> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 40 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1IT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1IT-0) %%Title: (TeX-OT1IT-0 TeX OT1IT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1IT) /Supplement 0 >> def /CMapName /TeX-OT1IT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <25> <26> <0025> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 42 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <23> <0023> <24> <00A3> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1IT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1TT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1TT-0) %%Title: (TeX-OT1TT-0 TeX OT1TT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1TT) /Supplement 0 >> def /CMapName /TeX-OT1TT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 5 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <21> <26> <0021> <28> <5F> <0028> <61> <7E> <0061> endbfrange 32 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <2191> <0C> <2193> <0D> <0027> <0E> <00A1> <0F> <00BF> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <20> <2423> <27> <2019> <60> <2018> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1TT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% \fi\fi % Set the font macro #1 to the font named #2, adding on the % specified font prefix (normally `cm'). % #3 is the font's design size, #4 is a scale factor, #5 is the CMap % encoding (currently only OT1, OT1IT and OT1TT are allowed, pass % empty to omit). \def\setfont#1#2#3#4#5{% \font#1=\fontprefix#2#3 scaled #4 \csname cmap#5\endcsname#1% } % This is what gets called when #5 of \setfont is empty. \let\cmap\gobble % emacs-page end of cmaps % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. \ifx\fontprefix\undefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} \def\rmbshape{bx} %where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} \def\ttbshape{tt} \def\ttslshape{sltt} \def\itshape{ti} \def\itbshape{bxti} \def\slshape{sl} \def\slbshape{bxsl} \def\sfshape{ss} \def\sfbshape{ss} \def\scshape{csc} \def\scbshape{csc} % Definitions for a main text size of 11pt. This is the default in % Texinfo. % \def\definetextfontsizexi{% % Text fonts (11.2pt, magstep1). \def\textnominalsize{11pt} \edef\mainmagstep{\magstephalf} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1095} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1}{OT1} \setfont\deftt\ttshape{10}{\magstep1}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\authorrm{\secrm} \def\authortt{\sectt} \def\titleecsize{2074} % Chapter (and unnumbered) fonts (17.28pt). \def\chapnominalsize{17pt} \setfont\chaprm\rmbshape{12}{\magstep2}{OT1} \setfont\chapit\itbshape{10}{\magstep3}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep3}{OT1} \setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} \setfont\chapsf\sfbshape{17}{1000}{OT1} \let\chapbf=\chaprm \setfont\chapsc\scbshape{10}{\magstep3}{OT1} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 \def\chapecsize{1728} % Section fonts (14.4pt). \def\secnominalsize{14pt} \setfont\secrm\rmbshape{12}{\magstep1}{OT1} \setfont\secit\itbshape{10}{\magstep2}{OT1IT} \setfont\secsl\slbshape{10}{\magstep2}{OT1} \setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\secsf\sfbshape{12}{\magstep1}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep2}{OT1} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 \def\sececsize{1440} % Subsection fonts (13.15pt). \def\ssecnominalsize{13pt} \setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} \setfont\ssecit\itbshape{10}{1315}{OT1IT} \setfont\ssecsl\slbshape{10}{1315}{OT1} \setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} \setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1315}{OT1} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 \def\ssececsize{1200} % Reduced fonts for @acro in text (10pt). \def\reducednominalsize{10pt} \setfont\reducedrm\rmshape{10}{1000}{OT1} \setfont\reducedtt\ttshape{10}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{1000}{OT1} \setfont\reducedit\itshape{10}{1000}{OT1IT} \setfont\reducedsl\slshape{10}{1000}{OT1} \setfont\reducedsf\sfshape{10}{1000}{OT1} \setfont\reducedsc\scshape{10}{1000}{OT1} \setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 \def\reducedecsize{1000} % reset the current fonts \textfonts \rm } % end of 11pt text font size definitions % Definitions to make the main text be 10pt Computer Modern, with % section, chapter, etc., sizes following suit. This is for the GNU % Press printing of the Emacs 22 manual. Maybe other manuals in the % future. Used with @smallbook, which sets the leading to 12pt. % \def\definetextfontsizex{% % Text fonts (10pt). \def\textnominalsize{10pt} \edef\mainmagstep{1000} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1000} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstephalf}{OT1} \setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\authorrm{\secrm} \def\authortt{\sectt} \def\titleecsize{2074} % Chapter fonts (14.4pt). \def\chapnominalsize{14pt} \setfont\chaprm\rmbshape{12}{\magstep1}{OT1} \setfont\chapit\itbshape{10}{\magstep2}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep2}{OT1} \setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\chapsf\sfbshape{12}{\magstep1}{OT1} \let\chapbf\chaprm \setfont\chapsc\scbshape{10}{\magstep2}{OT1} \font\chapi=cmmi12 scaled \magstep1 \font\chapsy=cmsy10 scaled \magstep2 \def\chapecsize{1440} % Section fonts (12pt). \def\secnominalsize{12pt} \setfont\secrm\rmbshape{12}{1000}{OT1} \setfont\secit\itbshape{10}{\magstep1}{OT1IT} \setfont\secsl\slbshape{10}{\magstep1}{OT1} \setfont\sectt\ttbshape{12}{1000}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} \setfont\secsf\sfbshape{12}{1000}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep1}{OT1} \font\seci=cmmi12 \font\secsy=cmsy10 scaled \magstep1 \def\sececsize{1200} % Subsection fonts (10pt). \def\ssecnominalsize{10pt} \setfont\ssecrm\rmbshape{10}{1000}{OT1} \setfont\ssecit\itbshape{10}{1000}{OT1IT} \setfont\ssecsl\slbshape{10}{1000}{OT1} \setfont\ssectt\ttbshape{10}{1000}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} \setfont\ssecsf\sfbshape{10}{1000}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1000}{OT1} \font\sseci=cmmi10 \font\ssecsy=cmsy10 \def\ssececsize{1000} % Reduced fonts for @acro in text (9pt). \def\reducednominalsize{9pt} \setfont\reducedrm\rmshape{9}{1000}{OT1} \setfont\reducedtt\ttshape{9}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{900}{OT1} \setfont\reducedit\itshape{9}{1000}{OT1IT} \setfont\reducedsl\slshape{9}{1000}{OT1} \setfont\reducedsf\sfshape{9}{1000}{OT1} \setfont\reducedsc\scshape{10}{900}{OT1} \setfont\reducedttsl\ttslshape{10}{900}{OT1TT} \font\reducedi=cmmi9 \font\reducedsy=cmsy9 \def\reducedecsize{0900} % reduce space between paragraphs \divide\parskip by 2 % reset the current fonts \textfonts \rm } % end of 10pt text font size definitions % We provide the user-level command % @fonttextsize 10 % (or 11) to redefine the text font size. pt is assumed. % \def\xword{10} \def\xiword{11} % \parseargdef\fonttextsize{% \def\textsizearg{#1}% \wlog{doing @fonttextsize \textsizearg}% % % Set \globaldefs so that documents can use this inside @tex, since % makeinfo 4.8 does not support it, but we need it nonetheless. % \begingroup \globaldefs=1 \ifx\textsizearg\xword \definetextfontsizex \else \ifx\textsizearg\xiword \definetextfontsizexi \else \errhelp=\EMsimple \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} \fi\fi \endgroup } % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since % texinfo doesn't allow for producing subscripts and superscripts except % in the main text, we don't bother to reset \scriptfont and % \scriptscriptfont (which would also require loading a lot more fonts). % \def\resetmathfonts{% \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf \textfont\ttfam=\tentt \textfont\sffam=\tensf } % The font-changing commands redefine the meanings of \tenSTYLE, instead % of just \STYLE. We do this because \STYLE needs to also set the % current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire % \tenSTYLE to set the current font. % % Each font-changing command also sets the names \lsize (one size lower) % and \lllsize (three sizes lower). These relative commands are used in % the LaTeX logo and acronyms. % % This all needs generalizing, badly. % \def\textfonts{% \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl \def\curfontsize{text}% \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl \def\curfontsize{title}% \def\lsize{chap}\def\lllsize{subsec}% \resetmathfonts \setleading{25pt}} \def\titlefont#1{{\titlefonts\rm #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl \def\curfontsize{chap}% \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl \def\curfontsize{sec}% \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl \def\curfontsize{ssec}% \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts \def\reducedfonts{% \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl \def\curfontsize{reduced}% \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl \def\curfontsize{small}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl \def\curfontsize{smaller}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts % About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample % can fit this many characters: % 8.5x11=86 smallbook=72 a4=90 a5=69 % If we use \scriptfonts (8pt), then we can fit this many characters: % 8.5x11=90+ smallbook=80 a4=90+ a5=77 % For me, subjectively, the few extra characters that fit aren't worth % the additional smallness of 8pt. So I'm making the default 9pt. % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 % % I wish the USA used A4 paper. % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % \definetextfontsizexi % Define these so they can be easily changed for other fonts. \def\angleleft{$\langle$} \def\angleright{$\rangle$} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000}{OT1} \setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000}{OT1} \setfont\shortconttt\ttshape{12}{1000}{OT1TT} %% Add scribe-like font environments, plus @l for inline lisp (usually sans %% serif) and @ii for TeX italic % \smartitalic{ARG} outputs arg in italics, followed by an italic correction % unless the following character is such as not to need one. \def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else \ptexslash\fi\fi\fi} \def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} \def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally uses \ttsl. % @var is set to this for defun arguments. \def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? \def\cite#1{{\sl #1}\futurelet\next\smartitalicx} \let\i=\smartitalic \let\slanted=\smartslanted \let\var=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic % @b, explicit bold. \def\b#1{{\bf #1}} \let\strong=\b % @sansserif, explicit sans. \def\sansserif#1{{\sf #1}} % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. % \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } % Set sfcode to normal for the chars that usually have another value. % Can't use plain's \frenchspacing because it uses the `\x notation, and % sometimes \x has an active definition that messes things up. % \catcode`@=11 \def\plainfrenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m \def\endofsentencespacefactor{1000}% for @. and friends } \def\plainnonfrenchspacing{% \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 \def\endofsentencespacefactor{3000}% for @. and friends } \catcode`@=\other \def\endofsentencespacefactor{3000}% default \def\t#1{% {\tt \rawbackslash \plainfrenchspacing #1}% \null } \def\samp#1{`\tclose{#1}'\null} \setfont\keyrm\rmshape{8}{1000}{OT1} \font\keysy=cmsy9 \def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% \vbox{\hrule\kern-0.4pt \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% \kern-0.4pt\hrule}% \kern-.06em\raise0.4pt\hbox{\angleright}}}} \def\key #1{{\nohyphenation \uppercase{#1}}\null} % The old definition, with no lozenge: %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} \def\ctrl #1{{\tt \rawbackslash \hat}#1} % @file, @option are the same as @samp. \let\file=\samp \let\option=\samp % @code is a modification of @t, % which makes spaces the same size as normal in the surrounding text. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. \spaceskip = \fontdimen2\font % % Switch to typewriter. \tt % % But `\ ' produces the large typewriter interword space. \def\ {{\spaceskip = 0pt{} }}% % % Turn off hyphenation. \nohyphenation % \rawbackslash \plainfrenchspacing #1% }% \null } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { \catcode`\-=\active \catcode`\_=\active \catcode`\'=\active \catcode`\`=\active % \global\def\code{\begingroup \catcode\rquoteChar=\active \catcode\lquoteChar=\active \let'\codequoteright \let`\codequoteleft % \catcode\dashChar=\active \catcode\underChar=\active \ifallowcodebreaks \let-\codedash \let_\codeunder \else \let-\realdash \let_\realunder \fi \codex } } \def\realdash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) % will therefore expand the active definition of _, which is us % (inside @code that is), therefore an endless loop. \ifusingtt{\ifmmode \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. \else\normalunderscore \fi \discretionary{}{}{}}% {\_}% } \def\codex #1{\tclose{#1}\endgroup} % An additional complication: the above will allow breaks after, e.g., % each of the four underscores in __typeof__. This is undesirable in % some manuals, especially if they don't have long identifiers in % general. @allowcodebreaks provides a way to control this. % \newif\ifallowcodebreaks \allowcodebreakstrue \def\keywordtrue{true} \def\keywordfalse{false} \parseargdef\allowcodebreaks{% \def\txiarg{#1}% \ifx\txiarg\keywordtrue \allowcodebreakstrue \else\ifx\txiarg\keywordfalse \allowcodebreaksfalse \else \errhelp = \EMsimple \errmessage{Unknown @allowcodebreaks option `\txiarg'}% \fi\fi } % @kbd is like @code, except that if the argument is just one @key command, % then @kbd has no effect. % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). \parseargdef\kbdinputstyle{% \def\txiarg{#1}% \ifx\txiarg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% \else\ifx\txiarg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% \else\ifx\txiarg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% \else \errhelp = \EMsimple \errmessage{Unknown @kbdinputstyle option `\txiarg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} % Default is `distinct.' \kbdinputstyle distinct \def\xkey{\key} \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% \ifx\one\xkey\ifx\threex\three \key{#2}% \else{\tclose{\kbdfont\look}}\fi \else{\tclose{\kbdfont\look}}\fi} % For @indicateurl, @env, @command quotes seem unnecessary, so use \code. \let\indicateurl=\code \let\env=\code \let\command=\code % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url % itself. First (mandatory) arg is the url. Perhaps eventually put in % a hypertex \special here. % \def\uref#1{\douref #1,,,\finish} \def\douref#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url \fi \else \code{#1}% only url given, so show it \fi \fi \endlink \endgroup} % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} \ifpdf \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces \pdfurl{mailto:#1}% \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi \endlink \endgroup} \else \let\email=\uref \fi % Check if we are currently using a typewriter font. Since all the % Computer Modern typewriter fonts have zero interword stretch (and % shrink), and it is reasonable to expect all typewriter fonts to have % this property, we can check that font parameter. % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} \def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} % Explicit font changes: @r, @sc, undocumented @ii. \def\r#1{{\rm #1}} % roman font \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. % \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @abbr for "Comput. J." and the like. % No font change, but don't do end-of-sentence spacing. % \def\abbr#1{\doabbr #1,,\finish} \def\doabbr#1,#2,#3\finish{% {\plainfrenchspacing #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @pounds{} is a sterling sign, which Knuth put in the CM italic font. % \def\pounds{{\it\$}} % @euro{} comes from a separate font, depending on the current style. % We use the free feym* fonts from the eurosym package by Henrik % Theiling, which support regular, slanted, bold and bold slanted (and % "outlined" (blackboard board, sort of) versions, which we don't need). % It is available from http://www.ctan.org/tex-archive/fonts/eurosym. % % Although only regular is the truly official Euro symbol, we ignore % that. The Euro is designed to be slightly taller than the regular % font height. % % feymr - regular % feymo - slanted % feybr - bold % feybo - bold slanted % % There is no good (free) typewriter version, to my knowledge. % A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. % Hmm. % % Also doesn't work in math. Do we need to do math with euro symbols? % Hope not. % % \def\euro{{\eurofont e}} \def\eurofont{% % We set the font at each command, rather than predefining it in % \textfonts and the other font-switching commands, so that % installations which never need the symbol don't have to have the % font installed. % % There is only one designed size (nominal 10pt), so we always scale % that to the current nominal size. % % By the way, simply using "at 1em" works for cmr10 and the like, but % does not work for cmbx10 and other extended/shrunken fonts. % \def\eurosize{\csname\curfontsize nominalsize\endcsname}% % \ifx\curfontstyle\bfstylename % bold: \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize \else % regular: \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize \fi \thiseurofont } % Hacks for glyphs from the EC fonts similar to \euro. We don't % use \let for the aliases, because sometimes we redefine the original % macro, and the alias should reflect the redefinition. \def\guillemetleft{{\ecfont \char"13}} \def\guillemotleft{\guillemetleft} \def\guillemetright{{\ecfont \char"14}} \def\guillemotright{\guillemetright} \def\guilsinglleft{{\ecfont \char"0E}} \def\guilsinglright{{\ecfont \char"0F}} \def\quotedblbase{{\ecfont \char"12}} \def\quotesinglbase{{\ecfont \char"0D}} % \def\ecfont{% % We can't distinguish serif/sanserif and italic/slanted, but this % is used for crude hacks anyway (like adding French and German % quotes to documents typeset with CM, where we lose kerning), so % hopefully nobody will notice/care. \edef\ecsize{\csname\curfontsize ecsize\endcsname}% \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% \ifx\curfontstyle\bfstylename % bold: \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize \else % regular: \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize \fi \thisecfont } % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% \hfil\crcr\Orb}}% }$% } % @textdegree - the normal degrees sign. % \def\textdegree{$^\circ$} % Laurent Siebenmann reports \Orb undefined with: % Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 % so we'll define it if necessary. % \ifx\Orb\undefined \def\Orb{\mathhexbox20D} \fi % Quotes. \chardef\quotedblleft="5C \chardef\quotedblright=`\" \chardef\quoteleft=`\` \chardef\quoteright=`\' \message{page headings,} \newskip\titlepagetopglue \titlepagetopglue = 1.5in \newskip\titlepagebottomglue \titlepagebottomglue = 2pc % First the title page. Must do @settitle before @titlepage. \newif\ifseenauthor \newif\iffinishedtitlepage % Do an implicit @contents or @shortcontents after @end titlepage if the % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. % \newif\ifsetcontentsaftertitlepage \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue \parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. \begingroup \parindent=0pt \textfonts % Leave some space at the very top of the page. \vglue\titlepagetopglue % No rule at page bottom unless we print one at the top with @title. \finishedtitlepagetrue % % Most title ``pages'' are actually two pages long, with space % at the top of the second. We don't want the ragged left on the second. \let\oldpage = \page \def\page{% \iffinishedtitlepage\else \finishtitlepage \fi \let\page = \oldpage \page \null }% } \def\Etitlepage{% \iffinishedtitlepage\else \finishtitlepage \fi % It is important to do the page break before ending the group, % because the headline and footline are only empty inside the group. % If we use the new definition of \page, we always get a blank page % after the title page, which we certainly don't want. \oldpage \endgroup % % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon % % If they want short, they certainly want long too. \ifsetshortcontentsaftertitlepage \shortcontents \contents \global\let\shortcontents = \relax \global\let\contents = \relax \fi % \ifsetcontentsaftertitlepage \contents \global\let\contents = \relax \global\let\shortcontents = \relax \fi } \def\finishtitlepage{% \vskip4pt \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } %%% Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines \let\tt=\authortt} \parseargdef\title{% \checkenv\titlepage \leftline{\titlefonts\rm #1} % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt } \parseargdef\subtitle{% \checkenv\titlepage {\subtitlefont \rightline{#1}}% } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% \def\temp{\quotation}% \ifx\thisenv\temp \def\quotationauthor{#1}% printed in \Equotation. \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi {\authorfont \leftline{#1}}% \fi } %%% Set up page headings and footings. \let\thispage=\folio \newtoks\evenheadline % headline on even pages \newtoks\oddheadline % headline on odd pages \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages % Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}\HEADINGShook} \let\HEADINGShook=\relax % Commands to set those variables. % For example, this is what @headings on does % @evenheading @thistitle|@thispage|@thischapter % @oddheading @thischapter|@thispage|@thistitle % @evenfooting @thisfile|| % @oddfooting ||@thisfile \def\evenheading{\parsearg\evenheadingxxx} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddheading{\parsearg\oddheadingxxx} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \def\evenfooting{\parsearg\evenfootingxxx} \def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} \def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddfooting{\parsearg\oddfootingxxx} \def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} \def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. \global\advance\pageheight by -12pt \global\advance\vsize by -12pt } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} % @evenheadingmarks top \thischapter <- chapter at the top of a page % @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page % % The same set of arguments for: % % @oddheadingmarks % @evenfootingmarks % @oddfootingmarks % @everyheadingmarks % @everyfootingmarks \def\evenheadingmarks{\headingmarks{even}{heading}} \def\oddheadingmarks{\headingmarks{odd}{heading}} \def\evenfootingmarks{\headingmarks{even}{footing}} \def\oddfootingmarks{\headingmarks{odd}{footing}} \def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} \headingmarks{odd}{heading}{#1} } \def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} \headingmarks{odd}{footing}{#1} } % #1 = even/odd, #2 = heading/footing, #3 = top/bottom. \def\headingmarks#1#2#3 {% \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname \global\expandafter\let\csname get#1#2marks\endcsname \temp } \everyheadingmarks bottom \everyfootingmarks bottom % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. % @headings off turns them off. % @headings on same as @headings double, retained for compatibility. % @headings after turns on double-sided headings after this page. % @headings doubleafter turns on double-sided headings after this page. % @headings singleafter turns on single-sided headings after this page. % By default, they are off at the start of a document, % and turned `on' after @end titlepage. \def\headings #1 {\csname HEADINGS#1\endcsname} \def\HEADINGSoff{% \global\evenheadline={\hfil} \global\evenfootline={\hfil} \global\oddheadline={\hfil} \global\oddfootline={\hfil}} \HEADINGSoff % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. \def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. \def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} \let\HEADINGSdoubleafter=\HEADINGSafter \def\HEADINGSdoublex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). \ifx\today\undefined \def\today{% \number\day\space \ifcase\month \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec \fi \space\number\year} \fi % @settitle line... specifies the title of the document, for headings. % It generates no output of its own. \def\thistitle{\putwordNoTitle} \def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} % Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in % default indentation of @itemize and @enumerate text \newdimen\itemindent \itemindent=.3in % margin between end of table item and start of table text. \newdimen\itemmargin \itemmargin=.1in % used internally for \itemindent minus \itemmargin \newdimen\itemmax % Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). \newif\ifitemxneedsnegativevskip \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % % If the item text does not fit in the space we have, put it on a line % by itself, and do not allow a page break either before or after that % line. We do not start a paragraph here because then if the next % command is, e.g., @kindex, the whatsit would get put into the % horizontal list on a line by itself, resulting in extra blank space. \ifdim \wd0>\itemmax % % Make this a paragraph so we get the \parskip glue and wrapping, % but leave it ragged-right. \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent \advance\rightskip by0pt plus1fil \leavevmode\unhbox0\par \endgroup % % We're going to be starting a paragraph, but we don't want the % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % % Stop a page break at the \parskip glue coming up. However, if % what follows is an environment such as @example, there will be no % \parskip glue; then the negative vskip we just inserted would % cause the example and the item to crash together. So we use this % bizarre value of 10001 as a signal to \aboveenvbreak to insert % \parskip glue after all. Section titles are handled this way also. % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and % eventually be printed. \nobreak\kern-\tableindent \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 \unhbox0 \nobreak\kern\dimen0 \endgroup \itemxneedsnegativevskiptrue \fi } \def\item{\errmessage{@item while not in a list environment}} \def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble \tablecheck{table}% } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% \tablecheck{ftable}% } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% \tablecheck{vtable}% } \def\tablecheck#1{% \ifnum \the\catcode`\^^M=\active \endgroup \errmessage{This command won't work in this context; perhaps the problem is that we are \inenvironment\thisenv}% \def\next{\doignore{#1}}% \else \let\next\tablex \fi \next } \def\tablex#1{% \def\itemindicate{#1}% \parsearg\tabley } \def\tabley#1{% {% \makevalueexpandable \edef\temp{\noexpand\tablez #1\space\space\space}% \expandafter }\temp \endtablez } \def\tablez #1 #2 #3 #4\endtablez{% \aboveenvbreak \ifnum 0#1>0 \advance \leftskip by #1\mil \fi \ifnum 0#2>0 \tableindent=#2\mil \fi \ifnum 0#3>0 \advance \rightskip by #3\mil \fi \itemmax=\tableindent \advance \itemmax by -\itemmargin \advance \leftskip by \tableindent \exdentamount=\tableindent \parindent = 0pt \parskip = \smallskipamount \ifdim \parskip=0pt \parskip=2pt \fi \let\item = \internalBitem \let\itemx = \internalBitemx } \def\Etable{\endgraf\afterenvbreak} \let\Eftable\Etable \let\Evtable\Etable \let\Eitemize\Etable \let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno \envdef\itemize{\parsearg\doitemize} \def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin \advance\leftskip by \itemindent \exdentamount=\itemindent \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi \def\itemcontents{#1}% % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi \let\item=\itemizeitem } % Definition of @item while inside @itemize and @enumerate. % \def\itemizeitem{% \advance\itemno by 1 % for enumerations {\let\par=\endgraf \smallbreak}% reasonable place to break {% % If the document has an @itemize directly after a section title, a % \nobreak will be last on the list, and \sectionheading will have % done a \vskip-\parskip. In that case, we don't want to zero % parskip, or the item text will crash with the heading. On the % other hand, when there is normal text preceding the item (as there % usually is), we do want to zero parskip, or there would be too much % space. In that case, we won't have a \nobreak before. At least % that's the theory. \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% % Allow an optional argument of an uppercase letter, lowercase letter, % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % \envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi % % Detect if the argument is a single token. If so, it might be a % letter. Otherwise, the only valid thing it can be is a number. % (We will always have one token, because of the test we just made. % This is a good thing, since \splitoff doesn't work given nothing at % all -- the first parameter is undelimited.) \expandafter\splitoff\thearg\endmark \ifx\rest\empty % Only one token in the argument. It could still be anything. % A ``lowercase letter'' is one whose \lccode is nonzero. % An ``uppercase letter'' is one whose \lccode is both nonzero, and % not equal to itself. % Otherwise, we assume it's a number. % % We need the \relax at the end of the \ifnum lines to stop TeX from % continuing to look for a . % \ifnum\lccode\expandafter`\thearg=0\relax \numericenumerate % a number (we hope) \else % It's a letter. \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax \lowercaseenumerate % lowercase letter \else \uppercaseenumerate % uppercase letter \fi \fi \else % Multiple tokens in the argument. We hope it's a number. \numericenumerate \fi } % An @enumerate whose labels are integers. The starting integer is % given in \thearg. % \def\numericenumerate{% \itemno = \thearg \startenumeration{\the\itemno}% } % The starting (lowercase) letter is in \thearg. \def\lowercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more lowercase letters in @enumerate; get a bigger alphabet}% \fi \char\lccode\itemno }% } % The starting (uppercase) letter is in \thearg. \def\uppercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more uppercase letters in @enumerate; get a bigger alphabet} \fi \char\uccode\itemno }% } % Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg % to @enumerate. % \def\alphaenumerate{\enumerate{a}} \def\capsenumerate{\enumerate{A}} \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 % % @multitable ... @end multitable will make as many columns as desired. % Contents of each column will wrap at width given in preamble. Width % can be specified either with sample text given in a template line, % or in percent of \hsize, the current width of text on page. % Table can continue over pages but will only break between lines. % To make preamble: % % Either define widths of columns in terms of percent of \hsize: % @multitable @columnfractions .25 .3 .45 % @item ... % % Numbers following @columnfractions are the percent of the total % current hsize to be used for each column. You may use as many % columns as desired. % Or use a template: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. % @item, @tab do not need to be on their own lines, but it will not hurt % if they are. % Sample multitable: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item first col stuff @tab second col stuff @tab third col % @item % first col stuff % @tab % second col stuff % @tab % third col % @item first col stuff @tab second col stuff % @tab Many paragraphs of text may be used in any column. % % They will wrap at the width determined by the template. % @item@tab@tab This will be in third column. % @end multitable % Default dimensions may be reset by user. % @multitableparskip is vertical space between paragraphs in table. % @multitableparindent is paragraph indent in table. % @multitablecolmargin is horizontal space to be left between columns. % @multitablelinespace is space to leave between table items, baseline % to baseline. % 0pt means it depends on current normal line spacing. % \newskip\multitableparskip \newskip\multitableparindent \newdimen\multitablecolspace \newskip\multitablelinespace \multitableparskip=0pt \multitableparindent=6pt \multitablecolspace=12pt \multitablelinespace=0pt % Macros used to set up halign preamble: % \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent % #1 is the @columnfraction, usually a decimal number like .5, but might % be just 1. We just use it, whatever it is. % \def\pickupwholefraction#1 {% \global\advance\colcount by 1 \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } \newcount\colcount \def\setuptable#1{% \def\firstarg{#1}% \ifx\firstarg\xendsetuptable \let\go = \relax \else \ifx\firstarg\xcolumnfractions \global\setpercenttrue \else \ifsetpercent \let\go\pickupwholefraction \else \global\advance\colcount by 1 \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi \ifx\go\pickupwholefraction % Put the argument back for the \pickupwholefraction call, so % we'll always have a period there to be parsed. \def\go{\pickupwholefraction#1}% \else \let\go = \setuptable \fi% \fi \go } % multitable-only commands. % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group % of an alignment entry. Note that \everycr resets \everytab. \def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we encounter the problem it was intended to solve again. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % \newtoks\everytab % insert after every tab. % \envdef\multitable{% \vskip\parskip \startsavinginserts % % @item within a multitable starts a normal row. % We use \def instead of \let so that if one of the multitable entries % contains an @itemize, we don't choke on the \item (seen as \crcr aka % \endtemplate) expanding \doitemize. \def\item{\crcr}% % \tolerance=9500 \hbadness=9500 \setmultitablespacing \parskip=\multitableparskip \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 % \everycr = {% \noalign{% \global\everytab={}% \global\colcount=0 % Reset the column counter. % Check for saved footnotes, etc. \checkinserts % Keeps underfull box messages off when table breaks over pages. %\filbreak % Maybe so, but it also creates really weird page breaks when the % table breaks over pages. Wouldn't \vfil be better? Wait until the % problem manifests itself, so it can be fixed for real --karl. }% }% % \parsearg\domultitable } \def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. \halign\bgroup &% \global\advance\colcount by 1 \multistrut \vtop{% % Use the current \colcount to find the correct column width: \hsize=\expandafter\csname col\the\colcount\endcsname % % In order to keep entries from bumping into each other % we will add a \leftskip of \multitablecolspace to all columns after % the first one. % % If a template has been used, we will add \multitablecolspace % to the width of each template entry. % % If the user has set preamble in terms of percent of \hsize we will % use that dimension as the width of the column, and the \leftskip % will keep entries from bumping into each other. Table will start at % left margin and final column will justify at right margin. % % Make sure we don't inherit \rightskip from the outer environment. \rightskip=0pt \ifnum\colcount=1 % The first column will be indented with the surrounding text. \advance\hsize by\leftskip \else \ifsetpercent \else % If user has not set preamble in terms of percent of \hsize % we will advance \hsize by \multitablecolspace. \advance\hsize by \multitablecolspace \fi % In either case we will make \leftskip=\multitablecolspace: \leftskip=\multitablecolspace \fi % Ignoring space at the beginning and end avoids an occasional spurious % blank line, when TeX decides to break the line at the space before the % box from the multistrut, so the strut ends up on a line by itself. % For example: % @multitable @columnfractions .11 .89 % @item @code{#} % @tab Legal holiday which is valid in major parts of the whole country. % Is automatically provided with highlighting sequences respectively % marking characters. \noindent\ignorespaces##\unskip\multistrut }\cr } \def\Emultitable{% \crcr \egroup % end the \halign \global\setpercentfalse } \def\setmultitablespacing{% \def\multistrut{\strut}% just use the standard line spacing % % Compute \multitablelinespace (if not defined by user) for use in % \multitableparskip calculation. We used define \multistrut based on % this, but (ironically) that caused the spacing to be off. % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 \fi %% Test to see if parskip is larger than space between lines of %% table. If not, do nothing. %% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi} \message{conditionals,} % @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't % attempt to close an environment group. % \def\makecond#1{% \expandafter\let\csname #1\endcsname = \relax \expandafter\let\csname iscond.#1\endcsname = 1 } \makecond{iftex} \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} \makecond{ifnotplaintext} \makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} \def\documentdescription{\doignore{documentdescription}} \def\docbook{\doignore{docbook}} \def\html{\doignore{html}} \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} % Ignore text until a line `@end #1', keeping track of nested conditionals. % % A count to remember the depth of nesting. \newcount\doignorecount \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: \obeylines \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. \spaceisspace % % Count number of #1's that we've seen. \doignorecount = 0 % % Swallow text until we reach the matching `@end #1'. \dodoignore{#1}% } { \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. \obeylines % % \gdef\dodoignore#1{% % #1 contains the command name as a string, e.g., `ifinfo'. % % Define a command to find the next `@end #1'. \long\def\doignoretext##1^^M@end #1{% \doignoretextyyy##1^^M@#1\_STOP_}% % % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. \doignoretext ^^M% }% } \def\doignoreyyy#1{% \def\temp{#1}% \ifx\temp\empty % Nothing found. \let\next\doignoretextzzz \else % Found a nested condition, ... \advance\doignorecount by 1 \let\next\doignoretextyyy % ..., look for another. % If we're here, #1 ends with ^^M\ifinfo (for example). \fi \next #1% the token \_STOP_ is present just after this macro. } % We have to swallow the remaining "\_STOP_". % \def\doignoretextzzz#1{% \ifnum\doignorecount = 0 % We have just found the outermost @end. \let\next\enddoignore \else % Still inside a nested condition. \advance\doignorecount by -1 \let\next\doignoretext % Look for the next @end. \fi \next } % Finish off ignored text. { \obeylines% % Ignore anything after the last `@end #1'; this matters in verbatim % environments, where otherwise the newline after an ignored conditional % would result in a blank line in the output. \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% } % @set VAR sets the variable VAR to an empty value. % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. % % Since we want to separate VAR from REST-OF-LINE (which might be % empty), we can't just use \parsearg; we have to insert a space of our % own to delimit the rest of the line, and then take it out again if we % didn't need it. % We rely on the fact that \parsearg sets \catcode`\ =10. % \parseargdef\set{\setyyy#1 \endsetyyy} \def\setyyy#1 #2\endsetyyy{% {% \makevalueexpandable \def\temp{#2}% \edef\next{\gdef\makecsname{SET#1}}% \ifx\temp\empty \next{}% \else \setzzz#2\endsetzzz \fi }% } % Remove the trailing space \setxxx inserted. \def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % \parseargdef\clear{% {% \makevalueexpandable \global\expandafter\let\csname SET#1\endcsname=\relax }% } % @value{foo} gets the text saved in variable foo. \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { \catcode`\- = \active \catcode`\_ = \active % \gdef\makevalueexpandable{% \let\value = \expandablevalue % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. \let-\realdash \let_\normalunderscore } } % We have this subroutine so that we can handle at least some @value's % properly in indexes (we call \makevalueexpandable in \indexdummies). % The command has to be fully expandable (if the variable is set), since % the result winds up in the index file. This means that if the % variable's value contains other Texinfo commands, it's almost certain % it will fail (although perhaps we could fix that with sufficient work % to do a one-level expansion on the result, instead of complete). % \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% \message{Variable `#1', used in @value, is not set.}% \else \csname SET#1\endcsname \fi } % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % % To get special treatment of `@end ifset,' call \makeond and the redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} \def\doifset#1#2{% {% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname SET#2\endcsname\relax #1% If not set, redefine \next. \fi \expandafter }\next } \def\ifsetfail{\doignore{ifset}} % @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the % above code: if the variable is not set, do nothing, if it is set, % then redefine \next to \ifclearfail. % \makecond{ifclear} \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite % except not \outer, so it can be used within macros and \if's. \edef\newwrite{\makecsname{ptexnewwrite}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that % \fooindex ...rest of line... puts an entry in the index foo. % It also defines \fooindfile to be the number of the output channel for % the file that accumulates this index. The file's extension is foo. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 % Open the file \fi \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} % \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. % \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 \fi \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. % % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. % \def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} \def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. \expandafter \ifx\csname donesynindex#2\endcsname \undefined % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname \expandafter\let\csname\donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp % redefine \fooindex: \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } % Define \doindex, the driver for all \fooindex macros. % Argument #1 is generated by the calling \fooindex macro, % and it is "foo", the name of the index. % \doindex just uses \parsearg; it calls \doind for the actual work. % This is because \doind is more useful to call from other macros. % There is also \dosubind {index}{topic}{subtopic} % which makes an entry in a two-level index such as the operation index. \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} \def\singleindexer #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} % Take care of Texinfo commands that can appear in an index entry. % Since there are some commands we want to expand, and others we don't, % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% \escapechar = `\\ % use backslash in output files. \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% % % Need these in case \tex is in effect and \{ is a \delimiter again. % But can't use \lbracecmd and \rbracecmd because texindex assumes % braces and backslashes are used only as delimiters. \let\{ = \mylbrace \let\} = \myrbrace % % I don't entirely understand this, but when an index entry is % generated from a macro call, the \endinput which \scanmacro inserts % causes processing to be prematurely terminated. This is, % apparently, because \indexsorttmp is fully expanded, and \endinput % is an expandable command. The redefinition below makes \endinput % disappear altogether for that purpose -- although logging shows that % processing continues to some further point. On the other hand, it % seems \endinput does not hurt in the printed index arg, since that % is still getting written without apparent harm. % % Sample source (mac-idx3.tex, reported by Graham Percival to % help-texinfo, 22may06): % @macro funindex {WORD} % @findex xyz % @end macro % ... % @funindex commtest % % The above is not enough to reproduce the bug, but it gives the flavor. % % Sample whatsit resulting: % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} % % So: \let\endinput = \empty % % Do the redefinitions. \commondummies } % For the aux and toc files, @ is the escape character. So we want to % redefine everything using @ as the escape character (instead of % \realbackslash, still used for index files). When everything uses @, % this will be simpler. % \def\atdummies{% \def\@{@@}% \def\ {@ }% \let\{ = \lbraceatcmd \let\} = \rbraceatcmd % % Do the redefinitions. \commondummies \otherbackslash } % Called from \indexdummies and \atdummies. % \def\commondummies{% % % \definedummyword defines \#1 as \string\#1\space, thus effectively % preventing its expansion. This is used only for control% words, % not control letters, because the \space would be incorrect for % control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the % space. % % These can be used both for control words that take an argument and % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % \def\definedummyword ##1{\def##1{\string##1\space}}% \def\definedummyletter##1{\def##1{\string##1}}% \let\definedummyaccent\definedummyletter % \commondummiesnofonts % \definedummyletter\_% % % Non-English letters. \definedummyword\AA \definedummyword\AE \definedummyword\L \definedummyword\OE \definedummyword\O \definedummyword\aa \definedummyword\ae \definedummyword\l \definedummyword\oe \definedummyword\o \definedummyword\ss \definedummyword\exclamdown \definedummyword\questiondown \definedummyword\ordf \definedummyword\ordm % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword\bf \definedummyword\gtr \definedummyword\hat \definedummyword\less \definedummyword\sf \definedummyword\sl \definedummyword\tclose \definedummyword\tt % \definedummyword\LaTeX \definedummyword\TeX % % Assorted special characters. \definedummyword\bullet \definedummyword\comma \definedummyword\copyright \definedummyword\registeredsymbol \definedummyword\dots \definedummyword\enddots \definedummyword\equiv \definedummyword\error \definedummyword\euro \definedummyword\guillemetleft \definedummyword\guillemetright \definedummyword\guilsinglleft \definedummyword\guilsinglright \definedummyword\expansion \definedummyword\minus \definedummyword\pounds \definedummyword\point \definedummyword\print \definedummyword\quotedblbase \definedummyword\quotedblleft \definedummyword\quotedblright \definedummyword\quoteleft \definedummyword\quoteright \definedummyword\quotesinglbase \definedummyword\result \definedummyword\textdegree % % We want to disable all macros so that they are not expanded by \write. \macrolist % \normalturnoffactive % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % \def\commondummiesnofonts{% % Control letters and accents. \definedummyletter\!% \definedummyaccent\"% \definedummyaccent\'% \definedummyletter\*% \definedummyaccent\,% \definedummyletter\.% \definedummyletter\/% \definedummyletter\:% \definedummyaccent\=% \definedummyletter\?% \definedummyaccent\^% \definedummyaccent\`% \definedummyaccent\~% \definedummyword\u \definedummyword\v \definedummyword\H \definedummyword\dotaccent \definedummyword\ringaccent \definedummyword\tieaccent \definedummyword\ubaraccent \definedummyword\udotaccent \definedummyword\dotless % % Texinfo font commands. \definedummyword\b \definedummyword\i \definedummyword\r \definedummyword\sc \definedummyword\t % % Commands that take arguments. \definedummyword\acronym \definedummyword\cite \definedummyword\code \definedummyword\command \definedummyword\dfn \definedummyword\emph \definedummyword\env \definedummyword\file \definedummyword\kbd \definedummyword\key \definedummyword\math \definedummyword\option \definedummyword\pxref \definedummyword\ref \definedummyword\samp \definedummyword\strong \definedummyword\tie \definedummyword\uref \definedummyword\url \definedummyword\var \definedummyword\verb \definedummyword\w \definedummyword\xref } % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string % would be for a given command (usually its argument). % \def\indexnofonts{% % Accent commands should become @asis. \def\definedummyaccent##1{\let##1\asis}% % We can just ignore other control letters. \def\definedummyletter##1{\let##1\empty}% % Hopefully, all control words can become @asis. \let\definedummyword\definedummyaccent % \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command % and is used in the definitions of the active chars like <, >, |, etc. % Likewise with the other plain tex font commands. %\let\tt=\asis % \def\ { }% \def\@{@}% % how to handle braces? \def\_{\normalunderscore}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\L{L}% \def\OE{OE}% \def\O{O}% \def\aa{aa}% \def\ae{ae}% \def\l{l}% \def\oe{oe}% \def\o{o}% \def\ss{ss}% \def\exclamdown{!}% \def\questiondown{?}% \def\ordf{a}% \def\ordm{o}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) \def\bullet{bullet}% \def\comma{,}% \def\copyright{copyright}% \def\registeredsymbol{R}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% \def\euro{euro}% \def\guillemetleft{<<}% \def\guillemetright{>>}% \def\guilsinglleft{<}% \def\guilsinglright{>}% \def\expansion{==>}% \def\minus{-}% \def\pounds{pounds}% \def\point{.}% \def\print{-|}% \def\quotedblbase{"}% \def\quotedblleft{"}% \def\quotedblright{"}% \def\quoteleft{`}% \def\quoteright{'}% \def\quotesinglbase{,}% \def\result{=>}% \def\textdegree{degrees}% % % We need to get rid of all macros, leaving only the arguments (if present). % Of course this is not nearly correct, but it is the best we can do for now. % makeinfo does not expand macros in the argument to @deffn, which ends up % writing an index entry, and texindex isn't prepared for an index sort entry % that starts with \. % % Since macro invocations are followed by braces, we can just redefine them % to take a single TeX argument. The case of a macro invocation that % goes to end-of-line is not handled. % \macrolist } \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? % Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. \def\doind#1#2{\dosubind{#1}{#2}{}} % Workhorse for all \fooindexes. % #1 is name of index, #2 is stuff to put there, #3 is subentry -- % empty if called from \doind, as we usually are (the main exception % is with most defuns, which call us directly). % \def\dosubind#1#2#3{% \iflinks {% % Store the main index entry text (including the third arg). \toks0 = {#2}% % If third arg is present, precede it with a space. \def\thirdarg{#3}% \ifx\thirdarg\empty \else \toks0 = \expandafter{\the\toks0 \space #3}% \fi % \edef\writeto{\csname#1indfile\endcsname}% % \safewhatsit\dosubindwrite }% \fi } % Write the entry in \toks0 to the index file: % \def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % % Process the index entry with all font commands turned off, to % get the string to sort by. {\indexnofonts \edef\temp{\the\toks0}% need full expansion \xdef\indexsorttmp{\temp}% }% % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. \edef\temp{% \write\writeto{% \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% \temp } % Take care of unwanted page breaks/skips around a whatsit: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the % \write or \pdfdest will make \lastskip zero. The result is that % sequences like this: % @end defun % @tindex whatever % @defun ... % will have extra space inserted, because the \medbreak in the % start of the @defun won't see the skip inserted by the @end of % the previous defun. % % But don't do any of this if we're not in vertical mode. We % don't want to do a \vskip and prematurely end a paragraph. % % Avoid page breaks due to these extra skips, too. % % But wait, there is a catch there: % We'll have to check whether \lastskip is zero skip. \ifdim is not % sufficient for this purpose, as it ignores stretch and shrink parts % of the skip. The only way seems to be to check the textual % representation of the skip. % % The following is almost like \def\zeroskipmacro{0.0pt} except that % the ``p'' and ``t'' characters have catcode \other, not 11 (letter). % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % \newskip\whatsitskip \newcount\whatsitpenalty % % ..., ready, GO: % \def\safewhatsit#1{% \ifhmode #1% \else % \lastskip and \lastpenalty cannot both be nonzero simultaneously. \whatsitskip = \lastskip \edef\lastskipmacro{\the\lastskip}% \whatsitpenalty = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this % -\whatsitskip glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else \vskip-\whatsitskip \fi % #1% % \ifx\lastskipmacro\zeroskipmacro % If \lastskip was zero, perhaps the last item was a penalty, and % perhaps it was >=10000, e.g., a \nobreak. In that case, we want % to re-insert the same penalty (values >10000 are used for various % signals); since we just inserted a non-discardable item, any % following glue (such as a \parskip) would be a breakpoint. For example: % % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. \nobreak\vskip\whatsitskip \fi \fi } % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or % \entry {sortstring}{page}{topic}{subtopic} % The texindex program reads in these files and writes files % containing these kinds of lines: % \initial {c} % before the first topic whose initial is c % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. \def\findex {\fnindex} \def\kindex {\kyindex} \def\cindex {\cpindex} \def\vindex {\vrindex} \def\tindex {\tpindex} \def\pindex {\pgindex} \def\cindexsub {\begingroup\obeylines\cindexsub} {\obeylines % \gdef\cindexsub "#1" #2^^M{\endgroup % \dosubind{cp}{#2}{#1}}} % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % \parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % \smallfonts \rm \tolerance = 9500 \plainfrenchspacing \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. % Change catcode of @ here so that if the index file contains % \initial {@} % as its first line, TeX doesn't complain about mismatched braces % (because it thinks @} is a control sequence). \catcode`\@ = 11 \openin 1 \jobname.#1s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent \else % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. \read 1 to \temp \ifeof 1 \putwordIndexIsEmpty \else % Index files are almost Texinfo source, but we use \ as the escape % character. It would be better to use @, but that's too big a change % to make right now. \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns \input \jobname.#1s \enddoublecolumns \fi \fi \closein 1 \endgroup} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. \def\initial#1{{% % Some minor font changes for the special characters. \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt % % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. \nobreak \vskip 0pt plus 3\baselineskip \penalty 0 \vskip 0pt plus -3\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus .5\baselineskip \leftline{\secbf #1}% % Do our best not to break after the initial. \nobreak \vskip .33\baselineskip plus .1\baselineskip }} % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % % A straightforward implementation would start like this: % \def\entry#1#2{... % But this frozes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. % % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% \begingroup % % Start a new paragraph if necessary, so our assignments below can't % affect previous text. \par % % Do not fill out the last line with white space. \parfillskip = 0in % % No extra space above this paragraph. \parskip = 0in % % Do not prefer a separate line ending with a hyphen to fewer lines. \finalhyphendemerits = 0 % % \hangindent is only relevant when the entry text and page number % don't both fit on one line. In that case, bob suggests starting the % dots pretty far over on the line. Unfortunately, a large % indentation looks wrong when the entry text itself is broken across % lines. So we use a small indentation and put up with long leaders. % % \hangafter is reset to 1 (which is the value we want) at the start % of each paragraph, so we need not do anything with that. \hangindent = 2em % % When the entry text needs to be broken, just fill out the first line % with blank space. \rightskip = 0pt plus1fil % % A bit of stretch before each entry for the benefit of balancing % columns. \vskip 0pt plus1pt % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. } \def\finishentry#1{% % #1 is the page number. % % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. \setbox\boxA = \hbox{#1}% \ifdim\wd\boxA = 0pt \ % \else % % If we must, put the page number on a line of its own, and fill out % this line with blank space. (The \hfil is overwhelmed with the % fill leaders glue in \indexdotfill if the page number does fit.) \hfil\penalty50 \null\nobreak\indexdotfill % Have leaders before the page number. % % The `\ ' here is removed by the implicit \unskip that TeX does as % part of (the primitive) \par. Without it, a spurious underfull % \hbox ensues. \ifpdf \pdfgettoks#1.% \ \the\toksA \else \ #1% \fi \fi \par \endgroup } % Like plain.tex's \dotfill, except uses up at least 1 em. \def\indexdotfill{\cleaders \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} \newskip\secondaryindent \secondaryindent=0.5cm \def\secondary#1#2{{% \parfillskip=0in \parskip=0in \hangindent=1in \hangafter=1 \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill \ifpdf \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. \else #2 \fi \par }} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. \catcode`\@=11 \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns % Grab any single-column material above us. \output = {% % % Here is a possibility not foreseen in manmac: if we accumulate a % whole lot of material, we might end up calling this \output % routine twice in a row (see the doublecol-lose test, which is % essentially a couple of indexes with @setchapternewpage off). In % that case we just ship out what is in \partialpage with the normal % output routine. Generally, \partialpage will be empty when this % runs and this will be a no-op. See the indexspread.tex test case. \ifvoid\partialpage \else \onepageout{\pagecontents\partialpage}% \fi % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. \unvbox\PAGE \kern-\topskip \kern\baselineskip }% }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. \output = {\doublecolumnout}% % % Change the page size parameters. We could do this once outside this % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 % format, but then we repeat the same computation. Repeating a couple % of assignments once per index is clearly meaningless for the % execution time, so we may as well do it in one place. % % First we halve the line length, less a little for the gutter between % the columns. We compute the gutter based on the line length, so it % changes automatically with the paper format. The magic constant % below is chosen so that the gutter has the same value (well, +-<1pt) % as it did when we hard-coded it. % % We put the result in a separate register, \doublecolumhsize, so we % can restore it in \pagesofar, after \hsize itself has (potentially) % been clobbered. % \doublecolumnhsize = \hsize \advance\doublecolumnhsize by -.04154\hsize \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % % Double the \vsize as well. (We don't need a separate register here, % since nobody clobbers \vsize.) \vsize = 2\vsize } % The double-column output routine for all double-column pages except % the last. % \def\doublecolumnout{% \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. \dimen@ = \vsize \divide\dimen@ by 2 \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty } % % Re-output the contents of the output page -- any previous material, % followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% } % % All done with double columns. \def\enddoublecolumns{% % The following penalty ensures that the page builder is exercised % _before_ we change the output routine. This is necessary in the % following situation: % % The last section of the index consists only of a single entry. % Before this section, \pagetotal is less than \pagegoal, so no % break occurs before the last section starts. However, the last % section, consisting of \initial and the single \entry, does not % fit on the page and has to be broken off. Without the following % penalty the page builder will not be exercised until \eject % below, and by that time we'll already have changed the output % routine to the \balancecolumns version, so the next-to-last % double-column page will be processed with \balancecolumns, which % is wrong: The two columns will go to the main vertical list, with % the broken-off section in the recent contributions. As soon as % the output routine finishes, TeX starts reconsidering the page % break. The two columns and the broken-off section both fit on the % page, because the two columns now take up only half of the page % goal. When TeX sees \eject from below which follows the final % section, it invokes the new output routine that we've set after % \balancecolumns below; \onepageout will try to fit the two columns % and the final section into the vbox of \pageheight (see % \pagebody), causing an overfull box. % % Note that glue won't work here, because glue does not exercise the % page builder, unlike penalties (see The TeXbook, pp. 280-281). \penalty0 % \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. \balancecolumns % % If we end up splitting too much material for the current page, % though, there will be another page break right after this \output % invocation ends. Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal % definition right away. (We hope \balancecolumns will never be % called on to balance too much material, but if it is, this makes % the output somewhat more palatable.) \global\output = {\onepageout{\pagecontents\PAGE}}% }% \eject \endgroup % started in \begindoublecolumns % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column % typesetting, so reset \pagegoal to the normal \vsize (after the % \endgroup where \vsize got restored). \pagegoal = \vsize } % % Called at the end of the double column material. \def\balancecolumns{% \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip \divide\dimen@ by 2 % target to split to %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% \splittopskip = \topskip % Loop until we get a decent breakpoint. {% \vbadness = 10000 \loop \global\setbox3 = \copy0 \global\setbox1 = \vsplit3 to \dimen@ \ifdim\ht3>\dimen@ \global\advance\dimen@ by 1pt \repeat }% %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% \setbox0=\vbox to\dimen@{\unvbox1}% \setbox2=\vbox to\dimen@{\unvbox3}% % \pagesofar } \catcode`\@ = \other \message{sectioning,} % Chapters, sections, etc. % \unnumberedno is an oxymoron, of course. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 % chapters, we're in trouble anyway, I'm sure.) \newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 \newcount\subsubsecno \subsubsecno=0 % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ % % \def\appendixletter{\char\the\appendixno} % We do the following ugly conditional instead of the above simple % construct for the sake of pdftex, which needs the actual % letter in the expansion, not just typeset. % \def\appendixletter{% \ifnum\appendixno=`A A% \else\ifnum\appendixno=`B B% \else\ifnum\appendixno=`C C% \else\ifnum\appendixno=`D D% \else\ifnum\appendixno=`E E% \else\ifnum\appendixno=`F F% \else\ifnum\appendixno=`G G% \else\ifnum\appendixno=`H H% \else\ifnum\appendixno=`I I% \else\ifnum\appendixno=`J J% \else\ifnum\appendixno=`K K% \else\ifnum\appendixno=`L L% \else\ifnum\appendixno=`M M% \else\ifnum\appendixno=`N N% \else\ifnum\appendixno=`O O% \else\ifnum\appendixno=`P P% \else\ifnum\appendixno=`Q Q% \else\ifnum\appendixno=`R R% \else\ifnum\appendixno=`S S% \else\ifnum\appendixno=`T T% \else\ifnum\appendixno=`U U% \else\ifnum\appendixno=`V V% \else\ifnum\appendixno=`W W% \else\ifnum\appendixno=`X X% \else\ifnum\appendixno=`Y Y% \else\ifnum\appendixno=`Z Z% % The \the is necessary, despite appearances, because \appendixletter is % expanded while writing the .toc file. \char\appendixno is not % expandable, thus it is written literally, thus all appendixes come out % with the same letter (or @) in the toc without it. \else\char\the\appendixno \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % Each @chapter defines these (using marks) as the number+name, number % and name of the chapter. Page headings and footings can use % these. @section does likewise. \def\thischapter{} \def\thischapternum{} \def\thischaptername{} \def\thissection{} \def\thissectionnum{} \def\thissectionname{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} \let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} \let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. % To achive this, remember the "biggest" unnum. sec. we are currently in: \chardef\unmlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. \def\chapheadtype{N} % Choose a heading macro % #1 is heading type % #2 is heading level % #3 is text for heading \def\genhead#1#2#3{% % Compute the abs. sec. level: \absseclevel=#2 \advance\absseclevel by \secbase % Make sure \absseclevel doesn't fall outside the range: \ifnum \absseclevel < 0 \absseclevel = 0 \else \ifnum \absseclevel > 3 \absseclevel = 3 \fi \fi % The heading type: \def\headtype{#1}% \if \headtype U% \ifnum \absseclevel < \unmlevel \chardef\unmlevel = \absseclevel \fi \else % Check for appendix sections: \ifnum \absseclevel = 0 \edef\chapheadtype{\headtype}% \else \if \headtype A\if \chapheadtype N% \errmessage{@appendix... within a non-appendix chapter}% \fi\fi \fi % Check for numbered within unnumbered: \ifnum \absseclevel > \unmlevel \def\headtype{U}% \else \chardef\unmlevel = 3 \fi \fi % Now print the heading: \if \headtype U% \ifcase\absseclevel \unnumberedzzz{#3}% \or \unnumberedseczzz{#3}% \or \unnumberedsubseczzz{#3}% \or \unnumberedsubsubseczzz{#3}% \fi \else \if \headtype A% \ifcase\absseclevel \appendixzzz{#3}% \or \appendixsectionzzz{#3}% \or \appendixsubseczzz{#3}% \or \appendixsubsubseczzz{#3}% \fi \else \ifcase\absseclevel \chapterzzz{#3}% \or \seczzz{#3}% \or \numberedsubseczzz{#3}% \or \numberedsubsubseczzz{#3}% \fi \fi \fi \suppressfirstparagraphindent } % an interface: \def\numhead{\genhead N} \def\apphead{\genhead A} \def\unnmhead{\genhead U} % @chapter, @appendix, @unnumbered. Increment top-level counter, reset % all lower-level sectioning counters to zero. % % Also set \chaplevelprefix, which we prepend to @float sequence numbers % (e.g., figures), q.v. By default (before any chapter), that is empty. \let\chaplevelprefix = \empty % \outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz \def\chapterzzz#1{% % section resetting is \global in case the chapter is in a group, such % as an @include file. \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\chapno by 1 % % Used for \float. \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % \message{\putwordChapter\space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% % % So @section and the like are numbered underneath this chapter. \global\let\section = \numberedsec \global\let\subsection = \numberedsubsec \global\let\subsubsection = \numberedsubsubsec } \outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % \def\appendixnum{\putwordAppendix\space \appendixletter}% \message{\appendixnum}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % \global\let\section = \appendixsec \global\let\subsection = \appendixsubsec \global\let\subsubsection = \appendixsubsubsec } \outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 % % Since an unnumbered has no number, no prefix for figures. \global\let\chaplevelprefix = \empty \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX % expanded them. For example, in `@unnumbered The @cite{Book}', TeX % expanded @cite (which turns out to cause errors because \cite is meant % to be executed, not expanded). % % Anyway, we don't want the fully-expanded definition of @cite to appear % as a result of the \message, we just want `@cite' itself. We use % \the to achieve this: TeX expands \the only once, % simply yielding the contents of . (We also do this for % the toc entries.) \toks0 = {#1}% \message{(\the\toks0)}% % \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % \global\let\section = \unnumberedsec \global\let\subsection = \unnumberedsubsec \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% % Well, we could do the following in a group, but that would break % an assumption that \chapmacro is called at the outermost level. % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax } % @top is like @unnumbered. \let\top\unnumbered % Sections. \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } \outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection \outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. \outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } \outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } \outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. \let\section = \numberedsec \let\subsection = \numberedsubsec \let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading % NOTE on use of \vbox for chapter headings, section headings, and such: % 1) We use \vbox rather than the earlier \line to permit % overlong headings to fold. % 2) \hyphenpenalty is set to 10000 because hyphenation in a % heading is obnoxious; this forbids it. % 3) Likewise, headings look best if no \parindent is used, and % if justification is not attempted. Hence \raggedright. \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz } \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}% \bigskip \par\penalty 200\relax \suppressfirstparagraphindent } % @heading, @subheading, @subsubheading. \parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. %%% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} %%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) \newskip\chapheadingskip \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} % Because \domark is called before \chapoddpage, the filler page will % get the headings for the next chapter, which is wrong. But we don't % care -- we just disable all headings on the filler page. \def\chapoddpage{% \chappager \ifodd\pageno \else \begingroup \evenheadline={\hfil}\evenfootline={\hfil}% \oddheadline={\hfil}\oddfootline={\hfil}% \hbox to 0pt{}% \chappager \endgroup \fi } \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chapbreak \global\let\pagealignmacro=\chappager} \def\CHAPPAGon{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chappager \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} \def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage \global\def\HEADINGSon{\HEADINGSdouble}} \CHAPPAGon % Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. % % To test against our argument. \def\Ynothingkeyword{Ynothing} \def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% % Insert the first mark before the heading break (see notes for \domark). \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% \gdef\thissection{}}% % \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{\thischaptername}}% \else\ifx\temptype\Yomitfromtockeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{}}% \else\ifx\temptype\Yappendixkeyword \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\appendixletter}% \gdef\noexpand\thischapter{\putwordAppendix{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \else \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\the\chapno}% \gdef\noexpand\thischapter{\putwordChapter{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \fi\fi\fi % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert the chapter heading break. \pchapsepmacro % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \domark % {% \chapfonts \rm % % Have to define \lastsection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. \gdef\lastsection{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the % \donoderef, because we include the current node name in the toc % entry, and \donoderef resets it to empty. \writetocentry{\toctype}{#1}{#3}% % % For pdftex, we have to write out the node definition (aka, make % the pdfdest) after any page break, but before the actual text has % been typeset. If the destination for the pdf outline is after the % text, then jumping from the outline may wind up with the text not % being visible, for instance under high magnification. \donoderef{#2}% % % Typeset the actual heading. \nobreak % Avoid page breaks at the interline glue. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax \def\centerparameters{% \advance\rightskip by 3\rightskip \leftskip = \rightskip \parfillskip = 0pt } % I don't think this chapter style is supported any more, so I'm not % updating it with the new noderef stuff. We'll see. --karl, 11aug03. % \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}\bigskip \par\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt \hfill {\rm #1}\hfill}}\bigskip \par\nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen \global\let\centerchapmacro=\centerchfopen} % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % \newskip\secheadingskip \def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. \newskip\subsecheadingskip \def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. \def\subsubsecheadingskip{\subsecheadingskip} \def\subsubsecheadingbreak{\subsecheadingbreak} % Print any size, any type, section title. % % #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % \def\seckeyword{sec} % \def\sectionheading#1#2#3#4{% {% % Switch to the right set of fonts. \csname #2fonts\endcsname \rm % \def\sectionlevel{#2}% \def\temptype{#3}% % % Insert first mark before the heading break (see notes for \domark). \let\prevsectiondefs=\lastsectiondefs \ifx\temptype\Ynothingkeyword \ifx\sectionlevel\seckeyword \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% \gdef\thissection{\thissectionname}}% \fi \else\ifx\temptype\Yomitfromtockeyword % Don't redefine \thissection. \else\ifx\temptype\Yappendixkeyword \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \else \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \fi\fi\fi % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert space above the heading. \csname #2headingbreak\endcsname % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevsectiondefs=\lastsectiondefs \domark % % Only insert the space after the number if we have a section number. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% \gdef\lastsection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, % and don't redefine \lastsection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% \gdef\lastsection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% \gdef\lastsection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chapmacro. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). % Again, see comments in \chapmacro. \donoderef{#3}% % % Interline glue will be inserted when the vbox is completed. % That glue will be a valid breakpoint for the page, since it'll be % preceded by a whatsit (usually from the \donoderef, or from the % \writetocentry if there was no node). We don't want to allow that % break, since then the whatsits could end up on page n while the % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. \nobreak % % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% % Add extra space after the heading -- half of whatever came above it. % Don't allow stretch, though. \kern .5 \csname #2headingskip\endcsname % % Do not let the kern be a potential breakpoint, as it would be if it % was followed by glue. \nobreak % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a % discardable item.) \vskip-\parskip % % This is purely so the last item on the list is a known \penalty > % 10000. This is so \startdefun can avoid allowing breakpoints after % section headings. Otherwise, it would insert a valid breakpoint between: % % @section sec-whatever % @deffn def-whatever \penalty 10001 } \message{toc,} % Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. % Called from @chapter, etc. % % Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} % We append the current node name (if any) and page number as additional % arguments for the \{chap,sec,...}entry macros which will eventually % read this. The node name is used in the pdf outlines as the % destination to jump to. % % We open the .toc file for writing here instead of at @setfilename (or % any other fixed time) so that @contents can be anywhere in the document. % But if #1 is `omit', then we don't do anything. This is used for the % table of contents chapter openings themselves. % \newif\iftocfileopened \def\omitkeyword{omit}% % \def\writetocentry#1#2#3{% \edef\writetoctype{#1}% \ifx\writetoctype\omitkeyword \else \iftocfileopened\else \immediate\openout\tocfile = \jobname.toc \global\tocfileopenedtrue \fi % \iflinks {\atdummies \edef\temp{% \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% \temp }% \fi \fi % % Tell \shipout to create a pdf destination on each page, if we're % writing pdf. These are used in the table of contents. We can't % just write one on every page because the title pages are numbered % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. \ifpdf \global\pdfmakepagedesttrue \fi } % These characters do not print properly in the Computer Modern roman % fonts, so we must take special care. This is more or less redundant % with the Texinfo input format setup at the end of this file. % \def\activecatcodes{% \catcode`\"=\active \catcode`\$=\active \catcode`\<=\active \catcode`\>=\active \catcode`\\=\active \catcode`\^=\active \catcode`\_=\active \catcode`\|=\active \catcode`\~=\active } % Read the toc file, which is essentially Texinfo input. \def\readtocfile{% \setupdatafile \activecatcodes \input \tocreadfilename } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 % Prepare to read what we've written to \tocfile. % \def\startcontents#1{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. Thus, we maintain % \contentsalignmacro in parallel with \pagealignmacro. % From: Torbjorn Granlund \contentsalignmacro \immediate\closeout\tocfile % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } % redefined for the two-volume lispref. We always output on % \jobname.toc even if this is redefined. % \def\tocreadfilename{\jobname.toc} % Normal (long) toc. % \def\contents{% \startcontents{\putwordTOC}% \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \ifeof 1 \else \pdfmakeoutlines \fi \closein 1 \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% \startcontents{\putwordShortTOC}% % \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry % We want a true roman here for the page numbers. \secfonts \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl \let\tt=\shortconttt \rm \hyphenpenalty = 10000 \advance\baselineskip by 1pt % Open it up a little. \def\numsecentry##1##2##3##4{} \let\appsecentry = \numsecentry \let\unnsecentry = \numsecentry \let\numsubsecentry = \numsecentry \let\appsubsecentry = \numsecentry \let\unnsubsecentry = \numsecentry \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \closein 1 \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } \let\shortcontents = \summarycontents % Typeset the label for a chapter or appendix for the short contents. % The arg is, e.g., `A' for an appendix, or `3' for a chapter. % \def\shortchaplabel#1{% % This space should be enough, since a single number is .5em, and the % widest letter (M) is 1em, at least in the Computer Modern fonts. % But use \hss just in case. % (This space doesn't include the extra space that gets added after % the label; that gets put in by \shortchapentry above.) % % We'd like to right-justify chapter numbers, but that looks strange % with appendix letters. And right-justifying numbers and % left-justifying letters looks strange when there is less than 10 % chapters. Have to read the whole toc once to know how many chapters % there are before deciding ... \hbox to 1em{#1\hss}% } % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } % Appendices, in the main contents. % Need the word Appendix, and a fixed-size box. % \def\appendixbox#1{% % We use M since it's probably the widest letter. \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % \def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} \def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. \def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} \let\appsecentry=\numsecentry \def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. \def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} \let\appsubsecentry=\numsubsecentry \def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. \def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} \let\appsubsubsecentry=\numsubsubsecentry \def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. % Same as \defaultparindent. \newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. % % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} % We use the same \entry macro as for the index entries. \let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} \def\dopageno#1{{\rm #1}} \def\doshortpageno#1{{\rm #1}} \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} \def\subsecentryfonts{\textfonts} \def\subsubsecentryfonts{\textfonts} \message{environments,} % @foo ... @end foo. % @point{}, @result{}, @expansion{}, @print{}, @equiv{}. % % Since these characters are used in examples, it should be an even number of % \tt widths. Each \tt character is 1en, so two makes it 1em. % \def\point{$\star$} \def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} \def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} \def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} % The @error{} command. % Adapted from the TeXbook's \boxit. % \newbox\errorbox % {\tentt \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt} % \setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. \kern3pt\vrule width\dimen2}% Space to right. \hrule height\dimen2} \hfil} % \def\error{\leavevmode\lower.7ex\copy\errorbox} % @tex ... @end tex escapes into raw Tex temporarily. % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain tex @ character. \envdef\tex{% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 \catcode `\+=\other \catcode `\"=\other \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other \escapechar=`\\ % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc \let\,=\ptexcomma \let\.=\ptexdot \let\dots=\ptexdots \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% } % There is no need to define \Etex. % Define @lisp ... @end lisp. % @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in % This is the definition that ^^M gets inside @lisp, @example, and other % such environments. \null is better than a space, since it doesn't % have any width. \def\lisppar{\null\endgraf} % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz and % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf \ifdim\lastskip<\envskipamount \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi }} \let\afterenvbreak = \aboveenvbreak % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will % also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. \font\circle=lcircle10 \newdimen\circthick \newdimen\cartouter\newdimen\cartinner \newskip\normbskip\newskip\normpskip\newskip\normlskip \circthick=\fontdimen8\circle % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} \def\cbl{{\circle\char'012\hskip -6pt}} \def\cbr{{\hskip 6pt\circle\char'011}} \def\carttop{\hbox to \cartouter{\hskip\lskip \ctl\leaders\hrule height\circthick\hfil\ctr \hskip\rskip}} \def\cartbot{\hbox to \cartouter{\hskip\lskip \cbl\leaders\hrule height\circthick\hfil\cbr \hskip\rskip}} % \newskip\lskip\newskip\rskip \envdef\cartouche{% \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip \leftskip=0pt\rightskip=0pt % we want these *outside*. \cartinner=\hsize \advance\cartinner by-\lskip \advance\cartinner by-\rskip \cartouter=\hsize \advance\cartouter by 18.4pt % allow for 3pt kerns on either % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. \let\nonarrowing = t% \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup \hskip\lskip \vrule\kern3pt \vbox\bgroup \kern3pt \hsize=\cartinner \baselineskip=\normbskip \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip \comment % For explanation, see the end of \def\group. } \def\Ecartouche{% \ifhmode\par\fi \kern3pt \egroup \kern3pt\vrule \hskip\rskip \egroup \cartbot \egroup \checkinserts } % This macro is called at the beginning of all the @example variants, % inside a group. \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt \parindent = 0pt \emergencystretch = 0pt % don't try to avoid overfull boxes \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing \else \let\nonarrowing = \relax \fi \let\exdent=\nofillexdent } % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: % @example, @display, @format, @lisp % \def\smallword{small} \def\nosmallword{nosmall} \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword % end paragraph for sake of leading, in case document has no blank % line. This is redundant with what happens in \aboveenvbreak, but % we need to do it before changing the fonts, and it's inconvenient % to change the fonts afterward. \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. % Let's do it by one command: \def\makedispenv #1#2{ \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } % Define two synonyms: \def\maketwodispenvs #1#2#3{ \makedispenv{#1}{#3} \makedispenv{#2}{#3} } % @lisp: indented, narrowed, typewriter font; @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % \maketwodispenvs {lisp}{example}{% \nonfillstart \tt\quoteexpand \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. \gobble % eat return } % @display/@smalldisplay: same as @lisp except keep current font. % \makedispenv {display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % \makedispenv{format}{% \let\nonarrowing = t% \nonfillstart \gobble } % @flushleft: same as @format, but doesn't obey \SETdispenvsize. \envdef\flushleft{% \let\nonarrowing = t% \nonfillstart \gobble } \let\Eflushleft = \afterenvbreak % @flushright. % \envdef\flushright{% \let\nonarrowing = t% \nonfillstart \advance\leftskip by 0pt plus 1fill \gobble } \let\Eflushright = \afterenvbreak % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % \envdef\quotation{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip \parindent=0pt % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing \advance\rightskip by \lispnarrowing \exdentamount = \lispnarrowing \else \let\nonarrowing = \relax \fi \parsearg\quotationlabel } % We have retained a nonzero parskip for the environment, since we're % doing normal filling. % \def\Equotation{% \par \ifx\quotationauthor\undefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% \def\temp{#1}% \ifx\temp\empty \else {\bf #1: }% \fi } % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, % we need the curly braces so that makeinfo sees the @verb command, eg: % `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org % % [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. % % [Knuth] p.344; only we need to do the other characters Texinfo sets % active too. Otherwise, they get lost as the first character on a % verbatim line. \def\dospecials{% \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % % [Knuth] pp. 380,381,391 % Disable Spanish ligatures ?` and !` of \tt font \begingroup \catcode`\`=\active\gdef`{\relax\lq} \endgroup % % Setup for the @verb command. % % Eight spaces for a tab \begingroup \catcode`\^^I=\active \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} \endgroup % \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% \catcode`\`=\active \tabeightspaces % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces } % Setup for the @verbatim environment % % Real tab expansion \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % \def\starttabbox{\setbox0=\hbox\bgroup} % Allow an option to not replace quotes with a regular directed right % quote/apostrophe (char 0x27), but instead use the undirected quote % from cmtt (char 0x0d). The undirected quote is ugly, so don't make it % the default, but it works for pasting with more pdf viewers (at least % evince), the lilypond developers report. xpdf does work with the % regular 0x27. % \def\codequoteright{% \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax '% \else \char'15 \fi \else \char'15 \fi } % % and a similar option for the left quote char vs. a grave accent. % Modern fonts display ASCII 0x60 as a grave accent, so some people like % the code environments to do likewise. % \def\codequoteleft{% \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax `% \else \char'22 \fi \else \char'22 \fi } % \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup \dimen0=\wd0 % the width so far, or since the previous tab \divide\dimen0 by\tabw \multiply\dimen0 by\tabw % compute previous multiple of \tabw \advance\dimen0 by\tabw % advance to next multiple of \tabw \wd0=\dimen0 \box0 \starttabbox }% } \catcode`\'=\active \gdef\rquoteexpand{\catcode\rquoteChar=\active \def'{\codequoteright}}% % \catcode`\`=\active \gdef\lquoteexpand{\catcode\lquoteChar=\active \def`{\codequoteleft}}% % \gdef\quoteexpand{\rquoteexpand \lquoteexpand}% \endgroup % start the verbatim environment. \def\setupverbatim{% \let\nonarrowing = t% \nonfillstart % Easiest (and conventionally used) font for verbatim \tt \def\par{\leavevmode\egroup\box0\endgraf}% \catcode`\`=\active \tabexpand \quoteexpand % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } % Do the @verb magic: verbatim text is quoted by unique % delimiter characters. Before first delimiter expect a % right brace, after last delimiter expect closing brace: % % \def\doverb'{'#1'}'{#1} % % [Knuth] p. 382; only eat outer {} \begingroup \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % \def\verb{\begingroup\setupverb\doverb} % % % Do the @verbatim magic: define the macro \doverbatim so that % the (first) argument ends when '@end verbatim' is reached, ie: % % \def\doverbatim#1@end verbatim{#1} % % For Texinfo it's a lot easier than for LaTeX, % because texinfo's \verbatim doesn't stop at '\end{verbatim}': % we need not redefine '\', '{' and '}'. % % Inspired by LaTeX's verbatim command set [latex.ltx] % \begingroup \catcode`\ =\active \obeylines % % ignore everything up to the first ^^M, that's the newline at the end % of the @verbatim input line itself. Otherwise we get an extra blank % line in the output. \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% % We really want {...\end verbatim} in the body of the macro, but % without the active space; thus we have to use \xdef and \gobble. \endgroup % \envdef\verbatim{% \setupverbatim\doverbatim } \let\Everbatim = \afterenvbreak % @verbatiminclude FILE - insert text of file in verbatim environment. % \def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \def\doverbatiminclude#1{% {% \makevalueexpandable \setupverbatim \input #1 \afterenvbreak }% } % @copying ... @end copying. % Save the text away for @insertcopying later. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as % possible is very desirable. % \def\copying{\checkenv{}\begingroup\scanargctxt\docopying} \def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} % \def\insertcopying{% \begingroup \parindent = 0pt % paragraph indentation looks wrong on title page \scanexp\copyingtext \endgroup } \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt \newcount\defunpenalty % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak \defunpenalty=10003 % Will keep this @deffn together with the % following @def command, see below. \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check specifically for penalty 10002, inserted % by \printdefunline, instead of 10000, since the sectioning % commands also insert a nobreak penalty, and we don't want to allow % a break between a section heading and a defun. % % As a minor refinement, we avoid "club" headers by signalling % with penalty of 10003 after the very first @deffn in the % sequence (see above), and penalty of 10002 after any following % @def command. \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. \medskip % preceded by discardable penalty, so not a breakpoint \fi % \parindent=0in \advance\leftskip by \defbodyindent \exdentamount=\defbodyindent } \def\dodefunx#1{% % First, check whether we are in the right environment: \checkenv#1% % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% } \def\gobbledefun#1\startdefun{} % \printdefunline \deffnheader{text} % \def\printdefunline#1#2{% \begingroup % call \deffnheader: #1#2 \endheader % common ending: \interlinepenalty = 10000 \advance\rightskip by 0pt plus 1fil \endgraf \nobreak\vskip -\parskip \penalty\defunpenalty % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts \endgroup } \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; % the only thing remainnig is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } % \domakedefun \deffn \deffnx \deffnheader % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. % \def\domakedefun#1#2#3{% \envdef#1{% \startdefun \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } %%% Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} % @deffn category class name args \makedefun{defop}#1 {\defopon{#1\ \putwordon}} % \defopon {category on}class name args \def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } %%% Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} % @deftypeop category class type name args \makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} % \deftypeopon {category on}class type name args \def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deftypefngeneral {subind}category type name args % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} % @deftypecv category class type var args \makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} % \deftypecvof {category of}class type var args \def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } % \deftypecvgeneral {subind}category type var args % \def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% \dosubind{vr}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args \makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } %%% Type: % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% \defname{#1}{}{#2}\defunargs{#3\unskip}% } % Remaining @defun-like shortcuts: \makedefun{defun}{\deffnheader{\putwordDeffunc} } \makedefun{defmac}{\deffnheader{\putwordDefmac} } \makedefun{defspec}{\deffnheader{\putwordDefspec} } \makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } \makedefun{defmethod}{\defopon\putwordMethodon} \makedefun{deftypemethod}{\deftypeopon\putwordMethodon} \makedefun{defivar}{\defcvof\putwordInstanceVariableof} \makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". % #2 is the return type, if any. % #3 is the function name. % % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % % How we'll format the type name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % % Figure out line sizes for the paragraph shape. % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent % (plain.tex says that \dimen1 should be used only as global.) \parshape 2 0in \dimen0 \defargsindent \dimen2 % % Put the type name to the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize % \hsize has to be shortened this way: \kern\leftskip % Intentionally do not respect \rightskip, since we need the space. }% % % Allow all lines to be underfull without complaint: \tolerance=10000 \hbadness=10000 \exdentamount=\defbodyindent {% % defun fonts. We use typewriter by default (used to be bold) because: % . we're printing identifiers, they should be in tt in principle. % . in languages with many accents, such as Czech or French, it's % common to leave accents off identifiers. The result looks ok in % tt, but exceedingly strange in rm. % . we don't want -- and --- to be treated as ligatures. % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt \def\temp{#2}% return value type \ifx\temp\empty\else \tclose{\temp} \fi #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm % \boldbrax % arguments will be output next, if any. } % Print arguments in slanted roman (not ttsl), inconsistently with using % tt for the name. This is because literal text is sometimes needed in % the argument list (groff manual), and ttsl and tt are not very % distinguishable. Prevent hyphenation at `-' chars. % \def\defunargs#1{% % use sl by default (not ttsl), % tt for the names. \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we % want a way to get ttsl. Let's try @var for that. \let\var=\ttslanted #1% \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. % \def\activeparens{% \catcode`\(=\active \catcode`\)=\active \catcode`\[=\active \catcode`\]=\active \catcode`\&=\active } % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. { \activeparens \global\let(=\lparen \global\let)=\rparen \global\let[=\lbrack \global\let]=\rbrack \global\let& = \& \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \newcount\parencount % If we encounter &foo, then turn on ()-hacking afterwards \newif\ifampseen \def\amprm#1 {\ampseentrue{\bf\ }} \def\parenfont{% \ifampseen % At the first level, print parens in roman, % otherwise use the default font. \ifnum \parencount=1 \rm \fi \else % The \sf parens (in \boldbrax) actually are a little bolder than % the contained text. This is especially needed for [ and ] . \sf \fi } \def\infirstlevel#1{% \ifampseen \ifnum\parencount=1 #1% \fi \fi } \def\bfafterword#1 {#1 \bf} \def\opnr{% \global\advance\parencount by 1 {\parenfont(}% \infirstlevel \bfafterword } \def\clnr{% {\parenfont)}% \infirstlevel \sl \global\advance\parencount by -1 } \newcount\brackcount \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% } \def\rbrb{% {\bf]}% \global\advance\brackcount by -1 } \def\checkparencounts{% \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } % these should not use \errmessage; the glibc manual, at least, actually % has such constructs (when documenting function pointers). \def\badparencount{% \message{Warning: unbalanced parentheses in @def...}% \global\parencount=0 } \def\badbrackcount{% \message{Warning: unbalanced square brackets in @def...}% \global\brackcount=0 } \message{macros,} % @macro. % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. \ifx\eTeXversion\undefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1}% \immediate\openout\macscribble=\jobname.tmp \immediate\write\macscribble{\the\toks0}% \immediate\closeout\macscribble \input \jobname.tmp } \fi \def\scanmacro#1{% \begingroup \newlinechar`\^^M \let\xeatspaces\eatspaces % Undo catcode changes of \startcontents and \doprintindex % When called from @insertcopying or (short)caption, we need active % backslash to get it printed correctly. Previously, we had % \catcode`\\=\other instead. We'll see whether a problem appears % with macro expansion. --kasal, 19aug04 \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ % ... and \example \spaceisspace % % Append \endinput to make sure that TeX does not see the ending newline. % I've verified that it is necessary both for e-TeX and for ordinary TeX % --kasal, 29nov03 \scantokens{#1\endinput}% \endgroup } \def\scanexp#1{% \edef\temp{\noexpand\scanmacro{#1}}% \temp } \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? % List of all defined macros in the form % \definedummyword\macro1\definedummyword\macro2... % Currently is also contains all @aliases; the list can be split % if there is a need. \def\macrolist{} % Add the macro to \macrolist \def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} \def\addtomacrolistxxx#1{% \toks0 = \expandafter{\macrolist\definedummyword#1}% \xdef\macrolist{\the\toks0}% } % Utility routines. % This does \let #1 = #2, with \csnames; that is, % \let \csname#1\endcsname = \csname#2\endcsname % (except of course we have to play expansion games). % \def\cslet#1#2{% \expandafter\let \csname#1\expandafter\endcsname \csname#2\endcsname } % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). {\catcode`\@=11 \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} \def\unbrace#1{#1} \unbrace{\gdef\trim@@@ #1 } #2@{#1} } % Trim a single trailing ^^M off a string. {\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% } % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active % (as in normal texinfo). It is necessary to change the definition of \. % Non-ASCII encodings make 8-bit characters active, so un-activate % them to avoid their expansion. Must do this non-globally, to % confine the change to the current group. % It's necessary to have hard CRs when the macro is executed. This is % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. \def\scanctxt{% \catcode`\"=\other \catcode`\+=\other \catcode`\<=\other \catcode`\>=\other \catcode`\@=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi } \def\scanargctxt{% \scanctxt \catcode`\\=\other \catcode`\^^M=\other } \def\macrobodyctxt{% \scanctxt \catcode`\{=\other \catcode`\}=\other \catcode`\^^M=\other \usembodybackslash } \def\macroargctxt{% \scanctxt \catcode`\\=\other } % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments \paramno=0% \else \expandafter\parsemargdef \argl;% \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% \else \expandafter\ifx\csname \the\macname\endcsname \relax \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% \addtomacrolist{\the\macname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} \parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax \let\definedummyword\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else \errmessage{Macro #1 not defined}% \fi } % Called by \do from \dounmacro on each macro. The idea is to omit any % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% \ifx #1\relax % remove this \else \noexpand\definedummyword \noexpand#1% \fi } % This makes use of the obscure feature that if the last token of a % is #, then the preceding argument is delimited by % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname #1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} % Parse the optional {params} list. Set up \paramno and \paramlist % so \defmacro knows what to do. Define \macarg.blah for each blah % in the params list, to be ##N where N is the position in that list. % That gets used by \mbodybackslash (above). % We need to get `macro parameter char #' into several definitions. % The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. \def\parsemargdef#1;{\paramno=0\def\paramlist{}% \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx \advance\paramno by 1% \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% % This defines the macro itself. There are six cases: recursive and % nonrecursive macros of zero, one, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\scanmacro{\temp}}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{\egroup\noexpand\scanmacro{\temp}}% \fi \else \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \expandafter\noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \fi \fi} \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence % as an argument (by \parsebrace or \parsearg) \def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg \fi \macnamexxx} % @alias. % We need some trickery to remove the optional spaces around the equal % sign. Just make them active and then expand them all to nothing. \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty \addtomacrolist{#1}% \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next } \message{cross references,} \newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in % cross-references. The @node line might or might not have commas, and % might or might not have spaces before the first comma, like: % @node foo , bar , ... % We don't want such trailing spaces in the node name. % \parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} % % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} \let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the % type (Ynumbered, Yappendix, Ynothing). % \def\donoderef#1{% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty \fi } % @anchor{NAME} -- define xref target at arbitrary point. % \newcount\savesfregister % \def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} \def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} \def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: % 1) NAME-title - the current sectioning name taken from \lastsection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. % 3) NAME-pg - the page number. % % This is called from \donoderef, \anchor, and \dofloat. In the case of % floats, there is an additional part, which is not written here: % 4) NAME-lof - the text as it should appear in a @listoffloats. % \def\setref#1#2{% \pdfmkdest{#1}% \iflinks {% \atdummies % preserve commands, but don't expand them \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = \expandafter{\lastsection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during \shipout }% \fi } % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces \def\printedmanual{\ignorespaces #5}% \def\printedrefname{\ignorespaces #3}% \setbox1=\hbox{\printedmanual\unskip}% \setbox0=\hbox{\printedrefname\unskip}% \ifdim \wd0 = 0pt % No printed node name was explicitly given. \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax % Use the node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else % Use the actual chapter/section title appear inside % the square brackets. Use the real section title if we have it. \ifdim \wd1 > 0pt % It is in another manual, so we don't have it. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % % Make link in pdf output. \ifpdf \leavevmode \getfilename{#4}% {\indexnofonts \turnoffactive % See comments at \activebackslashdouble. {\activebackslashdouble \xdef\pdfxrefdest{#1}% \backslashparens\pdfxrefdest}% % \ifnum\filenamelength>0 \startlink attr{/Border [0 0 0]}% goto file{\the\filename.pdf} name{\pdfxrefdest}% \else \startlink attr{/Border [0 0 0]}% goto name{\pdfmkpgn{\pdfxrefdest}}% \fi }% \setcolor{\linkcolor}% \fi % % Float references are printed completely differently: "Figure 1.2" % instead of "[somenode], p.3". We distinguish them by the % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". \ifdim\wd0 = 0pt \refx{#1-snt}{}% \else \printedrefname \fi % % if the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". \ifdim \wd1 > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. % % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not % insert empty discretionaries after hyphens, which means that it will % not find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, this % is a loss. Therefore, we give the text of the node name again, so it % is as if TeX is seeing it for the first time. \ifdim \wd1 > 0pt \putwordSection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% \else % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. {\turnoffactive % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% % output the `[mynode]' via a macro so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. \turnoffactive \putwordpage\tie\refx{#1-pg}{}% \fi \fi \endlink \endgroup} % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly % one that Bob is working on :). % \def\xrefprintnodename#1{[#1]} % Things referred to by \setref. % \def\Ynothing{} \def\Yomitfromtoc{} \def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 \putwordSection@tie \the\chapno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie \the\chapno.\the\secno.\the\subsecno \else \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } \def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno \else \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. % If its value is nonempty, SUFFIX is output afterward. % \def\refx#1#2{% {% \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs \message{\linenumber Undefined cross reference `#1'.}% \else \ifwarnedxrefs\else \global\warnedxrefstrue \message{Cross reference values unknown; you must run TeX again.}% \fi \fi \fi \else % It's defined, so just use it. \thisrefX \fi #2% Output the suffix in any case. } % This is the macro invoked by entries in the aux file. Usually it's % just a \def (we prepend XR to the control sequence name to avoid % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% {% The node name might contain 8-bit characters, which in our current % implementation are changed to commands like @'e. Don't let these % mess up the control sequence name. \indexnofonts \turnoffactive \xdef\safexrefname{#1}% }% % \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR\safexrefname\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname % % Is this the first time we've seen this float type? \expandafter\ifx\floatlist\relax \toks0 = {\do}% yes, so just \do \else % had it before, so preserve previous elements in list. \toks0 = \expandafter{\floatlist\do}% \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 {\safexrefname}}% \fi } % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else \readdatafile{aux}% \global\havexrefstrue \fi \closein 1 } \def\setupdatafile{% \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other \catcode`\^^C=\other \catcode`\^^D=\other \catcode`\^^E=\other \catcode`\^^F=\other \catcode`\^^G=\other \catcode`\^^H=\other \catcode`\^^K=\other \catcode`\^^L=\other \catcode`\^^N=\other \catcode`\^^P=\other \catcode`\^^Q=\other \catcode`\^^R=\other \catcode`\^^S=\other \catcode`\^^T=\other \catcode`\^^U=\other \catcode`\^^V=\other \catcode`\^^W=\other \catcode`\^^X=\other \catcode`\^^Z=\other \catcode`\^^[=\other \catcode`\^^\=\other \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. % in xref tags, i.e., node names. But since ^^e4 notation isn't % supported in the main text, it doesn't seem desirable. Furthermore, % that is not enough: for node names that actually contain a ^ % character, we would end up writing a line like this: 'xrdef {'hat % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first % argument, and \hat is not an expandable control sequence. It could % all be worked out, but why? Either we support ^^ or we don't. % % The other change necessary for this was to define \auxhat: % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter % and then to call \auxhat in \setq. % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other \catcode`\"=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % % This is to support \ in node names and titles, since the \ % characters end up in a \csname. It's easier than % leaving it active and making its active definition an actual \ % character. What I don't understand is why it works in the *value* % of the xrdef. Seems like it should be a catcode12 \, and that % should not typeset properly. But it works, so I'm moving on for % now. --karl, 15jan04. \catcode`\\=\other % % Make the characters 128-255 be printing characters. {% \count1=128 \def\loop{% \catcode\count1=\other \advance\count1 by 1 \ifnum \count1<256 \loop \fi }% }% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 } \def\readdatafile#1{% \begingroup \setupdatafile \input\jobname.#1 \endgroup} \message{insertions,} % including footnotes. \newcount \footnoteno % The trailing space in the following definition for supereject is % vital for proper filling; pages come out unaligned when you do a % pagealignmacro call if that space before the closing brace is % removed. (Generally, numeric constants should always be followed by a % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } % @footnotestyle is meaningful for info output only. \let\footnotestyle=\comment {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% \let\indent=\ptexindent \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % % Oh yes, they do; otherwise, @ifset (and anything else that uses % \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % \gdef\dofootnote{% \insert\footins\bgroup % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. \hsize=\pagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox \floatingpenalty\@MM \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip \parindent\defaultparindent % \smallfonts \rm % % Because we use hanging indentation in footnotes, a @noindent appears % to exdent this text, so make it be a no-op. makeinfo does not use % hanging indentation so @noindent can still be needed within footnote % text after an @example or the like (not that this is good style). \let\noindent = \relax % % Hang the footnote text off the number. Use \everypar in case the % footnote extends for more than one paragraph. \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut \futurelet\next\fo@t } }%end \catcode `\@=11 % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarily, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. % \def\startsavinginserts{% \ifx \insert\ptexinsert \let\insert\saveinsert \else \let\checkinserts\relax \fi } % This \insert replacement works for both \insert\footins{foo} and % \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % \def\saveinsert#1{% \edef\next{\noexpand\savetobox \makeSAVEname#1}% \afterassignment\next % swallow the left brace \let\temp = } \def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} \def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} \def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} \def\placesaveins#1{% \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname {\box#1}% } % eat @SAVE -- beware, all of them have catcode \other: { \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) \gdef\gobblesave @SAVE{} } % initialization: \def\newsaveins #1{% \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% \next } \def\newsaveinsX #1{% \csname newbox\endcsname #1% \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts \checksaveins #1}% } % initialize: \let\checkinserts\empty \newsaveins\footins \newsaveins\margin % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. % % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else % Do not bother showing banner with epsf.tex v2.7k (available in % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi \closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% \ifx\epsfbox\undefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. % #6 is just the usual extra ignored arg for parsing this stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names % If the image is by itself, center it. \ifvmode \imagevmodetrue \nobreak\bigskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak \line\bgroup \fi % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% \else % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% \fi % \ifimagevmode \egroup \bigbreak \fi % space after the image \endgroup} % @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, % etc. We don't actually implement floating yet, we always include the % float "here". But it seemed the best name for the future. % \envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} % There may be a space before second and/or third parameter; delete it. \def\eatcommaspace#1, {#1,} % #1 is the optional FLOATTYPE, the text label for this float, typically % "Figure", "Table", "Example", etc. Can't contain commas. If omitted, % this float will not be numbered and cannot be referred to. % % #2 is the optional xref label. Also must be present for the float to % be referable. % % #3 is the optional positioning argument; for now, it is ignored. It % will somehow specify the positions allowed to float to (here, top, bottom). % % We keep a separate counter for each FLOATTYPE, which we reset at each % chapter-level command. \let\resetallfloatnos=\empty % \def\dofloat#1,#2,#3,#4\finish{% \let\thiscaption=\empty \let\thisshortcaption=\empty % % don't lose footnotes inside @float. % % BEWARE: when the floats start float, we have to issue warning whenever an % insert appears inside a float which could possibly float. --kasal, 26may04 % \startsavinginserts % % We can't be used inside a paragraph. \par % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% \def\floatloc{#3}% we do nothing with this yet. % \ifx\floattype\empty \let\safefloattype=\empty \else {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% \fi % % If label is given but no type, we handle that as the empty type. \ifx\floatlabel\empty \else % We want each FLOATTYPE to be numbered separately (Figure 1, % Table 1, Figure 2, ...). (And if no label, no number.) % \expandafter\getfloatno\csname\safefloattype floatno\endcsname \global\advance\floatno by 1 % {% % This magic value for \lastsection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % \edef\lastsection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi % % start with \parskip glue, I guess. \vskip\parskip % % Don't suppress indentation if a float happens to start a section. \restorefirstparagraphindent } % we have these possibilities: % @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap % @float Foo,lbl & no caption: Foo 1.1 % @float Foo & @caption{Cap}: Foo: Cap % @float Foo & no caption: Foo % @float ,lbl & Caption{Cap}: 1.1: Cap % @float ,lbl & no caption: 1.1 % @float & @caption{Cap}: Cap % @float & no caption: % \def\Efloat{% \let\floatident = \empty % % In all cases, if we have a float type, it comes first. \ifx\floattype\empty \else \def\floatident{\floattype}\fi % % If we have an xref label, the number comes next. \ifx\floatlabel\empty \else \ifx\floattype\empty \else % if also had float type, need tie first. \appendtomacro\floatident{\tie}% \fi % the number. \appendtomacro\floatident{\chaplevelprefix\the\floatno}% \fi % % Start the printed caption with what we've constructed in % \floatident, but keep it separate; we need \floatident again. \let\captionline = \floatident % \ifx\thiscaption\empty \else \ifx\floatident\empty \else \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. \appendtomacro\captionline{\scanexp\thiscaption}% \fi % % If we have anything to print, print it, with space before. % Eventually this needs to become an \insert. \ifx\captionline\empty \else \vskip.5\parskip \captionline % % Space below caption. \vskip\parskip \fi % % If have an xref label, write the list of floats info. Do this % after the caption, to avoid chance of it being a breakpoint. \ifx\floatlabel\empty \else % Write the text that goes in the lof to the aux file as % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% \atdummies % % since we read the caption text in the macro world, where ^^M % is turned into a normal character, we have to scan it back, so % we don't write the literal three characters "^^M" into the aux file. \scanexp{% \xdef\noexpand\gtemp{% \ifx\thisshortcaption\empty \thiscaption \else \thisshortcaption \fi }% }% \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident \ifx\gtemp\empty \else : \gtemp \fi}}% }% \fi \egroup % end of \vtop % % place the captured inserts % % BEWARE: when the floats start floating, we have to issue warning % whenever an insert appears inside a float which could possibly % float. --kasal, 26may04 % \checkinserts } % Append the tokens #2 to the definition of macro #1, not expanding either. % \def\appendtomacro#1#2{% \expandafter\def\expandafter#1\expandafter{#1#2}% } % @caption, @shortcaption % \def\caption{\docaption\thiscaption} \def\shortcaption{\docaption\thisshortcaption} \def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} \def\defcaption#1#2{\egroup \def#1{#2}} % The parameter is the control sequence identifying the counter we are % going to use. Create it if it doesn't exist and assign it to \floatno. \def\getfloatno#1{% \ifx#1\relax % Haven't seen this figure type before. \csname newcount\endcsname #1% % % Remember to reset this floatno at the next chap. \expandafter\gdef\expandafter\resetallfloatnos \expandafter{\resetallfloatnos #1=0 }% \fi \let\floatno#1% } % \setref calls this to get the XREFLABEL-snt value. We want an @xref % to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we % first read the @float command. % \def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% % Magic string used for the XREFLABEL-title value, so \xrefX can % distinguish floats from other xref types. \def\floatmagic{!!float!!} % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic % \lastsection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % % #1 is (maybe) the \floatmagic string. If so, #2 will be the % (safe) float type for this float. We set \iffloattype to #2. % \def\doiffloat#1=#2=#3\finish{% \def\temp{#1}% \def\iffloattype{#2}% \ifx\temp\floatmagic } % @listoffloats FLOATTYPE - print a list of floats like a table of contents. % \parseargdef\listoffloats{% \def\floattype{#1}% floattype {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% % % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax \ifhavexrefs % if the user said @listoffloats foo but never @float foo. \message{\linenumber No `\safefloattype' floats to list.}% \fi \else \begingroup \leftskip=\tocindent % indent these entries like a toc \let\do=\listoffloatsdo \csname floatlist\safefloattype\endcsname \endgroup \fi } % This is called on each entry in a list of floats. We're passed the % xref label, in the form LABEL-title, which is how we save it in the % aux file. We strip off the -title and look up \XRLABEL-lof, which % has the text we're supposed to typeset here. % % Figures without xref labels will not be included in the list (since % they won't appear in the aux file). % \def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} \def\listoffloatsdoentry#1-title\finish{{% % Can't fully expand XR#1-lof because it can contain anything. Just % pass the control sequence. On the other hand, XR#1-pg is just the % page number, and we want to fully expand that so we can get a link % in pdf output. \toksA = \expandafter{\csname XR#1-lof\endcsname}% % % use the same \entry macro we use to generate the TOC and index. \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% \writeentry }} \message{localization,} % @documentlanguage is usually given very early, just after % @setfilename. If done too late, it may not override everything % properly. Single argument is the language (de) or locale (de_DE) % abbreviation. It would be nice if we could set up a hyphenation file. % { \catcode`\_ = \active \globaldefs=1 \parseargdef\documentlanguage{\begingroup \let_=\normalunderscore % normal _ character for filenames \tex % read txi-??.tex file in plain TeX. % Read the file by the name they passed if it exists. \openin 1 txi-#1.tex \ifeof 1 \documentlanguagetrywithoutunderscore{#1_\finish}% \else \input txi-#1.tex \fi \closein 1 \endgroup \endgroup} } % % If they passed de_DE, and txi-de_DE.tex doesn't exist, % try txi-de.tex. % \def\documentlanguagetrywithoutunderscore#1_#2\finish{% \openin 1 txi-#1.tex \ifeof 1 \errhelp = \nolanghelp \errmessage{Cannot read language file txi-#1.tex}% \else \input txi-#1.tex \fi \closein 1 } % \newhelp\nolanghelp{The given language definition file cannot be found or is empty. Maybe you need to install it? In the current directory should work if nowhere else does.} % Set the catcode of characters 128 through 255 to the specified number. % \def\setnonasciicharscatcode#1{% \count255=128 \loop\ifnum\count255<256 \global\catcode\count255=#1\relax \advance\count255 by 1 \repeat } \def\setnonasciicharscatcodenonglobal#1{% \count255=128 \loop\ifnum\count255<256 \catcode\count255=#1\relax \advance\count255 by 1 \repeat } % @documentencoding sets the definition of non-ASCII characters % according to the specified encoding. % \parseargdef\documentencoding{% % Encoding being declared for the document. \def\declaredencoding{\csname #1.enc\endcsname}% % % Supported encodings: names converted to tokens in order to be able % to compare them with \ifx. \def\ascii{\csname US-ASCII.enc\endcsname}% \def\latnine{\csname ISO-8859-15.enc\endcsname}% \def\latone{\csname ISO-8859-1.enc\endcsname}% \def\lattwo{\csname ISO-8859-2.enc\endcsname}% \def\utfeight{\csname UTF-8.enc\endcsname}% % \ifx \declaredencoding \ascii \asciichardefs % \else \ifx \declaredencoding \lattwo \setnonasciicharscatcode\active \lattwochardefs % \else \ifx \declaredencoding \latone \setnonasciicharscatcode\active \latonechardefs % \else \ifx \declaredencoding \latnine \setnonasciicharscatcode\active \latninechardefs % \else \ifx \declaredencoding \utfeight \setnonasciicharscatcode\active \utfeightchardefs % \else \message{Unknown document encoding #1, ignoring.}% % \fi % utfeight \fi % latnine \fi % latone \fi % lattwo \fi % ascii } % A message to be logged when using a character that isn't available % the default font encoding (OT1). % \def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} % Take account of \c (plain) vs. \, (Texinfo) difference. \def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} % First, make active non-ASCII characters in order for them to be % correctly categorized when TeX reads the replacement text of % macros containing the character definitions. \setnonasciicharscatcode\active % % Latin1 (ISO-8859-1) character definitions. \def\latonechardefs{% \gdef^^a0{~} \gdef^^a1{\exclamdown} \gdef^^a2{\missingcharmsg{CENT SIGN}} \gdef^^a3{{\pounds}} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\missingcharmsg{YEN SIGN}} \gdef^^a6{\missingcharmsg{BROKEN BAR}} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\copyright} \gdef^^aa{\ordf} \gdef^^ab{\missingcharmsg{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}} \gdef^^ac{$\lnot$} \gdef^^ad{\-} \gdef^^ae{\registeredsymbol} \gdef^^af{\={}} % \gdef^^b0{\textdegree} \gdef^^b1{$\pm$} \gdef^^b2{$^2$} \gdef^^b3{$^3$} \gdef^^b4{\'{}} \gdef^^b5{$\mu$} \gdef^^b6{\P} % \gdef^^b7{$^.$} \gdef^^b8{\cedilla\ } \gdef^^b9{$^1$} \gdef^^ba{\ordm} % \gdef^^bb{\missingcharmsg{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}} \gdef^^bc{$1\over4$} \gdef^^bd{$1\over2$} \gdef^^be{$3\over4$} \gdef^^bf{\questiondown} % \gdef^^c0{\`A} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\~A} \gdef^^c4{\"A} \gdef^^c5{\ringaccent A} \gdef^^c6{\AE} \gdef^^c7{\cedilla C} \gdef^^c8{\`E} \gdef^^c9{\'E} \gdef^^ca{\^E} \gdef^^cb{\"E} \gdef^^cc{\`I} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\"I} % \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}} \gdef^^d1{\~N} \gdef^^d2{\`O} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\~O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\O} \gdef^^d9{\`U} \gdef^^da{\'U} \gdef^^db{\^U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}} \gdef^^df{\ss} % \gdef^^e0{\`a} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\~a} \gdef^^e4{\"a} \gdef^^e5{\ringaccent a} \gdef^^e6{\ae} \gdef^^e7{\cedilla c} \gdef^^e8{\`e} \gdef^^e9{\'e} \gdef^^ea{\^e} \gdef^^eb{\"e} \gdef^^ec{\`{\dotless i}} \gdef^^ed{\'{\dotless i}} \gdef^^ee{\^{\dotless i}} \gdef^^ef{\"{\dotless i}} % \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}} \gdef^^f1{\~n} \gdef^^f2{\`o} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\~o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\o} \gdef^^f9{\`u} \gdef^^fa{\'u} \gdef^^fb{\^u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}} \gdef^^ff{\"y} } % Latin9 (ISO-8859-15) encoding character definitions. \def\latninechardefs{% % Encoding is almost identical to Latin1. \latonechardefs % \gdef^^a4{\euro} \gdef^^a6{\v S} \gdef^^a8{\v s} \gdef^^b4{\v Z} \gdef^^b8{\v z} \gdef^^bc{\OE} \gdef^^bd{\oe} \gdef^^be{\"Y} } % Latin2 (ISO-8859-2) character definitions. \def\lattwochardefs{% \gdef^^a0{~} \gdef^^a1{\missingcharmsg{LATIN CAPITAL LETTER A WITH OGONEK}} \gdef^^a2{\u{}} \gdef^^a3{\L} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\v L} \gdef^^a6{\'S} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\v S} \gdef^^aa{\cedilla S} \gdef^^ab{\v T} \gdef^^ac{\'Z} \gdef^^ad{\-} \gdef^^ae{\v Z} \gdef^^af{\dotaccent Z} % \gdef^^b0{\textdegree} \gdef^^b1{\missingcharmsg{LATIN SMALL LETTER A WITH OGONEK}} \gdef^^b2{\missingcharmsg{OGONEK}} \gdef^^b3{\l} \gdef^^b4{\'{}} \gdef^^b5{\v l} \gdef^^b6{\'s} \gdef^^b7{\v{}} \gdef^^b8{\cedilla\ } \gdef^^b9{\v s} \gdef^^ba{\cedilla s} \gdef^^bb{\v t} \gdef^^bc{\'z} \gdef^^bd{\H{}} \gdef^^be{\v z} \gdef^^bf{\dotaccent z} % \gdef^^c0{\'R} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\u A} \gdef^^c4{\"A} \gdef^^c5{\'L} \gdef^^c6{\'C} \gdef^^c7{\cedilla C} \gdef^^c8{\v C} \gdef^^c9{\'E} \gdef^^ca{\missingcharmsg{LATIN CAPITAL LETTER E WITH OGONEK}} \gdef^^cb{\"E} \gdef^^cc{\v E} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\v D} % \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}} \gdef^^d1{\'N} \gdef^^d2{\v N} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\H O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\v R} \gdef^^d9{\ringaccent U} \gdef^^da{\'U} \gdef^^db{\H U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\cedilla T} \gdef^^df{\ss} % \gdef^^e0{\'r} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\u a} \gdef^^e4{\"a} \gdef^^e5{\'l} \gdef^^e6{\'c} \gdef^^e7{\cedilla c} \gdef^^e8{\v c} \gdef^^e9{\'e} \gdef^^ea{\missingcharmsg{LATIN SMALL LETTER E WITH OGONEK}} \gdef^^eb{\"e} \gdef^^ec{\v e} \gdef^^ed{\'\i} \gdef^^ee{\^\i} \gdef^^ef{\v d} % \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}} \gdef^^f1{\'n} \gdef^^f2{\v n} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\H o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\v r} \gdef^^f9{\ringaccent u} \gdef^^fa{\'u} \gdef^^fb{\H u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\cedilla t} \gdef^^ff{\dotaccent{}} } % UTF-8 character definitions. % % This code to support UTF-8 is based on LaTeX's utf8.def, with some % changes for Texinfo conventions. It is included here under the GPL by % permission from Frank Mittelbach and the LaTeX team. % \newcount\countUTFx \newcount\countUTFy \newcount\countUTFz \gdef\UTFviiiTwoOctets#1#2{\expandafter \UTFviiiDefined\csname u8:#1\string #2\endcsname} % \gdef\UTFviiiThreeOctets#1#2#3{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} % \gdef\UTFviiiFourOctets#1#2#3#4{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} \gdef\UTFviiiDefined#1{% \ifx #1\relax \message{\linenumber Unicode char \string #1 not defined for Texinfo}% \else \expandafter #1% \fi } \begingroup \catcode`\~13 \catcode`\"12 \def\UTFviiiLoop{% \global\catcode\countUTFx\active \uccode`\~\countUTFx \uppercase\expandafter{\UTFviiiTmp}% \advance\countUTFx by 1 \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} \countUTFx = "C2 \countUTFy = "E0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiTwoOctets\string~}} \UTFviiiLoop \countUTFx = "E0 \countUTFy = "F0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiThreeOctets\string~}} \UTFviiiLoop \countUTFx = "F0 \countUTFy = "F4 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiFourOctets\string~}} \UTFviiiLoop \endgroup \begingroup \catcode`\"=12 \catcode`\<=12 \catcode`\.=12 \catcode`\,=12 \catcode`\;=12 \catcode`\!=12 \catcode`\~=13 \gdef\DeclareUnicodeCharacter#1#2{% \countUTFz = "#1\relax \wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% \begingroup \parseXMLCharref \def\UTFviiiTwoOctets##1##2{% \csname u8:##1\string ##2\endcsname}% \def\UTFviiiThreeOctets##1##2##3{% \csname u8:##1\string ##2\string ##3\endcsname}% \def\UTFviiiFourOctets##1##2##3##4{% \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% \expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter \gdef\UTFviiiTmp{#2}% \endgroup} \gdef\parseXMLCharref{% \ifnum\countUTFz < "A0\relax \errhelp = \EMsimple \errmessage{Cannot define Unicode char value < 00A0}% \else\ifnum\countUTFz < "800\relax \parseUTFviiiA,% \parseUTFviiiB C\UTFviiiTwoOctets.,% \else\ifnum\countUTFz < "10000\relax \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% \else \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiA!% \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% \fi\fi\fi } \gdef\parseUTFviiiA#1{% \countUTFx = \countUTFz \divide\countUTFz by 64 \countUTFy = \countUTFz \multiply\countUTFz by 64 \advance\countUTFx by -\countUTFz \advance\countUTFx by 128 \uccode `#1\countUTFx \countUTFz = \countUTFy} \gdef\parseUTFviiiB#1#2#3#4{% \advance\countUTFz by "#10\relax \uccode `#3\countUTFz \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} \endgroup \def\utfeightchardefs{% \DeclareUnicodeCharacter{00A0}{\tie} \DeclareUnicodeCharacter{00A1}{\exclamdown} \DeclareUnicodeCharacter{00A3}{\pounds} \DeclareUnicodeCharacter{00A8}{\"{ }} \DeclareUnicodeCharacter{00A9}{\copyright} \DeclareUnicodeCharacter{00AA}{\ordf} \DeclareUnicodeCharacter{00AB}{\guillemetleft} \DeclareUnicodeCharacter{00AD}{\-} \DeclareUnicodeCharacter{00AE}{\registeredsymbol} \DeclareUnicodeCharacter{00AF}{\={ }} \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} \DeclareUnicodeCharacter{00B4}{\'{ }} \DeclareUnicodeCharacter{00B8}{\cedilla{ }} \DeclareUnicodeCharacter{00BA}{\ordm} \DeclareUnicodeCharacter{00BB}{\guillemetright} \DeclareUnicodeCharacter{00BF}{\questiondown} \DeclareUnicodeCharacter{00C0}{\`A} \DeclareUnicodeCharacter{00C1}{\'A} \DeclareUnicodeCharacter{00C2}{\^A} \DeclareUnicodeCharacter{00C3}{\~A} \DeclareUnicodeCharacter{00C4}{\"A} \DeclareUnicodeCharacter{00C5}{\AA} \DeclareUnicodeCharacter{00C6}{\AE} \DeclareUnicodeCharacter{00C7}{\cedilla{C}} \DeclareUnicodeCharacter{00C8}{\`E} \DeclareUnicodeCharacter{00C9}{\'E} \DeclareUnicodeCharacter{00CA}{\^E} \DeclareUnicodeCharacter{00CB}{\"E} \DeclareUnicodeCharacter{00CC}{\`I} \DeclareUnicodeCharacter{00CD}{\'I} \DeclareUnicodeCharacter{00CE}{\^I} \DeclareUnicodeCharacter{00CF}{\"I} \DeclareUnicodeCharacter{00D1}{\~N} \DeclareUnicodeCharacter{00D2}{\`O} \DeclareUnicodeCharacter{00D3}{\'O} \DeclareUnicodeCharacter{00D4}{\^O} \DeclareUnicodeCharacter{00D5}{\~O} \DeclareUnicodeCharacter{00D6}{\"O} \DeclareUnicodeCharacter{00D8}{\O} \DeclareUnicodeCharacter{00D9}{\`U} \DeclareUnicodeCharacter{00DA}{\'U} \DeclareUnicodeCharacter{00DB}{\^U} \DeclareUnicodeCharacter{00DC}{\"U} \DeclareUnicodeCharacter{00DD}{\'Y} \DeclareUnicodeCharacter{00DF}{\ss} \DeclareUnicodeCharacter{00E0}{\`a} \DeclareUnicodeCharacter{00E1}{\'a} \DeclareUnicodeCharacter{00E2}{\^a} \DeclareUnicodeCharacter{00E3}{\~a} \DeclareUnicodeCharacter{00E4}{\"a} \DeclareUnicodeCharacter{00E5}{\aa} \DeclareUnicodeCharacter{00E6}{\ae} \DeclareUnicodeCharacter{00E7}{\cedilla{c}} \DeclareUnicodeCharacter{00E8}{\`e} \DeclareUnicodeCharacter{00E9}{\'e} \DeclareUnicodeCharacter{00EA}{\^e} \DeclareUnicodeCharacter{00EB}{\"e} \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} \DeclareUnicodeCharacter{00F1}{\~n} \DeclareUnicodeCharacter{00F2}{\`o} \DeclareUnicodeCharacter{00F3}{\'o} \DeclareUnicodeCharacter{00F4}{\^o} \DeclareUnicodeCharacter{00F5}{\~o} \DeclareUnicodeCharacter{00F6}{\"o} \DeclareUnicodeCharacter{00F8}{\o} \DeclareUnicodeCharacter{00F9}{\`u} \DeclareUnicodeCharacter{00FA}{\'u} \DeclareUnicodeCharacter{00FB}{\^u} \DeclareUnicodeCharacter{00FC}{\"u} \DeclareUnicodeCharacter{00FD}{\'y} \DeclareUnicodeCharacter{00FF}{\"y} \DeclareUnicodeCharacter{0100}{\=A} \DeclareUnicodeCharacter{0101}{\=a} \DeclareUnicodeCharacter{0102}{\u{A}} \DeclareUnicodeCharacter{0103}{\u{a}} \DeclareUnicodeCharacter{0106}{\'C} \DeclareUnicodeCharacter{0107}{\'c} \DeclareUnicodeCharacter{0108}{\^C} \DeclareUnicodeCharacter{0109}{\^c} \DeclareUnicodeCharacter{010A}{\dotaccent{C}} \DeclareUnicodeCharacter{010B}{\dotaccent{c}} \DeclareUnicodeCharacter{010C}{\v{C}} \DeclareUnicodeCharacter{010D}{\v{c}} \DeclareUnicodeCharacter{010E}{\v{D}} \DeclareUnicodeCharacter{0112}{\=E} \DeclareUnicodeCharacter{0113}{\=e} \DeclareUnicodeCharacter{0114}{\u{E}} \DeclareUnicodeCharacter{0115}{\u{e}} \DeclareUnicodeCharacter{0116}{\dotaccent{E}} \DeclareUnicodeCharacter{0117}{\dotaccent{e}} \DeclareUnicodeCharacter{011A}{\v{E}} \DeclareUnicodeCharacter{011B}{\v{e}} \DeclareUnicodeCharacter{011C}{\^G} \DeclareUnicodeCharacter{011D}{\^g} \DeclareUnicodeCharacter{011E}{\u{G}} \DeclareUnicodeCharacter{011F}{\u{g}} \DeclareUnicodeCharacter{0120}{\dotaccent{G}} \DeclareUnicodeCharacter{0121}{\dotaccent{g}} \DeclareUnicodeCharacter{0124}{\^H} \DeclareUnicodeCharacter{0125}{\^h} \DeclareUnicodeCharacter{0128}{\~I} \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} \DeclareUnicodeCharacter{012A}{\=I} \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} \DeclareUnicodeCharacter{012C}{\u{I}} \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} \DeclareUnicodeCharacter{0130}{\dotaccent{I}} \DeclareUnicodeCharacter{0131}{\dotless{i}} \DeclareUnicodeCharacter{0132}{IJ} \DeclareUnicodeCharacter{0133}{ij} \DeclareUnicodeCharacter{0134}{\^J} \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} \DeclareUnicodeCharacter{0139}{\'L} \DeclareUnicodeCharacter{013A}{\'l} \DeclareUnicodeCharacter{0141}{\L} \DeclareUnicodeCharacter{0142}{\l} \DeclareUnicodeCharacter{0143}{\'N} \DeclareUnicodeCharacter{0144}{\'n} \DeclareUnicodeCharacter{0147}{\v{N}} \DeclareUnicodeCharacter{0148}{\v{n}} \DeclareUnicodeCharacter{014C}{\=O} \DeclareUnicodeCharacter{014D}{\=o} \DeclareUnicodeCharacter{014E}{\u{O}} \DeclareUnicodeCharacter{014F}{\u{o}} \DeclareUnicodeCharacter{0150}{\H{O}} \DeclareUnicodeCharacter{0151}{\H{o}} \DeclareUnicodeCharacter{0152}{\OE} \DeclareUnicodeCharacter{0153}{\oe} \DeclareUnicodeCharacter{0154}{\'R} \DeclareUnicodeCharacter{0155}{\'r} \DeclareUnicodeCharacter{0158}{\v{R}} \DeclareUnicodeCharacter{0159}{\v{r}} \DeclareUnicodeCharacter{015A}{\'S} \DeclareUnicodeCharacter{015B}{\'s} \DeclareUnicodeCharacter{015C}{\^S} \DeclareUnicodeCharacter{015D}{\^s} \DeclareUnicodeCharacter{015E}{\cedilla{S}} \DeclareUnicodeCharacter{015F}{\cedilla{s}} \DeclareUnicodeCharacter{0160}{\v{S}} \DeclareUnicodeCharacter{0161}{\v{s}} \DeclareUnicodeCharacter{0162}{\cedilla{t}} \DeclareUnicodeCharacter{0163}{\cedilla{T}} \DeclareUnicodeCharacter{0164}{\v{T}} \DeclareUnicodeCharacter{0168}{\~U} \DeclareUnicodeCharacter{0169}{\~u} \DeclareUnicodeCharacter{016A}{\=U} \DeclareUnicodeCharacter{016B}{\=u} \DeclareUnicodeCharacter{016C}{\u{U}} \DeclareUnicodeCharacter{016D}{\u{u}} \DeclareUnicodeCharacter{016E}{\ringaccent{U}} \DeclareUnicodeCharacter{016F}{\ringaccent{u}} \DeclareUnicodeCharacter{0170}{\H{U}} \DeclareUnicodeCharacter{0171}{\H{u}} \DeclareUnicodeCharacter{0174}{\^W} \DeclareUnicodeCharacter{0175}{\^w} \DeclareUnicodeCharacter{0176}{\^Y} \DeclareUnicodeCharacter{0177}{\^y} \DeclareUnicodeCharacter{0178}{\"Y} \DeclareUnicodeCharacter{0179}{\'Z} \DeclareUnicodeCharacter{017A}{\'z} \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} \DeclareUnicodeCharacter{017C}{\dotaccent{z}} \DeclareUnicodeCharacter{017D}{\v{Z}} \DeclareUnicodeCharacter{017E}{\v{z}} \DeclareUnicodeCharacter{01C4}{D\v{Z}} \DeclareUnicodeCharacter{01C5}{D\v{z}} \DeclareUnicodeCharacter{01C6}{d\v{z}} \DeclareUnicodeCharacter{01C7}{LJ} \DeclareUnicodeCharacter{01C8}{Lj} \DeclareUnicodeCharacter{01C9}{lj} \DeclareUnicodeCharacter{01CA}{NJ} \DeclareUnicodeCharacter{01CB}{Nj} \DeclareUnicodeCharacter{01CC}{nj} \DeclareUnicodeCharacter{01CD}{\v{A}} \DeclareUnicodeCharacter{01CE}{\v{a}} \DeclareUnicodeCharacter{01CF}{\v{I}} \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} \DeclareUnicodeCharacter{01D1}{\v{O}} \DeclareUnicodeCharacter{01D2}{\v{o}} \DeclareUnicodeCharacter{01D3}{\v{U}} \DeclareUnicodeCharacter{01D4}{\v{u}} \DeclareUnicodeCharacter{01E2}{\={\AE}} \DeclareUnicodeCharacter{01E3}{\={\ae}} \DeclareUnicodeCharacter{01E6}{\v{G}} \DeclareUnicodeCharacter{01E7}{\v{g}} \DeclareUnicodeCharacter{01E8}{\v{K}} \DeclareUnicodeCharacter{01E9}{\v{k}} \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} \DeclareUnicodeCharacter{01F1}{DZ} \DeclareUnicodeCharacter{01F2}{Dz} \DeclareUnicodeCharacter{01F3}{dz} \DeclareUnicodeCharacter{01F4}{\'G} \DeclareUnicodeCharacter{01F5}{\'g} \DeclareUnicodeCharacter{01F8}{\`N} \DeclareUnicodeCharacter{01F9}{\`n} \DeclareUnicodeCharacter{01FC}{\'{\AE}} \DeclareUnicodeCharacter{01FD}{\'{\ae}} \DeclareUnicodeCharacter{01FE}{\'{\O}} \DeclareUnicodeCharacter{01FF}{\'{\o}} \DeclareUnicodeCharacter{021E}{\v{H}} \DeclareUnicodeCharacter{021F}{\v{h}} \DeclareUnicodeCharacter{0226}{\dotaccent{A}} \DeclareUnicodeCharacter{0227}{\dotaccent{a}} \DeclareUnicodeCharacter{0228}{\cedilla{E}} \DeclareUnicodeCharacter{0229}{\cedilla{e}} \DeclareUnicodeCharacter{022E}{\dotaccent{O}} \DeclareUnicodeCharacter{022F}{\dotaccent{o}} \DeclareUnicodeCharacter{0232}{\=Y} \DeclareUnicodeCharacter{0233}{\=y} \DeclareUnicodeCharacter{0237}{\dotless{j}} \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} \DeclareUnicodeCharacter{1E20}{\=G} \DeclareUnicodeCharacter{1E21}{\=g} \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} \DeclareUnicodeCharacter{1E26}{\"H} \DeclareUnicodeCharacter{1E27}{\"h} \DeclareUnicodeCharacter{1E30}{\'K} \DeclareUnicodeCharacter{1E31}{\'k} \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} \DeclareUnicodeCharacter{1E3E}{\'M} \DeclareUnicodeCharacter{1E3F}{\'m} \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} \DeclareUnicodeCharacter{1E54}{\'P} \DeclareUnicodeCharacter{1E55}{\'p} \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} \DeclareUnicodeCharacter{1E7C}{\~V} \DeclareUnicodeCharacter{1E7D}{\~v} \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} \DeclareUnicodeCharacter{1E80}{\`W} \DeclareUnicodeCharacter{1E81}{\`w} \DeclareUnicodeCharacter{1E82}{\'W} \DeclareUnicodeCharacter{1E83}{\'w} \DeclareUnicodeCharacter{1E84}{\"W} \DeclareUnicodeCharacter{1E85}{\"w} \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} \DeclareUnicodeCharacter{1E8C}{\"X} \DeclareUnicodeCharacter{1E8D}{\"x} \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} \DeclareUnicodeCharacter{1E90}{\^Z} \DeclareUnicodeCharacter{1E91}{\^z} \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} \DeclareUnicodeCharacter{1E97}{\"t} \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} \DeclareUnicodeCharacter{1EBC}{\~E} \DeclareUnicodeCharacter{1EBD}{\~e} \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} \DeclareUnicodeCharacter{1EF2}{\`Y} \DeclareUnicodeCharacter{1EF3}{\`y} \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} \DeclareUnicodeCharacter{1EF8}{\~Y} \DeclareUnicodeCharacter{1EF9}{\~y} \DeclareUnicodeCharacter{2013}{--} \DeclareUnicodeCharacter{2014}{---} \DeclareUnicodeCharacter{2018}{\quoteleft} \DeclareUnicodeCharacter{2019}{\quoteright} \DeclareUnicodeCharacter{201A}{\quotesinglbase} \DeclareUnicodeCharacter{201C}{\quotedblleft} \DeclareUnicodeCharacter{201D}{\quotedblright} \DeclareUnicodeCharacter{201E}{\quotedblbase} \DeclareUnicodeCharacter{2022}{\bullet} \DeclareUnicodeCharacter{2026}{\dots} \DeclareUnicodeCharacter{2039}{\guilsinglleft} \DeclareUnicodeCharacter{203A}{\guilsinglright} \DeclareUnicodeCharacter{20AC}{\euro} \DeclareUnicodeCharacter{2192}{\expansion} \DeclareUnicodeCharacter{21D2}{\result} \DeclareUnicodeCharacter{2212}{\minus} \DeclareUnicodeCharacter{2217}{\point} \DeclareUnicodeCharacter{2261}{\equiv} }% end of \utfeightchardefs % US-ASCII character definitions. \def\asciichardefs{% nothing need be done \relax } % Make non-ASCII characters printable again for compatibility with % existing Texinfo documents that may use them, even without declaring a % document encoding. % \setnonasciicharscatcode \other \message{formatting,} \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt \secheadingskip = 12pt plus 3pt minus 2pt \subsecheadingskip = 9pt plus 2pt minus 2pt % Prevent underfull vbox error messages. \vbadness = 10000 % Don't be so finicky about underfull hboxes, either. \hbadness = 2000 % Following George Bush, get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on % \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else \emergencystretch = .15\hsize \fi } % Parameters in order: 1) textheight; 2) textwidth; % 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; % 7) physical page height; 8) physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. % \def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip % \vsize = #1\relax \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin \pageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in \pagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax % if we don't reset these, they will remain at "1 true in" of % whatever layout pdftex was dumped with. \pdfhorigin = 1 true in \pdfvorigin = 1 true in \fi % \setleading{\textleading} % \parindent = \defaultparindent \setemergencystretch } % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % If page is nothing but text, make it come out even. \internalpagesizes{607.2pt}{6in}% that's 46 lines {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} % Use @smallbook to reset parameters for 7x9.25 trim size. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% {-.2in}{0in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} % Use @smallerbook to reset parameters for 6x9 trim size. % (Just testing, parameters still in flux.) \def\smallerbook{{\globaldefs = 1 \parskip = 1.5pt plus 1pt \textleading = 12pt % \internalpagesizes{7.4in}{4.8in}% {-.2in}{-.4in}% {0pt}{14pt}% {9in}{6in}% % \lispnarrowing = 0.25in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .4cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % Double-side printing via postscript on Laserjet 4050 % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. % To change the settings for a different printer or situation, adjust % \normaloffset until the front-side and back-side texts align. Then % do the same for \bindingoffset. You can set these for testing in % your texinfo source file like this: % @tex % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex \internalpagesizes{673.2pt}{160mm}% that's 51 lines {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% % \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} % Use @afivepaper to print on European A5 paper. % From romildo@urano.iceb.ufop.br, 2 July 2000. % He also recommends making @example and @lisp be small. \def\afivepaper{{\globaldefs = 1 \parskip = 2pt plus 1pt minus 0.1pt \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% {\voffset}{\hoffset}% {\bindingoffset}{8pt}% {210mm}{148mm}% % \lispnarrowing = 0.2in \tolerance = 800 \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm }} % A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 \afourpaper \internalpagesizes{237mm}{150mm}% {\voffset}{4.6mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% % % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} % Use @afourwide to print on A4 paper in landscape format. \def\afourwide{{\globaldefs = 1 \afourpaper \internalpagesizes{241mm}{165mm}% {\voffset}{-2.95mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% \globaldefs = 0 }} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. % \parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % \dimen0 = #1\relax \advance\dimen0 by \voffset % \dimen2 = \hsize \advance\dimen2 by \normaloffset % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% {\bindingoffset}{44pt}% {\dimen0}{\dimen2}% }} % Set default to letter. % \letterpaper \message{and turning on texinfo input format.} % Define macros to output various characters with catcode for normal text. \catcode`\"=\other \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\$=\other \def\normaldoublequote{"} \def\normaltilde{~} \def\normalcaret{^} \def\normalunderscore{_} \def\normalverticalbar{|} \def\normalless{<} \def\normalgreater{>} \def\normalplus{+} \def\normaldollar{$}%$ font-lock fix % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print % otherwise. Since all the Computer Modern typewriter fonts have zero % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % \def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} % Same as above, but check for italic font. Actually this also catches % non-italic slanted fonts since it is impossible to distinguish them from % italic fonts. But since this is only used by $ and it uses \sl anyway % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} % Turn off all special characters except @ % (and those which the user can use as if they were ordinary). % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote \catcode`\~=\active \def~{{\tt\char126}} \chardef\hat=`\^ \catcode`\^=\active \def^{{\tt \hat}} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} \let\realunder=_ % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } \catcode`\|=\active \def|{{\tt\char124}} \chardef \less=`\< \catcode`\<=\active \def<{{\tt \less}} \chardef \gtr=`\> \catcode`\>=\active \def>{{\tt \gtr}} \catcode`\+=\active \def+{{\tt \char 43}} \catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix % If a .fmt file is being used, characters that might appear in a file % name cannot be active until we have parsed the command line. % So turn them off again, and have \everyjob (or @setfilename) turn them on. % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} % Used sometimes to turn off (effectively) the active characters even after % parsing them. \def\turnoffactive{% \normalturnoffactive \otherbackslash } \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work % \realbackslash is an actual character `\' with catcode other, and % \doublebackslash is two of them (for the pdf outlines). {\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} % In texinfo, backslash is an active character; it prints the backslash % in fixed width font. \catcode`\\=\active @def@normalbackslash{{@tt@backslashcurfont}} % On startup, @fixbackslash assigns: % @let \ = @normalbackslash % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of % the literal character `\'. % @def@normalturnoffactive{% @let\=@normalbackslash @let"=@normaldoublequote @let~=@normaltilde @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let<=@normalless @let>=@normalgreater @let+=@normalplus @let$=@normaldollar %$ font-lock fix @unsepspaces } % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @otherifyactive % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. % @gdef@eatinput input texinfo{@fixbackslash} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then % the first `\' in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. % Also turn back on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @ifx\@eatinput @let\ = @normalbackslash @fi @catcode`+=@active @catcode`@_=@active } % Say @foo, not \foo, in error messages. @escapechar = `@@ % These look ok in all fonts, so just make them not special. @catcode`@& = @other @catcode`@# = @other @catcode`@% = @other @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @c page-delimiter: "^\\\\message" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: @c vim:sw=2: @ignore arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 @end ignore SPASS-3.7/m4/ac_prog_perl_version.m40000644000374100135600000000237710427632153014200 00000000000000dnl @synopsis AC_PROG_PERL_VERSION(VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl dnl Makes sure that perl supports the version indicated. If true the shell dnl commands in ACTION-IF-TRUE are executed. If not the shell commands in dnl ACTION-IF-FALSE are run. Note if $PERL is not set (for example by dnl running AC_CHECK_PROG or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl) will dnl be run. dnl dnl Example: dnl dnl AC_PROG_PERL_VERSION(5.6.0) dnl dnl This will check to make sure that the perl you have supports at least dnl version 5.6.0. dnl dnl @version $Id: ac_prog_perl_version.m4,v 1.1 2006/05/08 12:07:07 topic Exp $ dnl @author Dean Povey dnl AC_DEFUN([AC_PROG_PERL_VERSION],[dnl # Make sure we have perl if test -z "$PERL"; then AC_PATH_PROG(PERL,perl,perl) fi # Check if version of Perl is sufficient ac_perl_version="$1" if test "x$PERL" != "x"; then AC_MSG_CHECKING(for perl version greater than or equal to $ac_perl_version) # NB: It would be nice to log the error if there is one, but we cannot rely # on autoconf internals $PERL -e "use $ac_perl_version;" > /dev/null 2>&1 if test $? -ne 0; then AC_MSG_RESULT(no); $3 else AC_MSG_RESULT(ok); $2 fi else AC_MSG_WARN(could not find perl) fi ])dnl SPASS-3.7/m4/missing0000755000374100037200000002557711340746531011141 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2006-05-10.23 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program 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. # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case $1 in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $1 in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: SPASS-3.7/m4/depcomp0000755000374100037200000004271311340746531011106 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2007-03-29.01 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software # Foundation, Inc. # This program 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. # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: SPASS-3.7/m4/compile0000755000374100037200000000717311340746531011110 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2005-05-14.22 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program 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. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` # Create the lock directory. # Note: use `[/.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: SPASS-3.7/scripts/0000777000374100037200000000000011340746537010763 500000000000000SPASS-3.7/scripts/texi2pod.pl.in0000755000374100135600000002557111340746516013414 00000000000000#! @PERL@ # Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. # This file is part of GNU CC. # GNU CC 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 CC 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 CC; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston MA 02111-1307, USA. # This does trivial (and I mean _trivial_) conversion of Texinfo # markup to Perl POD format. It's intended to be used to extract # something suitable for a manpage from a Texinfo document. $output = 0; $skipping = 0; %sects = (); $section = ""; @icstack = (); @endwstack = (); @skstack = (); @instack = (); $shift = ""; %defs = (); $fnno = 1; $inf = ""; $ibase = ""; while ($_ = shift) { if (/^-D(.*)$/) { if ($1 ne "") { $flag = $1; } else { $flag = shift; } $value = ""; ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/); die "no flag specified for -D\n" unless $flag ne ""; die "flags may only contain letters, digits, hyphens, dashes and underscores\n" unless $flag =~ /^[a-zA-Z0-9_-]+$/; $defs{$flag} = $value; } elsif (/^-/) { usage(); } else { $in = $_, next unless defined $in; $out = $_, next unless defined $out; usage(); } } if (defined $in) { $inf = gensym(); open($inf, "<$in") or die "opening \"$in\": $!\n"; $ibase = $1 if $in =~ m|^(.+)/[^/]+$|; } else { $inf = \*STDIN; } if (defined $out) { open(STDOUT, ">$out") or die "opening \"$out\": $!\n"; } while(defined $inf) { while(<$inf>) { # Certain commands are discarded without further processing. /^\@(?: [a-z]+index # @*index: useful only in complete manual |need # @need: useful only in printed manual |(?:end\s+)?group # @group .. @end group: ditto |page # @page: ditto |node # @node: useful only in .info file |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents )\b/x and next; chomp; # Look for filename and title markers. /^\@setfilename\s+([^.]+)/ and $fn = $1, next; /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next; # Identify a man title but keep only the one we are interested in. /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do { if (exists $defs{$1}) { $fn = $1; $tl = postprocess($2); } next; }; # Look for blocks surrounded by @c man begin SECTION ... @c man end. # This really oughta be @ifman ... @end ifman and the like, but such # would require rev'ing all other Texinfo translators. /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do { $output = 1 if exists $defs{$2}; $sect = $1; next; }; /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next; /^\@c\s+man\s+end/ and do { $sects{$sect} = "" unless exists $sects{$sect}; $sects{$sect} .= postprocess($section); $section = ""; $output = 0; next; }; # handle variables /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do { $defs{$1} = $2; next; }; /^\@clear\s+([a-zA-Z0-9_-]+)/ and do { delete $defs{$1}; next; }; next unless $output; # Discard comments. (Can't do it above, because then we'd never see # @c man lines.) /^\@c\b/ and next; # End-block handler goes up here because it needs to operate even # if we are skipping. /^\@end\s+([a-z]+)/ and do { # Ignore @end foo, where foo is not an operation which may # cause us to skip, if we are presently skipping. my $ended = $1; next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex|copying)$/; die "\@end $ended without \@$ended at line $.\n" unless defined $endw; die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw; $endw = pop @endwstack; if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) { $skipping = pop @skstack; next; } elsif ($ended =~ /^(?:example|smallexample|display)$/) { $shift = ""; $_ = ""; # need a paragraph break } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) { $_ = "\n=back\n"; $ic = pop @icstack; } else { die "unknown command \@end $ended at line $.\n"; } }; # We must handle commands which can cause skipping even while we # are skipping, otherwise we will not process nested conditionals # correctly. /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do { push @endwstack, $endw; push @skstack, $skipping; $endw = "ifset"; $skipping = 1 unless exists $defs{$1}; next; }; /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do { push @endwstack, $endw; push @skstack, $skipping; $endw = "ifclear"; $skipping = 1 if exists $defs{$1}; next; }; /^\@(ignore|menu|iftex|copying)\b/ and do { push @endwstack, $endw; push @skstack, $skipping; $endw = $1; $skipping = 1; next; }; next if $skipping; # Character entities. First the ones that can be replaced by raw text # or discarded outright: s/\@copyright\{\}/(c)/g; s/\@dots\{\}/.../g; s/\@enddots\{\}/..../g; s/\@([.!? ])/$1/g; s/\@[:-]//g; s/\@bullet(?:\{\})?/*/g; s/\@TeX\{\}/TeX/g; s/\@pounds\{\}/\#/g; s/\@minus(?:\{\})?/-/g; s/\\,/,/g; # Now the ones that have to be replaced by special escapes # (which will be turned back into text by unmunge()) s/&/&/g; s/\@\{/{/g; s/\@\}/}/g; s/\@\@/&at;/g; # Inside a verbatim block, handle @var specially. if ($shift ne "") { s/\@var\{([^\}]*)\}/<$1>/g; } # POD doesn't interpret E<> inside a verbatim block. if ($shift eq "") { s//>/g; } else { s//>/g; } # Single line command handlers. /^\@include\s+(.+)$/ and do { push @instack, $inf; $inf = gensym(); # Try cwd and $ibase. open($inf, "<" . $1) or open($inf, "<" . $ibase . "/" . $1) or die "cannot open $1 or $ibase/$1: $!\n"; next; }; /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/ and $_ = "\n=head2 $1\n"; /^\@subsection\s+(.+)$/ and $_ = "\n=head3 $1\n"; # Block command handlers: /^\@itemize\s+(\@[a-z]+|\*|-)/ and do { push @endwstack, $endw; push @icstack, $ic; $ic = $1; $_ = "\n=over 4\n"; $endw = "itemize"; }; /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do { push @endwstack, $endw; push @icstack, $ic; if (defined $1) { $ic = $1 . "."; } else { $ic = "1."; } $_ = "\n=over 4\n"; $endw = "enumerate"; }; /^\@([fv]?table)\s+(\@[a-z]+)/ and do { push @endwstack, $endw; push @icstack, $ic; $endw = $1; $ic = $2; $ic =~ s/\@(?:samp|strong|key|gcctabopt|env)/B/; $ic =~ s/\@(?:code|kbd)/C/; $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/; $ic =~ s/\@(?:file)/F/; $_ = "\n=over 4\n"; }; /^\@((?:small)?example|display)/ and do { push @endwstack, $endw; $endw = $1; $shift = "\t"; $_ = ""; # need a paragraph break }; /^\@itemx?\s*(.+)?$/ and do { if (defined $1) { # Entity escapes prevent munging by the <> processing below. Removed. $_ = "\n=item $1 \n"; } else { $_ = "\n=item $ic\n"; $ic =~ y/A-Ya-y/B-Zb-z/; $ic =~ s/(\d+)/$1 + 1/eg; } }; $section .= $shift.$_."\n"; } # End of current file. close($inf); $inf = pop @instack; } die "No filename or title\n" unless defined $fn && defined $tl; $sects{NAME} = "$fn \- $tl\n"; $sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES EXAMPLES BUGS NOTES FOOTNOTES SEEALSO AUTHORS COPYRIGHT)) { if(exists $sects{$sect}) { $head = $sect; $head =~ s/SEEALSO/SEE ALSO/; print "=head1 $head\n\n"; print scalar unmunge ($sects{$sect}); print "\n"; } } sub usage { die "usage: $0 [-D toggle...] [infile [outfile]]\n"; } sub postprocess { local $_ = $_[0]; # @value{foo} is replaced by whatever 'foo' is defined as. while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) { if (! exists $defs{$2}) { print STDERR "Option $2 not defined\n"; s/\Q$1\E//; } else { $value = $defs{$2}; s/\Q$1\E/$value/; } } # Formatting commands. # Temporary escape for @r. s/\@r\{([^\}]*)\}/R<$1>/g; s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g; s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g; s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g; s/\@sc\{([^\}]*)\}/\U$1/g; s/\@file\{([^\}]*)\}/F<$1>/g; s/\@w\{([^\}]*)\}/S<$1>/g; s/\@(?:dmn|math)\{([^\}]*)\}/$1/g; # Cross references are thrown away, as are @noindent and @refill. # (@noindent is impossible in .pod, and @refill is unnecessary.) # @* is also impossible in .pod; we discard it and any newline that # follows it. Similarly, our macro @gol must be discarded. s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g; s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g; s/;\s+\@pxref\{(?:[^\}]*)\}//g; s/\@noindent\s*//g; s/\@refill//g; s/\@gol//g; s/\@\*\s*\n?//g; # @uref can take one, two, or three arguments, with different # semantics each time. @url and @email are just like @uref with # one argument, for our purposes. s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g; s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g; s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g; # Un-escape <> at this point. s/<//g; # Now un-nest all B<>, I<>, R<>. Theoretically we could have # indefinitely deep nesting; in practice, one level suffices. 1 while s/([BIR])<([^<>]*)([BIR])<([^<>]*)>/$1<$2>$3<$4>$1 with bare ...; eliminate empty markup, B<>; # shift white space at the ends of [BI]<...> expressions outside # the expression. s/R<([^<>]*)>/$1/g; s/[BI]<>//g; s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g; s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g; # Extract footnotes. This has to be done after all other # processing because otherwise the regexp will choke on formatting # inside @footnote. while (/\@footnote/g) { s/\@footnote\{([^\}]+)\}/[$fnno]/; add_footnote($1, $fnno); $fnno++; } return $_; } sub unmunge { # Replace escaped symbols with their equivalents. local $_ = $_[0]; s/</E/g; s/>/E/g; s/{/\{/g; s/}/\}/g; s/&at;/\@/g; s/&/&/g; return $_; } sub add_footnote { unless (exists $sects{FOOTNOTES}) { $sects{FOOTNOTES} = "\n=over 4\n\n"; } $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++; $sects{FOOTNOTES} .= $_[0]; $sects{FOOTNOTES} .= "\n\n"; } # stolen from Symbol.pm { my $genseq = 0; sub gensym { my $name = "GEN" . $genseq++; my $ref = \*{$name}; delete $::{$name}; return $ref; } } SPASS-3.7/scripts/dfg2otter.pl.in0000755000374100037200000001626211340746516013550 00000000000000#! @PERL@ #************************************************************** #* ********************************************************** * #* * * * #* * Adds appropriate options for Otter * * #* * * * #* * * * #* $Revision: 1.1 $ * * #* $State: Exp $ * * #* $Date: 2006-03-07 16:19:26 $ * * #* $Author: topic $ * * #* * * * #* * Contact: * * #* * Christoph Weidenbach * * #* * MPI fuer Informatik * * #* * Stuhlsatzenhausweg 85 * * #* * 66123 Saarbruecken * * #* * Email: spass@mpi-inf.mpg.de * * #* * Germany * * #* * * * #* ********************************************************** * #************************************************************** # $RCSfile: dfg2otter.pl,v $ ############################################################# # # Perl script for converting DFG input files into # OTTER input files. The main work is done by the # c-executable 'dfg2otter'. # # Usage: # # dfg2otter.pl [ -t] [file1] [file2] # # Options: # # -t (time): sets timelimit in seconds for OTTER in the converted # file (i.e., generates the command 'assign(max_seconds, time).') # # Functionality: # # The number of file arguments determines where dfg2otter # takes its input from and directs its output to: # # file1 and file2 are given: # read from file1, write to file2 # # file1 is given: # read from file1, generate output file file.ot # # No file arguments: # input is read from stdin, output written to stdout # # ############################################################# ######################################################### # Packages ######################################################### use strict; # getopts package use Getopt::Std; use File::Copy; ######################################################### # temporaries ######################################################### my @TOREMOVE = (); ######################################################### # Defaults ######################################################### my $DFG2OTTER = "dfg2otter"; # dfg2otterpath my $OUTFILESUFFIX = ".ot"; # generic output file suffix my $ERRORFILESUFFIX = ".error"; # generic error file suffix ######################################################### # options ######################################################### # define default options my %options = ( t => 10 ); # default: 10 seconds timeout for proof checker # read options &getopts("t:", \%options); # shortcuts for options my $timelimit = $options{'t'}; ######################################################### # MAIN ######################################################### $SIG{INT} = \&catchint; # set up interrupt handler # try to get dfg2otter path from environment # otherwise default is kept if (defined($ENV{'DFG2OTTER'})) { $DFG2OTTER = $ENV{'DFG2OTTER'}; } # check that there are at most 2 arguments if (@ARGV > 2) { die "Too many arguments.\n";} ######################################################### # if there are no arguments, just call the original ######################################################### if (@ARGV == 0) { system("$DFG2OTTER -Stdin"); } ######################################################### # if one argument is given, use it as input file and # generate file.ot output file ######################################################### my ($in, $out); if (@ARGV == 1) { $in = $ARGV[0]; $out = $in."_".$$."_".$OUTFILESUFFIX; print `$DFG2OTTER -Stdin < $in > $out`; } ######################################################### # if two arguments are given, generate output filename # first, write parameters to it, and then append dfg2otter # output ######################################################### my ($errorfile, $parout, $convout, @conv_res, $errorlines); if (@ARGV == 2) { $in = $ARGV[0]; $out = $ARGV[1]; $errorfile = $out."_".$$."_".$ERRORFILESUFFIX; # print parameters $parout = gettmp($out); open(CONV, ">$parout") or die "dfg2otter.pl: could not open '$in': $!"; select CONV; &print_parameters(); close CONV; # convert SPASS file $convout = gettmp($out); @conv_res = `$DFG2OTTER $in $convout 2>$errorfile`; # echo STDERR, remove files if errors occured # (that is if $errorfile is not empty) if (-e $errorfile) { unless (open(EF, "<$errorfile")) { cleanup(); die "dfg2otter.pl: error opening '$errorfile': $!"; } $errorlines = 0; while () { print STDERR; $errorlines++; } close(EF); unlink($errorfile); if ($errorlines) { unlink($out); } } # the following lines copy the file $parout to $out, and then append $convout, # like the UNIX command 'cat $parout $convout > $out' copy($parout, $out) or die "Could not copy $parout to $out: $!"; open (IN, "$convout") or die "Could not open $convout: $!"; open(APPEND, ">>$out") or die "Could not open $out: $!"; while () { print APPEND; } close(APPEND); close(IN); cleanup(); } #################################################### # INPUT : A signal name # EFFECTS: Remove temporaries and reports interrupt #################################################### sub catchint { my $signame = shift; cleanup(); die "\n\ndfg2otter.pl: caught signal $signame. Cleaning up."; } #################################################### # EFFECTS: Remove temporaries ##################################################### sub cleanup { unlink @TOREMOVE; } #################################################### # EFFECTS: Print otter default parameters to stdout #################################################### sub print_parameters { print "set(process_input).\n"; print "set(binary_res).\n"; print "set(factor).\n"; print "set(hyper_res).\n"; print "assign(pick_given_ratio, 4).\n"; print "clear(print_kept).\n"; print "clear(print_new_demod).\n"; print "clear(print_back_demod).\n"; print "clear(print_back_sub).\n"; print "set(knuth_bendix).\n"; print "set(para_from).\n"; print "set(para_into).\n"; print "set(para_from_right).\n"; print "set(para_into_right).\n"; print "set(para_from_left).\n"; print "set(para_into_left).\n"; print "set(para_from_vars).\n"; print "set(back_demod).\n"; print "set(auto).\n"; print "assign(max_seconds, $timelimit).\n"; } #################################################### # INPUT: A filename # OUTPUT: A similar filename that is unique #################################################### sub gettmp { my ($file) = @_; my ($cnt) = 0; while (-e $file."$cnt") { $cnt++; } $file = $file."$cnt"; unshift(@TOREMOVE, $file); return($file); } SPASS-3.7/examples/0000777000374100037200000000000011340746540011104 500000000000000SPASS-3.7/examples/problem54.dfg0000644000374100135600000000123510376314712013317 00000000000000begin_problem(Pelletier54). list_of_descriptions. name({*Pelletier's Problem No. 54*}). author({*Christoph Weidenbach*}). status(unsatisfiable). description({*Problem taken in revised form from the "Pelletier Collection", Journal of Automated Reasoning, Vol. 2, No. 2, pages 191-216*}). end_of_list. list_of_symbols. predicates[(F,2)]. end_of_list. list_of_formulae(axioms). formula(forall([U],exists([V],forall([W],equiv(F(W,V),equal(W,U)))))). end_of_list. list_of_formulae(conjectures). formula(not(exists([U],forall([V],equiv(F(V,U),forall([W],implies(F(V,W),exists([X],and(F(X,W),not(exists([Y],and(F(Y,W),F(Y,X))))))))))))). end_of_list. end_problem. SPASS-3.7/SPASS/0000777000374100037200000000000011340746541010160 500000000000000SPASS-3.7/SPASS/resolution.c0000644000374100037200000001361511340510067012441 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * RESOLUTION * */ /* * * */ /* * $Module: RESOLUTION * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: resolution.c,v $ */ #include "resolution.h" /**************************************************************/ /* Functions */ /**************************************************************/ void res_InsertClauseIndex(CLAUSE clause, st_INDEX stindex) /********************************************************** INPUT: A st_INDEX and a clause. RETURNS: Inserts the clause in the st_INDEX stindex. CAUTION: None. ***********************************************************/ { int n,j; n = clause_Length(clause); for (j = 0; j < n; j++) st_EntryCreate(stindex, clause_GetLiteral(clause,j), clause_GetLiteralTerm(clause,j), cont_LeftContext()); } void res_DeleteClauseIndex(CLAUSE clause, st_INDEX stindex) /********************************************************** INPUT: A st_INDEX and a clause. RETURNS: Deletes the clause from the st_INDEX stindex. CAUTION: None. ***********************************************************/ { int n, j; n = clause_Length(clause); for (j = 0; j < n; j++) if (!st_EntryDelete(stindex, clause_GetLiteral(clause,j), clause_GetLiteralTerm(clause,j), cont_LeftContext())) misc_DumpCore(); } CLAUSE res_SelectLightestClause(LIST clauselist) /********************************************************** INPUT: A list of clauses. RETURNS: The lightest clause of the clauselist. CAUTION: None. ***********************************************************/ { CLAUSE clause; LIST scan; int min; clause = list_Car(clauselist); min = clause_Weight(clause); for (scan=list_Cdr(clauselist); !list_Empty(scan); scan=list_Cdr(scan)) { if (clause_Weight(list_Car(scan)) < min) { clause = list_Car(scan); min = clause_Weight(clause); } } return clause; } BOOL res_HasTautology(CLAUSE clause) /********************************************************** INPUT: A clauses. RETURNS: TRUE if the clause contains a complementary literal pair and FALSE otherwise. CAUTION: None. ***********************************************************/ { BOOL found; TERM literal1; int i, j, n; found = FALSE; n = clause_Length(clause); for (i = 0; i < n && !found; i++) { literal1 = fol_ComplementaryTerm(clause_GetLiteralTerm(clause,i)); for (j = 0; j < n && !found; j++) if (j != i && term_Equal(literal1, clause_GetLiteralTerm(clause,j))) found = TRUE; term_Delete(literal1); } return found; } BOOL res_BackSubWithLength(CLAUSE clause, st_INDEX stindex) /********************************************************** INPUT: A clauses and an index. RETURNS: TRUE if a clause of the index subsumes the clause clause and length(clause) >= length(clause of index). CAUTION: None. ***********************************************************/ { int n,i; LIST scan,generals; TERM term; LITERAL litres; n = clause_Length(clause); for (i = 0; i < n; i++) { term = clause_GetLiteralTerm(clause,i); generals = st_GetGen(cont_LeftContext(), stindex, term); for (scan = generals; !list_Empty(scan); scan = list_Cdr(scan)) { litres = (LITERAL) list_Car(scan); if (litres == clause_GetLiteral(clause_LiteralOwningClause(litres),0) && clause_Length(clause) >= clause_Length(clause_LiteralOwningClause(litres)) && clause_Weight(clause) >= clause_Weight(clause_LiteralOwningClause(litres)) && subs_Idc(clause_LiteralOwningClause(litres),clause)) { list_Delete(generals); return TRUE; } } list_Delete(generals); } return FALSE; } SPASS-3.7/SPASS/hashmap.c0000644000374100037200000001654411334360556011674 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * HASHMAP SUPPORTED BY GROWABLE ARRAY * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /**************************************************************/ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /**************************************************************/ #include "hashmap.h" /**************************************************************/ /* Functions */ /**************************************************************/ void hm_Init(void) /************************************************************** INPUT: None. RETURNS: void. SUMMARY: Placebo satisfying the general module layout. ***************************************************************/ { return; } void hm_Free(void) /************************************************************** INPUT: None. RETURNS: void. SUMMARY: Placebo satisfying the general module layout. ***************************************************************/ { return; } HASHMAP_HASH hm_StringHash(const char* key) /************************************************************** INPUT: A string. RETURNS: A hash of a given string. COMMENT: The formula is made to ensure both admissable speed and hashing robustness. ***************************************************************/ { int i; HASHMAP_HASH result; i = 0; result = 0; while (key[i] != '\0') { result = result*31 + key[i]; i++; } return result; } HASHMAP hm_Create(int init_size_bits) /************************************************************** INPUT: An int denoting the logarithm of the initial size (the new size will be (1<size = (1<table = (LIST*)memory_Malloc(sizeof(LIST)*hm->size); hm->num_of_els = 0; for(i = 0; i < hm->size; i++) hm->table[i] = list_Nil(); return hm; } void hm_Delete(HASHMAP hm) /************************************************************** INPUT: Pointer to the hashmap to be deleted. MEMORY: Frees the memory associated with the given hashmap. ***************************************************************/ { int i; for(i = 0; i < hm->size; i++) list_DeleteWithElement(hm->table[i],(void (*)(POINTER))list_PairFree); memory_Free(hm->table,sizeof(LIST)*hm->size); memory_Free(hm,sizeof(HASHMAP_NODE)); } static __inline__ unsigned hm_IndexFor(HASHMAP_HASH h, int length) /************************************************************** Transformes a given hash to an address in an array of a given length. The length must be a power of 2. ***************************************************************/ { return h & (length-1); } void hm_Insert(HASHMAP hm, POINTER value, HASHMAP_HASH hash) /************************************************************** INPUT: A hashmap, an element to be inserted and its hash. EFFECT: Inserts a given value in the hashmap accoring to its hash. The function doesn't check if the key was already stored (which should not be the case). If the number of values stored in the hashmap exceeds a double of the current table size the table is doubled, new array allocated, and the records are rehashed. (This is completely heuristical and could be modified to exchange speed for memory and vice versa.) ***************************************************************/ { int i; i = hm_IndexFor(hash,hm->size); hm->table[i] = list_Cons(list_PairCreate((POINTER)hash,value),hm->table[i]); if (++hm->num_of_els > (hm->size << 1)) { /*grow and rehash*/ int new_size; LIST* new_table; new_size = hm->size << 1; new_table = (LIST*)memory_Malloc(sizeof(LIST)*new_size); for(i = 0; i < new_size; i++) new_table[i] = list_Nil(); for(i = 0; i < hm->size; i++) { LIST Scan; Scan = hm->table[i]; while (!list_Empty(Scan)) { int j; LIST Elem, Pair; Elem = Scan; Pair = list_Car(Elem); hash = (HASHMAP_HASH)list_PairFirst(Pair); j = hm_IndexFor(hash,new_size); Scan = list_Cdr(Scan); list_Rplacd(Elem,new_table[j]); new_table[j] = Elem; } } memory_Free(hm->table,sizeof(LIST)*hm->size); hm->size = new_size; hm->table = new_table; } } static __inline__ BOOL hm_ValueTest(POINTER value, POINTER pr) /************************************************************** Test function used to find an element in a hashmap's list. The first parameter is in fact just a value to be matched with the second part of pair thats stored in the list. (Used only in hm_Remove) ***************************************************************/ { return list_PairSecond((LIST)pr) == value; } void hm_Remove(HASHMAP hm, POINTER value, HASHMAP_HASH hash) /************************************************************** INPUT: A hashmap, an element to be inserted and its hash. EFFECT: Removes the given value from appropriate list in the hashmap's table. ***************************************************************/ { int i; LIST List; i = hm_IndexFor(hash,hm->size); List = hm->table[i]; hm->table[i] = list_DeleteElementFree(List, value, hm_ValueTest, (void (*)(POINTER))list_PairFree); hm->num_of_els--; } POINTER hm_Retrieve(HASHMAP hm, HASHMAP_HASH hash, BOOL(*test)(POINTER)) /************************************************************** INPUT: A hashmap, element's hash, and a test function that should recognize if a given a value stored in the hashmap is the one looked for (and for such return TRUE) RETURNS: The value found or HASHMAP_NO_RETRIEVE if the search fails. ***************************************************************/ { int i; LIST Scan; i = hm_IndexFor(hash,hm->size); Scan = hm->table[i]; while (!list_Empty(Scan)) { LIST Pair; HASHMAP_HASH h; Pair = list_Car(Scan); h = (HASHMAP_HASH)list_PairFirst(Pair); if (h == hash) { /*could be him*/ POINTER value; value = list_PairSecond(Pair); if (test(value)) return value; } Scan = list_Cdr(Scan); } return HASHMAP_NO_RETRIEVE; } SPASS-3.7/SPASS/unify.c0000644000374100037200000006304211340510070011361 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * STANDARD UNIFICATION * */ /* * * */ /* * $Module: UNIFY * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:10:00 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: unify.c,v $ */ #include "unify.h" /**************************************************************/ /* ********************************************************** */ /* * * */ /* * INITIALIZATION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void unify_Init(void) /********************************************************** INPUT: None. RETURNS: None. EFFECT: Initializes the unify module. ********************************************************/ { } void unify_Free(void) /********************************************************** INPUT: None. RETURNS: None. EFFECT: Frees internal structures of the unify module. ********************************************************/ { } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * MISC FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /**************************************************************/ /* ********************************************************** */ /* * * */ /* * OCCUR CHECK * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_OccurCheckCom(SYMBOL Top, CONTEXT Context, TERM Term) /********************************************************** INPUT: A variable symbol, a context, and a term. RETURNS: TRUE if there is a occur check failure with respect to the variable symbol and . The search is started in ***********************************************************/ { int Bottom; LIST Args; Bottom = stack_Bottom(); for (;;) { if (term_IsVariable(Term)) { if (symbol_Equal(Top, term_TopSymbol(Term))) { stack_SetBottom(Bottom); return TRUE; } else if (cont_VarIsBound(Context, term_TopSymbol(Term))) { Term = cont_ContextBindingTerm(Context, term_TopSymbol(Term)); continue; } } else if (term_IsComplex(Term)) { Args = term_ArgumentList(Term); if (!list_Empty(list_Cdr(Args))) stack_Push(list_Cdr(Args)); Term = list_Car(Args); continue; } if (stack_Empty(Bottom)) return FALSE; else { Args = (LIST)stack_PopResult(); Term = list_Car(Args); if (!list_Empty(list_Cdr(Args))) stack_Push(list_Cdr(Args)); } } } BOOL unify_OccurCheck(CONTEXT CTop, SYMBOL Top, CONTEXT CTerm, TERM Term) /********************************************************** INPUT: A context, a variable symbol, a context, and a term. RETURNS: TRUE if there is a occur check failure with respect to the variable symbol and . The search is started in ***********************************************************/ { int Bottom; LIST Args; SYMBOL TermTop; Bottom = stack_Bottom(); for (;;) { if (term_IsVariable(Term)) { TermTop = term_TopSymbol(Term); if ((CTop == CTerm) && (symbol_Equal(Top, TermTop))) { stack_SetBottom(Bottom); return TRUE; } else if (cont_VarIsBound(CTerm, TermTop)) { Term = cont_ContextBindingTerm(CTerm, TermTop); CTerm = cont_ContextBindingContext(CTerm, TermTop); continue; } } else if (term_IsComplex(Term)) { Args = term_ArgumentList(Term); if (!list_Empty(list_Cdr(Args))) { stack_Push(CTerm); stack_Push(list_Cdr(Args)); } Term = list_Car(Args); continue; } if (stack_Empty(Bottom)) return FALSE; else { Args = (LIST)stack_PopResult(); Term = list_Car(Args); CTerm = (CONTEXT)stack_Top(); if (list_Empty(list_Cdr(Args))) stack_Pop(); else stack_Push(list_Cdr(Args)); } } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * UNIFICATION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_Unify(CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) /********************************************************** INPUT: Two terms which may contain the same variable symbols. Equal variable symbols are interpreted different in and , respectively. RETURNS: TRUE, if and are unifiable, FALSE otherwise. CAUTION: None. ***********************************************************/ { CONTEXT CHelp; LIST ArgsL, ArgsR; int Bottom; BOOL Bound; Bound = FALSE; Bottom = stack_Bottom(); for (;;) { while (term_IsVariable(TermL) && cont_VarIsBound(CtL, term_TopSymbol(TermL))) { CHelp = cont_ContextBindingContext(CtL, term_TopSymbol(TermL)); TermL = cont_ContextBindingTerm(CtL, term_TopSymbol(TermL)); CtL = CHelp; } while (term_IsVariable(TermR) && cont_VarIsBound(CtR, term_TopSymbol(TermR))) { CHelp = cont_ContextBindingContext(CtR, term_TopSymbol(TermR)); TermR = cont_ContextBindingTerm(CtR, term_TopSymbol(TermR)); CtR = CHelp; } /* Caution: Bindings from variable to variable are made with priority from the right context into the left context. */ if (term_IsVariable(TermL)) { if (term_IsVariable(TermR)) { if (!(CtL == CtR && term_EqualTopSymbols(TermL, TermR))) Bound = cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); } else if (Bound && unify_OccurCheck(CtL, term_TopSymbol(TermL), CtR, TermR)) { stack_SetBottom(Bottom); return FALSE; } else Bound = cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); } else if (term_IsVariable(TermR)) { if (Bound && unify_OccurCheck(CtR, term_TopSymbol(TermR), CtL, TermL)) { stack_SetBottom(Bottom); return FALSE; } else Bound = cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL) && TermL != TermR) { ArgsL = term_ArgumentList(TermL); ArgsR = term_ArgumentList(TermR); if (!list_Empty(list_Cdr(ArgsL))) { stack_Push(CtL); stack_Push(CtR); stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } TermL = list_Car(ArgsL); TermR = list_Car(ArgsR); continue; } } else { stack_SetBottom(Bottom); return FALSE; } if (stack_Empty(Bottom)) return TRUE; else { ArgsR = stack_PopResult(); ArgsL = stack_PopResult(); TermR = list_Car(ArgsR); TermL = list_Car(ArgsL); CtR = (CONTEXT)stack_Top(); CtL = (CONTEXT)stack_NthTop(1); if (list_Empty(list_Cdr(ArgsL))) stack_NPop(2); else { stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } } } } BOOL unify_UnifyCom(CONTEXT Context, TERM TermL, TERM TermR) /********************************************************** INPUT: Two terms which may contain the same variable symbols. Equal variable symbols are interpreted equally in and , respectively. RETURNS: TRUE, if and are unifiable, FALSE otherwise. CAUTION: None. ***********************************************************/ { LIST ArgsL, ArgsR; int Bottom; Bottom = stack_Bottom(); for (;;) { while (term_IsVariable(TermL) && cont_VarIsBound(Context, term_TopSymbol(TermL))) TermL = cont_ContextBindingTerm(Context, term_TopSymbol(TermL)); while (term_IsVariable(TermR) && cont_VarIsBound(Context, term_TopSymbol(TermR))) TermR = cont_ContextBindingTerm(Context, term_TopSymbol(TermR)); if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL) && TermL != TermR) { ArgsL = term_ArgumentList(TermL); ArgsR = term_ArgumentList(TermR); if (!list_Empty(list_Cdr(ArgsL))) { stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } TermL = list_Car(ArgsL); TermR = list_Car(ArgsR); continue; } } else if (term_IsVariable(TermL)) { if (term_IsVariable(TermR)) cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); else if (unify_OccurCheckCom(term_TopSymbol(TermL), Context, TermR)) { stack_SetBottom(Bottom); return FALSE; } else cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); } else if (term_IsVariable(TermR)) { if (unify_OccurCheckCom(term_TopSymbol(TermR), Context, TermL)) { stack_SetBottom(Bottom); return FALSE; } else cont_CreateBinding(Context, term_TopSymbol(TermR), Context, TermL); } else { stack_SetBottom(Bottom); return FALSE; } if (stack_Empty(Bottom)) return TRUE; else { ArgsR = stack_PopResult(); ArgsL = stack_PopResult(); TermR = list_Car(ArgsR); TermL = list_Car(ArgsL); if (!list_Empty(list_Cdr(ArgsL))) { stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } } } } BOOL unify_UnifyNoOC(CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) /********************************************************** INPUT: Two terms which may contain the same variable symbols. Equal variable symbols are interpreted different in and , respectively. RETURNS: TRUE, if and are unifiable, FALSE otherwise. CAUTION: None. ***********************************************************/ { CONTEXT CHelp; LIST ArgsL, ArgsR; int Bottom; Bottom = stack_Bottom(); for (;;) { while (term_IsVariable(TermL) && cont_VarIsBound(CtL, term_TopSymbol(TermL))) { CHelp = cont_ContextBindingContext(CtL, term_TopSymbol(TermL)); TermL = cont_ContextBindingTerm(CtL, term_TopSymbol(TermL)); CtL = CHelp; } while (term_IsVariable(TermR) && cont_VarIsBound(CtR, term_TopSymbol(TermR))) { CHelp = cont_ContextBindingContext(CtR, term_TopSymbol(TermR)); TermR = cont_ContextBindingTerm(CtR, term_TopSymbol(TermR)); CtR = CHelp; } /* Caution: Bindings from variable to variable are made with priority from the right context into the left context. */ if (term_IsVariable(TermL)) { if (term_IsVariable(TermR)) { if (!(CtL == CtR && term_EqualTopSymbols(TermL, TermR))) cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); } else cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); } else if (term_IsVariable(TermR)) cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL) && TermL != TermR) { ArgsL = term_ArgumentList(TermL); ArgsR = term_ArgumentList(TermR); if (!list_Empty(list_Cdr(ArgsL))) { stack_Push(CtL); stack_Push(CtR); stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } TermL = list_Car(ArgsL); TermR = list_Car(ArgsR); continue; } } else { stack_SetBottom(Bottom); return FALSE; } if (stack_Empty(Bottom)) return TRUE; else { ArgsR = stack_PopResult(); ArgsL = stack_PopResult(); TermR = list_Car(ArgsR); TermL = list_Car(ArgsL); CtR = (CONTEXT) stack_Top(); CtL = (CONTEXT) stack_NthTop(1); if (list_Empty(list_Cdr(ArgsL))) stack_NPop(2); else { stack_Push(list_Cdr(ArgsL)); stack_Push(list_Cdr(ArgsR)); } } } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * UNIFICATION WITH FULL OCCUR CHECK (recursive) * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_UnifyAllOC(CONTEXT IndexContext, CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) { while (term_IsVariable(TermL)) { SYMBOL TermTop; TermTop = term_TopSymbol(TermL); if (cont_VarIsBound(CtL, TermTop)) { CONTEXT CHelp; CHelp = cont_ContextBindingContext(CtL, TermTop); TermL = cont_ContextBindingTerm(CtL, TermTop); CtL = CHelp; } else break; } while (term_IsVariable(TermR)) { SYMBOL TermTop; TermTop = term_TopSymbol(TermR); if (cont_VarIsBound(CtR, TermTop)) { CONTEXT CHelp; CHelp = cont_ContextBindingContext(CtR, TermTop); TermR = cont_ContextBindingTerm(CtR, TermTop); CtR = CHelp; } else break; } if (term_IsVariable(TermL)) { if (term_IsVariable(TermR)) { if ((CtL != CtR || !term_EqualTopSymbols(TermL, TermR))) { if (term_IsIndexVariable(TermL)) cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); else if (term_IsIndexVariable(TermR) || (CtR == IndexContext)) cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); else cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); } return TRUE; } else if (unify_OccurCheck(CtL, term_TopSymbol(TermL), CtR, TermR)) return FALSE; else { cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); return TRUE; } } else if (term_IsVariable(TermR)) { if (unify_OccurCheck(CtR, term_TopSymbol(TermR), CtL, TermL)) return FALSE; else { cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); return TRUE; } } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL)) { LIST ArgL, ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_UnifyAllOC(IndexContext, CtL, list_Car(ArgL), CtR, list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * GENERALIZATION TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_Match(CONTEXT Context, TERM TermL, TERM TermR) { if (term_IsVariable(TermL)) { if (cont_VarIsBound(Context, term_TopSymbol(TermL))) return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); else { cont_CreateBinding(Context, term_TopSymbol(TermL), cont_InstanceContext(), TermR); return TRUE; } } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL)) { LIST ArgL; LIST ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_Match(Context, list_Car(ArgL), list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } BOOL unify_MatchFlexible(CONTEXT Context, TERM TermL, TERM TermR) /************************************************************** INPUT: Two terms where symbols with flexible arity are allowed. RETURNS: TRUE if matches . ***************************************************************/ { if (term_IsVariable(TermL)) { if (cont_VarIsBound(Context, term_TopSymbol(TermL))) return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); else { cont_CreateBinding(Context, term_TopSymbol(TermL), cont_InstanceContext(), TermR); return TRUE; } } else if (term_EqualTopSymbols(TermL, TermR) && list_Length(term_ArgumentList(TermL)) == list_Length(term_ArgumentList(TermR))) { if (term_IsComplex(TermL)) { LIST ArgL; LIST ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_MatchFlexible(Context, list_Car(ArgL), list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } void unify_EstablishMatcher(CONTEXT Context, SUBST Subst) { while (subst_Exist(Subst)) { /* Index to query */ cont_CreateBinding(Context, subst_Dom(Subst), cont_InstanceContext(), subst_Cod(Subst)); Subst = subst_Next(Subst); } } BOOL unify_MatchBindingsHelp(const CONTEXT IndexContext, TERM TermL, CONTEXT CtR, TERM TermR) { while (term_IsVariable(TermR)) { SYMBOL TermTop; TermTop = term_TopSymbol(TermR); if (symbol_IsIndexVariable(TermTop)) CtR = IndexContext; else if (CtR == cont_InstanceContext()) break; if (cont_VarIsBound(CtR, TermTop)) { CONTEXT CHelp; CHelp = cont_ContextBindingContext(CtR, TermTop); TermR = cont_ContextBindingTerm(CtR, TermTop); CtR = CHelp; } else break; } if (term_IsVariable(TermL)) { /* Assertion: Variables of 'TermL' are bound in the index context only. */ if (cont_VarIsBound(IndexContext, term_TopSymbol(TermL))) return cont_TermEqualModuloBindings(IndexContext, cont_ContextBindingContext(IndexContext, term_TopSymbol(TermL)), cont_ContextBindingTerm(IndexContext, term_TopSymbol(TermL)), CtR, TermR); else { cont_CreateBinding(IndexContext, term_TopSymbol(TermL), CtR, TermR); return TRUE; } } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL)) { LIST ArgL; LIST ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_MatchBindingsHelp(IndexContext, list_Car(ArgL), CtR, list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } BOOL unify_MatchBindings(const CONTEXT IndexContext, TERM TermL, TERM TermR) { return unify_MatchBindingsHelp(IndexContext, TermL, cont_InstanceContext(), TermR); } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * INSTANCE TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_MatchReverse(const CONTEXT IndexContext, TERM TermL, CONTEXT CtR, TERM TermR) /********************************************************* INPUT: 'TermL' is in IndexContext and the codomain of a subst., 'CtR' is the context of 'TermR' which is the codomain of a subst. obtained by a variable binding, 'Bindings' is the number of established bindings. RETURNS: TRUE, if 'TermL' is an instance of 'TermR'; FALSE, otherwise. **********************************************************/ { while (term_IsVariable(TermR)) { SYMBOL TermTop; TermTop = term_TopSymbol(TermR); if (symbol_IsIndexVariable(TermTop)) CtR = IndexContext; else if (CtR == cont_InstanceContext()) break; if (cont_VarIsBound(CtR, TermTop)) { CONTEXT CHelp; CHelp = cont_ContextBindingContext(CtR, TermTop); TermR = cont_ContextBindingTerm(CtR, TermTop); CtR = CHelp; } else break; } if (term_IsVariable(TermL)) { if ((CtR == cont_InstanceContext()) && term_EqualTopSymbols(TermL, TermR)) /* 'TermL' and 'TermR' are exactly the same variables (via bindings), therefore do not bind them, just return positive. */ return TRUE; else if (term_IsIndexVariable(TermL)) { cont_CreateBinding(IndexContext, term_TopSymbol(TermL), CtR, TermR); return TRUE; } else if (term_IsVariable(TermR) && (term_IsIndexVariable(TermR) || (CtR == IndexContext))) { cont_CreateBinding(IndexContext, term_TopSymbol(TermR), cont_InstanceContext(), TermL); return TRUE; } else return FALSE; } else if (term_IsVariable(TermR)) { if (term_IsIndexVariable(TermR) || (CtR == IndexContext)) { cont_CreateBinding(IndexContext, term_TopSymbol(TermR), cont_InstanceContext(), TermL); return TRUE; } else return FALSE; } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL)) { LIST ArgL, ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_MatchReverse(IndexContext, list_Car(ArgL), CtR, list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * VARIATION TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL unify_Variation(const CONTEXT Context, TERM TermL, TERM TermR) { if (term_IsVariable(TermL)) { if (term_EqualTopSymbols(TermL, TermR)) /* TermL and TermR are in different contexts but both are term variables which do not need to be variated. Index variables cannot occur in TermR which is the term to be inserted. */ return TRUE; else if (term_IsIndexVariable(TermL)) { if (cont_VarIsBound(Context, term_TopSymbol(TermL))) return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); else { /* Index to query */ cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); return TRUE; } } else return FALSE; } else if (term_EqualTopSymbols(TermL, TermR)) { if (term_IsComplex(TermL)) { LIST ArgL; LIST ArgR; for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) if (!unify_Variation(Context, list_Car(ArgL), list_Car(ArgR))) return FALSE; } return TRUE; } else return FALSE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMMON GENERALIZATIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ TERM unify_ComGenLinear(const CONTEXT IndexContext, SUBST* SubstL, TERM TermL, SUBST* SubstR, TERM TermR) { if (term_IsIndexVariable(TermR)) { *SubstL = subst_Add(term_TopSymbol(TermR), term_Copy(TermL), *SubstL); return term_Copy(TermR); } else if (term_EqualTopSymbols(TermL, TermR)) { LIST ArgList, ArgL, ArgR; ArgList = list_Nil(); for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); !list_Empty(ArgL); ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) ArgList = list_Nconc(ArgList, list_List(unify_ComGenLinear(IndexContext, SubstL, list_Car(ArgL), SubstR, list_Car(ArgR)))); return term_Create(term_TopSymbol(TermL), ArgList); } else { SYMBOL Symbol; Symbol = cont_NextIndexVariable(IndexContext); *SubstL = subst_Add(Symbol, term_Copy(TermL), *SubstL); *SubstR = subst_Add(Symbol, term_Copy(TermR), *SubstR); return term_Create(Symbol, list_Nil()); } } SPASS-3.7/SPASS/sharing.h0000644000374100037200000002057711340510067011703 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * STRUCTURE SHARING * */ /* * * */ /* * $Module: SHARING * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: sharing.h,v $ */ #ifndef _SHARING_ #define _SHARING_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "term.h" #include "st.h" /**************************************************************/ /* Data Structures and Constants */ /**************************************************************/ /* Symbol Tables; constants are just positive */ /* integers and variables negative integers. */ /* For constants and vars is a special symbol */ /* table available, containing the sharing */ /* info, i.e. a POINTER to the term structure, if */ /* the symbol is already inserted in the sharing */ /* structure, a NULL Pointer else. */ typedef TERM VARTABLE[symbol__MAXVARIABLES]; typedef TERM CONSTTABLE[symbol__MAXSIGNATURE]; typedef struct { st_INDEX index; VARTABLE vartable; CONSTTABLE consttable; NAT stampId; } SHARED_INDEX_NODE, *SHARED_INDEX; /**************************************************************/ /* Inline Functions */ /**************************************************************/ static __inline__ st_INDEX sharing_Index(SHARED_INDEX ShIndex) { return ShIndex->index; } static __inline__ void sharing_SetIndex(SHARED_INDEX ShIndex, st_INDEX ST) { ShIndex->index = ST; } static __inline__ const TERM* sharing_Vartable(SHARED_INDEX ShIndex) { return ShIndex->vartable; } static __inline__ const TERM* sharing_Consttable(SHARED_INDEX ShIndex) { return ShIndex->consttable; } static __inline__ NAT sharing_StampID(SHARED_INDEX ShIndex) { return ShIndex->stampId; } static __inline__ void sharing_SetStampID(SHARED_INDEX ShIndex, NAT Stamp) { ShIndex->stampId = Stamp; } static __inline__ TERM sharing_VartableEntry(SHARED_INDEX ShIndex, NAT Index) { return ShIndex->vartable[Index]; } static __inline__ void sharing_SetVartableEntry(SHARED_INDEX ShIndex, NAT Index, TERM Term) { ShIndex->vartable[Index] = Term; } static __inline__ TERM sharing_ConsttableEntry(SHARED_INDEX ShIndex, NAT Index) { return ShIndex->consttable[Index]; } static __inline__ void sharing_SetConsttableEntry(SHARED_INDEX ShIndex, NAT Index, TERM Term) { ShIndex->consttable[Index] = Term; } static __inline__ TERM sharing_GetVarFromSymbol(SYMBOL S, SHARED_INDEX ShIndex) { return sharing_VartableEntry(ShIndex, symbol_VarIndex(S)); } static __inline__ int sharing_VariableIndex(TERM Term) { return symbol_VarIndex(term_TopSymbol(Term)); } static __inline__ int sharing_ConstantIndex(TERM Term) { return symbol_Index(term_TopSymbol(Term)); } static __inline__ BOOL sharing_IsSharedVar(TERM T, SHARED_INDEX ShIndex) /* RETURNS: True if there's already an entry for the variable T */ /* in the Vartable of the shared index ShIndex. */ { return sharing_VartableEntry(ShIndex, sharing_VariableIndex(T)) != NULL; } static __inline__ BOOL sharing_IsSharedConst(TERM T, SHARED_INDEX ShIndex) /* True if there's already an entry for the constant T */ /* in the Consttable of the shared index ShIndex. */ { return sharing_ConsttableEntry(ShIndex, sharing_ConstantIndex(T)) != NULL; } static __inline__ BOOL sharing_IsNotReallyShared(TERM Term) /* Der einzige Superterm ist der in dem ich loesche */ { return list_Length(term_SupertermList(Term)) <= 1; } static __inline__ void sharing_RememberSharedTermCopy(TERM Term, TERM Copy) /* The unshared term Term has now a link to its shared copy */ { term_RplacSuperterm(Term, Copy); } static __inline__ TERM sharing_SharedTermCopy(TERM Term) /* Return the shared copy of the unshared term Term */ { return term_Superterm(Term); } /**************************************************************/ /* Functions for Creation and Deletion of a SHARED_INDEX */ /**************************************************************/ SHARED_INDEX sharing_IndexCreate(void); void sharing_IndexDelete(SHARED_INDEX); /**************************************************************/ /* Functions on term insertion and deletion. */ /**************************************************************/ TERM sharing_Insert(POINTER, TERM, SHARED_INDEX); void sharing_Delete(POINTER, TERM, SHARED_INDEX); void sharing_PushOnStack(TERM); void sharing_PushReverseOnStack(TERM); void sharing_PushOnStackNoStamps(TERM); void sharing_PushListOnStack(LIST); void sharing_PushListReverseOnStack(LIST); void sharing_PushListReverseOnStackExcept(LIST, LIST); void sharing_PushListOnStackNoStamps(LIST); /**************************************************************/ /* Functions to access unshared data by the shared terms. */ /**************************************************************/ LIST sharing_GetDataList(TERM, SHARED_INDEX); void sharing_StartDataIterator(TERM, SHARED_INDEX); POINTER sharing_GetNextData(void); void sharing_StopDataIterator(void); LIST sharing_NAtomDataList(TERM); LIST sharing_GetAllSuperTerms(SHARED_INDEX); void sharing_ResetAllTermStamps(SHARED_INDEX); NAT sharing_GetNumberOfOccurances(TERM); NAT sharing_GetNumberOfInstances(TERM, SHARED_INDEX); /**************************************************************/ /* Output functions */ /**************************************************************/ void sharing_PrintVartable(SHARED_INDEX); void sharing_PrintConsttable(SHARED_INDEX); void sharing_PrintSharing(SHARED_INDEX); /**************************************************************/ /* Debugging Functions */ /**************************************************************/ void sharing_PrintStack(void); void sharing_PrintSharingConstterms1(SHARED_INDEX); void sharing_PrintSharingVarterms1(SHARED_INDEX); void sharing_PrintSameLevelTerms(TERM); #endif SPASS-3.7/SPASS/graph.c0000644000374100037200000002542511340510066011340 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * GRAPHS * */ /* * * */ /* * $Module: GRAPH * */ /* * * */ /* * Copyright (C) 1998, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: graph.c,v $ */ #include "graph.h" static LIST graph_ROOTS; /* used as stack by SCC algorithm */ static LIST graph_UNFINISHED; /* used as stack by SCC algorithm */ void graph_NodePrint(GRAPHNODE Node) /************************************************************** INPUT: A graph node. RETURNS: Nothing. EFFECT: Prints some node information to stdout. ***************************************************************/ { printf("(%d,%d,%d) ", graph_NodeNumber(Node), graph_NodeDfsNum(Node), graph_NodeCompNum(Node)); } GRAPH graph_Create(void) /************************************************************** INPUT: None. RETURNS: A new graph without nodes and edges. ***************************************************************/ { GRAPH result; result = memory_Malloc(sizeof(GRAPH_STRUCT)); result->size = 0; result->dfscount = 0; result->compcount = 0; result->nodes = list_Nil(); return result; } void graph_Delete(GRAPH Graph) /************************************************************** INPUT: A graph. RETURNS: Nothing. EFFECT: All memory required by the graph and its nodes is freed. ***************************************************************/ { for ( ; !list_Empty(Graph->nodes); Graph->nodes = list_Pop(Graph->nodes)) { list_Delete(graph_NodeNeighbors(list_Car(Graph->nodes))); memory_Free(list_Car(Graph->nodes), sizeof(GRAPHNODE_STRUCT)); } memory_Free(Graph, sizeof(GRAPH_STRUCT)); } GRAPHNODE graph_GetNode(GRAPH Graph, NAT Number) /************************************************************** INPUT: A graph and the ID of a node. RETURNS: The node with the requested number or NULL if such a node doesn't exist. ***************************************************************/ { LIST scan; for (scan = Graph->nodes; !list_Empty(scan); scan= list_Cdr(scan)) { if (graph_NodeNumber(list_Car(scan)) == Number) return list_Car(scan); } return NULL; } GRAPHNODE graph_AddNode(GRAPH Graph, NAT Number) /************************************************************** INPUT: A graph and the ID of a node. RETURNS: A node with the requested number. EFFECT: If the graph has no such node, a new node is created. ***************************************************************/ { GRAPHNODE result; result = graph_GetNode(Graph, Number); if (result == NULL) { result = memory_Malloc(sizeof(GRAPHNODE_STRUCT)); Graph->nodes = list_Cons(result, Graph->nodes); result->number = Number; result->dfs_num = -1; result->comp_num = -1; result->info = NULL; result->neighbors = list_Nil(); } return result; } void graph_AddEdge(GRAPHNODE From, GRAPHNODE To) /************************************************************** INPUT: Two graph nodes. RETURNS: Nothing. EFFECT: Adds a single (directed) edge (From, To). ***************************************************************/ { From->neighbors = list_Cons(To, From->neighbors); } void graph_DeleteEdge(GRAPHNODE From, GRAPHNODE To) /************************************************************** INPUT: Two graph nodes. RETURNS: Nothing. EFFECT: Removes ALL edges (From, To) from a graph. ***************************************************************/ { From->neighbors = list_PointerDeleteElement(From->neighbors, To); } void graph_DeleteDuplicateEdges(GRAPH Graph) /************************************************************** INPUT: A graph. RETURNS: Nothing. EFFECT: Removes duplicate edges between all nodes. ***************************************************************/ { LIST scan; for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { GRAPHNODE n = list_Car(scan); n->neighbors = list_PointerDeleteDuplicates(n->neighbors); } } void graph_SortNodes(GRAPH Graph, BOOL (*SortFunction)(GRAPHNODE, GRAPHNODE)) /************************************************************** INPUT: A graph and a sorting function for graph nodes. RETURNS: Nothing. EFFECT: The node list is sorted with respect to the sorting function. ***************************************************************/ { Graph->nodes = list_Sort(graph_Nodes(Graph), (BOOL (*) (POINTER, POINTER)) SortFunction); } static void graph_ReinitDFS(GRAPH Graph) /************************************************************** INPUT: A graph. RETURNS: Nothing. EFFECT: Prepares the graph and its nodes for a new DFS run. The DFS and COMP numbers are reset. ***************************************************************/ { LIST scan; Graph->dfscount = 0; Graph->compcount = 0; for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { graph_NodeSetDfsNum(list_Car(scan), -1); graph_NodeSetCompNum(list_Car(scan), -1); } } static void graph_InternSCC(GRAPH Graph, GRAPHNODE Node) /************************************************************** INPUT: A graph and a node of the graph. RETURNS: Nothing. EFFECT: This is an internal function used by graph_StronglyConnnectedComponents. It sets information in the graph structure which specifies the strongly connected components of the graph. ***************************************************************/ { GRAPHNODE n; LIST scan; NAT act_dfs; act_dfs = (Graph->dfscount)++; graph_NodeSetDfsNum(Node, act_dfs); graph_UNFINISHED = list_Push(Node, graph_UNFINISHED); graph_ROOTS = list_Push(Node, graph_ROOTS); /* putchar('\n'); list_Apply(graph_NodePrint, graph_UNFINISHED); putchar('\n'); list_Apply(graph_NodePrint, graph_ROOTS); fflush(stdout); DBG */ for (scan = graph_NodeNeighbors(Node); !list_Empty(scan); scan = list_Cdr(scan)) { n = list_Car(scan); if (!graph_NodeVisited(n)) { graph_InternSCC(Graph, n); /* Visit */ } else if (!graph_NodeCompleted(n)) { /* was visited but is not yet in a permanent component */ NAT dfs_num_of_n = graph_NodeDfsNum(n); while (!list_StackEmpty(graph_ROOTS) && graph_NodeDfsNum(list_Top(graph_ROOTS)) > dfs_num_of_n) graph_ROOTS = list_Pop(graph_ROOTS); /* putchar('\n'); list_Apply(symbol_Print, graph_UNFINISHED); putchar('\n'); list_Apply(symbol_Print, graph_ROOTS); fflush(stdout); DBG */ } } /* printf("\nDFS(%u) complete.", graph_NodeNumber(Node)); DBG */ if (Node == list_Top(graph_ROOTS)) { /* Node is root of a component, so make this component permanent */ while (!list_StackEmpty(graph_UNFINISHED) && graph_NodeDfsNum(list_Top(graph_UNFINISHED)) >= act_dfs) { n = list_Top(graph_UNFINISHED); graph_UNFINISHED = list_Pop(graph_UNFINISHED); graph_NodeSetCompNum(n, Graph->compcount); } Graph->compcount++; graph_ROOTS = list_Pop(graph_ROOTS); } /* putchar('\n'); list_Apply(graph_NodePrint, graph_UNFINISHED); putchar('\n'); list_Apply(graph_NodePrint, graph_ROOTS); fflush(stdout); DBG */ } NAT graph_StronglyConnectedComponents(GRAPH Graph) /************************************************************** INPUT: A graph. RETURNS: The number of strongly connected components in the graph. EFFECT: This function sets the component numbers of all nodes. Two nodes that belong to the same component will have the same component number. The algorithm is taken from the script "Datenstrukturen und Algorithmen" by Kurt Mehlhorn in winter semester 1997/98, pages 86-92. ***************************************************************/ { LIST scan; if (Graph->dfscount != 0) graph_ReinitDFS(Graph); /* Reinitializations for Depth First Search */ graph_ROOTS = list_Nil(); graph_UNFINISHED = list_Nil(); for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { if (!graph_NodeVisited(list_Car(scan))) graph_InternSCC(Graph, list_Car(scan)); } return Graph->compcount; } void graph_Print(GRAPH Graph) /************************************************************** INPUT: A graph. RETURNS: Nothing. EFFECT: The adjacency list representation of the graph is printed to stdout. ***************************************************************/ { LIST scan1, scan2; for (scan1 = graph_Nodes(Graph); !list_Empty(scan1); scan1 = list_Cdr(scan1)) { printf("\n%u -> ", graph_NodeNumber(list_Car(scan1))); for (scan2 = graph_NodeNeighbors(list_Car(scan1)); !list_Empty(scan2); scan2 = list_Cdr(scan2)) { printf("%u,", graph_NodeNumber(list_Car(scan2))); } } } SPASS-3.7/SPASS/clock.c0000644000374100037200000001525111340510065011325 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLOCK * */ /* * * */ /* * $Module: CLOCK * */ /* * * */ /* * Copyright (C) 1996, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: clock.c,v $ */ #include "clock.h" /**************************************************************/ /* Global Variables */ /**************************************************************/ float clock_Akku[clock_TYPESIZE]; CLOCK_TMS clock_Counters[clock_TYPESIZE]; /**************************************************************/ /* Functions */ /**************************************************************/ void clock_Init(void) /********************************************************* INPUT: None. EFFECT: Initializes the clock Module. RETURNS: None. MEMORY: None. **********************************************************/ { int i; for (i=0;i is initialized. RETURNS: None. MEMORY: None. **********************************************************/ { clock_Akku[ClockCounter] = 0; } void clock_StartCounter(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: The clock counter is started. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING gettimeofday(&(clock_Counters[ClockCounter]), NULL); #endif /* CLOCK_NO_TIMING */ } void clock_StopPassedTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Stores the number of seconds passed since given counter was started in the according accumulator. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; gettimeofday(&newtime, NULL); clock_Akku[ClockCounter] = clock_GetSeconds(ClockCounter); #endif } void clock_StopAddPassedTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Adds the number of seconds passed since given counter was started to the according accumulator. RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; gettimeofday(&newtime, NULL); clock_Akku[ClockCounter] += clock_GetSeconds(ClockCounter); #endif } float clock_GetAkku(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: None. RETURNS: The akkumulated number of seconds stored by the counter as a float. **********************************************************/ { return clock_Akku[ClockCounter]; } float clock_GetSeconds(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: Computes the number of seconds spent by the counter. RETURNS: The number of seconds spent by the counter as a float. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING CLOCK_TMS newtime; time_t seconds_passed; long microseconds_passed; gettimeofday(&newtime, NULL); seconds_passed = newtime.tv_sec - clock_Counters[ClockCounter].tv_sec; microseconds_passed = newtime.tv_usec - clock_Counters[ClockCounter].tv_usec; return ((float) seconds_passed + (microseconds_passed /(float)1000000)); #else /* CLOCK_NO_TIMING */ return 0; #endif /* ! CLOCK_NO_TIMING */ } void clock_PrintTime(CLOCK_CLOCKS ClockCounter) /********************************************************* INPUT: A clock counter. EFFECT: The time is printed in format hh:mm:ss.dd to stdout RETURNS: None. MEMORY: None. **********************************************************/ { #ifndef CLOCK_NO_TIMING NAT hours, minutes; float seconds; seconds = clock_Akku[ClockCounter]; hours = (NAT)seconds/3600; seconds -= hours*3600; minutes = (NAT)seconds/60; seconds -= (minutes*60); if (seconds >= 10.0) printf("%u:%02u:%2.2f",hours,minutes,seconds); else printf("%u:%02u:0%2.2f",hours,minutes,seconds); #else fputs(" No Timing on this machine. ",stdout); #endif } SPASS-3.7/SPASS/iascanner.c0000644000374100037200000013721011340746177012214 00000000000000#line 2 "iascanner.c" #line 4 "iascanner.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 33 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE ia_restart(ia_in ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int ia_leng; extern FILE *ia_in, *ia_out; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up ia_text. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up ia_text again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef unsigned int yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via ia_restart()), so that the user can continue scanning by * just pointing ia_in at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when ia_text is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int ia_leng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow ia_wrap()'s to do buffer switches * instead of setting up a fresh ia_in. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void ia_restart (FILE *input_file ); void ia__switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE ia__create_buffer (FILE *file,int size ); void ia__delete_buffer (YY_BUFFER_STATE b ); void ia__flush_buffer (YY_BUFFER_STATE b ); void ia_push_buffer_state (YY_BUFFER_STATE new_buffer ); void ia_pop_buffer_state (void ); static void ia_ensure_buffer_stack (void ); static void ia__load_buffer_state (void ); static void ia__init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER ia__flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE ia__scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE ia__scan_string (yyconst char *yy_str ); YY_BUFFER_STATE ia__scan_bytes (yyconst char *bytes,int len ); void *ia_alloc (yy_size_t ); void *ia_realloc (void *,yy_size_t ); void ia_free (void * ); #define yy_new_buffer ia__create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ ia_ensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ ia__create_buffer(ia_in,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ ia_ensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ ia__create_buffer(ia_in,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define ia_wrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *ia_in = (FILE *) 0, *ia_out = (FILE *) 0; typedef int yy_state_type; extern int ia_lineno; int ia_lineno = 1; extern char *ia_text; #define yytext_ptr ia_text static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up ia_text. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ ia_leng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 19 #define YY_END_OF_BUFFER 20 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[61] = { 0, 0, 0, 20, 18, 15, 16, 17, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 13, 14, 14, 14, 14, 14, 14, 14, 14, 10, 14, 14, 1, 14, 14, 14, 14, 14, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 2, 3, 14, 5, 14, 14, 12, 4, 6, 14, 7, 8, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, 4, 4, 4, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 1, 4, 1, 6, 1, 7, 6, 6, 8, 9, 10, 6, 6, 11, 6, 6, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 6, 23, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int16_t yy_base[62] = { 0, 0, 0, 86, 87, 83, 87, 87, 79, 0, 69, 7, 18, 69, 66, 62, 61, 60, 75, 71, 0, 67, 53, 62, 60, 53, 54, 49, 0, 53, 46, 0, 20, 47, 46, 57, 51, 0, 40, 52, 48, 37, 38, 48, 24, 24, 25, 0, 0, 0, 13, 0, 17, 19, 0, 0, 0, 18, 0, 0, 87, 33 } ; static yyconst flex_int16_t yy_def[62] = { 0, 60, 1, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 0, 60 } ; static yyconst flex_int16_t yy_nxt[111] = { 0, 4, 5, 6, 7, 8, 9, 10, 9, 11, 12, 13, 9, 9, 14, 15, 16, 9, 9, 9, 17, 9, 9, 9, 22, 24, 58, 40, 57, 56, 23, 41, 55, 25, 54, 53, 52, 59, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 39, 38, 37, 36, 35, 34, 33, 32, 31, 19, 18, 30, 29, 28, 27, 26, 21, 19, 18, 60, 3, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } ; static yyconst flex_int16_t yy_chk[111] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 12, 57, 32, 53, 52, 11, 32, 50, 12, 46, 45, 44, 57, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 43, 42, 41, 40, 39, 38, 36, 35, 34, 33, 30, 29, 27, 26, 25, 24, 23, 22, 21, 19, 18, 17, 16, 15, 14, 13, 10, 8, 5, 3, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int ia__flex_debug; int ia__flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *ia_text; #line 1 "iascanner.l" /**************************************************************/ /* ********************************************************** */ /* * * */ /* * SCANNER FOR SPASS INTERACTIVE MODULE * */ /* * * */ /* * $Module: KIV * */ /* * * */ /* * Copyright (C) 1997, 1998, 1999, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: iascanner.l,v $ */ #line 42 "iascanner.l" #include /* for isprint */ #include #include "misc.h" #include "memory.h" #include "symbol.h" #include "term.h" #include "ia.h" #include "iaparser.h" extern NAT dfg_LINENUMBER; /* defined in dfgparser.y */ /* Force the scanner to read the input character by character */ #line 542 "iascanner.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int ia_wrap (void ); #else extern int ia_wrap (void ); #endif #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( ia_text, ia_leng, 1, ia_out ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( ia_in )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( ia_in ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, ia_in))==0 && ferror(ia_in)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(ia_in); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int ia_lex (void); #define YY_DECL int ia_lex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after ia_text and ia_leng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 61 "iascanner.l" #line 696 "iascanner.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! ia_in ) ia_in = stdin; if ( ! ia_out ) ia_out = stdout; if ( ! YY_CURRENT_BUFFER ) { ia_ensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = ia__create_buffer(ia_in,YY_BUF_SIZE ); } ia__load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of ia_text. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 87 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 63 "iascanner.l" return IA_AND; YY_BREAK case 2: YY_RULE_SETUP #line 64 "iascanner.l" return IA_EQUAL; YY_BREAK case 3: YY_RULE_SETUP #line 65 "iascanner.l" return IA_EQUIV; YY_BREAK case 4: YY_RULE_SETUP #line 66 "iascanner.l" return IA_EXISTS; YY_BREAK case 5: YY_RULE_SETUP #line 67 "iascanner.l" return IA_FALSE; YY_BREAK case 6: YY_RULE_SETUP #line 68 "iascanner.l" return IA_FORALL; YY_BREAK case 7: YY_RULE_SETUP #line 69 "iascanner.l" return IA_IMPLIED; YY_BREAK case 8: YY_RULE_SETUP #line 70 "iascanner.l" return IA_IMPLIES; YY_BREAK case 9: YY_RULE_SETUP #line 71 "iascanner.l" return IA_NOT; YY_BREAK case 10: YY_RULE_SETUP #line 72 "iascanner.l" return IA_OR; YY_BREAK case 11: YY_RULE_SETUP #line 73 "iascanner.l" return IA_TRUE; YY_BREAK case 12: YY_RULE_SETUP #line 74 "iascanner.l" return IA_PROVE; YY_BREAK case 13: YY_RULE_SETUP #line 75 "iascanner.l" { unsigned long n; errno = 0; n = strtoul(ia_text, NULL, 10); if (errno != 0 || n > INT_MAX) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Number too big in line %d.\n", dfg_LINENUMBER); misc_FinishUserErrorReport(); } ia_lval.number = (int) n; return IA_NUM; } YY_BREAK case 14: YY_RULE_SETUP #line 87 "iascanner.l" { ia_lval.string = (char*) memory_Malloc(ia_leng+1); strcpy(ia_lval.string, ia_text); return IA_ID; } YY_BREAK case 15: YY_RULE_SETUP #line 91 "iascanner.l" /* ignore */ YY_BREAK case 16: /* rule 16 can match eol */ YY_RULE_SETUP #line 92 "iascanner.l" dfg_LINENUMBER++; YY_BREAK case 17: YY_RULE_SETUP #line 93 "iascanner.l" return ia_text[0]; YY_BREAK case 18: YY_RULE_SETUP #line 94 "iascanner.l" { misc_StartUserErrorReport(); misc_UserErrorReport("\n Illegal character '"); if (isprint((int)ia_text[0])) misc_UserErrorReport("%c",ia_text[0]); else misc_UserErrorReport("\\x%x", (unsigned int) ia_text[0]); misc_UserErrorReport("' in line %d.\n", dfg_LINENUMBER); misc_FinishUserErrorReport(); } YY_BREAK case 19: YY_RULE_SETUP #line 104 "iascanner.l" ECHO; YY_BREAK #line 895 "iascanner.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed ia_in at a new source and called * ia_lex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = ia_in; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( ia_wrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * ia_text, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of ia_lex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ ia_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; ia_restart(ia_in ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 60); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ ia_restart(ia_in ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( ia_wrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve ia_text */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void ia_restart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ ia_ensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = ia__create_buffer(ia_in,YY_BUF_SIZE ); } ia__init_buffer(YY_CURRENT_BUFFER,input_file ); ia__load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void ia__switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * ia_pop_buffer_state(); * ia_push_buffer_state(new_buffer); */ ia_ensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; ia__load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (ia_wrap()) processing, but the only time this flag * is looked at is after ia_wrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void ia__load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; ia_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE ia__create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) ia_alloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in ia__create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) ia_alloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in ia__create_buffer()" ); b->yy_is_our_buffer = 1; ia__init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with ia__create_buffer() * */ void ia__delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) ia_free((void *) b->yy_ch_buf ); ia_free((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a ia_restart() or at EOF. */ static void ia__init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; ia__flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then ia__init_buffer was _probably_ * called from ia_restart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = 1; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void ia__flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) ia__load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void ia_push_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; ia_ensure_buffer_stack(); /* This block is copied from ia__switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from ia__switch_to_buffer. */ ia__load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void ia_pop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; ia__delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { ia__load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void ia_ensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)ia_alloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)ia_realloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE ia__scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) ia_alloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in ia__scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; ia__switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to ia_lex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * ia__scan_bytes() instead. */ YY_BUFFER_STATE ia__scan_string (yyconst char * yystr ) { return ia__scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to ia_lex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE ia__scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) ia_alloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in ia__scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = ia__scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in ia__scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up ia_text. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ ia_text[ia_leng] = (yy_hold_char); \ (yy_c_buf_p) = ia_text + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ ia_leng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int ia_get_lineno (void) { return ia_lineno; } /** Get the input stream. * */ FILE *ia_get_in (void) { return ia_in; } /** Get the output stream. * */ FILE *ia_get_out (void) { return ia_out; } /** Get the length of the current token. * */ int ia_get_leng (void) { return ia_leng; } /** Get the current token. * */ char *ia_get_text (void) { return ia_text; } /** Set the current line number. * @param line_number * */ void ia_set_lineno (int line_number ) { ia_lineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see ia__switch_to_buffer */ void ia_set_in (FILE * in_str ) { ia_in = in_str ; } void ia_set_out (FILE * out_str ) { ia_out = out_str ; } int ia_get_debug (void) { return ia__flex_debug; } void ia_set_debug (int bdebug ) { ia__flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from ia_lex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT ia_in = stdin; ia_out = stdout; #else ia_in = (FILE *) 0; ia_out = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * ia_lex_init() */ return 0; } /* ia_lex_destroy is for both reentrant and non-reentrant scanners. */ int ia_lex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ ia__delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; ia_pop_buffer_state(); } /* Destroy the stack itself. */ ia_free((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * ia_lex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *ia_alloc (yy_size_t size ) { return (void *) malloc( size ); } void *ia_realloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void ia_free (void * ptr ) { free( (char *) ptr ); /* see ia_realloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 104 "iascanner.l" SPASS-3.7/SPASS/iaparser.c0000644000374100037200000016757011340746177012073 00000000000000/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse ia_parse #define yylex ia_lex #define yyerror ia_error #define yylval ia_lval #define yychar ia_char #define yydebug ia_debug #define yynerrs ia_nerrs /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { IA_AND = 258, IA_EQUAL = 259, IA_EQUIV = 260, IA_EXISTS = 261, IA_FALSE = 262, IA_FORALL = 263, IA_IMPLIED = 264, IA_IMPLIES = 265, IA_NOT = 266, IA_OR = 267, IA_PROVE = 268, IA_TRUE = 269, IA_NUM = 270, IA_ID = 271 }; #endif /* Tokens. */ #define IA_AND 258 #define IA_EQUAL 259 #define IA_EQUIV 260 #define IA_EXISTS 261 #define IA_FALSE 262 #define IA_FORALL 263 #define IA_IMPLIED 264 #define IA_IMPLIES 265 #define IA_NOT 266 #define IA_OR 267 #define IA_PROVE 268 #define IA_TRUE 269 #define IA_NUM 270 #define IA_ID 271 /* Copy the first part of user declarations. */ #line 41 "iaparser.y" #include "flags.h" #include "ia.h" #include "symbol.h" #include "term.h" #include "foldfg.h" #include "clause.h" extern NAT dfg_LINENUMBER; /* Defined in dfgparser.y */ LIST ia_PROOFREQUEST; /* A pair! */ FLAGSTORE ia_FLAGS; void yyerror(const char*); int yylex(void); /* Defined in iascanner.l */ static SYMBOL ia_Symbol(char*, NAT); static TERM ia_CreateQuantifier(SYMBOL, LIST, TERM); static __inline__ void ia_StringFree(char* String) { memory_Free(String, sizeof(char)*(strlen(String)+1)); } static __inline__ TERM ia_TermCreate(char* Name, LIST Arguments) /* Look up the symbol, check its arity and create the term */ { return term_Create(ia_Symbol(Name,list_Length(Arguments)), Arguments); } /**************************************************************/ /* Functions to check the arity of symbols */ /**************************************************************/ static void ia_SymCheck(SYMBOL, NAT); /**************************************************************/ /* Functions that handle variable names */ /**************************************************************/ /* List of quantified variables in the current input formula. */ /* This list is used to find symbols that by mistake weren't */ /* declared in the symbol declaration section */ /* --> free variables */ /* This is a list of lists, since each time a quantifier is */ /* reached, a new list is added to the global list. */ static LIST ia_VARLIST; static BOOL ia_VARDECL; static void ia_VarStart(void); static void ia_VarStop(void); static void ia_VarBacktrack(void); static void ia_VarCheck(void); static SYMBOL ia_VarLookup(char*); #define YY_INPUT(buf,result,max_size) \ { \ int c = getc(ia_in); \ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \ } #define YYERROR_VERBOSE /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 106 "iaparser.y" { int number; char* string; SYMBOL symbol; TERM term; LIST list; } /* Line 187 of yacc.c. */ #line 209 "iaparser.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 216 of yacc.c. */ #line 222 "iaparser.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 4 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 83 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 23 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 16 /* YYNRULES -- Number of rules. */ #define YYNRULES 36 /* YYNRULES -- Number of states. */ #define YYNSTATES 77 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 271 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 19, 2, 2, 18, 2, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 14, 16, 20, 22, 24, 26, 31, 38, 43, 48, 49, 50, 61, 62, 63, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 100, 102, 107, 110, 114, 116 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 24, 0, -1, -1, 13, 17, 26, 18, 37, 18, 15, 19, 20, -1, 26, -1, 25, 18, 26, -1, 34, -1, 14, -1, 7, -1, 11, 17, 26, 19, -1, 31, 17, 26, 18, 26, 19, -1, 32, 17, 25, 19, -1, 34, 17, 25, 19, -1, -1, -1, 33, 17, 21, 27, 35, 28, 22, 18, 26, 19, -1, -1, -1, 34, 17, 21, 29, 35, 30, 22, 18, 26, 19, -1, 4, -1, 5, -1, 9, -1, 10, -1, 3, -1, 12, -1, 6, -1, 8, -1, 16, -1, 15, -1, 36, -1, 35, 18, 36, -1, 34, -1, 34, 17, 34, 19, -1, 21, 22, -1, 21, 38, 22, -1, 34, -1, 38, 18, 34, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 129, 129, 130, 142, 143, 146, 147, 148, 149, 151, 153, 155, 157, 158, 157, 163, 164, 163, 172, 173, 174, 175, 178, 179, 182, 183, 186, 187, 190, 191, 194, 204, 225, 226, 229, 230 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "IA_AND", "IA_EQUAL", "IA_EQUIV", "IA_EXISTS", "IA_FALSE", "IA_FORALL", "IA_IMPLIED", "IA_IMPLIES", "IA_NOT", "IA_OR", "IA_PROVE", "IA_TRUE", "IA_NUM", "IA_ID", "'('", "','", "')'", "'.'", "'['", "']'", "$accept", "proofrequest", "termlist", "term", "@1", "@2", "@3", "@4", "binsymbol", "nsymbol", "quantsymbol", "id", "qtermlist", "qterm", "labellistopt", "labellist", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 40, 44, 41, 46, 91, 93 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 23, 24, 24, 25, 25, 26, 26, 26, 26, 26, 26, 26, 27, 28, 26, 29, 30, 26, 31, 31, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 9, 1, 3, 1, 1, 1, 4, 6, 4, 4, 0, 0, 10, 0, 0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 2, 3, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 0, 0, 0, 1, 23, 19, 20, 25, 8, 26, 21, 22, 0, 24, 7, 28, 27, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 16, 0, 9, 33, 35, 0, 0, 0, 0, 11, 0, 0, 12, 0, 34, 0, 0, 5, 31, 14, 29, 17, 36, 0, 10, 0, 0, 0, 0, 3, 0, 30, 0, 0, 32, 0, 0, 0, 0, 15, 18 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 2, 33, 34, 46, 63, 47, 64, 19, 20, 21, 22, 55, 56, 31, 41 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -29 static const yytype_int8 yypact[] = { -12, 12, 35, 0, -29, -29, -29, -29, -29, -29, -29, -29, -29, 19, -29, -29, -29, -29, 20, 22, 40, 41, 42, 0, 31, 0, 0, 43, 39, 18, 8, 38, 44, 7, -29, -29, -29, 9, -29, -29, -29, -5, 46, 0, 0, -29, 16, 16, -29, 16, -29, 47, 48, -29, 53, 45, -29, 45, -29, 51, -29, 16, 16, 50, 52, -29, 54, -29, 57, 58, -29, 0, 0, 59, 60, -29, -29 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -29, -29, 37, -3, -29, -29, -29, -29, -29, -29, -29, -28, 30, 21, -29, -29 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 18, 1, 40, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 49, 15, 16, 17, 50, 54, 54, 29, 58, 32, 16, 17, 44, 45, 44, 48, 3, 39, 16, 17, 66, 54, 4, 23, 38, 24, 25, 52, 53, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 30, 15, 16, 17, 42, 26, 27, 28, 36, 51, 43, 62, 35, 37, 59, 60, 73, 74, 61, 65, 68, 70, 69, 71, 72, 57, 75, 76, 0, 0, 0, 67 }; static const yytype_int8 yycheck[] = { 3, 13, 30, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 18, 14, 15, 16, 22, 46, 47, 23, 49, 25, 15, 16, 18, 19, 18, 19, 17, 22, 15, 16, 61, 62, 0, 17, 19, 18, 17, 43, 44, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 21, 14, 15, 16, 18, 17, 17, 17, 21, 15, 18, 18, 21, 28, 19, 19, 71, 72, 17, 20, 22, 19, 22, 18, 18, 47, 19, 19, -1, -1, -1, 62 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 13, 24, 17, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 26, 31, 32, 33, 34, 17, 18, 17, 17, 17, 17, 26, 21, 37, 26, 25, 26, 21, 21, 25, 19, 22, 34, 38, 18, 18, 18, 19, 27, 29, 19, 18, 22, 15, 26, 26, 34, 35, 36, 35, 34, 19, 19, 17, 18, 28, 30, 20, 34, 36, 22, 22, 19, 18, 18, 26, 26, 19, 19 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 129 "iaparser.y" { YYABORT; ;} break; case 3: #line 130 "iaparser.y" { ia_VarCheck(); ia_PROOFREQUEST = list_PairCreate((yyvsp[(3) - (9)].term),(yyvsp[(5) - (9)].list)); flag_SetFlagIntValue(ia_FLAGS,flag_TIMELIMIT,(yyvsp[(7) - (9)].number)); YYACCEPT; ;} break; case 4: #line 142 "iaparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].term)); ;} break; case 5: #line 143 "iaparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 6: #line 146 "iaparser.y" { (yyval.term) = ia_TermCreate((yyvsp[(1) - (1)].string), list_Nil()); ;} break; case 7: #line 147 "iaparser.y" { (yyval.term) = term_Create(fol_True(),list_Nil()); ;} break; case 8: #line 148 "iaparser.y" { (yyval.term) = term_Create(fol_False(),list_Nil()); ;} break; case 9: #line 150 "iaparser.y" { (yyval.term) = term_Create(fol_Not(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 10: #line 152 "iaparser.y" { (yyval.term) = term_Create((yyvsp[(1) - (6)].symbol), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 11: #line 154 "iaparser.y" { (yyval.term) = term_Create((yyvsp[(1) - (4)].symbol), (yyvsp[(3) - (4)].list)); ;} break; case 12: #line 156 "iaparser.y" { (yyval.term) = ia_TermCreate((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].list)); ;} break; case 13: #line 157 "iaparser.y" { ia_VarStart(); ;} break; case 14: #line 158 "iaparser.y" { ia_VarStop(); ;} break; case 15: #line 160 "iaparser.y" { ia_VarBacktrack(); (yyval.term) = ia_CreateQuantifier((yyvsp[(1) - (10)].symbol),(yyvsp[(5) - (10)].list),(yyvsp[(9) - (10)].term)); ;} break; case 16: #line 163 "iaparser.y" { ia_VarStart(); ;} break; case 17: #line 164 "iaparser.y" { ia_VarStop(); ;} break; case 18: #line 166 "iaparser.y" { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: SPASS can't handle the quantifier %s.\n", dfg_LINENUMBER, (yyvsp[(1) - (10)].string)); misc_FinishUserErrorReport(); ;} break; case 19: #line 172 "iaparser.y" { (yyval.symbol) = fol_Equality(); ;} break; case 20: #line 173 "iaparser.y" { (yyval.symbol) = fol_Equiv(); ;} break; case 21: #line 174 "iaparser.y" { (yyval.symbol) = fol_Implied(); ;} break; case 22: #line 175 "iaparser.y" { (yyval.symbol) = fol_Implies(); ;} break; case 23: #line 178 "iaparser.y" { (yyval.symbol) = fol_And(); ;} break; case 24: #line 179 "iaparser.y" { (yyval.symbol) = fol_Or(); ;} break; case 25: #line 182 "iaparser.y" { (yyval.symbol) = fol_Exist(); ;} break; case 26: #line 183 "iaparser.y" { (yyval.symbol) = fol_All(); ;} break; case 27: #line 186 "iaparser.y" { (yyval.string) = (yyvsp[(1) - (1)].string); ;} break; case 28: #line 187 "iaparser.y" { (yyval.string) = string_IntToString((yyvsp[(1) - (1)].number)); ;} break; case 29: #line 190 "iaparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].term)); ;} break; case 30: #line 191 "iaparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 31: #line 194 "iaparser.y" { SYMBOL s = ia_Symbol((yyvsp[(1) - (1)].string),0); if (!symbol_IsVariable(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, symbol_Name(s)); misc_UserErrorReport(" is not a variable.\n"); misc_FinishUserErrorReport(); } (yyval.term) = term_Create(s, list_Nil()); ;} break; case 32: #line 204 "iaparser.y" { SYMBOL p, v; p = ia_Symbol((yyvsp[(1) - (4)].string), 1); if (!symbol_IsPredicate(p)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, symbol_Name(p)); misc_UserErrorReport(" is not a predicate.\n"); misc_FinishUserErrorReport(); } v = ia_Symbol((yyvsp[(3) - (4)].string), 0); if (!symbol_IsVariable(v)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, symbol_Name(v)); misc_UserErrorReport(" is not a variable.\n"); misc_FinishUserErrorReport(); } (yyval.term) = term_Create(p, list_List(term_Create(v,list_Nil()))); ;} break; case 33: #line 225 "iaparser.y" { (yyval.list) = list_Nil(); ;} break; case 34: #line 226 "iaparser.y" { (yyval.list) = (yyvsp[(2) - (3)].list); ;} break; case 35: #line 229 "iaparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].string)); ;} break; case 36: #line 230 "iaparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].string))); ;} break; /* Line 1267 of yacc.c. */ #line 1683 "iaparser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } #line 233 "iaparser.y" void yyerror(const char *s) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %i: %s\n", dfg_LINENUMBER, s); misc_FinishUserErrorReport(); } LIST ia_GetNextRequest(FILE* Input, FLAGSTORE Flags) /************************************************************** INPUT: An input file containing one proof request from KIV. RETURNS: The proof request as pair (formula, labellist), list_Nil(), if EOF was reached. EFFECT: Reads ONE proof request from the file. may also be a UNIX pipe. ***************************************************************/ { extern FILE* ia_in; /* defined in kivscanner */ ia_in = Input; ia_PROOFREQUEST = list_Nil(); ia_FLAGS = Flags; ia_parse(); return ia_PROOFREQUEST; } /**************************************************************/ /* Static Functions */ /**************************************************************/ static SYMBOL ia_Symbol(char* Name, NAT Arity) /************************************************************** INPUT: The name of a symbol and the actual arity of the symbol. RETURNS: The corresponding SYMBOL. EFFECT: This function checks if the was declared as symbol or variable. If not, an error message is printed to stderr. The is deleted. ***************************************************************/ { SYMBOL symbol; symbol = symbol_Lookup(Name); if (symbol != 0) { ia_StringFree(Name); ia_SymCheck(symbol, Arity); /* Check the arity */ } else { /* Variable */ if (Arity > 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: Undefined symbol %s.\n",dfg_LINENUMBER,Name); misc_FinishUserErrorReport(); } symbol = ia_VarLookup(Name); } return symbol; } static TERM ia_CreateQuantifier(SYMBOL Symbol, LIST VarTermList, TERM Term) /************************************************************** INPUT: A quantifier symbol, a list possibly containing sorts, and a term. RETURNS: The created quantifier term.. ***************************************************************/ { LIST varlist, sortlist, scan; TERM helpterm; /* First collect the variable symbols in varlist and the sorts in sortlist */ varlist = sortlist = list_Nil(); for ( ; !list_Empty(VarTermList); VarTermList = list_Pop(VarTermList)) { helpterm = list_Car(VarTermList); if (term_IsVariable(helpterm)) { varlist = list_Nconc(varlist, list_List((POINTER)term_TopSymbol(helpterm))); term_Delete(helpterm); } else { SYMBOL var = term_TopSymbol(term_FirstArgument(helpterm)); varlist = list_Nconc(varlist, list_List((POINTER)var)); sortlist = list_Nconc(sortlist, list_List(helpterm)); } } varlist = list_PointerDeleteDuplicates(varlist); /* Now create terms from the variables */ for (scan = varlist; !list_Empty(scan); scan = list_Cdr(scan)) list_Rplaca(scan, term_Create((SYMBOL)list_Car(scan), list_Nil())); if (!list_Empty(sortlist)) { if (symbol_Equal(fol_All(), Symbol)) { /* The conjunction of all sortterms implies the Term */ if (symbol_Equal(fol_Or(), term_TopSymbol(Term))) { /* Special treatment if is a term with "or" like */ /* in clauses: add all sort terms negated to the args */ /* of the "or" */ for (scan = sortlist; !list_Empty(scan); scan = list_Cdr(scan)) /* Negate the sort terms */ list_Rplaca(scan, term_Create(fol_Not(), list_List(list_Car(scan)))); sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); term_RplacArgumentList(Term, sortlist); } else { /* No "or" term, so build the implication term */ if (list_Empty(list_Cdr(sortlist))) { /* Only one sort term */ list_Rplacd(sortlist, list_List(Term)); Term = term_Create(fol_Implies(), sortlist); } else { /* More than one sort term */ helpterm = term_Create(fol_And(), sortlist); Term = term_Create(fol_Implies(), list_Cons(helpterm, list_List(Term))); } } } else if (symbol_Equal(fol_Exist(), Symbol)) { /* Quantify the conjunction of all sort terms and */ if (symbol_Equal(fol_And(), term_TopSymbol(Term))) { /* Special treatment if has an "and" as top symbol: */ /* just add the sort terms to the args of the "and". */ sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); term_RplacArgumentList(Term, sortlist); } else { sortlist = list_Nconc(sortlist, list_List(Term)); Term = term_Create(fol_And(), sortlist); } } } helpterm = fol_CreateQuantifier(Symbol, varlist, list_List(Term)); return helpterm; } /**************************************************************/ /* Functions for the Symbol Table */ /**************************************************************/ static void ia_SymCheck(SYMBOL Symbol, NAT Arity) /************************************************************** INPUT: A symbol and the current arity of this symbol. RETURNS: Nothing. EFFECT: This function compares the previous arity of 'Symbol' with the actual 'Arity'. If these values differ a warning is printed to stderr and the program exits. ***************************************************************/ { /* Check if the specified arity corresponds with the actual arity */ if (symbol_Arity(Symbol) != symbol_ArbitraryArity() && symbol_Arity(Symbol) != Arity) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %u: Symbol %s", dfg_LINENUMBER, symbol_Name(Symbol)); misc_UserErrorReport(" was declared with arity %u.\n", symbol_Arity(Symbol)); misc_FinishUserErrorReport(); } } /**************************************************************/ /* Functions for the Variable Table */ /**************************************************************/ typedef struct { char* name; SYMBOL symbol; } IA_VARENTRY, *IA_VAR; static __inline__ char* ia_VarName(IA_VAR Entry) { return Entry->name; } static __inline__ SYMBOL ia_VarSymbol(IA_VAR Entry) { return Entry->symbol; } static __inline__ IA_VAR ia_VarCreate(void) { return (IA_VAR) memory_Malloc(sizeof(IA_VARENTRY)); } static void ia_VarFree(IA_VAR Entry) { ia_StringFree(Entry->name); memory_Free(Entry, sizeof(IA_VARENTRY)); } static void ia_VarStart(void) { ia_VARLIST = list_Push(list_Nil(), ia_VARLIST); ia_VARDECL = TRUE; } static void ia_VarStop(void) { ia_VARDECL = FALSE; } static void ia_VarBacktrack(void) { list_DeleteWithElement(list_Top(ia_VARLIST), (void (*)(POINTER)) ia_VarFree); ia_VARLIST = list_Pop(ia_VARLIST); } static void ia_VarCheck(void) /* Should be called after a complete clause or formula was parsed */ { if (!list_Empty(ia_VARLIST)) { misc_StartErrorReport(); misc_ErrorReport("\n In ia_VarCheck: List of variables should be empty!\n"); misc_FinishErrorReport(); } symbol_ResetStandardVarCounter(); } static SYMBOL ia_VarLookup(char* Name) /************************************************************** INPUT: A variable name. RETURNS: The corresponding variable symbol. EFFECT: If the variable name was quantified before, the corresponding symbol is returned and the is freed. If the variable name was not quantified, and is TRUE, a new variable is created, else an error message is printed and the program exits. ***************************************************************/ { LIST scan, scan2; SYMBOL symbol; symbol = symbol_Null(); scan = ia_VARLIST; scan2 = list_Nil(); while (!list_Empty(scan) && list_Empty(scan2)) { scan2 = list_Car(scan); while (!list_Empty(scan2) && !string_Equal(ia_VarName(list_Car(scan2)), Name)) scan2 = list_Cdr(scan2); scan = list_Cdr(scan); } if (!list_Empty(scan2)) { /* Found variable */ ia_StringFree(Name); symbol = ia_VarSymbol(list_Car(scan2)); } else { /* Variable not found */ if (ia_VARDECL) { IA_VAR newEntry = ia_VarCreate(); newEntry->name = Name; newEntry->symbol = symbol_CreateStandardVariable(); /* Add to the first list in ia_VARLIST */ list_Rplaca(ia_VARLIST, list_Cons(newEntry,list_Car(ia_VARLIST))); symbol = ia_VarSymbol(newEntry); } else { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %u: Free Variable %s.\n", dfg_LINENUMBER, Name); misc_FinishUserErrorReport(); } } return symbol; } SPASS-3.7/SPASS/rpos.c0000644000374100037200000006372011340510067011223 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * RECURSIVE PATH ORDERING WITH STATUS * */ /* * * */ /* * $Module: RPOS * */ /* * * */ /* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: rpos.c,v $ */ #include "rpos.h" BOOL rpos_ContEqual(CONTEXT, CONTEXT, TERM, CONTEXT, CONTEXT, TERM); ord_RESULT rpos_ContGreaterEqual(CONTEXT, CONTEXT, TERM, CONTEXT, CONTEXT, TERM, BOOL); /**************************************************************/ /* Comparisons */ /**************************************************************/ BOOL rpos_Greater(TERM T1, TERM T2, BOOL VarIsConst) { return ord_IsGreaterThan(rpos_GreaterEqual(T1, T2, VarIsConst)); } BOOL rpos_ContGreaterAux(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2, BOOL VarIsConst) { return ord_IsGreaterThan(rpos_ContGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, VarIsConst)); } BOOL rpos_ContGreater(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2) { return ord_IsGreaterThan(rpos_ContGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, FALSE)); } BOOL rpos_ContGreaterSkolemSubst(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2) { return ord_IsGreaterThan(rpos_ContGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, TRUE)); } /**************************************************************/ /* Top Down Version */ /**************************************************************/ static LIST rpos_MultisetDifference(TERM T1, TERM T2) /************************************************************** INPUT: Two terms. RETURNS: The multiset difference between the arguments of both terms with respect to rpos_Equal. ***************************************************************/ { LIST result; result = list_Copy(term_ArgumentList(T1)); result = list_NMultisetDifference(result, term_ArgumentList(T2), (BOOL (*)(POINTER,POINTER)) rpos_Equal); return result; } static ord_RESULT rpos_MulGreaterEqual(TERM T1, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two terms with equal top symbols and multiset status. RETURNS: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal and ord_UNCOMPARABLE otherwise. CAUTION: If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { LIST l1, l2; l1 = rpos_MultisetDifference(T1, T2); if (list_Empty(l1)) /* If |M| = |N| and M-N = {} then N-M = {} */ return ord_Equal(); /* Terms are equal */ else { LIST scan; BOOL greater; l2 = rpos_MultisetDifference(T2, T1); for (greater = TRUE; !list_Empty(l2) && greater; l2 = list_Pop(l2)) { for (scan = l1, greater = FALSE; !list_Empty(scan) && !greater; scan = list_Cdr(scan)) greater = rpos_Greater(list_Car(scan), list_Car(l2), VarIsConst); } list_Delete(l1); /* l2 was freed in the outer for loop */ if (greater) return ord_GreaterThan(); else return ord_Uncomparable(); } } static ord_RESULT rpos_LexGreaterEqual(TERM T1, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two terms with equal top symbols and lexicographic status. RETURNS: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal and ord_UNCOMPARABLE otherwise. CAUTION: If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { ord_RESULT result; LIST l1, l2, scan1, scan2; if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { l1 = list_Reverse(term_ArgumentList(T1)); /* Create new lists */ l2 = list_Reverse(term_ArgumentList(T2)); } else { l1 = term_ArgumentList(T1); l2 = term_ArgumentList(T2); } /* First ignore equal arguments */ result = ord_Equal(); for (scan1 = l1, scan2 = l2; !list_Empty(scan1); scan1 = list_Cdr(scan1), scan2 = list_Cdr(scan2)) { result = rpos_GreaterEqual(list_Car(scan1), list_Car(scan2), VarIsConst); if (!ord_IsEqual(result)) break; } if (ord_IsEqual(result)) /* All arguments are equal, so the terms */ /* empty */; /* are equal with respect to RPOS */ else if (ord_IsGreaterThan(result)) { /* Check if T1 > each remaining argument of T2 */ for (scan2 = list_Cdr(scan2); !list_Empty(scan2) && rpos_Greater(T1, list_Car(scan2), VarIsConst); scan2 = list_Cdr(scan2)); /* Empty body */ if (list_Empty(scan2)) result = ord_GreaterThan(); else result = ord_Uncomparable(); } else { /* Argument of T1 was not >= argument of T2. */ /* Try to find an argument of T1 that is >= T2 */ for (scan1 = list_Cdr(scan1), result = ord_Uncomparable(); !list_Empty(scan1) && !ord_IsGreaterThan(result); scan1 = list_Cdr(scan1)) { if (!ord_IsUncomparable(rpos_GreaterEqual(list_Car(scan1), T2, VarIsConst))) result = ord_GreaterThan(); } } if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { list_Delete(l1); /* Delete the lists create above */ list_Delete(l2); } return result; } BOOL rpos_Equal(TERM T1, TERM T2) /************************************************************** INPUT: Two terms. RETURNS: TRUE, if is equal to and FALSE otherwise. ***************************************************************/ { LIST l1, l2; if (!term_EqualTopSymbols(T1, T2)) return FALSE; else if (!term_IsComplex(T1)) /* Equal variable or constant */ return TRUE; else { if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) { /* MUL case */ l1 = rpos_MultisetDifference(T1, T2); if (list_Empty(l1)) return TRUE; else { list_Delete(l1); return FALSE; } } else { /* LEX case */ for (l1 = term_ArgumentList(T1), l2 = term_ArgumentList(T2); !list_Empty(l1) && rpos_Equal(list_Car(l1), list_Car(l2)); l1 = list_Cdr(l1), l2 = list_Cdr(l2)) /* empty */; return list_Empty(l1); /* All arguments were equal */ } } } ord_RESULT rpos_GreaterEqual(TERM T1, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two terms. RETURNS: ord_GREATER_THAN if is greater than ord_EQUAL if both terms are equal ord_UNCOMPARABLE otherwise. CAUTION: The precedence from the order module is used to determine the precedence of symbols! If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { LIST scan; if (term_IsVariable(T1)) { if (term_EqualTopSymbols(T1, T2)) return ord_Equal(); /* T2 is the same variable */ else if(VarIsConst && term_IsVariable(T2)) { if(term_TopSymbol(T1) > term_TopSymbol(T2)) return ord_GreaterThan(); else return ord_Uncomparable(); } else /* A variable can't be greater than another term */ return ord_Uncomparable(); } else if (!VarIsConst && term_IsVariable(T2)) { /* T1 isn't a variable */ if (term_ContainsSymbol(T1, term_TopSymbol(T2))) return ord_GreaterThan(); else return ord_Uncomparable(); } else if(VarIsConst && term_IsVariable(T2)){ return ord_GreaterThan(); } else if (term_EqualTopSymbols(T1, T2)) { if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) return rpos_MulGreaterEqual(T1, T2, VarIsConst); else return rpos_LexGreaterEqual(T1, T2, VarIsConst); } else { if (symbol_PrecedenceGreater(ord_PRECEDENCE, term_TopSymbol(T1), term_TopSymbol(T2))) { /* Different top symbols, symbol of T1 > symbol of T2. */ /* Try if T1 > each argument of T2. */ for (scan = term_ArgumentList(T2); !list_Empty(scan); scan = list_Cdr(scan)) if (!rpos_Greater(T1, list_Car(scan), VarIsConst)) return ord_Uncomparable(); return ord_GreaterThan(); } else { /* Try to find an argument of T1 that is >= T2 */ for (scan = term_ArgumentList(T1); !list_Empty(scan); scan = list_Cdr(scan)) if (!ord_IsUncomparable(rpos_GreaterEqual(list_Car(scan), T2, VarIsConst))) return ord_GreaterThan(); /* Argument of T1 >= T2 */ return ord_Uncomparable(); } } } ord_RESULT rpos_CompareAux(TERM T1, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two terms, a boolean flag indicating if variables of and are interpreted as skolem constants RETURNS: The relation between the two terms with respect to the RPOS ordering: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal, ord_SMALLER_THAN if is greater than and ord_UNCOMPARABLE otherwise. CAUTION: The precedence from the order module is used to determine the precedence of symbols! If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { ord_RESULT result; result = rpos_GreaterEqual(T1, T2, VarIsConst); if (!ord_IsUncomparable(result)) return result; else if (rpos_Greater(T2, T1, VarIsConst)) return ord_SmallerThan(); else return ord_UNCOMPARABLE; } ord_RESULT rpos_Compare(TERM T1, TERM T2) /************************************************************** INPUT: Two terms. RETURNS: The relation between the two terms with respect to the RPOS ordering: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal, ord_SMALLER_THAN if is greater than and ord_UNCOMPARABLE otherwise. CAUTION: The precedence from the order module is used to determine the precedence of symbols! ***************************************************************/ { return rpos_CompareAux(T1, T2, FALSE); } ord_RESULT rpos_CompareSkolem(TERM T1, TERM T2) /************************************************************** INPUT: Two terms. RETURNS: The relation between the two terms with respect to the RPOS ordering: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal, ord_SMALLER_THAN if is greater than and ord_UNCOMPARABLE otherwise. CAUTION: The precedence from the order module is used to determine the precedence of symbols! Variables are threated as constants ***************************************************************/ { return rpos_CompareAux(T1, T2, TRUE); } /**************************************************************/ /* Term comparison with respect to bindings */ /**************************************************************/ static LIST rpos_ContMultisetDifference(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2) /************************************************************** INPUT: Four contexts and two terms. RETURNS: The multiset difference between the arguments of both terms with respect to rpos_ContEqual. EFFECT: Variable bindings are considered. ASSUMPTION: All index variables of and are bound in and , respectively ***************************************************************/ { LIST result, scan1, scan2; /* Don't apply bindings at top level, since that happened */ /* in rpos_ContGreaterEqual */ /* We can't use list_NMultisetDifference, since that function */ /* expects an equality functions for terms that takes two terms */ /* as arguments. We also need the two contexts resolve variable */ /* bindings. */ result = list_Copy(term_ArgumentList(T1)); for (scan2 = term_ArgumentList(T2); !list_Empty(scan2); scan2 = list_Cdr(scan2)) { /* Delete at most one occurrence of the */ /* current element of list2 from list1 */ for (scan1 = result; !list_Empty(scan1); scan1 = list_Cdr(scan1)) { if (list_Car(scan1) != NULL && rpos_ContEqual(GlobalC1, TermC1, list_Car(scan1), GlobalC2, TermC2, list_Car(scan2))) { /* arg of list1 wasn't deleted earlier and terms are equal */ list_Rplaca(scan1, NULL); /* Mark argument of T1 as deleted */ break; } } } return list_PointerDeleteElement(result, NULL); /* Delete all marked terms */ } static ord_RESULT rpos_ContMulGreaterEqual(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two contexts and two terms with equal top symbols and multiset status. RETURNS: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal and ord_UNCOMPARABLE otherwise. EFFECT: Variable bindings are considered. ASSUMPTION: All index variables of and are bound in and , respectively ***************************************************************/ { LIST l1, l2; /* Don't apply bindings at top level, since that happened */ /* in rpos_ContGreaterEqual. */ l1 = rpos_ContMultisetDifference(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2); if (list_Empty(l1)) /* If |M| = |N| and M-N = {} then N-M = {} */ return ord_Equal(); /* Terms are equal */ else { LIST scan; BOOL greater; l2 = rpos_ContMultisetDifference(GlobalC2, TermC2, T2, GlobalC1, TermC1, T1); for (greater = TRUE; !list_Empty(l2) && greater; l2 = list_Pop(l2)) { for (scan = l1, greater = FALSE; !list_Empty(scan) && !greater; scan = list_Cdr(scan)) greater = rpos_ContGreaterAux(GlobalC1, TermC1, list_Car(scan), GlobalC2, TermC2, list_Car(l2), VarIsConst); } list_Delete(l1); /* l2 was freed in the outer for loop */ if (greater) return ord_GreaterThan(); else return ord_Uncomparable(); } } static ord_RESULT rpos_ContLexGreaterEqual(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two contexts and two terms with equal top symbols and lexicographic status and a flag. RETURNS: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal and ord_UNCOMPARABLE otherwise. EFFECT: Variable bindings are considered. ASSUMPTION: All index variables of and are bound in and , respectively CAUTION: If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { ord_RESULT result; LIST l1, l2, scan1, scan2; /* Don't apply bindings at top level, since that happened */ /* in rpos_ContGreaterEqual */ if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { l1 = list_Reverse(term_ArgumentList(T1)); /* Create new lists */ l2 = list_Reverse(term_ArgumentList(T2)); } else { l1 = term_ArgumentList(T1); l2 = term_ArgumentList(T2); } /* First ignore equal arguments */ result = ord_Equal(); for (scan1 = l1, scan2 = l2; !list_Empty(scan1); scan1 = list_Cdr(scan1), scan2 = list_Cdr(scan2)) { result = rpos_ContGreaterEqual(GlobalC1, TermC1, list_Car(scan1), GlobalC2, TermC2, list_Car(scan2), VarIsConst); if (!ord_IsEqual(result)) break; } if (ord_IsEqual(result)) /* All arguments are equal, so the terms */ /* empty */; /* are equal with respect to RPOS */ else if (ord_IsGreaterThan(result)) { /* Check if T1 > each remaining argument of T2 */ for (scan2 = list_Cdr(scan2); !list_Empty(scan2) && rpos_ContGreaterAux(GlobalC1, TermC1, T1, GlobalC2, TermC2, list_Car(scan2), VarIsConst); scan2 = list_Cdr(scan2)); /* Empty body */ if (list_Empty(scan2)) result = ord_GreaterThan(); else result = ord_Uncomparable(); } else { /* Argument of T1 was not >= argument of T2. */ /* Try to find an argument of T1 that is >= T2 */ for (scan1 = list_Cdr(scan1), result = ord_Uncomparable(); !list_Empty(scan1) && !ord_IsGreaterThan(result); scan1 = list_Cdr(scan1)) { if (!ord_IsUncomparable(rpos_ContGreaterEqual(GlobalC1, TermC1,list_Car(scan1), GlobalC2, TermC2,T2, VarIsConst))) result = ord_GreaterThan(); } } if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { list_Delete(l1); /* Delete the lists create above */ list_Delete(l2); } return result; } BOOL rpos_ContEqual(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2) /************************************************************** INPUT: Two contexts and two terms. RETURNS: TRUE, if is equal to and FALSE otherwise. EFFECT: Variable bindings are considered. ASSUMPTION: All index variables of and are bound in and , respectively ***************************************************************/ { LIST l1, l2; T1 = cont_Deref(GlobalC1, &TermC1, T1); T2 = cont_Deref(GlobalC2, &TermC2, T2); if (!term_EqualTopSymbols(T1, T2)) return FALSE; else if (!term_IsComplex(T1)) return TRUE; else { if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) { l1 = rpos_ContMultisetDifference(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2); if (list_Empty(l1)) return TRUE; else { list_Delete(l1); return FALSE; } } else { /* LEX case */ for (l1 = term_ArgumentList(T1), l2 = term_ArgumentList(T2); !list_Empty(l1) && rpos_ContEqual(GlobalC1, TermC1,list_Car(l1), GlobalC2, TermC2,list_Car(l2)); l1 = list_Cdr(l1), l2 = list_Cdr(l2)); /* empty body */ return list_Empty(l1); /* All arguments were equal */ } } } ord_RESULT rpos_ContGreaterEqual(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two contexts and two terms. RETURNS: ord_GREATER_THAN if is greater than ord_EQUAL if both terms are equal ord_UNCOMPARABLE otherwise. EFFECT: Variable bindings are considered. CAUTION: The precedence from the order module is used to determine the precedence of symbols! If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ASSUMPTION: All index variables of and are bound in and , respectively ***************************************************************/ { LIST scan; T1 = cont_Deref(GlobalC1, &TermC1, T1); T2 = cont_Deref(GlobalC2, &TermC2, T2); if (term_IsVariable(T1)) { if (term_EqualTopSymbols(T1, T2)) return ord_Equal(); /* T2 is the same variable */ else /* A variable can't be greater than another term */ return ord_Uncomparable(); } else if (term_IsVariable(T2)) { /* T1 isn't a variable */ if (cont_TermContainsSymbol(GlobalC1, TermC1, T1, term_TopSymbol(T2))) return ord_GreaterThan(); else return ord_Uncomparable(); } else if (term_EqualTopSymbols(T1, T2)) { if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) return rpos_ContMulGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, VarIsConst); else return rpos_ContLexGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, VarIsConst); } else { if (symbol_PrecedenceGreater(ord_PRECEDENCE, term_TopSymbol(T1), term_TopSymbol(T2))) { /* Different top symbols, symbol of T1 > symbol of T2. */ /* Try if T1 > each argument of T2. */ for (scan = term_ArgumentList(T2); !list_Empty(scan); scan = list_Cdr(scan)) if (!rpos_ContGreaterAux(GlobalC1, TermC1, T1, GlobalC2, TermC2, list_Car(scan), VarIsConst)) return ord_Uncomparable(); return ord_GreaterThan(); } else { /* Try to find an argument of T1 that is >= T2 */ for (scan = term_ArgumentList(T1); !list_Empty(scan); scan = list_Cdr(scan)) if (!ord_IsUncomparable(rpos_ContGreaterEqual(GlobalC1, TermC1,list_Car(scan), GlobalC2, TermC2,T2, VarIsConst))) return ord_GreaterThan(); /* Argument of T1 >= T2 */ return ord_Uncomparable(); } } } ord_RESULT rpos_ContCompareAux(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2, BOOL VarIsConst) /************************************************************** INPUT: Two contexts and two terms. RETURNS: The relation between the two terms with respect to the RPOS ordering: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal, ord_SMALLER_THAN if is greater than and ord_UNCOMPARABLE otherwise. EFFECT: Variable bindings are considered. If VarIsConst is true variables are interpreted as constants CAUTION: The precedence from the order module is used to determine the precedence of symbols! If is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { ord_RESULT result; CONTEXT GlobalC1, GlobalC2; GlobalC1 = C1; GlobalC2 = C2; T1 = cont_Deref(GlobalC1, &C1, T1); T2 = cont_Deref(GlobalC2, &C2, T2); result = rpos_ContGreaterEqual(GlobalC1, C1, T1, GlobalC2, C2, T2, VarIsConst); if (!ord_IsUncomparable(result)) return result; else if (rpos_ContGreaterAux(GlobalC2, C2, T2, GlobalC1, C1, T1, VarIsConst)) return ord_SmallerThan(); else return ord_UNCOMPARABLE; } ord_RESULT rpos_ContCompare(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2) /************************************************************** INPUT: Two contexts, two terms and a flag RETURNS: The relation between the two terms with respect to the RPOS ordering: ord_GREATER_THAN if is greater than , ord_EQUAL if both terms are equal, ord_SMALLER_THAN if is greater than and ord_UNCOMPARABLE otherwise. EFFECT: Variable bindings are considered. CAUTION: The precedence from the order module is used to determine the precedence of symbols! ***************************************************************/ { return rpos_ContCompareAux(C1, T1, C2, T2, FALSE); } SPASS-3.7/SPASS/cnf.c0000644000374100037200000053237011340510065011006 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CNF TRANSLATOR * */ /* * * */ /* * $Module: CNF * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.10 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: cnf.c,v $ */ #include "cnf.h" #include "rules-inf.h" #include "rules-red.h" static TERM cnf_AntiPrenexPath(TERM, TERM); static TERM cnf_ApplyDefinitionInternOnce(TERM, TERM, TERM, TERM, BOOL*); static SYMBOL cnf_GetDualSymbol(SYMBOL symbol); static TERM cnf_IsDefinition(TERM); static void cnf_OptimizedSkolemFormula(PROOFSEARCH, TERM, char*, BOOL, TERM, LIST*, LIST*, BOOL, HASH, int); static int cnf_PredicateOccurrences(TERM, SYMBOL); static void cnf_RplacVar(TERM, LIST, LIST); static LIST cnf_SatUnit(PROOFSEARCH, LIST); static LIST cnf_SkolemFunctionFormula(TERM, LIST, LIST, PRECEDENCE); /* For every variable the depth in the current term, required for */ /* strong skolemization */ static int* cnf_VARIABLEDEPTHARRAY; /* Holds a copy of the ProofSearch--Object built by cnf_Flotter */ /* during cnf_QueryFlotter */ static PROOFSEARCH cnf_SEARCHCOPY; /* Proofsearch--Object for the function cnf_HaveProof. We need this */ /* to reduce the number of term stamps required. */ static PROOFSEARCH cnf_HAVEPROOFPS; void cnf_Init(FLAGSTORE Flags) /*************************************************************** INPUT: A flag store. RETURNS: None. SUMMARY: Initializes the CNF Module. EFFECTS: Initializes global variables. CAUTION: MUST BE CALLED BEFORE ANY OTHER CNF-FUNCTION. ***************************************************************/ { /* If strong skolemization is performed, allocate array for variable depth */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) cnf_VARIABLEDEPTHARRAY = (int*) memory_Malloc(sizeof(int[symbol__MAXSTANDARDVAR + 1])); else cnf_VARIABLEDEPTHARRAY = NULL; cnf_SEARCHCOPY = prfs_Create(); cnf_HAVEPROOFPS = prfs_Create(); } void cnf_Free(FLAGSTORE Flags) /************************************************************** INPUT: A flag store. RETURNS: None. SUMMARY: Frees the CNF Module. ***************************************************************/ { /* If strong skolemization is performed, free array for variable depth */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { memory_Free(cnf_VARIABLEDEPTHARRAY, sizeof(int[symbol__MAXSTANDARDVAR + 1])); cnf_VARIABLEDEPTHARRAY = NULL; } prfs_Delete(cnf_SEARCHCOPY); cnf_SEARCHCOPY = NULL; prfs_Delete(cnf_HAVEPROOFPS); cnf_HAVEPROOFPS = NULL; } static int cnf_GetFormulaPolarity(TERM term, TERM subterm) /********************************************************** INPUT: Two terms term and subterm where subterm is a subterm of term. RETURNS: The polarity of subterm in term. ********************************************************/ { LIST scan; TERM term1; int polterm1,bottom; bottom = vec_ActMax(); vec_Push((POINTER) 1); vec_Push(term); do { term1 = (TERM)vec_PopResult(); polterm1 = (int)vec_PopResult(); if (term1 == subterm) { vec_SetMax(bottom); return polterm1; }else if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { vec_Push((POINTER) (- polterm1)); vec_Push(list_Car(term_ArgumentList(term1))); } if (symbol_Equal(term_TopSymbol(term1),fol_Exist()) || symbol_Equal(term_TopSymbol(term1),fol_All())) { vec_Push((POINTER)polterm1); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { vec_Push((POINTER) (- polterm1)); vec_Push(list_Car(term_ArgumentList(term1))); vec_Push((POINTER) polterm1); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { vec_Push(0); vec_Push(list_Car(term_ArgumentList(term1))); vec_Push(0); vec_Push(list_Second(term_ArgumentList(term1))); } else if (symbol_Equal(term_TopSymbol(term1),fol_And()) || symbol_Equal(term_TopSymbol(term1),fol_Or())) { for (scan = term_ArgumentList(term1); !list_Empty(scan); scan = list_Cdr(scan)) { vec_Push((POINTER) polterm1); vec_Push(list_Car(scan)); } } } while (bottom != vec_ActMax()); vec_SetMax(bottom); misc_StartErrorReport(); misc_ErrorReport("\n In cnf_GetFormulaPolarity: Wrong arguments !\n"); misc_FinishErrorReport(); return -2; } static BOOL cnf_ContainsDefinitionIntern(TERM TopDef, TERM Def, int Polarity, TERM* FoundPred) /********************************************************** INPUT: A term TopDef which is the top level term of the recursion. A term Def which is searched for a definition. A pointer to a term into which the predicate of the definition is stored if it is found. RETURNS: TRUE if Def contains a definition that can be converted to standard form. ********************************************************/ { /* AND / OR */ /* In these cases Def cannot be converted to standard form */ if ((symbol_Equal(term_TopSymbol(Def),fol_And()) && (Polarity == 1)) || (symbol_Equal(term_TopSymbol(Def),fol_Or()) && (Polarity == -1))) return FALSE; if (symbol_Equal(term_TopSymbol(Def), fol_And()) || symbol_Equal(term_TopSymbol(Def),fol_Or())) { /* Polarity is ok */ LIST l; for (l=term_ArgumentList(Def); !list_Empty(l); l=list_Cdr(l)) if (cnf_ContainsDefinitionIntern(TopDef, list_Car(l), Polarity, FoundPred)) return TRUE; return FALSE; } /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Def))) return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); /* Negation */ if (symbol_Equal(term_TopSymbol(Def),fol_Not())) return cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred); /* Implication */ if (symbol_Equal(term_TopSymbol(Def),fol_Implies())) { if (Polarity==1) { if (cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred)) return TRUE; return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); } return FALSE; } /* Equivalence */ if (symbol_Equal(term_TopSymbol(Def),fol_Equiv()) && (Polarity==1)) { /* Check if equivalence itself is in correct form */ TERM defpredicate; defpredicate = cnf_IsDefinition(Def); if (defpredicate != (TERM) NULL) { LIST predicate_vars, l, defpath; BOOL allquantifierfound; TERM super; int pol; /* Check if predicate occurs several times in TopDef */ /* if (cnf_PredicateOccurrences(TopDef, term_TopSymbol(defpredicate)) > 1) {} puts("\n Predicate occurs more than once."); return FALSE; */ /* Now make sure that the variables of the predicate are */ /* all--quantified and not in the scope of an exist quantifier */ /* predicate_vars = list_Copy(term_ArgumentList(defpredicate)); */ predicate_vars = term_ListOfVariables(defpredicate); predicate_vars = term_DeleteDuplicatesFromList(predicate_vars); /* So far (going bottom--up) no all-quantifier was found for */ /* a variable of the predicates' arguments */ allquantifierfound = FALSE; /* Build defpath here by going bottom up */ /* At first, list of superterms on path is top down */ defpath = list_Nil(); super = Def; while (super != (TERM) NULL) { defpath = list_Cons(super, defpath); super = term_Superterm(super); } /* No go top down and add polarities */ pol = 1; for (l=defpath; !list_Empty(l); l=list_Cdr(l)) { list_Rplaca(l, list_PairCreate((TERM) list_Car(l), (LIST) pol)); if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Not())) pol = -pol; else { if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Implies()) && (term_FirstArgument((TERM) list_Car(l)) == (TERM) list_Car(list_Cdr(l)))) pol = -pol; else if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Equiv())) pol = 0; } } /* is now a list of pairs (term, polarity) */ for (l=defpath; !list_Empty(l) && !list_Empty(predicate_vars); l=list_Cdr(l)) { LIST pair; TERM t; int p; /* Pair Term t / Polarity p */ pair = (LIST) list_Car(l); t = (TERM) list_PairFirst(pair); p = (int) list_PairSecond(pair); if (fol_IsQuantifier(term_TopSymbol(t))) { /* Variables of the predicate that are universally quantified are no problem */ if ((symbol_Equal(term_TopSymbol(t), fol_All()) && (p==1)) || (symbol_Equal(term_TopSymbol(t), fol_Exist()) && (p==-1))) { LIST scan; allquantifierfound = TRUE; for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) predicate_vars = list_DeleteElement(predicate_vars,(TERM) list_Car(scan), (BOOL (*)(POINTER,POINTER))term_Equal); } else { /* Check if allquantified variables of the predicate are in scope of an exist--quantifier */ /* We already found an all quantified variable */ if (allquantifierfound) { list_Delete(predicate_vars); list_DeletePairList(defpath); return FALSE; } else { LIST scan; /* Check if a variable of the predicate is exist--quantified */ for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) { if (term_ListContainsTerm(predicate_vars, list_Car(scan))) { list_Delete(predicate_vars); list_DeletePairList(defpath); return FALSE; } } } } } } #ifdef CHECK if (!list_Empty(predicate_vars)) { list_Delete(predicate_vars); misc_StartErrorReport(); misc_ErrorReport("\n In cnf_ContainsDefinitionIntern: Definition has free variables.\n"); misc_FinishErrorReport(); } #endif list_DeletePairList(defpath); *FoundPred = defpredicate; return TRUE; } } return FALSE; } BOOL cnf_ContainsDefinition(TERM Def, TERM* FoundPred) /********************************************************** INPUT: A term Def which is searched for a definition of a predicate. A pointer to a term into which the predicate of the definition is stored if it is found. RETURNS: TRUE if Def contains a definition that can be converted to standard form. ***********************************************************/ { BOOL result; #ifdef CHECK fol_CheckFatherLinks(Def); #endif result = cnf_ContainsDefinitionIntern(Def, Def, 1, FoundPred); #ifdef CHECK fol_CheckFatherLinks(Def); #endif return result; } static TERM cnf_IsDefinition(TERM Def) /********************************************************** INPUT: A term Def. RETURNS: The Def term where the arguments of the equivalence are exchanged iff the first one is not a predicate. **********************************************************/ { LIST l,freevars, predicatevars; #ifdef CHECK if (Def == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_IsDefinition: Empty formula.\n"); misc_FinishErrorReport(); } if (!symbol_Equal(term_TopSymbol(Def),fol_Equiv())) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_IsDefinition: Formula is no equivalence.\n"); misc_FinishErrorReport(); } #endif /* If the predicate is the second argument of the equivalence, exchange them */ if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) { TERM arg1; arg1 = term_FirstArgument(Def); term_RplacFirstArgument(Def, term_SecondArgument(Def)); term_RplacSecondArgument(Def, arg1); } /* Check if the first argument is a predicate */ if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) return NULL; /* Check if first argument is a predicate and not fol_Equality */ /* if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def))) || symbol_Equal(term_TopSymbol(term_FirstArgument(Def)), fol_Equality()))) { return NULL; }*/ /* The free variables of the non-predicate term must occur in the predicate term */ freevars = fol_FreeVariables(term_SecondArgument(Def)); freevars = term_DeleteDuplicatesFromList(freevars); predicatevars = term_ListOfVariables(term_FirstArgument(Def)); predicatevars = term_DeleteDuplicatesFromList(predicatevars); for (l=predicatevars; !list_Empty(l); l=list_Cdr(l)) freevars = list_DeleteElement(freevars, list_Car(l), (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(freevars)) { list_Delete(freevars); list_Delete(predicatevars); return NULL; } list_Delete(predicatevars); return term_FirstArgument(Def); } static BOOL cnf_ContainsPredicateIntern(TERM Target, SYMBOL Predicate, int Polarity, TERM* TargetPredicate, TERM* ToTopLevel, LIST* TargetVars, LIST* VarsForTopLevel) /********************************************************** INPUT: A term (sub--) Target A symbol Predicate which is searched in the target term. The polarity of the subterm. A pointer to the term TargetPredicate into which the found predicate term is stored. A pointer to the list TargetVars into which the variables found in the predicates' arguments are stored. A pointer to a list VarsForTopLevel into which all variables are stored that are all--quantified and can be moved to top level. RETURNS: TRUE if Formula contains the predicate for which a definition was found. ********************************************************/ { /* AND / OR */ /* In these cases the predicate (if it exists) can not be moved to a higher level */ if ((symbol_Equal(term_TopSymbol(Target),fol_And()) && Polarity == 1) || (symbol_Equal(term_TopSymbol(Target),fol_Or()) && Polarity == -1) || (symbol_Equal(term_TopSymbol(Target),fol_Implies()) && Polarity != 1) || symbol_Equal(term_TopSymbol(Target), fol_Equiv())) { TERM s; LIST l; /* Try to find Predicate in Target */ s = term_FindSubterm(Target, Predicate); if (s == NULL) return FALSE; /* Store variables found in the predicates arguments */ for (l=term_ArgumentList(s); !list_Empty(l); l = list_Cdr(l)) *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); /* Keep found predicate */ *TargetPredicate = s; *ToTopLevel = Target; return TRUE; } /* AND / OR continued */ if (symbol_Equal(term_TopSymbol(Target),fol_And()) || symbol_Equal(term_TopSymbol(Target),fol_Or())) { /* The polarity is ok here */ LIST l; for (l=term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) if (cnf_ContainsPredicateIntern((TERM) list_Car(l), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) return TRUE; return FALSE; } /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Target))) { if (cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) { /* Quantifiers for free variables of the predicate should be moved to top level to make the proof easier */ if ((symbol_Equal(term_TopSymbol(Target), fol_All()) && Polarity == 1) || (symbol_Equal(term_TopSymbol(Target), fol_Exist()) && Polarity == -1)) { LIST l; /* Check for all variables found in the predicates arguments */ for (l = *TargetVars; !list_Empty(l); l=list_Cdr(l)) { if (term_ListContainsTerm(fol_QuantifierVariables(Target),list_Car(l))) *VarsForTopLevel = list_Cons(list_Car(l), *VarsForTopLevel); } } return TRUE; } return FALSE; } /* Negation */ if (symbol_Equal(term_TopSymbol(Target),fol_Not())) return cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, -Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); /* Implication */ if (symbol_Equal(term_TopSymbol(Target),fol_Implies())) { /* In this case the predicate (if it exists) can be moved to a higher level */ if (cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, -Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel)) return TRUE; return cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, Polarity, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); } /* Found the predicate */ if (symbol_Equal(term_TopSymbol(Target), Predicate)) { LIST l; for (l = term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); *TargetPredicate = Target; *ToTopLevel = Target; return TRUE; } /* In all other cases the predicate was not found */ return FALSE; } BOOL cnf_ContainsPredicate(TERM Target, SYMBOL Predicate, TERM* TargetPredicate, TERM* ToTopLevel, LIST* TargetVars, LIST* VarsForTopLevel) /********************************************************** INPUT: A term Target without implications. A symbol Predicate which is searched in the target term. A pointer to the predicate found in TargetTerm is recorded. A pointer to the term TargetPredicate into which the found predicate term is stored. A pointer to the list TargetVars into which the variables found in the predicates' arguments are stored. A pointer to a list VarsForTopLevel into which all variables are stored that are all--quantified and can be moved to top level. RETURNS: TRUE if Formula contains the predicate for which a definition was found. ********************************************************/ { BOOL result; #ifdef CHECK fol_CheckFatherLinks(Target); #endif result = cnf_ContainsPredicateIntern(Target, Predicate, 1, TargetPredicate, ToTopLevel, TargetVars, VarsForTopLevel); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return result; } static int cnf_PredicateOccurrences(TERM Term, SYMBOL P) /**************************************************** INPUT: A term and a predicate symbol. RETURNS: The number of occurrences of the predicate symbol in Term **************************************************/ { /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(Term))) return cnf_PredicateOccurrences(term_SecondArgument(Term), P); /* Junctors and NOT */ if (fol_IsJunctor(term_TopSymbol(Term)) || symbol_Equal(term_TopSymbol(Term),fol_Not())) { LIST scan; int count; count = 0; for (scan=term_ArgumentList(Term); !list_Empty(scan); scan=list_Cdr(scan)) { count += cnf_PredicateOccurrences(list_Car(scan), P); /* Only the cases count==1 and count>1 are important */ if (count > 1) return count; } return count; } if (symbol_Equal(term_TopSymbol(Term), P)) return 1; return 0; } static TERM cnf_NegationNormalFormulaPath(TERM Term, TERM PredicateTerm) /********************************************************** INPUT: A term and a predicate term which is a subterm of term RETURNS: The negation normal form of the term along the path. CAUTION: The term is destructively changed. This works only if the superterm member of Term and its subterms are set. ********************************************************/ { TERM subterm, termL, term1; LIST scan; SYMBOL symbol; BOOL set; term1 = Term; while (term1 != NULL) { set = FALSE; if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { subterm = term_FirstArgument(term1); if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { LIST l; term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); term_Free(term_FirstArgument(subterm)); list_Delete(term_ArgumentList(subterm)); term_Free(subterm); /* Set superterm member to new superterm */ for (l=term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); /* term1 weiter betrachten */ set = TRUE; } else { if (fol_IsQuantifier(term_TopSymbol(subterm))) { LIST l; symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); termL = term_CreateAddFather(fol_Not(), list_List(term_SecondArgument(subterm))); list_RplacSecond(term_ArgumentList(subterm), termL); term_RplacSuperterm(termL, subterm); term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1, term_ArgumentList(subterm)); for (l=term_ArgumentList(term1); !list_Empty(l); l = list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); term_RplacArgumentList(subterm, list_Nil()); term_Delete(subterm); term1 = termL; /* Next term to check is not(subterm) */ set = TRUE; } else { if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || (symbol_Equal(term_TopSymbol(subterm),fol_And()))) { LIST l; symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); for (scan = term_ArgumentList(subterm); !list_Empty(scan); scan = list_Cdr(scan)) { TERM new; termL = list_Car(scan); new = term_CreateAddFather(fol_Not(),list_List(termL)); list_Rplaca(scan, new); term_RplacSuperterm(new, subterm); } term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(subterm)); for (l = term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm(list_Car(l), term1); term_RplacArgumentList(subterm, list_Nil()); term_Delete(subterm); } } } } if (!set) { if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) if (term_HasProperSuperterm(PredicateTerm, list_Car(scan))) { term1 = list_Car(scan); set = TRUE; break; } if (!set) term1 = NULL; } } return Term; } TERM cnf_ApplyDefinitionOnce(TERM Predicate, TERM Formula, TERM TargetTerm, TERM TargetPredicate, FLAGSTORE Flags) /********************************************************* INPUT: A term Predicate which is a predicate found in a definition. A term Formula which is a term equivalent to the predicate. A term TargetTerm in which one occurrence of the predicate may be replaced by the Formula. A term TargetPredicate which is the subterm of the TargetTerm to be replaced. A flag store. RETURNS: The changed TargetTerm. *************************************************************/ { SYMBOL maxvar, maxvar_temp; LIST bound, scan; BOOL success; /* Init varcounter */ maxvar = term_MaxVar(TargetTerm); maxvar_temp = term_MaxVar(Formula); if (maxvar_temp > maxvar) maxvar = maxvar_temp; symbol_SetStandardVarCounter(maxvar); /* Find bound variables in formula for renaming them */ bound = fol_BoundVariables(Formula); for (scan=bound; !list_Empty(scan); scan=list_Cdr(scan)) { /* Bound variable in definition is already used in term */ if (term_ContainsSymbol(TargetTerm, term_TopSymbol(list_Car(scan)))) term_ExchangeVariable(Formula, term_TopSymbol(list_Car(scan)), symbol_CreateStandardVariable()); } list_Delete(bound); TargetTerm = cnf_ApplyDefinitionInternOnce(Predicate, Formula, TargetTerm, TargetPredicate,&success); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { if (success) { fputs("\nTarget after applying def:\n", stdout); fol_PrettyPrint(TargetTerm); puts("\n"); } } return TargetTerm; } static TERM cnf_ApplyDefinitionInternOnce(TERM Predicate, TERM Formula, TERM TargetTerm, TERM TargetPredicate, BOOL* Success) /********************************************************** INPUT: A term Predicate which is equivalence to Formula and Term RETURNS: The term in which all occurrences of P(..) are replaced by Formula modulo the proper bindings CAUTION: Term is destructively changed! ***********************************************************/ { /* Quantifiers */ if (fol_IsQuantifier(term_TopSymbol(TargetTerm))) { term_RplacSecondArgument(TargetTerm, cnf_ApplyDefinitionInternOnce(Predicate, Formula, term_SecondArgument(TargetTerm), TargetPredicate, Success)); term_RplacSuperterm(term_SecondArgument(TargetTerm), TargetTerm); return TargetTerm; } /* Junctors and NOT */ if (fol_IsJunctor(term_TopSymbol(TargetTerm)) || symbol_Equal(term_TopSymbol(TargetTerm),fol_Not())) { LIST scan; for (scan=term_ArgumentList(TargetTerm); !list_Empty(scan); scan=list_Cdr(scan)) { list_Rplaca(scan, cnf_ApplyDefinitionInternOnce(Predicate, Formula, list_Car(scan), TargetPredicate, Success)); term_RplacSuperterm((TERM) list_Car(scan), TargetTerm); } return TargetTerm; } if (symbol_Equal(term_TopSymbol(TargetTerm), term_TopSymbol(Predicate))) { if (TargetTerm == TargetPredicate) { TERM result; result = Formula; cnf_RplacVar(result, term_ArgumentList(Predicate), term_ArgumentList(TargetTerm)); term_AddFatherLinks(result); term_Delete(TargetTerm); *Success = TRUE; return result; } } return TargetTerm; } static TERM cnf_RemoveEquivImplFromFormula(TERM term) /********************************************************** INPUT: A term. RETURNS: The term with replaced implications and equivalences. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1,termL,termR,termLneg,termRneg; LIST scan; int bottom,pol; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { term_RplacTop(term1, fol_Or()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_Not(), list_List(list_Car(term_ArgumentList(term1))))); }else if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { pol = cnf_GetFormulaPolarity(term,term1); termL = (TERM)list_Car(term_ArgumentList(term1)); termR = (TERM)list_Second(term_ArgumentList(term1)); termLneg = term_Create(fol_Not(),list_List(term_Copy(termL))); termRneg = term_Create(fol_Not(),list_List(term_Copy(termR))); if (pol == 1 || pol == 0) { term_RplacTop(term1, fol_And()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_Or(),list_Cons(termLneg,list_List(termR)))); list_RplacSecond(term_ArgumentList(term1),term_Create(fol_Or(),list_Cons(termRneg,list_List(termL)))); }else if (pol == -1) { term_RplacTop(term1, fol_Or()); list_Rplaca(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termLneg,list_List(termRneg)))); list_RplacSecond(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termL,list_List(termR)))); } } if (!list_Empty(term_ArgumentList(term1)) && !symbol_IsPredicate(term_TopSymbol(term1))) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return term; } static TERM cnf_MovePredicateVariablesUp(TERM Term, TERM TargetPredicateTerm, LIST VarsForTopLevel) /********************************************************** INPUT: A term and a predicate term which is a subterm of term an equivalence. RETURNS: The term where the free variables of the equivalence, which must be allquantified and not in the scope of an exist quantifier, are moved to toplevel. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { TERM arg; arg = (TERM) list_Car(scan); if (term_HasProperSuperterm(TargetPredicateTerm, arg)) { if (symbol_Equal(term_TopSymbol(arg), fol_All())) { LIST predicatevarscan, quantifiervars; quantifiervars = fol_QuantifierVariables(arg); for (predicatevarscan=VarsForTopLevel; !list_Empty(predicatevarscan); predicatevarscan = list_Cdr(predicatevarscan)) quantifiervars = list_DeleteElementFree(quantifiervars, (TERM) list_Car(predicatevarscan), (BOOL (*)(POINTER,POINTER))term_Equal, (void (*)(POINTER))term_Delete); if (!list_Empty(quantifiervars)) term_RplacArgumentList(term_FirstArgument(arg), quantifiervars); else { TERM subterm; subterm = term_SecondArgument(arg); term_Free(term_FirstArgument(arg)); list_Delete(term_ArgumentList(arg)); term_Free(arg); list_Rplaca(scan, subterm); term_RplacSuperterm(subterm, term1); } } vec_Push((TERM) list_Car(scan)); } } } for (scan=VarsForTopLevel; !list_Empty(scan); scan = list_Cdr(scan)) list_Rplaca(scan, term_Copy((TERM) list_Car(scan))); if (symbol_Equal(term_TopSymbol(Term), fol_All())) { LIST vars; vars = fol_QuantifierVariables(Term); vars = list_Nconc(vars, list_Copy(VarsForTopLevel)); vars = term_DestroyDuplicatesInList(vars); term_RplacArgumentList(term_FirstArgument(Term), vars); } else { TERM newtop; newtop = fol_CreateQuantifier(fol_All(), list_Copy(VarsForTopLevel), list_List(Term)); term_RplacSuperterm(Term, newtop); Term = newtop; } vec_SetMax(bottom); return Term; } static TERM cnf_RemoveImplFromFormulaPath(TERM Term, TERM PredicateTerm) /********************************************************** INPUT: A term and a predicate term which is a subterm of term RETURNS: The term where implications along the path to PredicateTerm are replaced. CAUTION: The term is destructively changed. This works only if the superterm member of Term and its subterms are set. ********************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (term_HasProperSuperterm(PredicateTerm, term1)) { if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { TERM newterm; term_RplacTop(term1, fol_Or()); newterm = term_CreateAddFather(fol_Not(), list_List(list_Car(term_ArgumentList(term1)))); list_Rplaca(term_ArgumentList(term1), newterm); term_RplacSuperterm(newterm, term1); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return Term; } static SYMBOL cnf_GetDualSymbol(SYMBOL symbol) /******************************************************** INPUT: A predefined symbol. RETURNS: The dual symbol. ********************************************************/ { SYMBOL dual; dual = symbol; if (symbol_Equal(symbol,fol_All())) dual = fol_Exist(); else if (symbol_Equal(symbol,fol_Exist())) dual = fol_All(); else if (symbol_Equal(symbol,fol_Or())) dual = fol_And(); else if (symbol_Equal(symbol,fol_And())) dual = fol_Or(); return dual; } TERM cnf_NegationNormalFormula(TERM term) /******************************************************** INPUT: A term. RETURNS: The negation normal form of the term. CAUTION: The term is destructively changed. ********************************************************/ { TERM term1,subterm,termL; LIST scan; SYMBOL symbol; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { subterm = (TERM)list_Car(term_ArgumentList(term1)); if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); term_Free(term_FirstArgument(subterm)); list_Delete(term_ArgumentList(subterm)); term_Free(subterm); vec_Push(term1); }else if (fol_IsQuantifier(term_TopSymbol(subterm))) { symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); termL = term_Create(fol_Not(), list_List(term_SecondArgument(subterm))); list_RplacSecond(term_ArgumentList(subterm), termL); term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); term_Delete(subterm); } else if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || symbol_Equal(term_TopSymbol(subterm),fol_And())) { symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); for (scan = term_ArgumentList(subterm); !list_Empty(scan); scan = list_Cdr(scan)) { termL = (TERM)list_Car(scan); list_Rplaca(scan, term_Create(fol_Not(),list_List(termL))); } term_RplacTop(term1,symbol); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); term_Delete(subterm); } } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); return term; } static TERM cnf_QuantMakeOneVar(TERM term) /************************************************************** INPUT: A term. RETURNS: The term where all quantifiers quantify over only one variable. CAUTION: The term is destructively changed. ***************************************************************/ { TERM term1,termL; SYMBOL quantor; LIST scan,varlist; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (fol_IsQuantifier(term_TopSymbol(term1))) { quantor = term_TopSymbol(term1); if (list_Length(term_ArgumentList(term_FirstArgument(term1))) > 1) { varlist = list_Copy(list_Cdr(term_ArgumentList(term_FirstArgument(term1)))); for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { termL = term_SecondArgument(term1); term_RplacSecondArgument(term1, fol_CreateQuantifier(quantor,list_List(list_Car(scan)),list_List(termL))); } for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { term_RplacArgumentList(term_FirstArgument(term1), list_PointerDeleteElement(term_ArgumentList(term_FirstArgument(term1)),list_Car(scan))); } list_Delete(varlist); } } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); return term; } static LIST cnf_GetSymbolList(LIST varlist) /************************************************************** INPUT: A list of variables RETURNS: The list of the symbols of the variables. ***************************************************************/ { LIST scan,result; result = list_Nil(); for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) result = list_Cons((POINTER)term_TopSymbol((TERM)list_Car(scan)),result); return result; } static BOOL cnf_TopIsAnd(LIST termlist) /************************************************************** INPUT: A list of terms. RETURNS: True if one term in termlist is a conjunction. ***************************************************************/ { LIST scan; for (scan=termlist;!list_Empty(scan);scan=list_Cdr(scan)) if (term_TopSymbol(list_Car(scan)) == fol_And()) return TRUE; return FALSE; } static TERM cnf_MakeOneOr(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan; if (symbol_Equal(term_TopSymbol(term),fol_Or())) { TERM argterm; scan=term_ArgumentList(term); while (!list_Empty(scan)) { argterm = (TERM)list_Car(scan); cnf_MakeOneOr(argterm); if (symbol_Equal(term_TopSymbol(argterm),fol_Or())) { scan = list_Cdr(scan); term_RplacArgumentList(term, list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); term_Free(argterm); } else scan = list_Cdr(scan); } } else if (!symbol_IsPredicate(term_TopSymbol(term))) for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) cnf_MakeOneOr(list_Car(scan)); return term; } static TERM cnf_MakeOneOrPredicate(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates and negated predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan,scan1,predlist; if (cnf_TopIsAnd(term_ArgumentList(term))) { for (scan1=term_ArgumentList(term); !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_And())); scan1=list_Cdr(scan1)); if (!list_Empty(scan1)) { predlist = list_Nil(); for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan))) { predlist = list_Cons(list_Car(scan),predlist); } } for (scan=predlist;!list_Empty(scan);scan=list_Cdr(scan)) term_RplacArgumentList(term, list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); if (!list_Empty(predlist)) term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); } } return term; } static TERM cnf_MakeOneOrTerm(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { return cnf_MakeOneOrPredicate(cnf_MakeOneOr(term)); } static TERM cnf_MakeOneAnd(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all arguments of an and together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan; if (symbol_Equal(term_TopSymbol(term),fol_And())) { TERM argterm; scan=term_ArgumentList(term); while (!list_Empty(scan)) { argterm = (TERM)list_Car(scan); cnf_MakeOneAnd(argterm); if (symbol_Equal(term_TopSymbol(argterm),fol_And())) { scan = list_Cdr(scan); term_RplacArgumentList(term, list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); term_Free(argterm); } else scan = list_Cdr(scan); } } else if (!symbol_IsPredicate(term_TopSymbol(term))) for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) cnf_MakeOneAnd(list_Car(scan)); return term; } static TERM cnf_MakeOneAndPredicate(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of one or together. CAUTION: The term is destructively changed. ***************************************************************/ { LIST scan,scan1,predlist; for (scan1=term_ArgumentList(term); !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_Or())); scan1=list_Cdr(scan1)); if (!list_Empty(scan1)) { /* The car of scan1 points to a term with topsymbol 'or' */ predlist = list_Nil(); for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) && fol_IsNegativeLiteral(list_Car(scan))) { predlist = list_Cons(list_Car(scan),predlist); } } for (scan=predlist; !list_Empty(scan); scan=list_Cdr(scan)) term_RplacArgumentList(term, list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); if (!list_Empty(predlist)) term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); } return term; } static TERM cnf_MakeOneAndTerm(TERM term) /************************************************************** INPUT: A term. RETURNS: Takes all predicates as arguments of an or together. CAUTION: The term is destructively changed. ***************************************************************/ { return cnf_MakeOneAndPredicate(cnf_MakeOneAnd(term)); } BOOL cnf_FlattenToSimpleORTerm(TERM Term) /************************************************************** INPUT: A term RETURNS: Traverse the term tree using BFS, and flatten the cascated OR Term to flat ones. Return True if it is a flat OR Term after all, returns FALSE if it contains any AND SubTerm EFFECTS: The input Term will be flattened on each level, as long as it contains no AND subTerm. The sub Terms of the AND Terms are no more flattened, even if it might contains cascated OR Terms as sub Terms. CAUTION: The term is changed. ***************************************************************/ { LIST Scan1,Scan2; BOOL SimpleOrTerm, SimpleOrSubTerm; SimpleOrTerm = FALSE; if (symbol_Equal(term_TopSymbol(Term), fol_Or())) { TERM Argterm; SimpleOrSubTerm = TRUE; Scan1 =term_ArgumentList(Term); while (!list_Empty(Scan1)) { Argterm = (TERM)list_Car(Scan1); Scan2 = list_Cdr(Scan1); if (symbol_Equal(term_TopSymbol(Argterm),fol_Or())) { SimpleOrSubTerm = cnf_FlattenToSimpleORTerm(Argterm); if (!SimpleOrSubTerm) SimpleOrTerm = FALSE; list_NInsert(Scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(Scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } else if (symbol_Equal(term_TopSymbol(Argterm),fol_And())) { SimpleOrTerm = FALSE; } Scan1 = Scan2; } } return SimpleOrTerm; } TERM cnf_ScanTree(TERM Tree) /************************************************************** INPUT: The input complex Term, which need to be transformed to CNF RETURNS: Traverse the term tree using BFS, and put the "or" subtree pointer into the stacks. CAUTION: The term is not changed. ***************************************************************/ { SYMBOL Symbol; LIST Temp; BOOL SimpleOrTerm; SimpleOrTerm = cnf_FlattenToSimpleORTerm(Tree); Symbol = term_TopSymbol(Tree); if (symbol_Equal(Symbol,fol_Or()) && (!SimpleOrTerm)) { stack_Push(Tree); } for (Temp=term_ArgumentList(Tree);!list_Empty(Temp);Temp=list_Cdr(Temp)) { cnf_ScanTree(list_Car(Temp)); } return Tree; } TERM cnf_CombineORTerms(TERM Term1, TERM Term2) /********************************************************** INPUT: Two OR Terms RETURNS: A big "OR" Term. Both argument lists are combined to be the new argument list of Term1. Term1 will be returned. MEMORY: Term2 will be freed. ***********************************************************/ { list_Nconc(term_ArgumentList(Term1), term_ArgumentList(Term2)); term_Free(Term2); return Term1; } TERM cnf_AddAtomToORTerm(TERM AtomTerm, TERM OrTerm) /********************************************************** INPUT: First arg is an Atom Term, second arg is an OR Term RETURNS: Atom Term will be added into the argumentlist of OR Term CAUTION: Atom Term is used, no copy or creation occured ***********************************************************/ { LIST ArgumentList; ArgumentList = list_Cons(AtomTerm, term_ArgumentList(OrTerm)); term_RplacArgumentList(OrTerm, ArgumentList); return OrTerm; } TERM cnf_BuildORTermFromAtoms(TERM Atom1, TERM Atom2) /********************************************************** INPUT: Two atom Terms RETURNS: An OR Term containing the input atom Terms as subterms MEMORY: One new list created, one new Term created. ***********************************************************/ { LIST ArgumentList; ArgumentList = list_List(Atom1); ArgumentList = list_Cons(Atom2, ArgumentList); return term_Create(fol_Or(), ArgumentList); } LIST cnf_List_MultiCons(LIST TempResultList, LIST RightCNFAndArgument) /********************************************************** INPUT: Two list of CNF list. RETURNS: One big CNF list after "multiplications" CAUTION: Both input lists will be destructed and deleted afterwards The content of these lists are reused in the result. New list is generated for the result ***********************************************************/ { LIST NewResult, Scan1, Scan2; TERM NewTerm, Term1, Term2; SYMBOL Symbol1, Symbol2; BOOL BreakOut; NewResult = list_Nil(); BreakOut = FALSE; for (Scan1=TempResultList;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { for (Scan2=RightCNFAndArgument;!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { Term1 = list_Car(Scan1); Term2 = list_Car(Scan2); if (!list_Empty(list_Cdr(Scan2))) { Term1 = term_Copy(Term1); } if (!list_Empty(list_Cdr(Scan1))) { Term2 = term_Copy(Term2); } Symbol1 = term_TopSymbol(Term1); Symbol2 = term_TopSymbol(Term2); /*Case analysis:*/ if (symbol_Equal(Symbol1,fol_Or()) && symbol_Equal(Symbol2,fol_Or())) { if((!list_Empty(list_Cdr(Scan1))) && list_Empty(list_Cdr(Scan2))) { NewTerm = cnf_CombineORTerms(Term2, Term1); } else { NewTerm = cnf_CombineORTerms(Term1, Term2); } } else if ((symbol_Equal(Symbol1,fol_Or())) && (!symbol_Equal(Symbol2,fol_Or()))) { NewTerm = cnf_AddAtomToORTerm(Term2, Term1); } else if ((!symbol_Equal(Symbol1,fol_Or())) && (symbol_Equal(Symbol2,fol_Or()))) { NewTerm = cnf_AddAtomToORTerm(Term1, Term2); } else { NewTerm = cnf_BuildORTermFromAtoms(Term1, Term2); } NewResult = list_Cons( NewTerm, NewResult); } } /* The list is not yet deleted*/ list_Delete(RightCNFAndArgument); list_Delete(TempResultList); NewResult = term_DestroyDuplicatesInList(NewResult); /*Debugging Code*/ /* printf("\nAfter multiplication, the new Result contains:"); for (Scan1= NewResult; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } */ return NewResult; } void cnf_SeparateAndTermsFromArgList(LIST* Input, LIST* AndList, LIST* AtomList, LIST* AndTail, LIST* AtomTail) /************************************************************** INPUT: A Pointer to Input Argument List A Pointer to AndList, which will be filled with And subterms A Pointer to AtomList,which will be filled with Atom subterms A Pointer to AndTail, the last element of AndList A Pointer to AtomTail, the last element of AtomList EFFECTS: All the arguments will be initialised. The given Input List (Argumentst) will be separated to AndList and AtomList. MEMORY: No memory allocation occurs here. The input argumentlist might become either AndList or AtomList, depending on the head element of it. ***************************************************************/ { LIST Scan1,Scan2; Scan1=*Input; while(!list_Empty(Scan1)) { Scan2 = list_Cdr(Scan1); list_Rplacd(Scan1,list_Nil()); if (symbol_Equal(term_TopSymbol(list_Car(Scan1)), fol_And())) { if (list_Empty(*AndList)){ *AndList = Scan1; } else { list_Rplacd(*AndTail,Scan1); } *AndTail = Scan1; } else { if (list_Empty(*AtomList)){ *AtomList = Scan1; } else { list_Rplacd(*AtomTail,Scan1); } *AtomTail = Scan1; } Scan1=Scan2; } /*Debugging Code*/ /* printf("\nAfter cnf_SeparateAtomOrAndTermsFrom:."); printf("\nAnd list:."); for (Scan1= *AndList; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } printf("\nAtom list:."); for (Scan1= *AtomList; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } printf("\nInput list:."); for (Scan1= *Input; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { printf("\n"); term_Print(list_Car(Scan1));fflush(stdout); } */ } LIST cnf_MakeBigAndList(LIST AndList) /************************************************************** INPUT: Build the list of OR SubTerms of a big AND Term RETURNS: The argumentlist of the big AND Term CAUTION: The content of the big AND list will be reused but the list itself is no more useful. The input list is deleted here. ***************************************************************/ { LIST Result, Scan; Result = term_ArgumentList(list_Car(AndList)); for (Scan=list_Cdr(AndList);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Result = cnf_List_MultiCons(Result, term_ArgumentList(list_Car(Scan))); term_Free(list_Car(Scan)); } term_Free(list_Car(AndList)); list_Delete(AndList); return Result; } void cnf_AttachAtomList(LIST* ResultCandidate, LIST AtomList) /************************************************************** INPUT: A candidate list containing either flattened OR Terms or atom Terms; A list containing only Atom Terms EFFECT: The candidate list will be manipulated, so that all subTerms are extended with the AtomList. CAUTION: Destructive on candidate list. The AtomList is useful afterwards, i.e. shouldn't be deleted. ***************************************************************/ { LIST Scan, Temp, AttachAtomList; for (Scan = *ResultCandidate;!list_Empty(Scan);Scan=list_Cdr(Scan)){ if (!list_Empty(list_Cdr(Scan))) { AttachAtomList = term_CopyTermList(AtomList); } else { AttachAtomList = AtomList; } if(symbol_Equal(term_TopSymbol(list_Car(Scan)), fol_Or())) {/*OR subterm*/ Temp = term_ArgumentList(list_Car(Scan)); Temp = list_Nconc(Temp, AttachAtomList); Temp = term_DestroyDuplicatesInList(Temp); term_RplacArgumentList(list_Car(Scan), Temp); } else {/*single atom*/ Temp = list_Cons(list_Car(Scan), AttachAtomList); Temp = term_DestroyDuplicatesInList(Temp); list_Rplaca(Scan, term_Create(fol_Or(), Temp)); } } } void cnf_TransformTree(NAT StackBottom) /************************************************************** INPUT: The NAT flag of stack bottom. EFFECTS: Go through the "or" subtrees bottom up by processing the Stack and convert the poped out subtree to CNF subtree CAUTION: The poped out subterm and the overall Term is distructively changed. ***************************************************************/ { TERM Term; LIST Result, Scan, ArgList, AtomList, AndList, AtomTail, AndTail; while (!stack_Empty(StackBottom)) { Term = stack_PopResult(); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { cnf_Flatten(list_Car(Scan), fol_And()); } AndList = list_Nil(); AtomList = list_Nil(); AndTail = list_Nil(); AtomTail = list_Nil(); ArgList = term_ArgumentList(Term); cnf_SeparateAndTermsFromArgList(&ArgList , &AndList, &AtomList,&AndTail, &AtomTail ); if (!list_Empty(AndList)) {/*The Term is not a simple OR Term, contains And subterms*/ Result = cnf_MakeBigAndList(AndList); if (!list_Empty(AtomList)) {/*The Term contains both AND and Atom sub terms */ cnf_AttachAtomList(&Result, AtomList); } term_RplacTop(Term, fol_And()); term_RplacArgumentList(Term,Result); } /* printf("\nSubOrTerm-After-Transformation: \n"); term_Print(Term);fflush(stdout); */ } } static TERM cnf_DistributiveFormula(TERM Formula) /************************************************************** INPUT: A Formula in NNF which consists only of disjunctions and conjunctions. RETURNS: The Formula where the distributivity rule is exhaustively applied and all disjunctions and the top level conjunction are grouped. CAUTION: The Formula is destructively changed. ***************************************************************/ { NAT StackBottom; if (symbol_Equal(term_TopSymbol(Formula), fol_Or()) || symbol_Equal(term_TopSymbol(Formula), fol_And())) { StackBottom = stack_Bottom(); cnf_ScanTree(Formula); cnf_TransformTree(StackBottom); cnf_Flatten(Formula, fol_And()); } return Formula; } void cnf_FPrintClause(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Print the term which contains only disjunctions to file. The disjunctions represent a clause. ***************************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_Or())) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); }else term_FPrint(file,term1); } fputs(".\n", file); vec_SetMax(bottom); } void cnf_FPrint(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { TERM term1; LIST scan; int bottom; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),fol_And())) { for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); }else if (symbol_Equal(term_TopSymbol(term1),fol_Or()) || symbol_IsPredicate(term_TopSymbol(term1)) || symbol_Equal(term_TopSymbol(term1),fol_Not())) cnf_FPrintClause(term1,file); } vec_SetMax(bottom); } void cnf_StdoutPrint(TERM term) /************************************************************** INPUT: A term. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to standard out. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) term_Print(list_Car(scan1)); puts("."); }else{ term_Print(list_Car(scan)); puts("."); } } } void cnf_FilePrint(TERM term, FILE* file) /************************************************************** INPUT: A term and a file. RETURNS: Nothing. EFFECT: Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) term_FPrint(file,list_Car(scan1)); fputs(".\n", file); }else{ term_FPrint(file,list_Car(scan)); fputs(".\n", file); } } } void cnf_FilePrintPrefix(TERM term, FILE* file) /************************************************************** INPUT: A term and a file pointer. RETURNS: Nothing. EFFECT: Prefix Print the term (in negation normal form) which contains only conjunctions of disjunctions to file. The conjunctions are interpreted to represent different clauses. ***************************************************************/ { LIST termlist,scan,scan1; for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) { termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) termlist = term_ArgumentList(list_Car(scan)); if (!list_Empty(termlist)) { for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) { term_FPrintPrefix(file,list_Car(scan1)); if (!list_Empty(list_Cdr(scan1))) fputs(" | ", file); } fputs(".\n", file); } else { term_FPrintPrefix(file,list_Car(scan)); fputs(".\n", file); } } } static LIST cnf_SubsumeClauseList(FLAGSTORE Flags, LIST clauselist) /********************************************************** INPUT: A list of clauses. RETURNS: The list of clauses without subsumed clauses. EFFECT: Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit subsumption reductions. CAUTION: The list is destructively changed. ***********************************************************/ { LIST scan; st_INDEX stindex; CLAUSE actclause; stindex = st_IndexCreate(); for (scan = clauselist; !list_Empty(scan); scan=list_Cdr(scan)) res_InsertClauseIndex(list_Car(scan),stindex); scan=clauselist; while (!list_Empty(scan)) { actclause = list_Car(scan); res_DeleteClauseIndex(actclause,stindex); if (res_BackSubWithLength(actclause,stindex)) { clause_Delete(actclause); list_Rplaca(scan,(POINTER)NULL); } else res_InsertClauseIndex(actclause,stindex); if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) scan = list_Nil(); else scan = list_Cdr(scan); } clauselist = list_PointerDeleteElement(clauselist, (POINTER)NULL); st_IndexDelete(stindex); return clauselist; } static LIST cnf_MakeClauseList(TERM term, BOOL Sorts, BOOL Conclause, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A term in cnf and two boolean values indicating whether sorts should be generated and whether the generated clauses are Conclauses, a flag store and a precedence. RETURNS: A list of clauses with respect to term. The terms in the new clauses are the copied subterms from term. EFFECT: The flag store and the precedence are not changed, but they're needed for creating clauses. Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit condesing and subsumption reductions. ***************************************************************/ { LIST termlist,scan,clauselist,condlist; CLAUSE clause; int j; termlist = list_Nil(); clauselist = list_Nil(); if (fol_IsTrue(term)) return clauselist; if (fol_IsNegativeLiteral(term) || symbol_IsPredicate(term_TopSymbol(term))) { termlist = list_List(term_Copy(term)); clause = clause_CreateFromLiterals(termlist, Sorts, Conclause,TRUE, Flags, Precedence); clauselist = list_Nconc(clauselist,list_List(clause)); term_StartMinRenaming(); term_Rename(clause_GetLiteralTerm(clause,0)); list_Delete(termlist); return clauselist; } term = cnf_MakeOneAndTerm(term); if (symbol_Equal(term_TopSymbol(term), fol_And())) { for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { list_Rplaca(scan, cnf_MakeOneOrTerm(list_Car(scan))); termlist = list_Nil(); if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || fol_IsNegativeLiteral(list_Car(scan)))) { termlist = term_CopyTermList(term_ArgumentList(list_Car(scan))); termlist = term_DestroyDuplicatesInList(termlist); } else termlist = list_List(term_Copy(list_Car(scan))); if (!list_Empty(termlist)) { clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, Flags, Precedence); term_StartMinRenaming(); for (j = 0; j < clause_Length(clause); j++) term_Rename(clause_GetLiteralTerm(clause,j)); clauselist = list_Cons(clause,clauselist); list_Delete(termlist); } } } else { /* Here the term is a disjunction, i.e. there is only one clause */ term = cnf_MakeOneOrTerm(term); if (!(symbol_IsPredicate(term_TopSymbol(term)) || fol_IsNegativeLiteral(term))) { termlist = term_CopyTermList(term_ArgumentList(term)); termlist = term_DestroyDuplicatesInList(termlist); } else termlist = list_List(term_Copy(term)); if (!list_Empty(termlist)) { clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, Flags, Precedence); term_StartMinRenaming(); for (j = 0; j < clause_Length(clause); j++) term_Rename(clause_GetLiteralTerm(clause,j)); clauselist = list_Cons(clause,clauselist); list_Delete(termlist); } } for (scan=clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { clause = (CLAUSE)list_Car(scan); if (res_HasTautology(clause)) { clause_Delete(clause); list_Rplaca(scan, (POINTER)NULL); } else if (flag_GetFlagIntValue(Flags, flag_CNFCON) == flag_ON) { condlist = cond_CondFast(clause); if (!list_Empty(condlist)) clause_DeleteLiterals(clause, condlist, Flags, Precedence); list_Delete(condlist); } if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) { flag_SetFlagIntValue(Flags, flag_CNFCON, flag_OFF); flag_SetFlagIntValue(Flags, flag_CNFSUB, flag_OFF); } } clauselist = list_PointerDeleteElement(clauselist, (POINTER)NULL); if (flag_GetFlagIntValue(Flags, flag_CNFSUB) == flag_ON) clauselist = cnf_SubsumeClauseList(Flags, clauselist); return clauselist; } TERM cnf_Flatten(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A and that is assumed to be associative. RETURNS: If the top symbol of is the is flattened as long as it contains further direct subterms starting with CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan1,Scan2; if (symbol_Equal(term_TopSymbol(Term), Symbol)) { TERM Argterm; Scan1 =term_ArgumentList(Term); while (!list_Empty(Scan1)) { Argterm = (TERM)list_Car(Scan1); Scan2 = list_Cdr(Scan1); if (symbol_Equal(term_TopSymbol(Argterm),Symbol)) { cnf_Flatten(Argterm,Symbol); list_NInsert(Scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(Scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } Scan1 = Scan2; } } return Term; } static TERM cnf_FlattenPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A and that is assumed to be associative, and a predicate term which is a subterm of term RETURNS: If the top symbol of is the is flattened as long as it contains further direct subterms starting with CAUTION: The term is destructively changed. ***************************************************************/ { TERM subterm; subterm = Term; while (symbol_Equal(term_TopSymbol(subterm), fol_All())) subterm = term_SecondArgument(subterm); if (symbol_Equal(term_TopSymbol(subterm), fol_Or())) { TERM Argterm; LIST scan1; scan1 = term_ArgumentList(subterm); while (!list_Empty(scan1)) { LIST scan2; Argterm = (TERM)list_Car(scan1); scan2 = list_Cdr(scan1); if (term_HasProperSuperterm(PredicateTerm, Argterm)) { if (symbol_Equal(term_TopSymbol(Argterm),fol_Or())) { LIST l; cnf_Flatten(Argterm,fol_Or()); for (l=term_ArgumentList(Argterm); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), subterm); list_NInsert(scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ list_Rplaca(scan1,list_Car(term_ArgumentList(Argterm))); list_Free(term_ArgumentList(Argterm)); term_Free(Argterm); } } scan1 = scan2; } } return Term; } static void cnf_DistrQuantorNoVarSub(TERM Term) /************************************************************** INPUT: A formula in negation normal form starting with a universal (existential) quantifier and a disjunction (conjunction) as argument. EFFECT: The Quantor is distributed if possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Variables,Subformulas,Scan1,Scan2,Rest; TERM Subterm,Var,NewForm; SYMBOL Subtop,Top; Top = term_TopSymbol(Term); Variables = list_Copy(fol_QuantifierVariables(Term)); Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); Subterm = cnf_Flatten(Subterm,Subtop); for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { Subformulas = list_Nil(); Var = (TERM)list_Car(Scan1); for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) if (!fol_VarOccursFreely(Var,list_Car(Scan2))) Subformulas = list_Cons(list_Car(Scan2),Subformulas); if (!list_Empty(Subformulas)) { Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); if (list_Empty(list_Cdr(Rest))) { /* One subformula */ if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ NewForm = (TERM)list_Car(Rest); term_RplacArgumentList(term_FirstArgument(NewForm), list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); list_Delete(Rest); } else NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),Rest); } else NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),list_List(term_Create(Subtop,Rest))); term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); term_RplacArgumentList(term_FirstArgument(Term), list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); } } if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ term_Free(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,Subtop); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); } list_Delete(Variables); } static TERM cnf_AntiPrenex(TERM Term) /************************************************************** INPUT: A formula in negation normal form. RETURNS: The term after application of anti-prenexing. Quantifiers are moved inside as long as possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) { TERM Subterm,Actterm; SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); if (!symbol_IsPredicate(Subtop) && !symbol_Equal(Subtop,fol_Not())) { /* Formula in NNF: No Literals or Atoms */ if (symbol_Equal(Top,fol_All())) DistrSymb = fol_And(); else DistrSymb = fol_Or(); if (fol_IsQuantifier(Subtop)) { cnf_AntiPrenex(Subterm); Subtop = term_TopSymbol(Subterm); } if (symbol_Equal(Subtop,DistrSymb)) { LIST Variables; LIST NewVars; Variables = fol_QuantifierVariables(Term); Subterm = cnf_Flatten(Subterm,DistrSymb); for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Actterm = (TERM)list_Car(Scan); NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(NewVars)) { if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ term_CopyTermsInList(NewVars); term_RplacArgumentList(term_FirstArgument(Actterm), list_Nconc(fol_QuantifierVariables(Actterm), NewVars)); } else { term_CopyTermsInList(NewVars); list_Rplaca(Scan,fol_CreateQuantifier(Top, NewVars, list_List(Actterm))); } } } term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,DistrSymb); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) list_Rplaca(Scan,cnf_AntiPrenex(list_Car(Scan))); } else if (!fol_IsQuantifier(Subtop)) { cnf_DistrQuantorNoVarSub(Term); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_AntiPrenex(list_Car(Scan)); } } } else if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_AntiPrenex(list_Car(Scan)); return Term; } static void cnf_DistrQuantorNoVarSubPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A formula in negation normal form starting with a universal (existential) quantifier and a disjunction (conjunction) as argument and a predicate term which is a subterm of term. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Variables,Subformulas,Scan1,Scan2,Rest; TERM Subterm,Var,NewForm; SYMBOL Subtop,Top; /*fputs("\nAN0:\t",stdout);term_Print(Term);*/ Top = term_TopSymbol(Term); Variables = list_Copy(fol_QuantifierVariables(Term)); Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); Subterm = cnf_Flatten(Subterm,Subtop); /*fputs("\nAN1:\t",stdout);term_Print(Subterm);*/ for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { Subformulas = list_Nil(); Var = (TERM)list_Car(Scan1); /* Find subterms in which the variable does not occur freely */ for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) if (!fol_VarOccursFreely(Var,list_Car(Scan2))) Subformulas = list_Cons(list_Car(Scan2),Subformulas); if (!list_Empty(Subformulas)) { /* Rest is the list of those subterms where the variable does occur freely */ Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); if (list_Empty(list_Cdr(Rest))) { /* One subformula */ if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ NewForm = (TERM)list_Car(Rest); /* Move one variable down */ term_RplacArgumentList(term_FirstArgument(NewForm), list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); list_Delete(Rest); } else { NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var), Rest); } } else { TERM t; t = term_CreateAddFather(Subtop,Rest); NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var),list_List(t)); } if (term_HasProperSuperterm(PredicateTerm, NewForm)) NewForm = cnf_AntiPrenexPath(NewForm, PredicateTerm); term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); term_RplacSuperterm(NewForm, Subterm); term_RplacArgumentList(term_FirstArgument(Term), list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); } } if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ LIST l; term_Free(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,Subtop); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); for (l=term_ArgumentList(Term); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), Term); } list_Delete(Variables); } static TERM cnf_AntiPrenexPath(TERM Term, TERM PredicateTerm) /************************************************************** INPUT: A formula in negation normal form and a predicate term which is a subterm of term. RETURNS: The term after application of anti-prenexing. Quantifiers are moved inside along the path as long as possible. CAUTION: The term is destructively changed. ***************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) { TERM Subterm,Actterm; SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ Subterm = term_SecondArgument(Term); Subtop = term_TopSymbol(Subterm); if (!symbol_Equal(Subtop,fol_Not()) && !symbol_IsPredicate(Subtop)) { /* No Literals or Atoms */ if (symbol_Equal(Top,fol_All())) DistrSymb = fol_And(); else DistrSymb = fol_Or(); if (fol_IsQuantifier(Subtop)) { cnf_AntiPrenexPath(Subterm, PredicateTerm); Subtop = term_TopSymbol(Subterm); } if (symbol_Equal(Subtop,DistrSymb)) { LIST Variables; LIST NewVars; Variables = fol_QuantifierVariables(Term); Subterm = cnf_Flatten(Subterm,DistrSymb); term_AddFatherLinks(Subterm); /* for (l=term_ArgumentList(Subterm); !list_Empty(l); l=list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), Subterm); */ for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Actterm = (TERM)list_Car(Scan); NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, (BOOL (*)(POINTER,POINTER))term_Equal); if (!list_Empty(NewVars)) { if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ term_CopyTermsInList(NewVars); term_RplacArgumentList(term_FirstArgument(Actterm), list_Nconc(fol_QuantifierVariables(Actterm), NewVars)); } else { term_CopyTermsInList(NewVars); list_Rplaca(Scan,fol_CreateQuantifierAddFather(Top, NewVars, list_List(Actterm))); } } } term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,DistrSymb); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); term_AddFatherLinks(Term); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { term_RplacSuperterm((TERM) list_Car(Scan), Term); if (term_HasPointerSubterm((TERM) list_Car(Scan), PredicateTerm)) { puts("\ncheck1"); list_Rplaca(Scan,cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm)); term_RplacSuperterm((TERM) list_Car(Scan), Term); } } } else if (!fol_IsQuantifier(Subtop)) { cnf_DistrQuantorNoVarSubPath(Term, PredicateTerm); for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (term_HasPointerSubterm(list_Car(Scan), PredicateTerm)) cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); } } } } else if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (term_HasProperSuperterm(PredicateTerm, (TERM) list_Car(Scan))) cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); term_AddFatherLinks(Term); return Term; } static TERM cnf_RemoveTrivialOperators(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after removal of "or" and "and" with only one argument CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top; LIST Scan; Top = term_TopSymbol(Term); if (symbol_IsPredicate(Top)) return Term; if ((symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) && list_Empty(list_Cdr(term_ArgumentList(Term)))) { TERM Result; Result = term_FirstArgument(Term); term_RplacSuperterm(Result, term_Superterm(Term)); list_Delete(term_ArgumentList(Term)); term_Free(Term); return cnf_RemoveTrivialOperators(Result); } for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { list_Rplaca(Scan,cnf_RemoveTrivialOperators(list_Car(Scan))); term_RplacSuperterm((TERM) list_Car(Scan), Term); } return Term; } static TERM cnf_SimplifyQuantors(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after removal of bindings of variables that don't occur in the respective subformula and possible mergings of quantors CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top; LIST Scan; Top = term_TopSymbol(Term); if (symbol_IsPredicate(Top) || symbol_Equal(Top,fol_Varlist())) return Term; if (fol_IsQuantifier(Top)) { LIST Vars; TERM Var,Subterm,Aux; Vars = list_Nil(); Subterm = term_SecondArgument(Term); while (symbol_Equal(term_TopSymbol(Subterm),Top)) { term_RplacArgumentList(term_FirstArgument(Term), list_Nconc(fol_QuantifierVariables(Term),fol_QuantifierVariables(Subterm))); term_Free(term_FirstArgument(Subterm)); Aux = term_SecondArgument(Subterm); list_Delete(term_ArgumentList(Subterm)); term_Free(Subterm); list_Rplaca(list_Cdr(term_ArgumentList(Term)),Aux); Subterm = Aux; } for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Var = (TERM)list_Car(Scan); if (!fol_VarOccursFreely(Var,Subterm)) Vars = list_Cons(Var,Vars); } if (!list_Empty(Vars)) { Subterm = term_FirstArgument(Term); term_RplacArgumentList(Subterm,list_NPointerDifference(term_ArgumentList(Subterm),Vars)); term_DeleteTermList(Vars); if (list_Empty(term_ArgumentList(Subterm))) { Subterm = term_SecondArgument(Term); term_Delete(term_FirstArgument(Term)); list_Delete(term_ArgumentList(Term)); term_Free(Term); return cnf_SimplifyQuantors(Subterm); } } } for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) list_Rplaca(Scan,cnf_SimplifyQuantors(list_Car(Scan))); return Term; } TERM cnf_RemoveTrivialAtoms(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula where occurrences of the atoms "true" and "false" are propagated and eventually removed. CAUTION: The term is destructively changed. ***************************************************************/ { SYMBOL Top,Subtop; LIST Scan; TERM Result; BOOL Update; if (!term_IsComplex(Term)) return Term; Top = term_TopSymbol(Term); Update = FALSE; if (symbol_Equal(Top,fol_And())) { Scan = term_ArgumentList(Term); while (!list_Empty(Scan)) { Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_True())) Update = TRUE; else if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_False()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } Scan = list_Cdr(Scan); } if (Update) { term_RplacArgumentList(Term,fol_DeleteTrueTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term,fol_True()); return Term; } } } else if (symbol_Equal(Top,fol_Or())) { Scan = term_ArgumentList(Term); while (!list_Empty(Scan)) { Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) Update = TRUE; else if (symbol_Equal(Subtop,fol_True())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } Scan = list_Cdr(Scan); } if (Update) { term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term,fol_False()); return Term; } } } else if (fol_IsQuantifier(Top) || symbol_Equal(Top,fol_Not())) { if (fol_IsQuantifier(Top)) Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); else Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if ((symbol_Equal(Subtop,fol_False()) && symbol_Equal(Top,fol_Not())) || (symbol_Equal(Subtop,fol_True()) && fol_IsQuantifier(Top))) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if ((symbol_Equal(Subtop,fol_True()) && symbol_Equal(Top,fol_Not())) || (symbol_Equal(Subtop,fol_False()) && fol_IsQuantifier(Top))) { term_RplacTop(Term,fol_False()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } } else if (symbol_Equal(Top,fol_Implies())) { Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); return cnf_RemoveTrivialAtoms(Term); } Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_True())) { term_RplacTop(Term,fol_True()); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term,list_Nil()); return Term; } else if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); } } else if (symbol_Equal(Top,fol_Equiv())) { Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); if (list_Empty(term_ArgumentList(Term))) { term_RplacTop(Term, fol_True()); return Term; } return cnf_RemoveTrivialAtoms(Term); } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); return cnf_RemoveTrivialAtoms(Term); } Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); Subtop = term_TopSymbol(Result); if (symbol_Equal(Subtop,fol_False())) { term_RplacTop(Term,fol_Not()); term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); } else if (symbol_Equal(Subtop,fol_True())) { term_Delete(Result); Result = term_FirstArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Result)); term_RplacArgumentList(Term,term_ArgumentList(Result)); term_Free(Result); } } return Term; } TERM cnf_ObviousSimplifications(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The formula after performing the following simplifications: - remove "or" and "and" with only one argument - remove bindings of variables that don't occur in the respective subformula - merge quantors CAUTION: The term is destructively changed. ***************************************************************/ { Term = cnf_RemoveTrivialAtoms(Term); Term = cnf_RemoveTrivialOperators(Term); Term = cnf_SimplifyQuantors(Term); return Term; } /* EK: warum wird Term zurueckgegeben, wenn er destruktiv geaendert wird??? */ static TERM cnf_SkolemFormula(TERM Term, FLAGSTORE Flags, PRECEDENCE Precedence, LIST* Symblist) /************************************************************** INPUT: A formula in negation normal form, a precedence and pointer to a list used as return value. RETURNS: The skolemized term and the list of introduced Skolem functions. CAUTION: The term is destructively changed. The precedence of the new Skolem functions is set in . ***************************************************************/ { SYMBOL Top,SkolemSymbol; TERM Subterm,SkolemTerm; LIST Varlist,Scan; NAT Arity; Top = term_TopSymbol(Term); if (fol_IsQuantifier(term_TopSymbol(Term))) { if (symbol_Equal(Top,fol_All())) { term_Delete(term_FirstArgument(Term)); Subterm = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Subterm)); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); return cnf_SkolemFormula(Term, Flags, Precedence, Symblist); } else { /* exist quantifier */ /* Implementation of the quantifier exchange operator of Ohlbach & * Schmidt for the functional translation of modal logics K, KD. * Constants are introduced during Skolemisation */ if (flag_GetFlagIntValue(Flags, flag_CNFQUANTEXCH)) { Varlist = list_Nil(); Arity = 0; } else { Varlist = fol_FreeVariables(Term); Arity = list_Length(Varlist); } for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { SkolemSymbol = symbol_CreateSkolemFunction(Arity, Precedence); *Symblist = list_Cons((POINTER)SkolemSymbol, *Symblist); SkolemTerm = term_Create(SkolemSymbol,Varlist); /* Caution: Sharing of Varlist ! */ fol_ReplaceVariable(term_SecondArgument(Term),term_TopSymbol(list_Car(Scan)),SkolemTerm); term_Free(SkolemTerm); } list_Delete(Varlist); term_Delete(term_FirstArgument(Term)); Subterm = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(Subterm)); term_RplacArgumentList(Term,term_ArgumentList(Subterm)); term_Free(Subterm); return cnf_SkolemFormula(Term, Flags, Precedence, Symblist); } } else if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) cnf_SkolemFormula(list_Car(Scan), Flags, Precedence, Symblist); return Term; } static TERM cnf_Cnf(TERM Term, FLAGSTORE Flags, PRECEDENCE Precedence, LIST* Symblist) /************************************************************** INPUT: A formula, a precedence and a pointer to a list of symbols used as return value. RETURNS: The term is transformed to conjunctive normal form. EFFECT: The term is destructively changed and not normalized. The precedence of new Skolem symbols is set in . ***************************************************************/ { /* Necessary because ren_Rename crashes if a e.g. and() has only one argument */ Term = cnf_ObviousSimplifications(Term); term_AddFatherLinks(Term); Term = ren_Rename(Term, Precedence, Symblist, FALSE, FALSE, flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); Term = cnf_RemoveEquivImplFromFormula(Term); Term = cnf_NegationNormalFormula(Term); Term = cnf_SkolemFormula(cnf_AntiPrenex(Term), Flags, Precedence, Symblist); Term = cnf_DistributiveFormula(Term); return Term; } static LIST cnf_GetUsedTerms(CLAUSE C, PROOFSEARCH Search, HASH InputClauseToTermLabellist) /************************************************************** INPUT: RETURNS: ***************************************************************/ { LIST UsedTerms, Used2, Scan; UsedTerms = list_Copy(hsh_Get(InputClauseToTermLabellist, C)); UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); if (!list_Empty(UsedTerms)) return UsedTerms; for (Scan = clause_ParentClauses(C); !list_Empty(Scan); Scan = list_Cdr(Scan)) { CLAUSE P; int ClauseNumber; ClauseNumber = (int) list_Car(Scan); P = clause_GetNumberedCl(ClauseNumber, prfs_WorkedOffClauses(Search)); if (P == NULL) { P = clause_GetNumberedCl(ClauseNumber, prfs_UsableClauses(Search)); if (P == NULL) P = clause_GetNumberedCl(ClauseNumber, prfs_DocProofClauses(Search)); } Used2 = cnf_GetUsedTerms(P, Search, InputClauseToTermLabellist); UsedTerms = list_Nconc(UsedTerms, Used2); } return UsedTerms; } static BOOL cnf_HaveProofOptSkolem(PROOFSEARCH Search, TERM topterm, char* toplabel, TERM term2, LIST* UsedTerms, LIST* Symblist, HASH InputClauseToTermLabellist) /************************************************************** INPUT: RETURNS: ??? EK ***************************************************************/ { LIST ConClauses, EmptyClauses; LIST scan; BOOL found; LIST Usables; FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); ConClauses = list_Nil(); found = FALSE; /* List of clauses from term2 */ term_AddFatherLinks(term2); term2 = cnf_Cnf(term2, Flags, Precedence, Symblist); Usables = cnf_MakeClauseList(term2, FALSE, FALSE, Flags, Precedence); term_Delete(term2); for (scan=Usables; !list_Empty(scan); scan = list_Cdr(scan)) { clause_SetFlag(list_Car(scan), CONCLAUSE); if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) { #ifdef CHECK hsh_Check(InputClauseToTermLabellist); #endif hsh_Put(InputClauseToTermLabellist, list_Car(scan), toplabel); #ifdef CHECK_CNF fputs("\nUsable : ", stdout); clause_Print(list_Car(scan)); printf(" Label %s", toplabel); #endif } } EmptyClauses = cnf_SatUnit(Search, Usables); if (!list_Empty(EmptyClauses)) { found = TRUE; #ifdef CHECK_CNF fputs("\nHaveProof : Empty Clause : ", stdout); clause_Print((CLAUSE) list_Car(EmptyClauses)); putchar('\n'); #endif if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) *UsedTerms = list_Nconc(*UsedTerms, cnf_GetUsedTerms((CLAUSE) list_Car(EmptyClauses), Search, InputClauseToTermLabellist)); EmptyClauses = list_PointerDeleteDuplicates(EmptyClauses); clause_DeleteClauseList(EmptyClauses); } /* Removing ConClauses from UsablesIndex */ ConClauses = list_Copy(prfs_UsableClauses(Search)); for (scan = ConClauses; !list_Empty(scan); scan = list_Cdr(scan)) if (flag_GetFlagIntValue(Flags, flag_DOCPROOF)) prfs_MoveUsableDocProof(Search, (CLAUSE) list_Car(scan)); else prfs_DeleteUsable(Search, (CLAUSE) list_Car(scan)); list_Delete(ConClauses); return found; } BOOL cnf_HaveProof(LIST TermList, TERM ToProve, FLAGSTORE InputFlags, PRECEDENCE InputPrecedence) /************************************************************** INPUT: A list of terms, a term to prove, a flag store and a precedence. The arguments are not changed. RETURNS: True if the termlist implies ToProve CAUTION: All terms are copied. ***************************************************************/ { PROOFSEARCH search; LIST scan, usables, symblist, emptyclauses; BOOL found; FLAGSTORE Flags; PRECEDENCE Precedence; /* Use global PROOFSEARCH object to avoid stamp overflow */ search = cnf_HAVEPROOFPS; usables = symblist = list_Nil(); /* Initialize search object's flag store */ Flags = prfs_Store(search); flag_CleanStore(Flags); flag_InitFlotterSubproofFlags(InputFlags, Flags); /* Initialize search object's precedence */ Precedence = prfs_Precedence(search); symbol_TransferPrecedence(InputPrecedence, Precedence); /* Build list of clauses from the termlist */ for (scan=TermList; !list_Empty(scan); scan=list_Cdr(scan)) { TERM t; t = term_Copy(list_Car(scan)); t = cnf_Cnf(t, Flags, Precedence, &symblist); usables = list_Nconc(cnf_MakeClauseList(t,FALSE,FALSE,Flags,Precedence), usables); term_Delete(t); } /* Build clauses from negated term to prove */ ToProve = term_Create(fol_Not(), list_List(term_Copy(ToProve))); term_AddFatherLinks(ToProve); ToProve = cnf_Cnf(ToProve, Flags, Precedence, &symblist); usables = list_Nconc(cnf_MakeClauseList(ToProve,FALSE,FALSE,Flags,Precedence), usables); term_Delete(ToProve); /* SatUnit requires the CONCLAUSE flag */ for (scan=usables;!list_Empty(scan); scan = list_Cdr(scan)) clause_SetFlag(list_Car(scan), CONCLAUSE); emptyclauses = cnf_SatUnit(search, usables); if (!list_Empty(emptyclauses)) { found = TRUE; emptyclauses = list_PointerDeleteDuplicates(emptyclauses); clause_DeleteClauseList(emptyclauses); } else found = FALSE; prfs_Clean(search); symbol_DeleteSymbolList(symblist); return found; } static void cnf_RplacVarsymbFunction(TERM term, SYMBOL varsymb, TERM function) /********************************************************** INPUT: A term, a variable symbol and a function. EFFECT: The variable with the symbol varsymb in the term is replaced by the function function. CAUTION: The term is destructively changed. ***********************************************************/ { int bottom; TERM term1; LIST scan; bottom = vec_ActMax(); vec_Push(term); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),varsymb)) { term_RplacTop(term1,term_TopSymbol(function)); term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(function))); }else if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); } static void cnf_RplacVar(TERM Term, LIST Varlist, LIST Termlist) /********************************************************** INPUT: A term,a variable symbol and a function. RETURNS: The variable with the symbol varsymb in the term is replaced by the function function. CAUTION: The term is destructively changed. ***********************************************************/ { int bottom; TERM term1; LIST scan,scan2; bottom = vec_ActMax(); vec_Push(Term); while (bottom != vec_ActMax()) { term1 = vec_PopResult(); if (symbol_IsVariable(term_TopSymbol(term1))) { BOOL done; done = FALSE; for (scan=Varlist, scan2=Termlist; !list_Empty(scan) && !done; scan = list_Cdr(scan), scan2 = list_Cdr(scan2)) { if (symbol_Equal(term_TopSymbol(term1),term_TopSymbol(list_Car(scan)))) { term_RplacTop(term1,term_TopSymbol((TERM) list_Car(scan2))); term_RplacArgumentList(term1, term_CopyTermList(term_ArgumentList(list_Car(scan2)))); done = TRUE; } } } else if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } vec_SetMax(bottom); } static TERM cnf_MakeSkolemFunction(LIST varlist, PRECEDENCE Precedence) /************************************************************** INPUT: A list of variables and a precedence. RETURNS: The new term oskf... (oskc...) which is a function with varlist as arguments. EFFECT: The precedence of the new Skolem function is set in . ***************************************************************/ { TERM term; SYMBOL skolem; skolem = symbol_CreateSkolemFunction(list_Length(varlist), Precedence); term = term_Create(skolem, term_CopyTermList(varlist)); return term; } static void cnf_PopAllQuantifier(TERM term) /******************************************************** INPUT: A term whose top symbol is fol_all. RETURNS: Nothing. EFFECT: Removes the quantifier ********************************************************/ { TERM SubTerm; LIST VarList; #ifdef CHECK if (!symbol_Equal(term_TopSymbol(term), fol_All())) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_PopAllQuantifier: Top symbol is not fol_All !\n"); misc_FinishErrorReport(); } #endif VarList = term_ArgumentList(term_FirstArgument(term)); term_DeleteTermList(VarList); term_Free(term_FirstArgument(term)); SubTerm = term_SecondArgument(term); list_Delete(term_ArgumentList(term)); term_RplacTop(term,term_TopSymbol(SubTerm)); term_RplacArgumentList(term,term_ArgumentList(SubTerm)); term_Free(SubTerm); } static TERM cnf_QuantifyAndNegate(TERM term, LIST VarList, LIST FreeList) /**************************************************************** INPUT: A term, a list of variables to be exist-quantified, a list of variables to be all-quantified RETURNS: not(forall[FreeList](exists[VarList](term))) MEMORY: The term, the lists and their arguments are copied. ***************************************************************/ { TERM Result; TERM TermCopy; LIST VarListCopy; LIST FreeListCopy; TermCopy = term_Copy(term); VarListCopy = term_CopyTermList(VarList); Result = fol_CreateQuantifier(fol_Exist(),VarListCopy,list_List(TermCopy)); FreeListCopy = list_Nil(); FreeList = fol_FreeVariables(Result); if (!list_Empty(FreeList)) { FreeListCopy = term_CopyTermList(FreeList); list_Delete(FreeList); Result = fol_CreateQuantifier(fol_All(), FreeListCopy, list_List(Result)); } Result = term_Create(fol_Not(), list_List(Result)); return Result; } static TERM cnf_MoveProvedTermToTopLevel(TERM Term, TERM Term1, TERM Proved, LIST VarList, LIST FreeList, PRECEDENCE Precedence) /******************************************************************** INPUT: A top-level term, which must be a conjunction, a subterm of , a subterm of , a list of existence quantified variables , a list of free variables and a precedence. is of the form exists[...](t1 and t2 and ... and Proved and ..) RETURNS: A new term, where is removed from the arguments of . EFFECT: The precedence of new Skolem functions is set in *******************************************************************/ { TERM termR; TERM skolemfunction; SYMBOL varsymb; LIST scan; termR = term_SecondArgument(Term1); /* t1 and t2 and ... and Proved ... */ term_RplacArgumentList(termR, list_PointerDeleteElement(term_ArgumentList(termR), Proved)); if (list_Length(term_ArgumentList(termR)) < 2) { TERM termRL = term_FirstArgument(termR); /* t1 */ list_Delete(term_ArgumentList(termR)); term_RplacTop(termR, term_TopSymbol(termRL)); term_RplacArgumentList(termR,term_ArgumentList(termRL)); term_Free(termRL); } for (scan = VarList; scan != list_Nil(); scan = list_Cdr(scan)) { varsymb = term_TopSymbol(list_Car(scan)); skolemfunction = cnf_MakeSkolemFunction(FreeList, Precedence); cnf_RplacVarsymbFunction(termR,varsymb,skolemfunction); cnf_RplacVarsymbFunction(Proved,varsymb,skolemfunction); term_Delete(skolemfunction); } if (!list_Empty(FreeList)) { Proved = fol_CreateQuantifier(fol_All(), term_CopyTermList(FreeList), list_List(Proved)); if (list_Length(FreeList) > 1) Proved = cnf_QuantMakeOneVar(Proved); } term_Delete(term_FirstArgument(Term1)); /* Variables of "exists" */ list_Delete(term_ArgumentList(Term1)); term_RplacTop(Term1,term_TopSymbol(termR)); term_RplacArgumentList(Term1,term_ArgumentList(termR)); term_Free(termR); term_RplacArgumentList(Term, list_Cons(Proved, term_ArgumentList(Term))); return Proved; } static void cnf_Skolemize(TERM Term, LIST FreeList, PRECEDENCE Precedence) /******************************************************** INPUT: A existence quantified term, the list of free variables and a precedence. RETURNS: Nothing. EFFECT: The term is destructively changed, i.e. the existence quantifier is removed by skolemization. The precedence of new Skolem functions is set in . *********************************************************/ { LIST exlist; TERM subterm; LIST symblist; symblist = list_Nil(); exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); term_Delete(term_FirstArgument(Term)); subterm = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(subterm)); term_RplacArgumentList(Term,term_ArgumentList(subterm)); term_Free(subterm); symblist = cnf_SkolemFunctionFormula(Term, FreeList, exlist, Precedence); list_Delete(exlist); list_Delete(symblist); } static LIST cnf_FreeVariablesBut(TERM Term, LIST Symbols) /******************************************************** INPUT: A term and a list of symbols RETURNS: A list of all free variable terms in Term whose symbols are not in Symbols *********************************************************/ { LIST follist, Scan; follist = fol_FreeVariables(Term); for (Scan = follist; !list_Empty(Scan); Scan = list_Cdr(Scan)) if (list_Member(Symbols, (POINTER)term_TopSymbol(list_Car(Scan)), (BOOL (*)(POINTER,POINTER))symbol_Equal)) list_Rplaca(Scan,NULL); follist = list_PointerDeleteElement(follist,NULL); return follist; } static void cnf_SkolemFunctionFormulaMapped(TERM term, LIST allist, LIST map) /************************************************************** INPUT: A term term and a list allist of variables and a list map of pairs (variable symbols, function symbol) RETURNS: None. CAUTION: The term is destructively changed. All variable symbols in map which appear in term are replaced by the skolem functions with respect to allist which contains the universally quantified variables. ***************************************************************/ { TERM term1; LIST scan,scan1; SYMBOL skolem, symbol; int bottom; bottom = vec_ActMax(); for (scan1=map; !list_Empty(scan1); scan1=list_Cdr(scan1)) { vec_Push(term); symbol = (SYMBOL) list_PairFirst((LIST) list_Car(scan1)); skolem = (SYMBOL) list_PairSecond((LIST) list_Car(scan1)); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nVariable : ", stdout); symbol_Print(symbol); fputs("\nFunction : ", stdout); symbol_Print(skolem); } #endif while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),symbol)) { term_RplacTop(term1,skolem); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(allist)); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { vec_Push(list_Car(scan)); } } } vec_SetMax(bottom); } static BOOL cnf_HasDeeperVariable(LIST List1, LIST List2) /****************************************************************** INPUT: Two lists of variable terms RETURNS: TRUE if a variable in the first list is deeper than all variables in the second list, FALSE otherwise. NOTE: If cnf_VARIABLEDEPTHARRAY is not allocated this will crash If new variables are introduced by strong skolemization, their depth is -1. *******************************************************************/ { LIST scan; int maxdepth1; /* Determine maximum depth of variables in List1 */ maxdepth1 = 0; for (scan=List1; !list_Empty(scan); scan=list_Cdr(scan)) { int i; i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nFor variable ", stdout); symbol_Print(term_TopSymbol((TERM) list_Car(scan))); printf(" depth is %d.", i); } #endif if (i > maxdepth1) maxdepth1 = i; } /* Compare with depth of variables in List2 */ for (scan=List2; !list_Empty(scan); scan=list_Cdr(scan)) { int i; i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nFor variable ", stdout); symbol_Print(term_TopSymbol((TERM) list_Car(scan))); printf(" depth is %d.", i); } #endif if (i >= maxdepth1) return FALSE; } return TRUE; } static void cnf_StrongSkolemization(PROOFSEARCH Search, TERM Topterm, char* Toplabel, BOOL TopAnd, TERM Term, LIST* UsedTerms, LIST* Symblist, BOOL Result1, HASH InputClauseToTermLabellist, int Depth) /****************************************************************** INPUT: An existence quantified formula. ??? EK RETURNS: Nothing. EFFECT: The existence quantifier is removed by strong skolemization. The precedence of new Skolem symbols is set in the precedence of the search object. *******************************************************************/ { LIST exlist; /* Variable symbols bound by exists[]() */ LIST pairlist; /* List of pairs (Subterm of AND, free variable symbols not in exlist) */ LIST allfreevariables; LIST newvariables; /* w2..wn*/ LIST mapping; /* List of pairs */ int numberofallfreevariables, acc_length, i; LIST pair, pairscan, pairscan_pred, scan, accumulatedvariables; TERM subterm, w; BOOL strskolemsuccess; /* Indicates whether strong skolemization was possible */ FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* Necessary so that new variables really are new ! */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) symbol_SetStandardVarCounter(term_MaxVar(Topterm)); /* Get list of quantified variable symbols x_k */ exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); /* Pop quantifier */ term_Delete(term_FirstArgument(Term)); subterm = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(subterm)); term_RplacArgumentList(Term,term_ArgumentList(subterm)); term_Free(subterm); /* Now for every argument get the list of free variables whose symbols are not in exlist */ pairlist = list_Nil(); for (scan=term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { pair = list_PairCreate((TERM) list_Car(scan), cnf_FreeVariablesBut((TERM) list_Car(scan), exlist)); if (list_Empty(pairlist)) pairlist = list_List(pair); else { /* First sort subterms by number of free variables */ int pairlength, currentlength; pairlength = list_Length((LIST) list_PairSecond(pair)); pairscan = pairlist; pairscan_pred = list_Nil(); currentlength = 0; while (!list_Empty(pairscan)) { currentlength = list_Length((LIST) list_PairSecond((LIST) list_Car(pairscan))); if (currentlength < pairlength) { pairscan_pred = pairscan; pairscan = list_Cdr(pairscan); } else if (currentlength == pairlength) { /* If both subterms have the same number of free variables compare depth of variables */ if (cnf_HasDeeperVariable((LIST) list_PairSecond((LIST) list_Car(pairscan)), /* in list */ (LIST) list_PairSecond(pair))) { /* new pair */ #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nTerm ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\n has deeper variable than ", stdout); term_Print((TERM) list_PairFirst(pair)); } #endif pairscan_pred = pairscan; pairscan = list_Cdr(pairscan); } else break; } else break; } /* New pair has more variables than all others in list */ if (list_Empty(pairscan)) list_Rplacd(pairscan_pred, list_List(pair)); /* New pair is inserted between pairscan_pred and pairscan */ else if (currentlength >= pairlength) { /* Head of list */ if (list_Empty(pairscan_pred)) pairlist = list_Cons(pair, pairlist); else list_InsertNext(pairscan_pred, pair); } /* The case for the same number of variables is not yet implemented */ } } #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { for (pairscan=pairlist; !list_Empty(pairscan); pairscan = list_Cdr(pairscan)) { LIST l; fputs("\nSubterm ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\n has free variables ", stdout); for (l=(LIST) list_PairSecond((LIST) list_Car(pairscan)); !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } } #endif /* Determine number of all free variablein and()--term whose symbols are not in exlist */ /* Create map from ex_variables tp skolem symbols */ allfreevariables = cnf_FreeVariablesBut(Term, exlist); numberofallfreevariables = list_Length(allfreevariables); mapping = list_Nil(); for (scan = exlist; !list_Empty(scan); scan = list_Cdr(scan)) { SYMBOL skolem; skolem = symbol_CreateSkolemFunction(numberofallfreevariables, Precedence); *Symblist = list_Cons((POINTER)skolem,*Symblist); mapping = list_Cons(list_PairCreate(list_Car(scan), (POINTER)skolem), mapping); } list_Delete(allfreevariables); /* Create new variables */ newvariables = list_Nil(); for (i=0; i < numberofallfreevariables; i++) { w = term_CreateStandardVariable(); newvariables = list_Cons(w, newvariables); } #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { LIST l; fputs("\nNew variables : ", stdout); for (l=newvariables; !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } #endif /* Now do the replacing */ accumulatedvariables = list_Nil(); acc_length = 0; strskolemsuccess = FALSE; for (pairscan=pairlist; !list_Empty(pairscan); pairscan=list_Cdr(pairscan)) { LIST allist; /* Add bound variables for this subterm */ accumulatedvariables = list_Nconc(accumulatedvariables, (LIST) list_PairSecond((LIST) list_Car(pairscan))); accumulatedvariables = term_DeleteDuplicatesFromList(accumulatedvariables); /* Remove new variables not (no longer) needed */ for (i=0; i < list_Length(accumulatedvariables) - acc_length; i++) { term_Delete((TERM) list_Top(newvariables)); newvariables = list_Pop(newvariables); } acc_length = list_Length(accumulatedvariables); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { LIST l; fputs("\n\nSubterm is ", stdout); term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); fputs("\nFree variables : ", stdout); for (l=accumulatedvariables; !list_Empty(l); l = list_Cdr(l)) { term_Print((TERM) list_Car(l)); fputs(" ", stdout); } } #endif if (!list_Empty(newvariables)) strskolemsuccess = TRUE; allist = list_Nconc(list_Copy(accumulatedvariables), list_Copy(newvariables)); cnf_SkolemFunctionFormulaMapped((TERM) list_PairFirst((LIST) list_Car(pairscan)), allist, mapping); #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(flag_PSTRSKOLEM)) { fputs("\nSubterm after skolemization : ", stdout); term_Print(list_PairFirst((LIST) list_Car(pairscan))); } #endif list_Delete(allist); cnf_OptimizedSkolemFormula(Search, Topterm, Toplabel, TopAnd, (TERM) list_PairFirst((LIST) list_Car(pairscan)), UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } while (!list_Empty(newvariables)) { term_Delete((TERM) list_Top(newvariables)); newvariables = list_Pop(newvariables); } list_Delete(accumulatedvariables); /* Only pairs and pairlist left */ list_DeletePairList(pairlist); list_Delete(exlist); list_DeletePairList(mapping); if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM) && strskolemsuccess) { fputs("\nStrong skolemization applied", stdout); } } static void cnf_OptimizedSkolemFormula(PROOFSEARCH Search, TERM topterm, char* toplabel, BOOL TopAnd, TERM term, LIST* UsedTerms, LIST* Symblist, BOOL Result1, HASH InputClauseToTermLabellist, int Depth) /************************************************************** INPUT: Two terms in negation normal form. ??? EK RETURNS: The skolemized term with the optimized skolemization due to Ohlbach and Weidenbach of and further improvements. is used as additional, conjunctively added information. EFFECT: The symbol precedence of the search object is changed because new Skolem symbols are defined. Checks the clock cnf_REDUCTION with respect to the value of flag_CNFREDTIME to permit optimized Skolemization steps. CAUTION: The term is destructively changed. ***************************************************************/ { TERM termL2, provedterm; LIST freevariables, scan, varlist; SYMBOL top; BOOL result2; BOOL optimized; FLAGSTORE Flags; PRECEDENCE Precedence; result2 = FALSE; freevariables = list_Nil(); Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); top = term_TopSymbol(term); if (fol_IsQuantifier(top)) { if (symbol_Equal(top,fol_All())) { /* For quantified variables store depth if strong skolemization is performed */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { LIST variables; variables = term_ArgumentList(term_FirstArgument(term)); for (scan=variables; !list_Empty(scan); scan=list_Cdr(scan)) { #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { if (cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] != -1) { fputs("\nFor variable ", stderr); term_Print((TERM) list_Car(scan)); printf(" depth is already set to %d, now setting it to %d", cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))],Depth); } } #endif #ifdef CHECK_STRSKOLEM if (flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nVariable ", stdout); term_Print((TERM) list_Car(scan)); printf(" has depth %d in term\n ", Depth); term_Print(term); } #endif cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] = Depth; } Depth++; } cnf_PopAllQuantifier(term); cnf_OptimizedSkolemFormula(Search,topterm, toplabel, TopAnd, term, UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); return; } freevariables = fol_FreeVariables(term); optimized = FALSE; if (symbol_Equal(term_TopSymbol(term_SecondArgument(term)), fol_And())) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM)) { scan = term_ArgumentList(term_SecondArgument(term)); varlist = term_ArgumentList(term_FirstArgument(term)); while (!list_Empty(scan) && !optimized) { if (!Result1) { if (TopAnd) { if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nHaveProof not necessary", stdout); } result2 = TRUE; } else { termL2 = cnf_QuantifyAndNegate((TERM) list_Car(scan), varlist, freevariables); result2 = cnf_HaveProofOptSkolem(Search, topterm, toplabel, termL2, UsedTerms, Symblist, InputClauseToTermLabellist); if (flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) != flag_CNFREDTIMELIMITUNLIMITED && flag_GetFlagIntValue(Flags,flag_CNFREDTIMELIMIT) <= ceil(clock_GetSeconds(clock_CNFREDUCTION))) flag_SetFlagIntValue(Flags, flag_CNFOPTSKOLEM, flag_OFF); #ifdef CHECK_OPTSKOLEM if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nHaveProof result : ", stdout); if (result2) fputs("TRUE", stdout); else fputs("FALSE", stdout); } #endif } } if (Result1 || result2) { optimized = TRUE; if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("\nIn term ", stdout); term_Print(topterm); fputs("\n subterm ", stdout); term_Print((TERM) list_Car(scan)); puts(" is moved to toplevel."); } provedterm = cnf_MoveProvedTermToTopLevel(topterm, term, list_Car(scan), varlist, freevariables, Precedence); if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM)) { fputs("Result : ", stdout); term_Print(topterm); putchar('\n'); } /* provedterm is argument of top AND term */ cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TRUE, provedterm,UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } else scan = list_Cdr(scan); } } if (!optimized) { /* Optimized skolemization not enabled or not possible */ if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { optimized = TRUE; /* Strong Skolemization is always possible after exists[..](and(..)) */ cnf_StrongSkolemization(Search, topterm, toplabel, TopAnd, term, UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } } } else TopAnd = FALSE; if (!optimized) { /* Optimized skolemization not enabled or not possible */ /* Strong skolemization not enabled or not possible */ cnf_Skolemize(term, freevariables, Precedence); } list_Delete(freevariables); cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, term,UsedTerms, Symblist,Result1,InputClauseToTermLabellist,Depth); return; } else { if (symbol_Equal(top,fol_And()) || symbol_Equal(top,fol_Or())) { if (symbol_Equal(top,fol_Or())) TopAnd = FALSE; for (scan=term_ArgumentList(term);!list_Empty(scan); scan=list_Cdr(scan)) cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, (TERM) list_Car(scan), UsedTerms, Symblist, Result1, InputClauseToTermLabellist, Depth); } } return; } static LIST cnf_SkolemFunctionFormula(TERM term, LIST allist, LIST exlist, PRECEDENCE Precedence) /************************************************************** INPUT: A term , a list of variables, a list of variable symbols and a precedence. RETURNS: The list of new Skolem functions. EFFECT: The term is destructively changed. All variable symbols in which appear in are replaced by skolem functions with respect to which contains the universally quantified variables. New Skolem functions are created and their precedence is set in . ***************************************************************/ { TERM term1; LIST scan, scan1, Result; SYMBOL skolem; int bottom,n; Result = list_Nil(); bottom = vec_ActMax(); n = list_Length(allist); for (scan1=exlist; !list_Empty(scan1); scan1=list_Cdr(scan1)) { vec_Push(term); skolem = symbol_CreateSkolemFunction(n, Precedence); Result = list_Cons((POINTER)skolem, Result); while (bottom != vec_ActMax()) { term1 = (TERM)vec_PopResult(); if (symbol_Equal(term_TopSymbol(term1),(SYMBOL)list_Car(scan1))) { term_RplacTop(term1,skolem); list_Delete(term_ArgumentList(term1)); term_RplacArgumentList(term1,term_CopyTermList(allist)); } if (!list_Empty(term_ArgumentList(term1))) for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) vec_Push(list_Car(scan)); } } vec_SetMax(bottom); return Result; } static LIST cnf_OptimizedSkolemization(PROOFSEARCH Search, TERM Term, char* Label, LIST* UsedTerms, LIST* Symblist, BOOL result, BOOL Conjecture, HASH InputClauseToTermLabellist) /************************************************************** INPUT: A term, a shared index and a list of non-ConClauses. ??? EK RETURNS: The list of clauses derived from Term. EFFECT: The term is skolemized using optimized skolemization wrt ShIndex. **************************************************************/ { LIST Clauses; TERM FirstArg; int i; FLAGSTORE Flags; PRECEDENCE Precedence; #ifdef CHECK if (Term == NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_OptimizedSkolemization: Input term is NULL.\n"); misc_FinishErrorReport(); } #endif Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); FirstArg = Term; if (flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { /* Initializing array */ for (i = 1; i <= symbol__MAXSTANDARDVAR; i++) cnf_VARIABLEDEPTHARRAY[i] = -1; } if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nTerm before skolemization : \n ", stdout); fol_PrettyPrintDFG(Term); } if (!fol_IsLiteral(Term)) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_CNFSTRSKOLEM)) { if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM)) Term = term_Create(fol_And(), list_List(Term)); /* CW hack: definitions are added on top level*/ cnf_OptimizedSkolemFormula(Search, Term, Label, TRUE, FirstArg, UsedTerms, Symblist, result, InputClauseToTermLabellist, 0); } else { LIST Symbols; Symbols = list_Nil(); Term = cnf_SkolemFormula(Term, Flags, Precedence, &Symbols); list_Delete(Symbols); } } if (flag_GetFlagIntValue(Flags, flag_POPTSKOLEM) || flag_GetFlagIntValue(Flags, flag_PSTRSKOLEM)) { fputs("\nTerm after skolemization : ", stdout); term_Print(Term); } Term = cnf_DistributiveFormula(Term); Clauses = cnf_MakeClauseList(Term, FALSE, Conjecture, Flags, Precedence); term_Delete(Term); return Clauses; } LIST cnf_GetSkolemFunctions(TERM Term, LIST ArgList, LIST* SkolToExVar) /************************************************************** INPUT: A term, the argumentlist of a skolem function, a mapping from a skolem function to a variable RETURNS: The longest argumentlist of all skolem functions found so far. EFFECT: Computes information for renaming variables and replacing skolem functions during de-skolemization. **************************************************************/ { LIST Scan; SYMBOL Top; Top = term_TopSymbol(Term); if (fol_IsQuantifier(Top)) return cnf_GetSkolemFunctions(term_SecondArgument(Term), ArgList, SkolToExVar); if (symbol_IsFunction(Top) && symbol_HasProperty(Top, SKOLEM)) { BOOL found; SYMBOL Var = 0; int Arity; found = FALSE; /* Keep longest argument list of all skolem functions in the clause for renaming */ /* Delete all other argument lists */ Arity = list_Length(term_ArgumentList(Term)); if (Arity > list_Length(ArgList)) { term_DeleteTermList(ArgList); ArgList = term_ArgumentList(Term); } else term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, NULL); /* Replace skolem function by variable */ if (list_Length(*SkolToExVar) > Arity) { NAT i; LIST SkolScan = *SkolToExVar; for (i = 0; i < Arity; i++) SkolScan = list_Cdr(SkolScan); for (SkolScan = (LIST) list_Car(SkolScan); (SkolScan != list_Nil()) && !found; SkolScan = list_Cdr(SkolScan)) { SYMBOL Skol; Skol = (SYMBOL) list_PairFirst((LIST) list_Car(SkolScan)); if (Skol == term_TopSymbol(Term)) { Var = (SYMBOL) list_PairSecond((LIST) list_Car(SkolScan)); found = TRUE; } } } if (!found) { LIST Pair; NAT i; LIST SkolScan; SkolScan = *SkolToExVar; for (i = 0; i < Arity; i++) { if (list_Cdr(SkolScan) == list_Nil()) list_Rplacd(SkolScan, list_List(NULL)); SkolScan = list_Cdr(SkolScan); } Var = symbol_CreateStandardVariable(); Pair = list_PairCreate((POINTER) term_TopSymbol(Term), (POINTER) Var); if (list_Car(SkolScan) == list_Nil()) list_Rplaca(SkolScan, list_List(Pair)); else list_Rplaca(SkolScan, list_Nconc((LIST) list_Car(SkolScan), list_List(Pair))); } term_RplacTop(Term, Var); } else { for (Scan = term_ArgumentList(Term); Scan != list_Nil(); Scan = list_Cdr(Scan)) ArgList = cnf_GetSkolemFunctions((TERM) list_Car(Scan), ArgList, SkolToExVar); } return ArgList; } void cnf_ReplaceVariable(TERM Term, SYMBOL Old, SYMBOL New) /************************************************************** INPUT: A term, two symbols that are variables EFFECT: In term every occurrence of Old is replaced by New **************************************************************/ { LIST Scan; #ifdef CHECK if (!symbol_IsVariable(Old)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_ReplaceVariable: Illegal input symbol.\n"); misc_FinishErrorReport(); } #endif if (symbol_Equal(term_TopSymbol(Term), Old)) term_RplacTop(Term, New); else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) cnf_ReplaceVariable(list_Car(Scan), Old, New); } LIST cnf_RemoveSkolemFunctions(CLAUSE Clause, LIST* SkolToExVar, LIST Vars) /************************************************************** INPUT: A clause, a list which is a mapping from skolem functions to variables and a list of variables for forall-quantification. RETURNS: A list of terms derived from the clause using deskolemization EFFECT: Arguments of skolem functions are renamed consistently. Skolemfunctions are replaced by variables. **************************************************************/ { LIST Scan; LIST TermScan, TermList, ArgList; TERM Term; int i; TermList = list_Nil(); ArgList = list_Nil(); for (i = 0; i < clause_Length(Clause); i++) { Term = term_Copy(clause_GetLiteralTerm(Clause, i)); ArgList = cnf_GetSkolemFunctions(Term, ArgList, SkolToExVar); TermList = list_Cons(Term, TermList); } if (list_Empty(ArgList)) return TermList; /* Rename variables */ for (Scan = ArgList; Scan != list_Nil(); Scan = list_Cdr(Scan)) { for (TermScan = TermList; TermScan != list_Nil(); TermScan = list_Cdr(TermScan)) { Term = (TERM) list_Car(TermScan); cnf_ReplaceVariable(Term, term_TopSymbol((TERM) list_Car(Scan)), (SYMBOL) list_Car(Vars)); } if (list_Cdr(Vars) == list_Nil()) { SYMBOL New = symbol_CreateStandardVariable(); Vars = list_Nconc(Vars, list_List((POINTER) New)); } Vars = list_Cdr(Vars); } term_DeleteTermList(ArgList); return TermList; } TERM cnf_DeSkolemFormula(LIST Clauses) /************************************************************** INPUT: A list of clauses. RETURNS: A formula built from the clauses. EFFECT: All skolem functions are removed from the clauses. **************************************************************/ { LIST Scan, SkolToExVar, Vars, FreeVars, FreeVarsCopy, VarScan, TermList; TERM VarListTerm, TopTerm, Term; BOOL First; SkolToExVar = list_List(NULL); Vars = list_List((POINTER) symbol_CreateStandardVariable()); TopTerm = term_Create(fol_And(), NULL); for (Scan = Clauses; Scan != list_Nil(); Scan = list_Cdr(Scan)) { TermList = cnf_RemoveSkolemFunctions((CLAUSE) list_Car(Scan), &SkolToExVar, Vars); Term = term_Create(fol_Or(), TermList); FreeVars = fol_FreeVariables(Term); if (!list_Empty(FreeVars)) { FreeVarsCopy = term_CopyTermList(FreeVars); list_Delete(FreeVars); Term = fol_CreateQuantifier(fol_All(), FreeVarsCopy, list_List(Term)); } term_RplacArgumentList(TopTerm, list_Cons(Term, term_ArgumentList(TopTerm))); } VarScan = Vars; First = TRUE; for (Scan = SkolToExVar; Scan != list_Nil(); Scan = list_Cdr(Scan)) { if (list_Empty(list_Car(Scan))) { if (term_TopSymbol(TopTerm) == fol_All()) term_RplacArgumentList(TopTerm, list_Cons(term_Create((SYMBOL) list_Car(VarScan), NULL), term_ArgumentList(TopTerm))); if (!First) TopTerm = fol_CreateQuantifier(fol_All(), list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), list_List(TopTerm)); } else { LIST ExVarScan; LIST ExVars = list_Nil(); for (ExVarScan = list_Car(Scan); ExVarScan != list_Nil(); ExVarScan = list_Cdr(ExVarScan)) { if (ExVars == list_Nil()) ExVars = list_List(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL)); else ExVars = list_Cons(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL), ExVars); list_PairFree((LIST) list_Car(ExVarScan)); } list_Delete((LIST) list_Car(Scan)); list_Rplaca(Scan, NULL); if (term_TopSymbol(TopTerm) == fol_Exist()) { VarListTerm = (TERM) list_Car(term_ArgumentList(TopTerm)); term_RplacArgumentList(VarListTerm, list_Nconc(term_ArgumentList(VarListTerm), ExVars)); } else TopTerm = fol_CreateQuantifier(fol_Exist(), ExVars, list_List(TopTerm)); ExVars = list_Nil(); if (!First) TopTerm = fol_CreateQuantifier(fol_All(), list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), list_List(TopTerm)); } if (!First) VarScan = list_Cdr(VarScan); else First = FALSE; } list_Delete(SkolToExVar); list_Delete(Vars); return TopTerm; } #ifdef OPTCHECK /* Currently unused */ /*static */ LIST cnf_CheckOptimizedSkolemization(LIST* AxClauses, LIST* ConClauses, TERM AxTerm, TERM ConTerm, LIST NonConClauses, LIST* SkolemPredicates, SHARED_INDEX ShIndex, BOOL result) /********************************************************** EFFECT: Used to check the correctness of optimized skolemization ***********************************************************/ { TERM DeSkolemizedAxOpt, DeSkolemizedConOpt, DeSkolemizedAx, DeSkolemizedCon; TERM TopOpt, Top, ToProve; LIST SkolemFunctions2; if (*AxClauses != list_Nil()) { DeSkolemizedAxOpt = cnf_DeSkolemFormula(*AxClauses); if (*ConClauses != list_Nil()) { DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); TopOpt = term_Create(fol_And(), list_Cons(DeSkolemizedAxOpt, list_List(DeSkolemizedConOpt))); } else TopOpt = DeSkolemizedAxOpt; } else { DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); TopOpt = DeSkolemizedConOpt; } clause_DeleteClauseList(*AxClauses); clause_DeleteClauseList(*ConClauses); *AxClauses = list_Nil(); *ConClauses = list_Nil(); flag_SetFlagIntValue(flag_CNFOPTSKOLEM, flag_CNFOPTSKOLEMOFF); if (AxTerm) { *AxClauses = cnf_OptimizedSkolemization(term_Copy(AxTerm), ShIndex, NonConClauses, result,FALSE, ClauseToTermLabellist); } if (ConTerm) { *ConClauses = cnf_OptimizedSkolemization(term_Copy(ConTerm), ShIndex, NonConClauses, result,TRUE, ClauseToTermLabellist); } if (*AxClauses != list_Nil()) { DeSkolemizedAx = cnf_DeSkolemFormula(*AxClauses); if (*ConClauses != list_Nil()) { DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); Top = term_Create(fol_And(), list_Cons(DeSkolemizedAx, list_List(DeSkolemizedCon))); } else Top = DeSkolemizedAx; } else { DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); Top = DeSkolemizedCon; } clause_DeleteClauseList(*AxClauses); clause_DeleteClausList(*ConClauses); *AxClauses = list_Nil(); *ConClauses = list_Nil(); ToProve = term_Create(fol_Equiv(), list_Cons(TopOpt, list_List(Top))); ToProve = term_Create(fol_Not(), list_List(ToProve)); fol_NormalizeVars(ToProve); ToProve = cnf_ObviousSimplifications(ToProve); term_AddFatherLinks(ToProve); ToProve = ren_Rename(ToProve,SkolemPredicates,FALSE); ToProve = cnf_RemoveEquivImplFromFormula(ToProve); ToProve = cnf_NegationNormalFormula(ToProve); ToProve = cnf_AntiPrenex(ToProve); SkolemFunctions2 = list_Nil(); ToProve = cnf_SkolemFormula(ToProve, &SkolemFunctions2); ToProve = cnf_DistributiveFormula(ToProve); *ConClauses = cnf_MakeClauseList(ToProve); if (ToProve) term_Delete(ToProve); *AxClauses = list_Nil(); return SkolemFunctions2; } #endif PROOFSEARCH cnf_Flotter(LIST AxiomList, LIST ConjectureList, LIST* AxClauses, LIST* AllLabels, HASH TermLabelToClauselist, HASH ClauseToTermLabellist, FLAGSTORE InputFlags, PRECEDENCE InputPrecedence, LIST* Symblist) /************************************************************** INPUT: A list of axiom formulae, a list of conjecture formulae, a pointer to a list in which clauses derived from axiom formulae are stored, a pointer to a list in which clauses derived from conjecture formulae are stored, ??? a pointer to a list of all termlabels, a hasharray in which for every term label the list of clauses derived from the term is stored (if DocProof is set), a hasharray in which for every clause the list of labels of the terms used for deriving the clause is stored (if DocProof is set), a flag store, a precedence a pointer to a list of symbols which have to be deleted later if the ProofSearch object is kept. RETURNS: If KeepProofSearch ??? is TRUE, then the ProofSearch object is not freed but returned. Else, NULL is returned. EFFECT: Initializes and checks the clock_CNFREDUCTION clock with respect to the flag_CNFREDTIME value for usable reduction time including optimized Skolemization, condensing and subsumption testing. The precedence of new skolem symbols is set in . ***************************************************************/ { LIST Scan, Scan2, FormulaClauses,SkolemFunctions; LIST SkolemPredicates, EmptyClauses, AllFormulae; LIST UsedTerms; TERM AxTerm,Formula; BOOL Result; PROOFSEARCH Search; PRECEDENCE Precedence; FLAGSTORE Flags; NAT Count; HASH InputClauseToTermLabellist; clock_InitCounter(clock_CNFREDUCTION); Search = prfs_Create(); /* Initialize the flagstore for the CNF transformation */ Flags = prfs_Store(Search); flag_CleanStore(Flags); flag_InitFlotterFlags(InputFlags, Flags); /* Initialize the precedence */ Precedence = prfs_Precedence(Search); symbol_TransferPrecedence(InputPrecedence, Precedence); if (flag_GetFlagIntValue(Flags, flag_DOCPROOF)) prfs_AddDocProofSharingIndex(Search); AxTerm = (TERM)NULL; SkolemPredicates = list_Nil(); Result = FALSE; if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) InputClauseToTermLabellist = hsh_Create(); else InputClauseToTermLabellist = NULL; symbol_ReinitGenericNameCounters(); for (Scan = AxiomList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Pair; Pair = list_Car(Scan); AxTerm = (TERM) list_PairSecond(Pair); fol_RemoveImplied(AxTerm); AxTerm = fol_RemoveXorNorNand(AxTerm); term_AddFatherLinks(AxTerm); fol_NormalizeVars(AxTerm); if (flag_GetFlagIntValue(Flags, flag_CNFFEQREDUCTIONS)) cnf_PropagateSubstEquations(AxTerm); AxTerm = cnf_ObviousSimplifications(AxTerm); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(AxTerm); AxTerm = ren_Rename(AxTerm, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } AxTerm = cnf_RemoveEquivImplFromFormula(AxTerm); AxTerm = cnf_NegationNormalFormula(AxTerm); AxTerm = cnf_AntiPrenex(AxTerm); list_Rplacd(Pair, (LIST) AxTerm); } AllFormulae = AxiomList; /* At this point the list contains max. 1 element, which is a pair of the label NULL and the negated conjunction of all conjecture formulae. */ Count = 0; for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { TERM ConTerm; char* Label; char buf[100]; /* Add label */ if (list_PairFirst(list_Car(Scan)) == NULL) { sprintf(buf, "conjecture%d", Count); Label = string_StringCopy(buf); list_Rplaca((LIST) list_Car(Scan), Label); if ((flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) && flag_GetFlagIntValue(Flags, flag_PLABELS)) { printf("\nAdded label %s for conjecture", Label); fol_PrettyPrintDFG((TERM) list_PairSecond(list_Car(Scan))); } } ConTerm = (TERM) list_PairSecond((LIST) list_Car(Scan)); fol_RemoveImplied(ConTerm); ConTerm = fol_RemoveXorNorNand(ConTerm); term_AddFatherLinks(ConTerm); fol_NormalizeVars(ConTerm); if (flag_GetFlagIntValue(Flags, flag_CNFFEQREDUCTIONS)) cnf_PropagateSubstEquations(ConTerm); ConTerm = cnf_ObviousSimplifications(ConTerm); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(ConTerm); ConTerm = ren_Rename(ConTerm, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } /* fputs("\nRen:\t",stdout);term_Print(ConTerm);putchar('\n'); */ ConTerm = cnf_RemoveEquivImplFromFormula(ConTerm); ConTerm = cnf_NegationNormalFormula(ConTerm); /* fputs("\nAn:\t",stdout);term_Print(ConTerm);putchar('\n'); */ ConTerm = cnf_AntiPrenex(ConTerm); /* fputs("\nPr:\t",stdout);term_Print(ConTerm);putchar('\n'); */ /* Insert changed term into pair */ list_Rplacd((LIST) list_Car(Scan), (LIST) ConTerm); Count++; } AllFormulae = list_Append(ConjectureList, AllFormulae); for (Scan = ConjectureList;!list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan,list_PairSecond(list_Car(Scan))); FormulaClauses = list_Nil(); SkolemFunctions = list_Nil(); Count = 0; clock_StartCounter(clock_CNFREDUCTION); if (flag_GetFlagIntValue(Flags, flag_CNFOPTSKOLEM) == flag_ON) { for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan), Count++) { LIST FormulaClausesTemp; Formula = term_Copy((TERM) list_PairSecond(list_Car(Scan))); #ifdef CHECK_CNF fputs("\nInputFormula : ",stdout); term_Print(Formula); printf("\nLabel : %s\n", (char*) list_PairFirst(list_Car(Scan))); #endif Formula = cnf_SkolemFormula(Formula,Flags,Precedence,&SkolemFunctions); Formula = cnf_DistributiveFormula(Formula); FormulaClausesTemp = cnf_MakeClauseList(Formula,FALSE,FALSE,Flags,Precedence); if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) { for (Scan2 = FormulaClausesTemp; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { hsh_Put(InputClauseToTermLabellist, list_Car(Scan2), list_PairFirst(list_Car(Scan))); } } FormulaClauses = list_Nconc(FormulaClauses, FormulaClausesTemp); term_Delete(Formula); } /* red_SatUnit works only on conclauses */ for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); /* For FormulaClauses a full saturation */ /* List is deleted in red_SatUnit ! */ EmptyClauses = red_SatUnit(Search, FormulaClauses); if (!list_Empty(EmptyClauses)) { /* Set now to FALSE because formula clause relationship for subsequent */ /* optimized Skolemization steps is then not properly set. However, this */ /* may cause performance problems */ Result = FALSE; /*puts("\nPROOF in FormulaClauses");*/ clause_DeleteClauseList(EmptyClauses); } /* Move all usables to workedoff */ FormulaClauses = list_Copy(prfs_UsableClauses(Search)); for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) prfs_MoveUsableWorkedOff(Search, (CLAUSE) list_Car(Scan)); list_Delete(FormulaClauses); FormulaClauses = list_Nil(); } #ifdef CHECK /*cnf_CheckClauseListsConsistency(ShIndex); */ #endif *Symblist = list_Nil(); for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Ax, Pair; UsedTerms = list_Nil(); Pair = list_Car(Scan); #ifdef CHECK_CNF fputs("\nFormula : ", stdout); term_Print((TERM) list_PairSecond(Pair)); printf("\nLabel : %s", (char*) list_PairFirst(Pair)); #endif Ax = cnf_OptimizedSkolemization(Search, term_Copy((TERM)list_PairSecond(Pair)), (char*) list_PairFirst(Pair), &UsedTerms, Symblist,Result,FALSE,InputClauseToTermLabellist); clock_StopAddPassedTime(clock_CNFREDUCTION); /* Set CONCLAUSE flag for clauses derived from conjectures */ if (list_PointerMember(ConjectureList,list_PairSecond(Pair))) { LIST l; for (l = Ax; !list_Empty(l); l = list_Cdr(l)) clause_SetFlag((CLAUSE) list_Car(l), CONCLAUSE); } if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) { hsh_PutListWithCompareFunc(TermLabelToClauselist, list_PairFirst(Pair), list_Copy(Ax), (BOOL (*)(POINTER,POINTER))cnf_LabelEqual, (unsigned long (*)(POINTER))hsh_StringHashKey); UsedTerms = list_Cons(list_PairFirst(Pair), UsedTerms); UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); for (Scan2 = Ax; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { hsh_PutList(ClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); hsh_PutList(InputClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); } } *AxClauses = list_Nconc(Ax, *AxClauses); list_Delete(UsedTerms); } /* Transfer precedence of new skolem symbols into */ symbol_TransferPrecedence(Precedence, InputPrecedence); list_Delete(ConjectureList); if (flag_GetFlagIntValue(Flags, flag_DOCPROOF) || flag_GetFlagIntValue(Flags, flag_FLOTTER)) hsh_Delete(InputClauseToTermLabellist); if (!flag_GetFlagIntValue(Flags, flag_INTERACTIVE)) { list_Delete(*Symblist); } *AllLabels = list_Nil(); for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { LIST Pair; Pair = list_Car(Scan); term_Delete((TERM) list_PairSecond(Pair)); *AllLabels = list_Cons(list_PairFirst(Pair), *AllLabels); list_PairFree(Pair); } list_Delete(AllFormulae); list_Delete(SkolemFunctions); list_Delete(SkolemPredicates); if (!flag_GetFlagIntValue(Flags, flag_INTERACTIVE)) { symbol_ResetSkolemIndex(); prfs_Delete(Search); return NULL; } else { /* Delete DocProof clauses */ prfs_DeleteDocProof(Search); return Search; } } LIST cnf_QueryFlotter(PROOFSEARCH Search, TERM Term, LIST* Symblist) /************************************************************** INPUT: A term to derive clauses from, using optimized skolemization, and a ProofSearch object. RETURNS: A list of derived clauses. EFFECT: ??? EK The precedence of new skolem symbols is set in . ***************************************************************/ { LIST SkolemPredicates, SkolemFunctions, IndexedClauses, Scan; LIST ResultClauses, Dummy, EmptyClauses; TERM TermCopy; int Formulae2Clause; BOOL Result; FLAGSTORE Flags, SubProofFlags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* Initialize the flagstore of the cnf_SEARCHCOPY object with default values */ /* and copy the value of flag_DOCPROOF from the global Proofserach object. */ SubProofFlags = prfs_Store(cnf_SEARCHCOPY); flag_InitStoreByDefaults(SubProofFlags); flag_TransferFlag(Flags, SubProofFlags, flag_DOCPROOF); /* Transfer the precedence into the local search object */ symbol_TransferPrecedence(Precedence, prfs_Precedence(cnf_SEARCHCOPY)); SkolemPredicates = SkolemFunctions = list_Nil(); Result = FALSE; prfs_CopyIndices(Search, cnf_SEARCHCOPY); Term = term_Create(fol_Not(), list_List(Term)); fol_NormalizeVars(Term); Term = cnf_ObviousSimplifications(Term); if (flag_GetFlagIntValue(Flags, flag_CNFRENAMING)) { term_AddFatherLinks(Term); Term = ren_Rename(Term, Precedence, &SkolemPredicates, flag_GetFlagIntValue(Flags, flag_CNFPRENAMING), flag_GetFlagIntValue(Flags, flag_CNFRENMATCH), flag_GetFlagIntValue(Flags, flag_CNFRENAMING)); } Term = cnf_RemoveEquivImplFromFormula(Term); Term = cnf_NegationNormalFormula(Term); Term = cnf_AntiPrenex(Term); TermCopy = term_Copy(Term); TermCopy = cnf_SkolemFormula(TermCopy, Flags, Precedence, &SkolemFunctions); TermCopy = cnf_DistributiveFormula(TermCopy); IndexedClauses = cnf_MakeClauseList(TermCopy,FALSE,FALSE,Flags,Precedence); term_Delete(TermCopy); /* red_SatUnit works only on conclauses */ for (Scan = IndexedClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); EmptyClauses = red_SatUnit(cnf_SEARCHCOPY, IndexedClauses); if (!list_Empty(EmptyClauses)) { Result = TRUE; clause_DeleteClauseList(EmptyClauses); } while (!list_Empty(prfs_UsableClauses(cnf_SEARCHCOPY))) { prfs_MoveUsableWorkedOff(cnf_SEARCHCOPY, (CLAUSE) list_Car(prfs_UsableClauses(cnf_SEARCHCOPY))); } /* Works only if DOCPROOF is false. Otherwise we need labels */ Dummy = list_Nil(); if (flag_GetFlagIntValue(SubProofFlags, flag_DOCPROOF)) Formulae2Clause = TRUE; else Formulae2Clause = FALSE; flag_SetFlagIntValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFOFF); ResultClauses = cnf_OptimizedSkolemization(cnf_SEARCHCOPY, term_Copy(Term), NULL, &Dummy, Symblist, Result, FALSE, NULL); if (Formulae2Clause) flag_SetFlagIntValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFON); term_Delete(Term); list_Delete(SkolemPredicates); list_Delete(SkolemFunctions); prfs_Clean(cnf_SEARCHCOPY); /* All result clauses of queries are conjecture clauses */ for (Scan=ResultClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); return ResultClauses; } #ifdef CHECK /* Currently unused */ /*static*/ void cnf_CheckClauseListsConsistency(SHARED_INDEX ShIndex) /************************************************************** INPUT: A shared index and a list of non-ConClauses. EFFECT: When this function is called all clauses in the index must be non-ConClauses, which must also be members of the list. **************************************************************/ { LIST AllClauses, scan; AllClauses = clause_AllIndexedClauses(ShIndex); for (scan = AllClauses; scan != list_Nil(); scan = list_Cdr(scan)) { if (clause_GetFlag((CLAUSE) list_Car(scan), CONCLAUSE)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is a CONCLAUSE.\n"); misc_FinishErrorReport(); } if (clause_GetFlag((CLAUSE) list_Car(scan), BLOCKED)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is BLOCKED.\n"); misc_FinishErrorReport(); } } list_Delete(AllClauses); } #endif static LIST cnf_SatUnit(PROOFSEARCH Search, LIST ClauseList) /********************************************************* INPUT: A list of unshared clauses, proof search object RETURNS: A possibly empty list of empty clauses. **********************************************************/ { CLAUSE Given; LIST Scan, Derivables, EmptyClauses, BackReduced; NAT n, Derived; FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); Derived = flag_GetFlagIntValue(Flags, flag_CNFPROOFSTEPS); EmptyClauses = list_Nil(); ClauseList = clause_ListSortWeighed(ClauseList); while (!list_Empty(ClauseList) && list_Empty(EmptyClauses)) { Given = (CLAUSE)list_NCar(&ClauseList); Given = red_CompleteReductionOnDerivedClause(Search, Given, red_ALL); if (Given) { if (clause_IsEmptyClause(Given)) EmptyClauses = list_List(Given); else { /*fputs("\n\nGiven: ",stdout);clause_Print(Given);*/ BackReduced = red_BackReduction(Search, Given, red_USABLE); if (Derived != 0) { Derivables = inf_BoundedDepthUnitResolution(Given, prfs_UsableSharingIndex(Search), FALSE, Flags, Precedence); Derivables = list_Nconc(Derivables, inf_BoundedDepthUnitResolution(Given,prfs_WorkedOffSharingIndex(Search), FALSE, Flags, Precedence)); n = list_Length(Derivables); if (n > Derived) Derived = 0; else Derived -= n; } else Derivables = list_Nil(); Derivables = list_Nconc(BackReduced,Derivables); Derivables = split_ExtractEmptyClauses(Derivables, &EmptyClauses); prfs_InsertUsableClause(Search, Given); for (Scan = Derivables; !list_Empty(Scan); Scan = list_Cdr(Scan)) ClauseList = clause_InsertWeighed(list_Car(Scan), ClauseList, Flags, Precedence); list_Delete(Derivables); } } } clause_DeleteClauseList(ClauseList); return EmptyClauses; } TERM cnf_DefTargetConvert(TERM Target, TERM ToTopLevel, TERM ToProveDef, LIST DefPredArgs, LIST TargetPredArgs, LIST TargetPredVars, LIST VarsForTopLevel, FLAGSTORE Flags, PRECEDENCE Precedence, BOOL* LocallyTrue) /********************************************************** INPUT: A term Target which contains a predicate that might be replaced by its definition. A term ToTopLevel which is the highest level subterm in Target that contains the predicate and can be moved to top level or(). A term ToProveDef which must hold if the definition is to be applied. (IS DESTROYED AND FREED) A list DefPredArgs of the arguments of the predicate in the Definition. A list TargetPredArgs of the arguments of the predicate in Target. A list TargetPredVars of the variables occurring in the arguments of the predicate in Target. A list VarsForTopLevel containing the variables that should be all-quantified at top level to make the proof easier. A flag store. A pointer to a boolean LocallyTrue which is set to TRUE iff the definition can be applied. RETURNS: The Target term which is brought into standard form. **********************************************************/ { TERM orterm, targettoprove; SYMBOL maxvar; /* For normalizing terms */ LIST l1, l2; LIST freevars, vars; /* Free variables in targettoprove */ if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nTarget :"); fol_PrettyPrint(Target); } #ifdef CHECK fol_CheckFatherLinks(Target); #endif /* No proof found yet */ *LocallyTrue = FALSE; /* Remove implications from path */ Target = cnf_RemoveImplFromFormulaPath(Target, ToTopLevel); /* Move negations as far down as possible */ Target = cnf_NegationNormalFormulaPath(Target, ToTopLevel); /* Move quantifiers as far down as possible */ Target = cnf_AntiPrenexPath(Target, ToTopLevel); /* Move all-quantified variables from the predicates' arguments to top level */ Target = cnf_MovePredicateVariablesUp(Target, ToTopLevel, VarsForTopLevel); /* Flatten top or() */ Target = cnf_FlattenPath(Target, ToTopLevel); /* Now make sure that all variables in the top forall quantifier are in TargetPredVars */ /* Not necessary, according to CW */ if (symbol_Equal(term_TopSymbol(Target), fol_All())) { targettoprove = term_Copy(term_SecondArgument(Target)); orterm = term_SecondArgument(Target); } else { targettoprove = term_Copy(Target); orterm = Target; } /* Find argument of targettoprove that contains the predicate and remove it */ if (symbol_Equal(term_TopSymbol(targettoprove), fol_Or())) { /* Find subterm that contains the predicate */ LIST arglist; arglist = term_ArgumentList(targettoprove); for (l1=arglist, l2=term_ArgumentList(orterm); !list_Empty(l1); l1 = list_Cdr(l1), l2 = list_Cdr(l2)) { if (term_HasProperSuperterm(ToTopLevel, (TERM) list_Car(l2)) || (ToTopLevel == (TERM) list_Car(l2))) { arglist = list_PointerDeleteElementFree(arglist, list_Car(l1), (void (*)(POINTER))term_Delete); break; } } term_RplacArgumentList(targettoprove, arglist); /* Nothing left for the proof ? */ if (list_Empty(term_ArgumentList(targettoprove))) { term_Delete(targettoprove); term_Delete(ToProveDef); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } } else { /* Nothing left for the proof */ term_Delete(targettoprove); term_Delete(ToProveDef); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } /* Normalize variables in ToProveDef with respect to targettoprove */ maxvar = term_MaxVar(targettoprove); symbol_SetStandardVarCounter(maxvar); vars = fol_BoundVariables(ToProveDef); vars = term_DeleteDuplicatesFromList(vars); for (l1=vars; !list_Empty(l1); l1=list_Cdr(l1)) term_ExchangeVariable(ToProveDef, term_TopSymbol(list_Car(l1)), symbol_CreateStandardVariable()); list_Delete(vars); /* Replace arguments of predicate in condition of definition by matching arguments of predicate in target term */ for (l1=DefPredArgs, l2=TargetPredArgs; !list_Empty(l1); l1=list_Cdr(l1), l2=list_Cdr(l2)) term_ReplaceVariable(ToProveDef, term_TopSymbol((TERM) list_Car(l1)), (TERM) list_Car(l2)); targettoprove = term_Create(fol_Not(), list_List(targettoprove)); targettoprove = cnf_NegationNormalFormula(targettoprove); targettoprove = term_Create(fol_Implies(), list_Cons(targettoprove, list_List(ToProveDef))); /* At this point ToProveDef must not be accessed again ! */ /* Add all--quantifier to targettoprove */ freevars = fol_FreeVariables(targettoprove); term_CopyTermsInList(freevars); targettoprove = fol_CreateQuantifier(fol_All(), freevars, list_List(targettoprove)); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nConverted to :"); fol_PrettyPrint(Target); } targettoprove = cnf_NegationNormalFormula(targettoprove); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nToProve for this target :"); fol_PrettyPrint(targettoprove); } *LocallyTrue = cnf_HaveProof(list_Nil(), targettoprove, Flags, Precedence); term_Delete(targettoprove); #ifdef CHECK fol_CheckFatherLinks(Target); #endif return Target; } static TERM cnf_RemoveQuantFromPathAndFlatten(TERM TopTerm, TERM SubTerm) /********************************************************** INPUT: Two terms, must be a subterm of . Superterm of must be an equivalence. Along the path to SubTerm there are only quantifiers or disjunctions. All free variables in the equivalence are free variables in . All free variables in are bound by a universal quantifier (with polarity 1). RETURN: The destructively changed . EFFECT: Removes all quantifiers not binding a variable in from 's path. Moves all universal quantifiers binding free variable in up. is transformed into the form forall([X1,...,Xn],or (equiv(,psi),phi)). **********************************************************/ { TERM Term1, Term2, Flat, Variable; LIST Scan1, Scan2, FreeVars; #ifdef CHECK if (!fol_CheckFormula(TopTerm) || !term_HasPointerSubterm(TopTerm, SubTerm)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal input."); misc_FinishErrorReport(); } #endif TopTerm = cnf_SimplifyQuantors(TopTerm); term_AddFatherLinks(TopTerm); Term1 = term_Superterm(SubTerm); while (Term1 != TopTerm) { while (symbol_Equal(fol_Or(), term_TopSymbol(Term1)) && (TopTerm != Term1)) { Term1 = term_Superterm(Term1); } if (fol_IsQuantifier(term_TopSymbol(Term1))) { Flat = term_SecondArgument(Term1); Flat = cnf_Flatten(Flat, fol_Or()); Scan1 = fol_QuantifierVariables(Term1); while (!list_Empty(Scan1)) { Variable = (TERM)list_Car(Scan1); if (fol_VarOccursFreely(Variable, SubTerm)) { Scan2 = list_Cdr(Scan1); fol_DeleteQuantifierVariable(Term1, term_TopSymbol(list_Car(Scan1))); Scan1 = Scan2; } else { Scan1 = list_Cdr(Scan1); } } if (fol_IsQuantifier(term_TopSymbol(Term1))) { /* still variables, but not binding a variable in the equivalence term */ LIST ArgList; term_RplacArgumentList(Flat, list_PointerDeleteOneElement(term_ArgumentList(Flat), SubTerm)); ArgList = term_ArgumentList(Term1); term_RplacArgumentList(Term1, list_Nil()); Term2 = term_Create(term_TopSymbol(Term1), ArgList); term_RplacArgumentList(Term1, list_Cons(SubTerm, list_List(Term2))); term_RplacTop(Term1, fol_Or()); Scan1 = term_ArgumentList(Term1); while (!list_Empty(Scan1)) { term_RplacSuperterm((TERM)list_Car(Scan1), Term1); Scan1 = list_Cdr(Scan1); } } } else { #ifdef CHECK if (!symbol_Equal(term_TopSymbol(Term1), fol_Or())) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal term Term1"); misc_FinishErrorReport(); } #endif Term1 = cnf_Flatten(Term1, fol_Or()); } } FreeVars = fol_FreeVariables(Term1); if (!list_Empty(FreeVars)) { term_CopyTermsInList(FreeVars); TopTerm = fol_CreateQuantifier(fol_All(), FreeVars, list_List(Term1)); } return TopTerm; } TERM cnf_DefConvert(TERM Def, TERM FoundPredicate, TERM* ToProve) /********************************************************* INPUT: A term Def which is an equivalence (P(x1,..,xn) <=> Formula) that can be converted to standard form. The subterm that holds the defined predicate. A pointer to a term ToProve into which a term is stored that has to be proved before applying the definition. RETURNS: The converted definition : forall([..], or(equiv(..,..), ..)) ************************************************************/ { TERM orterm; #ifdef CHECK fol_CheckFatherLinks(Def); #endif Def = cnf_RemoveImplFromFormulaPath(Def, FoundPredicate); /* Remove implications along the path */ Def = cnf_NegationNormalFormulaPath(Def, FoundPredicate); /* Move not's as far down as possible */ #ifdef CHECK if (!fol_CheckFormula(Def)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal input Formula.\n"); misc_FinishErrorReport(); } if (!term_HasPointerSubterm(Def, FoundPredicate)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal input SubTerm.\n"); misc_FinishErrorReport(); } #endif Def = cnf_RemoveQuantFromPathAndFlatten(Def, term_Superterm(FoundPredicate)); term_AddFatherLinks(Def); #ifdef CHECK if (!fol_CheckFormula(Def)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal term Def."); misc_FinishErrorReport(); } if (!term_HasPointerSubterm(Def, FoundPredicate)) { misc_StartErrorReport(); misc_ErrorReport("\nIn cnf_DefConvert: Illegal term FoundPredicate."); misc_FinishErrorReport(); } #endif /* Find top level or() */ if (symbol_Equal(term_TopSymbol(Def), fol_All())) { /* Make sure there are several arguments */ if (symbol_Equal(term_TopSymbol(term_SecondArgument(Def)), fol_Or()) && (list_Length(term_ArgumentList(term_SecondArgument(Def))) == 1)) { TERM t; t = term_SecondArgument(Def); term_RplacSecondArgument(Def, term_FirstArgument(term_SecondArgument(Def))); term_Free(t); orterm = NULL; term_RplacSuperterm(term_SecondArgument(Def), Def); } else orterm = term_SecondArgument(Def); } else { /* Make sure there are several arguments */ if (symbol_Equal(term_TopSymbol(Def), fol_Or()) && (list_Length(term_ArgumentList(Def)) == 1)) { TERM t; t = Def; Def = term_FirstArgument(Def); term_Free(t); orterm = NULL; term_RplacSuperterm(term_SecondArgument(Def), Def); } else orterm = Def; } /* If there is something to prove */ if (orterm != (TERM) NULL) { TERM equiv; LIST args; equiv = (TERM) NULL; /* In pell 10 there are no conditions for the equivalence */ if (symbol_Equal(term_TopSymbol(orterm), fol_Equiv())) { equiv = orterm; *ToProve = NULL; } else { TERM t; /* First find equivalence term among arguments */ args = term_ArgumentList(orterm); equiv = term_Superterm(FoundPredicate); /* Delete equivalence from list */ args = list_PointerDeleteElement(args, equiv); term_RplacArgumentList(orterm, args); /* ToProve consists of all the definitions arguments except the equivalence */ *ToProve = term_Copy(orterm); /* Now not(*ToProve) implies the equivalence */ /* Negate *ToProve */ *ToProve = term_Create(fol_Not(), list_List(*ToProve)); *ToProve = cnf_NegationNormalFormula(*ToProve); term_AddFatherLinks(*ToProve); /* Now convert definition to implication form */ term_RplacTop(orterm, fol_Implies()); t = term_Create(fol_Not(), list_List(term_Create(fol_Or(), term_ArgumentList(orterm)))); term_RplacArgumentList(orterm, list_Cons(t, list_List(equiv))); Def = cnf_NegationNormalFormula(Def); term_AddFatherLinks(Def); } } #ifdef CHECK fol_CheckFatherLinks(Def); #endif return Def; } LIST cnf_HandleDefinition(PROOFSEARCH Search, LIST Pair, LIST Axioms, LIST Sorts, LIST Conjectures) /******************************************************************* INPUT: A PROOFSEARCH object, a pair (label, term) and 3 lists of pairs. If the term in pair is a definition, the defined predicate is expanded in all the lists and added to the proofsearch object. RETURNS: The pair with the converted definition: forall([..], or(equiv(..,..), .......)) ********************************************************************/ { TERM definition, defpredicate, equivterm; BOOL alwaysapplicable; /* Is set to TRUE iff the definition can always be applied */ FLAGSTORE Flags; PRECEDENCE Precedence; Flags = prfs_Store(Search); Precedence = prfs_Precedence(Search); /* The axiomlist consists of (label, formula) pairs */ definition = list_PairSecond(Pair); /* Test if Definition contains a definition */ defpredicate = (TERM) NULL; if (cnf_ContainsDefinition(definition, &defpredicate)) { TERM toprove; LIST allformulae, scan; /* Create list of all formula pairs */ /* Check if definition may be applied to each formula */ allformulae = list_Copy(Axioms); allformulae = list_Nconc(allformulae, list_Copy(Sorts)); allformulae = list_Nconc(allformulae, list_Copy(Conjectures)); #ifdef CHECK for (scan=allformulae; !list_Empty(scan); scan=list_Cdr(scan)) { if (!list_Empty((LIST) list_Car(scan))) { if (!term_IsTerm((TERM) list_PairSecond((LIST) list_Car(scan)))) fol_CheckFatherLinks((TERM) list_PairSecond((LIST) list_Car(scan))); } } #endif /* Convert definition to standard form */ if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { fputs("\nPredicate : ", stdout); symbol_Print(term_TopSymbol(defpredicate)); } definition = cnf_DefConvert(definition, defpredicate, &toprove); if (toprove == NULL) alwaysapplicable = TRUE; else alwaysapplicable = FALSE; prfs_SetDefinitions(Search, list_Cons(term_Copy(definition), prfs_Definitions(Search))); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { if (alwaysapplicable) { fputs("\nAlways Applicable : ", stdout); fol_PrettyPrint(definition); } } /* Definition is converted to a form where the equivalence is the first argument of the disjunction */ equivterm = term_SecondArgument(term_Superterm(defpredicate)); scan = allformulae; while (!list_Empty(scan)) { BOOL localfound; LIST pair, targettermvars; /* Pair label / term */ pair = list_Car(scan); /* Pair may be NULL if it is a definition that could be deleted */ if ((pair != NULL) && (definition != (TERM) list_PairSecond(pair))) { TERM target, targetpredicate, totoplevel; LIST varsfortoplevel; target = (TERM) list_PairSecond(pair); targettermvars = varsfortoplevel = list_Nil(); /* If definition is not always applicable, check if it is applicable for this formula */ localfound = FALSE; if (!alwaysapplicable) { if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), &targetpredicate, &totoplevel, &targettermvars, &varsfortoplevel)) { TERM toprovecopy; toprovecopy = term_Copy(toprove); target = cnf_DefTargetConvert(target, totoplevel, toprovecopy, term_ArgumentList(defpredicate), term_ArgumentList(targetpredicate), targettermvars, varsfortoplevel, Flags, Precedence, &localfound); list_Delete(targettermvars); list_Delete(varsfortoplevel); targettermvars = varsfortoplevel = list_Nil(); list_Rplacd(pair, (LIST) target); if (localfound) list_Rplacd(pair, (LIST) cnf_ApplyDefinitionOnce(defpredicate, equivterm, list_PairSecond(pair), targetpredicate, Flags)); } } else { if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), &targetpredicate, &totoplevel, &targettermvars, &varsfortoplevel)) list_Rplacd(pair, (LIST) cnf_ApplyDefinitionOnce(defpredicate, equivterm, list_PairSecond(pair), targetpredicate, Flags)); else scan = list_Cdr(scan); list_Delete(targettermvars); list_Delete(varsfortoplevel); targettermvars = varsfortoplevel = list_Nil(); } } else scan = list_Cdr(scan); } list_Delete(allformulae); /* toprove can be NULL if the definition can always be applied */ if (toprove != (TERM) NULL) term_Delete(toprove); list_Rplacd(Pair, (LIST) definition); } return Pair; } LIST cnf_ApplyDefinitionToClause(CLAUSE Clause, TERM Predicate, TERM Expansion, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A clause, two terms and a flag store and a precedence. RETURNS: The list of clauses where each occurrence of Predicate is replaced by Expansion. ***************************************************************/ { NAT i; BOOL changed; LIST args, scan, symblist; TERM clauseterm, argument; changed = FALSE; /* Build term from clause */ args = list_Nil(); for (i = 0; i < clause_Length(Clause); i++) { argument = clause_GetLiteralTerm(Clause, i); /* with sign */ args = list_Cons(term_Copy(argument), args); } clauseterm = term_Create(fol_Or(), args); for (scan=term_ArgumentList(clauseterm); !list_Empty(scan); scan=list_Cdr(scan)) { BOOL isneg; argument = (TERM) list_Car(scan); if (symbol_Equal(term_TopSymbol(argument), fol_Not())) { argument = term_FirstArgument(argument); isneg = TRUE; } else isneg = FALSE; /* Try to match with predicate */ cont_StartBinding(); if (unify_Match(cont_LeftContext(), Predicate, argument)) { SUBST subst; TERM newargument; subst = subst_ExtractMatcher(); newargument = subst_Apply(subst, term_Copy(Expansion)); subst_Free(subst); if (isneg) newargument = term_Create(fol_Not(), list_List(newargument)); term_Delete((TERM) list_Car(scan)); list_Rplaca(scan, newargument); changed = TRUE; } cont_BackTrack(); } if (changed) { /* Build term and derive list of clauses */ LIST result; if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { puts("\nClause before applying def :"); clause_Print(Clause); puts("\nPredicate :"); fol_PrettyPrint(Predicate); puts("\nExpansion :"); fol_PrettyPrint(Expansion); } symblist = list_Nil(); clauseterm = cnf_Cnf(clauseterm, Flags, Precedence, &symblist); result = cnf_MakeClauseList(clauseterm,FALSE,FALSE,Flags,Precedence); list_Delete(symblist); term_Delete(clauseterm); if (flag_GetFlagIntValue(Flags, flag_PAPPLYDEFS)) { LIST l; puts("\nClauses derived by expanding definition :"); for (l = result; !list_Empty(l); l=list_Cdr(l)) { clause_Print((CLAUSE) list_Car(l)); fputs("\n", stdout); } } return result; } else { term_Delete(clauseterm); return list_Nil(); } } BOOL cnf_PropagateSubstEquations(TERM StartTerm) /************************************************************* INPUT: A term where we assume that father links are established and that no variable is bound by more than one quantifier. RETURNS: TRUE, if any substitutions were made, FALSE otherwise. EFFECT: Function looks for equations of the form x=t where x does not occur in t. If x=t occurs negatively and disjunctively below a universal quantifier binding x or if x=t occurs positively and conjunctively below an existential quantifier binding x, all occurrences of x are replaced by t in . **************************************************************/ { LIST Subequ; TERM QuantorTerm, Equation, EquationTerm; SYMBOL Variable; BOOL Hit, Substituted; #ifdef CHECK if (fol_VarBoundTwice(StartTerm)) { misc_StartErrorReport(); misc_ErrorReport("\n In cnf_PropagateSubstEquations: Variables of"); misc_ErrorReport("\n input term are not normalized."); misc_FinishErrorReport(); } #endif Substituted = FALSE; Subequ = fol_GetSubstEquations(StartTerm); for ( ; !list_Empty(Subequ); Subequ = list_Pop(Subequ)) { Hit = FALSE; Equation = list_Car(Subequ); Variable = symbol_Null(); QuantorTerm = term_Null(); EquationTerm = term_Null(); if (term_IsVariable(term_FirstArgument(Equation)) && !term_ContainsVariable(term_SecondArgument(Equation), term_TopSymbol(term_FirstArgument(Equation)))) { Variable = term_TopSymbol(term_FirstArgument(Equation)); QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); EquationTerm = term_SecondArgument(Equation); Hit = fol_PolarCheck(Equation, QuantorTerm); } if (!Hit && term_IsVariable(term_SecondArgument(Equation)) && !term_ContainsVariable(term_FirstArgument(Equation), term_TopSymbol(term_SecondArgument(Equation)))) { Variable = term_TopSymbol(term_SecondArgument(Equation)); QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); EquationTerm = term_FirstArgument(Equation); Hit = fol_PolarCheck(Equation, QuantorTerm); } if (Hit) { fol_DeleteQuantifierVariable(QuantorTerm,Variable); term_ReplaceVariable(StartTerm, Variable, EquationTerm); /* We replace everythere ! */ term_AddFatherLinks(StartTerm); if (symbol_Equal(term_TopSymbol(QuantorTerm),fol_Equality())) /* Trivial Formula */ fol_SetTrue(QuantorTerm); else fol_SetTrue(Equation); Substituted = TRUE; } } /* was freed in the loop. */ return Substituted; } SPASS-3.7/SPASS/subsumption.c0000644000374100037200000015635611340510067012640 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * SUBSUMPTION * */ /* * * */ /* * $Module: SUBSUMPTION * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: subsumption.c,v $ */ #include "subsumption.h" static NAT *multvec_i; static NAT *multvec_j; static NAT stamp; static NAT maxlits; static BOOL subs_InternIdc(CLAUSE, int, CLAUSE); static BOOL subs_InternIdcEq(CLAUSE, int, CLAUSE); static BOOL subs_InternIdcEqExcept(CLAUSE, int, CLAUSE, int); static BOOL subs_InternIdcRes(CLAUSE, int, int, int); /* The following functions are currently unused */ BOOL subs_IdcTestlits(CLAUSE, CLAUSE, LITPTR*); BOOL subs_Testlits(CLAUSE, CLAUSE); void subs_Init(void) { int i; stamp = 0; maxlits = 100; multvec_i = memory_Malloc(sizeof(NAT)*maxlits); multvec_j = memory_Malloc(sizeof(NAT)*maxlits); for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } void subs_Free(void) { memory_Free(multvec_i, sizeof(NAT)*maxlits); memory_Free(multvec_j, sizeof(NAT)*maxlits); } void subs_ExtendLitVector() { int i; memory_Free(multvec_i, sizeof(NAT)*maxlits); memory_Free(multvec_j, sizeof(NAT)*maxlits); maxlits = maxlits * 10; stamp = 0; multvec_i = memory_Malloc(sizeof(NAT)*maxlits); multvec_j = memory_Malloc(sizeof(NAT)*maxlits); for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } static BOOL subs_TestlitsEq(CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Two clauses c1 and c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { TERM t1,t2; int i,j,n,k; BOOL found; n = clause_Length(c1); k = clause_Length(c2); for (i = 0; i < n; i++){ j = 0; found = FALSE; t1 = clause_GetLiteralTerm(c1,i); do { t2 = clause_GetLiteralTerm(c2,j); cont_StartBinding(); if (unify_Match(cont_LeftContext(), t1, t2)) found = TRUE; else{ if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && fol_IsEquality(fol_Atom(t1)) && fol_IsEquality(fol_Atom(t2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { cont_BackTrackAndStart(); if (unify_Match(cont_LeftContext(), term_FirstArgument(fol_Atom(t1)), term_SecondArgument(fol_Atom(t2))) && unify_Match(cont_LeftContext(), term_SecondArgument(fol_Atom(t1)), term_FirstArgument(fol_Atom(t2)))) found = TRUE; else j++; } else j++; } cont_BackTrack(); } while (!found && j < k); if (!found) return FALSE; } return TRUE; } static BOOL subs_STMultiIntern(int i, CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Integers i,j and two clauses c1 and c2 i and j stand for the i-th and the j-th literal in the clause c1 respectively c2. RETURNS: FALSE if c1 does not multisubsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { int n,j; TERM lit1,lit2; j = 0; n = clause_Length(c2); lit1 = clause_GetLiteralTerm(c1,i); while (j < n) { if (multvec_j[j] != stamp) { lit2 = clause_GetLiteralTerm(c2,j); cont_StartBinding(); if (unify_Match(cont_LeftContext(),lit1,lit2)) { if (i == (clause_Length(c1)-1)) { cont_BackTrack(); return TRUE; } multvec_j[j] = stamp; if (subs_STMultiIntern(i+1, c1, c2)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_Match(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) { if (i == (clause_Length(c1)-1)) { cont_BackTrack(); return TRUE; } multvec_j[j] = stamp; if (subs_STMultiIntern(i+1, c1, c2)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); } } j++; } return FALSE; } BOOL subs_STMulti(CLAUSE c1, CLAUSE c2) { BOOL Result; int n; n = clause_Length(c1); /*printf("\n St-Multi: %d -> %d",clause_Number(c1),clause_Number(c2));*/ if (n > clause_Length(c2) || (n > 1 && !subs_TestlitsEq(c1,c2))) { /*fputs(" Testlits failure ", stdout);*/ return(FALSE); } if (clause_Length(c1) > maxlits || clause_Length(c2) > maxlits) { subs_ExtendLitVector(); stamp++; } else if (++stamp == NAT_MAX) { int i; stamp = 1; for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } /*unify_SaveState();*/ Result = subs_STMultiIntern(0,c1,c2); /*unify_CheckState();*/ return Result; } static BOOL subs_TestlitsEqExcept(CLAUSE C1, CLAUSE C2) { TERM t1,t2; int i,j,n,k; BOOL found; n = clause_Length(C1); k = clause_Length(C2); i = 0; while (multvec_i[i] == stamp && i < n) i++; while (i < n) { j = 0; found = FALSE; t1 = clause_GetLiteralTerm(C1,i); do { if (multvec_j[j] == stamp) j++; else { t2 = clause_GetLiteralTerm(C2,j); cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), t1, t2)) found = TRUE; else { if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && fol_IsEquality(fol_Atom(t1)) && fol_IsEquality(fol_Atom(t2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { cont_BackTrackAndStart(); if (unify_MatchBindings(cont_LeftContext(), term_FirstArgument(fol_Atom(t1)), term_SecondArgument(fol_Atom(t2))) && unify_MatchBindings(cont_LeftContext(), term_SecondArgument(fol_Atom(t1)), term_FirstArgument(fol_Atom(t2)))) found = TRUE; else j++; } else j++; } cont_BackTrack(); } /* else */ } while (!found && (j < k)); if (!found) return FALSE; do i++; while (multvec_i[i] == stamp && i < n); } /* while i < n */ return TRUE; } static BOOL subs_STMultiExceptIntern(CLAUSE C1, CLAUSE C2) { int n, i, j, k; NAT occs, occsaux; TERM lit1,lit2; i = -1; k = 0; occs = 0; j = 0; n = clause_Length(C2); while (k < clause_Length(C1)) { /* Select Literal with maximal number of variable occurrences. */ if (multvec_i[k] != stamp) { if (i < 0) { i = k; occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); } else if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) > occs) { i = k; occs = occsaux; } } k++; } if (i < 0) return TRUE; lit1 = clause_GetLiteralTerm(C1, i); multvec_i[i] = stamp; while (j < n) { if (multvec_j[j] != stamp) { lit2 = clause_GetLiteralTerm(C2, j); cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { multvec_j[j] = stamp; if (subs_STMultiExceptIntern(C1, C2)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_MatchBindings(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) { multvec_j[j] = stamp; if (subs_STMultiExceptIntern(C1, C2)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); } } j++; } multvec_i[i] = 0; return FALSE; } BOOL subs_STMultiExcept(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) /********************************************************** INPUT: Two clauses and for each clause a literal that is already bound to each other. If the literal value is negative, a general subsumption test is performed. RETURNS: TRUE if the first clause subsumes the second one. CAUTION: The weight of the clauses must be up to date! ***********************************************************/ { BOOL Result; int n; n = clause_Length(C1); if (n > clause_Length(C2) || (clause_Weight(C1)-clause_LiteralWeight(clause_GetLiteral(C1,ExceptI))) > (clause_Weight(C2)-clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)))) return FALSE; if (clause_Length(C1) > maxlits || clause_Length(C2) > maxlits) { subs_ExtendLitVector(); stamp++; } else if (++stamp == NAT_MAX) { int i; stamp = 1; for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } multvec_i[ExceptI] = stamp; multvec_j[ExceptJ] = stamp; if (n > 1 && !subs_TestlitsEqExcept(C1, C2)) return FALSE; /*unify_SaveState();*/ Result = subs_STMultiExceptIntern(C1, C2); /*unify_CheckState();*/ return Result; } static BOOL subs_PartnerTest(CLAUSE C1, int c1l, int c1r, CLAUSE C2, int c2l, int c2r) /********************************************************** INPUT: Two clauses and for each clause a starting left index and an exclusive right index. RETURNS: TRUE if every literal inside the bounds of the first clause can be matched against a literal inside the bounds of the second clause. CAUTION: None. ***********************************************************/ { TERM t1,t2; int j; BOOL found; if (c1l == c1r) return TRUE; while (multvec_i[c1l] == stamp && c1l < c1r) c1l++; if (c1l < c1r) { if (c2l == c2r) return FALSE; else do { j = c2l; found = FALSE; t1 = clause_GetLiteralTerm(C1,c1l); do { if (multvec_j[j] == stamp) j++; else { t2 = clause_GetLiteralTerm(C2,j); cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), t1, t2)) found = TRUE; else { if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && fol_IsEquality(fol_Atom(t1)) && fol_IsEquality(fol_Atom(t2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,c1l)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { cont_BackTrackAndStart(); if (unify_MatchBindings(cont_LeftContext(), term_FirstArgument(fol_Atom(t1)), term_SecondArgument(fol_Atom(t2))) && unify_MatchBindings(cont_LeftContext(), term_SecondArgument(fol_Atom(t1)), term_FirstArgument(fol_Atom(t2)))) found = TRUE; else j++; } else j++; } cont_BackTrack(); } /* else */ } while (!found && (j < c2r)); if (!found) return FALSE; do c1l++; while (multvec_i[c1l] == stamp && c1l < c1r); } while (c1l < c1r); } return TRUE; } static BOOL subs_SubsumesInternBasic(CLAUSE C1, int c1fa, int c1fs, int c1l, CLAUSE C2, int c2fa, int c2fs, int c2l) { int i, j, n, k; NAT occs, occsaux; TERM lit1,lit2; i = -1; k = clause_FirstLitIndex(); occs = 0; while (k < c1l) { /* Select literal with maximal variable occurrences. */ if (multvec_i[k] != stamp) { if (i < 0) { i = k; occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); } else if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) > occs) { i = k; occs = occsaux; } } k++; } if (i < 0) return TRUE; lit1 = clause_GetLiteralTerm(C1, i); multvec_i[i] = stamp; if (i < c1fa) { /* Only consider relevant partner literals */ j = clause_FirstLitIndex(); n = c2fa; } else if (i < c1fs) { j = c2fa; n = c2fs; } else { j = c2fs; n = c2l; } while (j < n) { if (multvec_j[j] != stamp) { lit2 = clause_GetLiteralTerm(C2, j); cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { multvec_j[j] = stamp; if (subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_MatchBindings(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) { multvec_j[j] = stamp; if (subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); } } j++; } multvec_i[i] = 0; return FALSE; } BOOL subs_SubsumesBasic(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) /********************************************************** INPUT: Two clauses and for each clause a literal that are already bound to each other. If the literal value is negative, a general subsumption test is performed. RETURNS: TRUE if the first clause subsumes the second one with respect to basic restrictions on the sort literals. CAUTION: The weight of the clauses must be up to date! ***********************************************************/ { BOOL Result; int c1fa,c1fs,c1l,c2fa,c2fs,c2l,lw1,lw2; c1fa = clause_FirstAntecedentLitIndex(C1); c1fs = clause_FirstSuccedentLitIndex(C1); c1l = clause_Length(C1); c2fa = clause_FirstAntecedentLitIndex(C2); c2fs = clause_FirstSuccedentLitIndex(C2); c2l = clause_Length(C2); lw1 = (ExceptI >= clause_FirstLitIndex() ? clause_LiteralWeight(clause_GetLiteral(C1,ExceptI)) : 0); lw2 = (ExceptJ >= clause_FirstLitIndex() ? clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)) : 0); if (c1l > c2l || /* Multiset restriction */ (clause_Weight(C1)-lw1) > (clause_Weight(C2)-lw2)) { return FALSE; } if (c1l > maxlits || c2l > maxlits) { subs_ExtendLitVector(); stamp++; } else if (++stamp == NAT_MAX) { int i; stamp = 1; for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } if (ExceptI >= clause_FirstLitIndex()) multvec_i[ExceptI] = stamp; if (ExceptJ >= clause_FirstLitIndex()) multvec_j[ExceptJ] = stamp; if (c1l > 1 && (!subs_PartnerTest(C1,clause_FirstConstraintLitIndex(C1),c1fa, C2,clause_FirstConstraintLitIndex(C2),c2fa) || !subs_PartnerTest(C1,c1fa,c1fs,C2,c2fa,c2fs) || !subs_PartnerTest(C1,c1fs,c1l,C2,c2fs,c2l))) return FALSE; #ifdef CHECK cont_SaveState(); #endif Result = subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l); #ifdef CHECK cont_CheckState(); #endif return Result; } static BOOL subs_SubsumesInternWithSignature(int i, CLAUSE c1, CLAUSE c2, BOOL Variants, LIST* Bindings) /********************************************************** INPUT: RETURNS: CAUTION: ***********************************************************/ { int n,j; TERM lit1,lit2; LIST NewBindings,Scan; j = 0; n = clause_Length(c2); lit1 = clause_GetLiteralTerm(c1,i); NewBindings = list_Nil(); while (j < n) { if (multvec_j[j] != stamp) { lit2 = clause_GetLiteralTerm(c2,j); cont_StartBinding(); if (fol_SignatureMatch(lit1,lit2,&NewBindings,Variants)) { if (i == (clause_Length(c1)-1)) { *Bindings = list_Nconc(NewBindings,*Bindings); return TRUE; } multvec_j[j] = stamp; if (subs_SubsumesInternWithSignature(i+1, c1, c2,Variants,&NewBindings)) { *Bindings = list_Nconc(NewBindings,*Bindings); return TRUE; } multvec_j[j] = 0; } for (Scan=NewBindings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { /* Backtrack bindings */ if (symbol_IsVariable((SYMBOL)list_Car(Scan))) term_ClearBinding((SYMBOL)list_Car(Scan)); else symbol_ContextClearValue((SYMBOL)list_Car(Scan)); } list_Delete(NewBindings); NewBindings = list_Nil(); if (symbol_Equal(term_TopSymbol(fol_Atom(lit1)),term_TopSymbol(fol_Atom(lit2))) && fol_IsEquality(fol_Atom(lit1))) { if (fol_SignatureMatch(term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2)), &NewBindings, Variants) && fol_SignatureMatch(term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)), &NewBindings, Variants)) { if (i == (clause_Length(c1)-1)) { *Bindings = list_Nconc(NewBindings,*Bindings); return TRUE; } multvec_j[j] = stamp; if (subs_SubsumesInternWithSignature(i+1, c1, c2,Variants,&NewBindings)) { *Bindings = list_Nconc(NewBindings,*Bindings); return TRUE; } multvec_j[j] = 0; } for (Scan=NewBindings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { /* Backtrack bindings */ if (symbol_IsVariable((SYMBOL)list_Car(Scan))) term_ClearBinding((SYMBOL)list_Car(Scan)); else symbol_ContextClearValue((SYMBOL)list_Car(Scan)); } list_Delete(NewBindings); NewBindings = list_Nil(); } } j++; } return FALSE; } BOOL subs_SubsumesWithSignature(CLAUSE C1, CLAUSE C2, BOOL Variants, LIST *Bindings) /********************************************************** INPUT: Two clauses . RETURNS: TRUE if the first clause subsumes the second one where we allow signature symbols to be matched as well. If is TRUE variables must be mapped to variables. Returns the signature symbols that were bound. EFFECT: Symbol context bindings are established. ***********************************************************/ { BOOL Result; if (clause_Length(C1) > clause_Length(C2) || clause_NumOfSuccLits(C1) > clause_NumOfSuccLits(C2) || (clause_NumOfAnteLits(C1) + clause_NumOfConsLits(C1)) > (clause_NumOfAnteLits(C2) + clause_NumOfConsLits(C2))) { /* Multiset restriction */ return FALSE; } if (clause_Length(C1) > maxlits || clause_Length(C2) > maxlits) { subs_ExtendLitVector(); stamp++; } else if (++stamp == NAT_MAX) { int i; stamp = 1; for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } term_NewMark(); Result = subs_SubsumesInternWithSignature(clause_FirstLitIndex(),C1,C2,Variants, Bindings); *Bindings = list_DeleteElementIf(*Bindings, (BOOL (*)(POINTER)) symbol_IsVariable); return Result; } static BOOL subs_SubsumesIntern(CLAUSE C1, int c1fs, int c1l, CLAUSE C2, int c2fs, int c2l) { int i, j, n, k; NAT occs, occsaux; TERM lit1,lit2; i = -1; k = clause_FirstLitIndex(); occs = 0; while (k < c1l) { /* Select literal with maximal variable occurrences. */ if (multvec_i[k] != stamp) { if (i < 0) { i = k; occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); } else if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) > occs) { i = k; occs = occsaux; } } k++; } if (i < 0) return TRUE; lit1 = clause_GetLiteralTerm(C1, i); multvec_i[i] = stamp; if (i < c1fs) { /* Only consider relevant partner literals */ j = clause_FirstLitIndex(); n = c2fs; } else { j = c2fs; n = c2l; } while (j < n) { if (multvec_j[j] != stamp) { lit2 = clause_GetLiteralTerm(C2, j); cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { multvec_j[j] = stamp; if (subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { cont_StartBinding(); if (unify_MatchBindings(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_MatchBindings(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) { multvec_j[j] = stamp; if (subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l)) { cont_BackTrack(); return TRUE; } multvec_j[j] = 0; } cont_BackTrack(); } } j++; } multvec_i[i] = 0; return FALSE; } BOOL subs_Subsumes(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) /********************************************************** INPUT: Two clauses and for each clause a literal that is already bound to each other. If the literal value is negative, a general subsumption test is performed. RETURNS: TRUE if the first clause subsumes the second one. CAUTION: The weight of the clauses must be up to date! ***********************************************************/ { BOOL Result; int c1fs, c1l, c2fs, c2l, lw1, lw2; c1fs = clause_FirstSuccedentLitIndex(C1); c1l = clause_Length(C1); c2fs = clause_FirstSuccedentLitIndex(C2); c2l = clause_Length(C2); lw1 = (ExceptI >= clause_FirstLitIndex() ? clause_LiteralWeight(clause_GetLiteral(C1,ExceptI)) : 0); lw2 = (ExceptJ >= clause_FirstLitIndex() ? clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)) : 0); if (c1l > c2l || /* Multiset restriction */ (clause_Weight(C1) - lw1) > (clause_Weight(C2) - lw2)) return FALSE; if (c1l > maxlits || c2l > maxlits) { subs_ExtendLitVector(); stamp++; } else if (++stamp == NAT_MAX) { int i; stamp = 1; for (i = 0; i < maxlits; i++) multvec_i[i] = multvec_j[i] = 0; } if (ExceptI >= clause_FirstLitIndex()) multvec_i[ExceptI] = stamp; if (ExceptJ >= clause_FirstLitIndex()) multvec_j[ExceptJ] = stamp; if (c1l > 1 && (!subs_PartnerTest(C1,clause_FirstConstraintLitIndex(C1),c1fs, C2,clause_FirstConstraintLitIndex(C2),c2fs) || !subs_PartnerTest(C1,c1fs,c1l,C2,c2fs,c2l))) return FALSE; #ifdef CHECK cont_SaveState(); #endif Result = subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l); #ifdef CHECK cont_CheckState(); #endif return Result; } BOOL subs_ST(int i, int j, CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Integers i,j and two clauses c1 and c2. i and j stand for the i-th and the j-th literal in the clause c1 respectively c2. RETURNS: FALSE if c1 does not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { cont_StartBinding(); while ((j < clause_Length(c2)) && !(unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1,i), clause_GetLiteralTerm(c2,j)))){ j++; cont_BackTrackAndStart(); } if (j >= clause_Length(c2)) { cont_BackTrack(); return FALSE; } if ((i == (clause_Length(c1)-1)) || subs_ST(i+1, 0, c1, c2)) return TRUE; else cont_BackTrack(); if (++j == clause_Length(c2)) return FALSE; return subs_ST(i, j, c1, c2); } BOOL subs_Testlits(CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Two clauses c1 and c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { TERM t1; int i,j; BOOL found; for (i = 0; i < clause_Length(c1); i++){ j = 0; found = FALSE; t1 = clause_GetLiteralTerm(c1,i); do { cont_StartBinding(); if (!(found = unify_Match(cont_LeftContext(), t1, clause_GetLiteralTerm(c2,j)))) j++; cont_BackTrack(); } while (!found && (j < clause_Length(c2))); if (!found) return FALSE; } return TRUE; } static LIST subs_GetVariables(TERM t) /********************************************************** INPUT: A term. RETURNS: The list of non bound variables of the term. CAUTION: None. ***********************************************************/ { LIST scan,insert,symbols,end; symbols = term_VariableSymbols(t); insert = symbols; end = list_Nil(); for (scan = symbols; !list_Empty(scan); scan = list_Cdr(scan)) { if (!cont_VarIsBound(cont_LeftContext(), (SYMBOL)list_Car(scan))) { end = insert; list_Rplaca(insert, list_Car(scan)); insert = list_Cdr(insert); } } if (!list_Empty(insert)) { list_Delete(insert); if (list_Empty(end)) symbols = list_Nil(); else list_Rplacd(end,list_Nil()); } return(symbols); } static BOOL subs_SubsumptionPossible(CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Two clauses c1 and c2. RETURNS: TRUE if every literal in c1 can independently be matched to a literal in c2. CAUTION: None. ***********************************************************/ { int i,j; for (i = 0; i < clause_Length(c1); i++) { for (j = 0; j < clause_Length(c2); j++) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1,i), clause_GetLiteralTerm(c2,j))) j = clause_Length(c2) + 1; cont_BackTrack(); } if (j == clause_Length(c2)) return FALSE; } return TRUE; } BOOL subs_IdcTestlits(CLAUSE c1, CLAUSE c2, LITPTR* litptr) /********************************************************** INPUT: Two clauses c1, c2 and a pointer to a litptr structure. RETURNS: FALSE if c1 can not independently be matched to c2 and TRUE otherwise. CAUTION: A structure is build and litptr points to that structure. ***********************************************************/ { LIST TermIndexlist,VarSymbList,TermSymbList; int i; if (subs_SubsumptionPossible(c1,c2)) { TermIndexlist = list_Nil(); VarSymbList = list_Nil(); TermSymbList = list_Nil(); for (i = 0; i < clause_Length(c1); i++) { VarSymbList = subs_GetVariables(clause_GetLiteralTerm(c1,i)); if (VarSymbList != list_Nil()){ TermIndexlist = list_Cons((POINTER)i, TermIndexlist); TermSymbList = list_Cons(VarSymbList,TermSymbList); } } *litptr = litptr_Create(TermIndexlist,TermSymbList); list_Delete(TermSymbList); list_Delete(TermIndexlist); return TRUE; } return FALSE; } static BOOL subs_SubsumptionVecPossible(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1 and c2 and a vector pointer. RETURNS: TRUE if all literals in c1 which indexes stand in the vector with bottom pointer vec can independently be matched to a literal in c2. CAUTION: None. ***********************************************************/ { int i,j; for (i = vec; i < vec_ActMax(); i++) { for (j = 0; j < clause_Length(c2); j++) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), clause_GetLiteralTerm(c2,j))) j = clause_Length(c2) + 1; cont_BackTrack(); } if (j == clause_Length(c2)) return FALSE; } return TRUE; } static BOOL subs_SubsumptionVecPossibleEq(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1 and c2 and a vector pointer. RETURNS: TRUE if all literals in c1 which indexes stand in the vector with bottom pointer vec can independently be matched to a literal in c2. CAUTION: None. ***********************************************************/ { int i,j,n; TERM lit1,lit2; n = clause_Length(c2); for (i = vec; i < vec_ActMax(); i++) { lit1 = clause_GetLiteralTerm(c1, (int) vec_GetNth(i)); for (j=0;j 0){ for (j = 0; j < n; j++) { if (!literal_GetUsed(litptr_Literal(litptr,j))) { complist = list_Cons((POINTER)j,complist); vec_Push((POINTER)literal_GetLitIndex(litptr_Literal(litptr,j))); literal_PutUsed(litptr_Literal(litptr,j), TRUE); j = n + 1; } } if (j != n) { end = complist; for (scan = complist; !list_Empty(scan); scan = list_Cdr(scan)) { lit = (int)list_Car(scan); for (i = 0; i < n; i++) { if (!literal_GetUsed(litptr_Literal(litptr,i)) && list_HasIntersection(literal_GetLitVarList(litptr_Literal(litptr,lit)), literal_GetLitVarList(litptr_Literal(litptr,i)))) { list_Rplacd(end,list_List((POINTER)i)); end = list_Cdr(end); vec_Push((POINTER)literal_GetLitIndex(litptr_Literal(litptr,i))); literal_PutUsed(litptr_Literal(litptr,i), TRUE); } } } list_Delete(complist); } } } static BOOL subs_StVec(int i, int j, CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Integers i,j and two clauses c1 and c2. i is a pointer to vector and represents a literal in clause c1 and j stand for the j-th literal in the clause c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { int a; if (j >= clause_Length(c2)) return FALSE; a = j; cont_StartBinding(); while ((a < clause_Length(c2)) && !(unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), clause_GetLiteralTerm(c2,a)))){ a++; cont_BackTrackAndStart(); } if (a >= clause_Length(c2)) { cont_BackTrack(); return FALSE; } if ((i == (vec_ActMax()-1)) || subs_StVec(i+1, 0, c1, c2)) return TRUE; else cont_BackTrack(); return subs_StVec(i, a+1, c1, c2); } static int subs_SearchTop(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: The index of that literal in c1 which has the least positive matching tests with the literals in c2. CAUTION: None. ***********************************************************/ { int found_index, i, j, zaehler; found_index = (int)vec_GetNth(vec); for (i = vec; i < vec_ActMax(); i++) { zaehler = 0; j = 0; while (j < clause_Length(c2) && zaehler < 2) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), clause_GetLiteralTerm(c2,j))) { zaehler++; } cont_BackTrack(); j++; } if (zaehler == 0 || zaehler == 1) { found_index = (int)vec_GetNth(i); return found_index; } } return found_index; } static BOOL subs_TcVec(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { int a,top_index; a = 0; top_index = subs_SearchTop(c1,vec,c2); do { cont_StartBinding(); while ((a < clause_Length(c2)) && !(unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1,top_index), clause_GetLiteralTerm(c2,a)))) { a++; cont_BackTrackAndStart(); } if (a >= clause_Length(c2)){ cont_BackTrack(); return FALSE; } if ((vec - vec_ActMax()) == 1) return TRUE; if (subs_InternIdc(c1, vec, c2)) return TRUE; else { cont_BackTrack(); /* Dies ist der 'Hurra' Fall.*/ a++; } } while (a < clause_Length(c2)); return FALSE; } static BOOL subs_TcVecEq(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { int a,top_index; BOOL search; TERM lit1,lit2; a = 0; top_index = subs_SearchTop(c1,vec,c2); lit1 = clause_GetLiteralTerm(c1,top_index); do { search = TRUE; while (a < clause_Length(c2) && search) { lit2 = clause_GetLiteralTerm(c2,a); cont_StartBinding(); if (unify_Match(cont_LeftContext(),lit1,lit2)) search = FALSE; else { if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,top_index)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,a)))) { cont_BackTrackAndStart(); if (unify_Match(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_Match(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) search = FALSE; } if (search) { a++; cont_BackTrack(); } } } if (a >= clause_Length(c2)) { cont_BackTrack(); return FALSE; } if ((vec_ActMax() - vec) == 1) return TRUE; if (subs_InternIdcEq(c1, vec, c2)) return TRUE; else { cont_BackTrack(); a++; } } while (a < clause_Length(c2)); return FALSE; } static BOOL subs_InternIdc(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: FALSE if the literals of c1 which are designed by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: ***********************************************************/ { int locvec; LITPTR litptr; if (!subs_IdcVecTestlits(c1,vec,c2,&litptr)) return FALSE; locvec = vec_ActMax(); do { subs_CompVec(litptr); if (!vec_IsMax(locvec)) { if (!subs_TcVec(c1,locvec,c2)) { vec_SetMax(locvec); litptr_Delete(litptr); return FALSE; } else vec_SetMax(locvec); } } while (!litptr_AllUsed(litptr)); litptr_Delete(litptr); return TRUE; } static BOOL subs_InternIdcEq(CLAUSE c1, int vec, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: FALSE if the literals of c1 which are designed by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: ***********************************************************/ { int locvec; LITPTR litptr; if (!subs_IdcVecTestlitsEq(c1,vec,c2,&litptr)) return FALSE; locvec = vec_ActMax(); do { subs_CompVec(litptr); if (!vec_IsMax(locvec)) { if (!subs_TcVecEq(c1,locvec,c2)) { vec_SetMax(locvec); litptr_Delete(litptr); return FALSE; } else vec_SetMax(locvec); } } while (!litptr_AllUsed(litptr)); litptr_Delete(litptr); return TRUE; } BOOL subs_Idc(CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: ***********************************************************/ { int i,vec; BOOL Result; vec = vec_ActMax(); for (i = 0; i < clause_Length(c1); i++) vec_Push((POINTER) i); Result = subs_InternIdc(c1,vec,c2); vec_SetMax(vec); cont_Reset(); return Result; } BOOL subs_IdcEq(CLAUSE c1, CLAUSE c2) /********************************************************** INPUT: Two clauses c1, c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: ***********************************************************/ { int i,vec; BOOL Result; /*fputs("\n Idc on: ", stdout); clause_Print(c1); putchar('\t'); clause_Print(c2); */ vec = vec_ActMax(); for (i = 0; i < clause_Length(c1); i++) vec_Push((POINTER) i); Result = subs_InternIdcEq(c1,vec,c2); vec_SetMax(vec); cont_Reset(); /*printf(" Result: %s ",(Result ? "TRUE" : "FALSE"));*/ return Result; } BOOL subs_IdcEqMatch(CLAUSE c1, CLAUSE c2, SUBST subst) /********************************************************** INPUT: Two clauses c1, c2. RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. CAUTION: ***********************************************************/ { int i,vec; BOOL Result; /* fputs("\n Idc on: ", stdout); clause_Print(c1); putchar('\t'); clause_Print(c2); DBG */ vec = vec_ActMax(); for (i = 0; i < clause_Length(c1); i++) vec_Push((POINTER) i); i = 0; /* Doesn't matter, there is a general cont_Reset below */ unify_EstablishMatcher(cont_LeftContext(), subst); Result = subs_InternIdcEq(c1,vec,c2); vec_SetMax(vec); cont_Reset(); /*fputs("\nsubs_Idc end: ",stdout); clause_Print(c1); clause_Print(c2); DBG */ return Result; } static BOOL subs_SubsumptionVecPossibleRes(CLAUSE c1, int vec, int beg, int end) /********************************************************** INPUT: Two clauses c1 and c2 and three vector pointer vec,beg and end. RETURNS: TRUE if all literals in c1 which indexes stand in the vector with bottom pointer vec can independently be matched to a literal in c2 which indexes stand in the vector between the pointers beg and end (exclusive). CAUTION: None. ***********************************************************/ { int j,i; for (i = vec; i < vec_ActMax(); i++) { for (j = beg; j < end; j++){ cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), clause_GetLiteralTerm(c1, (int) vec_GetNth(j)))) j = end+1; cont_BackTrack(); } if (j == end) return FALSE; } return TRUE; } static BOOL subs_IdcVecTestlitsRes(CLAUSE c1, int vec, int beg, int end, LITPTR* litptr) /********************************************************** INPUT: A clause c1, a pointer to a literal structure and three vector pointer vec, beg and end. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec can not be matched independently to literal in c2 which are designated by the elements of the vector between the pointers beg and end (exclusive). CAUTION: A structure is build and litptr points to that structure. ***********************************************************/ { LIST TermIndexlist,VarSymbList,TermSymbList; int i; if (subs_SubsumptionVecPossibleRes(c1,vec,beg,end)) { TermIndexlist = list_Nil(); VarSymbList = list_Nil(); TermSymbList = list_Nil(); for (i = vec; i < vec_ActMax(); i++) { VarSymbList = subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); if (VarSymbList != list_Nil()) { TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); TermSymbList = list_Cons(VarSymbList,TermSymbList); } } *litptr = litptr_Create(TermIndexlist,TermSymbList); list_Delete(TermSymbList); list_Delete(TermIndexlist); return TRUE; } return FALSE; } static int subs_SearchTopRes(CLAUSE c1, int vec, int beg, int end) /********************************************************** INPUT: A clause c1, three vector pointers vec, beg and end. RETURNS: The index of that literal in c1 which has the least positive matching tests with the literals in c2 with respect to vector and the vector pointers beg and end. CAUTION: None. ***********************************************************/ { int found_index,i,j,zaehler; found_index = (int) vec_GetNth(vec); for (i = vec; i < vec_ActMax(); i++) { zaehler = 0; j = beg; while ((j < end) && (zaehler < 2)) { cont_StartBinding(); if (unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), clause_GetLiteralTerm(c1, (int) vec_GetNth(j)))) { zaehler++; } cont_BackTrack(); j++; } if (zaehler == 0 || zaehler == 1) { found_index = (int)vec_GetNth(i); return found_index; } } return found_index; } static BOOL subs_TcVecRes(CLAUSE c1, int vec, int beg, int end) /********************************************************** INPUT: A clause c1, three vector pointers vec,beg and end. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 with respect to the vector and the vector pointers beg and end and TRUE otherwise. CAUTION: None. ***********************************************************/ { int a,top_index; a = beg; top_index = subs_SearchTopRes(c1,vec,beg,end); do { cont_StartBinding(); while ((a < end) && !unify_Match(cont_LeftContext(), clause_GetLiteralTerm(c1,top_index), clause_GetLiteralTerm(c1,(int)vec_GetNth(a)))) { a++; cont_BackTrackAndStart(); } if (a >= end){ cont_BackTrack(); return FALSE; } if ((vec - vec_ActMax()) == 1) return TRUE; if (subs_InternIdcRes(c1, vec, beg, end)) return TRUE; else { cont_BackTrack(); a++; } } while (a < end); return FALSE; } static BOOL subs_InternIdcRes(CLAUSE c1, int vec, int beg, int end) /********************************************************** INPUT: A clause c1 and three vector pointers vec,beg and end. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 with respect to vector and the vector pointers beg and end and TRUE otherwise. CAUTION: None. ***********************************************************/ { int locvec; LITPTR litptr; if (!subs_IdcVecTestlitsRes(c1,vec,beg,end,&litptr)) return FALSE; locvec = vec_ActMax(); do { subs_CompVec(litptr); if (!vec_IsMax(locvec)) { if (!subs_TcVecRes(c1,locvec,beg,end)) { vec_SetMax(locvec); litptr_Delete(litptr); return FALSE; } else vec_SetMax(locvec); } } while (!litptr_AllUsed(litptr)); litptr_Delete(litptr); return TRUE; } BOOL subs_IdcRes(CLAUSE c1, int beg, int end) /********************************************************** INPUT: A clause c1 and two vector pointers beg and end. RETURNS: FALSE if c1 do not subsume c2 with respect to vector and the vector pointers beg and end and TRUE otherwise. CAUTION: ***********************************************************/ { int i,vec; BOOL Result; vec = vec_ActMax(); for (i = 0; i < clause_Length(c1); i++) vec_Push((POINTER) i); Result = subs_InternIdcRes(c1, vec, beg, end); vec_SetMax(vec); cont_Reset(); return Result; } static BOOL subs_TcVecEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec. RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: None. ***********************************************************/ { int a,top_index; BOOL search; TERM lit1,lit2; a = 0; top_index = subs_SearchTop(c1,vec,c2); lit1 = clause_GetLiteralTerm(c1,top_index); do { search = TRUE; while (a < clause_Length(c2) && search) { if (a != i2) { lit2 = clause_GetLiteralTerm(c2,a); cont_StartBinding(); if (unify_Match(cont_LeftContext(),lit1,lit2)) search = FALSE; else { if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,top_index)) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,a)))) { cont_BackTrackAndStart(); if (unify_Match(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_Match(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) search = FALSE; } if (search) { a++; cont_BackTrack(); } } } else a++; } if (a>=clause_Length(c2)) { cont_BackTrack(); return FALSE; } if ((vec_ActMax() - vec) == 1) return TRUE; if (subs_InternIdcEqExcept(c1, vec, c2, i2)) return TRUE; else { cont_BackTrack(); a++; } } while (a < clause_Length(c2)); return FALSE; } static BOOL subs_SubsumptionVecPossibleEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2) /********************************************************** INPUT: Two clauses c1 and c2 and a vector pointer and an accept literal index for c2. RETURNS: TRUE if all literals in c1 which indexes stand in the vector with bottom pointer vec can independently be matched to a literal in c2. CAUTION: None. ***********************************************************/ { int i,j,n; TERM lit1,lit2; n = clause_Length(c2); for (i = vec; i < vec_ActMax(); i++) { lit1 = clause_GetLiteralTerm(c1, (int) vec_GetNth(i)); for (j = 0; j < n; j++) { if (j != i2) { lit2 = clause_GetLiteralTerm(c2,j); cont_StartBinding(); if (unify_Match(cont_LeftContext(),lit1,lit2)) j = n + 1; else { if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && fol_IsEquality(fol_Atom(lit1)) && fol_IsEquality(fol_Atom(lit2)) && (clause_LiteralIsNotOrientedEquality( clause_GetLiteral(c1,(int)vec_GetNth(i))) || clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { cont_BackTrackAndStart(); if (unify_Match(cont_LeftContext(), term_FirstArgument(fol_Atom(lit1)), term_SecondArgument(fol_Atom(lit2))) && unify_Match(cont_LeftContext(), term_SecondArgument(fol_Atom(lit1)), term_FirstArgument(fol_Atom(lit2)))) j = n+1; } } cont_BackTrack(); } } if (j==n) return FALSE; } return TRUE; } static BOOL subs_IdcVecTestlitsEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2, LITPTR* litptr) /********************************************************** INPUT: Two clauses c1, c2, a pointer to a literal structure and a vector pointer and a literal index i2 in c2 RETURNS: FALSE if the literals of c1 which are designated by the elements of vec do not subsume c2 and TRUE otherwise. CAUTION: A structure is build and litptr points to that structure. ***********************************************************/ { LIST TermIndexlist,VarSymbList,TermSymbList; int i; if (subs_SubsumptionVecPossibleEqExcept(c1,vec,c2,i2)) { TermIndexlist = list_Nil(); VarSymbList = list_Nil(); TermSymbList = list_Nil(); for (i = vec; i < vec_ActMax(); i++) { VarSymbList = subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); if (VarSymbList != list_Nil()){ TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); TermSymbList = list_Cons(VarSymbList,TermSymbList); } } *litptr = litptr_Create(TermIndexlist,TermSymbList); list_Delete(TermSymbList); list_Delete(TermIndexlist); return TRUE; } return FALSE; } static BOOL subs_InternIdcEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2) /********************************************************** INPUT: Two clauses c1, c2, a vector pointer vec and a literal i2 in c2 which must not be considered RETURNS: FALSE if the literals of c1 which are designed by the elements of vec do not subsume c2/i2 and TRUE otherwise. CAUTION: ***********************************************************/ { int locvec; LITPTR litptr; if (!subs_IdcVecTestlitsEqExcept(c1,vec,c2,i2,&litptr)) return FALSE; locvec = vec_ActMax(); do { subs_CompVec(litptr); if (!vec_IsMax(locvec)) { if (!subs_TcVecEqExcept(c1,locvec,c2,i2)) { vec_SetMax(locvec); litptr_Delete(litptr); return FALSE; } else vec_SetMax(locvec); } } while (!litptr_AllUsed(litptr)); litptr_Delete(litptr); return TRUE; } BOOL subs_IdcEqMatchExcept(CLAUSE c1, int i1, CLAUSE c2, int i2, SUBST subst) /********************************************************** INPUT: Two clauses c1, c2 with the indices of two literals which need not to be considered and a matcher RETURNS: TRUE if (/) subsumes (/) CAUTION: ***********************************************************/ { int i,vec; BOOL Result; /*fputs("\n IdcEQExcept on: \n\t", stdout); subst_Print(subst); fputs("\n\t", stdout); clause_Print(c1); printf(" \t\t%d \n\t",i1); clause_Print(c2); printf(" \t\t%d \n\t",i2);*/ if (clause_Length(c1) == 1) Result = TRUE; else { vec = vec_ActMax(); for (i = 0; i < clause_Length(c1); i++) if (i != i1) vec_Push((POINTER) i); i = 0; /* Doesn't matter, there is a general cont_Reset below */ unify_EstablishMatcher(cont_LeftContext(), subst); Result = subs_InternIdcEqExcept(c1,vec,c2,i2); /* printf("Result : %d",Result); */ vec_SetMax(vec); cont_Reset(); } return Result; } SPASS-3.7/SPASS/doc-proof.h0000644000374100037200000000677311340510066012141 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PROOF DOCUMENTATION * */ /* * * */ /* * $Module: DOCPROOF * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: doc-proof.h,v $ */ #ifndef _DOC_PROOF_ #define _DOC_PROOF_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "clause.h" #include "st.h" #include "sharing.h" #include "search.h" #include "doc-proof.h" #include "proofcheck.h" /**************************************************************/ /* Data Structures and Constants */ /**************************************************************/ extern int dp_DEPTH; /**************************************************************/ /* Macros */ /**************************************************************/ static __inline__ int dp_ProofDepth(void) { return dp_DEPTH; } static __inline__ void dp_SetProofDepth(int Depth) { dp_DEPTH = Depth; } /**************************************************************/ /* Functions */ /**************************************************************/ void dp_Init(void); LIST dp_PrintProof(PROOFSEARCH, LIST, const char*); #endif SPASS-3.7/SPASS/rules-split.c0000644000374100037200000006363511340510067012530 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * SPLITTING OF CLAUSES * */ /* * * */ /* * $Module: SPLIT * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2000 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.6 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: rules-split.c,v $ */ /**************************************************************/ /* Includes */ /**************************************************************/ #include "rules-split.h" static LIST split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH,LIST, int, LIST*); static LIST split_DeleteInvalidClausesFromList(PROOFSEARCH, int, LIST); /* static void split_RemoveUnnecessarySplits(PROOFSEARCH, SPLITFIELD, unsigned, int, LIST*, unsigned*); */ static void split_RemoveBackjumpedSplits(PROOFSEARCH, int, LIST*); static void split_RemoveTopSplit(PROOFSEARCH, LIST*); static void split_RemoveLeftTopSplit(PROOFSEARCH, CLAUSE, CLAUSE*, LIST*); /**************************************************************/ /* Functions */ /**************************************************************/ static SPLITFIELD __inline__ prfs_GetTopSplitfield(PROOFSEARCH PS, unsigned *Length) { SPLIT TopSplit; if (!prfs_SplitStackEmpty(PS)) { TopSplit = prfs_SplitStackTop(PS); if (prfs_SplitIsLeft(TopSplit)) return prfs_LeftSplitfield(TopSplit, Length); else return prfs_RightSplitfield(TopSplit, Length); } else { return NULL; } } static void __inline__ prfs_SetTopSplitfield(PROOFSEARCH PS, SPLITFIELD SF, unsigned SF_length) { SPLIT TopSplit; if (!prfs_SplitStackEmpty(PS)) { TopSplit = prfs_SplitStackTop(PS); if (prfs_SplitIsLeft(TopSplit)) prfs_SetLeftSplitfield(TopSplit, SF, SF_length); else prfs_SetRightSplitfield(TopSplit, SF, SF_length); } } static unsigned __inline__ prfs_ComputeDeepestRightBranchLevel(PROOFSEARCH PS) { LIST ScanStack; ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack) && prfs_SplitIsLeft(list_Car(ScanStack))) ScanStack = list_Cdr(ScanStack); if (!list_StackEmpty(ScanStack)) return prfs_SplitSplitLevel(list_Car(ScanStack)); else return 0; } static void __inline__ prfs_PrintStack(PROOFSEARCH PS) { LIST ScanStack; SPLIT Split; ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack)) { Split = list_Car(ScanStack); if (prfs_SplitIsUnused(Split)) if (prfs_SplitIsLeft(Split)) printf(".L%d",prfs_SplitSplitLevel(Split)); else printf(".R%d",prfs_SplitSplitLevel(Split)); else if (prfs_SplitIsLeft(Split)) printf(".[L%d]",prfs_SplitSplitLevel(Split)); else printf(".[R%d]",prfs_SplitSplitLevel(Split)); ScanStack = list_Cdr(ScanStack); } printf("\n"); } static SPLITFIELD prfs_CopySplitfield(SPLITFIELD Src, unsigned SrcLength) { SPLITFIELD Dst; unsigned i; if (SrcLength > 0) { Dst = memory_Malloc(SrcLength * sizeof(SPLITFIELDENTRY)); for (i=0; i < SrcLength; i++) Dst[i] = Src[i]; return Dst; } else return NULL; } static void __inline__ prfs_FreeSplitfield(SPLITFIELD *SF, unsigned *Length) { if (*SF != NULL) { memory_Free(*SF, sizeof(SPLITFIELDENTRY) * (*Length)); *SF = NULL; *Length = 0; } } static void __inline__ prfs_RemoveUsedSplitsFromTop(PROOFSEARCH PS) { SPLIT Top; while (!prfs_SplitStackEmpty(PS) && (!prfs_SplitIsUnused(prfs_SplitStackTop(PS)))) { Top = prfs_SplitStackTop(PS); prfs_SplitStackPop(PS); prfs_SplitDelete(Top); } if (!prfs_SplitStackEmpty(PS)) prfs_SetValidLevel(PS,prfs_SplitSplitLevel(prfs_SplitStackTop(PS))); else prfs_SetValidLevel(PS,0); } LIST split_Backtrack(PROOFSEARCH PS, CLAUSE EmptyClause, CLAUSE* SplitClause) { SPLIT ActBacktrackSplit; int Backtracklevel; SPLITFIELD CurrentSplitfield; unsigned CurrentSplitfield_length; LIST RecoverList = list_Nil(); int DeepestRightBranchLevel = prfs_ComputeDeepestRightBranchLevel(PS); LIST Scan; BOOL Done; Done = FALSE; CurrentSplitfield = clause_GetSplitfield(EmptyClause, &CurrentSplitfield_length); prfs_SetTopSplitfield(PS, CurrentSplitfield, CurrentSplitfield_length); /* loop: reducing to normal form */ while (!Done) { if (!prfs_SplitStackEmpty(PS)) { CurrentSplitfield = prfs_GetTopSplitfield(PS, &CurrentSplitfield_length); CurrentSplitfield = prfs_CopySplitfield(CurrentSplitfield,CurrentSplitfield_length); Backtracklevel = prfs_SplitfieldHighestLevel(CurrentSplitfield,CurrentSplitfield_length); if (prfs_ValidLevel(PS) > Backtracklevel) { /* apply backjump ----> */ split_RemoveBackjumpedSplits(PS, Backtracklevel, &RecoverList); prfs_RemoveUsedSplitsFromTop(PS); prfs_SetTopSplitfield(PS, CurrentSplitfield, CurrentSplitfield_length); DeepestRightBranchLevel = prfs_ComputeDeepestRightBranchLevel(PS); /* <---- apply backjump */ } else if (prfs_SplitIsLeft(prfs_SplitStackTop(PS))) { /* left */ /* apply branch-condense ----> */ /* deleted unsigned Removed = 0; split_RemoveUnnecessarySplits(PS, CurrentSplitfield, CurrentSplitfield_length, DeepestRightBranchLevel, &RecoverList, &Removed); if (Removed > 0) prfs_SetTopSplitfield(PS, CurrentSplitfield, CurrentSplitfield_length); <---- apply branch-condense else */ { /* apply enter-right ----> */ split_RemoveLeftTopSplit(PS, EmptyClause, SplitClause, &RecoverList); prfs_SetLastBacktrackLevel(PS, prfs_ValidLevel(PS)); /* remove invalid clauses from RecoverList */ RecoverList = split_DeleteInvalidClausesFromList(PS, prfs_ValidLevel(PS), RecoverList); /* stack is in normal form: */ Done = TRUE; /* <---- apply enter-right */ } } else { /* right */ /* apply right-collapse ----> */ SPLITFIELD LeftSplitfield, RightSplitfield, NewSplitfield; unsigned LeftSplitfield_length, RightSplitfield_length, NewSplitfield_length; ActBacktrackSplit = prfs_SplitStackTop(PS); LeftSplitfield = prfs_LeftSplitfield(ActBacktrackSplit,&LeftSplitfield_length); RightSplitfield = prfs_RightSplitfield(ActBacktrackSplit,&RightSplitfield_length); NewSplitfield = prfs_CombineSplitfields(LeftSplitfield, LeftSplitfield_length, RightSplitfield, RightSplitfield_length, prfs_SplitSplitLevel(ActBacktrackSplit), &NewSplitfield_length); split_RemoveTopSplit(PS, &RecoverList); prfs_RemoveUsedSplitsFromTop(PS); prfs_SetTopSplitfield(PS, NewSplitfield, NewSplitfield_length); prfs_FreeSplitfield(&NewSplitfield,&NewSplitfield_length); DeepestRightBranchLevel = prfs_ComputeDeepestRightBranchLevel(PS); /* <---- apply right-collapse */ } prfs_FreeSplitfield(&CurrentSplitfield,&CurrentSplitfield_length); } else { /* stack empty */ for (Scan = RecoverList; !list_Empty(Scan); Scan = list_Cdr(Scan)) prfs_InsertDocProofClause(PS, list_Car(Scan)); list_Delete(RecoverList); RecoverList = list_Nil(); Done = TRUE; } } prfs_MoveInvalidClausesDocProof(PS); return RecoverList; } static LIST split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH Search, LIST ClauseList, int Level, LIST* New) /************************************************************** INPUT: A proof search object, a list of unshared clauses and a split level. EFFECT: Deletes all clauses depending on split level from . All split stored deleted clauses from the level of the deleted clauses from are stored in <*New>. RETURNS: The updated list and the recover clauses in <*New>. ***************************************************************/ { LIST Scan; CLAUSE Clause; SPLIT Reinsert; for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Clause = list_Car(Scan); if (clause_DependsOnSplitLevel(Clause, Level)) { if (prfs_ExistsSplitOfLevel(clause_SplitLevel(Clause), Search)) { Reinsert = prfs_GetSplitOfLevel(clause_SplitLevel(Clause), Search); if (prfs_SplitDeletedClauses(Reinsert) != list_Nil()) { *New = list_Nconc(prfs_SplitDeletedClauses(Reinsert), *New); prfs_SplitSetDeletedClauses(Reinsert, list_Nil()); } } prfs_InsertDocProofClause(Search,Clause); list_Rplaca(Scan, NULL); } } return list_PointerDeleteElement(ClauseList, NULL); } static LIST split_DeleteClausesDependingOnLevelFromSet(PROOFSEARCH PS, LIST ClauseList, int SplitLevel) /************************************************************** INPUT: A PROOFSEARCH object, a list of shared clauses and a split level. RETURNS: A list of clauses that have to be recovered possibly. EFFECT: Clauses from the clause list depending on are moved to the doc proof index of . All formerly redundant clauses that were reduced by a clause of the same split level as a clause from the list depending on are returned. ***************************************************************/ { LIST scan, delList, recover; CLAUSE clause; SPLIT reinsert; int l; delList = recover = list_Nil(); for (scan = ClauseList; !list_Empty(scan); scan = list_Cdr(scan)){ clause = list_Car(scan); if (clause_DependsOnSplitLevel(clause, SplitLevel)) { l = clause_SplitLevel(clause); if (prfs_ExistsSplitOfLevel(l, PS)) { reinsert = prfs_GetSplitOfLevel(l, PS); /* this crashes */ if (reinsert != NULL) { recover = list_Nconc(prfs_SplitDeletedClauses(reinsert), recover); prfs_SplitSetDeletedClauses(reinsert, list_Nil()); delList = list_Cons(clause, delList); } } } } /* WARNING: The following move operations change the worked off */ /* and usable sets of the proof search object destructively. */ /* So it's impossible to move those function calls into the */ /* loop above. */ for ( ; !list_Empty(delList); delList = list_Pop(delList)) { clause = list_Car(delList); if (clause_GetFlag(clause, WORKEDOFF)) prfs_MoveWorkedOffDocProof(PS, clause); else prfs_MoveUsableDocProof(PS, clause); } return recover; } static LIST split_DeleteInvalidClausesFromList(PROOFSEARCH Search, int Level, LIST ClauseList) /************************************************************** INPUT: A proof search object, a split level and a list of clauses. RETURNS: The list where invalid clauses wrt 'Level' are deleted. EFFECT: The invalid clauses are stored in the doc proof index of the proof search object if necessary. ***************************************************************/ { LIST Scan; CLAUSE Clause; for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { Clause = list_Car(Scan); if ( clause_SplitLevel(Clause) != 0 && !prfs_ExistsSplitOfLevel(clause_SplitLevel(Clause), Search) ) { prfs_InsertDocProofClause(Search,Clause); list_Rplaca(Scan, NULL); } } return list_PointerDeleteElement(ClauseList, NULL); } /* static void split_RemoveUnnecessarySplits(PROOFSEARCH PS, SPLITFIELD SF, unsigned SF_length, int DeepestRightBranchLevel, LIST *Recover, unsigned *Removed) ************************************************************** INPUT: A proof search object, a splitfield and the last backtrack level (deepest right branch) RETURNS: The list of clauses depending on the unncecessary splits (splits with levels not in SF) are added to <*Recover>, <*Removed> is set to the number of unncecessary splits. EFFECT: All unnecessary splits are marked as used (not deleted!) and their blocked and deleted sets are set to Nil. *************************************************************** { LIST Scan; LIST New; LIST Deleted; LIST ScanStack; int SplitLevel; SPLIT Split,ScanSplit; Scan = prfs_SplitStack(PS); SplitLevel = prfs_ValidLevel(PS); * TopLevel; * *Removed = 0; while (SplitLevel > DeepestRightBranchLevel) { if (prfs_SplitIsUnused(list_Car(Scan)) && !prfs_SplitfieldContainsLevel(SF, SF_length, SplitLevel)) { New = list_Nil(); Split = list_Car(Scan); clause_DeleteClauseList(prfs_SplitBlockedClauses(Split)); prfs_SplitSetBlockedClauses(Split, list_Nil()); *Recover = list_Nconc(prfs_SplitDeletedClauses(Split), *Recover); prfs_SplitSetDeletedClauses(Split, list_Nil()); if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) { *Recover = list_Cons(prfs_SplitFatherClause(Split),*Recover); prfs_SplitSetFatherClause(Split,NULL); } *Recover = split_DeleteClausesDependingOnLevelFromList(PS, *Recover, SplitLevel, &New); ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack)) { ScanSplit = (SPLIT)list_Car(ScanStack); Deleted = prfs_SplitDeletedClauses(ScanSplit); prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); * IMPORTANT!, see next line * Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New); prfs_SplitSetDeletedClauses(ScanSplit, Deleted); ScanStack = list_Cdr(ScanStack); } while (!list_Empty(New)) { Deleted = list_Nil(); *Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted), *Recover); New = Deleted; } *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel)); *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel)); prfs_SplitSetUsed(Split); *Removed = *Removed + 1; } SplitLevel--; Scan = list_Cdr(Scan); } } */ static void split_RemoveBackjumpedSplits(PROOFSEARCH PS, int BacktrackLevel, LIST *Recover) /************************************************************** INPUT: A proof search object and the last backtrack level (deepest right branch) RETURNS: The list of clauses depending on the backjumped splits are added to <*Recover> EFFECT: All splits with levels greater than BacktrackLevel are marked as used and their blocked and deleted sets are set to Nil; the valid level of PS is updated. ***************************************************************/ { LIST Scan; LIST New; LIST Deleted; LIST ScanStack; int SplitLevel; SPLIT Split,ScanSplit; Scan = prfs_SplitStack(PS); SplitLevel = prfs_ValidLevel(PS); /* TopLevel; */ while (!list_Empty(Scan) && SplitLevel > BacktrackLevel) { if (prfs_SplitIsUnused(list_Car(Scan))) { New = list_Nil(); Split = list_Car(Scan); clause_DeleteClauseList(prfs_SplitBlockedClauses(Split)); prfs_SplitSetBlockedClauses(Split, list_Nil()); *Recover = list_Nconc(prfs_SplitDeletedClauses(Split), *Recover); prfs_SplitSetDeletedClauses(Split, list_Nil()); if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) { *Recover = list_Cons(prfs_SplitFatherClause(Split),*Recover); prfs_SplitSetFatherClause(Split,NULL); } *Recover = split_DeleteClausesDependingOnLevelFromList(PS, *Recover, SplitLevel, &New); ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack)) { ScanSplit = (SPLIT)list_Car(ScanStack); Deleted = prfs_SplitDeletedClauses(ScanSplit); prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); /* IMPORTANT!, see next line */ Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New); prfs_SplitSetDeletedClauses(ScanSplit, Deleted); ScanStack = list_Cdr(ScanStack); } while (!list_Empty(New)) { Deleted = list_Nil(); *Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted), *Recover); New = Deleted; } *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel)); *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel)); prfs_SplitSetUsed(Split); } SplitLevel--; prfs_DecValidLevel(PS); Scan = list_Cdr(Scan); } } static void split_RemoveTopSplit(PROOFSEARCH PS, LIST *Recover) /************************************************************** ***************************************************************/ { LIST Scan; LIST New; LIST Deleted; LIST ScanStack; int SplitLevel; SPLIT Split,ScanSplit; Scan = prfs_SplitStack(PS); SplitLevel = prfs_ValidLevel(PS); /* TopLevel; */ if (prfs_SplitIsUnused(list_Car(Scan))) { New = list_Nil(); Split = list_Car(Scan); clause_DeleteClauseList(prfs_SplitBlockedClauses(Split)); prfs_SplitSetBlockedClauses(Split, list_Nil()); *Recover = list_Nconc(prfs_SplitDeletedClauses(Split), *Recover); prfs_SplitSetDeletedClauses(Split, list_Nil()); if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) { *Recover = list_Cons(prfs_SplitFatherClause(Split),*Recover); prfs_SplitSetFatherClause(Split,NULL); } *Recover = split_DeleteClausesDependingOnLevelFromList(PS, *Recover, SplitLevel, &New); ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack)) { ScanSplit = (SPLIT)list_Car(ScanStack); Deleted = prfs_SplitDeletedClauses(ScanSplit); prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); /* IMPORTANT!, see next line */ Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New); prfs_SplitSetDeletedClauses(ScanSplit, Deleted); ScanStack = list_Cdr(ScanStack); } while (!list_Empty(New)) { Deleted = list_Nil(); *Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted), *Recover); New = Deleted; } *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel)); *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel)); prfs_SplitSetUsed(Split); } prfs_DecValidLevel(PS); } static void split_RemoveLeftTopSplit(PROOFSEARCH PS, CLAUSE EmptyClause, CLAUSE *SplitClause, LIST *Recover) /************************************************************** ***************************************************************/ { LIST Scan; LIST New; LIST Deleted; LIST ScanStack; LIST RightClauses; SPLIT ScanSplit; SPLIT TopSplit = prfs_SplitStackTop(PS); int SplitLevel = prfs_ValidLevel(PS); New = list_Nil(); *Recover = list_Nconc(prfs_SplitDeletedClauses(TopSplit), *Recover); prfs_SplitSetDeletedClauses(TopSplit, list_Nil()); *Recover = split_DeleteClausesDependingOnLevelFromList(PS, *Recover, SplitLevel, &New); RightClauses = prfs_SplitBlockedClauses(TopSplit); prfs_SplitSetBlockedClauses(TopSplit, list_Nil()); for (Scan = RightClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_Number(list_Car(Scan)) == 0) { /* Found the right clause, the negation clauses have number -1. */ *SplitClause = list_Car(Scan); } clause_NewNumber((CLAUSE) list_Car(Scan)); clause_AddParentClause((CLAUSE) list_Car(Scan), clause_Number(EmptyClause)); clause_AddParentLiteral((CLAUSE) list_Car(Scan), 0); /* dummy literal */ } *Recover = list_Nconc(RightClauses, *Recover); ScanStack = prfs_SplitStack(PS); while (!list_StackEmpty(ScanStack)) { ScanSplit = (SPLIT)list_Car(ScanStack); Deleted = prfs_SplitDeletedClauses(ScanSplit); prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); /* IMPORTANT!, see next line */ Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New); prfs_SplitSetDeletedClauses(ScanSplit, Deleted); ScanStack = list_Cdr(ScanStack); } while (!list_Empty(New)) { Deleted = list_Nil(); *Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted), *Recover); New = Deleted; } *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel)); *Recover = list_Nconc(*Recover, split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel)); prfs_SplitSetRight(TopSplit); } void split_DeleteClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level) /************************************************************** INPUT: A clause, a level and a proofsearch object RETURNS: Nothing. EFFECT: is deleted from the usable or worked off set and made unshared. ***************************************************************/ { if (clause_GetFlag(Clause,WORKEDOFF)) prfs_ExtractWorkedOff(PS, Clause); else prfs_ExtractUsable(PS, Clause); split_KeepClauseAtLevel(PS, Clause, Level); } void split_KeepClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level) /************************************************************** INPUT: A clause and a level as int. RETURNS: None. MEMORY: A copy of clause is made and kept within the split stack. ***************************************************************/ { SPLIT Split; if (prfs_ExistsSplitOfLevel(Level, PS)) { Split = prfs_GetSplitOfLevel(Level, PS); prfs_SplitSetDeletedClauses(Split,list_Cons(Clause, prfs_SplitDeletedClauses(Split))); } else { misc_StartErrorReport(); misc_ErrorReport("\n Clause %d is redundant but can't be kept at split level %d.\n", clause_Number(Clause), Level); misc_FinishErrorReport(); } } LIST split_ExtractEmptyClauses(LIST Clauses, LIST* EmptyClauses) /************************************************************** INPUT: A list of clauses and a pointer to a list of empty clauses. RETURNS: without all empty clauses where the empty clauses are moved to MEMORY: Destructive on . ***************************************************************/ { LIST Scan; CLAUSE Clause; for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { Clause = (CLAUSE)list_Car(Scan); if (clause_IsEmptyClause(Clause)) { *EmptyClauses = list_Cons(Clause,*EmptyClauses); list_Rplaca(Scan,NULL); } } Clauses = list_PointerDeleteElement(Clauses,NULL); return Clauses; } CLAUSE split_SmallestSplitLevelClause(LIST Clauses) /************************************************************** INPUT: A non-empty list of clauses. RETURNS: The clause with the smallest split level and among those the one with the fewest dependencies ***************************************************************/ { CLAUSE Result; NAT Dependencies, New; Result = (CLAUSE)list_Car(Clauses); Dependencies = clause_SplitLevelDependencies(Result); Clauses = list_Cdr(Clauses); while (!list_Empty(Clauses)) { if (clause_SplitLevel(Result) > clause_SplitLevel(list_Car(Clauses))) Result = list_Car(Clauses); else if (clause_SplitLevel(Result) == clause_SplitLevel(list_Car(Clauses))) { New = clause_SplitLevelDependencies(list_Car(Clauses)); if (New < Dependencies) { Dependencies = New; Result = list_Car(Clauses); } } Clauses = list_Cdr(Clauses); } return Result; } SPASS-3.7/SPASS/memory.c0000644000374100037200000016013711340510066011547 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * DYNAMIC MEMORY MANAGEMENT MODULE * */ /* * * */ /* * $Module: MEMORY * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: memory.c,v $ */ #include "memory.h" unsigned int memory_PAGESIZE; /* size of a page */ long memory_MAXMEM; /* amount of memory available for allocation */ static int memory__EOF = EOF; /* internal "End Of Memory" marker */ unsigned long memory_NEWBYTES; /* number of allocated bytes */ unsigned long memory_FREEDBYTES; /* number of freed bytes */ const unsigned int memory_ALIGN = sizeof(POINTER); /* Crucial: hardware must support access to words of size POINTER. */ #ifdef CHECK unsigned int memory_LEFTTAG; /* size of left debug mark */ unsigned int memory_OFFSET; /* alignment-correct size of left debug mark */ unsigned int memory_MARKSIZE; /* total size of debug marks */ BOOL memory_MANAGEMENT_INITIALIZED = FALSE; #else /* CHECK not defined */ unsigned int memory_MARKSIZE = 0; unsigned int memory_OFFSET = 0; #endif /* CHECK */ const unsigned int memory_MAGICMALLOC = 1; /* "block allocated" marker */ const unsigned int memory_MAGICFREE = 2; /* "block freed" marker */ /* Internal array of resources for different block sizes */ /* ... + 1 to support odd values for memory__SHAREDPAGES like 7 */ static MEMORY_RESOURCE memory_PAGES[memory__DYNMAXSIZE/memory__SHAREDPAGES + 1]; /* Resources for all administrated block sizes */ MEMORY_RESOURCE * memory_ARRAY[memory__DYNMAXSIZE]; /* double linked list for administering blocks of memory whose size is greater or equal to memory__DYNMAXSIZE. */ MEMORY_BIGBLOCKHEADER memory_BIGBLOCKS = NULL; /**************************************************************/ /* ********************************************************** */ /* * * */ /* * INITIALIZATION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifdef CHECK static BOOL memory_ManagementInitialized(void) /********************************************************** INPUT : None. RETURNS: TRUE if memory management is already initialized, else FALSE. SUMMARY: Checks if memory_Init was called. **********************************************************/ { return memory_MANAGEMENT_INITIALIZED; } #endif /* CHECK */ void memory_Init(long Maxmem) /************************************************************* INPUT : The maximal amount of memory available in bytes for the memory module; if Maxmem < 0 the module allocates as much memory as available from the system. RETURNS: None. SUMMARY: Initializes the memory management. It has to be called before you can perform any module operation. This function automatically increases the default page size if it is too small for two objects of size memory__DYNMAXSIZE. *************************************************************/ { int i; int extra; /* size of internally used space on each page */ memory_FREEDBYTES = 0; /* set total number of freed bytes to zero */ memory_NEWBYTES = 0; /* set total number of allocated bytes to zero */ /* set the size of a page we allocate from the operating system */ memory_PAGESIZE = memory__DEFAULTPAGESIZE; #ifdef CHECK /* Test if memory management has already been initialized */ if (!memory_ManagementInitialized()) { /* if that is not the case, set check variable to TRUE */ memory_MANAGEMENT_INITIALIZED = TRUE; } else { /* otherwise the user is trying initialize it for a second time, so print an error and exit. */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Init:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Trying to initialize memory management"); misc_UserErrorReport(" for a second time.\n"); misc_FinishUserErrorReport(); } /* Calculate the size of debug marks */ memory_LEFTTAG = sizeof(MEMORY_INFONODE) + sizeof(unsigned int); if ((sizeof(MEMORY_INFONODE) + sizeof(unsigned int)) % memory_ALIGN == 0) { memory_OFFSET = memory_LEFTTAG; } else { memory_OFFSET = memory_LEFTTAG + memory_ALIGN - (memory_LEFTTAG % memory_ALIGN); } if ((sizeof(unsigned int) % memory_ALIGN) == 0) { memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int); } else { memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int) + memory_ALIGN - (sizeof(unsigned int) % memory_ALIGN); } #endif /* Calculate the size of internally used space on each page */ /* extra: One pointer for chaining pages, one for EOF (+ marksize) */ extra = 2*sizeof(POINTER) + memory_MARKSIZE; /* Test whether page size is reasonable with respect to dynamic allocation threshold */ while (memory_PAGESIZE < (2*(memory__DYNMAXSIZE + memory_MARKSIZE) + extra)) { /* Minimum two objects per allocated page */ memory_PAGESIZE += memory__DEFAULTPAGESIZE/2; } /* Set amount of memory available to the module for allocation */ if (Maxmem <= 0) { /* unlimited (limited only by the operating system) */ memory_MAXMEM = memory__UNLIMITED; } else { /* Maxmem bytes */ memory_MAXMEM = Maxmem; } /* Initialize memory_ARRAY and memory_RESOURCEs */ for (i=1; ifree = &memory__EOF; /* no blocks freed */ CurrentResource->next = &memory__EOF; /* no blocks allocated */ CurrentResource->end_of_page = &memory__EOF; /* no (end of) page */ CurrentResource->page = &memory__EOF; /* no page allocated */ /* Size of a properly aligned block of requested size i */ CurrentResource->aligned_size = memory_CalculateRealBlockSize(i); /* Total block size including debug marks */ CurrentResource->total_size = memory_MARKSIZE + CurrentResource->aligned_size; TotalSize = CurrentResource->total_size; /* last block´s offset */ CurrentResource->offset = ((memory_PAGESIZE-extra)/TotalSize)*TotalSize + sizeof(POINTER) + memory_OFFSET; } } void memory_Restrict(long Maxmem) /************************************************************* INPUT : The maximal amount of memory available for further allocation (in bytes); if Maxmem < 0 future allocations are unrestricted. RETURNS: None. SUMMARY: Sets the maximal amount of memory available for future allocations. If the user tries to allocate more memory, the module displays an error message and terminates the program by calling the exit() function. *************************************************************/ { /* Reset the maximum amount of memory available */ if (Maxmem <= 0) { /* unlimited */ memory_MAXMEM = memory__UNLIMITED; } else { /* Maxmem bytes */ memory_MAXMEM = Maxmem; } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * CHECK CODE * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifdef CHECK static void memory_CheckIfModuleIsInitialized(const char * Function, const char * File, unsigned short int Line) /******************************************************** INPUT : The name of the function that requests the check, the name of the file and the line, where the requesting function was called, and the line. RETURNS: None. SUMMARY: Checks if the memory management module has been properly initialized. You need to initialize the module by calling memory_Init before you use any functions from the module. If the check fails, this function prints an error message and exits the application. *********************************************************/ { if (!memory_ManagementInitialized()) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In %s:", Function); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Memory management is not initialized."); misc_UserErrorReport("\n You have to call memory_Init()"); misc_UserErrorReport(" before you can use memory management functions.\n"); misc_UserErrorReport("\n Error occurred in %s", Function); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); misc_FinishUserErrorReport(); } } static void memory_CheckIfPointerIsAlreadyFreed(POINTER Pointer, const char * Function, const char * File, unsigned short int Line) /******************************************************** INPUT : The pointer to be checked, the name of the function that requests the check, the name of the file and the line, where the requesting function was called, and the line. RETURNS: None. SUMMARY: Checks if the pointer has already been freed. If the check fails, this function prints an error message and exits the application. *********************************************************/ { if ( memory_GetBlockStatus(Pointer) == memory_MAGICFREE) { MEMORY_INFO Info; /* block´s debug information */ Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET); misc_StartUserErrorReport(); misc_UserErrorReport("\n In %s:", Function); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d.", Pointer, Info->mallocInFile, Info->mallocAtLine); misc_UserErrorReport("\n It has already been freed in file %s at line %d.", Info->freeInFile, Info->freeAtLine); misc_UserErrorReport("\n Size of memory block is %d bytes.", memory_GetBlockSize(Pointer)); misc_UserErrorReport("\n Error occurred in %s", Function); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); misc_FinishUserErrorReport(); } } static void memory_CheckPointer(POINTER Pointer, unsigned int Size) /********************************************************* INPUT : A pointer to a block of memory, and its size. RETURNS: Nothing. SUMMARY: Checks whether a pointer points to a valid block of memory. This function performs the following tests: Is Pointer a NULL pointer? Is Size equal to zero? Is the Pointer alignment correct? Did someone write over the memory block boundaries? Is Size still correct? If Size is greater than memory__DYNMAXSIZE: Is it properly administrated by the module? If the memory block was freed: Did someone write to it after deallocation? *********************************************************/ { MEMORY_INFO Info; unsigned int BlockSize, RealBlockSize, BlockStatus; Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET); RealBlockSize = memory_LookupRealBlockSize(Size); if (Pointer == NULL) { /* NULL pointers must not be dereferenced */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error. Pointer is a NULL pointer.\n"); misc_FinishUserErrorReport(); } if (Size == 0) { /* We don´t allocate 0 byte sized blocks */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p points to a block of memory", Pointer); misc_UserErrorReport(" with size 0.\n"); misc_FinishUserErrorReport(); } if ((unsigned long)Pointer % (unsigned long)memory_ALIGN){ /* we expect all pointers to be correctly aligned */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p is not a legal pointer.\n", Pointer); misc_FinishUserErrorReport(); } /* BlockStatus and BlockSize are initialized after we can be sure Pointer is properly aligned. */ BlockStatus = memory_GetBlockStatus(Pointer); BlockSize = memory_GetBlockSize(Pointer); if (BlockStatus != memory_MAGICMALLOC && BlockStatus != memory_MAGICFREE) { /* we expect block status to be either memory_MAGICMALLOC or memory_MAGICFREE. Other values might result from overwriting, trying to return an unallocated block, or trying to return a block allocated with another allocator. */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was not (de)allocated by the module,", Pointer); misc_UserErrorReport("\n or the memory block was corrupted.\n"); misc_FinishUserErrorReport(); } if (BlockStatus == memory_MAGICMALLOC) { if (BlockSize != Size) { /* we expect block size in a block´s debug information and given block size to match. */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was apparently allocated for", Pointer); misc_UserErrorReport(" a block of size %d,", BlockSize); misc_UserErrorReport("\n but it is expected to be a block of size %d.", Size); misc_UserErrorReport("\n Probably the memory block was corrupted.\n"); misc_FinishUserErrorReport(); /* since the left dog tag seems to be corrupted we can not safely assume that our memory info structure is still valid so we can't print it*/ } if ((Size % memory_ALIGN) || (Size % memory__SHAREDPAGES)) { /* check the fillbytes between used storage and dog tag for overwriting */ char * ptr, * limit; limit = (char *)Pointer + RealBlockSize; for (ptr = (char *)Pointer + Size; ptr < limit; ptr++) { if (*ptr != memory__FREESHREDDER) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d,", Pointer, Info->mallocInFile, Info->mallocAtLine); misc_UserErrorReport("\n for a block of size %d.", BlockSize); misc_UserErrorReport("\n The memory block was corrupted.\n"); misc_FinishUserErrorReport(); } } } } if (Size >= memory__DYNMAXSIZE) { /* we expect big blocks to be correctly linked */ MEMORY_BIGBLOCKHEADER BigBlockHeader; BigBlockHeader = (MEMORY_BIGBLOCKHEADER) ((char *) Pointer - memory_OFFSET - sizeof(MEMORY_BIGBLOCKHEADERNODE)); /* this test might crash the program if something is wrong with the pointers, so you may not get a message every time. */ if (((BigBlockHeader->previous != NULL) && (BigBlockHeader->previous->next != BigBlockHeader)) || ((BigBlockHeader->previous == NULL) && (memory_BIGBLOCKS != BigBlockHeader)) || ((BigBlockHeader->next != NULL) && (BigBlockHeader->next->previous != BigBlockHeader))) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was not allocated by the module,", Pointer); misc_UserErrorReport("\n or the memory block was corrupted.\n"); misc_FinishUserErrorReport(); } } if (BlockStatus == memory_MAGICFREE) { /* test if someone wrote over freed memory */ char * ptr, * limit; limit = (char *)Pointer + RealBlockSize; for (ptr = (char *)Pointer + sizeof(POINTER); ptr < limit ; ptr++){ /* first sizeof(POINTER) bytes are reserved for the pointer to the next freed block in the list. All other bytes in the block should still have the value of memory__FREESHREDDER */ if (*ptr != memory__FREESHREDDER) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_CheckPointer:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d", Pointer, Info->mallocInFile, Info->mallocAtLine); misc_UserErrorReport("\n for a block of size %d",BlockSize); misc_UserErrorReport("\n and freed in file %s at line %d.", Info->freeInFile, Info->freeAtLine); misc_UserErrorReport("\n The memory block was used after deallocation.\n"); misc_FinishUserErrorReport(); } } } } void memory_CheckFree(POINTER Freepointer, unsigned int Size, unsigned int RealBlockSize, const char * File, unsigned short int Line) /********************************************************** INPUT : The pointer to be freed, the size of the block it is supposed to point to, the real size of that block, the file and line where memory_Free was called. RETURNS: None. SUMMARY: Checks if memory management was initialized, the given pointer is legal, and not freed already. It also zeroes the freed memory, and sets the block's debug and administration information. **********************************************************/ { MEMORY_INFO Info; /* block´s debug information */ /* Check if memory management was initialized */ memory_CheckIfModuleIsInitialized("memory_Free", File, Line); /* Check if given pointer is legal */ memory_CheckPointer(Freepointer, Size); /* Check if current pointer is being freed for a second time */ memory_CheckIfPointerIsAlreadyFreed(Freepointer, "memory_Free", File, Line); /* Set all bytes to zero, so we can detect overwriting of freed memory */ memset (Freepointer, memory__FREESHREDDER, RealBlockSize); /* Get current block´s debug information */ Info = (MEMORY_INFO) ((char *) Freepointer - memory_OFFSET); /* Set block´s debug and administration information */ memory_SetInfo(Info,Info->mallocInFile, Info->mallocAtLine, File, Line); memory_SetBlockStatusAndSize(Freepointer, memory_MAGICFREE, Size); } #endif /* CHECK */ /**************************************************************/ /* ********************************************************** */ /* * * */ /* * MALLOC * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifdef NO_MEMORY_MANAGEMENT POINTER memory_Malloc(unsigned int Bytes) { char *mem; /* pointer to memory block obtained from malloc */ /* Pass the call through to compiler´s malloc */ mem = (char *)malloc(Bytes); /* If malloc fails print an error message and exit */ if (mem == NULL) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Malloc:"); misc_UserErrorReport("\n Memory Error. Out of memory.\n"); misc_FinishUserErrorReport(); } return mem; } #else #ifdef CHECK POINTER memory_MallocIntern(unsigned int Bytes, const char * File, unsigned short int Line) #else POINTER memory_Malloc(unsigned int Bytes) #endif /******************************************************** INPUT : The size of the requested memory block. RETURNS: A pointer to a block of bytes. SUMMARY: Allocates a memory block of requested length. EXCEPT : Trying to allocate 0 bytes, violating a memory restriction, or running out of system memory cause the function to print an error message and call exit(). *********************************************************/ { char *NewMemory; /* pointer to allocated memory */ MEMORY_RESOURCE *Resource; /* current page resource, required if we do not allocate a big block */ #ifdef CHECK MEMORY_INFO NewInfo; /* Storage for file and line of allocation */ #endif #ifdef CHECK /* Is the module initialized? */ memory_CheckIfModuleIsInitialized("memory_Malloc", File, Line); /* Is it a request for a block of zero bytes? */ if (Bytes == 0) { /* The latest draft for the ANSI C 9X standard says in section 7.20.3: "If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the pointer shall not be used to access an object." We have decided to print an error and exit upon such requests since they are often originated by a bug. Nonstandard but hopefully helpful. */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Malloc:"); misc_UserErrorReport("\n Memory Error. Tried to allocate 0 Bytes!"); misc_UserErrorReport("\n Error occurred in memory_Malloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); misc_FinishUserErrorReport(); } #endif /* If it is a big block, then it has to be administrated in a special way */ if (Bytes >= memory__DYNMAXSIZE) { unsigned int RealBigBlockSize; /* real block size including padding,header and debug marks */ /* This is what a big block looks like: -------------------------------------------------------------------- | MEMORY_BIGBLOCKHEADERNODE | debug marks | char * | debug marks | | previous and next big block |in debug mode| block |in debug mode| -------------------------------------------------------------------- */ /* Calculate the real size of the big block, from the size of administration information, the size of debug marks and the requested block size */ RealBigBlockSize = sizeof(MEMORY_BIGBLOCKHEADERNODE) + memory_MARKSIZE + memory_CalculateRealBlockSize(Bytes); /* Check for violation of maximum allocation limit */ if (memory_MAXMEM >= 0) { /* there is a maximum allocation limit, let´s see if there is enough left */ if ((unsigned int)memory_MAXMEM < RealBigBlockSize) { /* if it is not print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Malloc:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Terminated by user given memory restriction,\n"); misc_UserErrorReport("\n while trying to allocate %lu bytes.\n", RealBigBlockSize); misc_UserErrorReport("\n Maximum amount of memory"); misc_UserErrorReport(" left for allocation is %l bytes.\n", memory_MAXMEM); #ifdef CHECK misc_UserErrorReport("\n Error occurred in memory_Malloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); #endif misc_FinishUserErrorReport(); } else /* otherwise subtract the real block size from the amount of memory available for allocation */ memory_MAXMEM -= RealBigBlockSize; } /* allocate a fresh block of memory via a call to malloc */ NewMemory = (char *)malloc(RealBigBlockSize); /* Check if allocation was successful */ if (NewMemory != NULL) { /* if it was, then administrate the fresh block: insert it into the big block list. The list is double linked for fast deletion */ MEMORY_BIGBLOCKHEADER NewBigBlock; /* new block´s administration information */ /* insert the fresh block as the first list element */ NewBigBlock = (MEMORY_BIGBLOCKHEADER) NewMemory; NewBigBlock->next = memory_BIGBLOCKS; NewBigBlock->previous = NULL; /* if there are already elements in the big block list, change the first element´s pointer to the previous block to point to the fresh block´s administration information */ if (memory_BIGBLOCKS != NULL) { memory_BIGBLOCKS->previous = NewBigBlock; } /* reset the big block list pointer to point to the fresh block */ memory_BIGBLOCKS = NewBigBlock; /* skip the administration information */ NewMemory += sizeof(MEMORY_BIGBLOCKHEADERNODE); #ifdef CHECK /* set the debug information address */ NewInfo = (MEMORY_INFO) NewMemory; /* skip left debug mark */ NewMemory += memory_OFFSET; #endif /* add block´s real size to the total sum of allocated bytes */ memory_NEWBYTES += RealBigBlockSize; } else { /* NewMemory == NULL. malloc could not allocate a memory block of required size, so we print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_MallocIntern:"); misc_UserErrorReport("\n Memory Error. Out of memory."); misc_UserErrorReport("\n Failed to allocate %d bytes.\n", RealBigBlockSize); #ifdef CHECK misc_UserErrorReport("\n Error occurred in memory_Malloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); #endif misc_FinishUserErrorReport(); } } else { /* Bytes < memory__DYNMAXSIZE. A memory request for a manageable size */ /* Initialize the memory resource for the given size */ Resource = memory_ARRAY[Bytes]; /* Check if there are freed blocks of that size */ if (*((int *)Resource->free) != EOF) { /* if that is the case, then use an already freed block */ NewMemory = (char *) Resource->free; /* update the free blocks list for that size */ Resource->free = *((POINTER *)(NewMemory)); /* subtract block´s total size from the sum of freed bytes */ memory_FREEDBYTES -= Resource->total_size; #ifdef CHECK /* calculate the address of the block´s debug information */ NewInfo = (MEMORY_INFO) ((char*) NewMemory - memory_OFFSET); /* Check if the block has been used after deallocation */ memory_CheckPointer(NewMemory, Bytes); #endif } else { /* there are no already freed blocks of that size */ /* Check if there is enough space left on current page */ if (Resource->next != Resource->end_of_page) { /* if that is the case, then use a fresh block from current page */ NewMemory = (char *)Resource->next; /* update the pointer to the next usable block */ Resource->next = NewMemory + Resource->total_size; /* add block´s total size to the sum of allocated bytes */ memory_NEWBYTES += Resource->total_size; #ifdef CHECK /* Check if the fresh block´s address is sane */ if ((char *)NewMemory > (char *) Resource->end_of_page) { /* if it is not, then we have detected an internal error in the module itself. Oops! So we print an error message and abort, hoping that the core dump will enable us to trace the error back to its origin */ misc_StartErrorReport(); misc_ErrorReport("\n In memory_Malloc:"); misc_ErrorReport("\n Memory Error. Address overflow %d.",Bytes); misc_ErrorReport("\n Error occurred in memory_Malloc"); misc_ErrorReport(" called from file %s at line %d.\n", File, Line); misc_FinishErrorReport(); } /* if all is well, we initialize the pointer to fresh block´s debug information */ NewInfo = (MEMORY_INFO)((char*) NewMemory - memory_OFFSET); #endif } else { /* Check for violation of maximum allocation limit */ if (memory_MAXMEM >=0) { /* there is a maximum allocation limit, let´s see if there is enough left */ if ((unsigned int)memory_MAXMEM < memory_PAGESIZE) { /* if it is not, then print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Malloc:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Terminated by user given memory restriction.\n"); #ifdef CHECK misc_UserErrorReport("\n Error occurred in memory_Malloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); #endif misc_FinishUserErrorReport(); } else { /* otherwise subtract the page size from the limit */ memory_MAXMEM -= memory_PAGESIZE; } } /* try to allocate a new page via malloc */ NewMemory=(char *)malloc(memory_PAGESIZE); /* check if allocation was successful */ if (NewMemory == NULL) { /* if it wasn´t print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Malloc:"); misc_UserErrorReport("\n Memory Error."); misc_UserErrorReport(" Terminated, ran out of system memory.\n"); #ifdef CHECK misc_UserErrorReport("\n Error occurred in memory_Malloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); #endif misc_FinishUserErrorReport(); } /* otherwise administrate the fresh page, i.e insert it as the first element of the page list for the given size */ *((POINTER *)NewMemory) = Resource->page; Resource->page = NewMemory; /* add block´s total size to the sum of allocated bytes */ memory_NEWBYTES += Resource->total_size; /* set the end of page pointer for the fresh page */ Resource->end_of_page = (char *) NewMemory + Resource->offset; /* skip the page list */ NewMemory += sizeof(POINTER); #ifdef CHECK /* set the debug information address */ NewInfo = (MEMORY_INFO) NewMemory; /* skip the left debug mark */ NewMemory += memory_OFFSET; #endif /* update the pointer to the next usable block */ Resource->next = NewMemory + Resource->total_size; } } } #ifdef CHECK /* Set block´s debug information */ memory_SetInfo(NewInfo, File, Line, NULL, 0); memory_SetBlockStatusAndSize(NewMemory, memory_MAGICMALLOC, Bytes); /* delete all block´s usable bytes with a shredder value */ memset(NewMemory, memory__FREESHREDDER, memory_LookupRealBlockSize(Bytes)); #endif return NewMemory; } #endif #ifdef NO_MEMORY_MANAGEMENT void memory_Free(POINTER Freepointer, unsigned int Size) { free((char*)Freepointer); } #else #ifdef CHECK void memory_FreeIntern(POINTER Freepointer, unsigned int Size, const char * File, unsigned short int Line) #else void memory_Free(POINTER Freepointer, unsigned int Size) #endif /********************************************************** INPUT : Pointer to the block of memory to be freed, and the block's size RETURNS: Nothing. SUMMARY: Frees a block of memory for reallocation. This function performs correctness checks in debugging mode. **********************************************************/ { unsigned int RealBlockSize; /* block´s alignment correct size */ RealBlockSize = memory_LookupRealBlockSize(Size); #ifdef CHECK memory_CheckFree(Freepointer, Size, RealBlockSize, File, Line); #endif /* Check if current block is a big block */ if (Size >= memory__DYNMAXSIZE) { /* if that´s true, remove it from the double linked big block list */ MEMORY_BIGBLOCKHEADER BigBlockHeader; BigBlockHeader = (MEMORY_BIGBLOCKHEADER) ((char *) Freepointer - memory_OFFSET - sizeof(MEMORY_BIGBLOCKHEADERNODE)); /* Check if current big block is the first block in the list */ if (BigBlockHeader->previous != NULL) { /* if that´s not true, set previous block´s successor to current block´s successor */ BigBlockHeader->previous->next = BigBlockHeader->next; } else { /* otherwise set the first block in the big blocks list to current block´s successor */ memory_BIGBLOCKS = BigBlockHeader->next; } /* Check if current block is the last block in the list */ if (BigBlockHeader->next != NULL) { /* if that´s not true, set next block´ predecessor to current block´s predecessor */ BigBlockHeader->next->previous = BigBlockHeader->previous; } /* Adapt total number of freed bytes and number of bytes available for allocation accordingly */ memory_FREEDBYTES += RealBlockSize + memory_MARKSIZE + sizeof(MEMORY_BIGBLOCKHEADERNODE); if (memory_MAXMEM >= 0) { memory_MAXMEM += RealBlockSize + memory_MARKSIZE + sizeof(MEMORY_BIGBLOCKHEADERNODE); } /* pass the call though to free() with correct pointer value */ #ifdef CHECK free((char *)Freepointer - memory_OFFSET - sizeof(MEMORY_BIGBLOCKHEADERNODE)); #else free((char*) Freepointer - sizeof(MEMORY_BIGBLOCKHEADERNODE)); #endif } else { /* current block is not a big block */ /* Adapt number of allocated bytes and the freed blocks list accordingly */ memory_FREEDBYTES += memory_ARRAY[Size]->total_size; *(POINTER *)Freepointer = memory_ARRAY[Size]->free; memory_ARRAY[Size]->free = Freepointer; } } #endif #ifdef NO_MEMORY_MANAGEMENT POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes) { char *mem; /* pointer to memory block obtained from calloc */ /* Pass call through to compiler´s calloc */ mem = (char *)calloc(Elements, Bytes); /* If calloc fails print an error message and exit */ if (mem == NULL) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Calloc:"); misc_UserErrorReport("\n Memory Error. Out of memory.\n"); misc_FinishUserErrorReport(); } return mem; } #else #ifdef CHECK POINTER memory_CallocIntern(unsigned int Elements, unsigned int Bytes, const char * File, unsigned short int Line) #else POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes) #endif /******************************************************** INPUT : The number of requested equally huge blocks, and each block's size. RETURNS: A pointer to a block of (Bytes * Elements) bytes. SUMMARY: Allocates a memory block of requested length filled with char value '\0'. *********************************************************/ { char * mem; /* pointer to memory block obtained from the module */ /* Allocate memory via our memory management */ #ifdef CHECK mem = (char *)memory_MallocIntern(Elements * Bytes, File, Line); #else mem = (char *)memory_Malloc(Elements * Bytes); #endif /* If allocation was successful set all bytes to zero */ if (mem != NULL) { memset(mem,0, Elements * Bytes); } /* otherwise print an error message and exit */ else { misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_Calloc:"); misc_UserErrorReport("\n Memory Error. Out of memory.\n"); #ifdef CHECK misc_UserErrorReport("\n Error occurred in memory_Calloc"); misc_UserErrorReport(" called from file %s at line %d.\n", File, Line); #endif misc_FinishUserErrorReport(); } return mem; } #endif void memory_FreeAllMem(void) /************************************************************** INPUT : None. RETURNS: None. SUMMARY: Frees all memory allocated by calls to the module. ***************************************************************/ { int i; /* delete all pages first by going through the memory_ARRAY. This is slower than traversing the array memory_PAGES directly, but is easier to implement correctly. Since the only reasonable way to call memory_FreeAllMem is before the program exits, a minimal performance penalty should be acceptable */ for (i = 1; i < memory__DYNMAXSIZE; i++) { POINTER thispage, nextpage; MEMORY_RESOURCE * Resource; Resource = memory_ARRAY[i]; thispage = Resource->page; if (*((int *)thispage) != EOF) { do { nextpage = *((POINTER *)thispage); free(thispage); thispage = nextpage; } while (*((int *)thispage) != EOF); /* and reset the resource structure */ Resource->page = &memory__EOF; Resource->free = &memory__EOF; Resource->next = &memory__EOF; Resource->end_of_page = &memory__EOF; } } /* now delete all big blocks left */ if (memory_BIGBLOCKS != NULL) { MEMORY_BIGBLOCKHEADER thisblock, nextblock; for (thisblock = memory_BIGBLOCKS; thisblock != NULL; thisblock = nextblock) { nextblock = thisblock->next; free(thisblock); } /* and reset the list pointer */ memory_BIGBLOCKS = NULL; } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * DEBUGGING INFORMATION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void memory_Print(void) /************************************************************** INPUT : None. RETURNS: None. SUMMARY: Prints module status information to stdout: the fixed size of an internal memory page, the size of debug marks for a block of memory, the size of demanded and freed memory in kilobytes, remaining memory in bytes and the number of allocated pages of memory. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT /* Call memory_FPrint to print status information to stdout */ memory_FPrint(stdout); #endif } void memory_FPrint(FILE* File) /************************************************************** INPUT : A file pointer. RETURNS: None. SUMMARY: Prints module status information to given File: the fixed size of an internal memory page, the size of debug marks for a block of memory, the size of demanded and freed memory in kilobytes, remaining memory in bytes and the number of allocated pages of memory. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT int Pages; /* number of allocated pages */ int i; POINTER ActPage; /* current page in page list for a block size */ /* Calculate the total number of pages */ Pages = 0; for (i = 1; i < memory__DYNMAXSIZE; i+=memory__SHAREDPAGES) { /* increase i by memory_SHAREDPAGES due to page sharing */ ActPage = memory_ARRAY[i]->page; /* Traverse the page list */ while (*((int *)ActPage) != EOF) { Pages++; ActPage = *((POINTER *)ActPage); } } /* Print status information */ fputs("\n###\n", File); fprintf(File,"### Pagesize: %d\n", memory_PAGESIZE); fprintf(File,"### Marksize: %d\n", (int)memory_MARKSIZE); fprintf(File,"### Memory demanded: %lu KBytes\n", memory_NEWBYTES/memory__KILOBYTE); fprintf(File,"### Memory freed: %lu KBytes\n", memory_FREEDBYTES/memory__KILOBYTE); fprintf(File,"### Memory remaining: %lu Bytes\n", memory_NEWBYTES-memory_FREEDBYTES); fprintf(File,"### Pages allocated: %d Pages\n", Pages); fputs("###\n", File); #endif } void memory_PrintAllocatedBlocks(unsigned int Size) /************************************************************** INPUT : Block size. RETURNS: None. SUMMARY: Prints addresses of allocated memory blocks with given Size to stdout, if Size is less than memory_DYNMAXSIZE. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT MEMORY_RESOURCE *Resource; /* current resource */ POINTER ActPage; /* current page */ POINTER ActNext; /* next usable block on current page */ POINTER ActEndOfPage; /* end of current page */ unsigned int BlockSize; /* current block size */ #ifdef CHECK MEMORY_INFO Info; /* current block´s debug information */ #endif /* Allocated blocks are administered in two ways depending on their size. If the size is less than memory__DYNMAXSIZE the block is allocated from the appropriate page. Otherwise the block is allocated directly via a call to malloc or calloc. Thus we have two functions to print the allocated blocks: memory_PrintAllocatedBlocks and memory_PrintAlocatedBigBlocks. */ /* Check if memory_PrintAllocatedBlocks has been called for a legal block size */ if (Size >= memory__DYNMAXSIZE) { /* if that´s not the case print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_PrintAllocatedBlocks:"); misc_UserErrorReport("\n Parameter size is too big: %d.", Size); misc_UserErrorReport("\n Maximal allowed value is: %d.\n", memory__DYNMAXSIZE); misc_FinishUserErrorReport(); } else { /* otherwise size is legal */ /* initialize the variables */ Resource = memory_ARRAY[Size]; ActPage = Resource->page; ActNext = Resource->next; ActEndOfPage = Resource->end_of_page; BlockSize = Resource->total_size; /* Test if there were any requests made for blocks of that size */ if (*((int *)ActPage) == EOF) { /* Check if pointers are consistent */ if (*((int *)ActNext) == EOF) { /* If that is true, print that information to stdout */ puts(" No request so far"); } else { /* Otherwise print an error message and abort */ misc_StartErrorReport(); misc_ErrorReport("\n In memory_PrintAllocatedBlocks:"); misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n"); misc_FinishErrorReport(); } } else { /* We have received some requests for blocks of that size */ #ifdef CHECK POINTER ActData; /* current block */ /* Traverse through the page list for given block size */ while (*((int *)ActPage) != EOF) { /* Initialize the variables */ ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET; ActEndOfPage = (char *)ActPage + Resource->offset; /* Visit blocks on current page until the end of page is reached, or an allocated block is found */ while (ActData != ActNext && ActData != ActEndOfPage && memory_GetBlockStatus(ActData) != memory_MAGICMALLOC) { ActData = (char *)ActData + BlockSize; } /* Check if there were any allocated blocks from current page */ if (ActData == ActNext || ActData == ActEndOfPage) { /* if that´s not the case print the information to stdout */ printf("\n\n No memory allocated from page at address %p\n", ActPage); } else { /* otherwise print address and origin of (de)allocation of all allocated blocks on current page, starting with the block just found */ fputs("\n\n Allocated but not freed: ", stdout); do { Info = (MEMORY_INFO) ((char *) ActData - memory_OFFSET); if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC && memory_GetBlockSize(ActData) == Size) { printf("\n\t%p allocated in file %s at line %d ", ActData, Info->mallocInFile, Info->mallocAtLine); } ActData = (char *)ActData + BlockSize; } while (ActData != ActNext && ActData != ActEndOfPage); } /* go to the next page in the page list for given block size */ ActPage = *((POINTER *)ActPage); } #endif } } #endif } void memory_PrintFreedBlocks(unsigned int Size) /************************************************************** INPUT : Block size. RETURNS: None. SUMMARY: Prints addresses of freed memory blocks with given Size to stdout, if Size is less than memory_DYNMAXSIZE. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT POINTER ActFree; /* current block */ #ifdef CHECK MEMORY_INFO Info; /* current block´s debug information */ #endif /* since we don´t recycle blocks whose size is greater or equal to memory__DYNMAXSIZE, memory_PrintFreedBlocks is meaningless for such block sizes. */ /* test if given block size is legal */ if (Size >= memory__DYNMAXSIZE) { /* if that´s not the case print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_PrintFreedBlocks."); misc_UserErrorReport("\n Parameter Size is too big: %d.", Size); misc_UserErrorReport("\n Maximal allowed value is: %d.\n", memory__DYNMAXSIZE); misc_FinishUserErrorReport(); } else { /* otherwise size is legal */ /* start at the first element of the free block list for the given block size */ ActFree = memory_ARRAY[Size]->free; /* test if the free block list is empty */ if (*((int *)ActFree) == EOF) { /* if that´s true, print that information to stdout */ puts("\n\n No freed memory"); } else { /* otherwise traverse the list of freed blocks */ fputs("\n\n Free: ", stdout); while (*((int *)ActFree) != EOF) { #ifdef CHECK /* in debug mode print current block´s address and origin of (de)allocation */ /* check if block´s size is correct */ if ( memory_GetBlockSize(ActFree) == Size) { /* if that´s true than print block´s information */ Info = (MEMORY_INFO) ((char *) ActFree - memory_OFFSET); printf("\n\t%p\tallocated in file %s at line %d", ActFree, Info->mallocInFile, Info->mallocAtLine); printf("\n\t\tfreed in file %s at line %d", Info->freeInFile, Info->freeAtLine); } else { /* otherwise if we are sharing pages among different block sizes, the block is uncorrupted, despite not matching assumed and real size. But if we are not sharing pages then the block is probably corrupted, so print an error message and exit */ /* test if we are not in page sharing mode */ if (memory__SHAREDPAGES == 1) { /* if that´s true print an error message and exit */ misc_StartUserErrorReport(); misc_UserErrorReport("\n In memory_PrintFreedBlocks:"); misc_UserErrorReport("\n Memory Error. Memory block size mismatch."); misc_UserErrorReport("\n Expected %d found %d for memory block at %p.\n", Size, memory_GetBlockSize(ActFree), ActFree); misc_UserErrorReport("\n Probably the memory block was corrupted.\n"); misc_FinishUserErrorReport(); } } #endif /* go to the next free block in list */ ActFree = *((POINTER *)ActFree); } } } #endif } void memory_PrintAllocatedBigBlocks(void) /************************************************************** INPUT : None. RETURNS: None. SUMMARY: Prints addresses of all allocated memory blocks, that are greater than memory_DYNMAXSIZE to stdout. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT #ifdef CHECK MEMORY_BIGBLOCKHEADER Ptr; /* current big block in list */ MEMORY_INFO Info; /* block´s debug information */ char * BlockStart; /* block´s start address */ /* start with the first block in the big block list */ Ptr = memory_BIGBLOCKS; /* check whether big block list isn´t empty */ if (Ptr != NULL) { /* if that´s the case traverse through the list and print each block´s address, size and origin of (de)allocation information */ do { BlockStart = (char *)Ptr + memory_OFFSET + sizeof(MEMORY_BIGBLOCKHEADERNODE); Info = (MEMORY_INFO) (BlockStart - memory_OFFSET); printf("\n\t%p %d bytes allocated in file %s at line %d ", (void*)BlockStart, memory_GetBlockSize(BlockStart), Info->mallocInFile, Info->mallocAtLine); Ptr = Ptr->next; } while (Ptr != NULL); puts(""); } else { /* otherwise there are no big blocks allocated */ puts(" No request so far"); } #endif #endif } void memory_PrintDetailed(void) /************************************************************** INPUT : None. RETURNS: None. SUMMARY: Prints addresses of all pages, and allocated and freed blocks on them. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT MEMORY_RESOURCE *Resource; /* current resource */ POINTER ActPage; /* current page */ POINTER ActData; /* current block */ POINTER ActEndOfPage; /* end of current page */ unsigned int BlockSize; /* total size of a block of current size */ unsigned int PageOffset; /* current page´s offset */ unsigned int i; /* print end-of-memory pointer´s address */ printf("\n\nEOF Pointer: %p\n", (void*)&memory__EOF); /* for all administrated block sizes print detailed information */ for (i=1; ipage; ActData = Resource->next; ActEndOfPage = Resource->end_of_page; PageOffset = Resource->offset; BlockSize = Resource->total_size; /* print requested block size, aligned block size and block size including debug marks */ printf("\n\n Entry: %d aligned size: %d total size: %d\n", i , Resource->aligned_size, BlockSize); /* Check if there were any requests for blocks of size i */ if (*((int *)ActPage) == EOF) { /* if that´s not the case check if memory management is consistent */ if (*((int *)ActData) == EOF) { /* if that´s true, print that no requests occurred to stdout */ puts(" No request so far"); } else { /* our memory management is no longer consistent, so print an error message and abort. We hope that the core dump will help us to find the bug */ misc_StartErrorReport(); misc_ErrorReport("\n In memory_PrintDetailed:"); misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n"); misc_FinishErrorReport(); } } else { /* we have received requests for blocks of size i */ /* traverse the list of pages for size i */ while (*((int *)ActPage) != EOF) { /* print information about current page */ printf("\n\n Page: %p Next Page: %p\n", ActPage, *((POINTER *)ActPage)); /* initialize variables for current page */ ActData = ((char *)ActPage + sizeof(POINTER) + memory_OFFSET); ActEndOfPage = (char *)ActPage + PageOffset; /* print addresses of all blocks on current page */ fputs(" Data: ", stdout); while (ActData != ActEndOfPage) { int column; fputs("\n\t\t", stdout); for (column = 0; column < 6; column++) { printf("%p ", ActData); ActData = (char *)ActData + BlockSize; if (ActData == ActEndOfPage) { break; } } } /* go to next page in list */ ActPage = *((POINTER *)ActPage); } /* print allocated and freed blocks of size i */ memory_PrintAllocatedBlocks(i); memory_PrintFreedBlocks(i); } } #ifdef CHECK /* print allocated blocks of size >= memory_DYNMAXSIZE */ printf("\n\n Allocated blocks of size >= %d\n", memory__DYNMAXSIZE); memory_PrintAllocatedBigBlocks(); #endif #endif } void memory_PrintLeaks(void) /************************************************************** INPUT : None. RETURNS: None. SUMMARY: Prints addresses of all allocated blocks. Should be used at the end of a program before the call to memory_FreeAllMem. ***************************************************************/ { #ifndef NO_MEMORY_MANAGEMENT POINTER ActPage; /* current page */ POINTER ActNext; /* next fresh block on current page */ POINTER ActEndOfPage; /* end of current page */ MEMORY_RESOURCE *Resource; /* current resource */ unsigned int Size; /* current size */ unsigned int BlockSize; /* total block size */ /* Check if some memory is still allocated */ if (memory_UsedBytes() != 0L) { /* If that´s true, print all allocated blocks */ /* Start with blocks administered by our memory management */ for (Size = 1; Size < memory__DYNMAXSIZE; Size++) { /* Initialize variables for current block size */ Resource = memory_ARRAY[Size]; ActPage = Resource->page; ActNext = Resource->next; ActEndOfPage = Resource->end_of_page; BlockSize = Resource->total_size; /* Check if there were any requests for memory blocks of that size */ if (*((int *)ActPage) != EOF) { /* if that´s true, browse through all blocks on all pages to find a block that is still allocated */ #ifdef CHECK POINTER ActData; BOOL LeakFound; LeakFound = FALSE; while (*((int *)ActPage) != EOF) { /* search through all pages for a block that is still allocated */ ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET; ActEndOfPage = (char *)ActPage + Resource->offset; while (ActData != ActNext && ActData != ActEndOfPage) { if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC) { LeakFound = TRUE; break; } ActData = (char *)ActData + BlockSize; } if (LeakFound) { /* if we have found one, than call memory_PrintAllocatedBlocks to print its address */ printf("\n\n Leaked blocks of size %d:", Size); memory_PrintAllocatedBlocks(Size); putchar('\n'); /* since memory_PrintAllocatedblocks prints *all* allocated blocks of specific size, we can break out of the while loop */ break; } else { /* go to next page */ ActPage = *((POINTER *)ActPage); } } #endif } } #ifdef CHECK /* Print allocated blocks of size >= memory__DYNMAXSIZE */ if (memory_BIGBLOCKS != NULL) { printf("\n\n Leaked blocks of size >= %d\n", memory__DYNMAXSIZE); memory_PrintAllocatedBigBlocks(); putchar('\n'); } #endif } #endif } SPASS-3.7/SPASS/partition.c0000644000374100037200000002116411340510066012244 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PARTITION * */ /* * * */ /* * $Module: PARTITION * */ /* * * */ /* * Copyright (C) 1999, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /**************************************************************/ /* Include */ /**************************************************************/ #include "partition.h" /**************************************************************/ /* Inline functions */ /**************************************************************/ static __inline__ ECLASS part_GetClass(PARTITION p, ELEMENT e) { return p[e]; } static __inline__ PARTITION part_SetClass(PARTITION p, ELEMENT e, ECLASS c) { p[e] = c; return p; } static __inline__ int part_GetClassSize(PARTITION p, ELEMENT e) { return p[p[part_CARD] + e]; } static __inline__ PARTITION part_SetClassSize(PARTITION p, ELEMENT e, int classsize) { p[p[part_CARD] + e] = classsize; return p; } static __inline__ int part_GetStamp(PARTITION p, ELEMENT e) { return p[-part_HEAD - 1 - e]; } static __inline__ PARTITION part_SetStamp(PARTITION p, ELEMENT e, int stamp) { p[-part_HEAD - 1 - e] = stamp; return p; } static __inline__ BOOL part_Stamped(PARTITION p, ELEMENT e) { return part_GetStamp(p, e) == p[part_STAMPCOUNTER]; } static __inline__ ELEMENT part_DelayedInit(PARTITION p, ELEMENT e) /*************************************************************** RETURNS: the (now stamped) element EFFECT: establishes the equivalence class {e} in p, thus partially initializing p ***************************************************************/ { if (!part_Stamped(p, e)) { part_SetClass(p, e, -e - 1); /* representative e (>= 0) of {e} is coded */ /* as -e - 1 (< 0) */ part_SetClassSize(p, e, 1); part_SetStamp(p, e, p[part_STAMPCOUNTER]); } return e; } /**************************************************************/ /* Functions */ /**************************************************************/ PARTITION part_Create(int size) /**************************************************************** RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}} of the set {0, 1, 2, ..., size - 1} ****************************************************************/ { PARTITION result; #ifdef CHECK if (size < 0) { misc_StartErrorReport(); misc_ErrorReport("\n In part_Create: negative size %d.", size); misc_FinishErrorReport(); } #endif result = (PARTITION) memory_Calloc(size * 3 + part_HEAD, sizeof(int)) + size + part_HEAD; /* move pointer to the middle of the array */ /* to allow negative indices */ result[part_CARD] = size; result[part_ALLOC] = size * 3 + part_HEAD; result[part_STAMPCOUNTER] = 1; return result; } PARTITION part_Init(PARTITION p, int size) /**************************************************************** RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}} of the set {0, 1, 2, ..., size - 1} EFFECT: stores the initial partition to p if it's big enough, otherwise creates a new partition, therefore CAUTION: must be called inside an assignment like: p = part_Init(p, ...) ****************************************************************/ { int alloc, i; #ifdef CHECK if (size < 0) { misc_StartErrorReport(); misc_ErrorReport("\n In part_Init: negative size %d.", size); misc_FinishErrorReport(); } #endif alloc = (p[part_ALLOC] - part_HEAD) / 3; if (size > alloc) { part_Free(p); p = part_Create(size); } else { p[part_CARD] = size; p[part_STAMPCOUNTER]++; /* if a stamp overflow occurs, reinit stamps: */ if (p[part_STAMPCOUNTER] <= 0) { for (i = 0; i < alloc; i++) part_SetStamp(p, i, 0); p[part_STAMPCOUNTER] = 1; } } return p; } static ELEMENT part_NF(PARTITION p, ELEMENT e) /*************************************************************** RETURNS: the normal form element of the class [e]; this is an element of [e] that sometimes differ from the representative EFFECT: makes the normal form to the direct parent of all elements visited on the search path from e to this normal form ("path compression") ***************************************************************/ { ELEMENT nf, aux; #ifdef CHECK if (!part_Element(p, e)) { misc_StartErrorReport(); misc_ErrorReport("\n In part_NF: %d not in partitioned set.", e); misc_FinishErrorReport(); } #endif nf = e; while (part_GetClass(p, part_DelayedInit(p, nf)) >= 0) nf = part_GetClass(p, nf); /* path compression: */ while (e != nf) { aux = part_GetClass(p, e); part_SetClass(p, e, nf); e = aux; } return nf; } ECLASS part_Find(PARTITION p, ELEMENT e) /*************************************************************** RETURNS: (the representative of) class [e] ***************************************************************/ { #ifdef CHECK if (!part_Element(p, e)) { misc_StartErrorReport(); misc_ErrorReport("\n In part_Find: %d not in partitioned set.", e); misc_FinishErrorReport(); } #endif return -part_GetClass(p, part_NF(p, e)) - 1; /* representative e is coded as -e - 1 (cf. part_DelayedInit) */ } PARTITION part_Union(PARTITION p, ECLASS c1, ECLASS c2) /*************************************************************** RETURNS: the union of the classes EFFECT: the representative of c1 is the representative of the union ***************************************************************/ { ELEMENT nf1, nf2, aux; #ifdef CHECK if (!part_Element(p, c1)) { misc_StartErrorReport(); misc_ErrorReport("\n In part_Union: first class %d not in partitioned set.", c1); misc_FinishErrorReport(); } if (!part_Element(p, c2)) { misc_StartErrorReport(); misc_ErrorReport ("\n In part_Union: second class %d not in partitioned set.", c2); misc_FinishErrorReport(); } #endif nf1 = part_NF(p, c1); nf2 = part_NF(p, c2); if (nf1 != nf2) { /* make [nf1] the bigger (or at least not smaller) class: */ if (part_GetClassSize(p, nf1) < part_GetClassSize(p, nf2)) { aux = nf1; nf1 = nf2; nf2 = aux; part_SetClass(p, nf1, part_GetClass(p, nf2)); part_SetClass(p, -part_GetClass(p, nf2) - 1, nf1); } part_SetClass(p, nf2, nf1); part_SetClassSize(p, nf1, part_GetClassSize(p, nf1) + part_GetClassSize(p, nf2)); } return p; } SPASS-3.7/SPASS/config.h.in0000644000374100037200000000470511340746530012123 00000000000000/* SPASS/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_MMSYSTEM_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the `time' function. */ #undef HAVE_TIME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_WINDOWS_H /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const SPASS-3.7/SPASS/description.h0000644000374100037200000000510711334355234012571 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PROBLEM DESCRIPTION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ #ifndef _DESC_ #define _DESC_ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /**************************************************************/ /* Includes */ /**************************************************************/ #include #include "memory.h" #include "strings.h" /**************************************************************/ /* Structures */ /**************************************************************/ typedef enum { DFG_SATISFIABLE, DFG_UNSATISFIABLE, DFG_UNKNOWNSTATE } DFG_STATE; /* Used for the texts from description section. */ typedef struct DFGDESCRIPTION_HELP { char* name; char* author; char* version; char* logic; DFG_STATE status; char* description; char* date; } DFGDESCRIPTION_NODE; typedef DFGDESCRIPTION_NODE* DFGDESCRIPTION; /**************************************************************/ /* Functions */ /**************************************************************/ DFGDESCRIPTION desc_Create(void); void desc_Delete(DFGDESCRIPTION); /* Functions for accessing description information */ const char* desc_Name(DFGDESCRIPTION); const char* desc_Author(DFGDESCRIPTION); const char* desc_Version(DFGDESCRIPTION); const char* desc_Logic(DFGDESCRIPTION); const char* desc_StatusString(DFGDESCRIPTION); DFG_STATE desc_Status(DFGDESCRIPTION); const char* desc_Description(DFGDESCRIPTION); const char* desc_Date(DFGDESCRIPTION); void desc_FPrintDescription(DFGDESCRIPTION, FILE*); #endif SPASS-3.7/SPASS/rules-sort.h0000644000374100037200000000706411340510067012363 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * INFERENCE RULES FOR SORTS * */ /* * * */ /* * $Module: SORTRULES * */ /* * * */ /* * Copyright (C) 1996, 1997, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: rules-sort.h,v $ */ #ifndef _SORTRULES_ #define _SORTRULES_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "sort.h" #include "unify.h" #include "clause.h" #include "flags.h" /**************************************************************/ /* Functions */ /**************************************************************/ LIST inf_ForwardSortResolution(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, PRECEDENCE); LIST inf_BackwardSortResolution(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, PRECEDENCE); LIST inf_ForwardEmptySort(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, PRECEDENCE); LIST inf_BackwardEmptySort(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, PRECEDENCE); LIST inf_ForwardWeakening(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); LIST inf_BackwardWeakening(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); LIST inf_ForwardEmptySortPlusPlus(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); LIST inf_BackwardEmptySortPlusPlus(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); #endif SPASS-3.7/SPASS/term.c0000644000374100037200000021653211340510067011210 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * TERMS * */ /* * * */ /* * $Module: TERM * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: term.c,v $ */ #include "term.h" /**************************************************************/ /* Global variables */ /**************************************************************/ NAT term_MARK; POINTER term_BIND[symbol__MAXVARIABLES][2]; #ifdef CHECK BOOL term_BINDPHASE; #endif NAT term_STAMP; BOOL term_STAMPBLOCKED; static BOOL term_STAMPOVERFLOW[term_MAXSTAMPUSERS]; static NAT term_STAMPUSERS; /**************************************************************/ /* ********************************************************** */ /* * * */ /* * TERM CREATION FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void term_Init(void) /********************************************************** INPUT: None. RETURNS: None. CAUTION: The term module is initialized. ***********************************************************/ { int i; term_MARK = 1; term_STAMP = 0; term_STAMPBLOCKED = FALSE; for (i = 0; i < term_MAXSTAMPUSERS; i++) term_STAMPOVERFLOW[i] = FALSE; term_STAMPUSERS = 0; #ifdef CHECK term_BINDPHASE = FALSE; #endif } TERM term_Create(SYMBOL Symbol, LIST List) /********************************************************** INPUT: A symbol and a list of arguments. RETURNS: A term consisting of the top symbol 'Symbol' and the arguments stored in 'List'. CAUTION: None. ********************************************************/ { TERM Result; #ifdef CHECK if (!symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Create: Illegal symbol."); misc_FinishErrorReport(); } if (!term_IsTermList(List)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Create: Illegal term list."); misc_FinishErrorReport(); } #endif Result = (TERM)memory_Malloc(sizeof(TERM_NODE)); Result->symbol = Symbol; Result->args = List; Result->super.termlist = list_Nil(); Result->stamp = 0; Result->size = 0; return Result; } TERM term_CreateAddFather(SYMBOL Symbol, LIST List) /********************************************************** INPUT: A symbol and a list of arguments. RETURNS: A term consisting of the top symbol 'Symbol' and the arguments stored in 'List'. In contrast to term_Create the superterm members are set for the arguments. CAUTION: None. ********************************************************/ { TERM Result; LIST l; Result = term_Create(Symbol, List); for (l=term_ArgumentList(Result); !list_Empty(l); l = list_Cdr(l)) term_RplacSuperterm((TERM) list_Car(l), Result); return Result; } TERM term_CreateStandardVariable(void) /********************************************************** RETURNS: Returns a term with a new variable as top symbol. ***********************************************************/ { return term_Create(symbol_CreateStandardVariable(), list_Nil()); } void term_Delete(TERM Term) /********************************************************** INPUT: A term. SUMMARY: Deletes the term and frees the storage. CAUTION: The arguments of Term are also deleted. ********************************************************/ { if (term_IsComplex(Term)) { LIST Scan; for (Scan = term_ArgumentList(Term); list_Exist(Scan); Scan = list_Cdr(Scan)) term_Delete(list_Car(Scan)); list_Delete(term_ArgumentList(Term)); } term_Free(Term); } void term_DeleteIterative(TERM Term) /********************************************************** INPUT: A term. SUMMARY: Deletes the term and frees the storage. CAUTION: The arguments of Term are also deleted. ********************************************************/ { if (term_IsComplex(Term)) { LIST Stack, Aux; Stack = list_StackBottom(); do { if (term_IsComplex(Term)) Stack = list_Push(term_ArgumentList(Term),Stack); term_Free(Term); while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) Stack = list_Pop(Stack); if (!list_StackEmpty(Stack)) { Aux = list_Top(Stack); Term = (TERM)list_Car(Aux); list_RplacTop(Stack, list_Cdr(Aux)); list_Free(Aux); } } while (!list_StackEmpty(Stack)); } else term_Free(Term); } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * PRIMITIVE TERM FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL term_Equal(TERM Term1, TERM Term2) /********************************************************* INPUT: Two terms. RETURNS: The boolean value TRUE if the terms are equal. CAUTION: EQUAL FUNCTION- OR PREDICATE SYMBOLS SHARE THE SAME ARITY. THIS IS NOT VALID FOR JUNCTORS! **********************************************************/ { #ifdef CHECK if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Equal: Illegal input."); misc_FinishErrorReport(); } #endif /* if (term_IsIndexVariable(Term1)) puts("\nterm_Equal: Left index variable."); else if (term_IsIndexVariable(Term2)) puts("\nterm_Equal: Right index variable."); fflush(stdout); */ if (Term1 == Term2) /* pointers are equal */ return TRUE; else if (!term_EqualTopSymbols(Term1, Term2)) return FALSE; else if (term_ArgumentList(Term1)) { LIST Scan1, Scan2; for (Scan1=term_ArgumentList(Term1), Scan2=term_ArgumentList(Term2); list_Exist(Scan1) && list_Exist(Scan2); Scan1=list_Cdr(Scan1), Scan2=list_Cdr(Scan2)) if (!term_Equal(list_Car(Scan1),list_Car(Scan2))) return FALSE; return (list_Empty(Scan1) ? list_Empty(Scan2) : FALSE); } else return TRUE; } BOOL term_EqualIterative(TERM Term1, TERM Term2) /********************************************************* INPUT: Two terms. RETURNS: The boolean value TRUE if the terms are equal. CAUTION: Notice that there may be symbols with arbitrary arity *******************************************************/ { LIST Stack1,Stack2; #ifdef CHECK if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_EqualIterative: Illegal input."); misc_FinishErrorReport(); } #endif Stack1 = Stack2 = list_StackBottom(); do { if (term_EqualTopSymbols(Term1,Term2) && term_IsComplex(Term1) && term_IsComplex(Term2)) { Stack1 = list_Push(term_ArgumentList(Term1),Stack1); Stack2 = list_Push(term_ArgumentList(Term2),Stack2); } if (!term_EqualTopSymbols(Term1,Term2) || term_IsComplex(Term1) != term_IsComplex(Term2)) { Stack1 = list_StackFree(Stack1); Stack2 = list_StackFree(Stack2); return FALSE; } while (!list_StackEmpty(Stack1) && list_Empty(list_Top(Stack1))) if (!list_StackEmpty(Stack2) && list_Empty(list_Top(Stack2))) { Stack1 = list_Pop(Stack1); Stack2 = list_Pop(Stack2); } else { Stack1 = list_StackFree(Stack1); Stack2 = list_StackFree(Stack2); return FALSE; } if (!list_StackEmpty(Stack1)) { if (!list_Empty(list_Top(Stack2))) { Term1 = (TERM)list_Car(list_Top(Stack1)); list_RplacTop(Stack1, list_Cdr(list_Top(Stack1))); Term2 = (TERM)list_Car(list_Top(Stack2)); list_RplacTop(Stack2, list_Cdr(list_Top(Stack2))); } else { Stack1 = list_StackFree(Stack1); Stack2 = list_StackFree(Stack2); return FALSE; } } } while (!list_StackEmpty(Stack1)); return TRUE; } BOOL term_VariableEqual(TERM Variable1, TERM Variable2) /********************************************************* INPUT: Two Variables. RETURNS: The boolean value TRUE, if the variables are equal. **********************************************************/ { return term_EqualTopSymbols(Variable1, Variable2); } BOOL term_IsGround(TERM Term) /********************************************************** INPUT: A term. RETURNS: A boolean value which is TRUE, if 'Term' is a ground term, i.e. does not contain variables. ********************************************************/ { #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_IsGround: Illegal input."); misc_FinishErrorReport(); } #endif if (term_IsComplex(Term)) { LIST Stack; Stack = list_StackBottom(); do { if (term_IsComplex(Term)) Stack = list_Push(term_ArgumentList(Term),Stack); else if (term_IsVariable(Term)) { Stack = list_StackFree(Stack); return FALSE; } while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) Stack = list_Pop(Stack); if (!list_StackEmpty(Stack)) { Term = (TERM)list_Car(list_Top(Stack)); list_RplacTop(Stack, list_Cdr(list_Top(Stack))); } } while (!list_StackEmpty(Stack)); return TRUE; } else return !term_IsVariable(Term); } BOOL term_IsTerm(TERM Term) /********************************************************* INPUT: A term. RETURNS: TRUE, if 'Term' is not NULL and has a symbol as its top symbol. **********************************************************/ { return (Term != (TERM)NULL && symbol_IsSymbol(term_TopSymbol(Term))); } BOOL term_IsTermList(LIST TermList) /********************************************************* INPUT: A term. RETURNS: TRUE iff is a list of terms. *******************************************************/ { for ( ; !list_Empty(TermList); TermList=list_Cdr(TermList)) if (!(term_IsTerm((TERM)list_Car(TermList)))) return FALSE; return TRUE; } BOOL term_AllArgsAreVar(TERM Term) /********************************************************* INPUT: A term. RETURNS: The boolean value TRUE, if all arguments of the term are variables. *******************************************************/ { LIST Scan; for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) if (!term_IsVariable(list_Car(Scan))) return FALSE; return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * LOW LEVEL FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ TERM term_Copy(TERM Term) /********************************************************** INPUT: A term. RETURNS: A copy of 'Term' where the stamp field is copied, too. SUMMARY: Copies "Term" and returns a pointer to the copy. *********************************************************/ { TERM Result; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Copy: Illegal input."); misc_FinishErrorReport(); } #endif if (term_IsComplex(Term)) { LIST Scan, ArgumentList; for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); list_Exist(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, term_Copy(list_Car(Scan))); Result = term_Create(term_TopSymbol(Term), ArgumentList); } else Result = term_Create(term_TopSymbol(Term), list_Nil()); Result->stamp = Term->stamp; Result->size = Term->size; return Result; } TERM term_CopyIterative(TERM Term) /********************************************************** INPUT: A term. RETURNS: A copy of . SUMMARY: Copies and returns a pointer to the copy. *********************************************************/ { #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_CopyIterative: Illegal input."); misc_FinishErrorReport(); } #endif if (term_IsComplex(Term)) { LIST TopStack, ArgumentStack, ActStack; TopStack = list_Push((POINTER)term_TopSymbol(Term), list_StackBottom()); ArgumentStack = list_Push(list_Copy(term_ArgumentList(Term)), list_StackBottom()); ActStack = list_Push(list_Top(ArgumentStack), list_StackBottom()); while (!list_StackEmpty(TopStack)) { if (list_Empty(list_Top(ActStack))) { Term = term_Create((SYMBOL)list_Top(TopStack), (LIST)list_Top(ArgumentStack)); TopStack = list_Pop(TopStack); ArgumentStack = list_Pop(ArgumentStack); ActStack = list_Pop(ActStack); if (!list_StackEmpty(TopStack)) { list_Rplaca(list_Top(ActStack), Term); list_RplacTop(ActStack, list_Cdr(list_Top(ActStack))); } } else { Term = (TERM)list_Car(list_Top(ActStack)); if (term_IsComplex(Term)) { TopStack = list_Push((POINTER)term_TopSymbol(Term), TopStack); ArgumentStack = list_Push(list_Copy(term_ArgumentList(Term)), ArgumentStack); ActStack = list_Push(list_Top(ArgumentStack), ActStack); } else { list_Rplaca(list_Top(ActStack), term_Create(term_TopSymbol(Term), list_Nil())); list_RplacTop(ActStack, list_Cdr(list_Top(ActStack))); } } } return Term; } else return term_Create(term_TopSymbol(Term), list_Nil()); } TERM term_CopyWithEmptyArgListNode(TERM Term, LIST ArgListNode, LIST* ListNodeCopyPt) /********************************************************** INPUT: A term and a pointer to an argument list node of this term. RETURNS: A copy of 'Term' with a NULL as list_Car(ListNodeCopy). SUMMARY: Copies "Term" and returns a pointer to the copy. *********************************************************/ { #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_CopyWithEmptyArgListNode: Illegal input."); misc_FinishErrorReport(); } #endif if (term_IsComplex(Term)) { LIST Scan, ArgumentList, HelpScan; TERM Result; HelpScan = term_ArgumentList(Term); ArgumentList = list_Copy(HelpScan); for (Scan = ArgumentList; list_Exist(Scan); Scan = list_Cdr(Scan),HelpScan = list_Cdr(HelpScan)) if (HelpScan != ArgListNode) list_Rplaca(Scan, term_CopyWithEmptyArgListNode(list_Car(Scan), ArgListNode, ListNodeCopyPt)); else{ list_Rplaca(Scan, (TERM)NULL); *ListNodeCopyPt = Scan; } Result = (TERM)memory_Malloc(sizeof(TERM_NODE)); Result->symbol = term_TopSymbol(Term); Result->args = ArgumentList; Result->super.termlist = list_Nil(); return Result; } else return term_Create(term_TopSymbol(Term), list_Nil()); } void term_PrintWithEmptyArgListNode(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints any term to stdout, especially terms with empty argument list nodes. CAUTION: Uses the other term_Output functions. *************************************************************/ { if (Term == (TERM)NULL) fputs("(NULL)", stdout); else if (term_IsComplex(Term)) { putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(' '); list_Apply((void (*)(POINTER)) term_PrintWithEmptyArgListNode, term_ArgumentList(Term)); putchar(')'); } else if (term_IsVariable(Term)) { symbol_Print(term_TopSymbol(Term)); } else { /* term_IsConstant(Term) */ putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(')'); } } BOOL term_ReplaceSubtermBy(TERM Atom, TERM TermS, TERM TermT) /************************************************************** INPUT: Three terms. RETURNS: None. EFFECT: Replaces all occurrences of TermS in Atom by TermT. Top level is NOT considered! *************************************************************/ { LIST ArgListNode; BOOL Replaced; int B_Stack; #ifdef CHECK if (!term_IsTerm(Atom) || !term_IsTerm(TermS) || !term_IsTerm(TermT) || term_Equal(Atom, TermS)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ReplaceSubtermBy: Illegal input."); misc_FinishErrorReport(); } #endif /*fputs("\nWe look for: ",stdout);term_Print(TermS); fputs("\nin: ",stdout);term_Print(Atom); */ Replaced = FALSE; TermS = term_Copy(TermS); if (!term_Equal(Atom, TermS) && !list_Empty(term_ArgumentList(Atom))) { B_Stack = stack_Bottom(); stack_Push(term_ArgumentList(Atom)); while (!stack_Empty(B_Stack)) { ArgListNode = stack_Top(); Atom = (TERM)list_Car(ArgListNode); stack_RplacTop(list_Cdr(ArgListNode)); if (term_Equal(Atom, TermS)) { Replaced = TRUE; list_Rplaca(ArgListNode, term_Copy(TermT)); term_Delete(Atom); } else if (term_IsComplex(Atom)) stack_Push(term_ArgumentList(Atom)); while (!stack_Empty(B_Stack) && list_Empty(stack_Top())) stack_Pop(); } } term_Delete(TermS); return Replaced; } void term_ReplaceVariable(TERM Term, SYMBOL Symbol, TERM Repl) /************************************************************** INPUT: A term, a variable symbol and a replacement term. RETURNS: void EFFECT: All variables with in are replaced with copies of CAUTION: Destructive ***************************************************************/ { LIST Scan; #ifdef CHECK if (!term_IsTerm(Term) || !term_IsTerm(Repl) || !symbol_IsVariable(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ReplaceVariable: Illegal input."); misc_FinishErrorReport(); } #endif if (symbol_Equal(term_TopSymbol(Term), Symbol)) { term_RplacTop(Term,term_TopSymbol(Repl)); term_RplacArgumentList(Term,term_CopyTermList(term_ArgumentList(Repl))); } else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) term_ReplaceVariable(list_Car(Scan),Symbol,Repl); } void term_ExchangeVariable(TERM Term, SYMBOL Old, SYMBOL New) /************************************************************** INPUT: A term, and two variable symbols. RETURNS: void EFFECT: All variables in are replaced with CAUTION: Destructive ***************************************************************/ { LIST Scan; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsVariable(Old) || !symbol_IsVariable(New)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ExchangeVariable: Illegal input."); misc_FinishErrorReport(); } #endif if (symbol_Equal(term_TopSymbol(Term), Old)) term_RplacTop(Term,New); else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) term_ExchangeVariable(list_Car(Scan),Old,New); } BOOL term_SubstituteVariable(SYMBOL Symbol, TERM Repl, TERM Term) /****************************************************** INPUT: A Symbol which has to be found in the Term, a term which is the replacement for the 'Symbol', and a term in which the substitu- tions take place. RETURNS: A boolean value which is TRUE, if any sub- stitutions were made. SUMMARY: term_Substitute works recursively and repl. every occurence of 'Symbol' in 'Term' by 'Repl'. CAUTION: FUNCTION IS DESTRUCTIVE ON 'Term'. REPLACE- MENT IS COPIED EACH TIME A SUB. TAKES PLACE *******************************************************/ { #ifdef CHECK if (!term_IsTerm(Term) || !term_IsTerm(Repl) || !symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_SubstituteVariable: Illegal input."); misc_FinishErrorReport(); } #endif if (symbol_Equal(term_TopSymbol(Term), Symbol)) { TERM New; New = term_Copy(Repl); Term->symbol = Repl->symbol; Term->args = term_ArgumentList(New); /* Free Top-Node of New, as the symbol has been written */ /* into the node pointed to by `Term'. */ memory_Free(New, sizeof(TERM_NODE)); return TRUE; } else { BOOL Result; LIST List; Result = FALSE; for (List = term_ArgumentList(Term); list_Exist(List); List = list_Cdr(List)) if (term_SubstituteVariable(Symbol, Repl, List->car)) Result = TRUE; return Result; } } static int term_CompareByConstants(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: The terms are compared by their multisets of constants. The frequency of elements in the multisets is a multiset itself. The frequencies are sorted and the resulting sorted multisets compared. ***************************************************************/ { LIST lconsts, rconsts; int result; /* Get multiset of constants. */ lconsts = term_ListOfConstants(Left); rconsts = term_ListOfConstants(Right); result = list_CompareMultisetsByElementDistribution(lconsts, rconsts); list_Delete(lconsts); list_Delete(rconsts); return result; } static int term_CompareByFunctions(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: The terms are compared by their multisets of functions. The frequency of elements in the multisets is a multiset itself. The frequencies are sorted and the resulting sorted multisets compared. ***************************************************************/ { LIST lfuns, rfuns; int result; /* Get multiset of functions. */ lfuns = term_ListOfFunctions(Left); rfuns = term_ListOfFunctions(Right); result = list_CompareMultisetsByElementDistribution(lfuns, rfuns); list_Delete(lfuns); list_Delete(rfuns); return result; } static int term_CompareByVariables(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: The terms are compared by their multisets of variables. The frequency of elements in the multisets is a multiset itself. The frequencies are sorted and the resulting sorted multisets compared. ***************************************************************/ { LIST lvars, rvars; int result; /* Get multiset of variables. */ lvars = term_ListOfVariables(Left); rvars = term_ListOfVariables(Right); result = list_CompareMultisetsByElementDistribution(lvars, rvars); list_Delete(lvars); list_Delete(rvars); return result; } LIST term_ListOfConstants(TERM Term) /************************************************************** INPUT: A term. RETURNS: A list of constants. EFFECT: Creates a list of constants used in a term. If no constants are used in a term, it returns an empty list. ***************************************************************/ { #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ListOfConstants: Illegal input."); misc_FinishErrorReport(); } #endif if (symbol_IsConstant(term_TopSymbol(Term))) return list_List((POINTER) term_TopSymbol(Term)); else { LIST result; LIST scan; result = list_Nil(); for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { /* Append to the smaller list for efficiency. A subterm's list of constants will usually be smaller than the intermediate result. */ result = list_Nconc(term_ListOfConstants((TERM) list_Car(scan)), result); } return result; } } LIST term_ListOfFunctions(TERM Term) /************************************************************** INPUT: A term. RETURNS: A list of functions. EFFECT: Creates a list of functions used in a term. If no functions are used in a term, it returns an empty list. ***************************************************************/ { LIST result; LIST scan; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ListOfFunctions: Illegal input."); misc_FinishErrorReport(); } #endif result = list_Nil(); /* If the term starts with a function, add the function symbol to the result. */ if (symbol_IsFunction(term_TopSymbol(Term))) { result = list_Nconc(result, list_List((POINTER) term_TopSymbol(Term))); } /* A function can utilize other functions, so traverse the argument list for further functions. */ for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { /* Append to the smaller list for efficiency. A subterm's list of functions will usually be smaller than the intermediate result. */ result = list_Nconc(term_ListOfFunctions((TERM) list_Car(scan)), result); } return result; } void term_CountSymbols(TERM Term) /************************************************************** INPUT: A term. RETURNS: None. EFFECT: Counts the non-variable symbols in the term, and increases their counts accordingly. ***************************************************************/ { LIST scan; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_CountSymbols: Illegal input."); misc_FinishErrorReport(); } #endif /* If the term starts with a function, increase the count for the function symbol. */ if (symbol_IsFunction(term_TopSymbol(Term))) { SYMBOL S; S = term_TopSymbol(Term); symbol_SetCount(S, symbol_GetCount(S) + 1); } /* A function can utilize other functions, so traverse the argument list for further function symbols. */ for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { term_CountSymbols((TERM) list_Car(scan)); } } static int term_CompareByArity(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: Terms are compared top down, left to right with respect to the arity of their signature symbols, where variables in addition are defined to be smaller than constants. ***************************************************************/ { NAT lval, rval; SYMBOL lsymb, rsymb; LIST largs, rargs; int result; result = 0; /* Compare top symbols first */ lsymb = term_TopSymbol(Left); rsymb = term_TopSymbol(Right); if (symbol_IsVariable(lsymb)) { if (symbol_IsVariable(rsymb)) return 0; else return 1; } else if (symbol_IsVariable(rsymb)) return -1; lval = symbol_Arity(lsymb); rval = symbol_Arity(rsymb); if (lval > rval) return -1; if (lval < rval) return 1; /* If top symbol arities are equal, compare subterms left to right */ largs = term_ArgumentList(Left); rargs = term_ArgumentList(Right); while(!list_Empty(largs)) { result = term_CompareByArity(list_Car(largs), list_Car(rargs)); if (result != 0) break; largs = list_Cdr(largs); rargs = list_Cdr(rargs); } return result; } int term_CompareBySymbolOccurences(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: Terms are compared top down, left to right with respect to the frequency of their symbols. ***************************************************************/ { unsigned long lval, rval; SYMBOL lsymb, rsymb; LIST largs, rargs; int result; result = 0; /* Compare top symbols first */ lsymb = term_TopSymbol(Left); rsymb = term_TopSymbol(Right); if (symbol_IsFunction(lsymb)) { if (symbol_IsFunction(rsymb)) { lval = symbol_GetCount(lsymb); rval = symbol_GetCount(rsymb); if (lval > rval) return -1; if (lval < rval) return 1; /* If top symbol arities are equal, compare subterms left to right */ largs = term_ArgumentList(Left); rargs = term_ArgumentList(Right); while(!list_Empty(largs)) { result = term_CompareBySymbolOccurences(list_Car(largs), list_Car(rargs)); if (result != 0) break; largs = list_Cdr(largs); rargs = list_Cdr(rargs); } } else { return -1; } } else { if (symbol_IsFunction(rsymb)) { return 1; } } return result; } int term_CompareAbstract(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: 1 if left term < right term 0 if left term = right term -1 if left term > right term EFFECT: Compares two terms using an internal array of term comparison functions. As soon as a term is found to compare greater than the other, the result of the comparison is returned. If all term comparison functions yield an "equal", then 0 is returned. ***************************************************************/ { int result; int i; int functions; typedef int (*TERM_COMPARE_FUNCTION) (TERM, TERM); static const TERM_COMPARE_FUNCTION term_compare_functions [] = { term_CompareByArity, term_CompareBySymbolOccurences, term_CompareByConstants, term_CompareByVariables, term_CompareByFunctions }; #ifdef CHECK if (!(term_IsTerm(Left) && term_IsTerm(Right))) { misc_StartErrorReport(); misc_ErrorReport("\n In term_CompareAbstract: Illegal input."); misc_FinishErrorReport(); } #endif result = 0; functions = sizeof(term_compare_functions)/sizeof(TERM_COMPARE_FUNCTION); for (i = 0; i < functions; i++) { result = term_compare_functions[i](Left, Right); if ( result != 0) { return result; } } return result; } BOOL term_CompareAbstractLEQ(TERM Left, TERM Right) /************************************************************** INPUT: Two terms. RETURNS: TRUE if left term <= right term, FALSE otherwise. EFFECT: Terms are compared top down, left to right with respect to the arity of their signature symbols, where variables in addition are defined to be smaller than constants. ***************************************************************/ { return (term_CompareAbstract(Left, Right) >= 0); } NAT term_ComputeSize(TERM Term) /************************************************************** INPUT: A term. RETURNS: The number of symbols in the term. EFFECT: None ***************************************************************/ { NAT Weight; LIST Scan; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ComputeSize: Illegal input."); misc_FinishErrorReport(); } #endif Weight = 1; for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) Weight += term_ComputeSize((TERM)list_Car(Scan)); return Weight; } NAT term_RootDistance(TERM Term) /************************************************************** INPUT: A term with establised father links. RETURNS: The distance from to its root father term. EFFECT: None ***************************************************************/ { NAT Distance; Distance = 0; while (term_Superterm(Term) != (TERM)NULL) { Distance++; Term = term_Superterm(Term); } return Distance; } BOOL term_RootDistanceSmaller(TERM Term1, TERM Term2) /************************************************************** INPUT: Two terms with establised father links. RETURNS: TRUE iff root distance of is smaller than root distance of EFFECT: None ***************************************************************/ { return (term_RootDistance(Term1) Depth) Depth = Help; } return (Depth+1); } BOOL term_ContainsSymbol(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A term and a symbol. RETURNS: TRUE, if the symbol occurs somewhere in the term, FALSE otherwise. ***************************************************************/ { int Stack; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ContainsSymbol: Illegal input."); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); do { if (term_TopSymbol(Term) == Symbol) { stack_SetBottom(Stack); /* Clean up the stack */ return TRUE; } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return FALSE; } TERM term_FindSubterm(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A term and a symbol. RETURNS: If the symbol occurs in the Term the subterm is returned. NULL otherwise. ***************************************************************/ { int stack; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_FindSubterm: Illegal input."); misc_FinishErrorReport(); } #endif stack = stack_Bottom(); do { if (term_TopSymbol(Term) == Symbol) { stack_SetBottom(stack); /* Clean up the stack */ return Term; } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(stack)) { Term = list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(stack)); return NULL; } static int term_SharingList(TERM Term, LIST List) /************************************************************** INPUT: A term and a list cell. RETURNS: The number of times occurs in EFFECT: None ***************************************************************/ { LIST Scan; int n; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_SharingList: Illegal input."); misc_FinishErrorReport(); } #endif n = 0; for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { if (Scan == List) n++; n += term_SharingList(list_Car(Scan), List); } return n; } static int term_SharingTerm(TERM Term, TERM CompareTerm) /************************************************************** INPUT: A term and a compare term RETURNS: The number of occurrences of in EFFECT: None ***************************************************************/ { LIST Scan; int n; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_SharingTerm: Illegal input."); misc_FinishErrorReport(); } #endif n = 0; if (Term == CompareTerm) n = 1; for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) n += term_SharingTerm(list_Car(Scan),CompareTerm); return n; } BOOL term_Sharing(TERM Term) /************************************************************** INPUT: A term. RETURNS: TRUE iff the term shares list cells or subterms. EFFECT: None ***************************************************************/ { LIST Scan; int stack; TERM ActTerm; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Sharing: Illegal input."); misc_FinishErrorReport(); } #endif stack = stack_Bottom(); stack_Push(Term); while (!stack_Empty(stack)) { ActTerm = (TERM)stack_Top(); stack_Pop(); if (term_SharingTerm(Term,ActTerm)>1) return TRUE; if (term_IsComplex(Term)) { for (Scan = term_ArgumentList(ActTerm); !list_Empty(Scan); Scan=list_Cdr(Scan)) if (term_SharingList(Term, Scan) > 1) return TRUE; else stack_Push(list_Car(Scan)); } } return FALSE; } void term_AddFatherLinks(TERM Term) /************************************************************** INPUT: A term. RETURNS: void. EFFECT: The super term links of Term are cleared and then all its subterms are set. ***************************************************************/ { LIST Scan; TERM ActTerm; term_RplacSuperterm(Term,(TERM)NULL); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { ActTerm = (TERM)list_Car(Scan); term_AddFatherLinks(ActTerm); term_RplacSuperterm(ActTerm,Term); } } BOOL term_FatherLinksEstablished(TERM Term) /************************************************************** INPUT: A term. RETURNS: TRUE iff all father links in Term are established. EFFECT: None. ***************************************************************/ { LIST Scan; for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (Term != term_Superterm(list_Car(Scan)) || !term_FatherLinksEstablished(list_Car(Scan))) return FALSE; return TRUE; } TERM term_TopLevelTerm(TERM Term) /************************************************************** INPUT: A term. RETURNS: The top level father of the term. EFFECT: The father links have to be established! ***************************************************************/ { while (term_Superterm(Term)) Term = term_Superterm(Term); return Term; } BOOL term_HasPointerSubterm(TERM Term, TERM Subterm) /************************************************************** INPUT: Two terms. RETURNS: TRUE, if has as a subterm. CAUTION: Only term pointers are compared, term_Equal isn't used. ***************************************************************/ { if (Term == Subterm) return TRUE; else { LIST scan = term_ArgumentList(Term); while (!list_Empty(scan)) { if (term_HasPointerSubterm((TERM) list_Car(scan), Subterm)) return TRUE; scan = list_Cdr(scan); } } return FALSE; } BOOL term_HasSubterm(TERM Term, TERM Subterm) /************************************************************** INPUT: Two terms. RETURNS: TRUE, if has as a subterm. CAUTION: term_Equal is used. ***************************************************************/ { if (term_Equal(Term,Subterm)) return TRUE; else { LIST Scan; Scan = term_ArgumentList(Term); while (!list_Empty(Scan)) { if (term_HasSubterm((TERM) list_Car(Scan), Subterm)) return TRUE; Scan = list_Cdr(Scan); } } return FALSE; } BOOL term_HasProperSuperterm(TERM Term, TERM Super) /********************************************************** INPUT : Two terms. RETURNS : TRUE iff Super can be reached from Term by following the superterm member of the TERM structure. CAUTION : not reflexive **********************************************************/ { if (Term == Super) return FALSE; while (Term != (TERM) NULL) { if (Term == Super) /* Pointer equality ! */ return TRUE; else Term = term_Superterm(Term); } return FALSE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * TERM OUTPUT FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void term_Print(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints the term to stdout. CAUTION: Uses the other term output functions. ***************************************************************/ { if (term_IsComplex(Term)) { putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(' '); term_TermListPrint(term_ArgumentList(Term)); putchar(')'); } else if (term_IsVariable(Term)) { symbol_Print(term_TopSymbol(Term)); } else { /* term_IsConstant(Term) */ putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(')'); } } static void term_PrettyPrintIntern(TERM Term, int Depth) /************************************************************** INPUT: A term and a depth parameter for indentation. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { int i; LIST scan; for (i=0; i < Depth; i++) fputs(" ", stdout); if (symbol_IsJunctor(term_TopSymbol(Term))) { if (term_IsComplex(Term)) { symbol_Print(term_TopSymbol(Term)); putchar('('); fputs("\n", stdout); for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { term_PrettyPrintIntern((TERM) list_Car(scan), Depth+1); if (!list_Empty(list_Cdr(scan))) fputs(",\n", stdout); } putchar(')'); } else { if (term_IsVariable(Term)) { symbol_Print(term_TopSymbol(Term)); } else { putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(')'); } } } else { term_PrintPrefix(Term); } } void term_PrettyPrint(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { term_PrettyPrintIntern(Term, 0); } void term_FPrint(FILE* File,TERM Term) /************************************************************** INPUT: A file and a term. RETURNS: none. SUMMARY: Prints the term to the file. CAUTION: Uses the other term output functions. ***************************************************************/ { if (term_IsComplex(Term)) { putc('(', File); symbol_FPrint(File,term_TopSymbol(Term)); putc(' ', File); term_TermListFPrint(File,term_ArgumentList(Term)); putc(')', File); } else if (term_IsVariable(Term)) { symbol_FPrint(File,term_TopSymbol(Term)); } else { /* term_IsConstant(Term) */ putc('(', File); symbol_FPrint(File,term_TopSymbol(Term)); putc(')', File); } } void term_TermListPrint(LIST List) /************************************************************** INPUT: A list of terms. RETURNS: None. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { term_Print(list_Car(List)); fflush(stdout); if (!list_Empty(list_Cdr(List))) putchar(' '); } } void term_TermListFPrint(FILE* File, LIST List) /************************************************************** INPUT: A list of terms. RETURNS: None. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { term_FPrint(File,list_Car(List)); if (!list_Empty(list_Cdr(List))) putc(' ', File); } } void term_PrintPrefix(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints the term in prefix notation to stdout. CAUTION: Uses the other term output functions. ***************************************************************/ { if (term_IsComplex(Term)) { symbol_Print(term_TopSymbol(Term)); putchar('('); term_TermListPrintPrefix(term_ArgumentList(Term)); putchar(')'); } else symbol_Print(term_TopSymbol(Term)); } void term_FPrintPrefix(FILE* File, TERM Term) /************************************************************** INPUT: A file and a term. RETURNS: none. SUMMARY: Prints the term in prefix notation to the file. CAUTION: Uses the other term output functions. ***************************************************************/ { if (term_IsComplex(Term)) { symbol_FPrint(File,term_TopSymbol(Term)); putc('(', File); term_TermListFPrintPrefix(File,term_ArgumentList(Term)); putc(')', File); } else symbol_FPrint(File,term_TopSymbol(Term)); } void term_TermListPrintPrefix(LIST List) /************************************************************** INPUT: A list of terms. RETURNS: None. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { term_PrintPrefix(list_Car(List)); if (!list_Empty(list_Cdr(List))) putchar(','); } } void term_TermListFPrintPrefix(FILE* File, LIST List) /************************************************************** INPUT: A list of terms. RETURNS: None. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { term_FPrintPrefix(File,list_Car(List)); if (!list_Empty(list_Cdr(List))) putc(',', File); } } void term_FPrintOtterPrefix(FILE* File, TERM Term) /************************************************************** INPUT: A file and a term. RETURNS: none. SUMMARY: Prints the term in prefix notation to the file. CAUTION: Uses the other term_Output functions. ***************************************************************/ { if (term_IsComplex(Term)) { symbol_FPrintOtter(File, term_TopSymbol(Term)); putc('(', File); term_TermListFPrintOtterPrefix(File, term_ArgumentList(Term)); putc(')', File); } else symbol_FPrintOtter(File, term_TopSymbol(Term)); } void term_TermListFPrintOtterPrefix(FILE* File, LIST List) /************************************************************** INPUT: A list of terms. RETURNS: None. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { term_FPrintOtterPrefix(File,list_Car(List)); if (!list_Empty(list_Cdr(List))) putc(',', File); } } void term_FPrintPosition(FILE* File, TERM TopTerm, TERM Subterm) /************************************************************** INPUT: An output file and two terms where is a subterm of . RETURNS: Nothing. SUMMARY: The position of relative to is printed to the output file. A simple top-down search is done, so the superterm pointers are not needed. Note that we compare terms with respect to pointers! If isn't a subterm of at all, this causes an error message followed by a core dump. ***************************************************************/ { NAT pos; LIST Scan; if (TopTerm == Subterm) return; for (Scan = term_ArgumentList(TopTerm), pos = 1; !list_Empty(Scan); Scan = list_Cdr(Scan), pos++) { if (term_HasPointerSubterm(list_Car(Scan), Subterm)) { fprintf(File, "%u", pos); if (Subterm != list_Car(Scan)) { putc('.', File); term_FPrintPosition(File, list_Car(Scan), Subterm); } return; } } misc_StartErrorReport(); misc_ErrorReport("\n In term_FPrintPosition: Term isn't subterm of the other one."); misc_FinishErrorReport(); } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * HIGH LEVEL FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ NAT term_Bytes(TERM Term) /************************************************************** INPUT: A term. RETURNS: The number of bytes occupied by the term. EFFECT: None ***************************************************************/ { NAT Bytes; LIST Scan; Bytes = sizeof(TERM_NODE) + list_Bytes(term_ArgumentList(Term)); for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) Bytes += term_Bytes((TERM)list_Car(Scan)); return Bytes; } LIST term_ListOfVariables(TERM Term) /************************************************************** INPUT: A term. RETURNS: The list of variables occurring in the term. Note that there may be many terms with same variable symbol. ***************************************************************/ { LIST Stack, Variables; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ListOfVariables: Illegal input."); misc_FinishErrorReport(); } #endif Variables = list_Nil(); Stack = list_StackBottom(); do { if (term_IsComplex(Term)) Stack = list_Push(term_ArgumentList(Term),Stack); else if (term_IsVariable(Term)) Variables = list_Cons(Term, Variables); while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) Stack = list_Pop(Stack); if (!list_StackEmpty(Stack)) { Term = (TERM)list_Car(list_Top(Stack)); list_RplacTop(Stack, list_Cdr(list_Top(Stack))); } } while (!list_StackEmpty(Stack)); return Variables; } void term_MarkVariables(TERM Term, NAT Mark) /************************************************************** INPUT: A term. RETURNS: Nothing. EFFECT: All variables from are marked with . CAUTION: The term module must be in a binding phase (started with term_StartBinding)! ***************************************************************/ { int Stack; #ifdef CHECK if (!term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In term_MarkVariables:"); misc_ErrorReport(" Called while not in binding phase."); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); do { if (term_IsComplex(Term)) { stack_Push(term_ArgumentList(Term)); } else if (term_IsVariable(Term)) term_CreateBinding(term_TopSymbol(Term), Mark); while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); } LIST term_VariableSymbols(TERM Term) /************************************************************** INPUT: A term. RETURNS: The list of variable symbols occurring in the term. ***************************************************************/ { LIST Variables; int Stack; SYMBOL Top; NAT ActMark; #ifdef CHECK if (!term_IsTerm(Term) || term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In term_VariableSymbols: Illegal input or context."); misc_FinishErrorReport(); } #endif term_StartBinding(); Variables = list_Nil(); Stack = stack_Bottom(); ActMark = term_ActMark(); do { if (term_IsComplex(Term)) { stack_Push(term_ArgumentList(Term)); } else { Top = term_TopSymbol(Term); if (symbol_IsVariable(Top) && !term_VarIsMarked(Top, ActMark)) { Variables = list_Cons((POINTER)Top, Variables); term_CreateBinding(Top, ActMark); } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); term_StopBinding(); return Variables; } NAT term_NumberOfVarOccs(TERM Term) /************************************************************** INPUT: A term. RETURNS: The list of variable symbols occurring in the term. ***************************************************************/ { NAT Result; int Stack; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_NumberOfVarOccs: Illegal input."); misc_FinishErrorReport(); } #endif Result = 0; Stack = stack_Bottom(); do { if (term_IsComplex(Term)) { stack_Push(term_ArgumentList(Term)); } else { if (symbol_IsVariable(term_TopSymbol(Term))) Result++; } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return Result; } NAT term_NumberOfSymbolOccurrences(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A term and a symbol. RETURNS: The number of occurrences of in ***************************************************************/ { NAT Result; LIST Scan; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_NumberOfSymbolOccurrences: Illegal input."); misc_FinishErrorReport(); } #endif Result = 0; if (symbol_Equal(term_TopSymbol(Term),Symbol)) Result++; for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) Result += term_NumberOfSymbolOccurrences(list_Car(Scan), Symbol); return Result; } BOOL term_ContainsFunctions(TERM Term) /************************************************************** INPUT: A term. RETURNS: TRUE iff the term contains a function symbol ***************************************************************/ { int Stack; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ContainsFunctions: Illegal input."); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); do { if (term_IsComplex(Term)) { if (symbol_IsFunction(term_TopSymbol(Term)) && !symbol_IsConstant(term_TopSymbol(Term))) { stack_SetBottom(Stack); return TRUE; } stack_Push(term_ArgumentList(Term)); } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return FALSE; } BOOL term_ContainsVariable(TERM Term, SYMBOL Var) /************************************************************** INPUT: A term and a variable symbol. RETURNS: TRUE iff the term contains the variable symbol ***************************************************************/ { int Stack; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsSymbol(Var)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_ContainsVariable: Illegal input."); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); do { if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); else if (symbol_Equal(term_TopSymbol(Term),Var)) { stack_SetBottom(Stack); return TRUE; } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return FALSE; } SYMBOL term_MaxVar(TERM Term) /********************************************************* INPUT: A term. RETURNS: The maximal variable in , NULL otherwise ********************************************************/ { LIST Scan; int Stack; SYMBOL Result; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_MaxVar: Illegal input."); misc_FinishErrorReport(); } #endif Result = (SYMBOL)NULL; Stack = stack_Bottom(); if (term_IsStandardVariable(Term)) { if (term_TopSymbol(Term)>Result) Result = term_TopSymbol(Term); } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(Stack)) { Scan = stack_Top(); Term = (TERM)list_Car(Scan); stack_RplacTop(list_Cdr(Scan)); if (term_IsStandardVariable(Term)) { if (term_TopSymbol(Term)>Result) Result = term_TopSymbol(Term); } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); } return Result; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * Renaming * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void term_StartMinRenaming(void) /************************************************************** INPUT: None EFFECT: Initializes the term and symbol modules for min co var renaming ***************************************************************/ { symbol_ResetStandardVarCounter(); term_NewMark(); } void term_StartMaxRenaming(SYMBOL MaxVar) /************************************************************** INPUT: A variable symbol. EFFECT: Initializes the term and symbol modules for renaming above ***************************************************************/ { symbol_SetStandardVarCounter(MaxVar); term_NewMark(); } TERM term_Rename(TERM Term) /************************************************************** INPUT: A Term. RETURNS: The destructively renamed term. EFFECT: All co variables are destructively renamed in ***************************************************************/ { int Stack; SYMBOL Top; NAT ActMark; TERM ActTerm; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Rename: Illegal input."); misc_FinishErrorReport(); } if (term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In term_Rename: Illegal context."); misc_FinishErrorReport(); } #endif term_StartBinding(); Stack = stack_Bottom(); ActMark = term_OldMark(); ActTerm = Term; do { if (term_IsComplex(ActTerm)) { stack_Push(term_ArgumentList(ActTerm)); } else { Top = term_TopSymbol(ActTerm); if (symbol_IsVariable(Top)) { if (!term_VarIsMarked(Top, ActMark)) term_CreateValueBinding(Top, ActMark, (POINTER)symbol_CreateStandardVariable()); term_RplacTop(ActTerm,(SYMBOL)term_BindingValue(Top)); } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { ActTerm = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); term_StopBinding(); return Term; } SYMBOL term_GetRenamedVarSymbol(SYMBOL Var) /************************************************************** INPUT: A variable symbol. RETURNS: The renamed variable for symbol for with respect to the current renaming. If it does not exist, itself is returned. EFFECT: None. ***************************************************************/ { NAT ActMark; #ifdef CHECK if (!symbol_IsStandardVariable(Var)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_GetRenamedVarSymbol: Illegal input."); misc_FinishErrorReport(); } #endif ActMark = term_OldMark(); if (term_VarIsMarked(Var, ActMark)) return (SYMBOL)term_BindingValue(Var); return Var; } static LIST term_MakePseudoLinear(TERM Term, NAT Depth, NAT Mark) /************************************************************** INPUT: A Term and a variable and the current depth. RETURNS: A list of pairs (,) EFFECT: The term is destructively made pseudo_linear. ***************************************************************/ { LIST Result,Scan; SYMBOL Top; Result = list_Nil(); if (term_IsComplex(Term)) for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) Result = list_Nconc(term_MakePseudoLinear(list_Car(Scan),Depth+1,Mark), Result); else { Top = term_TopSymbol(Term); if (symbol_IsVariable(Top)) { if (term_VarIsMarked(Top, Mark)) { if (Depth != (NAT)term_BindingValue(Top)) term_RplacTop(Term,symbol_CreateStandardVariable()); Result = list_Cons(list_PairCreate((POINTER)Top, (POINTER)term_TopSymbol(Term)), Result); } else { term_CreateValueBinding(Top, Mark, (POINTER)Depth); } } } return Result; } LIST term_RenamePseudoLinear(TERM Term, SYMBOL Var) /************************************************************** INPUT: A Term and a variable. RETURNS: A list of pairs (,) EFFECT: The term is destructively renamed. ***************************************************************/ { NAT Mark; LIST Result; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsVariable(Var) || term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In term_RenamePseudoLinear: Illegal input or context."); misc_FinishErrorReport(); } #endif term_StartBinding(); symbol_SetStandardVarCounter(Var); term_NewMark(); Mark = term_ActMark(); Result = term_MakePseudoLinear(Term,0,Mark); term_StopBinding(); return Result; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * STAMP FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ NAT term_GetStampID(void) /************************************************************** INPUT: None RETURNS: An identifier that must be used for some stamp functions EFFECT: Each module using the term stamp has to request an identifier that is needed for function term_StampOverflow The purpose of this identifier is to synchronize different modules in case of an overflow of the variable term_STAMP. ***************************************************************/ { if (term_STAMPUSERS >= term_MAXSTAMPUSERS) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In term_GetStampID: no more free stamp IDs."); misc_UserErrorReport("\n You have to increase the constant term_MAXSTAMPUSERS."); misc_FinishUserErrorReport(); } return term_STAMPUSERS++; } BOOL term_StampOverflow(NAT ID) /************************************************************** INPUT: The identifier of the calling module as returned by the function term_GetStampID. RETURNS: True if an overflow of the variable term_STAMP occurred for the module with the identifier ID. CAUTION: If an overflow occurred for a module you can test that only once!!! After the first test the overflow flag is cleared for that module. ***************************************************************/ { BOOL Result = FALSE; NAT i; #ifdef CHECK if (ID >= term_MAXSTAMPUSERS) { misc_StartErrorReport(); misc_ErrorReport("\n In term_StampOverflow: Illegal input."); misc_FinishErrorReport(); } #endif if (term_STAMP == NAT_MAX) { term_STAMP = 0; /* set overflow flag for all other modules */ for (i = 0; i < term_MAXSTAMPUSERS; i++) term_STAMPOVERFLOW[i] = TRUE; term_STAMPOVERFLOW[ID] = FALSE; Result = TRUE; } else if (term_STAMPOVERFLOW[ID]) { term_STAMPOVERFLOW[ID] = FALSE; Result = TRUE; } return Result; } void term_SetTermSubtermStamp(TERM Term) /************************************************************** INPUT: A term. RETURNS: void. EFFECT: Sets the current stamp to and its subterms. ***************************************************************/ { #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_SetTermSubtermStamp: Illegal input."); misc_FinishErrorReport(); } #endif term_SetTermStamp(Term); list_Apply((void (*)(POINTER)) term_SetTermSubtermStamp, term_ArgumentList(Term)); } LIST term_ListOfAtoms(TERM Term, SYMBOL Predicate) /************************************************************** INPUT: A term and a predicate symbol. RETURNS: A list of pointers to all atoms in Term with predicate symbol . ***************************************************************/ { if (symbol_Equal(term_TopSymbol(Term), Predicate)) return list_List(Term); else { LIST Result, List; Result = list_Nil(); for (List = term_ArgumentList(Term); !list_Empty(List); List = list_Cdr(List)) Result = list_Nconc(Result, term_ListOfAtoms(list_Car(List), Predicate)); return Result; } } /* Currently only in CHECK mode */ #ifdef CHECK void term_StartStamp(void) /************************************************************** INPUT: None RETURNS: Nothing EFFECT: The stamp is prepared for a new term traversal. ***************************************************************/ { if (term_STAMPBLOCKED) { /* Error: the Stamp is already used */ misc_StartErrorReport(); misc_ErrorReport("\n In term_StartStamp: Illegal context, term stamp is already used."); misc_FinishErrorReport(); } else { term_STAMP++; term_STAMPBLOCKED = TRUE; } } #endif LIST term_FindAllAtoms(TERM Term, SYMBOL Predicate) /********************************************************************** INPUT: A term Term and a symbol Predicate. RETURN: A list of all atoms of Term with Symbol as top symbol. ***********************************************************************/ { int stack; LIST Result; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsPredicate(Predicate)) { misc_StartErrorReport(); misc_ErrorReport("\n In term_FindAllPredicates: Illegal input."); misc_FinishErrorReport(); } #endif stack = stack_Bottom(); Result = list_Nil(); do { if (term_TopSymbol(Term) == Predicate) { Result = list_Cons(Term, Result); } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(stack)) { Term = list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(stack)); return Result; } BOOL term_CheckTermIntern(TERM Term, BOOL Links) /************************************************************************** INPUT: A term and a boolean. RETURN: True iff 1) the arity of each top symbol is equal to the number of arguments of symbol's term. and 2) either all father links are set correctly iff Links is TRUE or none is set iff Links is FALSE. COMMENT: Intern function of term_CheckTerm. ***************************************************************************/ { LIST Scan; SYMBOL Top; if (!term_IsTerm(Term)) return FALSE; Top = term_TopSymbol(Term); if (symbol_IsSignature(Top) && symbol_Arity(Top) != -1 && symbol_Arity(Top) != (int)list_Length(term_ArgumentList(Term))) return FALSE; if (symbol_IsVariable(Top) && !list_Empty(term_ArgumentList(Term))) return FALSE; if (Links) { for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (term_Superterm(list_Car(Scan)) != Term || !term_CheckTermIntern(list_Car(Scan), Links)) return FALSE; } } else { for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (term_Superterm(list_Car(Scan)) != term_Null() || !term_CheckTermIntern(list_Car(Scan), Links)) return FALSE; } } return TRUE; } BOOL term_CheckTerm(TERM Term) /******************************************************************************** INPUT : A term Term. RETURN: TRUE iff eihter all or no father links are set AND the length of any argument list matches the arity of the respective symbol *********************************************************************************/ { if (term_IsComplex(Term) && term_Superterm(term_FirstArgument(Term)) != term_Null()) /* check father links as well */ return term_CheckTermIntern(Term, TRUE); else return term_CheckTermIntern(Term, FALSE); } SPASS-3.7/SPASS/context.h0000644000374100037200000006465511340510065011737 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * CONTEXTS FOR VARIABLES * */ /* * * */ /* * $Module: CONTEXT * */ /* * * */ /* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.5 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:57 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: context.h,v $ */ #define SHOWBINDINGS 0 #ifndef _CONTEXT_ #define _CONTEXT_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "term.h" #include "symbol.h" #include "list.h" /**************************************************************/ /* Structures */ /**************************************************************/ /* Set 'SHOWBINDINGS' to non-zero value to enable debug output. */ /* #define SHOWBINDINGS 1 */ #define cont__SIZE symbol__MAXVARIABLES extern int cont_NOOFCONTEXTS; extern LIST cont_LISTOFCONTEXTS; extern int cont_BINDINGS; /* An array to remember bindings for the variables. The array */ /* is indexed by the variable index and holds the binding term. */ typedef struct binding { SYMBOL symbol; SYMBOL renaming; TERM term; struct binding *context; struct binding *link; } *CONTEXT, CONTEXT_NODE; extern CONTEXT cont_LASTBINDING; /* The last binding made. */ extern CONTEXT cont_CURRENTBINDING; /* Help variable. */ extern SYMBOL cont_INDEXVARSCANNER; /* Two contexts are allocated by default */ extern CONTEXT cont_LEFTCONTEXT; extern CONTEXT cont_RIGHTCONTEXT; extern CONTEXT cont_INSTANCECONTEXT; /* This context is used as a label only (dummy context) */ static __inline__ CONTEXT cont_LeftContext(void) { return cont_LEFTCONTEXT; } static __inline__ CONTEXT cont_RightContext(void) { return cont_RIGHTCONTEXT; } static __inline__ CONTEXT cont_InstanceContext(void) { return cont_INSTANCECONTEXT; } /**************************************************************/ /* Binding Functions */ /**************************************************************/ void cont_BackTrackLastBindingHelp(void); CONTEXT cont_ContextOfBinding(CONTEXT); void cont_CreateBindingHelp(CONTEXT, SYMBOL, CONTEXT, TERM); void cont_BindingOutput(CONTEXT C, SYMBOL Var); /**************************************************************/ /* A stack for the number of established bindings */ /**************************************************************/ #define cont__STACKSIZE 1000 typedef int cont_STACK_TYPE[cont__STACKSIZE]; extern cont_STACK_TYPE cont_STACK; extern int cont_STACKPOINTER; /* Stack operations */ static __inline__ void cont_StackInit(void) { cont_STACKPOINTER = 1; } static __inline__ void cont_StackPush(int Entry) { #ifdef CHECK if (cont_STACKPOINTER >= cont__STACKSIZE) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StackPush: Context stack overflow!\n"); misc_FinishErrorReport(); } #endif cont_STACK[cont_STACKPOINTER++] = Entry; } static __inline__ void cont_StackPop(void) { --cont_STACKPOINTER; } static __inline__ int cont_StackPopResult(void) { return cont_STACK[--cont_STACKPOINTER]; } static __inline__ void cont_StackNPop(int N) { cont_STACKPOINTER -= N; } static __inline__ int cont_StackTop(void) { return cont_STACK[cont_STACKPOINTER - 1]; } static __inline__ int cont_StackNthTop(int N) { return cont_STACK[cont_STACKPOINTER - (1 + N)]; } static __inline__ void cont_StackRplacTop(int Entry) { cont_STACK[cont_STACKPOINTER - 1] = Entry; } static __inline__ void cont_StackRplacNthTop(int N, int Entry) { cont_STACK[cont_STACKPOINTER - (1 + N)] = Entry; } static __inline__ void cont_StackRplacNth(int N, int Entry) { cont_STACK[N] = Entry; } static __inline__ int cont_StackBottom(void) { return cont_STACKPOINTER; } static __inline__ void cont_StackSetBottom(int Pointer) { cont_STACKPOINTER = Pointer; } static __inline__ BOOL cont_StackEmpty(int Pointer) { return cont_STACKPOINTER == Pointer; } static __inline__ void cont_StartBinding(void) { cont_StackPush(cont_BINDINGS); cont_BINDINGS = 0; } static __inline__ int cont_BindingsSinceLastStart(void) { return cont_BINDINGS; } static __inline__ void cont_StopAndStartBinding(void) { cont_StackRplacTop(cont_StackTop() + cont_BINDINGS); cont_BINDINGS = 0; } /**************************************************************/ /* Access */ /**************************************************************/ static __inline__ CONTEXT cont_Binding(CONTEXT C, SYMBOL Var) { return &(C)[Var]; } static __inline__ CONTEXT cont_BindingLink(CONTEXT B) { return B->link; } static __inline__ void cont_SetBindingLink(CONTEXT B, CONTEXT L) { B->link = L; } static __inline__ TERM cont_BindingTerm(CONTEXT B) { return B->term; } static __inline__ void cont_SetBindingTerm(CONTEXT B, TERM T) { B->term = T; } static __inline__ SYMBOL cont_BindingSymbol(CONTEXT B) { return B->symbol; } static __inline__ void cont_SetBindingSymbol(CONTEXT B, SYMBOL S) { B->symbol = S; } static __inline__ SYMBOL cont_BindingRenaming(CONTEXT B) { return B->renaming; } static __inline__ void cont_SetBindingRenaming(CONTEXT B, SYMBOL S) { B->renaming = S; } static __inline__ CONTEXT cont_BindingContext(CONTEXT B) { return B->context; } static __inline__ void cont_SetBindingContext(CONTEXT B, CONTEXT C) { B->context = C; } static __inline__ CONTEXT cont_ContextBindingLink(CONTEXT C,SYMBOL Var) { return C[Var].link; } static __inline__ TERM cont_ContextBindingTerm(CONTEXT C,SYMBOL Var) { return C[Var].term; } static __inline__ void cont_SetContextBindingTerm(CONTEXT C, SYMBOL Var, TERM t) { C[Var].term = t; } static __inline__ SYMBOL cont_ContextBindingSymbol(CONTEXT C,SYMBOL Var) { return C[Var].symbol; } static __inline__ SYMBOL cont_ContextBindingRenaming(CONTEXT C,SYMBOL Var) { return C[Var].renaming; } static __inline__ void cont_SetContextBindingRenaming(CONTEXT C, SYMBOL Var, SYMBOL R) { C[Var].renaming = R; } static __inline__ CONTEXT cont_ContextBindingContext(CONTEXT C,SYMBOL Var) { return C[Var].context; } /**************************************************************/ /* Predicates */ /**************************************************************/ static __inline__ BOOL cont_VarIsBound(CONTEXT C, SYMBOL Var) { return cont_ContextBindingTerm(C,Var) != (TERM) NULL; } static __inline__ BOOL cont_VarIsUsed(CONTEXT C, SYMBOL Var) { return cont_ContextBindingContext(C,Var) != (CONTEXT) NULL; } static __inline__ BOOL cont_VarIsLinked(CONTEXT C, SYMBOL Var) { return cont_ContextBindingLink(C,Var) != (CONTEXT) NULL; } static __inline__ BOOL cont_VarIsRenamed(CONTEXT C, SYMBOL Var) { return cont_ContextBindingRenaming(C, Var) != symbol_Null(); } static __inline__ BOOL cont_VarIsClosed(CONTEXT C,SYMBOL Var) { return !cont_VarIsBound(C,Var) && cont_VarIsUsed(C,Var); } static __inline__ BOOL cont_BindingIsBound(CONTEXT B) { return cont_BindingTerm(B) != (TERM) NULL; } static __inline__ BOOL cont_BindingIsUsed(CONTEXT B) { return cont_BindingContext(B) != (CONTEXT) NULL; } static __inline__ BOOL cont_IsBoundToVar(CONTEXT C) { return term_IsStandardVariable(cont_BindingTerm(C)); } /**************************************************************/ /* Aux functions for backtracking */ /**************************************************************/ static __inline__ CONTEXT cont_LastBinding(void) { return cont_LASTBINDING; } static __inline__ void cont_SetLastBinding(CONTEXT B) { cont_LASTBINDING = B; } static __inline__ TERM cont_LastBindingTerm(void) { return cont_BindingTerm(cont_LastBinding()); } static __inline__ SYMBOL cont_LastBindingSymbol(void) { return cont_BindingSymbol(cont_LastBinding()); } static __inline__ CONTEXT cont_LastBindingContext(void) { return cont_BindingContext(cont_LastBinding()); } static __inline__ BOOL cont_LastIsBound(void) { return cont_BindingIsBound(cont_LastBinding()); } static __inline__ BOOL cont_LastIsUsed(void) { return cont_LastBindingContext() != (CONTEXT) NULL; } static __inline__ BOOL cont_LastIsClosed(void) { return !cont_LastIsBound() && cont_LastIsUsed(); } static __inline__ BOOL cont_IsInContext(CONTEXT C, SYMBOL Var, CONTEXT B) { return cont_Binding(C, Var) == B; } /**************************************************************/ /* Initialization */ /**************************************************************/ void cont_InitBinding(CONTEXT C, SYMBOL Var); static __inline__ void cont_InitContext(CONTEXT C) { int i; for (i = 0; i < cont__SIZE; i++) cont_InitBinding(C, i); } /**************************************************************/ /* Creation and deletion of contexts */ /**************************************************************/ static __inline__ CONTEXT cont_Create(void) { CONTEXT Result; Result = (CONTEXT)memory_Malloc(cont__SIZE*sizeof(CONTEXT_NODE)); cont_InitContext(Result); cont_LISTOFCONTEXTS = list_Cons(Result, cont_LISTOFCONTEXTS); cont_NOOFCONTEXTS++; return Result; } static __inline__ void cont_Delete(CONTEXT C) { #ifdef CHECK if ((cont_NOOFCONTEXTS == 0) || !list_PointerMember(cont_LISTOFCONTEXTS, C)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_Delete: Context %ld not registered.\n", (unsigned long)C); misc_FinishErrorReport(); } #endif cont_LISTOFCONTEXTS = list_PointerDeleteOneElement(cont_LISTOFCONTEXTS, C); cont_NOOFCONTEXTS--; memory_Free(C, cont__SIZE*sizeof(CONTEXT_NODE)); } static __inline__ void cont_ResetIndexVarScanner(void) { cont_INDEXVARSCANNER = symbol_GetInitialIndexVarCounter(); } /**************************************************************/ /* Output bindings */ /**************************************************************/ static __inline__ void cont_PrintCurrentTrail(void) { fputs("\nPrint bindings:", stdout); cont_CURRENTBINDING = cont_LastBinding(); while (cont_CURRENTBINDING) { cont_BindingOutput(cont_ContextOfBinding(cont_CURRENTBINDING), cont_BindingSymbol(cont_CURRENTBINDING)); cont_CURRENTBINDING = cont_BindingLink(cont_CURRENTBINDING); if (cont_CURRENTBINDING) putchar('\n'); } fflush(stdout); } /**************************************************************/ /* Check Current Trail */ /**************************************************************/ static __inline__ BOOL cont_OnlyVariablesInCoDomOfCurrentTrail() { cont_CURRENTBINDING = cont_LastBinding(); while(cont_CURRENTBINDING){ #ifdef CHECK if(cont_BindingSymbol(cont_CURRENTBINDING) != cont_ContextBindingSymbol(cont_ContextOfBinding(cont_CURRENTBINDING), cont_BindingSymbol(cont_CURRENTBINDING))) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_OnlyVariablesInCoDomOfCurrentTrail: Wrong Trail.\n"); misc_FinishErrorReport(); } #endif if(symbol_IsStandardVariable(cont_BindingSymbol(cont_CURRENTBINDING)) && !cont_IsBoundToVar(cont_CURRENTBINDING)) { return FALSE; } cont_CURRENTBINDING = cont_BindingLink(cont_CURRENTBINDING); } return TRUE; } /**************************************************************/ /* Close bindings */ /**************************************************************/ static __inline__ void cont_CloseBindingHelp(CONTEXT C, SYMBOL Var) { cont_SetContextBindingTerm(C, Var, NULL); } static __inline__ void cont_CloseBindingBindingHelp(CONTEXT B) { cont_SetBindingTerm(B, NULL); } #if SHOWBINDINGS static __inline__ void cont_CloseBinding(CONTEXT C, SYMBOL Var) { fputs("\nClose binding from ", stdout); cont_BindingOutput(C, Var); cont_CloseBindingHelp(C, Var); } #else static __inline__ void cont_CloseBinding(CONTEXT C, SYMBOL Var) { cont_CloseBindingHelp(C, Var); } #endif static __inline__ void cont_CloseBindingBinding(CONTEXT B) { cont_CloseBindingBindingHelp(B); } /**************************************************************/ /* Establish bindings */ /**************************************************************/ #if SHOWBINDINGS static __inline__ int cont_CreateBinding(CONTEXT C, SYMBOL Var, CONTEXT CTerm, TERM Term) { cont_CreateBindingHelp(C,Var,CTerm,Term); fputs("\nEstablish binding from ", stdout); cont_BindingOutput(C, Var); return ++cont_BINDINGS; } static __inline__ int cont_CreateClosedBinding(CONTEXT C, SYMBOL Var) { cont_CreateBindingHelp(C, Var, C, NULL); fputs("\nEstablish closed binding from ", stdout); cont_BindingOutput(C,Var); return ++cont_BINDINGS; } #else static __inline__ int cont_CreateBinding(CONTEXT C, SYMBOL Var, CONTEXT CTerm, TERM Term) { cont_CreateBindingHelp(C,Var,CTerm,Term); return ++cont_BINDINGS; } static __inline__ int cont_CreateClosedBinding(CONTEXT C, SYMBOL Var) { cont_CreateBindingHelp(C, Var, C, NULL); return ++cont_BINDINGS; } #endif /**************************************************************/ /* Backtracking */ /**************************************************************/ #if SHOWBINDINGS static __inline__ void cont_BackTrackLastBinding(void) { CONTEXT LastContext; SYMBOL LastSymbol; LastContext = cont_ContextOfBinding(cont_LastBinding()); LastSymbol = cont_LastBindingSymbol(); fputs("\nBacktrack binding from ", stdout); cont_BindingOutput(LastContext, LastSymbol); cont_BackTrackLastBindingHelp(); } static __inline__ int cont_BackTrack(void) { printf("\nBacktrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); if (!cont_StackEmpty(0)) cont_BINDINGS = cont_StackPopResult(); fflush(stdout); return 0; } static __inline__ int cont_StopAndBackTrack(void) { #ifdef CHECK if (cont_BINDINGS > 0) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); misc_FinishErrorReport(); } else if (cont_StackEmpty(0)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); misc_FinishErrorReport(); } #endif cont_BINDINGS = cont_StackPopResult(); printf("\nStop and Backtrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); fflush(stdout); return 0; } static __inline__ int cont_BackTrackAndStart(void) { printf("\nBacktrack %d bindings:", cont_BINDINGS); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); fflush(stdout); return 0; } static __inline__ void cont_Reset(void) { fputs("\nReset bindings:", stdout); while (cont_LastBinding()) cont_BackTrackLastBinding(); cont_BINDINGS = 0; cont_StackInit(); cont_ResetIndexVarScanner(); fflush(stdout); } #else static __inline__ void cont_BackTrackLastBinding(void) { cont_BackTrackLastBindingHelp(); } static __inline__ int cont_BackTrack(void) { while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); if (!cont_StackEmpty(0)) cont_BINDINGS = cont_StackPopResult(); return 0; } static __inline__ int cont_StopAndBackTrack(void) { #ifdef CHECK if (cont_BINDINGS > 0) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); misc_FinishErrorReport(); } else if (cont_StackEmpty(0)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); misc_FinishErrorReport(); } #endif cont_BINDINGS = cont_StackPopResult(); while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); return 0; } static __inline__ int cont_BackTrackAndStart(void) { while (cont_BINDINGS > 0) cont_BackTrackLastBinding(); return 0; } static __inline__ void cont_Reset(void) { while (cont_LastBinding()) cont_BackTrackLastBinding(); cont_BINDINGS = 0; cont_StackInit(); cont_ResetIndexVarScanner(); } #endif /**************************************************************/ /* Check state of bindings */ /**************************************************************/ #define cont__CHECKSTACKSIZE 1000 #define cont__CHECKSTACKEMPTY 0 typedef POINTER cont_CHECKSTACK_TYPE[cont__CHECKSTACKSIZE]; extern cont_CHECKSTACK_TYPE cont_CHECKSTACK; extern int cont_CHECKSTACKPOINTER; /* Stack operations */ static __inline__ void cont_CheckStackInit(void) { cont_CHECKSTACKPOINTER = cont__CHECKSTACKEMPTY; } static __inline__ void cont_CheckStackPush(POINTER Entry) { #ifdef CHECK if (cont_CHECKSTACKPOINTER >= cont__STACKSIZE) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckStackPush: Context check stack overflow!\n"); misc_FinishErrorReport(); } #endif cont_CHECKSTACK[cont_CHECKSTACKPOINTER++] = Entry; } static __inline__ void cont_CheckStackPop(void) { --cont_CHECKSTACKPOINTER; } static __inline__ POINTER cont_CheckStackPopResult(void) { return cont_CHECKSTACK[--cont_CHECKSTACKPOINTER]; } static __inline__ void cont_CheckStackNPop(int N) { cont_CHECKSTACKPOINTER -= N; } static __inline__ POINTER cont_CheckStackTop(void) { return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1]; } static __inline__ POINTER cont_CheckStackNthTop(int N) { return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)]; } static __inline__ void cont_CheckStackRplacTop(POINTER Entry) { cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1] = Entry; } static __inline__ void cont_CheckStackRplacNthTop(int N, POINTER Entry) { cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)] = Entry; } static __inline__ void cont_CheckStackRplacNth(int N, POINTER Entry) { cont_CHECKSTACK[N] = Entry; } static __inline__ int cont_CheckStackBottom(void) { return cont_CHECKSTACKPOINTER; } static __inline__ void cont_CheckStackSetBottom(int Pointer) { cont_CHECKSTACKPOINTER = Pointer; } static __inline__ BOOL cont_CheckStackEmpty(int Pointer) { return cont_CHECKSTACKPOINTER == Pointer; } extern CONTEXT cont_STATELASTBINDING; /* Storage to save state of trails. */ extern int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ extern int cont_STATESTACK; /* Storage to save state of stack. */ extern int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ static __inline__ BOOL cont_CheckLastBinding(CONTEXT Check, int Bindings) { CONTEXT Scan; BOOL Result; Scan = cont_LastBinding(); while (Bindings > 0) { Scan = cont_BindingLink(Scan); Bindings--; } if (Check == Scan) Result = TRUE; else Result = FALSE; return Result; } static __inline__ void cont_CheckState(void) { if (cont_CheckStackEmpty(cont__CHECKSTACKEMPTY)) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckState: No states saved.\n"); misc_FinishErrorReport(); } cont_STATETOPSTACK = (int)cont_CheckStackPopResult(); cont_STATESTACK = (int)cont_CheckStackPopResult(); cont_STATEBINDINGS = (int)cont_CheckStackPopResult(); cont_STATELASTBINDING = (CONTEXT)cont_CheckStackPopResult(); if ((cont_STATELASTBINDING != cont_LastBinding()) || (cont_STATEBINDINGS != cont_BINDINGS) || (!cont_StackEmpty(cont_STATESTACK)) || (cont_STATETOPSTACK != cont_StackTop())) { misc_StartErrorReport(); misc_ErrorReport("\n In cont_CheckState: State of contexts does not match saved state."); misc_ErrorReport("\nTrail: Saved state: %ld; current state: %ld.", (long)cont_STATELASTBINDING, (long)cont_LastBinding()); misc_ErrorReport("\nNumber of bindings: Saved state: %d; current state: %d.", cont_STATEBINDINGS, cont_BINDINGS); misc_ErrorReport("\nBinding stack pointer: Saved state: %d; current state: %d.", cont_STATESTACK, cont_StackBottom()); misc_ErrorReport("\nNumber of bindings on top of stack: Saved state: %d; current state: %d.\n\n", cont_STATETOPSTACK, cont_StackTop()); misc_FinishErrorReport(); } } static __inline__ void cont_SaveState(void) { cont_CheckStackPush((POINTER)cont_LastBinding()); cont_CheckStackPush((POINTER)cont_BINDINGS); cont_CheckStackPush((POINTER)cont_StackBottom()); cont_CheckStackPush((POINTER)cont_StackTop()); } static __inline__ BOOL cont_IsContextEmpty(const CONTEXT Check) { int i; for (i = 0; i < cont__SIZE; i++) if (cont_VarIsBound(Check, i) || cont_VarIsUsed(Check, i) || cont_VarIsLinked(Check, i) || cont_VarIsRenamed(Check, i)) return FALSE; return TRUE; } /**************************************************************/ /* Generation of index variables */ /**************************************************************/ static __inline__ SYMBOL cont_NextIndexVariable(const CONTEXT IndexContext) { if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); else for (;;) { cont_INDEXVARSCANNER = symbol_NextIndexVariable(cont_INDEXVARSCANNER); if (!cont_VarIsUsed(IndexContext, cont_INDEXVARSCANNER)) break; else if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) { cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); break; } } return cont_INDEXVARSCANNER; } /**************************************************************/ /* Dereferencing of terms wrt. contexts */ /**************************************************************/ static __inline__ TERM cont_SymbolDeref(CONTEXT* Context, SYMBOL Symbol) /************************************************************** INPUT: A call-by-ref context and a variable symbol. RETURNS: The dereferenced term and the corresponding context, NULL if the symbol is not bound SUMMARY: Dereferences bindings of variables. CAUTION: In general, the context of the returned term is different to the input context. ***************************************************************/ { TERM Term; Term = (TERM)NULL; while (symbol_IsVariable(Symbol) && *Context != cont_InstanceContext()) { if (cont_VarIsBound(*Context, Symbol)) { CONTEXT HelpContext; HelpContext = cont_ContextBindingContext(*Context, Symbol); Term = cont_ContextBindingTerm(*Context, Symbol); *Context = HelpContext; Symbol = term_TopSymbol(Term); } else return Term; } return Term; } /**************************************************************/ /* Functions for Initialization and Controlling */ /**************************************************************/ void cont_Init(void); void cont_Check(void); void cont_Free(void); /**************************************************************/ /* Functions for Term Equality Test with respect to Bindings */ /**************************************************************/ BOOL cont_TermEqual(CONTEXT, CONTEXT, TERM, CONTEXT, CONTEXT, TERM); BOOL cont_TermEqualModuloBindings(CONTEXT, CONTEXT, TERM, CONTEXT, TERM); /**************************************************************/ /* Dereferencing of terms wrt. contexts */ /**************************************************************/ TERM cont_Deref(CONTEXT, CONTEXT*, TERM); /**************************************************************/ /* Functions for Applying Bindings */ /**************************************************************/ TERM cont_CopyAndApplyBindings(CONTEXT, TERM); TERM cont_CopyAndApplyBindingsCom(const CONTEXT, TERM); TERM cont_ApplyBindingsModuloMatching(const CONTEXT, TERM, BOOL); TERM cont_ApplyBindingsModuloMatchingReverse(const CONTEXT, TERM); BOOL cont_BindingsAreRenamingModuloMatching(const CONTEXT); /**************************************************************/ /* Misc Functions */ /**************************************************************/ SYMBOL cont_TermMaxVar(CONTEXT, CONTEXT, TERM); NAT cont_TermSize(CONTEXT, CONTEXT, TERM); BOOL cont_TermContainsSymbol(CONTEXT, CONTEXT, TERM, SYMBOL); /**************************************************************/ /* Functions for Output */ /**************************************************************/ void cont_TermPrintPrefix(CONTEXT, CONTEXT, TERM); #endif SPASS-3.7/SPASS/renaming.h0000644000374100037200000001322111340510066012033 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * RENAMING * */ /* * * */ /* * $Module: REN * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: renaming.h,v $ */ #ifndef _SPASS_RENAMING_ #define _SPASS_RENAMING_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "misc.h" #include "foldfg.h" #include "unify.h" #include "vector.h" /**************************************************************/ /* Data Structures and Constants */ /**************************************************************/ typedef struct { TERM hit; LIST matches; BOOL general; int polarity; } *RENAMING, RENAMING_NODE; /* is the formula that has a positive benefit */ /* are further matches of in the overall formula */ /* is TRUE iff the formula must not be replaced but */ /* is a generalzation of the matches formulae that are to */ /* be replaced */ /* is the most general polarity of and all */ /**************************************************************/ /* Functions */ /**************************************************************/ static __inline__ int ren_OverallPolarity(RENAMING ren) { return ren->polarity; } static __inline__ TERM ren_Hit(RENAMING ren) { return ren->hit; } static __inline__ LIST ren_Matches(RENAMING ren) { return ren->matches; } static __inline__ BOOL ren_General(RENAMING ren) { return ren->general; } static __inline__ void ren_SetMatches(RENAMING ren, LIST matches) { ren->matches = matches; } static __inline__ void ren_SetHit(RENAMING ren, TERM hit) { ren->hit = hit; } static __inline__ void ren_SetOverallPolarity(RENAMING ren, int polarity) { ren->polarity = polarity; } static __inline__ void ren_SetGeneral(RENAMING ren, BOOL general) { ren->general = general; } static __inline__ RENAMING ren_Create(TERM hit, LIST matches, int polarity) /************************************************************** INPUT: A formula, a list of further matching formulae and the overall polarity of the and the further . RETURNS: A new renaming object, which is initialized. General is set to false. MEMORY: Allocates memory for the RENAMING. ***************************************************************/ { RENAMING Result; Result = (RENAMING)memory_Malloc(sizeof(RENAMING_NODE)); Result->hit = hit; Result->matches = matches; Result->polarity = polarity; Result->general = FALSE; return Result; } static __inline__ void ren_Delete(RENAMING ren) /************************************************************** INPUT: A renaming. RETURNS: void. MEMORY: Frees memory for the RENAMING and the matches list. Formulae are not deleted. ***************************************************************/ { list_Delete(ren->matches); memory_Free(ren,sizeof(RENAMING_NODE)); } /**************************************************************/ /* Function Prototypes */ /**************************************************************/ void ren_Init(void); TERM ren_Rename(TERM, PRECEDENCE, LIST*,BOOL, BOOL, FLAG_CNFRENAMINGTYPE); void ren_PrettyPrint(RENAMING); #endif SPASS-3.7/SPASS/proofcheck.c0000644000374100037200000013444511340510066012365 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * PROOF CHECKING * */ /* * * */ /* * Copyright (C) 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* $Revision: 1.4 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:58 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /* $RCSfile: proofcheck.c,v $ */ #include "proofcheck.h" /* options */ int pcheck_Timelimit; const char *pcheck_ProofFileSuffix; BOOL pcheck_Quiet; /* options for graph generation */ BOOL pcheck_ClauseCg; BOOL pcheck_GenNamedCg, pcheck_GenRedCg; const char *pcheck_CgName, *pcheck_RedCgName; GRAPHFORMAT pcheck_GraphFormat; static int pcheck_MaxSplitLevel(LIST Clauses) /************************************************************** INPUT: A list of clauses. RETURNS: The maximum split level of a clause. ***************************************************************/ { int Max; int Act; Max = 0; while (!list_Empty(Clauses)) { Act = clause_SplitLevel(list_Car(Clauses)); if (Act > Max) Max = Act; Clauses = list_Cdr(Clauses); } return Max; } static __inline__ int pcheck_MaxParentSplitLevel(CLAUSE Clause) /************************************************************** INPUT: A clause RETURNS: The max split level of the parent clauses ***************************************************************/ { return pcheck_MaxSplitLevel(clause_ParentClauses(Clause)); } static BOOL pcheck_ClauseIsFromLeftSplit(CLAUSE Clause) /************************************************************** INPUT : A Clause RETURNS: TRUE iff the clause is the left half of a split CAUTION: This works also for clauses without parents, since pcheck_MaxParentSplitLevel returns 0 in that case. ***************************************************************/ { return (clause_SplitLevel(Clause) > pcheck_MaxParentSplitLevel(Clause)); } static BOOL pcheck_ClauseIsFromRightSplit(CLAUSE Clause) /************************************************************** INPUT: A clause RETURNS: TRUE iff the clause is from the right half of a split ***************************************************************/ { if (list_Empty(clause_ParentClauses(Clause))) return FALSE; return clause_IsEmptyClause(list_Car(clause_ParentClauses(Clause))); } static BOOL pcheck_ClauseIsFromSplit(CLAUSE Clause) /************************************************************** INPUT : A clause RETURNS: TRUE iff the clause is from a split ***************************************************************/ { return (pcheck_ClauseIsFromRightSplit(Clause) || pcheck_ClauseIsFromLeftSplit(Clause)); } static int pcheck_LabelToNumber(const char* Label) /************************************************************** INPUT: A clause label RETURNS: The label converted to a number. EFFECT: If the conversion fails an error message is printed and the program exits. ***************************************************************/ { int Number; if (!string_StringToInt(Label, FALSE, &Number)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n In pcheck_LabelToNumber:"); misc_UserErrorReport(" Could not convert clause"); misc_UserErrorReport(" label %s to a number.\n", Label); misc_FinishUserErrorReport(); } return Number; } static int pcheck_CompareNumberAndClause(const void* Number, const void* ClausePtr) /************************************************************** INPUT: A number and a pointer to a CLAUSE. RETURNS: 1) a negative number if is < number of 2) 0 if is equal to the number of 3) a positive number if is > number of EFFECT: This function is used as parameter to the bsearch function. ***************************************************************/ { return (int)Number - clause_Number(*(const CLAUSE*)ClausePtr); } static void pcheck_ParentNumbersToPointersInVector(CLAUSE* ClauseVector, int Size) /************************************************************** INPUT: A clause vector without duplicate clauses and the maximal number of elements in the vector EFFECTS: All clause parent numbers are replaced by pointers to the parents. CAUTION: The clause vector has to be sorted by increasing clause numbers, since this function performs a binary search on the vector. ***************************************************************/ { int Position; LIST NewParents, OldParents; LIST ScanParents; int ParentNum; CLAUSE* Parent; for (Position = 0; Position < Size; Position++) { OldParents = clause_ParentClauses(ClauseVector[Position]); NewParents = list_Copy(OldParents); for (ScanParents = NewParents; !list_Empty(ScanParents); ScanParents = list_Cdr(ScanParents)) { ParentNum = (int)list_Car(ScanParents); /* Binary search for parent clause with number . */ Parent = bsearch((const void*)ParentNum, ClauseVector, Size, sizeof(CLAUSE), pcheck_CompareNumberAndClause); if (Parent != NULL) list_Rplaca(ScanParents, *Parent); else { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Missing parent clause %d of clause %d.\n", ParentNum, clause_Number(ClauseVector[Position])); misc_FinishUserErrorReport(); } } clause_SetParentClauses(ClauseVector[Position], NewParents); list_Delete(OldParents); } } static LIST pcheck_ForceParentNumbersToPointersInVector(CLAUSE* ClauseVector, int Size) /************************************************************** INPUT: A clause vector, possibly with duplicates RETURNS: All numbers of clauses that are missing a parent clause from the transitive hull of parent clauses of . EFFECTS: All MARKED and HIDDEN flags of the clauses are changed. All parent numbers are converted to pointers, if the parents exist, otherwise the parent number is deleted from the list. The parent literal list is changed accordingly. A clause is marked as HIDDEN, if any clause from the transitive hull of parent clauses of was missing in . ***************************************************************/ { int Position; LIST NewParents, NewPLits, Parents, PLits, Missing; int ParentNum, PLitNum; CLAUSE *Parent, Clause; Missing = list_Nil(); for (Position = 0; Position < Size; Position++) { clause_RemoveFlag(ClauseVector[Position], MARKED); clause_RemoveFlag(ClauseVector[Position], HIDDEN); } for (Position = 0; Position < Size; Position++) { Clause = ClauseVector[Position]; if (!clause_GetFlag(Clause, MARKED)) { clause_SetFlag(Clause, MARKED); Parents = clause_ParentClauses(Clause); PLits = clause_ParentLiterals(Clause); NewParents = list_Nil(); NewPLits = list_Nil(); while (!list_Empty(Parents)) { ParentNum = (int)list_Car(Parents); PLitNum = (int)list_Car(PLits); /* Binary search for parent clause with number . */ Parent = bsearch((const void*)ParentNum, ClauseVector, Size, sizeof(CLAUSE), pcheck_CompareNumberAndClause); if (Parent == NULL) { Missing = list_Cons((POINTER)ParentNum, Missing); clause_SetFlag(Clause, HIDDEN); } else { if (clause_GetFlag(*Parent, HIDDEN)) clause_SetFlag(Clause, HIDDEN); NewParents = list_Cons((POINTER)*Parent, NewParents); NewPLits = list_Cons((POINTER)PLitNum, NewPLits); } Parents = list_Cdr(Parents); PLits = list_Cdr(PLits); } list_Delete(clause_ParentClauses(Clause)); list_Delete(clause_ParentLiterals(Clause)); NewParents = list_NReverse(NewParents); NewPLits = list_NReverse(NewPLits); clause_SetParentClauses(Clause, NewParents); clause_SetParentLiterals(Clause, NewPLits); } /* if clause is not marked */ } /* for all clauses */ return Missing; } static int pcheck_CompareClauseNumber(const void* C1, const void* C2) /************************************************************** INPUT : Two pointers to CLAUSEs. RETURNS: 1) a negative number if the number of C1 is < number of C2. 2) 0 if C1 and C2 have the same clause number (that means a possible bug in SPASS) 3) a positive number if number of C1 > number of C2 EFFECT: This function is used as parameter to the qsort function. ************************************************************/ { return clause_Number(*(const CLAUSE*)C1) - clause_Number(*(const CLAUSE*)C2); } static LIST pcheck_ConvertParentsInList(LIST List) /************************************************************** INPUT: A list of clauses. RETURNS: The list of missing parent clause numbers from the list EFFECTS: Parent numbers are converted to pointers ***************************************************************/ { int Size, Index; CLAUSE* ClauseVector; LIST Missing; Size = list_Length(List); if (Size == 0) return list_Nil(); /* convert list into vector for binary search */ ClauseVector = (CLAUSE*)memory_Malloc(sizeof(CLAUSE) * Size); for (Index = 0; !list_Empty(List); List = list_Cdr(List), Index++) ClauseVector[Index] = list_Car(List); /* sort the clauses in vector by increasing clause number */ qsort(ClauseVector, Size, sizeof(CLAUSE), pcheck_CompareClauseNumber); /* convert parent lists */ Missing = pcheck_ForceParentNumbersToPointersInVector(ClauseVector, Size); memory_Free(ClauseVector, sizeof(CLAUSE) * Size); return Missing; } LIST pcheck_ConvertParentsInSPASSProof(PROOFSEARCH Search, LIST EmptyClauses) /************************************************************** INPUT : A proofsearch object with clauses sorted by weight and an unsorted list RETURNS: The lists, where the clauses in are now sorted by weight, and parent numbers in the clauses are replaced by parent pointers ***************************************************************/ { LIST AllLists; LIST Missing; AllLists = list_Nconc(list_Copy(prfs_DocProofClauses(Search)), list_Copy(EmptyClauses)); AllLists = list_Nconc(list_Copy(prfs_UsableClauses(Search)), AllLists); AllLists = list_Nconc(list_Copy(prfs_WorkedOffClauses(Search)), AllLists); AllLists = pcheck_ClauseNumberMergeSort(AllLists); Missing = pcheck_ConvertParentsInList(AllLists); list_Delete(AllLists); return Missing; } static LIST pcheck_ParentNumbersToParents(LIST Proof) /************************************************************** INPUT: A list of clauses, representing a proof. RETURNS: The list, where parent numbers in the parent list of clauses are replaced by the parents (pointers). CAUTION: For finding the clause corresponding to a a clause number, the list is searched with binary search. This is correct only if the clause numbers in are increasing. ************************************************************/ { LIST ScanClauses; int ProofLength, Position; CLAUSE* ClauseVector; if (list_Empty(Proof)) return list_Nil(); /* convert list into vector for binary search */ ProofLength = list_Length(Proof); ClauseVector = (CLAUSE*) memory_Malloc(ProofLength * sizeof(CLAUSE)); for (ScanClauses = Proof, Position = 0; !list_Empty(ScanClauses); ScanClauses = list_Cdr(ScanClauses), Position++) { ClauseVector[Position] = list_Car(ScanClauses); } /* sort the clauses in vector by increasing clause number */ qsort(ClauseVector, ProofLength, sizeof(CLAUSE), pcheck_CompareClauseNumber); /* convert parent lists */ pcheck_ParentNumbersToPointersInVector(ClauseVector, ProofLength); memory_Free(ClauseVector, ProofLength * sizeof(CLAUSE)); return Proof; } LIST pcheck_ParentPointersToParentNumbers(LIST Clauses) /************************************************************** INPUT : A list of clauses RETURNS: The list with parent pointers replaced by parent numbers EFFECTS: Sets marks on all clauses. ***************************************************************/ { LIST ScanClauses; LIST ScanParents; pcheck_ClauseListRemoveFlag(Clauses, MARKED); for (ScanClauses = Clauses; !list_Empty(ScanClauses); ScanClauses = list_Cdr(ScanClauses)) { if (!clause_GetFlag(list_Car(ScanClauses), MARKED)) { for (ScanParents = clause_ParentClauses(list_Car(ScanClauses)); !list_Empty(ScanParents); ScanParents = list_Cdr(ScanParents)) list_Rplaca(ScanParents, (POINTER)clause_Number(list_Car(ScanParents))); clause_SetFlag(list_Car(ScanClauses), MARKED); } } return Clauses; } LIST pcheck_ConvertTermListToClauseList(LIST ProofRest, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: A list of quintupels (lists) representing a proof, a flag store, and a precedence. RETURNS: The conversion of this list into the internal clause structure. For each clause, the numbers of parent clauses are replaced by pointers to the parents. ***************************************************************/ { LIST Clauses; LIST ProofLine; TERM ClauseTerm; CLAUSE Clause; int Level; int ClauseNumber; LIST ParentLabels; LIST ParentIds; LIST ParentLits; /* this is a dummy list; parent lits are not yet specified in a SPASS proof */ RULE Origin; char* ClauseLabel; Clauses = list_Nil(); /* result */ while (!list_Empty(ProofRest)) { /* break proof line into components */ ProofLine = list_Car(ProofRest); ClauseLabel = list_First(ProofLine); ClauseTerm = list_Second(ProofLine); /* replace by NULL clause, since dfg_CreateClauseFromTerm deletes clause ! */ list_Rplaca(list_Cdr(ProofLine), clause_Null()); ParentLabels = (LIST)list_Third(ProofLine); Level = (int)list_Fourth(ProofLine); Origin = (RULE)list_Fifth(ProofLine); /* Conversion */ Clause = dfg_CreateClauseFromTerm(ClauseTerm, TRUE, Flags,Precedence); /* It's necessary to update the weight since dfg_CreateClauseFromTerm */ /* doesn't set it. */ clause_UpdateWeight(Clause, Flags); ClauseNumber = pcheck_LabelToNumber(ClauseLabel); ParentIds = list_Nil(); ParentLits = list_Nil(); while (!list_Empty(ParentLabels)) { ParentIds = list_Cons((POINTER)pcheck_LabelToNumber(list_Car(ParentLabels)), ParentIds); ParentLits = list_Cons(0, ParentLits); ParentLabels = list_Cdr(ParentLabels); } /* set all data */ clause_SetNumber(Clause, ClauseNumber); ParentIds = list_NReverse(ParentIds); clause_SetParentClauses(Clause, ParentIds); clause_SetParentLiterals(Clause, ParentLits); Clause->origin = Origin; clause_SetSplitLevel(Clause, Level); if (Level > 0) { clause_ClearSplitField(Clause); clause_SetSplitFieldBit(Clause, Level); } else clause_SetSplitField(Clause, (SPLITFIELD)NULL,0); clause_RemoveFlag(Clause, MARKED); Clauses = list_Cons(Clause, Clauses); ProofRest = list_Cdr(ProofRest); } Clauses = list_NReverse(Clauses); /* convert parent numbers to pointers */ Clauses = pcheck_ParentNumbersToParents(Clauses); return Clauses; } static BOOL pcheck_ClauseIsUnmarked(CLAUSE C) /************************************************************** INPUT: A clause RETURNS: The value of the clauses MARKED flag ***************************************************************/ { return !clause_GetFlag(C, MARKED); } static void pcheck_RemoveUnmarkedFromTableau(TABLEAU T) /************************************************************** INPUT: A tableau RETURNS: Nothing. EFFECTS: Delete all clauses that have the MARKED flag set from tableau. ***************************************************************/ { if (tab_IsEmpty(T)) return; tab_SetClauses(T, list_DeleteElementIf(tab_Clauses(T), (BOOL (*)(POINTER))pcheck_ClauseIsUnmarked)); pcheck_RemoveUnmarkedFromTableau(tab_LeftBranch(T)); pcheck_RemoveUnmarkedFromTableau(tab_RightBranch(T)); } static void pcheck_CollectUnmarkedSplits(TABLEAU T, LIST* Splits) /************************************************************** INPUT: A tableau, a list of clauses by reference RETURNS: Nothing. EFFECTS: Add all split clauses in the tableau that are not marked to the list. ***************************************************************/ { LIST Scan; if (tab_IsEmpty(T)) return; for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (!clause_GetFlag(list_Car(Scan), MARKED) && clause_IsFromSplitting(list_Car(Scan))) (*Splits) = list_Cons(list_Car(Scan), *Splits); } pcheck_CollectUnmarkedSplits(tab_LeftBranch(T), Splits); pcheck_CollectUnmarkedSplits(tab_RightBranch(T), Splits); } /* EK: unused, only recursive */ static void pcheck_TableauSplitsComplete(TABLEAU T) /************************************************************** INPUT : A tableau RETURNS: Checks that every split has exactly two or no successors. This condition must be true after tab_RemoveRedundantSplits has been called. ***************************************************************/ { if (tab_IsEmpty(T)) return; if (tab_RightBranchIsEmpty(T) && !tab_LeftBranchIsEmpty(T)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split of clause %d has no right branch.\n", clause_Number(tab_SplitClause(T))); misc_FinishUserErrorReport(); } if (!tab_RightBranchIsEmpty(T) && tab_LeftBranchIsEmpty(T)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split of clause %d has no left branch.\n", clause_Number(tab_SplitClause(T))); misc_FinishUserErrorReport(); } pcheck_TableauSplitsComplete(tab_LeftBranch(T)); pcheck_TableauSplitsComplete(tab_RightBranch(T)); } static void pcheck_RightSplitParents(CLAUSE SplitClause, CLAUSE RightSplitClause, CLAUSE LeftSplitClause) /************************************************************** INPUT: A split clause, and its left and right successors EFFECTS: Prints an error message if the split is not correctly closed. ***************************************************************/ { LIST Scan; BOOL HasEmpty, ContainsSplitClause; HasEmpty = ContainsSplitClause = FALSE; for (Scan = clause_ParentClauses(RightSplitClause); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (clause_IsEmptyClause(list_Car(Scan))) HasEmpty = TRUE; if (clause_Number(list_Car(Scan)) == clause_Number(SplitClause)) ContainsSplitClause = TRUE; } if (!HasEmpty) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Right split clause %d has no empty clause as parent.\n", clause_Number(SplitClause)); misc_FinishUserErrorReport(); } if (!ContainsSplitClause) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Right split clause %d", clause_Number(SplitClause)); misc_UserErrorReport(" does not have its split parent as parent clause.\n"); misc_FinishUserErrorReport(); } } /* EK: unused, only recursive */ static void pcheck_SplitFormats(TABLEAU T) /************************************************************** INPUT : A tableau RETURNS: TRUE iff all splits: - have generated negations of the left split clause if the left split clause is ground - the conditions for right split clauses are as demanded in pcheck_RightSplitParents ***************************************************************/ { LIST Scan; if (tab_IsEmpty(T)) return; /* for right splits, check that parents have an empty clause */ /* and the split clause as a parent */ for (Scan = tab_RightSplitClauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { pcheck_RightSplitParents(tab_SplitClause(T), list_Car(Scan), tab_LeftSplitClause(T)); } pcheck_SplitFormats(tab_RightBranch(T)); pcheck_SplitFormats(tab_LeftBranch(T)); } static void pcheck_SplitLevels(TABLEAU T) /************************************************************** INPUT : A Tableau RETURNS: TRUE iff all clauses in the tableau that are not splitting clauses have the max split level of their parents. CAUTION: We assume that has correct and complete split entries. See pcheck_SplitToProblems. ***************************************************************/ { LIST Scan; CLAUSE Clause; int CorrectLevel; if (tab_IsEmpty(T)) return; /* check split levels */ for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { Clause = list_Car(Scan); if (!list_Empty(clause_ParentClauses(Clause)) && !clause_IsFromSplitting(Clause)) { CorrectLevel = pcheck_MaxParentSplitLevel(Clause); if (clause_SplitLevel(Clause) != CorrectLevel) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split level of clause %d should be %d.\n", clause_Number(Clause), CorrectLevel); misc_FinishUserErrorReport(); } } } pcheck_SplitLevels(tab_RightBranch(T)); pcheck_SplitLevels(tab_LeftBranch(T)); } /* EK: unused, only recursive */ static void pcheck_SplitPrecheck(TABLEAU T) /************************************************************** INPUT : A tableau. EFFECTS: Stops and prints an error message if a left half of a split does not subsume its parents, or if negations have been generated for a non-ground left split clause. ***************************************************************/ { if (tab_IsEmpty(T)) return; if (!subs_Subsumes(tab_LeftSplitClause(T), tab_SplitClause(T), -1, -1)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Incorrect split of %d,", tab_SplitClause(T)); misc_UserErrorReport(" left half of split does not subsume splitted clause.\n"); misc_FinishUserErrorReport(); } if (list_Length(tab_RightSplitClauses(T)) > 1 && !clause_IsGround(tab_LeftSplitClause(T))) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Incorrect split of %d,", tab_SplitClause(T)); misc_UserErrorReport(" non-ground split generated more than two clause.\n"); misc_FinishUserErrorReport(); } pcheck_SplitPrecheck(tab_LeftBranch(T)); pcheck_SplitPrecheck(tab_RightBranch(T)); } BOOL pcheck_BuildTableauFromProof(LIST Proof, TABLEAU* Tableau) /************************************************************** INPUT : A list of clauses representing a proof, and a pointer to a tableau used as return value. RETURNS: TRUE iff no errors occurred, FALSE otherwise. If TRUE is returned is set to a tableau representing the proof. EFFECTS: Errors are commented when they occur. ***************************************************************/ { LIST ProofRest; TABLEAU SplitPos; TABPATH Path; CLAUSE Clause; int ClauseLevel, SplitLevel; int ProofDepth; if (list_Empty(Proof)) { *Tableau = tab_EmptyTableau(); return TRUE; } ProofDepth = pcheck_MaxSplitLevel(Proof); *Tableau = tab_CreateNode(); Path = tab_PathCreate(ProofDepth, *Tableau); ProofRest = Proof; while (!list_Empty(ProofRest)) { SplitLevel = tab_PathLength(Path); Clause = list_Car(ProofRest); ClauseLevel = clause_SplitLevel(Clause); /* Special treatment for clauses that result from a splitting step */ if (pcheck_ClauseIsFromSplit(Clause)) { if (ClauseLevel == 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split level of split clause %d is 0.\n", clause_Number(Clause)); misc_FinishUserErrorReport(); } if (ClauseLevel > SplitLevel+1) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split level of split clause %d", clause_Number(Clause)); misc_UserErrorReport(" is not increment of current split level.\n"); misc_FinishUserErrorReport(); } SplitPos = tab_PathNthNode(Path, ClauseLevel-1); if (pcheck_ClauseIsFromLeftSplit(Clause)) { /* Left branch of a splitting step */ if (!tab_LeftBranchIsEmpty(SplitPos)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Multiple left splits for clause %d.\n", clause_Number(tab_SplitClause(SplitPos))); misc_FinishUserErrorReport(); } Path = tab_PathPrefix(ClauseLevel-1, Path); tab_SetSplitClause(SplitPos, list_Car(clause_ParentClauses(Clause))); tab_SetLeftSplitClause(SplitPos, Clause); tab_AddSplitAtCursor(Path, TRUE); } else { /* Right branch of a splitting step */ if (tab_RightBranchIsEmpty(SplitPos)) { if (tab_LeftBranchIsEmpty(SplitPos)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Right split with incorrect split level, clause %d.\n", clause_Number(Clause)); misc_FinishUserErrorReport(); } Path = tab_PathPrefix(ClauseLevel-1, Path); tab_AddSplitAtCursor(Path, FALSE); } tab_AddRightSplitClause(SplitPos, Clause); } /* clause from right split */ } /* clause from split */ if (ClauseLevel > tab_PathLength(Path)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Split level of clause %d greater than current level.\n", clause_Number(Clause)); misc_FinishUserErrorReport(); } tab_AddClauseOnItsLevel(Clause, Path); ProofRest = list_Cdr(ProofRest); } /* while proof is not empty */ tab_PathDelete(Path); return TRUE; } static BOOL pcheck_TableauJustificationsRec(TABLEAU T, TABPATH Path) /************************************************************** INPUT : A Tableau , a in the tableau RETURNS: TRUE iff all clauses in the last node of the path are correctly justified. ***************************************************************/ { CLAUSE Clause; LIST ScanClauses; LIST ScanParents; LIST Parents; CLAUSE Parent; BOOL Ok, RightSplit; if (tab_IsEmpty(T)) return TRUE; Ok = TRUE; /* for each clause, check that its parents have been justified */ for (ScanClauses = tab_Clauses(tab_PathTop(Path)); !list_Empty(ScanClauses); ScanClauses = list_Cdr(ScanClauses)) { Clause = list_Car(ScanClauses); Parents = clause_ParentClauses(Clause); RightSplit = pcheck_ClauseIsFromRightSplit(Clause); /* check all parents */ for (ScanParents = Parents; !list_Empty(ScanParents); ScanParents = list_Cdr(ScanParents)) { Parent = list_Car(ScanParents); if ((!(RightSplit && clause_IsEmptyClause(Parent)) && !(RightSplit && pcheck_ClauseIsFromLeftSplit(Parent))) || (clause_Number(Parent) > clause_Number(Clause)) ) { if (!tab_PathContainsClause(Path, Parent)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Parent clause with number %d is not yet justified.\n", clause_Number(Parent)); misc_FinishUserErrorReport(); } } } } /* for all clauses in current node */ /* Recursion */ if (!tab_LeftBranchIsEmpty(T)) { Path = tab_PathPush(tab_LeftBranch(T), Path); Ok = Ok && pcheck_TableauJustificationsRec(tab_LeftBranch(T), Path); Path = tab_PathPop(Path); } if (!tab_RightBranchIsEmpty(T)) { Path = tab_PathPush(tab_RightBranch(T), Path); Ok = Ok && pcheck_TableauJustificationsRec(tab_RightBranch(T), Path); Path = tab_PathPop(Path); } return Ok; } static BOOL pcheck_TableauJustifications(TABLEAU T) /************************************************************** INPUT : A Tableau RETURNS: TRUE iff for each clause in tableau, all its parent clauses have been derived in a split on the same level or below. ***************************************************************/ { TABPATH Path; BOOL Ok; Path = tab_PathCreate(tab_Depth(T),T); Ok = pcheck_TableauJustificationsRec(T,Path); tab_PathDelete(Path); return Ok; } BOOL pcheck_TableauProof(TABLEAU* Tableau, LIST Proof) /************************************************************** INPUT: RETURNS: ***************************************************************/ { LIST RedundantClauses; LIST EmptyClauses; LIST UnmarkedSplits; tab_LabelNodes(*Tableau); /* print out current tableau */ if (pcheck_GenNamedCg) tab_WriteTableau(*Tableau, pcheck_CgName, pcheck_GraphFormat); RedundantClauses = list_Nil(); if (!pcheck_Quiet) { fputs("pruning closed branches...", stdout); fflush(stdout); } (*Tableau) = tab_PruneClosedBranches(*Tableau, &RedundantClauses); /* delete descendants of already closed branches */ if (!pcheck_Quiet) puts("finished."); if (!pcheck_Quiet) { fputs("removing incomplete splits...", stdout); fflush(stdout); } (*Tableau) = tab_RemoveIncompleteSplits(*Tableau, &RedundantClauses); /* reduce open node redundancies */ if (!pcheck_Quiet) { fputs("removing unfinished splits...", stdout); fflush(stdout); } (*Tableau) = tab_RemoveUnfinishedSplits(*Tableau, &RedundantClauses); if (!pcheck_Quiet) puts("finished."); list_Delete(RedundantClauses); /* remove all clauses that are not needed for the empty clauses */ /* of the proof or for the tableau structure (splits) */ EmptyClauses = list_Nil(); tab_GetEarliestEmptyClauses(*Tableau, &EmptyClauses); pcheck_ClauseListRemoveFlag(Proof, MARKED); pcheck_MarkRecursive(EmptyClauses); UnmarkedSplits = list_Nil(); pcheck_CollectUnmarkedSplits(*Tableau, &UnmarkedSplits); pcheck_MarkRecursive(UnmarkedSplits); pcheck_RemoveUnmarkedFromTableau(*Tableau); list_Delete(UnmarkedSplits); list_Delete(EmptyClauses); /* print reduced graph */ if (pcheck_GenRedCg) tab_WriteTableau(*Tableau, pcheck_RedCgName, pcheck_GraphFormat); tab_SetSplitLevels(*Tableau); pcheck_SplitLevels(*Tableau); tab_CheckEmpties(*Tableau); if (!tab_IsClosed(*Tableau)) { puts("\nerror: tableau is not closed."); return FALSE; } /* check justifications */ if (!pcheck_Quiet) { fputs("checking justifications...", stdout); fflush(stdout); } if (!pcheck_TableauJustifications(*Tableau)) return FALSE; if (!pcheck_Quiet) puts("finished."); return TRUE; } void pcheck_MarkRecursive(LIST Clauses) /************************************************************** INPUT: A list of clauses RETURNS: Nothing. EFFECTS: Marks all and its ancestors with the MARKED clause flag. ***************************************************************/ { CLAUSE Clause; for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) { Clause = list_Car(Clauses); if (!clause_GetFlag(Clause, MARKED)) { pcheck_MarkRecursive(clause_ParentClauses(Clause)); clause_SetFlag(Clause, MARKED); } } } static LIST pcheck_CollectTermVariables(TERM Term) /************************************************************** INPUT: A term. RETURNS: A list of terms. For each variable in the list contains exactly one term representing the variable. EFFECT: Memory is allocated for the terms. ***************************************************************/ { LIST Result, Scan; Result = term_VariableSymbols(Term); for (Scan = Result; !list_Empty(Scan); Scan = list_Cdr(Scan)) list_Rplaca(Scan, term_Create((SYMBOL)list_Car(Scan), list_Nil())); return Result; } static BOOL pcheck_IsRightSplitHalf(CLAUSE C) /************************************************************** INPUT : A clause. RETURNS: TRUE iff the following conditions are fulfilled: - the first parent clause is an empty clause - the clause subsumes its second parent ***************************************************************/ { LIST Parents; BOOL Ok; Parents = list_Copy(clause_ParentClauses(C)); Parents = list_PointerDeleteDuplicates(Parents); Ok = FALSE; if (list_Length(Parents) == 2 && clause_IsEmptyClause(list_First(Parents))) Ok = subs_Subsumes(C, list_Second(Parents), -1, -1); list_Delete(Parents); return Ok; } static TERM pcheck_UnivClosure(TERM T) /************************************************************** INPUT: A term, representing a formula. RETURNS: The universal closure of the term. EFFECTS: is part of the returned term! ***************************************************************/ { LIST Vars; Vars = pcheck_CollectTermVariables(T); if (list_Empty(Vars)) return T; return fol_CreateQuantifier(fol_All(), Vars, list_List(T)); } static TERM pcheck_ClauseToTerm(CLAUSE Clause) /************************************************************** INPUT: A clause. RETURNS: The clause represented as a TERM. ***************************************************************/ { int LitScan; LIST Args; TERM Lit; TERM ClauseTerm; Args = list_Nil(); for (LitScan = clause_FirstLitIndex(); LitScan <= clause_LastLitIndex(Clause); LitScan++) { Lit = clause_LiteralSignedAtom(clause_GetLiteral(Clause, LitScan)); Args = list_Cons(term_Copy(Lit), Args); } if (list_Empty(Args)) Args = list_List(term_Create(fol_False(), list_Nil())); /* Build the disjunction of the literals */ if (list_Empty(list_Cdr(Args))) { /* only one arg */ ClauseTerm = list_Car(Args); list_Delete(Args); } else ClauseTerm = term_Create(fol_Or(), Args); ClauseTerm = pcheck_UnivClosure(ClauseTerm); return ClauseTerm; } static LIST pcheck_ClauseListToTermList(LIST Clauses) /************************************************************** INPUT : A list of clauses. RETURNS: A new list containing the clauses represented as TERMs. ***************************************************************/ { LIST Terms; Terms = list_Nil(); for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) Terms = list_Cons(pcheck_ClauseToTerm(list_Car(Clauses)), Terms); return Terms; } static void pcheck_SaveNumberedDFGProblem(int Number, LIST Axioms, LIST Conjectures, const char* ProofFileName, const char* DestPrefix) /************************************************************** INPUT : A (clause) number, a list of axioms and conjectures, and a filename (of the proof file of the currently checked proof) RETURNS: Nothing. EFFECTS: Saves a DFG file containing and under the name "_" ***************************************************************/ { char *Filename, *Tmp, *NumStr; FILE *File; NumStr = string_IntToString(Number); Tmp = pcheck_GenericFilename(ProofFileName, NumStr); Filename = string_Conc(DestPrefix, Tmp); File = misc_OpenFile(Filename, "w"); fol_FPrintDFGProblem(File, "{*Sub Proof*}", "{* Proof Checker *}", "unsatisfiable", "{* The problem is the correctness test for a single proof line *}", Axioms, Conjectures); misc_CloseFile(File, Filename); string_StringFree(NumStr); string_StringFree(Tmp); string_StringFree(Filename); } static void pcheck_SplitToProblems(TABLEAU T, const char* ProofFileName, const char* DestPrefix) /************************************************************** INPUT: A tableau, which isn't a leaf of the tableau tree, the name of a proof file and a file name prefix used for generating files. RETURNS: Nothing. EFFECT: This function generates proof check tasks for clauses resulting from splitting steps and writes them to output files. CAUTION: We assume that we get non-null clauses when calling tab_SplitClause and tab_LeftSplitClause. ***************************************************************/ { TERM SplitClauseTerm, LeftClauseTerm, RightClauseTerm; TERM Equiv, Disj, Tmp; LIST Conj, Args, Negations; #ifdef CHECK if (tab_IsLeaf(T)) { misc_StartErrorReport(); misc_ErrorReport("\n In pcheck_SplitToProblems: Tableau is a leaf of the "); misc_ErrorReport("tableau tree."); misc_FinishErrorReport(); } #endif SplitClauseTerm = pcheck_ClauseToTerm(tab_SplitClause(T)); LeftClauseTerm = pcheck_ClauseToTerm(tab_LeftSplitClause(T)); /* by default, take all right split clauses as negations */ /* if the first clause is the second half of a split clause, */ /* take only the rest of the right split clauses as negations. */ Negations = tab_RightSplitClauses(T); if (!list_Empty(Negations) && pcheck_IsRightSplitHalf(list_Car(Negations))) { /* EK: Meiner Meinung nach ist es eine Invariante, daß die erste */ /* Elternklausel die rechte Hälfte eines Splittings ist??? */ Negations = list_Cdr(Negations); /* build C <=> C' v C'' */ RightClauseTerm = pcheck_ClauseToTerm(list_Car(tab_RightSplitClauses(T))); Disj = term_Create(fol_Or(), list_Cons(LeftClauseTerm, list_List(RightClauseTerm))); Equiv = term_Create(fol_Equiv(), list_Cons(SplitClauseTerm, list_List(Disj))); Conj = list_List(Equiv); pcheck_SaveNumberedDFGProblem(clause_Number(tab_LeftSplitClause(T)), list_Nil(), Conj, ProofFileName, DestPrefix); term_DeleteTermList(Conj); } Args = list_Nil(); /* build conjunction of negations, if there are any. */ if (!list_Empty(Negations)) { LeftClauseTerm = pcheck_ClauseToTerm(tab_LeftSplitClause(T)); Args = pcheck_ClauseListToTermList(Negations); /* Build the conjunction */ if (list_Empty(list_Cdr(Args))) { /* only one arg */ Tmp = list_Car(Args); list_Delete(Args); } else Tmp = term_Create(fol_And(), Args); Tmp = term_Create(fol_Not(), list_List(Tmp)); Equiv = term_Create(fol_Implies(),list_Cons(Tmp,list_List(LeftClauseTerm))); Conj = list_List(Equiv); /* problem id is number of right part of split clause, if it exists, number of first negation otherwise */ pcheck_SaveNumberedDFGProblem(clause_Number(list_Car(tab_RightSplitClauses(T))), list_Nil(), Conj, ProofFileName, DestPrefix); term_DeleteTermList(Conj); } } void pcheck_TableauToProofTask(TABLEAU T, const char* ProofFileName, const char* DestPrefix) /************************************************************** INPUT: A Tableau, two strings for filename generation. RETURNS: Nothing. EFFECTS: Generates DFG problem files for each clause in the tableau. The problem asserts that the clause follows from its parents. For splits, see pcheck_SplitToProblems ***************************************************************/ { LIST Scan; LIST Axioms, Conj, Help; CLAUSE Clause; if (tab_IsEmpty(T)) return; /* treat the splitting clauses at inner nodes of the tableau tree */ if (!tab_IsLeaf(T)) pcheck_SplitToProblems(T, ProofFileName, DestPrefix); /* treat derived clauses that don't result from splitting */ for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { Clause = list_Car(Scan); if (!clause_IsFromSplitting(Clause) && !list_Empty(clause_ParentClauses(Clause))) { Axioms = list_Copy(clause_ParentClauses(Clause)); Axioms = list_PointerDeleteDuplicates(Axioms); Help = Axioms; Axioms = pcheck_ClauseListToTermList(Axioms); list_Delete(Help); Conj = list_List(pcheck_ClauseToTerm(Clause)); pcheck_SaveNumberedDFGProblem(clause_Number(Clause), Axioms, Conj, ProofFileName, DestPrefix); term_DeleteTermList(Axioms); term_DeleteTermList(Conj); } } /* recursion */ pcheck_TableauToProofTask(tab_RightBranch(T), ProofFileName, DestPrefix); pcheck_TableauToProofTask(tab_LeftBranch(T), ProofFileName, DestPrefix); } int pcheck_SeqProofDepth(LIST Proof) /************************************************************** INPUT : A sequential proof (list of clauses) RETURNS: The maximum clause depth in the proof ***************************************************************/ { int Max; Max = 0; for ( ; !list_Empty(Proof); Proof = list_Cdr(Proof)) if (clause_Depth(list_Car(Proof)) > Max) Max = clause_Depth(list_Car(Proof)); return Max; } LIST pcheck_ReduceSPASSProof(LIST Proof) /************************************************************** INPUT: A list of clauses representing a SPASS proof. Parents are pointers. RETURNS: A list of clauses where incomplete splits and closed branches with descendants have been removed. ***************************************************************/ { LIST EmptyClauses, RedundantClauses; LIST ReducedProof; TABLEAU Tableau; LIST UnmarkedSplits; if (!pcheck_BuildTableauFromProof(Proof, &Tableau)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Error: Proof could not be translated into a closed tableau.\n"); misc_FinishUserErrorReport(); } /* printf("\n\n (1) \n"); */ /* tab_PrintTableau(Tableau); */ RedundantClauses = list_Nil(); Tableau = tab_PruneClosedBranches(Tableau, &RedundantClauses); /* printf("\n\n (2) \n"); */ /* tab_PrintTableau(Tableau); */ Tableau = tab_RemoveIncompleteSplits(Tableau, &RedundantClauses); /* printf("\n\n (3) \n"); */ /* tab_PrintTableau(Tableau); */ Tableau = tab_RemoveUnfinishedSplits(Tableau, &RedundantClauses); /* printf("\n\n (4) \n"); */ /* tab_PrintTableau(Tableau); */ list_Delete(RedundantClauses); tab_SetSplitLevels(Tableau); /* * get minimal proof: First find earliest derived empty clauses, * then recursively mark ancestors of these clauses. Put * only marked clauses in . */ EmptyClauses = list_Nil(); tab_GetEarliestEmptyClauses(Tableau, &EmptyClauses); pcheck_ClauseListRemoveFlag(Proof, MARKED); pcheck_MarkRecursive(EmptyClauses); UnmarkedSplits = list_Nil(); pcheck_CollectUnmarkedSplits(Tableau, &UnmarkedSplits); pcheck_MarkRecursive(UnmarkedSplits); pcheck_RemoveUnmarkedFromTableau(Tableau); list_Delete(UnmarkedSplits); ReducedProof = list_Nil(); tab_ToClauseList(Tableau, &ReducedProof); ReducedProof = pcheck_ClauseNumberMergeSort(ReducedProof); tab_Delete(Tableau); list_Delete(EmptyClauses); return ReducedProof; } void pcheck_DeleteProof(LIST Proof) /************************************************************** INPUT: A Proof RETURNS: Nothing. EFFECTS: Frees memory associated with proof **************************************************************/ { LIST Line, Scan2, Scan1; Scan1 = Proof; while (!list_Empty(Scan1)) { Line = list_Car(Scan1); string_StringFree(list_Car(Line)); if (list_Second(Line) != clause_Null()) /* clause */ term_Delete(list_Second(Line)); /* delete labels in justification list and list itself */ for (Scan2 = list_Third(Line); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) string_StringFree(list_Car(Scan2)); list_Delete(list_Third(Line)); /* now contents of line are deleted. Delete line. */ list_Delete(Line); Scan1 = list_Cdr(Scan1); } list_Delete(Proof); } char* pcheck_GenericFilename(const char* Filename, const char* Id) /************************************************************** INPUT: Two strings. RETURNS: A string with Suffix as new extension to Filename (Filename = name.ext -> name_.prf) EFFECTS: Memory is allocated for the returned string. **************************************************************/ { char *Help1, *Help2; int i; Help1 = string_Conc("_", Id); Help2 = string_Conc(Help1, pcheck_ProofFileSuffix); string_StringFree(Help1); /* remove filename extension */ for (i = 0; Filename[i] != '.' && i < strlen(Filename); i++) /* empty */; Help1 = string_Prefix(Filename, i); return string_Nconc(Help1, Help2); /* Help1 and Help2 are freed, too */ } void pcheck_ClauseListRemoveFlag(LIST Clauses, CLAUSE_FLAGS Flag) /************************************************************** INPUT: A list of clauses and a clause flag RETURNS: Nothing. EFFECTS: Removes the in all clauses in the list **************************************************************/ { for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) clause_RemoveFlag(list_Car(Clauses), Flag); } LIST pcheck_ClauseNumberMergeSort(LIST L) /************************************************************** INPUT: A list of clauses RETURNS: The sorted list: clause_Number(L[i]) < clause_Number(L[i+1]) EFFECTS: Destructive ***************************************************************/ { return clause_NumberSort(L); } SPASS-3.7/SPASS/subst.c0000644000374100037200000004731011340510067011375 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * SUBSTITUTION * */ /* * * */ /* * $Module: SUBSTITUTION * */ /* * * */ /* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ /* * MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.3 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile: subst.c,v $ */ #include "subst.h" /**************************************************************/ /* ********************************************************** */ /* * * */ /* * SUBSTITUTION CREATION AND DELETION * */ /* * * */ /* ********************************************************** */ /**************************************************************/ SUBST subst_Add(SYMBOL Symbol, TERM Codomain, SUBST Subst) { SUBST Result; Result = subst_Get(); Result->next = Subst; Result->dom = Symbol; Result->codomain = Codomain; return Result; } void subst_Delete(SUBST Subst) { SUBST Next; while (subst_Exist(Subst)) { Next = subst_Next(Subst); if (subst_Cod(Subst)) term_Delete(subst_Cod(Subst)); subst_FreeOneNode(Subst); Subst = Next; } } void subst_Free(SUBST Subst) { SUBST Next; while (subst_Exist(Subst)) { Next = subst_Next(Subst); subst_FreeOneNode(Subst); Subst = Next; } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * FUNCTIONS ON SUBSTITUTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ TERM subst_Term(SYMBOL Symbol, SUBST Subst) { for (; subst_Exist(Subst); Subst = subst_Next(Subst)) if (symbol_Equal(Symbol,subst_Dom(Subst))) return subst_Cod(Subst); return (TERM)NULL; } static TERM subst_ApplyIntern(SUBST Subst, TERM Term) { TERM RplacTerm; LIST Arglist; SYMBOL Top; Top = term_TopSymbol(Term); if (symbol_IsVariable(Top) && (RplacTerm = subst_Term(Top,Subst))) { Arglist = term_CopyTermList(term_ArgumentList(RplacTerm)); term_RplacTop(Term, term_TopSymbol(RplacTerm)); term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, Arglist); } else { for (Arglist = term_ArgumentList(Term); !list_Empty(Arglist); Arglist = list_Cdr(Arglist)) subst_ApplyIntern(Subst, list_Car(Arglist)); } return Term; } TERM subst_Apply(SUBST Subst, TERM Term) { if (subst_Empty(Subst)) return Term; return subst_ApplyIntern(Subst, Term); } SUBST subst_Merge(SUBST Source, SUBST Drain) { SUBST Scan; BOOL Changed; for (; subst_Exist(Source); Source = subst_Next(Source)) { /* Apply current assignment of Source to all */ /* assignments of Drain. If the current ass. */ /* cannot be applied to any codomain in Drain */ /* the current assignment is added to Drain. */ Changed = FALSE; for (Scan = Drain; subst_Exist(Scan); Scan = subst_Next(Scan)) if (term_SubstituteVariable(Source->dom, Source->codomain, Scan->codomain)) Changed = TRUE; if (!Changed) Drain = subst_Add(Source->dom, term_Copy(Source->codomain), Drain); } return Drain; } SUBST subst_Compose(SUBST Outer, SUBST Inner) /************************************************************** INPUT: Two substitutions. RETURNS: The substitution corresponding to the composition of and . EFFECT: is destructively applied to the codomain of is destructively extended ***************************************************************/ { SUBST Scan1,Scan2,New; New = subst_Nil(); for (Scan1=Outer; subst_Exist(Scan1); Scan1 = subst_Next(Scan1)) { for (Scan2 = Inner;subst_Exist(Scan2);Scan2 = subst_Next(Scan2)) term_SubstituteVariable(subst_Dom(Scan1),subst_Cod(Scan1),Scan2->codomain); if (!subst_BindVar(subst_Dom(Scan1),Inner)) New = subst_Add(subst_Dom(Scan1), term_Copy(subst_Cod(Scan1)),New); } return subst_NUnion(Inner,New); } BOOL subst_BindVar(SYMBOL Var, SUBST Subst) /************************************************************** INPUT: A variable symbol and a substitution. RETURNS: TRUE iff is contained in the domain of ***************************************************************/ { SUBST Scan; for (Scan=Subst; subst_Exist(Scan); Scan = subst_Next(Scan)) if (symbol_Equal(subst_Dom(Scan),Var)) return TRUE; return FALSE; } SUBST subst_Copy(SUBST Subst) { SUBST Copy, Result; for (Result = subst_Nil(), Copy = subst_Nil(); subst_Exist(Subst); Subst = subst_Next(Subst)) if (subst_Exist(Result)) { subst_SetNext(Copy, subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), subst_Nil())); Copy = subst_Next(Copy); } else { Result = subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), subst_Nil()); Copy = Result; } return Result; } BOOL subst_MatchTops(const CONTEXT Context, SUBST Subst) { for ( ; subst_Exist(Subst); Subst = subst_Next(Subst)) if (cont_ContextBindingTerm(Context, subst_Dom(Subst)) && term_EqualTopSymbols(cont_ContextBindingTerm(Context, subst_Dom(Subst)), subst_Cod(Subst))) return TRUE; return FALSE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * UNIFICATION TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL subst_Unify(CONTEXT IndexContext, SUBST Subst) /********************************************************* INPUT: RETURNS: CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. **********************************************************/ { while (subst_Exist(Subst)) { if (!cont_VarIsBound(IndexContext, subst_Dom(Subst))) { if (unify_OccurCheck(IndexContext, subst_Dom(Subst), IndexContext, subst_Cod(Subst))) return FALSE; else cont_CreateBinding(IndexContext, subst_Dom(Subst), IndexContext, subst_Cod(Subst)); } else if (!unify_UnifyAllOC(IndexContext, IndexContext, subst_Cod(Subst), cont_ContextBindingContext(IndexContext, subst_Dom(Subst)), cont_ContextBindingTerm(IndexContext, subst_Dom(Subst)))) return FALSE; Subst = subst_Next(Subst); } return TRUE; } BOOL subst_IsShallow(SUBST Subst) { /********************************************************** INPUT: A unifier RETURNS: TRUE, if the unifier is valid : a variable or a ground term or a function with only variables or ground terms as arguments. ***********************************************************/ SUBST SubstScan; for (SubstScan = Subst; SubstScan != subst_Nil(); SubstScan = subst_Next(SubstScan)) { TERM Codomain = subst_Cod(SubstScan); if ((!term_IsVariable(Codomain)) && (!term_IsGround(Codomain))) { LIST Scan ; for (Scan = term_ArgumentList(Codomain); Scan != list_Nil(); Scan = list_Cdr(Scan)) { if ((!term_IsVariable(list_Car(Scan)) && (!term_IsGround(list_Car(Scan))))) return FALSE; } } } return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * GENERALIZATION TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL subst_Match(const CONTEXT Context, SUBST Subst) /********************************************************* INPUT: RETURNS: CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. **********************************************************/ { while (subst_Exist(Subst)) { if (!cont_VarIsBound(Context, subst_Dom(Subst)) || !unify_Match(Context, subst_Cod(Subst), cont_ContextBindingTerm(Context, subst_Dom(Subst)))) return FALSE; Subst = subst_Next(Subst); } return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * INSTANCE TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL subst_MatchReverse(const CONTEXT IndexContext, SUBST Subst) /********************************************************* INPUT: RETURNS: CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. **********************************************************/ { while (subst_Exist(Subst)) { if (!cont_VarIsBound(IndexContext, subst_Dom(Subst))) { if (symbol_IsIndexVariable(subst_Dom(Subst))) cont_CreateBinding(IndexContext, subst_Dom(Subst), cont_InstanceContext(), subst_Cod(Subst)); else return FALSE; } else if (!unify_MatchReverse(IndexContext, subst_Cod(Subst), cont_ContextBindingContext(IndexContext, subst_Dom(Subst)), cont_ContextBindingTerm(IndexContext, subst_Dom(Subst)))) return FALSE; Subst = subst_Next(Subst); } return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * VARIATION TEST * */ /* * * */ /* ********************************************************** */ /**************************************************************/ BOOL subst_Variation(const CONTEXT Context, SUBST Subst) /********************************************************* INPUT: RETURNS: CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. **********************************************************/ { while (subst_Exist(Subst)) { if (!cont_VarIsBound(Context, subst_Dom(Subst)) || !unify_Variation(Context, subst_Cod(Subst), cont_ContextBindingTerm(Context, subst_Dom(Subst)))) return FALSE; Subst = subst_Next(Subst); } return TRUE; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * COMMON GENERALIZATIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ SUBST subst_ComGen(const CONTEXT Context, SUBST Subst, SUBST* SubstOld, SUBST* SubstNew) /********************************************************* INPUT: RETURNS: CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. **********************************************************/ { SUBST Result; Result = *SubstOld = *SubstNew = NULL; do { if (!cont_VarIsBound(Context, subst_Dom(Subst))) *SubstOld=subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), *SubstOld); else if (term_Equal(cont_ContextBindingTerm(Context, subst_Dom(Subst)), subst_Cod(Subst))) Result = subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), Result); else if (!symbol_Equal(term_TopSymbol(cont_ContextBindingTerm(Context, subst_Dom(Subst))), term_TopSymbol(subst_Cod(Subst)))) { *SubstOld=subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), *SubstOld); *SubstNew=subst_Add(subst_Dom(Subst), term_Copy(cont_ContextBindingTerm(Context, subst_Dom(Subst))), *SubstNew); } else Result = subst_Add(subst_Dom(Subst), unify_ComGenLinear(Context, SubstNew, cont_ContextBindingTerm(Context, subst_Dom(Subst)), SubstOld, subst_Cod(Subst)), Result); cont_CloseBinding(Context, subst_Dom(Subst)); Subst = subst_Next(Subst); } while (subst_Exist(Subst)); return Result; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * CLOSE BINDINGS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void subst_CloseVariables(const CONTEXT Context, SUBST Subst) { for (; subst_Exist(Subst); Subst = subst_Next(Subst)) cont_CloseBinding(Context, subst_Dom(Subst)); } SUBST subst_CloseOpenVariables(SUBST Result) { while (cont_LastBinding()) { if (cont_LastIsBound()) Result = subst_Add(cont_LastBindingSymbol(), term_Copy(cont_LastBindingTerm()), Result); cont_BackTrackLastBinding(); } return Result; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * EXTRACT UNIFIER * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void subst_ExtractUnifier(const CONTEXT CL, SUBST* LeftSubst, const CONTEXT CR, SUBST* RightSubst) /********************************************************* INPUT: 'LeftSubst', 'RightSubst' for the unifier, renaming the codomain variables starts at 'MinimumCoVariable' excl., number of renamings are ADDED to 'Bindings'. RETURNS: Nothing. SUMMARY: Extracts the unifier into two substitutions with renamed variables in the codomain. CAUTION: DOES NOT RESET THE BINDINGS, CREATES EVEN MORE BINDINGS BECAUSE OF RENAMING. **********************************************************/ { CONTEXT Scan; *LeftSubst = subst_Nil(); *RightSubst = subst_Nil(); Scan = cont_LastBinding(); while (Scan) { if (cont_IsInContext(CL, cont_BindingSymbol(Scan), Scan)) *LeftSubst = subst_Add(cont_BindingSymbol(Scan), cont_CopyAndApplyBindings(cont_BindingContext(Scan), cont_BindingTerm(Scan)), *LeftSubst); else if (cont_IsInContext(CR, cont_BindingSymbol(Scan), Scan)) *RightSubst = subst_Add(cont_BindingSymbol(Scan), cont_CopyAndApplyBindings(cont_BindingContext(Scan), cont_BindingTerm(Scan)), *RightSubst); Scan = cont_BindingLink(Scan); } } void subst_ExtractUnifierCom(const CONTEXT Context, SUBST* Subst) /********************************************************* INPUT: 'LeftSubst', 'RightSubst' for the unifier, renaming the codomain variables starts at 'MinimumCoVariable' excl., number of renamings are ADDED to 'Bindings'. RETURNS: Nothing. SUMMARY: Extracts the unifier into two substitutions with renamed variables in the codomain. CAUTION: DOES NOT RESET THE BINDINGS, CREATES EVEN MORE BINDINGS BECAUSE OF RENAMING. **********************************************************/ { CONTEXT Scan; *Subst = subst_Nil(); Scan = cont_LastBinding(); while (Scan) { *Subst = subst_Add(cont_BindingSymbol(Scan), cont_CopyAndApplyBindingsCom(Context, cont_BindingTerm(Scan)), *Subst); Scan = cont_BindingLink(Scan); } } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * EXTRACT MATCHER * */ /* * * */ /* ********************************************************** */ /**************************************************************/ SUBST subst_ExtractMatcher(void) /********************************************************* INPUT: None. RETURNS: The matcher. SUMMARY: Extracts the matcher without renaming. CAUTION: DOES NOT RESET THE BINDINGS, DOES NOT COPY THE CODOMAINS. **********************************************************/ { CONTEXT Scan; SUBST Result; for (Scan = cont_LastBinding(), Result = subst_Nil(); Scan; Scan = cont_BindingLink(Scan)) Result = subst_Add(cont_BindingSymbol(Scan), cont_BindingTerm(Scan), Result); return Result; } /**************************************************************/ /* ********************************************************** */ /* * * */ /* * OUTPUT * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void subst_Print(SUBST Subst) { fputs("{ ", stdout); for (; subst_Exist(Subst); Subst = subst_Next(Subst)) { symbol_Print(subst_Dom(Subst)); if (subst_Cod(Subst)) { fputs(" -> ", stdout); term_PrintPrefix(subst_Cod(Subst)); } if (subst_Next(Subst)) fputs("; ", stdout); } fputs(" }", stdout); } SPASS-3.7/SPASS/table.h0000644000374100037200000001051311340510067011324 00000000000000/**************************************************************/ /* ********************************************************** */ /* * * */ /* * SIGNATURE TABLE * */ /* * * */ /* * $Module: TABLE * */ /* * * */ /* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ /* * * */ /* * This program is free software; you can redistribute * */ /* * it and/or modify it under the terms of the FreeBSD * */ /* * Licence. * */ /* * * */ /* * This program 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 LICENCE file * */ /* * for more details. * */ /* * * */ /* * * */ /* $Revision: 1.2 $ * */ /* $State: Exp $ * */ /* $Date: 2010-02-22 14:09:59 $ * */ /* $Author: weidenb $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: spass@mpi-inf.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* module manages signature tables i. e. tables of terms (including the empty */ /* term NULL) where the lookup key is the tuple of top symbol index and */ /* arguments' equivalence classes with respect to a partition p, the */ /* _p-signature_ (sigtab_Index(top symbol), [arg 1] , ..., [arg n] ) */ /* p p */ #ifndef _TABLE_ #define _TABLE_ /**************************************************************/ /* Includes */ /**************************************************************/ #include "term.h" #include "partition.h" /**************************************************************/ /* Basic types */ /**************************************************************/ typedef struct termarray { TERM term; int stamp; struct termarray *child; } *TERMARRAY; typedef struct table { TERMARRAY ta, *pos; int *posstamp, stampcounter, opbound, varbound, termbound; } *TABLE; /* a signature table is an "array of terms allocated by need" (i. e. a tree */ /* where the nodes of the same layer represent array entries with the same */ /* dimension), an array of positions in this "array", stamps for the */ /* positions, the stamp counter and bounds for the operator symbol, variable */ /* and term indices of the terms to be stored in the signature table (i. e. */ /* for every such term its top symbol index has to be in [1, opbound] and the */ /* term numbers of its arguments in [0, termbound] - or its variable index in */ /* [1, varbound] if it is a variable) */ /**************************************************************/ /* Prototypes */ /**************************************************************/ TABLE table_Null(void); TABLE table_Create(int, int, int); void table_Free(TABLE); TABLE table_Init(TABLE, int, int, int); TERM table_QueryAndEnter(TABLE, PARTITION, TERM); TABLE table_Delete(TABLE, TERM); #endif SPASS-3.7/SPASS/dfgparser.c0000644000374100037200000053244211340746175012232 00000000000000/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse dfg_parse #define yylex dfg_lex #define yyerror dfg_error #define yylval dfg_lval #define yychar dfg_char #define yydebug dfg_debug #define yynerrs dfg_nerrs /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { DFG_AND = 258, DFG_AUTHOR = 259, DFG_AXIOMS = 260, DFG_BEGPROB = 261, DFG_BY = 262, DFG_CLAUSE = 263, DFG_CLOSEBRACE = 264, DFG_CLSLIST = 265, DFG_CNF = 266, DFG_CONJECS = 267, DFG_DATE = 268, DFG_DECLLIST = 269, DFG_INCLUDELIST = 270, DFG_INCLUDE = 271, DFG_DESC = 272, DFG_DESCLIST = 273, DFG_DNF = 274, DFG_DOMPRED = 275, DFG_ENDLIST = 276, DFG_ENDPROB = 277, DFG_EQUAL = 278, DFG_EQUIV = 279, DFG_EXISTS = 280, DFG_FALSE = 281, DFG_FORMLIST = 282, DFG_FORMULA = 283, DFG_FORALL = 284, DFG_FREELY = 285, DFG_FUNC = 286, DFG_GENERATED = 287, DFG_GENSET = 288, DFG_HYPOTH = 289, DFG_IMPLIED = 290, DFG_IMPLIES = 291, DFG_LOGIC = 292, DFG_NAME = 293, DFG_NOT = 294, DFG_OPENBRACE = 295, DFG_XOR = 296, DFG_NOR = 297, DFG_NAND = 298, DFG_OPERAT = 299, DFG_OR = 300, DFG_PREC = 301, DFG_CLFORE = 302, DFG_PRED = 303, DFG_PRDICAT = 304, DFG_PRFLIST = 305, DFG_QUANTIF = 306, DFG_SATIS = 307, DFG_SELECT = 308, DFG_SETFLAG = 309, DFG_SETTINGS = 310, DFG_SYMLIST = 311, DFG_SORT = 312, DFG_SORTS = 313, DFG_STATUS = 314, DFG_STEP = 315, DFG_SUBSORT = 316, DFG_TERMLIST = 317, DFG_TRUE = 318, DFG_UNKNOWN = 319, DFG_UNSATIS = 320, DFG_VERSION = 321, DFG_END_OF_CONSTRAINT_LITERALS = 322, DFG_END_OF_ANTECEDENT_LITERALS = 323, DFG_LITERAL_IS_SELECTED = 324, DFG_EML = 325, DFG_PROP_FORMULA = 326, DFG_REL_FORMULA = 327, DFG_SPECIALFORMLIST = 328, DFG_TRANSLPAIRS = 329, DFG_BOX = 330, DFG_DIA = 331, DFG_TEST = 332, DFG_DOMAIN = 333, DFG_RANGE = 334, DFG_COMP = 335, DFG_SUM = 336, DFG_CONV = 337, DFG_IDENTITY = 338, DFG_DIVERSITY = 339, DFG_DOMRESTR = 340, DFG_RANRESTR = 341, DFG_NUM = 342, DFG_MINUS1 = 343, DFG_ID = 344, DFG_TEXT = 345, single_quoted = 346 }; #endif /* Tokens. */ #define DFG_AND 258 #define DFG_AUTHOR 259 #define DFG_AXIOMS 260 #define DFG_BEGPROB 261 #define DFG_BY 262 #define DFG_CLAUSE 263 #define DFG_CLOSEBRACE 264 #define DFG_CLSLIST 265 #define DFG_CNF 266 #define DFG_CONJECS 267 #define DFG_DATE 268 #define DFG_DECLLIST 269 #define DFG_INCLUDELIST 270 #define DFG_INCLUDE 271 #define DFG_DESC 272 #define DFG_DESCLIST 273 #define DFG_DNF 274 #define DFG_DOMPRED 275 #define DFG_ENDLIST 276 #define DFG_ENDPROB 277 #define DFG_EQUAL 278 #define DFG_EQUIV 279 #define DFG_EXISTS 280 #define DFG_FALSE 281 #define DFG_FORMLIST 282 #define DFG_FORMULA 283 #define DFG_FORALL 284 #define DFG_FREELY 285 #define DFG_FUNC 286 #define DFG_GENERATED 287 #define DFG_GENSET 288 #define DFG_HYPOTH 289 #define DFG_IMPLIED 290 #define DFG_IMPLIES 291 #define DFG_LOGIC 292 #define DFG_NAME 293 #define DFG_NOT 294 #define DFG_OPENBRACE 295 #define DFG_XOR 296 #define DFG_NOR 297 #define DFG_NAND 298 #define DFG_OPERAT 299 #define DFG_OR 300 #define DFG_PREC 301 #define DFG_CLFORE 302 #define DFG_PRED 303 #define DFG_PRDICAT 304 #define DFG_PRFLIST 305 #define DFG_QUANTIF 306 #define DFG_SATIS 307 #define DFG_SELECT 308 #define DFG_SETFLAG 309 #define DFG_SETTINGS 310 #define DFG_SYMLIST 311 #define DFG_SORT 312 #define DFG_SORTS 313 #define DFG_STATUS 314 #define DFG_STEP 315 #define DFG_SUBSORT 316 #define DFG_TERMLIST 317 #define DFG_TRUE 318 #define DFG_UNKNOWN 319 #define DFG_UNSATIS 320 #define DFG_VERSION 321 #define DFG_END_OF_CONSTRAINT_LITERALS 322 #define DFG_END_OF_ANTECEDENT_LITERALS 323 #define DFG_LITERAL_IS_SELECTED 324 #define DFG_EML 325 #define DFG_PROP_FORMULA 326 #define DFG_REL_FORMULA 327 #define DFG_SPECIALFORMLIST 328 #define DFG_TRANSLPAIRS 329 #define DFG_BOX 330 #define DFG_DIA 331 #define DFG_TEST 332 #define DFG_DOMAIN 333 #define DFG_RANGE 334 #define DFG_COMP 335 #define DFG_SUM 336 #define DFG_CONV 337 #define DFG_IDENTITY 338 #define DFG_DIVERSITY 339 #define DFG_DOMRESTR 340 #define DFG_RANRESTR 341 #define DFG_NUM 342 #define DFG_MINUS1 343 #define DFG_ID 344 #define DFG_TEXT 345 #define single_quoted 346 /* Copy the first part of user declarations. */ #line 41 "dfgparser.y" #include #include "dfg.h" #include "symbol.h" #include "term.h" #include "foldfg.h" #include "strings.h" #include "eml.h" /* Used for delayed parsing of plain clauses */ typedef struct { LIST constraint; LIST antecedent; LIST succedent; TERM selected; } DFG_PLAINCLAUSEHELP, *DFG_PLAINCLAUSE; static DFGDESCRIPTION dfg_DESC; static LIST dfg_AXIOMLIST; static LIST dfg_CONJECLIST; static LIST dfg_SORTDECLLIST; static LIST dfg_INCLUDELIST; /* symbol precedence explicitly defined by user */ static LIST dfg_USERPRECEDENCE; static LIST dfg_USERSELECTION; static LIST dfg_CLAXRELATION; static LIST dfg_CLAXAXIOMS; static LIST dfg_AXCLAUSES; static LIST dfg_CONCLAUSES; static LIST dfg_PROOFLIST; /* list_of_proofs */ static LIST dfg_TERMLIST; /* list_of_terms */ static LIST dfg_PLAINAXCLAUSES; /* list of DFG_PLAINCLAUSE */ static LIST dfg_PLAINCONCLAUSES; /* list of DFG_PLAINCLAUSE */ static LIST dfg_TEMPPLAINCLAUSES; /* temporal list of DFG_PlAINCLAUSE, until they are concatenated to dfg_PLAINAXCLAUSES or dfg_PLAINCONCLAUSES */ static TERM dfg_SELECTED_LITERAL; /* last selected literal */ static BOOL dfg_IGNORE; /* tokens are ignored while TRUE */ static BOOL dfg_IGNORESETTINGS; /* issue a warning for included file with SPASS settings */ static FLAGSTORE dfg_FLAGS; static PRECEDENCE dfg_PRECEDENCE; /* used also in the scanner */ NAT dfg_LINENUMBER; BOOL dfg_IGNORETEXT; void yyerror(const char*); int yylex(void); /* Defined in dfgscanner.l */ static void dfg_SymbolDecl(int, char*, int); static SYMBOL dfg_Symbol(char*, NAT); static void dfg_SubSort(char*, char*); static void dfg_SymbolGenerated(SYMBOL, BOOL, LIST); static void dfg_TranslPairDecl(char*, char*); static TERM dfg_CreateQuantifier(SYMBOL, LIST, TERM); static __inline__ TERM dfg_TermCreate(char* Name, LIST Arguments) /*************************************************************** INPUT: A string and a list of terms . RETURNS: Does a symbol lookup for and creates out of the found or otherwise created new symbol and a new term. CAUTION: Deletes the string . ***************************************************************/ { SYMBOL s; NAT arity; arity = list_Length(Arguments); s = dfg_Symbol(Name, arity); /* Frees the string */ if (!symbol_IsVariable(s) && !symbol_IsFunction(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: is not a function.\n", dfg_LINENUMBER); misc_FinishUserErrorReport(); } return term_Create(s, Arguments); } static __inline__ TERM dfg_AtomCreate(char* Name, LIST Arguments) /* Look up the symbol, check its arity and create the atom term */ { SYMBOL s; s = dfg_Symbol(Name, list_Length(Arguments)); /* Frees the string */ if (symbol_IsVariable(s) || !symbol_IsPredicate(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: Symbol is not a predicate.\n", dfg_LINENUMBER); misc_FinishUserErrorReport(); } return term_Create(s, Arguments); } static __inline__ void dfg_DeleteStringList(LIST List) { list_DeleteWithElement(List, (void (*)(POINTER)) string_StringFree); } /**************************************************************/ /* Functions that handle symbols with unspecified arity */ /**************************************************************/ /* The symbol list holds all symbols whose arity wasn't */ /* specified in the symbol declaration section. */ /* If the arity of a symbol was not specified in this section */ /* it is first set to 0. If the symbol occurs with always the */ /* same arity 'A' the arity of this symbol is set to 'A'. */ static LIST dfg_SYMBOLLIST; static void dfg_SymAdd(SYMBOL); static void dfg_SymCheck(SYMBOL, NAT); static void dfg_SymCleanUp(void); /**************************************************************/ /* Functions that handle variable names */ /**************************************************************/ /* List of quantified variables in the current input formula. */ /* This list is used to find symbols that by mistake weren't */ /* declared in the symbol declaration section */ /* --> free variables */ /* This is a list of lists, since each time a quantifier is */ /* reached, a new list is added to the global list. */ static LIST dfg_VARLIST; static BOOL dfg_VARDECL; static void dfg_VarStart(void); static void dfg_VarStop(void); static void dfg_VarBacktrack(void); static void dfg_VarCheck(void); static SYMBOL dfg_VarLookup(char*); static DFG_PLAINCLAUSE dfg_PlainClauseCreate(void); static void dfg_PlainClauseFree(DFG_PLAINCLAUSE Clause); static char * dfg_StripQuotes(char * str); /* strip quotes from include filename */ /* #define DEBUG_PARSER */ #ifdef DEBUG_PARSER #define YYERROR_VERBOSE #define YYDEBUG 1000 dfg_debug = 1; #endif /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 1 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE #line 184 "dfgparser.y" { int number; char* string; SYMBOL symbol; SPROPERTY property; TERM term; LIST list; DFG_STATE state; BOOL bool; } /* Line 187 of yacc.c. */ #line 440 "dfgparser.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 216 of yacc.c. */ #line 453 "dfgparser.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 4 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 823 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 99 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 131 /* YYNRULES -- Number of rules. */ #define YYNRULES 280 /* YYNRULES -- Number of states. */ #define YYNSTATES 666 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 346 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 93, 2, 2, 97, 2, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 98, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 15, 27, 33, 39, 45, 51, 52, 58, 59, 65, 66, 72, 74, 76, 78, 86, 87, 98, 99, 105, 107, 111, 113, 119, 120, 126, 128, 132, 134, 140, 141, 147, 149, 153, 154, 160, 162, 166, 168, 174, 175, 181, 183, 187, 189, 195, 197, 199, 200, 206, 208, 212, 213, 219, 220, 226, 227, 230, 232, 240, 243, 251, 252, 253, 265, 275, 276, 278, 280, 284, 286, 290, 299, 301, 303, 304, 307, 308, 316, 317, 320, 322, 327, 334, 339, 340, 341, 352, 353, 355, 357, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, 401, 403, 408, 419, 420, 423, 424, 432, 440, 448, 449, 451, 452, 454, 456, 460, 462, 466, 468, 470, 472, 477, 482, 487, 494, 499, 506, 508, 510, 512, 517, 519, 521, 526, 531, 538, 545, 552, 557, 559, 561, 563, 565, 567, 569, 570, 573, 584, 585, 597, 598, 606, 607, 609, 610, 611, 619, 621, 622, 623, 634, 639, 640, 642, 646, 647, 650, 651, 654, 658, 660, 665, 667, 671, 673, 675, 677, 684, 689, 690, 698, 699, 701, 703, 712, 717, 719, 724, 726, 730, 731, 734, 735, 745, 746, 762, 764, 768, 769, 774, 778, 784, 785, 789, 791, 793, 795, 797, 799, 801, 803, 805, 807, 808, 812, 820, 822, 824, 825, 828, 829, 836, 837, 841, 842, 845, 851, 852, 855, 862, 867, 868, 870, 874, 876, 877, 880, 886, 887, 897, 899, 903, 904, 908, 913, 918, 923, 928, 935, 937, 941, 943, 950, 952, 956, 962, 964, 968, 970, 972, 976, 978, 979, 982, 984, 987, 993, 995 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 100, 0, -1, 6, 92, 152, 93, 94, 101, 110, 205, 212, 22, 94, -1, 18, 94, 102, 103, 106, 107, 104, 105, 108, 21, 94, -1, 38, 92, 90, 93, 94, -1, 4, 92, 90, 93, 94, -1, 59, 92, 109, 93, 94, -1, 17, 92, 90, 93, 94, -1, -1, 66, 92, 90, 93, 94, -1, -1, 37, 92, 90, 93, 94, -1, -1, 13, 92, 90, 93, 94, -1, 52, -1, 65, -1, 64, -1, 111, 130, 141, 156, 166, 189, 201, -1, -1, 56, 94, 112, 115, 118, 120, 123, 127, 21, 94, -1, -1, 31, 95, 113, 96, 94, -1, 114, -1, 113, 97, 114, -1, 152, -1, 92, 152, 97, 126, 93, -1, -1, 49, 95, 116, 96, 94, -1, 117, -1, 116, 97, 117, -1, 152, -1, 92, 152, 97, 126, 93, -1, -1, 58, 95, 119, 96, 94, -1, 152, -1, 119, 97, 152, -1, -1, 44, 95, 121, 96, 94, -1, 122, -1, 121, 97, 122, -1, 152, -1, 92, 152, 97, 126, 93, -1, -1, 51, 95, 124, 96, 94, -1, 125, -1, 124, 97, 125, -1, 152, -1, 92, 152, 97, 126, 93, -1, 88, -1, 87, -1, -1, 74, 95, 128, 96, 94, -1, 129, -1, 128, 97, 129, -1, -1, 92, 152, 97, 152, 93, -1, -1, 14, 94, 131, 21, 94, -1, -1, 131, 132, -1, 135, -1, 61, 92, 152, 97, 152, 93, 94, -1, 182, 94, -1, 48, 92, 152, 97, 138, 93, 94, -1, -1, -1, 29, 92, 95, 133, 153, 134, 96, 97, 182, 93, 94, -1, 57, 152, 136, 32, 7, 95, 137, 96, 94, -1, -1, 30, -1, 152, -1, 137, 97, 152, -1, 152, -1, 138, 97, 152, -1, 27, 92, 140, 93, 94, 142, 21, 94, -1, 5, -1, 12, -1, -1, 141, 139, -1, -1, 142, 28, 92, 147, 143, 93, 94, -1, -1, 97, 152, -1, 182, -1, 39, 92, 144, 93, -1, 149, 92, 144, 97, 144, 93, -1, 150, 92, 148, 93, -1, -1, -1, 151, 92, 95, 145, 153, 146, 96, 97, 144, 93, -1, -1, 144, -1, 144, -1, 148, 97, 144, -1, 24, -1, 35, -1, 36, -1, 41, -1, 42, -1, 43, -1, 3, -1, 45, -1, 25, -1, 29, -1, 89, -1, 87, -1, 54, -1, 20, -1, 46, -1, 47, -1, 53, -1, 154, -1, 153, 97, 154, -1, 152, -1, 152, 92, 152, 93, -1, 73, 92, 140, 97, 70, 93, 94, 157, 21, 94, -1, -1, 156, 155, -1, -1, 157, 28, 92, 147, 143, 93, 94, -1, 157, 71, 92, 158, 143, 93, 94, -1, 157, 72, 92, 159, 143, 93, 94, -1, -1, 162, -1, -1, 163, -1, 162, -1, 160, 97, 162, -1, 163, -1, 161, 97, 163, -1, 152, -1, 63, -1, 26, -1, 39, 92, 162, 93, -1, 78, 92, 163, 93, -1, 79, 92, 163, 93, -1, 149, 92, 162, 97, 162, 93, -1, 150, 92, 160, 93, -1, 164, 92, 163, 97, 162, 93, -1, 152, -1, 63, -1, 26, -1, 39, 92, 163, 93, -1, 83, -1, 84, -1, 82, 92, 163, 93, -1, 77, 92, 162, 93, -1, 85, 92, 163, 97, 162, 93, -1, 86, 92, 163, 97, 162, 93, -1, 149, 92, 163, 97, 163, 93, -1, 165, 92, 161, 93, -1, 75, -1, 76, -1, 3, -1, 45, -1, 80, -1, 81, -1, -1, 166, 167, -1, 10, 92, 140, 97, 11, 93, 94, 169, 21, 94, -1, -1, 10, 92, 140, 97, 19, 93, 94, 168, 183, 21, 94, -1, -1, 169, 8, 92, 170, 143, 93, 94, -1, -1, 173, -1, -1, -1, 171, 178, 67, 179, 68, 178, 172, -1, 176, -1, -1, -1, 29, 92, 95, 174, 153, 175, 96, 97, 176, 93, -1, 45, 92, 177, 93, -1, -1, 180, -1, 177, 97, 180, -1, -1, 178, 180, -1, -1, 179, 180, -1, 179, 180, 69, -1, 182, -1, 39, 92, 182, 93, -1, 182, -1, 181, 97, 182, -1, 152, -1, 63, -1, 26, -1, 23, 92, 187, 97, 187, 93, -1, 152, 92, 188, 93, -1, -1, 183, 8, 92, 184, 143, 93, 94, -1, -1, 185, -1, 186, -1, 25, 92, 95, 181, 96, 97, 186, 93, -1, 3, 92, 177, 93, -1, 152, -1, 152, 92, 188, 93, -1, 187, -1, 188, 97, 187, -1, -1, 189, 190, -1, -1, 50, 92, 152, 93, 94, 191, 192, 21, 94, -1, -1, 192, 60, 92, 196, 97, 200, 97, 152, 97, 95, 193, 96, 194, 93, 94, -1, 196, -1, 193, 97, 196, -1, -1, 97, 95, 195, 96, -1, 196, 98, 196, -1, 195, 97, 196, 98, 196, -1, -1, 198, 197, 199, -1, 152, -1, 39, -1, 24, -1, 35, -1, 36, -1, 3, -1, 45, -1, 29, -1, 25, -1, -1, 92, 148, 93, -1, 92, 95, 153, 96, 97, 144, 93, -1, 173, -1, 185, -1, -1, 201, 202, -1, -1, 62, 94, 203, 204, 21, 94, -1, -1, 204, 187, 94, -1, -1, 205, 206, -1, 15, 94, 207, 21, 94, -1, -1, 207, 208, -1, 16, 92, 211, 209, 93, 94, -1, 97, 95, 210, 96, -1, -1, 152, -1, 152, 97, 210, -1, 91, -1, -1, 212, 213, -1, 33, 94, 227, 21, 94, -1, -1, 55, 92, 152, 214, 93, 94, 215, 21, 94, -1, 90, -1, 40, 216, 9, -1, -1, 216, 217, 94, -1, 46, 92, 218, 93, -1, 53, 92, 224, 93, -1, 47, 92, 220, 93, -1, 20, 92, 229, 93, -1, 54, 92, 89, 97, 126, 93, -1, 219, -1, 218, 97, 219, -1, 152, -1, 92, 152, 97, 87, 226, 93, -1, 221, -1, 220, 97, 221, -1, 92, 87, 97, 222, 93, -1, 223, -1, 222, 97, 223, -1, 152, -1, 225, -1, 224, 97, 225, -1, 152, -1, -1, 97, 89, -1, 228, -1, 227, 228, -1, 34, 95, 229, 96, 94, -1, 152, -1, 229, 97, 152, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 242, 242, 255, 266, 270, 274, 278, 282, 283, 287, 288, 292, 293, 297, 298, 299, 306, 319, 320, 330, 331, 334, 335, 338, 339, 343, 344, 347, 348, 351, 352, 355, 356, 359, 360, 363, 364, 367, 368, 371, 372, 375, 376, 379, 380, 383, 384, 387, 388, 391, 392, 395, 396, 399, 399, 406, 407, 412, 413, 416, 417, 419, 420, 422, 423, 422, 432, 436, 437, 440, 441, 444, 445, 452, 462, 463, 466, 467, 470, 471, 485, 486, 489, 490, 492, 494, 496, 497, 496, 504, 505, 508, 510, 514, 515, 516, 517, 518, 519, 522, 523, 526, 527, 530, 536, 538, 540, 542, 544, 546, 550, 552, 556, 567, 591, 602, 603, 606, 607, 620, 632, 648, 649, 652, 653, 660, 661, 664, 665, 668, 670, 672, 674, 676, 678, 680, 682, 684, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 714, 715, 718, 719, 720, 721, 729, 730, 733, 755, 754, 761, 762, 776, 777, 778, 778, 778, 796, 797, 798, 797, 805, 809, 810, 812, 816, 817, 821, 822, 824, 839, 840, 844, 845, 848, 850, 852, 854, 856, 863, 864, 867, 868, 871, 872, 875, 882, 884, 888, 890, 898, 899, 903, 902, 916, 917, 938, 940, 945, 946, 949, 957, 968, 967, 979, 980, 981, 982, 983, 984, 985, 986, 987, 990, 991, 992, 995, 996, 1004, 1005, 1008, 1008, 1015, 1016, 1023, 1024, 1027, 1030, 1031, 1034, 1037, 1038, 1041, 1042, 1047, 1054, 1055, 1064, 1065, 1065, 1073, 1076, 1079, 1080, 1083, 1084, 1085, 1086, 1106, 1118, 1119, 1122, 1134, 1151, 1152, 1155, 1162, 1163, 1166, 1172, 1173, 1176, 1195, 1196, 1213, 1214, 1217, 1221, 1222 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "DFG_AND", "DFG_AUTHOR", "DFG_AXIOMS", "DFG_BEGPROB", "DFG_BY", "DFG_CLAUSE", "DFG_CLOSEBRACE", "DFG_CLSLIST", "DFG_CNF", "DFG_CONJECS", "DFG_DATE", "DFG_DECLLIST", "DFG_INCLUDELIST", "DFG_INCLUDE", "DFG_DESC", "DFG_DESCLIST", "DFG_DNF", "DFG_DOMPRED", "DFG_ENDLIST", "DFG_ENDPROB", "DFG_EQUAL", "DFG_EQUIV", "DFG_EXISTS", "DFG_FALSE", "DFG_FORMLIST", "DFG_FORMULA", "DFG_FORALL", "DFG_FREELY", "DFG_FUNC", "DFG_GENERATED", "DFG_GENSET", "DFG_HYPOTH", "DFG_IMPLIED", "DFG_IMPLIES", "DFG_LOGIC", "DFG_NAME", "DFG_NOT", "DFG_OPENBRACE", "DFG_XOR", "DFG_NOR", "DFG_NAND", "DFG_OPERAT", "DFG_OR", "DFG_PREC", "DFG_CLFORE", "DFG_PRED", "DFG_PRDICAT", "DFG_PRFLIST", "DFG_QUANTIF", "DFG_SATIS", "DFG_SELECT", "DFG_SETFLAG", "DFG_SETTINGS", "DFG_SYMLIST", "DFG_SORT", "DFG_SORTS", "DFG_STATUS", "DFG_STEP", "DFG_SUBSORT", "DFG_TERMLIST", "DFG_TRUE", "DFG_UNKNOWN", "DFG_UNSATIS", "DFG_VERSION", "DFG_END_OF_CONSTRAINT_LITERALS", "DFG_END_OF_ANTECEDENT_LITERALS", "DFG_LITERAL_IS_SELECTED", "DFG_EML", "DFG_PROP_FORMULA", "DFG_REL_FORMULA", "DFG_SPECIALFORMLIST", "DFG_TRANSLPAIRS", "DFG_BOX", "DFG_DIA", "DFG_TEST", "DFG_DOMAIN", "DFG_RANGE", "DFG_COMP", "DFG_SUM", "DFG_CONV", "DFG_IDENTITY", "DFG_DIVERSITY", "DFG_DOMRESTR", "DFG_RANRESTR", "DFG_NUM", "DFG_MINUS1", "DFG_ID", "DFG_TEXT", "single_quoted", "'('", "')'", "'.'", "'['", "']'", "','", "':'", "$accept", "problem", "description", "name", "author", "status", "desctext", "versionopt", "logicopt", "dateopt", "log_state", "logicalpart", "symbollistopt", "functionsopt", "functionlist", "func", "predicatesopt", "predicatelist", "pred", "sortsopt", "sortlist", "operatorsopt", "operatorlist", "op", "quantifiersopt", "quantifierlist", "quant", "number", "translpairsopt", "translpairlist", "translpair", "declarationlistopt", "decllistopt", "decl", "@1", "@2", "gendecl", "freelyopt", "funclist", "sortdecl", "formulalist", "origin", "formulalistsopt", "formulalistopt", "labelopt", "formula", "@3", "@4", "formulaopt", "arglist", "binsymbol", "nsymbol", "quantsymbol", "id", "qtermlist", "qterm", "specialformulalist", "specialformulalistsopt", "specialformulalistopt", "propformulaopt", "relformulaopt", "proparglist", "relarglist", "propformula", "relformula", "relpropbinsymbol", "relnsymbol", "clauselistsopt", "clauselist", "@5", "cnfclausesopt", "cnfclauseopt", "@6", "@7", "cnfclause", "@8", "@9", "cnfclausebody", "litlist", "litlist_ws", "selected_litlist_ws", "lit", "atomlist", "atom", "dnfclausesopt", "dnfclauseopt", "dnfclause", "dnfclausebody", "term", "termlist", "prooflistsopt", "prooflist", "@10", "prooflistopt", "parentlist", "assoclistopt", "assoclist", "id_or_formula", "@11", "anysymbol", "optargs", "clause", "listOfTermsopt", "listOfTerms", "@12", "terms", "includelistopt", "includelist", "includes", "include", "formula_selection", "name_list", "filename", "settinglistsopt", "settinglist", "@13", "flags", "spassflags", "spassflag", "preclist", "precitem", "clfolist", "clfoitem", "clfoaxseq", "clfoaxseqitem", "selectlist", "selectitem", "statopt", "gsettings", "gsetting", "labellist", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 40, 41, 46, 91, 93, 44, 58 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 99, 100, 101, 102, 103, 104, 105, 106, 106, 107, 107, 108, 108, 109, 109, 109, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 132, 132, 133, 134, 132, 135, 136, 136, 137, 137, 138, 138, 139, 140, 140, 141, 141, 142, 142, 143, 143, 144, 144, 144, 144, 145, 146, 144, 147, 147, 148, 148, 149, 149, 149, 149, 149, 149, 150, 150, 151, 151, 152, 152, 152, 152, 152, 152, 152, 153, 153, 154, 154, 155, 156, 156, 157, 157, 157, 157, 158, 158, 159, 159, 160, 160, 161, 161, 162, 162, 162, 162, 162, 162, 162, 162, 162, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 164, 164, 165, 165, 165, 165, 166, 166, 167, 168, 167, 169, 169, 170, 170, 171, 172, 170, 173, 174, 175, 173, 176, 177, 177, 177, 178, 178, 179, 179, 179, 180, 180, 181, 181, 182, 182, 182, 182, 182, 183, 183, 184, 184, 185, 185, 186, 187, 187, 188, 188, 189, 189, 191, 190, 192, 192, 193, 193, 194, 194, 195, 195, 197, 196, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 199, 199, 200, 200, 201, 201, 203, 202, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209, 210, 210, 211, 212, 212, 213, 214, 213, 215, 215, 216, 216, 217, 217, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 222, 222, 223, 224, 224, 225, 226, 226, 227, 227, 228, 229, 229 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 11, 11, 5, 5, 5, 5, 0, 5, 0, 5, 0, 5, 1, 1, 1, 7, 0, 10, 0, 5, 1, 3, 1, 5, 0, 5, 1, 3, 1, 5, 0, 5, 1, 3, 0, 5, 1, 3, 1, 5, 0, 5, 1, 3, 1, 5, 1, 1, 0, 5, 1, 3, 0, 5, 0, 5, 0, 2, 1, 7, 2, 7, 0, 0, 11, 9, 0, 1, 1, 3, 1, 3, 8, 1, 1, 0, 2, 0, 7, 0, 2, 1, 4, 6, 4, 0, 0, 10, 0, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 10, 0, 2, 0, 7, 7, 7, 0, 1, 0, 1, 1, 3, 1, 3, 1, 1, 1, 4, 4, 4, 6, 4, 6, 1, 1, 1, 4, 1, 1, 4, 4, 6, 6, 6, 4, 1, 1, 1, 1, 1, 1, 0, 2, 10, 0, 11, 0, 7, 0, 1, 0, 0, 7, 1, 0, 0, 10, 4, 0, 1, 3, 0, 2, 0, 2, 3, 1, 4, 1, 3, 1, 1, 1, 6, 4, 0, 7, 0, 1, 1, 8, 4, 1, 4, 1, 3, 0, 2, 0, 9, 0, 15, 1, 3, 0, 4, 3, 5, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 7, 1, 1, 0, 2, 0, 6, 0, 3, 0, 2, 5, 0, 2, 6, 4, 0, 1, 3, 1, 0, 2, 5, 0, 9, 1, 3, 0, 3, 4, 4, 4, 4, 6, 1, 3, 1, 6, 1, 3, 5, 1, 3, 1, 1, 3, 1, 0, 2, 1, 2, 5, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint16 yydefact[] = { 0, 0, 0, 0, 1, 107, 108, 109, 110, 106, 105, 104, 0, 0, 0, 0, 18, 0, 0, 236, 56, 0, 0, 20, 247, 0, 77, 0, 0, 8, 0, 26, 0, 237, 0, 58, 116, 0, 0, 0, 10, 0, 0, 32, 239, 0, 0, 0, 248, 0, 0, 78, 157, 0, 0, 0, 0, 0, 0, 0, 22, 24, 0, 0, 36, 0, 2, 0, 0, 0, 0, 188, 0, 0, 0, 0, 187, 59, 60, 186, 0, 0, 0, 117, 202, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 30, 0, 0, 42, 0, 0, 240, 0, 0, 276, 250, 57, 0, 0, 0, 68, 0, 0, 62, 75, 76, 0, 0, 0, 158, 230, 5, 0, 0, 0, 0, 12, 0, 21, 23, 0, 0, 0, 0, 34, 0, 0, 50, 0, 238, 0, 0, 277, 0, 198, 0, 64, 0, 69, 0, 0, 200, 0, 0, 0, 0, 0, 203, 17, 9, 0, 14, 16, 15, 0, 0, 0, 0, 49, 48, 0, 0, 27, 29, 0, 0, 0, 0, 38, 40, 0, 0, 0, 246, 243, 279, 0, 249, 0, 0, 0, 0, 0, 0, 0, 190, 0, 79, 0, 0, 0, 0, 231, 11, 0, 0, 0, 0, 25, 0, 33, 35, 0, 0, 0, 0, 0, 44, 46, 54, 0, 0, 0, 0, 0, 0, 0, 0, 113, 65, 111, 0, 72, 0, 0, 201, 0, 0, 0, 0, 232, 6, 0, 0, 3, 31, 0, 37, 39, 0, 0, 0, 0, 0, 52, 19, 0, 0, 278, 280, 254, 252, 0, 199, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 7, 0, 0, 0, 43, 45, 0, 0, 54, 244, 0, 241, 0, 0, 0, 112, 0, 63, 73, 0, 70, 61, 74, 90, 118, 0, 0, 204, 0, 13, 41, 0, 0, 51, 53, 0, 242, 253, 0, 0, 0, 0, 0, 0, 251, 114, 0, 0, 0, 100, 94, 102, 103, 95, 96, 0, 97, 98, 99, 101, 91, 81, 0, 0, 0, 83, 0, 162, 160, 206, 0, 0, 47, 0, 245, 0, 0, 0, 0, 0, 255, 0, 67, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 0, 233, 235, 55, 0, 0, 263, 0, 261, 0, 0, 265, 273, 0, 271, 0, 0, 0, 82, 0, 0, 92, 0, 87, 115, 90, 122, 124, 0, 0, 0, 0, 0, 259, 0, 256, 0, 0, 258, 0, 257, 0, 0, 66, 84, 80, 0, 86, 0, 0, 81, 132, 0, 131, 151, 152, 0, 0, 0, 0, 130, 81, 123, 0, 153, 141, 0, 154, 140, 0, 155, 156, 0, 143, 144, 0, 0, 0, 139, 81, 125, 0, 166, 159, 0, 0, 205, 0, 0, 262, 0, 266, 272, 0, 0, 93, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 177, 165, 169, 193, 161, 221, 218, 224, 223, 219, 220, 217, 222, 216, 0, 214, 274, 270, 0, 268, 260, 85, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 174, 0, 0, 0, 0, 81, 194, 195, 0, 225, 0, 0, 267, 0, 0, 119, 133, 134, 135, 0, 137, 0, 120, 0, 142, 146, 145, 0, 0, 0, 121, 150, 0, 170, 0, 0, 175, 182, 0, 179, 178, 174, 0, 0, 228, 229, 0, 0, 215, 275, 264, 269, 0, 0, 127, 0, 0, 0, 0, 129, 0, 0, 173, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 136, 138, 147, 148, 149, 171, 0, 176, 177, 180, 197, 0, 184, 192, 0, 0, 226, 89, 0, 183, 167, 181, 0, 0, 0, 0, 0, 168, 0, 185, 0, 0, 0, 0, 0, 208, 0, 0, 196, 210, 0, 227, 172, 0, 0, 209, 0, 0, 0, 0, 207, 211, 0, 0, 0, 212, 0, 213 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 2, 16, 22, 29, 90, 128, 40, 57, 169, 166, 19, 20, 31, 59, 60, 43, 95, 96, 64, 135, 100, 179, 180, 139, 218, 219, 172, 184, 255, 256, 26, 49, 77, 193, 269, 78, 151, 300, 233, 51, 118, 36, 238, 367, 341, 426, 515, 342, 399, 454, 344, 345, 79, 231, 232, 83, 52, 347, 438, 456, 521, 532, 439, 457, 440, 458, 84, 121, 376, 375, 492, 493, 635, 494, 595, 626, 495, 570, 537, 600, 571, 619, 346, 407, 540, 541, 542, 153, 154, 122, 159, 350, 377, 642, 652, 656, 507, 544, 508, 583, 581, 160, 204, 280, 309, 24, 33, 65, 103, 224, 291, 186, 34, 48, 145, 264, 293, 324, 384, 385, 387, 388, 511, 512, 390, 391, 546, 105, 106, 188 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -526 static const yytype_int16 yypact[] = { 15, -74, 27, 479, -526, -526, -526, -526, -526, -526, -526, -526, -21, -12, 78, 4, 48, 69, 19, -526, 124, 54, 115, 147, 179, 110, -526, 107, 114, 145, 122, 171, 133, -526, 47, -526, 208, 160, 167, 166, 222, 228, 168, 204, -526, 172, 173, 181, -526, 639, 184, -526, 198, 189, 191, 187, 194, 229, 479, -47, -526, -526, 288, 192, 245, 30, -526, 256, 479, 197, 200, -526, 201, 202, 479, 203, -526, -526, -526, 205, 206, 65, 207, -526, 286, -526, 209, 211, 212, 213, 281, 214, 215, 228, 479, 33, -526, -526, 479, 217, 250, 224, 220, -526, 223, 2, -526, -526, -526, 479, 226, 479, 289, 479, 479, -526, -526, -526, 230, 65, 233, -526, 272, -526, 237, 239, 22, 244, 325, 57, -526, -526, 247, 254, 288, 75, -526, 349, 257, 285, 264, -526, 479, 266, -526, 268, 270, 267, -526, 269, -526, 333, 271, -526, 0, 276, 274, 65, 280, -526, 311, -526, 282, -526, -526, -526, 290, 284, 292, 357, -526, -526, 293, 57, -526, -526, 287, 479, 479, 105, -526, -526, 367, 294, 361, -526, 291, -526, 113, -526, 296, 479, 479, 479, 479, 378, 479, -526, 479, -526, 322, 297, 479, 303, -526, -526, 310, 305, 315, 312, -526, 316, -526, -526, 314, 318, 349, 479, 119, -526, -526, 324, 323, 313, 326, 328, 479, -34, 12, 332, 334, 321, -526, 35, -526, 336, 339, -526, 71, 341, 9, 342, -526, -526, 343, 351, -526, -526, 57, -526, -526, 345, 354, 367, 479, 137, -526, -526, 479, 358, -526, -526, -526, -526, 432, -526, -526, 479, 479, 359, 366, 479, 479, 368, 369, 373, 372, 376, 377, 383, -526, -526, 391, 395, 57, -526, -526, 374, 396, 324, 399, 401, -526, 178, 398, 405, -526, 403, -526, -526, 142, -526, -526, -526, 404, -526, 409, 410, -526, 96, -526, -526, 412, 479, -526, -526, 479, -526, -526, 414, 415, 416, 417, 418, 419, -526, -526, 590, 420, 479, -526, -526, -526, -526, -526, -526, 423, -526, -526, -526, -526, -526, 421, 424, 425, 427, -526, -11, -526, -526, -526, 426, 428, -526, 430, -526, 479, 448, 429, 479, 422, -526, 431, -526, -526, 404, 479, 434, 404, 404, 435, 437, 442, 444, 446, 36, -526, -7, -526, -526, -526, 40, 479, -526, 43, -526, 452, 59, -526, -526, 60, -526, 445, 447, 436, -526, 449, 450, -526, 61, -526, -526, 404, 628, 543, 457, 462, 37, 463, 466, -526, 465, -526, 448, 468, -526, 429, -526, 479, 57, -526, -526, -526, 404, -526, 404, 479, 421, -526, 478, -526, -526, -526, 480, 481, 482, 483, -526, 421, -526, 484, -526, -526, 485, -526, -526, 489, -526, -526, 495, -526, -526, 499, 501, 502, -526, 421, -526, 503, -14, -526, 506, 477, -526, 183, 512, -526, 479, -526, -526, 451, 507, -526, 321, 510, 628, 543, 543, 628, 628, 511, 543, 543, 628, 543, 543, 543, 543, 514, 543, 513, 516, 421, -526, -526, -526, 16, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, 515, -526, 517, -526, 62, -526, -526, -526, 519, 523, 518, 525, 526, 524, 68, -526, 528, 536, 541, 545, 546, 544, 549, 550, 548, 70, -526, 554, 734, 547, 685, 558, 563, 421, -526, -526, 23, 564, 520, 573, -526, 479, 575, -526, -526, -526, -526, 628, -526, 628, -526, 628, -526, -526, -526, 628, 628, 543, -526, -526, 543, -526, 584, 73, -526, -526, 586, -526, -526, 734, 583, 591, -526, -526, 592, 304, -526, -526, -526, -526, 404, 595, -526, 597, 601, 602, 604, -526, 479, 590, -526, 734, -526, 690, 87, 590, 589, 479, 479, 103, 605, -526, -526, -526, -526, -526, 321, 606, -526, -526, 443, -526, 144, -526, -526, 612, 146, -526, -526, 616, -526, 734, -526, 617, 590, 623, 622, 624, -526, 698, -526, 183, 404, 675, 629, 148, -526, 630, 632, -526, 633, 183, -526, -526, 638, 634, -526, 183, 640, 150, 637, -526, -526, 183, 183, 642, -526, 183, -526 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, 648, -526, -526, 608, -526, -526, -526, -526, 529, -526, -526, 493, -170, -526, -526, 458, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -103, -526, -526, -416, -361, -526, -526, 347, 169, -302, -394, -526, -3, -413, 487, -526, -526, -526, -526, -526, -526, -526, -436, -452, -526, -526, -526, -526, -526, -526, -526, -526, -526, 216, -526, -526, 116, 174, 149, -526, -525, -526, -48, -526, -526, 218, 126, -104, 572, -526, -526, -526, -526, -526, -526, -526, -513, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, -526, 453, -526, -526, -526, -526, -526, -526, -526, -526, 353, -526, 348, -526, 219, -526, 350, -526, -526, 665, 433 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -165 static const yytype_int16 yytable[] = { 12, 80, 343, 211, 394, 147, 262, 397, 398, 436, 371, 474, 575, 473, 408, 490, 156, 372, 3, 538, 277, 1, 480, 143, 518, 519, 538, 4, 278, 524, 525, 491, 527, 528, 529, 530, 104, 533, 61, 517, 488, 539, 520, 522, 405, 461, 101, 526, 539, 92, 93, 102, 490, 409, 201, 91, 263, 406, 462, 97, 373, 374, 471, 343, 472, 107, 343, 343, 491, 45, 116, 112, 13, 615, 163, 617, 536, 117, 283, -164, 46, 436, 14, -164, 436, 436, 164, 165, 229, 436, 61, 132, 274, 197, 237, 136, 15, 198, 17, 275, 343, 435, 47, 575, 18, 265, 146, 21, 149, 198, 152, 146, 593, 23, 312, 594, 5, 351, 588, 28, 589, 343, 590, 343, 578, 643, 591, 592, 270, 133, 134, 97, 271, 410, 181, 653, 412, 226, 25, 187, 413, 657, 6, 7, 170, 171, 27, 662, 663, 8, 9, 665, 415, 417, 424, 547, 416, 418, 425, 548, 436, 555, 436, 566, 436, 556, 597, 567, 436, 436, 598, 176, 177, 435, 213, 214, 435, 435, 30, 220, 618, 435, 613, 10, 598, 11, 498, 318, 146, 146, 230, 234, 623, 236, 32, 146, 624, 37, 319, 241, 425, 215, 216, 5, 35, 352, 38, 499, 500, 225, 226, 39, 501, 181, 251, 252, 253, 41, 502, 503, 42, 398, 504, 261, 320, 321, 607, 44, 505, 6, 7, 322, 323, 288, 289, 50, 8, 9, 328, 329, 630, 631, 633, 268, 647, 648, 659, 660, 5, 470, 220, 287, 435, 53, 435, 290, 435, 54, 55, 56, 435, 435, 63, 62, 295, 230, 66, 67, 299, 301, 10, 82, 11, 68, 6, 7, 81, 87, 644, 362, 343, 8, 9, 85, 86, 343, 88, 98, 89, 99, 104, 108, 109, 110, 111, 113, 120, 114, 127, 119, 115, 138, 125, 123, 124, 126, 146, 330, 5, 130, 354, 129, 137, 290, 141, 10, 140, 11, 142, 150, 58, 148, 158, 155, 5, 157, 364, 70, 331, 332, 71, 161, 162, 333, 6, 7, 167, 343, 168, 334, 335, 8, 9, 336, 173, 337, 338, 339, 174, 340, 6, 7, 182, 187, 383, 185, 389, 8, 9, 183, 189, 190, 191, 395, 192, 195, 194, 76, 196, 5, 199, 200, 202, 203, 207, 10, 205, 11, 209, 411, 94, 212, 222, 206, 208, 235, 210, 5, 223, 221, 227, 10, 239, 11, 240, 6, 7, 242, 244, 605, 437, 455, 8, 9, 243, 245, 246, 330, 258, 247, 383, 248, 249, 6, 7, 389, 254, 257, 268, 259, 8, 9, 260, 230, 5, 266, 267, 70, 331, 332, 71, 272, 273, 333, 276, 279, 10, 281, 11, 334, 335, 178, 284, 336, 282, 337, 338, 339, 285, 340, 6, 7, 292, 294, 10, 297, 11, 8, 9, 217, 298, 506, 302, 303, 510, 304, 305, 76, 5, 306, 307, 313, 437, 455, 455, 437, 437, 308, 455, 455, 437, 455, 455, 455, 455, 310, 455, 572, 311, 572, 314, 10, 325, 11, 6, 7, 316, 317, 326, 5, 327, 8, 9, 348, 349, 353, 356, 357, 358, 359, 360, 392, 629, 361, 363, 365, 368, 369, 366, 370, 378, 386, 379, 380, 393, 6, 7, 396, 572, 421, 400, 401, 8, 9, 402, 10, 403, 11, 404, 414, 382, 420, 419, 422, 513, 510, 441, 423, 614, 459, 572, 437, 572, 437, 620, 437, 460, 463, 464, 437, 437, 455, 465, 5, 455, 467, 10, 331, 11, 442, 475, 497, 476, 477, 478, 479, 481, 482, 334, 335, 572, 483, 443, 637, 337, 338, 339, 484, 444, 6, 7, 485, 230, 486, 487, 489, 8, 9, 496, 509, 514, 622, 230, 516, 523, 534, 445, 531, 535, 584, 5, 551, 543, 70, 545, 549, 71, 550, 552, 553, 446, 554, 557, 447, 448, 449, 450, 451, 452, 453, 10, 330, 11, 558, 559, 506, 6, 7, 560, 561, 573, 562, 565, 8, 9, 506, 563, 564, 5, 568, 576, 506, 331, 76, 428, 577, 582, 506, 506, 5, 69, 506, 70, 334, 335, 71, 585, 429, 72, 337, 338, 339, 587, 340, 6, 7, 596, 10, 602, 11, 599, 8, 9, 621, 603, 6, 7, 73, 608, 604, 609, 430, 8, 9, 610, 611, 74, 612, 625, 627, 75, 538, 76, 431, 432, 5, 433, 434, 70, 632, 5, 71, 634, 70, 636, 10, 71, 11, 638, 639, 491, 640, 646, 649, 569, 650, 10, 655, 11, 569, 651, 6, 7, 654, 658, 661, 6, 7, 8, 9, 664, 131, 175, 8, 9, 250, 286, 315, 76, 427, 601, 606, 574, 76, 5, 296, 645, 70, 616, 579, 71, 580, 641, 228, 468, 628, 466, 586, 469, 355, 144, 0, 10, 569, 11, 0, 0, 10, 0, 11, 6, 7, 0, 0, 0, 0, 0, 8, 9, 381, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 11 }; static const yytype_int16 yycheck[] = { 3, 49, 304, 173, 365, 109, 40, 368, 369, 403, 21, 427, 537, 426, 21, 29, 119, 28, 92, 3, 11, 6, 438, 21, 476, 477, 3, 0, 19, 481, 482, 45, 484, 485, 486, 487, 34, 489, 41, 475, 456, 25, 478, 479, 8, 8, 16, 483, 25, 96, 97, 21, 29, 60, 157, 58, 90, 21, 21, 62, 71, 72, 423, 365, 425, 68, 368, 369, 45, 22, 5, 74, 93, 598, 52, 600, 492, 12, 248, 93, 33, 475, 94, 97, 478, 479, 64, 65, 192, 483, 93, 94, 21, 93, 198, 98, 18, 97, 94, 28, 402, 403, 55, 628, 56, 93, 109, 38, 111, 97, 113, 114, 564, 94, 284, 567, 20, 21, 554, 4, 556, 423, 558, 425, 540, 638, 562, 563, 93, 96, 97, 134, 97, 93, 137, 648, 93, 97, 14, 142, 97, 654, 46, 47, 87, 88, 92, 660, 661, 53, 54, 664, 93, 93, 93, 93, 97, 97, 97, 97, 554, 93, 556, 93, 558, 97, 93, 97, 562, 563, 97, 96, 97, 475, 177, 178, 478, 479, 31, 182, 93, 483, 595, 87, 97, 89, 3, 9, 191, 192, 193, 194, 605, 196, 15, 198, 93, 90, 20, 202, 97, 96, 97, 20, 94, 309, 92, 24, 25, 96, 97, 66, 29, 216, 217, 96, 97, 95, 35, 36, 49, 582, 39, 226, 46, 47, 587, 94, 45, 46, 47, 53, 54, 96, 97, 27, 53, 54, 96, 97, 96, 97, 96, 97, 96, 97, 96, 97, 20, 419, 253, 254, 554, 93, 556, 258, 558, 90, 92, 37, 562, 563, 58, 95, 267, 268, 94, 94, 271, 272, 87, 73, 89, 92, 46, 47, 92, 90, 639, 327, 582, 53, 54, 94, 93, 587, 92, 95, 59, 44, 34, 94, 92, 92, 92, 92, 10, 92, 17, 92, 94, 51, 90, 94, 93, 92, 309, 3, 20, 94, 313, 97, 95, 316, 94, 87, 92, 89, 95, 30, 92, 95, 50, 93, 20, 92, 329, 23, 24, 25, 26, 94, 93, 29, 46, 47, 92, 639, 13, 35, 36, 53, 54, 39, 97, 41, 42, 43, 94, 45, 46, 47, 95, 356, 357, 91, 359, 53, 54, 74, 94, 93, 92, 366, 97, 32, 97, 63, 97, 20, 94, 97, 92, 62, 90, 87, 94, 89, 21, 382, 92, 94, 21, 93, 92, 7, 93, 20, 97, 95, 94, 87, 70, 89, 97, 46, 47, 94, 93, 95, 403, 404, 53, 54, 94, 90, 94, 3, 95, 93, 413, 97, 94, 46, 47, 418, 92, 94, 97, 93, 53, 54, 94, 426, 20, 93, 92, 23, 24, 25, 26, 95, 93, 29, 93, 93, 87, 94, 89, 35, 36, 92, 97, 39, 93, 41, 42, 43, 94, 45, 46, 47, 94, 21, 87, 96, 89, 53, 54, 92, 94, 464, 94, 94, 467, 92, 94, 63, 20, 93, 93, 97, 475, 476, 477, 478, 479, 94, 481, 482, 483, 484, 485, 486, 487, 94, 489, 535, 93, 537, 94, 87, 94, 89, 46, 47, 97, 96, 93, 20, 97, 53, 54, 94, 94, 93, 92, 92, 92, 92, 92, 89, 69, 94, 94, 92, 92, 92, 97, 92, 94, 92, 94, 93, 93, 46, 47, 93, 576, 93, 95, 94, 53, 54, 92, 87, 92, 89, 92, 87, 92, 94, 97, 94, 93, 548, 3, 97, 596, 92, 598, 554, 600, 556, 602, 558, 94, 94, 92, 562, 563, 564, 97, 20, 567, 97, 87, 24, 89, 26, 92, 94, 92, 92, 92, 92, 92, 92, 35, 36, 628, 92, 39, 631, 41, 42, 43, 92, 45, 46, 47, 92, 595, 92, 92, 92, 53, 54, 92, 87, 93, 604, 605, 93, 93, 92, 63, 93, 92, 89, 20, 93, 97, 23, 97, 96, 26, 94, 93, 93, 77, 97, 94, 80, 81, 82, 83, 84, 85, 86, 87, 3, 89, 97, 93, 638, 46, 47, 93, 93, 93, 97, 94, 53, 54, 648, 97, 97, 20, 95, 92, 654, 24, 63, 26, 92, 92, 660, 661, 20, 21, 664, 23, 35, 36, 26, 93, 39, 29, 41, 42, 43, 97, 45, 46, 47, 92, 87, 95, 89, 94, 53, 54, 94, 93, 46, 47, 48, 93, 97, 93, 63, 53, 54, 93, 93, 57, 93, 93, 93, 61, 3, 63, 75, 76, 20, 78, 79, 23, 97, 20, 26, 96, 23, 97, 87, 26, 89, 95, 97, 45, 97, 93, 93, 39, 93, 87, 93, 89, 39, 97, 46, 47, 95, 94, 98, 46, 47, 53, 54, 98, 93, 134, 53, 54, 216, 253, 289, 63, 402, 576, 582, 67, 63, 20, 268, 640, 23, 68, 543, 26, 543, 636, 191, 416, 616, 413, 548, 418, 316, 105, -1, 87, 39, 89, -1, -1, 87, -1, 89, 46, 47, -1, -1, -1, -1, -1, 53, 54, 356, -1, -1, -1, -1, -1, -1, -1, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 87, -1, 89 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 6, 100, 92, 0, 20, 46, 47, 53, 54, 87, 89, 152, 93, 94, 18, 101, 94, 56, 110, 111, 38, 102, 94, 205, 14, 130, 92, 4, 103, 31, 112, 15, 206, 212, 94, 141, 90, 92, 66, 106, 95, 49, 115, 94, 22, 33, 55, 213, 131, 27, 139, 156, 93, 90, 92, 37, 107, 92, 113, 114, 152, 95, 58, 118, 207, 94, 94, 92, 21, 23, 26, 29, 48, 57, 61, 63, 132, 135, 152, 182, 92, 73, 155, 166, 94, 93, 90, 92, 59, 104, 152, 96, 97, 92, 116, 117, 152, 95, 44, 120, 16, 21, 208, 34, 227, 228, 152, 94, 92, 92, 92, 152, 92, 92, 94, 5, 12, 140, 92, 10, 167, 189, 94, 93, 90, 92, 17, 105, 97, 94, 114, 152, 96, 97, 119, 152, 95, 51, 123, 92, 94, 95, 21, 228, 214, 152, 187, 95, 152, 30, 136, 152, 187, 188, 93, 140, 92, 50, 190, 201, 94, 93, 52, 64, 65, 109, 92, 13, 108, 87, 88, 126, 97, 94, 117, 96, 97, 92, 121, 122, 152, 95, 74, 127, 91, 211, 152, 229, 94, 93, 92, 97, 133, 97, 32, 97, 93, 97, 94, 97, 140, 92, 62, 202, 94, 93, 90, 92, 21, 93, 126, 94, 152, 152, 96, 97, 92, 124, 125, 152, 95, 21, 97, 209, 96, 97, 94, 188, 187, 152, 153, 154, 138, 152, 7, 152, 187, 142, 70, 97, 152, 94, 94, 93, 90, 94, 93, 97, 94, 122, 152, 96, 97, 92, 128, 129, 94, 95, 93, 94, 152, 40, 90, 215, 93, 93, 92, 97, 134, 93, 97, 95, 93, 21, 28, 93, 11, 19, 93, 203, 94, 93, 126, 97, 94, 125, 152, 96, 97, 152, 210, 94, 216, 21, 152, 154, 96, 94, 152, 137, 152, 94, 94, 92, 94, 93, 93, 94, 204, 94, 93, 126, 97, 94, 129, 97, 96, 9, 20, 46, 47, 53, 54, 217, 94, 93, 97, 96, 97, 3, 24, 25, 29, 35, 36, 39, 41, 42, 43, 45, 144, 147, 149, 150, 151, 182, 157, 94, 94, 191, 21, 187, 93, 152, 210, 92, 92, 92, 92, 92, 94, 182, 94, 152, 92, 97, 143, 92, 92, 92, 21, 28, 71, 72, 169, 168, 192, 94, 94, 93, 229, 92, 152, 218, 219, 92, 220, 221, 152, 224, 225, 89, 93, 144, 152, 93, 144, 144, 148, 95, 94, 92, 92, 92, 8, 21, 183, 21, 60, 93, 152, 93, 97, 87, 93, 97, 93, 97, 97, 94, 93, 94, 97, 93, 97, 145, 147, 26, 39, 63, 75, 76, 78, 79, 149, 150, 152, 158, 162, 164, 3, 26, 39, 45, 63, 77, 80, 81, 82, 83, 84, 85, 86, 149, 152, 159, 163, 165, 92, 94, 8, 21, 94, 92, 97, 219, 97, 221, 225, 126, 144, 144, 153, 143, 92, 92, 92, 92, 92, 143, 92, 92, 92, 92, 92, 92, 92, 143, 92, 29, 45, 170, 171, 173, 176, 92, 94, 3, 24, 25, 29, 35, 36, 39, 45, 152, 196, 198, 87, 152, 222, 223, 93, 93, 146, 93, 162, 163, 163, 162, 160, 162, 93, 163, 163, 162, 163, 163, 163, 163, 93, 161, 163, 92, 92, 143, 178, 3, 25, 184, 185, 186, 97, 197, 97, 226, 93, 97, 96, 94, 93, 93, 93, 97, 93, 97, 94, 97, 93, 93, 93, 97, 97, 97, 94, 93, 97, 95, 39, 177, 180, 182, 93, 67, 180, 92, 92, 143, 173, 185, 200, 92, 199, 89, 93, 223, 97, 162, 162, 162, 162, 162, 163, 163, 174, 92, 93, 97, 94, 179, 177, 95, 93, 97, 95, 148, 144, 93, 93, 93, 93, 93, 153, 182, 180, 68, 180, 93, 181, 182, 94, 152, 153, 93, 93, 175, 93, 178, 69, 96, 97, 97, 96, 96, 172, 97, 182, 95, 97, 97, 186, 193, 196, 144, 176, 93, 96, 97, 93, 93, 97, 194, 196, 95, 93, 195, 196, 94, 96, 97, 98, 196, 196, 98, 196 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 247 "dfgparser.y" { string_StringFree((yyvsp[(3) - (11)].string)); YYACCEPT; /* Stop immediately */ ;} break; case 4: #line 267 "dfgparser.y" { dfg_DESC->name = (yyvsp[(3) - (5)].string); ;} break; case 5: #line 271 "dfgparser.y" { dfg_DESC->author = (yyvsp[(3) - (5)].string); ;} break; case 6: #line 275 "dfgparser.y" { dfg_DESC->status = (yyvsp[(3) - (5)].state); ;} break; case 7: #line 279 "dfgparser.y" { dfg_DESC->description = (yyvsp[(3) - (5)].string); ;} break; case 9: #line 284 "dfgparser.y" { dfg_DESC->version = (yyvsp[(3) - (5)].string); ;} break; case 11: #line 289 "dfgparser.y" { dfg_DESC->logic = (yyvsp[(3) - (5)].string); ;} break; case 13: #line 294 "dfgparser.y" { dfg_DESC->date = (yyvsp[(3) - (5)].string); ;} break; case 14: #line 297 "dfgparser.y" { (yyval.state) = DFG_SATISFIABLE; ;} break; case 15: #line 298 "dfgparser.y" { (yyval.state) = DFG_UNSATISFIABLE; ;} break; case 16: #line 299 "dfgparser.y" { (yyval.state) = DFG_UNKNOWNSTATE; ;} break; case 24: #line 338 "dfgparser.y" { dfg_SymbolDecl(DFG_FUNC, (yyvsp[(1) - (1)].string), -2); ;} break; case 25: #line 340 "dfgparser.y" { dfg_SymbolDecl(DFG_FUNC, (yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].number)); ;} break; case 30: #line 351 "dfgparser.y" { dfg_SymbolDecl(DFG_PRDICAT, (yyvsp[(1) - (1)].string), -2); ;} break; case 31: #line 352 "dfgparser.y" { dfg_SymbolDecl(DFG_PRDICAT, (yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].number)); ;} break; case 34: #line 359 "dfgparser.y" { dfg_SymbolDecl(DFG_PRDICAT, (yyvsp[(1) - (1)].string), 1); ;} break; case 35: #line 360 "dfgparser.y" { dfg_SymbolDecl(DFG_PRDICAT, (yyvsp[(3) - (3)].string), 1); ;} break; case 40: #line 371 "dfgparser.y" { dfg_SymbolDecl(DFG_OPERAT, (yyvsp[(1) - (1)].string), -2); ;} break; case 41: #line 372 "dfgparser.y" { dfg_SymbolDecl(DFG_OPERAT, (yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].number)); ;} break; case 46: #line 383 "dfgparser.y" { dfg_SymbolDecl(DFG_QUANTIF, (yyvsp[(1) - (1)].string), -2); ;} break; case 47: #line 384 "dfgparser.y" { dfg_SymbolDecl(DFG_QUANTIF, (yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].number)); ;} break; case 48: #line 387 "dfgparser.y" { (yyval.number) = -1; ;} break; case 49: #line 388 "dfgparser.y" { (yyval.number) = (yyvsp[(1) - (1)].number); ;} break; case 55: #line 399 "dfgparser.y" { dfg_TranslPairDecl((yyvsp[(2) - (5)].string), (yyvsp[(4) - (5)].string)); ;} break; case 61: #line 418 "dfgparser.y" { dfg_SubSort((yyvsp[(3) - (7)].string),(yyvsp[(5) - (7)].string)); ;} break; case 62: #line 419 "dfgparser.y" { dfg_SORTDECLLIST = list_Nconc(dfg_SORTDECLLIST,list_List(list_PairCreate(NULL,(yyvsp[(1) - (2)].term)))); ;} break; case 63: #line 421 "dfgparser.y" { string_StringFree((yyvsp[(3) - (7)].string)); ;} break; case 64: #line 422 "dfgparser.y" { dfg_VarStart(); ;} break; case 65: #line 423 "dfgparser.y" { dfg_VarStop(); ;} break; case 66: #line 424 "dfgparser.y" { TERM term; dfg_VarBacktrack(); dfg_VarCheck(); term = dfg_CreateQuantifier(fol_All(),(yyvsp[(5) - (11)].list),(yyvsp[(9) - (11)].term)); dfg_SORTDECLLIST = list_Nconc(dfg_SORTDECLLIST,list_List(list_PairCreate(NULL,term))); ;} break; case 67: #line 433 "dfgparser.y" { dfg_SymbolGenerated(dfg_Symbol((yyvsp[(2) - (9)].string),1), (yyvsp[(3) - (9)].bool), (yyvsp[(7) - (9)].list)); ;} break; case 68: #line 436 "dfgparser.y" { (yyval.bool) = FALSE; ;} break; case 69: #line 437 "dfgparser.y" { (yyval.bool) = TRUE; ;} break; case 70: #line 440 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].string)); ;} break; case 71: #line 441 "dfgparser.y" { (yyval.list) = list_Cons((yyvsp[(3) - (3)].string), (yyvsp[(1) - (3)].list)); ;} break; case 72: #line 444 "dfgparser.y" { string_StringFree((yyvsp[(1) - (1)].string)); ;} break; case 73: #line 445 "dfgparser.y" { string_StringFree((yyvsp[(3) - (3)].string)); ;} break; case 74: #line 454 "dfgparser.y" { list_NReverse((yyvsp[(6) - (8)].list)); if ((yyvsp[(3) - (8)].bool)) /* Axioms */ dfg_AXIOMLIST = list_Nconc(dfg_AXIOMLIST, (yyvsp[(6) - (8)].list)); else dfg_CONJECLIST = list_Nconc(dfg_CONJECLIST, (yyvsp[(6) - (8)].list)); ;} break; case 75: #line 462 "dfgparser.y" { (yyval.bool) = TRUE; ;} break; case 76: #line 463 "dfgparser.y" { (yyval.bool) = FALSE; ;} break; case 79: #line 470 "dfgparser.y" { (yyval.list) = list_Nil(); ;} break; case 80: #line 472 "dfgparser.y" { LIST pair; if ((yyvsp[(4) - (7)].term) == NULL) { /* No term */ if ((yyvsp[(5) - (7)].string) != NULL) string_StringFree((yyvsp[(5) - (7)].string)); (yyval.list) = (yyvsp[(1) - (7)].list); } else { pair = list_PairCreate((yyvsp[(5) - (7)].string), (yyvsp[(4) - (7)].term)); (yyval.list) = list_Cons(pair, (yyvsp[(1) - (7)].list)); } dfg_VarCheck(); ;} break; case 81: #line 485 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 82: #line 486 "dfgparser.y" { (yyval.string) = (yyvsp[(2) - (2)].string); ;} break; case 83: #line 489 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 84: #line 491 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_Not(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 85: #line 493 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (6)].symbol), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 86: #line 495 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (4)].symbol), (yyvsp[(3) - (4)].list)); ;} break; case 87: #line 496 "dfgparser.y" { dfg_VarStart(); ;} break; case 88: #line 497 "dfgparser.y" { dfg_VarStop(); ;} break; case 89: #line 499 "dfgparser.y" { dfg_VarBacktrack(); (yyval.term) = dfg_IGNORE ? NULL : dfg_CreateQuantifier((yyvsp[(1) - (10)].symbol),(yyvsp[(5) - (10)].list),(yyvsp[(9) - (10)].term)); ;} break; case 90: #line 504 "dfgparser.y" { (yyval.term) = NULL; ;} break; case 91: #line 505 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 92: #line 509 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? list_Nil() : list_List((yyvsp[(1) - (1)].term)); ;} break; case 93: #line 511 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (3)].list) : list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 94: #line 514 "dfgparser.y" { (yyval.symbol) = fol_Equiv(); ;} break; case 95: #line 515 "dfgparser.y" { (yyval.symbol) = fol_Implied(); ;} break; case 96: #line 516 "dfgparser.y" { (yyval.symbol) = fol_Implies(); ;} break; case 97: #line 517 "dfgparser.y" { (yyval.symbol) = fol_Xor(); ;} break; case 98: #line 518 "dfgparser.y" { (yyval.symbol) = fol_Nor(); ;} break; case 99: #line 519 "dfgparser.y" { (yyval.symbol) = fol_Nand(); ;} break; case 100: #line 522 "dfgparser.y" { (yyval.symbol) = fol_And(); ;} break; case 101: #line 523 "dfgparser.y" { (yyval.symbol) = fol_Or(); ;} break; case 102: #line 526 "dfgparser.y" { (yyval.symbol) = fol_Exist(); ;} break; case 103: #line 527 "dfgparser.y" { (yyval.symbol) = fol_All(); ;} break; case 104: #line 530 "dfgparser.y" { if (dfg_IGNORE) { string_StringFree((yyvsp[(1) - (1)].string)); (yyval.string) = NULL; } else (yyval.string) = (yyvsp[(1) - (1)].string); ;} break; case 105: #line 537 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_IntToString((yyvsp[(1) - (1)].number)); ;} break; case 106: #line 539 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_StringCopy("set_flag"); ;} break; case 107: #line 541 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_StringCopy("set_DomPred"); ;} break; case 108: #line 543 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_StringCopy("set_precedence"); ;} break; case 109: #line 545 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_StringCopy("set_ClauseFormulaRelation"); ;} break; case 110: #line 547 "dfgparser.y" { (yyval.string) = dfg_IGNORE ? NULL : string_StringCopy("set_selection"); ;} break; case 111: #line 551 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? list_Nil() : list_List((yyvsp[(1) - (1)].term)); ;} break; case 112: #line 553 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (3)].list) : list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 113: #line 557 "dfgparser.y" { if (!dfg_IGNORE) { SYMBOL s = dfg_Symbol((yyvsp[(1) - (1)].string),0); if (!symbol_IsVariable(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: Symbol is not a variable.\n",dfg_LINENUMBER); misc_FinishUserErrorReport(); } (yyval.term) = term_Create(s, list_Nil()); } ;} break; case 114: #line 568 "dfgparser.y" { if (!dfg_IGNORE) { SYMBOL p, v; p = dfg_Symbol((yyvsp[(1) - (4)].string), 1); if (!symbol_IsPredicate(p)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: Symbol is not a predicate.\n",dfg_LINENUMBER); misc_FinishUserErrorReport(); } v = dfg_Symbol((yyvsp[(3) - (4)].string), 0); if (!symbol_IsVariable(v)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %d: Symbol is not a variable.\n",dfg_LINENUMBER); misc_FinishUserErrorReport(); } (yyval.term) = term_Create(p, list_List(term_Create(v,list_Nil()))); } ;} break; case 115: #line 593 "dfgparser.y" { list_NReverse((yyvsp[(8) - (10)].list)); if ((yyvsp[(3) - (10)].bool)) /* Axioms */ dfg_AXIOMLIST = list_Nconc(dfg_AXIOMLIST, (yyvsp[(8) - (10)].list)); else dfg_CONJECLIST = list_Nconc(dfg_CONJECLIST, (yyvsp[(8) - (10)].list)); flag_SetFlagIntValue(dfg_FLAGS, flag_EML, flag_EMLON); ;} break; case 118: #line 606 "dfgparser.y" { (yyval.list) = list_Nil(); ;} break; case 119: #line 609 "dfgparser.y" { LIST pair; if ((yyvsp[(4) - (7)].term) == NULL) { /* No term */ if ((yyvsp[(5) - (7)].string) != NULL) string_StringFree((yyvsp[(5) - (7)].string)); (yyval.list) = (yyvsp[(1) - (7)].list); } else { pair = list_PairCreate((yyvsp[(5) - (7)].string), (yyvsp[(4) - (7)].term)); (yyval.list) = list_Cons(pair, (yyvsp[(1) - (7)].list)); } dfg_VarCheck(); ;} break; case 120: #line 622 "dfgparser.y" { LIST pair; if ((yyvsp[(4) - (7)].term) == NULL) { /* No term */ if ((yyvsp[(5) - (7)].string) != NULL) string_StringFree((yyvsp[(5) - (7)].string)); (yyval.list) = (yyvsp[(1) - (7)].list); } else { pair = list_PairCreate((yyvsp[(5) - (7)].string), (yyvsp[(4) - (7)].term)); (yyval.list) = list_Nconc((yyvsp[(1) - (7)].list), list_List(pair)); } ;} break; case 121: #line 634 "dfgparser.y" { LIST pair; if ((yyvsp[(4) - (7)].term) == NULL) { /* No term */ if ((yyvsp[(5) - (7)].string) != NULL) string_StringFree((yyvsp[(5) - (7)].string)); (yyval.list) = (yyvsp[(1) - (7)].list); } else { pair = list_PairCreate((yyvsp[(5) - (7)].string), (yyvsp[(4) - (7)].term)); (yyval.list) = list_Nconc((yyvsp[(1) - (7)].list), list_List(pair)); } ;} break; case 122: #line 648 "dfgparser.y" { (yyval.term) = NULL; ;} break; case 123: #line 649 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 124: #line 652 "dfgparser.y" { (yyval.term) = NULL; ;} break; case 125: #line 653 "dfgparser.y" { (yyval.term) = term_Create(eml_Box(), list_Cons(term_Create(fol_Not(), list_List((yyvsp[(1) - (1)].term))), list_List(term_Create(fol_False(), list_Nil())))); /* since r = 1 iff (r':1)' = 1 */ ;} break; case 126: #line 660 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].term)); ;} break; case 127: #line 661 "dfgparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 128: #line 664 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].term)); ;} break; case 129: #line 665 "dfgparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 130: #line 669 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_AtomCreate((yyvsp[(1) - (1)].string), list_Nil()); ;} break; case 131: #line 671 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_True(),list_Nil()); ;} break; case 132: #line 673 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_False(),list_Nil()); ;} break; case 133: #line 675 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_Not(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 134: #line 677 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Domain(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 135: #line 679 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Range(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 136: #line 681 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (6)].symbol), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 137: #line 683 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (4)].symbol), (yyvsp[(3) - (4)].list)); ;} break; case 138: #line 685 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (6)].symbol), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 139: #line 689 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_AtomCreate((yyvsp[(1) - (1)].string), list_Nil()); ;} break; case 140: #line 691 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_True(),list_Nil()); ;} break; case 141: #line 693 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_False(),list_Nil()); ;} break; case 142: #line 695 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_Not(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 143: #line 697 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Id(),list_Nil()); ;} break; case 144: #line 699 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Div(),list_Nil()); ;} break; case 145: #line 701 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Conv(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 146: #line 703 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_Test(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 147: #line 705 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_DomRestr(), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 148: #line 707 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(eml_RanRestr(), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 149: #line 709 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (6)].symbol), list_Cons((yyvsp[(3) - (6)].term), list_List((yyvsp[(5) - (6)].term)))); ;} break; case 150: #line 711 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create((yyvsp[(1) - (4)].symbol), (yyvsp[(3) - (4)].list)); ;} break; case 151: #line 714 "dfgparser.y" { (yyval.symbol) = eml_Box(); ;} break; case 152: #line 715 "dfgparser.y" { (yyval.symbol) = eml_Dia(); ;} break; case 153: #line 718 "dfgparser.y" { (yyval.symbol) = fol_And(); ;} break; case 154: #line 719 "dfgparser.y" { (yyval.symbol) = fol_Or(); ;} break; case 155: #line 720 "dfgparser.y" { (yyval.symbol) = eml_Comp(); ;} break; case 156: #line 721 "dfgparser.y" { (yyval.symbol) = eml_Sum(); ;} break; case 159: #line 736 "dfgparser.y" { list_NReverse((yyvsp[(8) - (10)].list)); if (!list_Empty(dfg_TEMPPLAINCLAUSES)) { /* Plain clauses are temporarily stored in the list dfg_TEMPPLAINCLAUSES. They need to be concatenated to their respective axiom or conjecture plain clause lists. */ if ((yyvsp[(3) - (10)].bool)) /* Axioms */ dfg_PLAINAXCLAUSES = list_Nconc(dfg_PLAINAXCLAUSES, list_NReverse(dfg_TEMPPLAINCLAUSES)); else dfg_PLAINCONCLAUSES = list_Nconc(dfg_PLAINCONCLAUSES, list_NReverse(dfg_TEMPPLAINCLAUSES)); dfg_TEMPPLAINCLAUSES = list_Nil(); } if (!list_Empty((yyvsp[(8) - (10)].list))) { if ((yyvsp[(3) - (10)].bool)) /* Axioms */ dfg_AXCLAUSES = list_Nconc(dfg_AXCLAUSES, (yyvsp[(8) - (10)].list)); else dfg_CONCLAUSES = list_Nconc(dfg_CONCLAUSES, (yyvsp[(8) - (10)].list)); } ;} break; case 160: #line 755 "dfgparser.y" { stack_Push((POINTER)dfg_IGNORE); dfg_IGNORE = TRUE; ;} break; case 161: #line 758 "dfgparser.y" { dfg_IGNORE = (BOOL)stack_PopResult(); ;} break; case 162: #line 761 "dfgparser.y" { (yyval.list) = list_Nil(); ;} break; case 163: #line 763 "dfgparser.y" { LIST pair; if ((yyvsp[(4) - (7)].term) == NULL) { /* No clause */ if ((yyvsp[(5) - (7)].string) != NULL) string_StringFree((yyvsp[(5) - (7)].string)); (yyval.list) = (yyvsp[(1) - (7)].list); } else { pair = list_PairCreate((yyvsp[(5) - (7)].string), (yyvsp[(4) - (7)].term)); (yyval.list) = list_Cons(pair, (yyvsp[(1) - (7)].list)); } dfg_VarCheck(); ;} break; case 164: #line 776 "dfgparser.y" { (yyval.term) = NULL; ;} break; case 165: #line 777 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 166: #line 778 "dfgparser.y" {dfg_VarStart();;} break; case 167: #line 778 "dfgparser.y" {dfg_VarStop();;} break; case 168: #line 779 "dfgparser.y" { dfg_VarBacktrack(); if (dfg_IGNORE) (yyval.term) = NULL; else { /* C || A -> S */ DFG_PLAINCLAUSE clause = dfg_PlainClauseCreate(); clause->constraint = (yyvsp[(2) - (7)].list); clause->antecedent = (yyvsp[(4) - (7)].list); clause->succedent = (yyvsp[(6) - (7)].list); clause->selected = dfg_SELECTED_LITERAL; dfg_SELECTED_LITERAL = (TERM) NULL; dfg_TEMPPLAINCLAUSES = list_Cons(clause,dfg_TEMPPLAINCLAUSES); (yyval.term) = NULL; } ;} break; case 169: #line 796 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 170: #line 797 "dfgparser.y" { dfg_VarStart(); ;} break; case 171: #line 798 "dfgparser.y" { dfg_VarStop(); ;} break; case 172: #line 800 "dfgparser.y" { dfg_VarBacktrack(); (yyval.term) = dfg_IGNORE ? NULL : dfg_CreateQuantifier(fol_All(),(yyvsp[(5) - (10)].list),(yyvsp[(9) - (10)].term)); ;} break; case 173: #line 806 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_Or(), (yyvsp[(3) - (4)].list)); ;} break; case 174: #line 809 "dfgparser.y" {(yyval.list) = list_Nil();;} break; case 175: #line 811 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? list_Nil() : list_List((yyvsp[(1) - (1)].term)); ;} break; case 176: #line 813 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (3)].list) : list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 177: #line 816 "dfgparser.y" {(yyval.list) = list_Nil();;} break; case 178: #line 818 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (2)].list) : list_Nconc((yyvsp[(1) - (2)].list), list_List((yyvsp[(2) - (2)].term))); ;} break; case 179: #line 821 "dfgparser.y" {(yyval.list) = list_Nil();;} break; case 180: #line 823 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (2)].list) : list_Nconc((yyvsp[(1) - (2)].list), list_List((yyvsp[(2) - (2)].term))); ;} break; case 181: #line 825 "dfgparser.y" { if (dfg_IGNORE) (yyval.list) = (yyvsp[(1) - (3)].list); else { if(dfg_SELECTED_LITERAL != NULL) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Trying to select two literals in a clause."); misc_FinishUserErrorReport(); } dfg_SELECTED_LITERAL = (yyvsp[(2) - (3)].term); (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(2) - (3)].term))); } ;} break; case 182: #line 839 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 183: #line 841 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? (yyvsp[(3) - (4)].term) : term_Create(fol_Not(),list_List((yyvsp[(3) - (4)].term))); ;} break; case 184: #line 844 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].term)); ;} break; case 185: #line 845 "dfgparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].term))); ;} break; case 186: #line 849 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_AtomCreate((yyvsp[(1) - (1)].string),list_Nil()); ;} break; case 187: #line 851 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_True(),list_Nil()); ;} break; case 188: #line 853 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_False(),list_Nil()); ;} break; case 189: #line 855 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : term_Create(fol_Equality(),list_Cons((yyvsp[(3) - (6)].term),list_List((yyvsp[(5) - (6)].term)))); ;} break; case 190: #line 857 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_AtomCreate((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].list)); ;} break; case 198: #line 883 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_TermCreate((yyvsp[(1) - (1)].string),list_Nil()); ;} break; case 199: #line 885 "dfgparser.y" { (yyval.term) = dfg_IGNORE ? NULL : dfg_TermCreate((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].list)); ;} break; case 200: #line 889 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? list_Nil() : list_List((yyvsp[(1) - (1)].term)); ;} break; case 201: #line 891 "dfgparser.y" { (yyval.list) = dfg_IGNORE ? (yyvsp[(1) - (3)].list) : list_Nconc((yyvsp[(1) - (3)].list),list_List((yyvsp[(3) - (3)].term))); ;} break; case 204: #line 903 "dfgparser.y" { if (!string_Equal((yyvsp[(3) - (5)].string),"SPASS")) { stack_Push((POINTER)dfg_IGNORE); dfg_IGNORE = TRUE; } ;} break; case 205: #line 910 "dfgparser.y" { if (!string_Equal((yyvsp[(3) - (9)].string),"SPASS")) dfg_IGNORE = (BOOL)stack_PopResult(); string_StringFree((yyvsp[(3) - (9)].string)); ;} break; case 207: #line 919 "dfgparser.y" { if (!dfg_IGNORE && (yyvsp[(4) - (15)].string)!=NULL && (yyvsp[(6) - (15)].term)!=NULL && !list_Empty((yyvsp[(11) - (15)].list))) { LIST tupel; RULE Rule = clause_GetOriginFromString((yyvsp[(8) - (15)].string)); string_StringFree((yyvsp[(8) - (15)].string)); /* Build a tuple (label,clause,parentlist,split level,origin) */ tupel = list_Cons((POINTER)(yyvsp[(13) - (15)].number),list_List((POINTER)Rule)); tupel = list_Cons((yyvsp[(4) - (15)].string),list_Cons((yyvsp[(6) - (15)].term),list_Cons((yyvsp[(11) - (15)].list),tupel))); dfg_PROOFLIST = list_Cons(tupel, dfg_PROOFLIST); } else { /* ignore DNF clauses and clauses with incomplete data */ if ((yyvsp[(4) - (15)].string) != NULL) string_StringFree((yyvsp[(4) - (15)].string)); if ((yyvsp[(6) - (15)].term) != NULL) term_Delete((yyvsp[(6) - (15)].term)); if ((yyvsp[(8) - (15)].string) != NULL) string_StringFree((yyvsp[(8) - (15)].string)); dfg_DeleteStringList((yyvsp[(11) - (15)].list)); } dfg_VarCheck(); ;} break; case 208: #line 939 "dfgparser.y" { (yyval.list) = (dfg_IGNORE||(yyvsp[(1) - (1)].string)==NULL) ? list_Nil() : list_List((yyvsp[(1) - (1)].string)); ;} break; case 209: #line 941 "dfgparser.y" { (yyval.list) = (dfg_IGNORE||(yyvsp[(3) - (3)].string)==NULL) ? (yyvsp[(1) - (3)].list) : list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].string))); ;} break; case 210: #line 945 "dfgparser.y" { (yyval.number) = 0; ;} break; case 211: #line 946 "dfgparser.y" { (yyval.number) = (yyvsp[(3) - (4)].number); ;} break; case 212: #line 950 "dfgparser.y" { if (!dfg_IGNORE && (yyvsp[(1) - (3)].string)!=NULL && (yyvsp[(3) - (3)].string)!=NULL && string_Equal((yyvsp[(1) - (3)].string),"splitlevel")) string_StringToInt((yyvsp[(3) - (3)].string), TRUE, &(yyval.number)); else (yyval.number) = 0; if ((yyvsp[(1) - (3)].string) != NULL) string_StringFree((yyvsp[(1) - (3)].string)); if ((yyvsp[(3) - (3)].string) != NULL) string_StringFree((yyvsp[(3) - (3)].string)); ;} break; case 213: #line 958 "dfgparser.y" { if (!dfg_IGNORE && (yyvsp[(3) - (5)].string)!=NULL && (yyvsp[(5) - (5)].string)!=NULL && string_Equal((yyvsp[(3) - (5)].string),"splitlevel")) string_StringToInt((yyvsp[(5) - (5)].string), TRUE, &(yyval.number)); else (yyval.number) = (yyvsp[(1) - (5)].number); if ((yyvsp[(3) - (5)].string) != NULL) string_StringFree((yyvsp[(3) - (5)].string)); if ((yyvsp[(5) - (5)].string) != NULL) string_StringFree((yyvsp[(5) - (5)].string)); ;} break; case 214: #line 968 "dfgparser.y" { stack_Push((POINTER) dfg_IGNORE); dfg_IGNORE = TRUE; ;} break; case 215: #line 970 "dfgparser.y" { dfg_IGNORE = (BOOL) stack_PopResult(); if ((yyvsp[(3) - (3)].bool)) { if ((yyvsp[(1) - (3)].string) != NULL) string_StringFree((yyvsp[(1) - (3)].string)); (yyval.string) = NULL; } else (yyval.string) = (yyvsp[(1) - (3)].string); ;} break; case 216: #line 979 "dfgparser.y" { (yyval.string) = (yyvsp[(1) - (1)].string); ;} break; case 217: #line 980 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 218: #line 981 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 219: #line 982 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 220: #line 983 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 221: #line 984 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 222: #line 985 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 223: #line 986 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 224: #line 987 "dfgparser.y" { (yyval.string) = NULL; ;} break; case 225: #line 990 "dfgparser.y" { (yyval.bool) = FALSE; ;} break; case 226: #line 991 "dfgparser.y" { (yyval.bool) = TRUE; ;} break; case 227: #line 992 "dfgparser.y" { (yyval.bool) = TRUE; ;} break; case 228: #line 995 "dfgparser.y" { (yyval.term) = (yyvsp[(1) - (1)].term); ;} break; case 229: #line 996 "dfgparser.y" { (yyval.term) = NULL; ;} break; case 232: #line 1008 "dfgparser.y" { dfg_VarStart(); ;} break; case 233: #line 1009 "dfgparser.y" { dfg_VarStop(); dfg_VarBacktrack(); dfg_VarCheck(); ;} break; case 235: #line 1016 "dfgparser.y" { dfg_TERMLIST = list_Nconc(dfg_TERMLIST, list_List((yyvsp[(2) - (3)].term))); ;} break; case 238: #line 1027 "dfgparser.y" { dfg_INCLUDELIST = list_Nconc(dfg_INCLUDELIST,(yyvsp[(3) - (5)].list)); ;} break; case 239: #line 1030 "dfgparser.y" { (yyval.list) = list_Nil(); ;} break; case 240: #line 1031 "dfgparser.y" { (yyval.list) = list_Cons((yyvsp[(2) - (2)].list),(yyvsp[(1) - (2)].list)); ;} break; case 241: #line 1034 "dfgparser.y" { (yyval.list) = list_PairCreate((yyvsp[(3) - (6)].string),(yyvsp[(4) - (6)].list)); ;} break; case 242: #line 1037 "dfgparser.y" { (yyval.list) = (yyvsp[(3) - (4)].list); ;} break; case 243: #line 1038 "dfgparser.y" { (yyval.list) = list_Nil(); ;} break; case 244: #line 1041 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].string)); ;} break; case 245: #line 1042 "dfgparser.y" { (yyval.list) = list_Cons((yyvsp[(1) - (3)].string),(yyvsp[(3) - (3)].list)); ;} break; case 246: #line 1047 "dfgparser.y" { (yyval.string) = dfg_StripQuotes((yyvsp[(1) - (1)].string)); ;} break; case 248: #line 1055 "dfgparser.y" { if (dfg_IGNORESETTINGS) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Settings not allowed in included files\n"); misc_FinishUserErrorReport(); } ;} break; case 250: #line 1065 "dfgparser.y" { if (string_Equal((yyvsp[(3) - (3)].string),"SPASS")) dfg_IGNORETEXT = FALSE; string_StringFree((yyvsp[(3) - (3)].string)); ;} break; case 251: #line 1070 "dfgparser.y" { dfg_IGNORETEXT = TRUE; ;} break; case 252: #line 1073 "dfgparser.y" { /* no SPASS flags */ string_StringFree((yyvsp[(1) - (1)].string)); ;} break; case 259: #line 1087 "dfgparser.y" { SYMBOL s; for ( ; !list_Empty((yyvsp[(3) - (4)].list)); (yyvsp[(3) - (4)].list) = list_Pop((yyvsp[(3) - (4)].list))) { s = symbol_Lookup(list_Car((yyvsp[(3) - (4)].list))); if (s == 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Undefined symbol %s", list_Car((yyvsp[(3) - (4)].list))); misc_UserErrorReport(" in DomPred list.\n"); misc_FinishUserErrorReport(); } if (!symbol_IsPredicate(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Symbol %s isn't a predicate", list_Car((yyvsp[(3) - (4)].list))); misc_UserErrorReport(" in DomPred list.\n"); misc_FinishUserErrorReport(); } string_StringFree(list_Car((yyvsp[(3) - (4)].list))); symbol_AddProperty(s, DOMPRED); } ;} break; case 260: #line 1107 "dfgparser.y" { int flag = flag_Id((yyvsp[(3) - (6)].string)); if (flag == -1) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Found unknown flag %s", (yyvsp[(3) - (6)].string)); misc_FinishUserErrorReport(); } string_StringFree((yyvsp[(3) - (6)].string)); flag_SetFlagIntValue(dfg_FLAGS, flag, (yyvsp[(5) - (6)].number)); ;} break; case 263: #line 1123 "dfgparser.y" { SYMBOL s = symbol_Lookup((yyvsp[(1) - (1)].string)); if (s == 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Undefined symbol %s ", (yyvsp[(1) - (1)].string)); misc_UserErrorReport(" in precedence list.\n"); misc_FinishUserErrorReport(); } string_StringFree((yyvsp[(1) - (1)].string)); symbol_SetIncreasedOrdering(dfg_PRECEDENCE, s); dfg_USERPRECEDENCE = list_Cons((POINTER)s, dfg_USERPRECEDENCE); ;} break; case 264: #line 1135 "dfgparser.y" { SYMBOL s = symbol_Lookup((yyvsp[(2) - (6)].string)); if (s == 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Undefined symbol %s", (yyvsp[(2) - (6)].string)); misc_UserErrorReport("in precedence list.\n"); misc_FinishUserErrorReport(); } string_StringFree((yyvsp[(2) - (6)].string)); symbol_SetIncreasedOrdering(dfg_PRECEDENCE, s); dfg_USERPRECEDENCE = list_Cons((POINTER)s, dfg_USERPRECEDENCE); symbol_SetWeight(s, (yyvsp[(4) - (6)].number)); if ((yyvsp[(5) - (6)].property) != 0) symbol_AddProperty(s, (yyvsp[(5) - (6)].property)); ;} break; case 267: #line 1156 "dfgparser.y" { dfg_CLAXRELATION = list_Cons(list_Cons((POINTER)(yyvsp[(2) - (5)].number), dfg_CLAXAXIOMS), dfg_CLAXRELATION); dfg_CLAXAXIOMS = list_Nil(); ;} break; case 270: #line 1167 "dfgparser.y" { dfg_CLAXAXIOMS = list_Cons((POINTER)(yyvsp[(1) - (1)].string), dfg_CLAXAXIOMS); ;} break; case 273: #line 1177 "dfgparser.y" { SYMBOL s = symbol_Lookup((yyvsp[(1) - (1)].string)); if (s == 0) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Undefined symbol %s ", (yyvsp[(1) - (1)].string)); misc_UserErrorReport(" in selection list.\n"); misc_FinishUserErrorReport(); } if (!symbol_IsPredicate(s)) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Symbol %s isn't a predicate", (yyvsp[(1) - (1)].string)); misc_UserErrorReport(" in selection list.\n"); misc_FinishUserErrorReport(); } string_StringFree((yyvsp[(1) - (1)].string)); dfg_USERSELECTION = list_Cons((POINTER)s, dfg_USERSELECTION); ;} break; case 274: #line 1195 "dfgparser.y" { (yyval.property) = 0; /* left */ ;} break; case 275: #line 1197 "dfgparser.y" { if ((yyvsp[(2) - (2)].string)[1] != '\0' || ((yyvsp[(2) - (2)].string)[0]!='l' && (yyvsp[(2) - (2)].string)[0]!='m' && (yyvsp[(2) - (2)].string)[0]!='r')) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Invalid symbol status %s", (yyvsp[(2) - (2)].string)); misc_UserErrorReport(" in precedence list."); misc_FinishUserErrorReport(); } switch ((yyvsp[(2) - (2)].string)[0]) { case 'm': (yyval.property) = ORDMUL; break; case 'r': (yyval.property) = ORDRIGHT; break; default: (yyval.property) = 0; } string_StringFree((yyvsp[(2) - (2)].string)); ;} break; case 278: #line 1218 "dfgparser.y" { dfg_DeleteStringList((yyvsp[(3) - (5)].list)); ;} break; case 279: #line 1221 "dfgparser.y" { (yyval.list) = list_List((yyvsp[(1) - (1)].string)); ;} break; case 280: #line 1222 "dfgparser.y" { (yyval.list) = list_Nconc((yyvsp[(1) - (3)].list), list_List((yyvsp[(3) - (3)].string))); ;} break; /* Line 1267 of yacc.c. */ #line 3602 "dfgparser.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } #line 1225 "dfgparser.y" void yyerror(const char *s) { misc_StartUserErrorReport(); misc_UserErrorReport("\n Line %i: %s\n", dfg_LINENUMBER, s); misc_FinishUserErrorReport(); } static void dfg_Init(FILE* Input, FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description) /************************************************************** INPUT: The input file stream for the parser, a flag store, a precedence and a problem description store. RETURNS: Nothing. EFFECT: The parser and scanner are initialized. The parser will use the flag store and the precedence to memorize the settings from the input file. ***************************************************************/ { extern FILE* dfg_in; /* declared in dfgscanner */ dfg_in = Input; dfg_LINENUMBER = 1; dfg_IGNORETEXT = TRUE; dfg_AXIOMLIST = list_Nil(); dfg_CONJECLIST = list_Nil(); dfg_INCLUDELIST = list_Nil(); dfg_SORTDECLLIST = list_Nil(); dfg_USERPRECEDENCE = list_Nil(); dfg_USERSELECTION = list_Nil(); dfg_CLAXRELATION = list_Nil(); dfg_CLAXAXIOMS = list_Nil(); dfg_AXCLAUSES = list_Nil(); dfg_CONCLAUSES = list_Nil(); dfg_PROOFLIST = list_Nil(); dfg_TERMLIST = list_Nil(); dfg_SYMBOLLIST = list_Nil(); dfg_VARLIST = list_Nil(); dfg_PLAINAXCLAUSES = list_Nil(); dfg_PLAINCONCLAUSES = list_Nil(); dfg_TEMPPLAINCLAUSES = list_Nil(); dfg_SELECTED_LITERAL = (TERM) NULL; dfg_VARDECL = FALSE; dfg_IGNORE = FALSE; dfg_FLAGS = Flags; dfg_PRECEDENCE = Precedence; dfg_DESC = Description; } void dfg_DeleteClAxRelation(LIST ClAxRelation) { LIST Scan1, Scan2; for (Scan1=ClAxRelation;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { for (Scan2=list_Cdr(list_Car(Scan1));!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) string_StringFree((char *)list_Car(Scan2)); list_Delete(list_Car(Scan1)); } list_Delete(ClAxRelation); } FILE* dfg_OpenFile(const char * FileName, char ** const DiscoveredName) /************************************************************** INPUT: A string filename, and a pointer to char pointer to hold the fullpath name of the file that was opened in the end (can be null). RETURNS: A opened file. EFFECT: Opens a file for reading. The file is searched for using the extended search mechanism wrt SPASSINPUT environment variable. ***************************************************************/ { return misc_OpenFileEnv(FileName,"r","SPASSINPUT",DiscoveredName); } static LIST dfg_TestList; /* list of strings used in nonmember tests */ static BOOL dfg_LabelFormulaPairIsNonmember(POINTER pair) { if (list_PairFirst(pair) == NULL) return TRUE; return !list_Member(dfg_TestList,list_PairFirst(pair),(BOOL (*)(POINTER, POINTER))string_Equal); } static void dfg_DeleteLabelTermPair(POINTER pair) { term_Delete(list_PairSecond(pair)); if (list_PairFirst(pair) != NULL) string_StringFree(list_PairFirst(pair)); /* Free the label */ list_PairFree(pair); } void dfg_FilterClausesBySelection(LIST* Clauses, LIST* ClAxRelation, LIST selection) /************************************************************** INPUT: A pointer to a clause list, a pointer to a ClAxRelation list and a char* list. RETURNS: Nothing. EFFECT: The clause list is filtered in such a way that clauses with names not in the selection list are deleted. The name for the clauses is found in the ClAxRelation structure. And the corresponding entry in ClAxRelation is also deleted if the clause is. The clause list and the ClAxRelation list are assumed to be coherent. NOTE: The coherence is assured when the lists come from an included file, because in includes settings sections are forbidden and so the user cannot specify ClAxRelation herself. ***************************************************************/ { /* result lists */ LIST RClauses; LIST RClAxRelation; /* pointers to last element in the result */ LIST RLClauses = list_Nil(); LIST RLClAxRelation = list_Nil(); RClauses = list_Nil(); RClAxRelation = list_Nil(); /* Performs parallel tranversal of Clauses and ClAxRelation. Either deleting from both or keeping both for the result. */ while (!list_Empty(*Clauses)) { CLAUSE Clause; LIST ClAx; LIST Labels; char* Label; /* current list elements */ LIST CClause; LIST CClAxRelation; CClause = *Clauses; CClAxRelation = *ClAxRelation; Clause = (CLAUSE) list_Car(CClause); #ifdef CHECK if (list_Empty(CClAxRelation)) { misc_StartUserErrorReport(); misc_ErrorReport("\n In dfg_FilterClausesBySelection: ClAxRelation too short!\n"); misc_FinishUserErrorReport(); } #endif ClAx = (LIST) list_Car(CClAxRelation); #ifdef CHECK if ((int)list_Car(ClAx) != clause_Number(Clause)) { misc_StartUserErrorReport(); misc_ErrorReport("\n In dfg_FilterClausesBySelection: Incompatible ClAxRelation!\n"); misc_FinishUserErrorReport(); } #endif Labels = list_Cdr(ClAx); if (list_Empty(Labels)) Label = NULL; else Label = (char*)list_Car(Labels); /*and we can already move on*/ *Clauses = list_Cdr(*Clauses); *ClAxRelation = list_Cdr(*ClAxRelation); if (!Label || !list_Member(selection,Label,(BOOL (*)(POINTER, POINTER))string_Equal)) { /* deleting */ if (RClauses) { /*if RClauses exists so does RLClauses and RLClAxRelation*/ list_Rplacd(RLClauses,*Clauses); list_Rplacd(RLClAxRelation,*ClAxRelation); } clause_Delete(Clause); list_DeleteWithElement(Labels,(void (*)(POINTER))string_StringFree); list_Free(ClAx); list_Free(CClause); list_Free(CClAxRelation); } else { /* keeping */ if (!RClauses) { /* the result will contain at least one element */ RClauses = CClause; RClAxRelation = CClAxRelation; } /* if we delete the next, whis will need to be updated */ RLClauses = CClause; RLClAxRelation = CClAxRelation; } } *Clauses = RClauses; *ClAxRelation = RClAxRelation; } LIST dfg_DFGParser(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description, LIST* Axioms, LIST* Conjectures, LIST* SortDecl, LIST* UserDefinedPrecedence, LIST* UserDefinedSelection, LIST* ClAxRelation, BOOL* HasPlainClauses) /************************************************************** A stub around the real parser that takes care of following include directives. NOTE: This function is almost the same as tptp_TPTPParser form tptpparser.y any change in its implementation should propably be also propagated there. ***************************************************************/ { LIST Includes, Clauses; LIST FilesRead; DFGDESCRIPTION description_dummy; FilesRead = list_Nil(); Includes = list_Nil(); dfg_IGNORESETTINGS = FALSE; Clauses = dfg_DFGParserIncludesExplicit(File,Flags,Precedence,Description,FALSE,Axioms,Conjectures,SortDecl,UserDefinedPrecedence,UserDefinedSelection,ClAxRelation,&Includes,HasPlainClauses); while (list_Exist(Includes)) { LIST pair; char* filename; LIST selection; pair = list_Top(Includes); filename = (char*)list_PairFirst(pair); selection = (LIST)list_PairSecond(pair); list_PairFree(pair); Includes = list_Pop(Includes); if (list_Member(FilesRead,filename,(BOOL (*)(POINTER, POINTER))string_Equal)) { misc_UserWarning("File %s already included, skipped!\n",filename); string_StringFree(filename); } else { LIST Axs, Conjs, Cls, UDS, CAR; BOOL HPC; FILE* FileToInclude; FileToInclude = dfg_OpenFile(filename, NULL); Axs = Conjs = UDS = CAR = list_Nil(); dfg_IGNORESETTINGS = TRUE; description_dummy = desc_Create(); Cls = dfg_DFGParserIncludesExplicit(FileToInclude, Flags, Precedence, description_dummy, TRUE, &Axs, &Conjs, SortDecl, UserDefinedPrecedence, &UDS, &CAR, &Includes, &HPC); desc_Delete(description_dummy); if (list_Exist(selection)) { /*use the selection to filter Axs and Conjs */ dfg_FilterClausesBySelection(&Cls,&CAR,selection); dfg_TestList = selection; Axs = list_DeleteElementIfFree(Axs,dfg_LabelFormulaPairIsNonmember,dfg_DeleteLabelTermPair); Conjs = list_DeleteElementIfFree(Conjs,dfg_LabelFormulaPairIsNonmember,dfg_DeleteLabelTermPair); } Clauses = list_Nconc(Clauses, Cls); *Axioms = list_Nconc(*Axioms,Axs); *Conjectures = list_Nconc(*Conjectures,Conjs); /* "Summing up" UserDefinedSelection and ClAxRelation from all the files included. */ *UserDefinedSelection = list_Nconc(*UserDefinedSelection, UDS); /* No explicit (user specified) ClAxRelation coming in dfg from includes! *ClAxRelation = list_Nconc(*ClAxRelation, CAR); */ dfg_DeleteClAxRelation(CAR); /*The whole thing has plain clauses only if all the files have!*/ if (!HPC) *HasPlainClauses = FALSE; misc_CloseFile(FileToInclude,filename); FilesRead = list_Cons(filename,FilesRead); } list_DeleteWithElement(selection,(void (*)(POINTER))string_StringFree); } list_DeleteWithElement(FilesRead,(void (*)(POINTER))string_StringFree); return Clauses; } void dfg_InitExplicitParser() /************************************************************** This function should be called prior to calling dfg_DFGParserIncludesExplicit from outside the dfg module. ***************************************************************/ { dfg_IGNORESETTINGS = FALSE; } void dfg_CreateClausesFromTerms(LIST* Axioms, LIST* Conjectures, LIST* ClAxRelation, BOOL BuildClAx, FLAGSTORE Flags, PRECEDENCE Precedence) /************************************************************** INPUT: Pointers to two lists of term-label pairs, pointer to ClAx list, boolean flag and a flag store and a precedence. EFFECT: Applies dfg_CreateClauseFromTerm to the pairs in the lists treating the firsts as axioms and second as conjectures, releasing the pair struct and the labels. If BuildClAx is set the labels are not deleted, but instead used to record the relation between the clauses and their original names in the ClAxRelation structure (otherwise ClAxRelation remains intact). ***************************************************************/ { LIST scan, tupel; TERM clauseTerm; CLAUSE clause; LIST ClAxContribution, labels; ClAxContribution = list_Nil(); /* Remove clause labels and create clauses from the terms */ for (scan = *Axioms; !list_Empty(scan); scan = list_Cdr(scan)) { tupel = list_Car(scan); clauseTerm = list_PairSecond(tupel); clause = dfg_CreateClauseFromTerm(clauseTerm,TRUE, Flags, Precedence); list_Rplaca(scan, clause); if (BuildClAx) { if (list_PairFirst(tupel) != NULL) labels = list_List(list_PairFirst(tupel)); else labels = list_Nil(); ClAxContribution = list_Cons(list_Cons((POINTER)clause_Number(clause),labels),ClAxContribution); } else { if (list_PairFirst(tupel) != NULL) /* Label is defined */ string_StringFree(list_PairFirst(tupel)); /* Delete the label */ } list_PairFree(tupel); } /* Since dfg_CreateClauseFromTerm() returns NULL for trivial tautologies */ /* we now delete those NULL pointers from the clause list. */ *Axioms = list_PointerDeleteElement(*Axioms, NULL); for (scan = *Conjectures; !list_Empty(scan); scan = list_Cdr(scan)) { tupel = list_Car(scan); clauseTerm = list_PairSecond(tupel); clause = dfg_CreateClauseFromTerm(clauseTerm,FALSE, Flags, Precedence); list_Rplaca(scan, clause); if (BuildClAx) { if (list_PairFirst(tupel) != NULL) labels = list_List(list_PairFirst(tupel)); else labels = list_Nil(); ClAxContribution = list_Cons(list_Cons((POINTER)clause_Number(clause),labels),ClAxContribution); } else { if (list_PairFirst(tupel) != NULL) /* Label is defined */ string_StringFree(list_PairFirst(tupel)); /* Delete the label */ } list_PairFree(tupel); } /* Since dfg_CreateClauseFromTerm() returns NULL for trivial tautologies */ /* we now delete those NULL pointers from the clause list. */ *Conjectures = list_PointerDeleteElement(*Conjectures, NULL); if (BuildClAx) { /* appending the contribution to the end! */ *ClAxRelation = list_Nconc(*ClAxRelation,list_NReverse(ClAxContribution)); } } LIST dfg_DFGParserIncludesExplicit(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence, DFGDESCRIPTION Description, BOOL AppendImplicitClAx, LIST* Axioms, LIST* Conjectures, LIST* SortDecl, LIST* UserDefinedPrecedence, LIST* UserDefinedSelection, LIST* ClAxRelation, LIST* Includes, BOOL* HasPlainClauses) /************************************************************** INPUT: The input file containing clauses or formulae in DFG syntax, a flag store, a precedence used to memorize settings from the file, and Description to store problem description. Boolean flag determinig whether the implicit ClAxRelation from Clauses should be appended to the explicit one coming from settings. Axioms, Conjectures, SortDecl, UserDefinedPrecedence UserDefinedSelection, and ClAxRelation, and Includes are pointers to lists used as return values. HasPlainClauses is a return value to indicate if the problem had clauses in the plain format. RETURNS: The list of clauses from File. EFFECT: Reads formulae and clauses from the input file. The axioms, conjectures, sort declarations, user-defined precedences, and includes are appended to the respective lists, the lists are not deleted! The Includes list contains pairs (filename, selection), where selection is a list of names of formulas chosen to include. All lists except the returned clause list contain pairs (label, term), where