--- /dev/null
+PACKAGE=cost-plug-in
+VERSION=0.1
+PACKAGE_RES=$(PACKAGE)-$(VERSION).tgz
+
+JESSIE=frama-c_jessie
+
+all:
+ make -C plugin
+ make -C wrapper
+
+install:
+ mkdir -p /usr/local/bin
+ cp $(JESSIE) /usr/local/bin
+ make -C plugin install
+ make -C wrapper install
+
+clean:
+ rm -fr $(PACKAGE) $(PACKAGE_RES) doc
+ make -C plugin clean
+ make -C wrapper clean
+
+distclean: clean
+ make -C plugin distclean
+ make -C wrapper distclean
+
+dist:
+ rm -fr $(PACKAGE) $(PACKAGE_RES)
+ mkdir $(PACKAGE)
+ for i in `cat distributed_files` doc/html/*.html; do \
+ if test -f $$i; then \
+ cp -fr --parents $$i $(PACKAGE); \
+ else \
+ mkdir -p $$i; \
+ fi; \
+ done
+ tar cvfz $(PACKAGE_RES) $(PACKAGE)
+
+.PHONY = install clean distclean dist
--- /dev/null
+PACKAGE=cost-plug-in
+VERSION=0.1
+PACKAGE_RES=$(PACKAGE)-$(VERSION).tgz
+
+JESSIE=frama-c_jessie
+
+all:
+ make -C plugin
+ make -C wrapper
+
+install:
+ mkdir -p @prefix@/bin
+ cp $(JESSIE) @prefix@/bin
+ make -C plugin install
+ make -C wrapper install
+
+clean:
+ rm -fr $(PACKAGE) $(PACKAGE_RES) doc
+ make -C plugin clean
+ make -C wrapper clean
+
+distclean: clean
+ make -C plugin distclean
+ make -C wrapper distclean
+
+dist:
+ rm -fr $(PACKAGE) $(PACKAGE_RES)
+ mkdir $(PACKAGE)
+ for i in `cat distributed_files` doc/html/*.html; do \
+ if test -f $$i; then \
+ cp -fr --parents $$i $(PACKAGE); \
+ else \
+ mkdir -p $$i; \
+ fi; \
+ done
+ tar cvfz $(PACKAGE_RES) $(PACKAGE)
+
+.PHONY = install clean distclean dist
--- /dev/null
+Presentation
+--------------
+
+This is a Frama-C plug-in and a wrapper for Lustre that makes the synthesis of
+the results of the CerCo compiler.
+
+ Requirements
+--------------
+
+ - Frama-C Nitrogen
+ - Ocaml >= 3.12
+ - CerCo
+ - Lustre compiler (for Lustre files only)
+ - Jessie plug-in and simplify (for verification only)
+
+ Compilation
+-------------
+
+ You can compile the plug-in and the wrapper using the following command:
+
+ % make
+
+ (assuming that you are located at the root of the source tree)
+
+ Installation
+--------------
+
+ You can install the plug-in and the wrapper using the following command:
+
+ % make install
+
+ You may need administrative rights.
+
+Note: both the plug-in and the wrapper can be installed seperately. See their
+README in their respective source folders ("plugin" for the plug-in and
+"wrapper" for the Lustre wrapper). Also note that the wrapper uses the plug-in.
+
+ Usage
+-------
+
+ - Plug-in:
+
+ You can run the plug-in on a C file "file.c" using the following command:
+
+ % frama-c -cost file.c
+
+ The result will be in file "file-annotated.c" in the same directory if the
+ name is fresh. Otherwise an integer suffix will be added to the base name of
+ the output file.
+
+ For a complete description of the options, use the command:
+
+ % frama-c -cost-help
+
+ - Lustre wrapper:
+
+ You can run the wrapper for Lustre on a node "node" of a Lustre file
+ "file.lus" using the following command:
+
+ % frama-c_lustre file.lus node
+
+ The result will be in file "file-annotated.c" in the same directory if the
+ name is fresh. Otherwise an integer suffix will be added to the base name of
+ the output file.
+
+ For a complete description of the options, use the command:
+
+ % frama-c_lustre -help
+
+ - Jessie script
+
+ For verification through a graphical user interface, a script that calls the
+ Jessie plug-in of Frama-C with specific options is also provided. It can be
+ ran using the following command on an annotated C file (obtained with the
+ Cost plug-in for instance):
+
+ % frama-c_jessie annotated-file.c
+
+ Note: the script calls Jessie with generation of safety conditions
+ disabled, i.e. proof obligations regarding interger overflow, pointer
+ dereferencing, preconditions, loop variants, etc, will *not* be
+ generated. Thus, verification with frama-c_jessie is only correct modulo
+ safety. If you wish to turn on the generation of safety conditions you can
+ use Jessie in its simplest form:
+
+ % frama-c -jessie annotated-file.c
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="configure.ac"
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+FRAMAC
+ACC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+for ac_prog in acc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ACC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ACC"; then
+ ac_cv_prog_ACC="$ACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ACC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ACC=$ac_cv_prog_ACC
+if test -n "$ACC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ACC" >&5
+$as_echo "$ACC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ACC" && break
+done
+
+
+
+for ac_prog in frama-c
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_FRAMAC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$FRAMAC"; then
+ ac_cv_prog_FRAMAC="$FRAMAC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FRAMAC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FRAMAC=$ac_cv_prog_FRAMAC
+if test -n "$FRAMAC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FRAMAC" >&5
+$as_echo "$FRAMAC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$FRAMAC" && break
+done
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+ac_config_files="$ac_config_files frama-c_jessie"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "frama-c_jessie") CONFIG_FILES="$CONFIG_FILES frama-c_jessie" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+ac_config_files="$ac_config_files wrapper/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "frama-c_jessie") CONFIG_FILES="$CONFIG_FILES frama-c_jessie" ;;
+ "wrapper/Makefile") CONFIG_FILES="$CONFIG_FILES wrapper/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
--- /dev/null
+#
+# Autoconf
+#
+AC_INIT(configure.ac)
+
+AC_CHECK_PROGS([ACC],[acc])
+AC_SUBST(ACC)
+
+AC_CHECK_PROGS([FRAMAC],[frama-c])
+AC_SUBST(FRAMAC)
+
+AC_OUTPUT(Makefile)
+AC_OUTPUT(frama-c_jessie)
+AC_OUTPUT(wrapper/Makefile)
+
--- /dev/null
+#!/bin/env sh
+
+ERROR="usage: $(basename $0) file.c\n"
+
+if [ $# -eq 0 ] ; then
+ echo -e $ERROR
+else
+ @FRAMAC@ -jessie -jessie-behavior default -jessie-why-opt="-fast-wp" $1
+fi
--- /dev/null
+##########################################################################
+# #
+# This file is part of Frama-C. #
+# #
+# Copyright (C) 2007-2011 #
+# CEA (Commissariat � l'�nergie atomique et aux �nergies #
+# alternatives) #
+# #
+# you can redistribute it and/or modify it under the terms of the GNU #
+# Lesser General Public License as published by the Free Software #
+# Foundation, version 2.1. #
+# #
+# It 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 Lesser General Public License for more details. #
+# #
+# See the GNU Lesser General Public License version 2.1 #
+# for more details (enclosed in the file licenses/LGPLv2.1). #
+# #
+##########################################################################
+
+# Generic Makefile for bytecode plugins
+
+FRAMAC_SHARE := $(shell frama-c.byte -print-path)
+FRAMAC_LIBDIR := $(shell frama-c.byte -print-libpath)
+
+PLUGIN_NAME = Cost_synthesis
+PLUGIN_CMO = eset emap completeMap multiset misc arithSig arith \
+ cost_value compute parameters simplify_terms normAtLabels \
+ compute_simple compute_simple_stack_size cerco cost
+
+# PLUGIN_HAS_MLI := yes
+
+# include Makefile.plugin
+include $(FRAMAC_SHARE)/Makefile.dynamic
+
+distclean: clean
+
+.PHONY = distclean
\ No newline at end of file
--- /dev/null
+Presentation
+--------------
+
+This is a Frama-C plug-in that makes the synthesis of the results of the CerCo
+compiler.
+
+ Requirements
+--------------
+
+ - Frama-C Nitrogen
+ - Ocaml >= 3.12
+ - CerCo
+
+ Compilation
+-------------
+
+ You can compile the plug-in using the following command:
+
+ % make
+
+ (assuming that you are located at the root of the source tree)
+
+ Installation
+--------------
+
+ You can install the plug-in using the following command:
+
+ % make install
+
+ You may need administrative rights.
+
+ Usage
+-------
+
+ You can run the plug-in on a C file "file.c" using the following command:
+
+ % frama-c -cost file.c
+
+ The result will be in file "file-annotated.c" in the same directory if the
+ name is fresh. Otherwise an integer suffix will be added to the base name of
+ the output file.
+
+ For a complete description of the options, use the command:
+
+ % frama-c -cost-help
--- /dev/null
+
+(** This module provides functions to manipulate parameterized arithmetic
+ expressions (see the ArithSig module) when instanciaded on a specific
+ type. *)
+
+
+module Make (S : ArithSig.S) = struct
+
+ include ArithSig.P
+
+ let compare = compare S.compare
+
+ type t = S.t tt
+
+ let fill_subs v subs = ArithSig.fill_subs v subs
+
+ let subs v = ArithSig.subs v
+
+ let fold f v = ArithSig.fold f v
+
+
+ let f_to_string v subs_res = match v, subs_res with
+ | A a, _ -> "(A " ^ (S.to_string a) ^ ")"
+ | Int i, _ -> string_of_int i
+ | Var x, _ -> x
+ | UnOp (unop, _), v :: _ -> (string_of_unop unop) ^ "(" ^ v ^ ")"
+ | BinOp (binop, _, _), v1 :: v2 :: _ ->
+ "(" ^ v1 ^ ")" ^ (string_of_binop binop) ^ "(" ^ v2 ^ ")"
+ | Cond (_, rel, _, _, _), t1 :: t2 :: tif :: telse :: _ ->
+ Printf.sprintf "(%s %s %s)? (%s) : (%s)"
+ t1 (string_of_relation rel) t2 tif telse
+ | UnOp _, _ | BinOp _, _ | Cond _, _ ->
+ assert false (* wrong number of arguments *)
+
+ let to_string v = fold f_to_string v
+
+
+ let is_supported_rel = function
+ | Cil_types.Lt | Cil_types.Gt | Cil_types.Le | Cil_types.Ge -> true
+ | _ -> false
+
+ let rel_of_cil_binop = function
+ | Cil_types.Lt -> Lt
+ | Cil_types.Gt -> Gt
+ | Cil_types.Le -> Le
+ | Cil_types.Ge -> Ge
+ | _ -> raise (Failure "Arith.rel_of_cil_binop")
+
+
+ let cil_binop_of_rel = function
+ | Lt -> Cil_types.Lt
+ | Gt -> Cil_types.Gt
+ | Le -> Cil_types.Le
+ | Ge -> Cil_types.Ge
+
+ let cil_unop_of_unop = function
+ | Neg -> Cil_types.Neg
+
+ let cil_binop_of_binop = function
+ | Add -> Cil_types.PlusA
+ | Sub -> Cil_types.MinusA
+ | Mul -> Cil_types.Mult
+ | Div -> Cil_types.Div
+ | Mod -> Cil_types.Mod
+ (* No direct translation. Handle this case in the calling function. *)
+ | Max -> assert false
+
+
+ let integer_term term = Logic_const.term term Cil_types.Linteger
+
+ let tinteger i =
+ let cint64 = Cil_types.CInt64 (My_bigint.of_int i, Cil_types.IInt, None) in
+ let iterm = Cil_types.TConst cint64 in
+ integer_term iterm
+
+ let f_to_cil_term v subs_res = match v, subs_res with
+ | A a, _ -> S.to_cil_term a
+ | Int i, _ -> tinteger i
+ | Var x, _ ->
+ Logic_const.tvar (Cil_const.make_logic_var x Cil_types.Linteger)
+ | UnOp (unop, _), t :: _ ->
+ integer_term (Cil_types.TUnOp (cil_unop_of_unop unop, t))
+ | BinOp (Max, _, _), t1 :: t2 :: _ ->
+ let test = integer_term (Cil_types.TBinOp (Cil_types.Ge, t1, t2)) in
+ integer_term (Cil_types.Tif (test, t1, t2))
+ | BinOp (binop, _, _), t1 :: t2 :: _ ->
+ integer_term (Cil_types.TBinOp (cil_binop_of_binop binop, t1, t2))
+ | Cond (_, rel, _, _, _), t1 :: t2 :: tif :: telse :: _ ->
+ let test =
+ integer_term (Cil_types.TBinOp (cil_binop_of_rel rel, t1, t2)) in
+ integer_term (Cil_types.Tif (test, tif, telse))
+ | _ -> assert false (* wrong number of arguments *)
+
+ let to_cil_term v = fold f_to_cil_term v
+
+
+ let cil_rel_of_rel = function
+ | Lt -> Cil_types.Rlt
+ | Gt -> Cil_types.Rgt
+ | Le -> Cil_types.Rle
+ | Ge -> Cil_types.Rge
+
+
+ let of_int i = Int i
+ let of_var x = Var x
+
+ let apply_unop unop v = UnOp (unop, v)
+ let apply_binop binop v1 v2 = BinOp (binop, v1, v2)
+
+ let int_op_of_rel = function
+ | Lt -> (<)
+ | Le -> (<=)
+ | Gt -> (>)
+ | Ge -> (>=)
+
+ (* The functions below allows to build arithmetic expressions with their usual
+ operators (add, sub, etc) and with a partial simplification. *)
+
+ let rec neg = function
+ | A a -> S.neg a
+ | Int i -> Int (-i)
+ | UnOp (Neg, v) -> v
+ | BinOp (Add, v1, v2) -> add (neg v1) (neg v2)
+ | BinOp (Sub, v1, v2) -> minus (neg v1) (neg v2)
+ | v -> apply_unop Neg v
+
+ and add v1 v2 = match v1, v2 with
+ | Int i1, Int i2 -> Int (i1 + i2)
+ | Int 0, v | v, Int 0 -> v
+ | BinOp (Add, Int i1, v), Int i2
+ | BinOp (Add, v, Int i1), Int i2
+ | Int i1, BinOp (Add, Int i2, v)
+ | Int i1, BinOp (Add, v, Int i2) -> add (Int (i1 + i2)) v
+ | BinOp (Sub, Int i1, v), Int i2
+ | Int i1, BinOp (Sub, Int i2, v) -> minus (Int (i1 + i2)) v
+ | BinOp (Sub, v, Int i1), Int i2
+ | Int i1, BinOp (Sub, v, Int i2) -> add (Int (i1 - i2)) v
+ | A a, v -> S.addl a v
+ | v, A a -> S.addr v a
+ | _ -> apply_binop Add v1 v2
+
+ and minus v1 v2 = match v1, v2 with
+ | A a, v -> S.minusl a v
+ | v, A a -> S.minusr v a
+ | Int i1, Int i2 -> Int (i1 - i2)
+ | _, Int 0 -> v1
+ | Int 0, _ -> neg v2
+ | _ -> apply_binop Sub v1 v2
+
+ and mul v1 v2 = match v1, v2 with
+ | A a, v -> S.mull a v
+ | v, A a -> S.mulr v a
+ | Int i1, Int i2 -> Int (i1 * i2)
+ | Int 1, v | v, Int 1 -> v
+ | Int 0, _ | _, Int 0 -> Int 0
+ | Int (-1), v | v, Int (-1) -> neg v
+ | _ -> apply_binop Mul v1 v2
+
+ and div v1 v2 = match v1, v2 with
+ | _, Int 0 -> raise (Invalid_argument "Arith.div")
+ | A a, v -> S.divl a v
+ | v, A a -> S.divr v a
+ | Int i1, Int i2 -> Int (i1 / i2)
+ | Int 1, v | v, Int 1 -> v
+ | Int 0, _ -> Int 0
+ | Int (-1), v | v, Int (-1) -> neg v
+ | _ -> apply_binop Div v1 v2
+
+ and modulo v1 v2 = match v1, v2 with
+ | _, Int 0 -> raise (Invalid_argument "Arith.modulo")
+ | A a, v -> S.modl a v
+ | v, A a -> S.modr v a
+ | Int i1, Int i2 -> Int (i1 mod i2)
+ | Int 0, _ | _, Int 1 -> Int 0
+ | _ -> apply_binop Mod v1 v2
+
+ and max v1 v2 = match v1, v2 with
+ | A a, v -> S.maxl a v
+ | v, A a -> S.maxr v a
+ | Int i1, Int i2 -> Int (Pervasives.max i1 i2)
+ | _ -> apply_binop Max v1 v2
+
+ and cond v1 rel v2 v3 v4 = match v1, v2 with
+ | Int i1, Int i2 when (int_op_of_rel rel) i1 i2 -> v3
+ | Int _, Int _ -> v4
+ | _ -> Cond (v1, rel, v2, v3, v4)
+
+ let cmp is_large cmpal cmpar int_cmp v1 v2 = match v1, v2 with
+ | Int i1, Int i2 -> int_cmp i1 i2
+ | A a, v -> cmpal a v
+ | v, A a -> cmpar v a
+ | _ when is_large -> v1 = v2
+ | _ -> false
+
+ let binop_false _ _ = false
+
+ let lt = cmp false S.ltl S.ltr (<)
+ let le = cmp true S.lel S.ler (<=)
+ let gt = cmp false S.gtl S.gtr (>)
+ let ge = cmp true S.gel S.ger (>=)
+
+ let op_of_unop = function
+ | Neg -> neg
+
+ let op_of_binop = function
+ | Add -> add
+ | Sub -> minus
+ | Mul -> mul
+ | Div -> div
+ | Mod -> modulo
+ | Max -> max
+
+ let op_of_relation = function
+ | Lt -> lt
+ | Le -> le
+ | Gt -> gt
+ | Ge -> ge
+
+ let bool_of_cond = op_of_relation
+
+ let f_compute v subs_res = match v, subs_res with
+ | A a, _ -> A (S.compute a)
+ | UnOp (unop, _), v :: _ -> (op_of_unop unop) v
+ | BinOp (binop, _, _), v1 :: v2 :: _ -> (op_of_binop binop) v1 v2
+ | Cond (_, rel, _, _, _), v1 :: v2 :: v3 :: _
+ when (op_of_relation rel) v1 v2 -> v3
+ | Cond (_, rel, _, _, _), v1 :: v2 :: _ :: v4 :: _
+ when (op_of_relation (opposite rel)) v1 v2 -> v4
+ | _ -> fill_subs v subs_res
+
+ (** [compute v] partially simplifies the arithmetic expression [v]. *)
+
+ let compute v = fold f_compute v
+
+ let abs v = cond (Int 0) Le v v (neg v)
+
+ let f_replace_vars replacements v subs_res = match fill_subs v subs_res with
+ | Var x when Misc.String.Map.mem x replacements ->
+ Misc.String.Map.find x replacements
+ | v -> v
+
+ let replace_vars replacements = fold (f_replace_vars replacements)
+
+end
--- /dev/null
+
+(** This module defines parameterized arithmetic expressions, i.e. arithmetic
+ expressions mixed with any other type. For instance, one can define
+ arithmetic expressions with function calls, arithmetic expressions with top
+ and bottom (the abstract interpretation constants), etc. *)
+
+(* Note: the feature 'mixed with any other type' is not used anymore. It would
+ make the code clearer to remove it. *)
+
+
+module P = struct
+
+ type relation = Lt | Gt | Le | Ge
+
+ let is_large = function
+ | Le | Ge -> true
+ | Lt | Gt -> false
+
+ let has_lower_type = function
+ | Lt | Le -> true
+ | Gt | Ge -> false
+
+ let string_of_relation = function
+ | Lt -> "<"
+ | Le -> "<="
+ | Gt -> ">"
+ | Ge -> ">="
+
+ let mk_strict = function
+ | Lt | Le -> Lt
+ | Gt | Ge -> Gt
+
+ let mk_large = function
+ | Lt | Le -> Le
+ | Gt | Ge -> Ge
+
+ let opposite = function
+ | Lt -> Ge
+ | Le -> Gt
+ | Gt -> Le
+ | Ge -> Lt
+
+ type unop = Neg
+
+ type binop = Add | Sub | Div | Mul | Mod | Max
+
+ let string_of_unop = function
+ | Neg -> "-"
+
+ let string_of_binop = function
+ | Add -> "+"
+ | Sub -> "-"
+ | Div -> "/"
+ | Mul -> "*"
+ | Mod -> "%"
+ | Max -> "max"
+
+ type 'a tt =
+ | A of 'a
+ | Int of int
+ | Var of string
+ | UnOp of unop * 'a tt
+ | BinOp of binop * 'a tt * 'a tt
+ | Cond of 'a tt * relation * 'a tt * 'a tt * 'a tt (* ternary expressions *)
+
+ let compare compare_a v1 v2 = match v1, v2 with
+ | A a1, A a2 -> compare_a a1 a2
+ | A _, _ -> -1
+ | _, A _ -> 1
+ | _ -> Pervasives.compare v1 v2
+
+ let rec map f = function
+ | A a -> A (f a)
+ | Int i -> Int i
+ | Var x -> Var x
+ | UnOp (unop, v) -> UnOp (unop, map f v)
+ | BinOp (binop, v1, v2) -> BinOp (binop, map f v1, map f v2)
+ | Cond (v1, rel, v2, v3, v4) ->
+ Cond (map f v1, rel, map f v2, map f v3, map f v4)
+
+ let fill_subs v subs = match v, subs with
+ | A _, _ | Int _, _ | Var _, _ -> v
+ | UnOp (unop, _), v :: _ -> UnOp (unop, v)
+ | BinOp (binop, _, _), v1 :: v2 :: _ -> BinOp (binop, v1, v2)
+ | Cond (_, rel, _, _, _), t1 :: t2 :: tif :: telse :: _ ->
+ Cond (t1, rel, t2, tif, telse)
+ | _ -> raise (Failure "ArithSig.fill_subs") (* wrong number of arguments *)
+
+ let subs = function
+ | A _ | Int _ | Var _ -> []
+ | UnOp (_, v) -> [v]
+ | BinOp (_, v1, v2) -> [v1 ; v2]
+ | Cond (t1, _, t2, tif, telse) -> [t1 ; t2 ; tif ; telse]
+
+ let rec fold f v =
+ let subs_res = List.map (fold f) (subs v) in
+ f v subs_res
+
+ let f_is_independent v subs_res =
+ let b = match v with A _ -> false | _ -> true in
+ List.fold_left (&&) true (b :: subs_res)
+
+ (** [is_independent v] returns true if and only if the arithmetic expression
+ [v] does not mention a value of its parameter type. *)
+
+ let is_independent v = fold f_is_independent v
+
+ let f_replace replacements v subs_res =
+ let v = match v with
+ | Var x when List.mem_assoc x replacements -> List.assoc x replacements
+ | _ -> v in
+ fill_subs v subs_res
+
+ let replace replacements v = fold (f_replace replacements) v
+
+end
+
+include P
+
+
+module type S = sig
+ type t
+
+ val to_string : t -> string
+ val to_cil_term : t -> Cil_types.term
+
+ val compute : t -> t
+ val neg : t -> t tt
+ val addl : t -> t tt -> t tt
+ val addr : t tt -> t -> t tt
+ val minusl : t -> t tt -> t tt
+ val minusr : t tt -> t -> t tt
+ val mull : t -> t tt -> t tt
+ val mulr : t tt -> t -> t tt
+ val divl : t -> t tt -> t tt
+ val divr : t tt -> t -> t tt
+ val modl : t -> t tt -> t tt
+ val modr : t tt -> t -> t tt
+ val maxl : t -> t tt -> t tt
+ val maxr : t tt -> t -> t tt
+ val lel : t -> t tt -> bool
+ val ler : t tt -> t -> bool
+ val ltl : t -> t tt -> bool
+ val ltr : t tt -> t -> bool
+ val gel : t -> t tt -> bool
+ val ger : t tt -> t -> bool
+ val gtl : t -> t tt -> bool
+ val gtr : t tt -> t -> bool
+
+ val compare : t -> t -> int
+end
--- /dev/null
+
+type cost_id =
+ {
+ cost_id : string;
+ cost_incr : string;
+ extern_costs : string Misc.String.Map.t;
+ }
+(** This file makes the interface between the cost plug-in and CerCo's
+ compiler. *)
+
+
+let rec read_extern_cost_variables cin =
+ try
+ let s = input_line cin in
+ assert (String.contains s ' ') ;
+ let i = String.index s ' ' in
+ assert (String.length s > i + 1) ;
+ let fun_name = String.sub s 0 i in
+ let var_name = String.sub s (i+1) (String.length s - (i+1)) in
+ Misc.String.Map.add fun_name var_name (read_extern_cost_variables cin)
+ with End_of_file -> Misc.String.Map.empty
+
+(** [multifile_exists exts filename] returns true if and only if the file name
+ [filename] concatenated with an extension from the list [exts] exists. *)
+
+let multifile_exists exts filename =
+ let f b ext = b || (Sys.file_exists (filename ^ ext)) in
+ List.fold_left f false exts
+
+(** [fresh_multifile exts filename] returns a file name whose base is [filename]
+ and suffixed with an integer such that the result is fresh when concatenated
+ with any extension from the list [exts]. *)
+
+let fresh_multifile exts filename =
+ if not (multifile_exists exts filename) then filename
+ else
+ let rec aux i =
+ let new_filename = filename ^ (string_of_int i) in
+ if not (multifile_exists exts new_filename) then new_filename
+ else aux (i+1) in
+ aux 0
+
+(** [index_of e l] returns the index of the element [e] in the list [l], if
+ any. *)
+
+let index_of e l =
+ let f (i, res) e' =
+ let res' = if e' = e then Some i else res in
+ (i+1, res') in
+ match snd (List.fold_left f (0, None) l) with
+ | None -> raise (Failure "Cerco.index_of")
+ | Some i -> i
+
+let acc_option lustre_option lustre_verify_option lustre_test_option =
+ if lustre_verify_option || lustre_test_option then "-remove-lustre-externals "
+ else
+ if lustre_option then "-lustre "
+ else ""
+
+(** [apply (filename, _)] apply CerCo's compiler on the file [filename]. The
+ result is a new C file with cost annotations, the name of the cost
+ variable, and the name of the cost update function. *)
+
+let apply acc_name lustre_option lustre_verify_option lustre_test_option
+ user_output_filename
+ (filename, _) =
+ let annotated_ext = "-instrumented.c" in
+ let asm_ext = ".s" in
+ let cerco_ext = ".cerco" in
+ let cerco_stack_ext = ".stack_cerco" in
+ let hex_ext = ".hex" in
+ let exts =
+ [annotated_ext ; asm_ext ; cerco_ext ; cerco_stack_ext ; hex_ext] in
+ let tmp_filename =
+ if user_output_filename <> "" then user_output_filename else
+ let tmp_filename = Filename.chop_extension filename in
+ fresh_multifile exts tmp_filename in
+ let acc_option =
+ acc_option lustre_option lustre_verify_option lustre_test_option in
+ let com_acc =
+ Printf.sprintf "%s -a %s -o %s %s"
+ acc_name acc_option tmp_filename filename in
+ let ext_tmp_filename ext = tmp_filename ^ ext in
+ let tmp_filenames = List.map ext_tmp_filename exts in
+ let index_of s = List.nth tmp_filenames (index_of s exts) in
+ let c_tmp_filename = index_of annotated_ext in
+ let s_tmp_filename = index_of asm_ext in
+ let cerco_tmp_filename = index_of cerco_ext in
+ let cerco_stack_tmp_filename = index_of cerco_stack_ext in
+ (* let hex_tmp_filename = index_of hex_ext in *)
+ let rm () =
+ let com =
+ "rm -rf " ^ s_tmp_filename ^ " " ^
+ (if lustre_test_option then "" else cerco_tmp_filename)
+ (* ^ " " ^ hex_tmp_filename *) in
+ ignore (Sys.command com) in
+ if Sys.command com_acc <> 0 then
+ (rm () ; failwith "Error calling acc.")
+ else
+ (let (_, file) = Frontc.parse c_tmp_filename () in
+ let time =
+ let cin = open_in cerco_tmp_filename in
+ let cost_id = input_line cin in
+ let cost_incr = input_line cin in
+ let extern_cost_variables = read_extern_cost_variables cin in
+ close_in cin ;
+ {cost_id = cost_id; cost_incr = cost_incr;
+ extern_costs = extern_cost_variables} in
+ let stack =
+ try
+ let cin = try open_in cerco_stack_tmp_filename with _ -> raise Exit in
+ let cost_stack_id = input_line cin in
+ let cost_stack_max_id = input_line cin in
+ let cost_stack_incr = input_line cin in
+ let extern_cost_stack_variables = read_extern_cost_variables cin in
+ close_in cin ;
+ Some ({cost_id = cost_stack_max_id; cost_incr = cost_stack_incr;
+ extern_costs = extern_cost_stack_variables},
+ cost_stack_id)
+ with Exit -> None in
+ rm () ;
+ (file, c_tmp_filename, time, stack))
--- /dev/null
+
+(** This modules describes complete (and potentially finite) mappings. *)
+
+
+(** The signature of the functor's parameter module. *)
+
+module type T = sig
+ type key
+ type 'a t
+ (** [keys] needs to be given for finite mappings, and needs to be [None] for
+ non finite mappings. *)
+ val keys : key list option
+ val mem : key -> 'a t -> bool
+ val find : key -> 'a t -> 'a
+ val add : key -> 'a -> 'a t -> 'a t
+ val empty : 'a t
+ val map : ('a -> 'b) -> 'a t -> 'b t
+ val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+end
+
+(** The result signature of the functor. *)
+
+module type S = sig
+ type key
+ type 'a t
+ val empty : 'a -> 'a t
+ val find : key -> 'a t -> 'a
+ val upd : key -> 'a -> 'a t -> 'a t
+ val map : ('a -> 'b) -> 'a t -> 'b t
+ (** Keys in case of finite mappings. *)
+ val keys : key list option
+ (** Only works on [keys]. Raises [Failure "CompleteMap.fold: not finite
+ domain"] is no keys. *)
+ val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
+ val merge : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
+ val cmp : ('a -> 'b -> bool -> bool) -> 'a t -> 'b t -> bool -> bool
+ val to_string : (key -> string) -> ('a -> string) -> 'a t -> string
+end
+
+module Make (T : T) : S with type key = T.key = struct
+
+ type key = T.key
+
+ type 'a t = ('a * 'a T.t)
+
+ let empty a = (a, T.empty)
+
+ let find x (a, map) = if T.mem x map then T.find x map else a
+
+ let (!!) = find
+
+ let upd x b (a, map) = (a, T.add x b map)
+
+ let map f (a, map) = (f a, T.map f map)
+
+ let keys = T.keys
+
+ let fold f cmap a = match T.keys with
+ | None -> raise (Failure "CompleteMap.fold: not finite domain")
+ | Some keys ->
+ List.fold_left (fun res key -> f key (find key cmap) res) a keys
+
+ let f_merge f_default f_map ((a1, map1) as cmap1) ((a2, map2) as cmap2) a =
+ let f1 x v1 a = f_map x v1 (find x cmap2) a in
+ let f2 x v2 a = f_map x (find x cmap1) v2 a in
+ let a = T.fold f1 map1 a in
+ f_default a1 a2 (T.fold f2 map2 a)
+
+ let merge f cmap1 cmap2 =
+ let f_default a1 a2 map = (f a1 a2, map) in
+ let f_map x v1 v2 map = T.add x (f v1 v2) map in
+ f_merge f_default f_map cmap1 cmap2 T.empty
+
+ let cmp f cmap1 cmap2 a =
+ let f_default a1 a2 a = f a1 a2 a in
+ let f_map _ v1 v2 a = f v1 v2 a in
+ f_merge f_default f_map cmap1 cmap2 a
+
+ let to_string string_of_key string_of_a (_, map) =
+ let f key a res =
+ res ^ "--KEY\n" ^ (string_of_key key) ^ "\n--VAL\n" ^ (string_of_a a) in
+ T.fold f map ""
+
+end
--- /dev/null
+
+(* TODO: transform precondition into assertions, transform added code into ghost
+ code. *)
+
+(** This module defines the main analysis of the plug-in. Its actions are:
+ - build the CFG of the program;
+ - initialize the static environment of analysis (parameters of the
+ functions, number of loops, etc);
+ - compute the cost of each function depending on the costs of the others;
+ - try to solve the inequations formed from the previous step so as to obtain
+ an independent cost for each function;
+ - save the results;
+ - add the annotations on the program. *)
+
+
+(*** Exceptions ***)
+
+exception ASM_unsupported
+exception Try_unsupported
+
+let string_of_exception = function
+ | ASM_unsupported -> "ASM instructions not supported"
+ | Try_unsupported -> "Try instructions not supported"
+ | Cost_value.Unknown_cost fun_name ->
+ "Cost for function " ^ fun_name ^ " not found."
+ | Cost_value.Unknown_prototype fun_name ->
+ "Prototype for function " ^ fun_name ^ " not found."
+ | e -> raise e
+
+
+(*** Debug flag ***)
+
+let debug = ref false
+
+
+(*** Helpers ***)
+
+let identity x = x
+
+let string_of_list sep f l =
+ let rec aux = function
+ | [] -> ""
+ | [e] -> f e
+ | e :: l -> (f e) ^ sep ^ (aux l) in
+ aux l
+
+let integer_term term = Logic_const.term term Cil_types.Linteger
+
+let tinteger i =
+ let cint64 = Cil_types.CInt64 (My_bigint.of_int i, Cil_types.IInt, None) in
+ let iterm = Cil_types.TConst cint64 in
+ integer_term iterm
+
+let cil_logic_int_var x =
+ Logic_const.tvar (Cil_const.make_logic_var x Cil_types.Linteger)
+
+let current_kf obj = match obj#current_kf with
+ | None -> raise (Failure "Compute.current_kf")
+ | Some kf -> kf
+
+let add_loop_annot obj stmt annot =
+ let annot = Cil_types.User annot in
+ let kf =
+ Cil.get_original_kernel_function (Cil.copy_visit ()) (current_kf obj) in
+ Queue.add (fun () -> Annotations.add kf stmt [Ast.self] annot)
+ obj#get_filling_actions
+
+let add_loop_annots obj stmt annots = List.iter (add_loop_annot obj stmt) annots
+
+let mk_invariant pred =
+ Logic_const.new_code_annotation (Cil_types.AInvariant ([], true, pred))
+
+let mk_variant term =
+ Logic_const.new_code_annotation (Cil_types.AVariant (term, None))
+
+let mk_fun_cost_pred rel cost_id cost =
+ let cost_var = Cil_const.make_logic_var cost_id Cil_types.Linteger in
+ let cost_var = Logic_const.tvar cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let new_cost = Cil_types.TBinOp (Cil_types.PlusA, old_cost, cost) in
+ let new_cost = integer_term new_cost in
+ Logic_const.prel (rel, cost_var, new_cost)
+
+(** Casts may get in the way when looking for a loop counter, just remove
+ them. *)
+
+let rec remove_casts e = match e.Cil_types.enode with
+ | Cil_types.Lval lval ->
+ { e with Cil_types.enode = Cil_types.Lval (remove_casts_lval lval) }
+ | Cil_types.SizeOfE e ->
+ { e with Cil_types.enode = Cil_types.SizeOfE (remove_casts e) }
+ | Cil_types.AlignOfE e ->
+ { e with Cil_types.enode = Cil_types.AlignOfE (remove_casts e) }
+ | Cil_types.UnOp (unop, e, typ) ->
+ { e with Cil_types.enode = Cil_types.UnOp (unop, remove_casts e, typ) }
+ | Cil_types.BinOp (binop, e1, e2, typ) ->
+ let enode =
+ Cil_types.BinOp (binop, remove_casts e1, remove_casts e2, typ) in
+ { e with Cil_types.enode }
+ | Cil_types.CastE (_, e) -> remove_casts e
+ | Cil_types.AddrOf lval ->
+ { e with Cil_types.enode = Cil_types.AddrOf (remove_casts_lval lval) }
+ | Cil_types.StartOf lval ->
+ { e with Cil_types.enode = Cil_types.StartOf (remove_casts_lval lval) }
+ | Cil_types.Info (e, info) ->
+ { e with Cil_types.enode = Cil_types.Info (remove_casts e, info) }
+ | _ -> e
+
+and remove_casts_lval (lhost, offset) =
+ (remove_casts_lhost lhost, remove_casts_offset offset)
+
+and remove_casts_lhost = function
+ | Cil_types.Mem e -> Cil_types.Mem (remove_casts e)
+ | lhost -> lhost
+
+and remove_casts_offset = function
+ | Cil_types.Field (fieldinfo, offset) ->
+ Cil_types.Field (fieldinfo, remove_casts_offset offset)
+ | Cil_types.Index (e, offset) ->
+ Cil_types.Index (remove_casts e, remove_casts_offset offset)
+ | offset -> offset
+
+let rec exp_is_var name e = match (remove_casts e).Cil_types.enode with
+ | Cil_types.Lval (Cil_types.Var v, _) -> v.Cil_types.vname = name
+ | Cil_types.Info (e, _) -> exp_is_var name e
+ | _ -> false
+
+let has_fun_type varinfo = match varinfo.Cil_types.vtype with
+ | Cil_types.TFun _ -> true
+ | _ -> false
+
+let formals_of_varinfo varinfo = match varinfo.Cil_types.vtype with
+ | Cil_types.TFun (_, args, _, _) ->
+ List.map (fun (x, t, _) -> Cil.makeVarinfo false true x t)
+ (Cil.argsToList args)
+ | _ -> assert false (* do not use on these arguments *)
+
+let dummy_location = (Lexing.dummy_pos, Lexing.dummy_pos)
+
+let dummy_varinfo = Cil.makeVarinfo false false "" (Cil_types.TVoid [])
+
+let make_list n a =
+ let rec aux acc i = if i >= n then acc else aux (a :: acc) (i+1) in
+ aux [] 0
+
+let rec stmt_subs stmt =
+ let added = match stmt.Cil_types.skind with
+ | Cil_types.If (_, block1, block2, _)
+ | Cil_types.TryFinally (block1, block2, _)
+ | Cil_types.TryExcept (block1, _, block2, _) ->
+ (block_subs block1) @ (block_subs block2)
+ | Cil_types.Switch (_, block, _, _)
+ | Cil_types.Loop (_, block, _, _, _)
+ | Cil_types.Block block -> block_subs block
+ | Cil_types.UnspecifiedSequence l ->
+ List.map (fun (stmt, _, _, _, _) -> stmt) l
+ | _ -> [] in
+ stmt :: added
+
+and block_subs block = List.flatten (List.map stmt_subs block.Cil_types.bstmts)
+
+let rec first_stmt block = match block.Cil_types.bstmts with
+ | [] -> None
+ | stmt :: _ -> match stmt.Cil_types.skind with
+ | Cil_types.Block block -> first_stmt block
+ | _ -> Some stmt
+
+let stmt_is_break stmt = match stmt.Cil_types.skind with
+ | Cil_types.Break _ -> true
+ | _ -> false
+
+let starts_with_break block = match first_stmt block with
+ | Some stmt ->
+ (match stmt.Cil_types.skind with
+ | Cil_types.Goto (stmt_ref, _) -> stmt_is_break !stmt_ref
+ | _ -> stmt_is_break stmt)
+ | _ -> false
+
+let rec last = function
+ | [] -> None
+ | [e] -> Some e
+ | _ :: l -> last l
+
+let rec last_stmt block = match last block.Cil_types.bstmts with
+ | None -> None
+ | Some stmt -> match stmt.Cil_types.skind with
+ | Cil_types. Block block -> last_stmt block
+ | _ -> Some stmt
+
+module IntSet = Misc.Int.Set
+module IntMap = Misc.Int.Map
+module IntCMap = Misc.Int.CMap
+
+
+(*** Temporary variable name generator ***)
+
+module GenName = struct
+
+ let prefix = ref ""
+ let index = ref 0
+
+ let set_prefix prf = prefix := prf
+ let reset () = index := 0
+
+ let concat suffix = !prefix ^ "_" ^ suffix
+
+ let fresh () =
+ let s = !prefix ^ (string_of_int !index) in
+ index := !index + 1 ;
+ s
+
+ let rec freshes n = if n = 0 then [] else (freshes (n-1)) @ [fresh ()]
+
+ let fresh_varinfo fundec =
+ Cil.makeTempVar fundec ~name:(fresh ()) Cil.intType
+
+ let freshes_varinfo fundec n =
+ let vars = freshes n in
+ List.map (fun name -> Cil.makeTempVar fundec ~name Cil.intType) vars
+
+end
+
+
+(*** Debug helpers ***)
+
+let string_of_intset set =
+ IntSet.fold (fun i s -> s ^ (string_of_int i) ^ " ") set ""
+let string_of_intset_intmap map =
+ let f i set s = Printf.sprintf "%s%d: %s\n" s i (string_of_intset set) in
+ IntMap.fold f map ""
+
+class print_CFG prj = object inherit Visitor.frama_c_copy prj as super
+
+ method vfunc func =
+ Format.printf "*** %s ***\n\n%!" func.Cil_types.svar.Cil_types.vname ;
+ List.iter
+ (fun stmt ->
+ Format.printf "%d: %a\n--> %!" stmt.Cil_types.sid Cil.d_stmt stmt ;
+ List.iter (fun stmt -> Format.printf "%d %!" stmt.Cil_types.sid)
+ stmt.Cil_types.succs ;
+ Format.printf "\n\n%!")
+ func.Cil_types.sallstmts ;
+ Format.printf "\n\n%!" ;
+ Cil.SkipChildren
+
+end
+
+let print_CFG () =
+ let print_CFG_prj =
+ File.create_project_from_visitor "print_CFG" (new print_CFG) in
+ let f () = () in
+ Project.on print_CFG_prj f ()
+
+class loop_exit prj = object inherit Visitor.frama_c_copy prj as super
+
+ method vstmt_aux stmt =
+ let _ = match stmt.Cil_types.skind with
+ | Cil_types.Loop (_, block, _, _, _) ->
+ (match first_stmt block with
+ | Some stmt ->
+ (match stmt.Cil_types.skind with
+ | Cil_types.If (_, _, block, _) ->
+ (match first_stmt block with
+ | Some stmt ->
+ (match stmt.Cil_types.skind with
+ | Cil_types.Break _ ->
+ Format.printf "Loop exit: %!" ;
+ List.iter
+ (fun stmt -> Format.printf "%d %!" stmt.Cil_types.sid)
+ stmt.Cil_types.succs ;
+ Format.printf "\n%!"
+ | _ -> Format.printf "If but no break\n%!")
+ | _ -> Format.printf "If but no child\n%!")
+ | _ -> Format.printf "Loop but no if\n%!")
+ | _ -> Format.printf "Loop but no child\n%!")
+ | _ -> () in
+ Cil.DoChildren
+
+end
+
+let loop_exit () =
+ let loop_exit_prj =
+ File.create_project_from_visitor "loop_exit" (new loop_exit) in
+ let f () = () in
+ Format.printf "\n%!" ;
+ Project.on loop_exit_prj f ()
+
+
+(*** Make CFG ***)
+
+class make_CFG prj = object inherit Visitor.frama_c_copy prj as super
+
+ method vfile file =
+ Cfg.clearFileCFG file ;
+ Cfg.computeFileCFG file ;
+ Cil.SkipChildren
+
+end
+
+let make_CFG () =
+ let make_CFG_prj =
+ File.create_project_from_visitor "make_CFG" (new make_CFG) in
+ let f () = () in
+ Project.on make_CFG_prj f ()
+
+
+(*** Control points that are gotoed to, control points of a loop. Those will
+ help checking that a loop has a supported form. ***)
+
+module PointsInfo = struct
+
+ type t = { gotoed : IntSet.t IntMap.t ; loop_points : IntSet.t IntMap.t }
+
+ let empty = { gotoed = IntMap.empty ; loop_points = IntMap.empty }
+
+ let gotoed points_info = points_info.gotoed
+
+ let loop_points points_info = points_info.loop_points
+
+ let mem_gotoed to_id points_info = IntMap.mem to_id (gotoed points_info)
+
+ let find_gotoed to_id points_info = IntMap.find to_id (gotoed points_info)
+
+ let add_gotoed to_id to_from_ids points_info =
+ let gotoed = IntMap.add to_id to_from_ids (gotoed points_info) in
+ { points_info with gotoed }
+
+ let mem_loop_points loop_id points_info =
+ IntMap.mem loop_id (loop_points points_info)
+
+ let find_loop_points loop_id points_info =
+ IntMap.find loop_id (loop_points points_info)
+
+ let add_loop_points loop_id ids points_info =
+ let loop_points = IntMap.add loop_id ids (loop_points points_info) in
+ { points_info with loop_points }
+
+end
+
+(*** PointsInfo for each function ***)
+
+module PointsInfos = struct
+
+ type t = PointsInfo.t Misc.String.Map.t
+
+ let empty = Misc.String.Map.empty
+
+ let mem = Misc.String.Map.mem
+
+ let add = Misc.String.Map.add
+
+ let find = Misc.String.Map.find
+
+ let add_gotoed fun_name to_id to_from_ids points_infos =
+ let points_info =
+ if mem fun_name points_infos then find fun_name points_infos
+ else PointsInfo.empty in
+ let points_info = PointsInfo.add_gotoed to_id to_from_ids points_info in
+ add fun_name points_info points_infos
+
+ let add_loop_points fun_name loop_id ids points_infos =
+ let points_info =
+ if mem fun_name points_infos then find fun_name points_infos
+ else PointsInfo.empty in
+ let points_info = PointsInfo.add_loop_points loop_id ids points_info in
+ add fun_name points_info points_infos
+
+end
+
+class points_infos points_infos prj =
+object inherit Visitor.frama_c_copy prj as super
+
+ val mutable current_fun_name = ""
+
+ method vstmt_aux stmt =
+ (* because it is initialized in vfunc *)
+ assert (PointsInfos.mem current_fun_name !points_infos) ;
+ let points_info = PointsInfos.find current_fun_name !points_infos in
+ let _ = match stmt.Cil_types.skind with
+ | Cil_types.Goto (stmt_ref, _) ->
+ let from_id = stmt.Cil_types.sid in
+ let to_id = !stmt_ref.Cil_types.sid in
+ let to_from_ids =
+ if PointsInfo.mem_gotoed to_id points_info then
+ PointsInfo.find_gotoed to_id points_info
+ else IntSet.empty in
+ let to_from_ids = IntSet.add from_id to_from_ids in
+ points_infos :=
+ PointsInfos.add_gotoed current_fun_name to_id to_from_ids
+ !points_infos
+ | Cil_types.Loop (_, block, _, _, _) ->
+ let loop_id = stmt.Cil_types.sid in
+ let ids =
+ if PointsInfo.mem_loop_points loop_id points_info then
+ PointsInfo.find_loop_points loop_id points_info
+ else IntSet.empty in
+ let ids = IntSet.add loop_id ids in
+ let f_stmts stmt = stmt :: (stmt_subs stmt) in
+ let stmts = List.flatten (List.map f_stmts block.Cil_types.bstmts) in
+ let f ids stmt = IntSet.add stmt.Cil_types.sid ids in
+ let ids = List.fold_left f ids stmts in
+ points_infos :=
+ PointsInfos.add_loop_points current_fun_name loop_id ids !points_infos
+ | _ -> () in
+ Cil.DoChildren
+
+ method vfunc fundec =
+ current_fun_name <- fundec.Cil_types.svar.Cil_types.vname ;
+ points_infos :=
+ PointsInfos.add current_fun_name PointsInfo.empty !points_infos ;
+ Cil.DoChildren
+
+end
+
+(** [points_infos ()] returns a mapping that associates to each function of the
+ current program in the currently opened project the control points that are
+ gotoed to and the control points of loops. *)
+
+let points_infos () : PointsInfos.t =
+ let map = ref PointsInfos.empty in
+ let points_infos_prj =
+ File.create_project_from_visitor "points_infos" (new points_infos map) in
+ let f () = !map in
+ Project.on points_infos_prj f ()
+
+
+(*** Value (flat) domain extremes ***)
+
+module BotAndTop = struct
+
+ type t = Bot | Top
+
+ let compare = Pervasives.compare
+
+ let to_string = function
+ | Bot -> "bot"
+ | Top -> "top"
+
+ let to_cil_term _ = assert false (* should not be used *)
+
+ let top = ArithSig.A Top
+ let bot = ArithSig.A Bot
+
+ let neg = function
+ | Top -> top
+ | Bot -> bot
+
+ let addl a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot -> bot
+ | Top, _ -> top
+
+ let addr v a = addl a v
+
+ let minusl a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot -> bot
+ | Top, _ -> top
+
+ let minusr v a = match v, a with
+ | _, Bot | ArithSig.A Bot, _ -> bot
+ | _, Top -> top
+
+ let mull a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot -> bot
+ | _, ArithSig.Int 0 -> ArithSig.Int 0
+ | Top, _ -> top
+
+ let mulr v a = mull a v
+
+ let divl a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot | _, ArithSig.Int 0 -> bot
+ | Top, _ -> top
+
+ let divr v a = match v, a with
+ | _, Bot | ArithSig.A Bot, _ -> bot
+ | _, Top -> top
+
+ let modl a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot | _, ArithSig.Int 0 -> bot
+ | Top, _ -> top
+
+ let modr v a = match v, a with
+ | _, Bot | ArithSig.A Bot, _ -> bot
+ | _, Top -> top
+
+ let maxl a v = match a, v with
+ | Bot, _ | _, ArithSig.A Bot -> bot
+ | Top, _ -> top
+
+ let maxr v a = maxl a v
+
+ let lel a v = match a, v with
+ | Bot, _ -> true
+ | Top, ArithSig.A Top -> true
+ | Top, _ -> false
+
+ let ler v a = match v, a with
+ | _, Top -> true
+ | ArithSig.A Bot, Bot -> true
+ | _, Bot -> false
+
+ let ltl a v = match a, v with
+ | Bot, ArithSig.A Bot -> false
+ | Bot, _ -> true
+ | Top, _ -> false
+
+ let ltr v a = match v, a with
+ | ArithSig.A Top, Top -> false
+ | _, Top -> true
+ | _, Bot -> false
+
+ let gel a v = ler v a
+
+ let ger v a = lel a v
+
+ let gtl a v = ltr v a
+
+ let gtr v a = ltl a v
+
+ let compute v = v
+
+end
+
+
+(*** Arithmetic expressions flat domain ***)
+
+module ArithValDom = struct
+
+ include Arith.Make (BotAndTop)
+
+ let top = A BotAndTop.Top
+
+ let bot = A BotAndTop.Bot
+
+ let join v1 v2 = match v1, v2 with
+ | A BotAndTop.Bot, v | v, A BotAndTop.Bot -> v
+ | _ when v1 = v2 -> v1
+ | _ -> A BotAndTop.Top
+
+ let widen = join
+
+ let narrow v1 v2 = match v1, v2 with
+ | A BotAndTop.Top, A _ -> v1
+ | A BotAndTop.Top, _ -> v2
+ | _ -> v1
+
+ let f_is_concrete v subs_res =
+ let b = match v with
+ | A _ -> false
+ | _ -> true in
+ List.fold_left (&&) true (b :: subs_res)
+
+ let is_concrete v = fold f_is_concrete v
+
+ let add_list l = List.fold_left add (Int 0) l
+
+ let last_value rel _ exit_value increment =
+ let rel_added = of_int (if is_large rel then 0 else 1) in
+ let rel_op = if has_lower_type rel then minus else add in
+ add (rel_op exit_value rel_added) increment
+
+ let iteration_nb init_value counter increment =
+ div (minus (of_var counter) init_value) increment
+
+end
+
+module Domain = ArithValDom
+
+
+(*** Abstract cost ***)
+
+module AbsCost = struct
+
+ include (Cost_value.Make (ArithValDom))
+
+end
+
+
+(*** Requirements for loop termination ***)
+
+module Require = struct
+
+ type t =
+ { relation : Domain.relation ;
+ init_value : Domain.t ;
+ exit_value : Domain.t ;
+ increment : Domain.t }
+
+ let compare = Pervasives.compare
+
+ let relation require = require.relation
+ let init_value require = require.init_value
+ let exit_value require = require.exit_value
+ let increment require = require.increment
+
+ let merge f require1 require2 =
+ (* each loop has a single condition relation *)
+ assert (relation require1 = relation require2) ;
+ { relation = relation require1 ;
+ init_value = f (init_value require1) (init_value require2) ;
+ exit_value = f (exit_value require1) (exit_value require2) ;
+ increment = f (increment require1) (increment require2) }
+
+ let join = merge Domain.join
+ let widen = merge Domain.widen
+ let narrow = merge Domain.narrow
+
+ let le require1 require2 =
+ (* each loop has a single condition relation *)
+ (relation require1 = relation require2) &&
+ (Domain.le (init_value require1) (init_value require2)) &&
+ (Domain.le (exit_value require1) (exit_value require2)) &&
+ (Domain.le (increment require1) (increment require2))
+
+ let make relation init_value exit_value increment =
+ { relation ; init_value ; exit_value ; increment }
+
+ let replace_vars replacements require =
+ let init_value = Domain.replace_vars replacements (init_value require) in
+ let exit_value = Domain.replace_vars replacements (exit_value require) in
+ let increment = Domain.replace_vars replacements (increment require) in
+ { require with init_value ; exit_value ; increment }
+
+ let to_string require =
+ Printf.sprintf "%s %s %s %s"
+ (Domain.string_of_relation (relation require))
+ (Domain.to_string (init_value require))
+ (Domain.to_string (exit_value require))
+ (Domain.to_string (increment require))
+
+end
+
+(*** Associates Require to control points ***)
+
+module Requires = struct
+
+ module M = Misc.Int.Map
+
+ type t = Require.t M.t
+
+ let empty = M.empty
+
+ let mem = M.mem
+
+ let find = M.find
+
+ let merge f =
+ let f_merge _ require1 require2 = match require1, require2 with
+ | None, None -> None
+ | Some require, None | None, Some require -> Some require
+ | Some require1, Some require2 -> Some (f require1 require2) in
+ M.merge f_merge
+
+ let join = merge Require.join
+ let widen = merge Require.widen
+ let narrow = merge Require.narrow
+
+ let le requires1 requires2 =
+ let f id require1 res =
+ res && (mem id requires2) && (Require.le require1 (find id requires2)) in
+ M.fold f requires1 true
+
+ let cardinal = M.cardinal
+
+ let fold f requires a =
+ let f' _ require a = f require a in
+ M.fold f' requires a
+
+ let add = M.add
+
+ let replace_vars replacements = M.map (Require.replace_vars replacements)
+
+ let to_string requires =
+ let f id require res =
+ Printf.sprintf "%s%d: %s\n%!" res id (Require.to_string require) in
+ M.fold f requires ""
+
+end
+
+
+(*** Point kind ***)
+
+module LoopInfo = struct
+
+ type t =
+ { tmp_loop : Cil_types.varinfo ;
+ counter : string ;
+ relation : Domain.relation ;
+ exit_exp : Cil_types.exp ;
+ increment : Cil_types.exp ;
+ prev_stmts : (Cil_types.stmt * int (* position *)) list ;
+ last_stmts : Cil_types.stmt list }
+
+ let tmp_loop loop_info = loop_info.tmp_loop
+
+ let counter loop_info = loop_info.counter
+
+ let relation loop_info = loop_info.relation
+
+ let exit_exp loop_info = loop_info.exit_exp
+
+ let increment loop_info = loop_info.increment
+
+ let prev_stmts loop_info = loop_info.prev_stmts
+
+ let last_stmts loop_info = loop_info.last_stmts
+
+ let make tmp_loop counter relation exit_exp increment prev_stmts last_stmts =
+ { tmp_loop ; counter ; relation ; exit_exp ; increment ;
+ prev_stmts ; last_stmts }
+
+
+end
+
+module PointKind = struct
+
+ type t =
+ | LoopStart of LoopInfo.t
+ | LoopExit of LoopInfo.t
+ | ULoopStart (* start of an unrecognized loop *)
+ | ULoopExit (* exit of an unrecognized loop *)
+ | RegularPoint
+
+ let is_recognized_loop_start = function
+ | LoopStart _ -> true
+ | _ -> false
+
+ let tmp_loop = function
+ | LoopStart loop_info -> LoopInfo.tmp_loop loop_info
+ | _ -> raise (Invalid_argument "PointKind.tmp_loop")
+
+end
+
+module PointKinds = struct
+
+ type t = PointKind.t IntMap.t
+
+ let empty = IntMap.empty
+ let add = IntMap.add
+ let mem = IntMap.mem
+ let find = IntMap.find
+ let fold = IntMap.fold
+ let dom point_kinds = List.map fst (IntMap.bindings point_kinds)
+
+ let mem_loop_start point point_kinds =
+ mem point point_kinds &&
+ (PointKind.is_recognized_loop_start (find point point_kinds))
+
+ let find_tmp_loop point point_kinds =
+ let error = Invalid_argument "PointKinds.find_tmp_loop" in
+ PointKind.tmp_loop (IntMap.error_find point point_kinds error)
+
+end
+
+
+(*** Fun infos ***)
+
+module FunInfo = struct
+
+ type local_vars = (Cil_types.varinfo * string) list * Cil_types.varinfo list
+
+ type t =
+ { prototype : local_vars ;
+ (* exactly one start and one end points in Frama-C's CFG *)
+ start_and_end_points : (int * int) option ;
+ nb_loops : int ;
+ point_kinds : PointKinds.t }
+
+ let empty =
+ { prototype = ([], []) ; start_and_end_points = None ; nb_loops = 0 ;
+ point_kinds = PointKinds.empty }
+
+ let make formals locals nb_loops start_and_end_points point_kinds =
+ { prototype = (formals, locals) ;
+ nb_loops ; start_and_end_points ; point_kinds }
+
+ let prototype fun_info =
+ List.map (fun (x, _) -> x.Cil_types.vname) (fst fun_info.prototype)
+
+ let start_and_end_points fun_info = fun_info.start_and_end_points
+
+ let formals_and_locals fun_info = fun_info.prototype
+
+ let point_kinds fun_info = fun_info.point_kinds
+
+ let mem_point point fun_info = PointKinds.mem point fun_info.point_kinds
+
+ let find_point point fun_info = PointKinds.find point fun_info.point_kinds
+
+ let points fun_info = PointKinds.dom fun_info.point_kinds
+
+ let nb_loops fun_info = fun_info.nb_loops
+
+ let add_nb_loops fun_info =
+ let nb_loops = fun_info.nb_loops + 1 in
+ { fun_info with nb_loops }
+
+ let mem_loop_start point fun_info =
+ PointKinds.mem_loop_start point fun_info.point_kinds
+
+ let find_tmp_loop point fun_info =
+ PointKinds.find_tmp_loop point fun_info.point_kinds
+
+end
+
+module FunInfos = struct
+
+ type t = FunInfo.t Misc.String.Map.t
+
+ let empty = Misc.String.Map.empty
+
+ let prototypes = Misc.String.Map.map FunInfo.prototype
+
+ let mem = Misc.String.Map.mem
+
+ let add
+ fun_name formals locals nb_loops start_and_end_points point_kinds
+ fun_infos =
+ let fun_info =
+ FunInfo.make formals locals nb_loops start_and_end_points point_kinds in
+ Misc.String.Map.add fun_name fun_info fun_infos
+
+ let start_and_end_points fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.start_and_end_points" in
+ let fun_info = Misc.String.Map.error_find fun_name fun_infos error in
+ FunInfo.start_and_end_points fun_info
+
+ let formals_and_locals fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.formals_and_locals" in
+ let fun_info = Misc.String.Map.error_find fun_name fun_infos error in
+ FunInfo.formals_and_locals fun_info
+
+ let mem_point fun_name point fun_infos =
+ Misc.String.Map.mem fun_name fun_infos &&
+ FunInfo.mem_point point (Misc.String.Map.find fun_name fun_infos)
+
+ let find_point fun_name point fun_infos =
+ FunInfo.find_point point (Misc.String.Map.find fun_name fun_infos)
+
+ let points fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.points" in
+ FunInfo.points (Misc.String.Map.error_find fun_name fun_infos error)
+
+ let nb_loops fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.nb_loops" in
+ FunInfo.nb_loops (Misc.String.Map.error_find fun_name fun_infos error)
+
+ let add_nb_loops fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.add_nb_loops" in
+ let fun_info = Misc.String.Map.error_find fun_name fun_infos error in
+ let fun_info = FunInfo.add_nb_loops fun_info in
+ Misc.String.Map.add fun_name fun_info fun_infos
+
+ let mem_loop_start fun_name point fun_infos =
+ Misc.String.Map.mem fun_name fun_infos &&
+ FunInfo.mem_loop_start point (Misc.String.Map.find fun_name fun_infos)
+
+ let find_tmp_loop fun_name point fun_infos =
+ let error = Invalid_argument "FunInfos.find_tmp_loop" in
+ let fun_info = Misc.String.Map.error_find fun_name fun_infos error in
+ FunInfo.find_tmp_loop point fun_info
+
+ let point_kinds fun_name fun_infos =
+ let error = Invalid_argument "FunInfos.point_kinds" in
+ let fun_info = Misc.String.Map.error_find fun_name fun_infos error in
+ FunInfo.point_kinds fun_info
+
+end
+
+
+(*** Static environment ***)
+
+module StaticEnv = struct
+
+ type t =
+ { fname : string ;
+ f_old_name : string ;
+ cost_id : string ;
+ cost_incr : string ;
+ cost_varinfo : Cil_types.varinfo ;
+ fun_infos : FunInfos.t ;
+ globals : Misc.String.Set.t ;
+ extern_costs : string Misc.String.Map.t }
+
+ let init fname f_old_name cost_id cost_incr extern_costs =
+ { fname ; f_old_name ; cost_id ; cost_incr ; cost_varinfo = dummy_varinfo ;
+ fun_infos = FunInfos.empty ;
+ globals = Misc.String.Set.empty ; extern_costs }
+
+ let fname static_env = static_env.fname
+
+ let f_old_name static_env = static_env.f_old_name
+
+ let prototypes static_env = FunInfos.prototypes static_env.fun_infos
+
+ let add_fun_infos
+ fun_name formals locals nb_loops start_and_end_points point_kinds
+ static_env =
+ let fun_infos =
+ FunInfos.add fun_name formals locals nb_loops start_and_end_points
+ point_kinds static_env.fun_infos in
+ { static_env with fun_infos }
+
+ let globals static_env = static_env.globals
+
+ let add_globals x static_env =
+ let globals = Misc.String.Set.add x (globals static_env) in
+ { static_env with globals }
+
+ let formals_and_locals fun_name static_env =
+ FunInfos.formals_and_locals fun_name static_env.fun_infos
+
+ let locals fun_name static_env = snd (formals_and_locals fun_name static_env)
+ let formals fun_name static_env = fst (formals_and_locals fun_name static_env)
+
+ let is_local fun_name x static_env =
+ let f varinfo = varinfo.Cil_types.vname = x in
+ List.exists f (locals fun_name static_env)
+
+ let is_formal fun_name x static_env =
+ let (formals, locals) = formals_and_locals fun_name static_env in
+ let f_local varinfo = varinfo.Cil_types.vname <> x in
+ let f_formal (varinfo, _) = varinfo.Cil_types.vname = x in
+ (List.for_all f_local locals) && (List.exists f_formal formals)
+
+ let is_global fun_name x static_env =
+ let (formals, locals) = formals_and_locals fun_name static_env in
+ let f_local varinfo = varinfo.Cil_types.vname <> x in
+ let f_formal (varinfo, _) = varinfo.Cil_types.vname <> x in
+ (List.for_all f_local locals) && (List.for_all f_formal formals) &&
+ (Misc.String.Set.mem x (globals static_env))
+
+ let cost_id static_env = static_env.cost_id
+
+ let cost_varinfo static_env = static_env.cost_varinfo
+
+ let cost_incr static_env = static_env.cost_incr
+
+ let set_cost_varinfo cost_varinfo static_env =
+ { static_env with cost_varinfo }
+
+ let mem_point fun_name point static_env =
+ FunInfos.mem_point fun_name point static_env.fun_infos
+
+ let find_point fun_name point static_env =
+ FunInfos.find_point fun_name point static_env.fun_infos
+
+ let extern_costs static_env = static_env.extern_costs
+
+ let start_and_end_points fun_name static_env =
+ FunInfos.start_and_end_points fun_name static_env.fun_infos
+
+ let mem_fun_name fun_name static_env =
+ FunInfos.mem fun_name static_env.fun_infos
+
+ let points fun_name static_env =
+ FunInfos.points fun_name static_env.fun_infos
+
+ let nb_loops fun_name static_env =
+ FunInfos.nb_loops fun_name static_env.fun_infos
+
+ let add_nb_loops fun_name static_env =
+ let fun_infos = FunInfos.add_nb_loops fun_name static_env.fun_infos in
+ { static_env with fun_infos }
+
+ let mem_loop_start fun_name point static_env =
+ FunInfos.mem_loop_start fun_name point static_env.fun_infos
+
+ let find_tmp_loop fun_name point static_env =
+ FunInfos.find_tmp_loop fun_name point static_env.fun_infos
+
+ let point_kinds fun_name static_env =
+ FunInfos.point_kinds fun_name static_env.fun_infos
+
+end
+
+
+(*** Initializations ***)
+
+let special_point f body = match f body with
+ | None -> None
+ | Some stmt -> Some stmt.Cil_types.sid
+
+let start_point = special_point first_stmt
+
+let end_point = special_point last_stmt
+
+let make_start_and_end_points start_point end_point =
+ match start_point, end_point with
+ | None, _ | _, None -> None
+ | Some start_point, Some end_point -> Some (start_point, end_point)
+
+let make_tmp_names formals =
+ let f varinfo = (varinfo, GenName.concat varinfo.Cil_types.vname) in
+ List.map f formals
+
+let rec extract_added_value counter e = match e.Cil_types.enode with
+ | Cil_types.BinOp (Cil_types.PlusA, e1, e2, _) when exp_is_var counter e1 ->
+ Some (counter, e2)
+ | Cil_types.BinOp (Cil_types.MinusA, e1, e2, typ)
+ when exp_is_var counter e1 ->
+ let enode = Cil_types.UnOp (Cil_types.Neg, e2, typ) in
+ let e2 = { e2 with Cil_types.enode = enode } in
+ Some (counter, e2)
+ | Cil_types.CastE (_, e) -> extract_added_value counter e
+ | _ ->
+ if !debug then
+ Format.printf
+ "Could not find added increment value for counter %s in %a.\n%!"
+ counter Cil.d_exp e ;
+ None
+
+let extract_increment block =
+ let open Misc.Option in
+ last_stmt block >>=
+ (fun stmt -> match stmt.Cil_types.skind with
+ | Cil_types.Instr (Cil_types.Set ((Cil_types.Var v, _), e, _)) ->
+ extract_added_value v.Cil_types.vname e
+ | _ ->
+ if !debug then
+ Format.printf
+ "Could not find increment instruction; found %a instead.\n%!"
+ Cil.d_stmt stmt ;
+ None)
+
+let extract_guard block (counter, increment) =
+ let open Misc.Option in
+ first_stmt block >>=
+ (fun stmt -> match stmt.Cil_types.skind with
+ | Cil_types.If (e, _, block, _) when starts_with_break block ->
+ (match e.Cil_types.enode with
+ | Cil_types.BinOp (rel, e1, e2, _)
+ when exp_is_var counter e1 && Domain.is_supported_rel rel ->
+ Some (counter, Domain.rel_of_cil_binop rel, e2, increment)
+ | Cil_types.BinOp (rel, e1, e2, _)
+ when exp_is_var counter e2 && Domain.is_supported_rel rel ->
+ let rel = Domain.rel_of_cil_binop rel in
+ let rel = Domain.opposite rel in
+ Some (counter, rel, e1, increment)
+ | _ ->
+ if !debug then
+ Format.printf "Unsupported guard condition %a on counter %s.\n%!"
+ Cil.d_exp e counter ;
+ None)
+ | Cil_types.If (_, _, block, _) ->
+ if !debug then
+ Format.printf "Loop not guarded by a break:\n%a\n%!" Cil.d_block block ;
+ None
+ | _ ->
+ if !debug then Format.printf "Loop not guarded:\n%a\n%!" Cil.d_stmt stmt ;
+ None)
+
+let add_point_kinds
+ start_id loop_start_info last_stmts loop_exit_info point_kinds =
+ let point_kinds = PointKinds.add start_id loop_start_info point_kinds in
+ let f_last_stmts point_kinds stmt =
+ PointKinds.add stmt.Cil_types.sid loop_exit_info point_kinds in
+ List.fold_left f_last_stmts point_kinds last_stmts
+
+let add_loop_point_kinds id tmp_loop exps prev_stmts last_stmts point_kinds =
+ match exps with
+ | None ->
+ let loop_start_info = PointKind.ULoopStart in
+ let loop_exit_info = PointKind.ULoopExit in
+ add_point_kinds id loop_start_info last_stmts loop_exit_info point_kinds
+ | Some (counter, relation, exit_exp, increment) ->
+ let loop_info =
+ LoopInfo.make
+ tmp_loop counter relation exit_exp increment prev_stmts last_stmts in
+ let loop_start_info = PointKind.LoopStart loop_info in
+ let loop_exit_info = PointKind.LoopExit loop_info in
+ add_point_kinds id loop_start_info last_stmts loop_exit_info point_kinds
+
+let loop_exits loop_points body =
+ let f_exists stmt = not (IntSet.mem stmt.Cil_types.sid loop_points) in
+ let f stmt = List.exists f_exists stmt.Cil_types.succs in
+ List.filter f (block_subs body)
+
+let stmt_point_kinds fundec points_info point_kinds stmt =
+ let id = stmt.Cil_types.sid in
+ match stmt.Cil_types.skind with
+ | Cil_types.Loop (_, body, _, _, _) ->
+ let open Misc.Option in
+ assert (PointsInfo.mem_loop_points id points_info) ;
+ let loop_points = PointsInfo.find_loop_points id points_info in
+ let tmp_loop = GenName.fresh_varinfo fundec in
+ let exps = extract_increment body >>= extract_guard body in
+ let f_preds res pred =
+ let pred_id = pred.Cil_types.sid in
+ if IntSet.mem pred_id loop_points then res
+ else
+ let succs_id =
+ List.map (fun stmt -> stmt.Cil_types.sid) pred.Cil_types.succs in
+ let opt_pos = Misc.List.pos id succs_id in
+ (* otherwise pred would not be a predecessor of the loop *)
+ assert (opt_pos <> None) ;
+ (pred, Misc.Option.extract opt_pos) :: res in
+ let prev_stmts =
+ List.fold_left f_preds [] stmt.Cil_types.preds in
+ let last_stmts = loop_exits loop_points body in
+ let last_stmts = match last_stmt body with
+ | None -> last_stmts
+ | Some last_stmt -> last_stmt :: last_stmts in
+ add_loop_point_kinds id tmp_loop exps prev_stmts last_stmts point_kinds
+ | _ when PointKinds.mem id point_kinds -> point_kinds
+ | _ -> PointKinds.add id PointKind.RegularPoint point_kinds
+
+class initialize points_infos static_env prj =
+object inherit Visitor.frama_c_copy prj as super
+
+ method vglob_aux glob =
+ let _ = match glob with
+ | Cil_types.GVarDecl (_, varinfo, _) when has_fun_type varinfo ->
+ GenName.reset () ;
+ GenName.set_prefix "__tmp" ;
+ let fun_name = varinfo.Cil_types.vname in
+ let formals = formals_of_varinfo varinfo in
+ let formals = make_tmp_names formals in
+ let locals = [] in
+ let nb_loops = 0 in
+ let start_and_end_points = None in
+ let point_kinds = PointKinds.empty in
+ static_env :=
+ StaticEnv.add_fun_infos
+ fun_name formals locals nb_loops start_and_end_points point_kinds
+ !static_env
+ | Cil_types.GFun (fundec, _) ->
+ GenName.reset () ;
+ GenName.set_prefix "__tmp" ;
+ let fun_name = fundec.Cil_types.svar.Cil_types.vname in
+ (* supposes a good initialization of [points_infos] *)
+ assert (PointsInfos.mem fun_name points_infos) ;
+ let points_info = PointsInfos.find fun_name points_infos in
+ let formals = fundec.Cil_types.sformals in
+ let formals = make_tmp_names formals in
+ let locals = fundec.Cil_types.slocals in
+ let nb_loops = 0 in
+ let start_point = start_point fundec.Cil_types.sbody in
+ let end_point = end_point fundec.Cil_types.sbody in
+ let start_and_end_points =
+ make_start_and_end_points start_point end_point in
+ GenName.set_prefix "__tmp_loop" ;
+ let point_kinds =
+ List.fold_left (stmt_point_kinds fundec points_info) PointKinds.empty
+ fundec.Cil_types.sallstmts in
+ static_env :=
+ StaticEnv.add_fun_infos
+ fun_name formals locals nb_loops start_and_end_points point_kinds
+ !static_env
+ | Cil_types.GVar (varinfo, _, _)
+ when varinfo.Cil_types.vname = StaticEnv.cost_id !static_env ->
+ static_env := StaticEnv.set_cost_varinfo varinfo !static_env ;
+ static_env := StaticEnv.add_globals varinfo.Cil_types.vname !static_env
+ | Cil_types.GVar (varinfo, _, _) | Cil_types.GVarDecl (_, varinfo, _) ->
+ static_env := StaticEnv.add_globals varinfo.Cil_types.vname !static_env
+ | _ -> () in
+ Cil.DoChildren
+
+end
+
+let initialize tmp_prefix fname f_old_name cost_id cost_incr extern_costs =
+ let points_infos = points_infos () in
+ GenName.set_prefix tmp_prefix ;
+ let static_env_ref =
+ ref (StaticEnv.init fname f_old_name cost_id cost_incr extern_costs) in
+ let initialize_prj =
+ File.create_project_from_visitor "initialize"
+ (new initialize points_infos static_env_ref) in
+ let f () = !static_env_ref in
+ Project.on initialize_prj f ()
+
+
+(*** Abstract domains and environments ***)
+
+module type DOMAIN = sig
+ type t
+ val of_int : int -> t
+ val of_var : string -> t
+ val top : t
+ val bot : t
+ val join : t -> t -> t
+ val widen : t -> t -> t
+ val narrow : t -> t -> t
+ val le : t -> t -> bool
+ val to_string : t -> string
+ val neg : t -> t
+ val add : t -> t -> t
+ val minus : t -> t -> t
+ val mul : t -> t -> t
+ val div : t -> t -> t
+ val modulo : t -> t -> t
+end
+
+module type VARABSENV = sig
+ module Domain : DOMAIN
+ type t
+ val bot : t
+ val top : t
+ val upd : string -> Domain.t -> t -> t
+ val find : string -> t -> Domain.t
+ val init : Misc.String.Set.t -> (string * string) list -> t
+ val join : t -> t -> t
+ val widen : t -> t -> t
+ val narrow : t -> t -> t
+ val le : t -> t -> bool
+ val to_string : t -> string
+end
+
+module type ABSENV = sig
+ module VarAbsEnv : VARABSENV
+ module Domain : DOMAIN
+ type t
+ type addressed = Misc.String.Set.t
+ val cost : t -> AbsCost.t
+ val requires : t -> Requires.t
+ val set_cost : t -> AbsCost.t -> t
+ val add_cost : t -> AbsCost.t -> t
+ val add_addressed : t -> addressed -> t
+ val set_lval : t -> Cil_types.lval -> Domain.t -> t
+ val top_vars : t -> Misc.String.Set.t -> t
+ val find : string -> t -> Domain.t
+ val bot : t
+ val init : Misc.String.Set.t -> (string * string) list -> t
+ val join : t -> t -> t
+ val widen : t -> t -> t
+ val narrow : t -> t -> t
+ val le : t -> t -> bool
+ val add_require : t -> int -> Require.t -> t
+ val to_string : t -> string
+end
+
+module MakeVarAbsEnv (D : DOMAIN) : VARABSENV with module Domain = D = struct
+
+ module Domain = D
+
+ type t = Domain.t Misc.String.CMap.t
+
+ let bot = Misc.String.CMap.empty D.bot
+ let upd = Misc.String.CMap.upd
+ let find = Misc.String.CMap.find
+
+ let init globals formals =
+ let f x env = Misc.String.CMap.upd x D.top env in
+ let env = Misc.String.Set.fold f globals bot in
+ let f env (x, tmp) =
+ let env = Misc.String.CMap.upd x (D.of_var tmp) env in
+ Misc.String.CMap.upd tmp (D.of_var tmp) env in
+ List.fold_left f env formals
+
+ let join = Misc.String.CMap.merge D.join
+ let widen = Misc.String.CMap.merge D.widen
+ let narrow = Misc.String.CMap.merge D.narrow
+
+ let top = Misc.String.CMap.empty D.top
+
+ let le env1 env2 =
+ let f v1 v2 res = res && (Domain.le v1 v2) in
+ Misc.String.CMap.cmp f env1 env2 true
+
+ let to_string =
+ Misc.String.CMap.to_string (fun x -> x) (fun v -> (D.to_string v) ^ "\n")
+
+end
+
+module MakeAbsEnv (VAE : VARABSENV)
+ : ABSENV with module VarAbsEnv = VAE
+ and module Domain = VAE.Domain = struct
+
+ module VarAbsEnv = VAE
+ module Domain = VarAbsEnv.Domain
+
+ type addressed = Misc.String.Set.t
+
+ type t =
+ { cost : AbsCost.t ; var_abs_env : VarAbsEnv.t ; addressed : addressed ;
+ requires : Requires.t }
+
+ let init globals formals =
+ let cost = AbsCost.bot in
+ let var_abs_env = VarAbsEnv.init globals formals in
+ let addressed = Misc.String.Set.empty in
+ let requires = Requires.empty in
+ { cost ; var_abs_env ; addressed ; requires }
+
+ let cost env = env.cost
+
+ let requires env = env.requires
+
+ let var_abs_env env = env.var_abs_env
+
+ let find x env = VarAbsEnv.find x (var_abs_env env)
+
+ let set_cost env cost = { env with cost }
+
+ let add_cost env cost = { env with cost = AbsCost.add env.cost cost }
+
+ let addressed env = env.addressed
+
+ let add_addressed env addressed =
+ { env with addressed = Misc.String.Set.union env.addressed addressed }
+
+ let set_lval env lval v = match fst lval with
+ | Cil_types.Var x ->
+ let var_abs_env = VarAbsEnv.upd x.Cil_types.vname v env.var_abs_env in
+ { env with var_abs_env }
+ | _ -> env
+
+ let top_vars env vars =
+ let f x var_abs_env = VarAbsEnv.upd x Domain.top var_abs_env in
+ let var_abs_env = Misc.String.Set.fold f vars env.var_abs_env in
+ { env with var_abs_env }
+
+ let bot =
+ { cost = AbsCost.bot ; var_abs_env = VarAbsEnv.bot ;
+ addressed = Misc.String.Set.empty ; requires = Requires.empty }
+
+ let join env1 env2 =
+ { cost = AbsCost.join (cost env1) (cost env2) ;
+ var_abs_env = VarAbsEnv.join (var_abs_env env1) (var_abs_env env2) ;
+ addressed = Misc.String.Set.union (addressed env1) (addressed env2) ;
+ requires = Requires.join (requires env1) (requires env2) }
+
+ let widen env1 env2 =
+ { cost = AbsCost.widen (cost env1) (cost env2) ;
+ var_abs_env = VarAbsEnv.widen (var_abs_env env1) (var_abs_env env2) ;
+ addressed = Misc.String.Set.union (addressed env1) (addressed env2) ;
+ requires = Requires.widen (requires env1) (requires env2) }
+
+ let narrow env1 env2 =
+ { cost = AbsCost.narrow (cost env1) (cost env2) ;
+ var_abs_env = VarAbsEnv.narrow (var_abs_env env1) (var_abs_env env2) ;
+ addressed = addressed env1 ;
+ requires = Requires.narrow (requires env1) (requires env2) }
+
+ let le env1 env2 =
+ (AbsCost.le (cost env1) (cost env2)) &&
+ (VarAbsEnv.le (var_abs_env env1) (var_abs_env env2)) &&
+ (Misc.String.Set.is_subset (addressed env1) (addressed env2)) &&
+ (Requires.le (requires env1) (requires env2))
+
+ let add_require env id require =
+ { env with requires = Requires.add id require (requires env) }
+
+ let to_string env =
+ let f_addressed x res = res ^ x ^ " " in
+ "Cost: " ^ (AbsCost.to_string (cost env)) ^ "\n" ^
+ "Var env:\n" ^ (VarAbsEnv.to_string (var_abs_env env)) ^
+ "Addressed: " ^ (Misc.String.Set.fold f_addressed (addressed env) "") ^
+ "\n" ^
+ "Requires:\n" ^ (Requires.to_string (requires env)) ^ "\n"
+
+end
+
+module MakePointsAbsEnv (AE : ABSENV) = struct
+
+ module AbsEnv = AE
+ module Domain = AbsEnv.Domain
+
+ type t =
+ { abs_env : AbsEnv.t IntCMap.t }
+
+ let empty = { abs_env = IntCMap.empty AbsEnv.bot }
+ let bot = empty
+
+ let abs_env env = env.abs_env
+
+ let find point env = IntCMap.find point env.abs_env
+
+ let add point abs_env env =
+ let abs_env = IntCMap.upd point abs_env env.abs_env in
+ { abs_env }
+
+ let le env1 env2 =
+ let cmp abs_env1 abs_env2 res = res && (AbsEnv.le abs_env1 abs_env2) in
+ IntCMap.cmp cmp (abs_env env1) (abs_env env2) true
+
+ let cost point env = AbsEnv.cost (find point env)
+
+ let requires point env = AbsEnv.requires (find point env)
+
+ let init start_point globals formals =
+ add start_point (AbsEnv.init globals formals) empty
+
+ let to_string env =
+ IntCMap.to_string string_of_int AbsEnv.to_string (abs_env env)
+
+ let widen env1 env2 =
+ let abs_env = IntCMap.merge AbsEnv.widen (abs_env env1) (abs_env env2) in
+ { abs_env }
+
+ let narrow env1 env2 =
+ let abs_env = IntCMap.merge AbsEnv.narrow (abs_env env1) (abs_env env2) in
+ { abs_env }
+
+ let set_cost id cost env = add id (AbsEnv.set_cost (find id env) cost) env
+
+end
+
+
+module PointsAbsEnv = struct
+
+ module D = Domain
+
+ module VAE = MakeVarAbsEnv (D)
+
+ module AE = MakeAbsEnv (VAE)
+
+ include MakePointsAbsEnv (AE)
+
+end
+
+module AbsEnv = PointsAbsEnv.AbsEnv
+
+
+(*** Dependent cost results ***)
+
+module LoopAnnotInfo = struct
+
+ type t =
+ { counter : string ;
+ relation : Domain.relation ;
+ init_value : Domain.t ;
+ exit_value : Domain.t ;
+ increment : Domain.t ;
+ last_value : Domain.t ;
+ cost_id : string ;
+ tmp_loop : string ;
+ iteration_nb : Domain.t ;
+ body_cost : AbsCost.t }
+
+ let counter loop_annot_info = loop_annot_info.counter
+
+ let relation loop_annot_info = loop_annot_info.relation
+
+ let init_value loop_annot_info = loop_annot_info.init_value
+
+ let exit_value loop_annot_info = loop_annot_info.exit_value
+
+ let increment loop_annot_info = loop_annot_info.increment
+
+ let last_value loop_annot_info = loop_annot_info.last_value
+
+ let cost_id loop_annot_info = loop_annot_info.cost_id
+
+ let tmp_loop loop_annot_info = loop_annot_info.tmp_loop
+
+ let iteration_nb loop_annot_info = loop_annot_info.iteration_nb
+
+ let body_cost loop_annot_info = loop_annot_info.body_cost
+
+ let make
+ counter relation init_value exit_value increment last_value cost_id
+ tmp_loop iteration_nb body_cost =
+ { counter ; relation ; init_value ; exit_value ; increment ; last_value ;
+ cost_id ; tmp_loop ; iteration_nb ; body_cost }
+
+end
+
+module LoopAnnot = struct
+
+ type t =
+ | Variant of Domain.t
+ | CounterMod of Domain.t * Domain.t
+ | CounterLastValue of
+ string * Domain.relation * Domain.t * Domain.t * Domain.t
+ | NoIteration of string * Domain.relation * Domain.t * Domain.t
+ | Cost of string * string * Domain.t * AbsCost.t
+
+ let reduce prototypes costs = function
+ | Cost (cost_id, tmp_loop, iteration_nb, body_cost) ->
+ let body_cost = AbsCost.reduce prototypes costs body_cost in
+ Cost (cost_id, tmp_loop, iteration_nb, body_cost)
+ | v -> v
+
+ let compare = Pervasives.compare
+
+ let variant_to_cil v =
+ if Domain.is_concrete v then Some (mk_variant (Domain.to_cil_term v))
+ else None
+
+ let counter_mod_to_cil v1 v2 =
+ if Domain.is_concrete v1 && Domain.is_concrete v2 then
+ if v1 = v2 then None
+ else
+ let v1 = Domain.to_cil_term v1 in
+ let v2 = Domain.to_cil_term v2 in
+ let invariant = Logic_const.prel (Cil_types.Req, v1, v2) in
+ Some (mk_invariant invariant)
+ else None
+
+ let counter_last_value_to_cil counter rel init_value exit_value last_value =
+ if Domain.is_concrete init_value &&
+ Domain.is_concrete exit_value &&
+ Domain.is_concrete last_value then
+ let init_value = Domain.to_cil_term init_value in
+ let exit_value = Domain.to_cil_term exit_value in
+ let last_value = Domain.to_cil_term last_value in
+ let rel' = Domain.cil_rel_of_rel rel in
+ let require = Logic_const.prel (rel', init_value, exit_value) in
+ let rel' = Domain.cil_rel_of_rel (Domain.mk_large rel) in
+ let counter = cil_logic_int_var counter in
+ let prop = Logic_const.prel (rel', counter, last_value) in
+ let invariant = Logic_const.pimplies (require, prop) in
+ Some (mk_invariant invariant)
+ else None
+
+ let no_iteration_to_cil counter rel init_value exit_value =
+ if Domain.is_concrete init_value && Domain.is_concrete exit_value then
+ let rel = Domain.opposite rel in
+ let rel' = Domain.cil_rel_of_rel rel in
+ let init_value = Domain.to_cil_term init_value in
+ let exit_value = Domain.to_cil_term exit_value in
+ let require = Logic_const.prel (rel', init_value, exit_value) in
+ let counter = cil_logic_int_var counter in
+ let prop = Logic_const.prel (Cil_types.Req, counter, init_value) in
+ let invariant = Logic_const.pimplies (require, prop) in
+ Some (mk_invariant invariant)
+ else None
+
+ let cost_to_cil cost_id tmp_loop iteration_nb body_cost =
+ if Domain.is_concrete iteration_nb && AbsCost.is_concrete body_cost then
+ let cost_var = cil_logic_int_var cost_id in
+ let body_cost = AbsCost.to_ext body_cost in
+ let loop_cost = Domain.mul iteration_nb body_cost in
+ let cost = Domain.add (Domain.of_var tmp_loop) loop_cost in
+ if Domain.is_concrete cost then
+ let cost = Domain.to_cil_term cost in
+ let invariant = Logic_const.prel (Cil_types.Rle, cost_var, cost) in
+ Some (mk_invariant invariant)
+ else None
+ else None
+
+ let to_cil = function
+ | Variant v -> variant_to_cil v
+ | CounterMod (v1, v2) -> counter_mod_to_cil v1 v2
+ | CounterLastValue(counter, rel, init_value, exit_value, last_value) ->
+ counter_last_value_to_cil counter rel init_value exit_value last_value
+ | NoIteration (counter, rel, init_value, exit_value) ->
+ no_iteration_to_cil counter rel init_value exit_value
+ | Cost (cost_id, tmp_loop, iteration_nb, body_cost) ->
+ cost_to_cil cost_id tmp_loop iteration_nb body_cost
+
+ let make_variant loop_annot_info =
+ let rel = LoopAnnotInfo.relation loop_annot_info in
+ let counter = LoopAnnotInfo.counter loop_annot_info in
+ let last_value = LoopAnnotInfo.last_value loop_annot_info in
+ let counter_var = Domain.of_var counter in
+ let (v1, v2) = match rel with
+ | Domain.Lt | Domain.Le -> (last_value, counter_var)
+ | Domain.Gt | Domain.Ge -> (counter_var, last_value) in
+ Variant (Domain.minus v1 v2)
+
+ let make_counter_mod loop_annot_info =
+ let counter = LoopAnnotInfo.counter loop_annot_info in
+ let init_value = LoopAnnotInfo.init_value loop_annot_info in
+ let increment = LoopAnnotInfo.increment loop_annot_info in
+ let mk_value value = Domain.modulo value (Domain.abs increment) in
+ let v1 = mk_value (Domain.of_var counter) in
+ let v2 = mk_value init_value in
+ CounterMod (v1, v2)
+
+ let make_counter_last_value loop_annot_info =
+ let counter = LoopAnnotInfo.counter loop_annot_info in
+ let rel = LoopAnnotInfo.relation loop_annot_info in
+ let init_value = LoopAnnotInfo.init_value loop_annot_info in
+ let exit_value = LoopAnnotInfo.exit_value loop_annot_info in
+ let last_value = LoopAnnotInfo.last_value loop_annot_info in
+ CounterLastValue (counter, rel, init_value, exit_value, last_value)
+
+ let make_no_iteration loop_annot_info =
+ let counter = LoopAnnotInfo.counter loop_annot_info in
+ let rel = LoopAnnotInfo.relation loop_annot_info in
+ let init_value = LoopAnnotInfo.init_value loop_annot_info in
+ let exit_value = LoopAnnotInfo.exit_value loop_annot_info in
+ NoIteration (counter, rel, init_value, exit_value)
+
+ let make_cost loop_annot_info =
+ let cost_id = LoopAnnotInfo.cost_id loop_annot_info in
+ let tmp_loop = LoopAnnotInfo.tmp_loop loop_annot_info in
+ let iteration_nb = LoopAnnotInfo.iteration_nb loop_annot_info in
+ let body_cost = LoopAnnotInfo.body_cost loop_annot_info in
+ Cost (cost_id, tmp_loop, iteration_nb, body_cost)
+
+end
+
+module LoopAnnots = struct
+
+ include Eset.Make (LoopAnnot)
+
+ let make loop_annot_info =
+ let variant = LoopAnnot.make_variant loop_annot_info in
+ (* let counter_mod = LoopAnnot.make_counter_mod loop_annot_info in *)
+ let counter_last_value =
+ LoopAnnot.make_counter_last_value loop_annot_info in
+ let no_iteration = LoopAnnot.make_no_iteration loop_annot_info in
+ let cost = LoopAnnot.make_cost loop_annot_info in
+ of_list [variant ; (* counter_mod ; *)
+ counter_last_value ; no_iteration ; cost]
+
+ let to_cil loop_annots =
+ let f loop_annot res = match LoopAnnot.to_cil loop_annot with
+ | Some loop_annot -> loop_annot :: res
+ | None -> res in
+ fold f loop_annots []
+
+ let reduce prototypes costs loop_annots =
+ let f loop_annot res =
+ add (LoopAnnot.reduce prototypes costs loop_annot) res in
+ fold f loop_annots empty
+
+end
+
+module LoopsAnnots = struct
+
+ type t = LoopAnnots.t IntMap.t
+
+ let empty = IntMap.empty
+
+ let mem = IntMap.mem
+
+ let find = IntMap.find
+
+ let add = IntMap.add
+
+ let to_cil loops_annots =
+ IntMap.map LoopAnnots.to_cil loops_annots
+
+ let reduce prototypes costs loops_annots =
+ IntMap.map (LoopAnnots.reduce prototypes costs) loops_annots
+
+end
+
+module CostInfo = struct
+
+ type t = { cost : AbsCost.t ; requires : Requires.t ;
+ loops_annots : LoopsAnnots.t }
+
+ let cost cost_info = cost_info.cost
+
+ let requires cost_info = cost_info.requires
+
+ let make cost requires loops_annots = { cost ; requires ; loops_annots }
+
+ let set_cost cost_info cost = { cost_info with cost }
+
+ let init cost =
+ { cost ; requires = Requires.empty ; loops_annots = LoopsAnnots.empty }
+
+ let loops_annots cost = cost.loops_annots
+
+ let mem_loop_annots id cost = LoopsAnnots.mem id (loops_annots cost)
+
+ let find_loop_annots id cost = LoopsAnnots.find id (loops_annots cost)
+
+ let to_string cost_info = AbsCost.to_string (cost cost_info)
+
+ let reduce_loops_annots prototypes costs cost_info =
+ let loops_annots =
+ LoopsAnnots.reduce prototypes costs cost_info.loops_annots in
+ { cost_info with loops_annots }
+
+ let replace_vars replacements cost_info =
+ let cost = AbsCost.replace_vars replacements (cost cost_info) in
+ let requires = Requires.replace_vars replacements (requires cost_info) in
+ { cost_info with cost ; requires }
+
+end
+
+module Costs = struct
+
+ type t = CostInfo.t Misc.String.Map.t
+
+ let empty = Misc.String.Map.empty
+
+ let init extern_costs =
+ let f fun_name cost costs =
+ let cost_info = CostInfo.init (AbsCost.of_extern cost) in
+ Misc.String.Map.add fun_name cost_info costs in
+ Misc.String.Map.fold f extern_costs empty
+
+ let mem = Misc.String.Map.mem
+
+ let add fun_name cost requires loops_annots costs =
+ Misc.String.Map.add fun_name
+ (CostInfo.make cost requires loops_annots) costs
+
+ let find_cost fun_name costs =
+ CostInfo.cost (Misc.String.Map.find fun_name costs)
+
+ let find_requires fun_name costs =
+ CostInfo.requires (Misc.String.Map.find fun_name costs)
+
+ let fun_costs = Misc.String.Map.map CostInfo.cost
+
+ let set_fun_costs costs fun_costs =
+ let f fun_name cost_info =
+ let cost =
+ if Misc.String.Map.mem fun_name fun_costs then
+ Misc.String.Map.find fun_name fun_costs
+ else CostInfo.cost cost_info in
+ CostInfo.set_cost cost_info cost in
+ Misc.String.Map.mapi f costs
+
+ let fold = Misc.String.Map.fold
+
+ let to_string costs =
+ let f fun_name cost_info res =
+ res ^ "\n" ^ fun_name ^ ": " ^ (CostInfo.to_string cost_info) in
+ fold f costs ""
+
+ let mem_loop_point fun_name id costs =
+ (Misc.String.Map.mem fun_name costs) &&
+ (CostInfo.mem_loop_annots id (Misc.String.Map.find fun_name costs))
+
+ let find_loop_annots fun_name id costs =
+ let error = Invalid_argument "Costs.find_loop_annotations" in
+ let fun_info = Misc.String.Map.error_find fun_name costs error in
+ CostInfo.find_loop_annots id fun_info
+
+ let reduce_loops_annots prototypes costs =
+ let fun_costs = fun_costs costs in
+ Misc.String.Map.map
+ (CostInfo.reduce_loops_annots prototypes fun_costs) costs
+
+ let restore_formals static_env costs =
+ let f fun_name cost_info =
+ if StaticEnv.mem_fun_name fun_name static_env then
+ let formals = StaticEnv.formals fun_name static_env in
+ let f (formal, tmp) = (tmp, Domain.of_var formal.Cil_types.vname) in
+ let replacements = Misc.String.Map.of_list (List.map f formals) in
+ CostInfo.replace_vars replacements cost_info
+ else cost_info in
+ Misc.String.Map.mapi f costs
+
+end
+
+
+(*** Abstract interpretation ***)
+
+module MakeAI (M : sig val static_env : StaticEnv.t end) = struct
+
+ let rec addressed e = match e.Cil_types.enode with
+ | Cil_types.Const _ | Cil_types.SizeOf _ | Cil_types.SizeOfStr _
+ | Cil_types.AlignOf _ ->
+ Misc.String.Set.empty
+ | Cil_types.Lval lval | Cil_types.AddrOf lval | Cil_types.StartOf lval ->
+ lval_addressed lval
+ | Cil_types.SizeOfE e | Cil_types.AlignOfE e | Cil_types.UnOp (_, e, _)
+ | Cil_types.CastE (_, e) | Cil_types.Info (e, _) -> addressed e
+ | Cil_types.BinOp (_, e1, e2, _) ->
+ Misc.String.Set.union (addressed e1) (addressed e2)
+
+ and lhost_addressed = function
+ | Cil_types.Var _ -> Misc.String.Set.empty
+ | Cil_types.Mem e -> addressed e
+
+ and offset_addressed = function
+ | Cil_types.Index (e, offset) ->
+ Misc.String.Set.union (addressed e) (offset_addressed offset)
+ | _ -> Misc.String.Set.empty
+
+ and lval_addressed (lhost, offset) =
+ Misc.String.Set.union (lhost_addressed lhost) (offset_addressed offset)
+
+ let branch abs_env _ = [abs_env ; abs_env]
+
+ let abs_fun_of_unop = function
+ | Cil_types.Neg -> Domain.neg
+ | _ -> (fun _ -> Domain.top)
+
+ let abs_fun_of_binop = function
+ | Cil_types.PlusA -> Domain.add
+ | Cil_types.MinusA -> Domain.minus
+ | Cil_types.Mult -> Domain.mul
+ | Cil_types.Div -> Domain.div
+ | Cil_types.Mod -> Domain.modulo
+ | _ -> (fun _ _ -> Domain.top)
+
+ let rec exp abs_env e = match e.Cil_types.enode with
+ | Cil_types.Const (Cil_types.CInt64 (i, _, _)) ->
+ Domain.of_int (My_bigint.to_int i)
+ | Cil_types.Lval (Cil_types.Var varinfo, _) ->
+ AbsEnv.find varinfo.Cil_types.vname abs_env
+ | Cil_types.Info (e, _) -> exp abs_env e
+ | Cil_types.UnOp (unop, e, _) ->
+ abs_fun_of_unop unop (exp abs_env e)
+ | Cil_types.BinOp (binop, e1, e2, _) ->
+ abs_fun_of_binop binop (exp abs_env e1) (exp abs_env e2)
+ | Cil_types.CastE (_, e) -> exp abs_env e (* TODO: may be incorrect *)
+ | _ -> Domain.top
+
+ let cost_incr_cost = function
+ | e :: _ ->
+ (match e.Cil_types.enode with
+ | Cil_types.Const (Cil_types.CInt64 (i, _, _)) ->
+ AbsCost.of_int (My_bigint.to_int i)
+ | _ -> AbsCost.top)
+ | _ -> AbsCost.top
+
+ let call_proc_cost fun_name abs_env sid f args =
+ let f_add_addrd addrd e = Misc.String.Set.union addrd (addressed e) in
+ let addrd = List.fold_left f_add_addrd Misc.String.Set.empty (f :: args) in
+ let abs_env = AbsEnv.add_addressed abs_env addrd in
+ let cost = match f.Cil_types.enode with
+ | Cil_types.Lval (Cil_types.Var var, _)
+ when var.Cil_types.vname = StaticEnv.cost_incr M.static_env ->
+ cost_incr_cost args
+ | Cil_types.Lval (Cil_types.Var var, _) ->
+ AbsCost.of_fun_call
+ fun_name sid var.Cil_types.vname (List.map (exp abs_env) args)
+ | _ -> AbsCost.top in
+ let vars_to_top =
+ Misc.String.Set.union (StaticEnv.globals M.static_env) addrd in
+ AbsEnv.add_cost (AbsEnv.top_vars abs_env vars_to_top) cost
+
+ (* Executing a goto may create a loop. We over-approximate its cost with a
+ Top. There is one exception though: Frama-C transforms programs so that
+ there is exactly one return statement that previous return statements in
+ the code point to with a goto. So if a goto leads to a return, the cost
+ remains the same; in other cases, it is Top. *)
+
+ let stmt_goto abs_env stmt = match stmt.Cil_types.skind with
+ | Cil_types.Return _ -> [abs_env]
+ | _ -> [AbsEnv.set_cost abs_env AbsCost.top]
+
+ let stmt fun_name abs_env stmt = match stmt.Cil_types.skind with
+ | Cil_types.Return _ -> []
+ | Cil_types.Break _ | Cil_types.Continue _
+ | Cil_types.Loop _ | Cil_types.Block _ | Cil_types.Switch _
+ | Cil_types.Instr (Cil_types.Skip _ | Cil_types.Code_annot _) -> [abs_env]
+ | Cil_types.Goto (stmt_ref, _) -> stmt_goto abs_env !stmt_ref
+ | Cil_types.UnspecifiedSequence l -> make_list (List.length l) abs_env
+ | Cil_types.If (e, _, _, _) -> branch abs_env e
+ | Cil_types.Instr (Cil_types.Set (lval, e, _)) ->
+ let addressed =
+ Misc.String.Set.union (lval_addressed lval) (addressed e) in
+ let v = exp abs_env e in
+ let abs_env = AbsEnv.add_addressed abs_env addressed in
+ [AbsEnv.set_lval abs_env lval v]
+ | Cil_types.Instr (Cil_types.Call (None, f, args, _)) ->
+ [call_proc_cost fun_name abs_env stmt.Cil_types.sid f args]
+ | Cil_types.Instr (Cil_types.Call (Some lval, f, args, _)) ->
+ let addressed = lval_addressed lval in
+ let abs_env = AbsEnv.add_addressed abs_env addressed in
+ let abs_env = call_proc_cost fun_name abs_env stmt.Cil_types.sid f args in
+ [AbsEnv.set_lval abs_env lval Domain.top]
+ | Cil_types.Instr (Cil_types.Asm _) -> raise ASM_unsupported
+ | Cil_types.TryFinally _ | Cil_types.TryExcept _ -> raise Try_unsupported
+
+ let merge_succ_regular points_abs_env abs_env stmt =
+ let id = stmt.Cil_types.sid in
+ let abs_env' = PointsAbsEnv.find id points_abs_env in
+ let abs_env' = AbsEnv.join abs_env abs_env' in
+ PointsAbsEnv.add id abs_env' points_abs_env
+
+ let merge_succ_uloop_start src_id points_abs_env abs_env =
+ let points_abs_env =
+ PointsAbsEnv.set_cost src_id AbsCost.top points_abs_env in
+ let abs_env = AbsEnv.set_cost abs_env (AbsCost.of_int 0) in
+ merge_succ_regular points_abs_env abs_env
+
+ let prev_init_and_cost fun_name counter points_abs_env prev_stmts =
+ let f (init_value, before_cost) (stmt_, pos) =
+ let abs_env = PointsAbsEnv.find (stmt_.Cil_types.sid) points_abs_env in
+ let abs_env = List.nth (stmt fun_name abs_env stmt_) pos in
+ let init_value = Domain.join init_value (AbsEnv.find counter abs_env) in
+ let before_cost = AbsCost.join before_cost (AbsEnv.cost abs_env) in
+ (init_value, before_cost) in
+ List.fold_left f (Domain.bot, AbsCost.bot) prev_stmts
+
+ let body_cost points_abs_env last_stmts =
+ (* Exiting a loop can only be done through a break or a goto or whatever,
+ but certainly not with a cost increment instruction. Thus, executing the
+ last statements of a loop should not change the cost information, so its
+ unnecessary when this is all we care about. *)
+ let f res stmt =
+ let id = stmt.Cil_types.sid in
+ AbsCost.join res (AbsEnv.cost (PointsAbsEnv.find id points_abs_env)) in
+ List.fold_left f AbsCost.bot last_stmts
+
+ let loop_cost fun_name id loop_info points_abs_env abs_env =
+ let cost_id = StaticEnv.cost_id M.static_env in
+ let tmp_loop = LoopInfo.tmp_loop loop_info in
+ let counter = LoopInfo.counter loop_info in
+ let relation = LoopInfo.relation loop_info in
+ let prev_stmts = LoopInfo.prev_stmts loop_info in
+ let last_stmts = LoopInfo.last_stmts loop_info in
+ let (init_value, before_cost) =
+ prev_init_and_cost fun_name counter points_abs_env prev_stmts in
+ let exit_value = exp abs_env (LoopInfo.exit_exp loop_info) in
+ let increment = exp abs_env (LoopInfo.increment loop_info) in
+ let last_value =
+ Domain.last_value relation init_value exit_value increment in
+ let iteration_nb = Domain.iteration_nb init_value counter increment in
+ let body_cost = body_cost points_abs_env last_stmts in
+ let loop_cost =
+ if AbsCost.is_top body_cost then AbsCost.top
+ else
+ AbsCost.of_loop_cost
+ fun_name id relation init_value exit_value increment
+ (AbsCost.extract body_cost) in
+ let succ_loop_cost = AbsCost.add before_cost loop_cost in
+ (counter, relation, init_value, exit_value, increment, last_value, cost_id,
+ tmp_loop, iteration_nb, body_cost, succ_loop_cost)
+
+ let merge_succ_loop_start
+ fun_name src_id loop_info points_abs_env points_abs_env' abs_env =
+ let src_abs_env = PointsAbsEnv.find src_id points_abs_env in
+ let (_, rel, init_value, exit_value, increment, _, _, _, _, _, _) =
+ loop_cost fun_name src_id loop_info points_abs_env src_abs_env in
+ let require = Require.make rel init_value exit_value increment in
+ let abs_env = AbsEnv.add_require abs_env src_id require in
+ merge_succ_uloop_start src_id points_abs_env' abs_env
+
+ let merge_succ_loop_exit
+ fun_name loop_start_id loop_info points_abs_env points_abs_env'
+ abs_env stmt =
+ let start_abs_env = PointsAbsEnv.find loop_start_id points_abs_env in
+ let (_, _, _, _, _, _, _, _, _, _, succ_loop_cost) =
+ loop_cost fun_name loop_start_id loop_info points_abs_env start_abs_env
+ in
+ let abs_env = AbsEnv.set_cost abs_env succ_loop_cost in
+ merge_succ_regular points_abs_env' abs_env stmt
+
+ let merge_succ_uloop_exit points_abs_env abs_env =
+ let abs_env = AbsEnv.set_cost abs_env AbsCost.top in
+ merge_succ_regular points_abs_env abs_env
+
+ let merge_succ fun_name src_id points_abs_env =
+ if StaticEnv.mem_point fun_name src_id M.static_env then
+ match StaticEnv.find_point fun_name src_id M.static_env with
+ | PointKind.RegularPoint -> merge_succ_regular
+ | PointKind.LoopStart loop_info ->
+ merge_succ_loop_start fun_name src_id loop_info points_abs_env
+ | PointKind.LoopExit loop_info ->
+ merge_succ_loop_exit fun_name src_id loop_info points_abs_env
+ | PointKind.ULoopStart -> merge_succ_uloop_start src_id
+ | PointKind.ULoopExit -> merge_succ_uloop_exit
+ else raise (Invalid_argument "AI.merge_succ")
+
+ let fundec_stmt fun_name points_abs_env points_abs_env' stmt_ =
+ let id = stmt_.Cil_types.sid in
+ let abs_env = PointsAbsEnv.find id points_abs_env in
+ let abs_envs = stmt fun_name abs_env stmt_ in
+ (* Otherwise the [stmt] function is not correct. *)
+ assert (List.length abs_envs = List.length stmt_.Cil_types.succs) ;
+ let f = merge_succ fun_name id points_abs_env in
+ List.fold_left2 f points_abs_env' abs_envs stmt_.Cil_types.succs
+
+ let rec fundec_stmts fun_name points_abs_env cmp merge stmts =
+ if !debug then
+ Printf.printf "%s\n%!" (PointsAbsEnv.to_string points_abs_env) ;
+ let f = fundec_stmt fun_name points_abs_env in
+ let points_abs_env' = List.fold_left f PointsAbsEnv.bot stmts in
+ let points_abs_env' = merge points_abs_env points_abs_env' in
+ if cmp points_abs_env' points_abs_env then
+ (if !debug then
+ Printf.printf "%s\n%!" (PointsAbsEnv.to_string points_abs_env') ;
+ points_abs_env')
+ else fundec_stmts fun_name points_abs_env' cmp merge stmts
+
+ let fundec_stmts_widen fun_name points_abs_env =
+ fundec_stmts fun_name points_abs_env PointsAbsEnv.le PointsAbsEnv.widen
+
+ let fundec_stmts_narrow fun_name points_abs_env =
+ let cmp env1 env2 = PointsAbsEnv.le env2 env1 in
+ fundec_stmts fun_name points_abs_env cmp PointsAbsEnv.narrow
+
+ let loop_annot_info fun_name id points_abs_env loop_info =
+ let abs_env = PointsAbsEnv.find id points_abs_env in
+ let (counter, relation, init_value, exit_value, last_value, increment,
+ cost_id, tmp_loop, iteration_nb, body_cost, _) =
+ loop_cost fun_name id loop_info points_abs_env abs_env in
+ LoopAnnotInfo.make
+ counter relation init_value exit_value last_value increment cost_id
+ tmp_loop.Cil_types.vname iteration_nb body_cost
+
+ let loop_annots fun_name points_abs_env id point_kind loops_annots =
+ match point_kind with
+ | PointKind.LoopStart loop_info ->
+ let loop_annot_info =
+ loop_annot_info fun_name id points_abs_env loop_info in
+ let loop_annots = LoopAnnots.make loop_annot_info in
+ LoopsAnnots.add id loop_annots loops_annots
+ | PointKind.ULoopStart ->
+ let loop_annots = LoopAnnots.empty in
+ LoopsAnnots.add id loop_annots loops_annots
+ | _ -> loops_annots
+
+ let loops_annots fun_name points_abs_env =
+ PointKinds.fold (loop_annots fun_name points_abs_env)
+ (StaticEnv.point_kinds fun_name M.static_env) LoopsAnnots.empty
+
+end
+
+
+(*** Dependent costs computation ***)
+
+class compute_costs widen narrow loops_annots static_env costs prj =
+object inherit Visitor.frama_c_copy prj as super
+
+ method vfunc fundec =
+ let fun_name = fundec.Cil_types.svar.Cil_types.vname in
+ if fun_name = StaticEnv.cost_incr static_env then begin
+ costs := Costs.add fun_name AbsCost.top Requires.empty
+ LoopsAnnots.empty !costs ;
+ Cil.SkipChildren end
+ else begin
+ (* The function should be in the static environment because of the
+ initializations. *)
+ assert (StaticEnv.mem_fun_name fun_name static_env) ;
+ let _ = match StaticEnv.start_and_end_points fun_name static_env with
+ | None ->
+ costs := Costs.add fun_name AbsCost.top Requires.empty
+ LoopsAnnots.empty !costs
+ | Some (start_point, end_point) ->
+ if !debug then Printf.printf "Interpreting %s\n%!" fun_name ;
+ let formals = StaticEnv.formals fun_name static_env in
+ let f_formals (varinfo, tmp) = (varinfo.Cil_types.vname, tmp) in
+ let globals = StaticEnv.globals static_env in
+ let formals = List.map f_formals formals in
+ let env = PointsAbsEnv.init start_point globals formals in
+ if !debug then Printf.printf "WIDEN\n%!" ;
+ let env = widen fun_name env fundec.Cil_types.sallstmts in
+ if !debug then Printf.printf "NARROW\n%!" ;
+ let env = narrow fun_name env fundec.Cil_types.sallstmts in
+ let cost = PointsAbsEnv.cost end_point env in
+ let requires = PointsAbsEnv.requires end_point env in
+ let loops_annots = loops_annots fun_name env in
+ (* The last instruction should be a return. Executing it shouldn't
+ change the environment. *)
+ costs := Costs.add fun_name cost requires loops_annots !costs in
+ Cil.SkipChildren end
+
+end
+
+let compute_costs static_env =
+ let module AI = MakeAI (struct let static_env = static_env end) in
+ let costs = ref (Costs.init (StaticEnv.extern_costs static_env)) in
+ let compute_costs_prj =
+ File.create_project_from_visitor
+ "compute_costs"
+ (new compute_costs AI.fundec_stmts_widen AI.fundec_stmts_narrow
+ AI.loops_annots static_env costs) in
+ let f () = !costs in
+ Project.on compute_costs_prj f ()
+
+
+(*** Costs solver ***)
+
+let solve_end costs1 costs2 =
+ let f fun_name cost res =
+ res && (Misc.String.Map.mem fun_name costs1) &&
+ (cost = Misc.String.Map.find fun_name costs1) in
+ Misc.String.Map.fold f costs2 true
+
+let string_of_fun_costs fun_costs =
+ let f fun_name cost res =
+ Printf.sprintf "%s%s: %s\n%!" res fun_name (AbsCost.to_string cost) in
+ Misc.String.Map.fold f fun_costs ""
+
+let solve_costs static_env costs =
+ let costs = Costs.restore_formals static_env costs in
+ let fun_costs = Costs.fun_costs costs in
+ let prototypes = StaticEnv.prototypes static_env in
+ let rec aux fun_costs =
+ if !debug then Printf.printf "%s\n%!" (string_of_fun_costs fun_costs) ;
+ let fun_costs' = AbsCost.reduces prototypes fun_costs in
+ if solve_end fun_costs fun_costs' then fun_costs
+ else aux fun_costs' in
+ let fun_costs = aux fun_costs in
+ let costs = Costs.set_fun_costs costs fun_costs in
+ Costs.reduce_loops_annots prototypes costs
+
+
+(*** Add annotations ***)
+
+let add_tmp_loop_init cost_varinfo tmp_loop stmt =
+ let lval = Cil.var tmp_loop in
+ let e =
+ Cil.new_exp dummy_location (Cil_types.Lval (Cil.var cost_varinfo)) in
+ let new_stmt =
+ Cil_types.Instr (Cil_types.Set (lval, e, dummy_location)) in
+ let new_stmt = Cil.mkStmt new_stmt in
+ Cil.mkStmt (Cil_types.Block (Cil.mkBlock [new_stmt ; stmt]))
+
+let make_tmp_formal_init fundec varinfo tmp_var =
+ let tmp_var = Cil.makeTempVar fundec ~name:tmp_var varinfo.Cil_types.vtype in
+ let lval = Cil.var tmp_var in
+ let e = Cil.new_exp dummy_location (Cil_types.Lval (Cil.var varinfo)) in
+ let new_stmt = Cil_types.Instr (Cil_types.Set (lval, e, dummy_location)) in
+ Cil.mkStmt new_stmt
+
+let make_tmp_formals_init fundec l =
+ let f (varinfo, tmp_var) = make_tmp_formal_init fundec varinfo tmp_var in
+ List.map f l
+
+let add_tmp_formals_init formals fundec =
+ let tmp_formals_init = make_tmp_formals_init fundec formals in
+ let block = tmp_formals_init @ fundec.Cil_types.sbody.Cil_types.bstmts in
+ let body = { fundec.Cil_types.sbody with Cil_types.bstmts = block } in
+ { fundec with Cil_types.sbody = body }
+
+let make_require require =
+ let rel = Require.relation require in
+ let init_value = Require.init_value require in
+ let exit_value = Require.exit_value require in
+ let increment = Require.increment require in
+ if Domain.is_concrete init_value &&
+ Domain.is_concrete exit_value &&
+ Domain.is_concrete increment then
+ let zero = Domain.of_int 0 in
+ let rel' = Domain.mk_strict rel in
+ let cil_init_value = Domain.to_cil_term init_value in
+ let cil_exit_value = Domain.to_cil_term exit_value in
+ let cil_zero = Domain.to_cil_term zero in
+ let cil_increment = Domain.to_cil_term increment in
+ let cil_rel = Domain.cil_rel_of_rel rel in
+ let cil_rel' = Domain.cil_rel_of_rel rel' in
+ let t1 = Logic_const.prel (cil_rel, cil_init_value, cil_exit_value) in
+ let t2 = Logic_const.prel (cil_rel', cil_zero, cil_increment) in
+ let t3 = Logic_const.pimplies (t1, t2) in
+ Some t3
+(*
+ if Domain.bool_of_cond rel' zero increment then None
+ else
+ if Domain.bool_of_cond (Domain.opposite rel) init_value exit_value then
+ None
+ else
+ if Domain.bool_of_cond rel init_value exit_value then Some t2
+ else Some t3
+*)
+ else None
+
+let make_requires requires =
+ let f require res =
+ let added_require = match make_require require with
+ | None -> []
+ | Some require -> [require] in
+ added_require @ res in
+ Requires.fold f requires []
+
+let add_spec pres post spec =
+ let requires = List.map Logic_const.new_predicate pres in
+ let post_cond = [(Cil_types.Normal, Logic_const.new_predicate post)] in
+ let new_behavior = Cil.mk_behavior ~requires ~post_cond () in
+ spec.Cil_types.spec_behavior <- new_behavior :: spec.Cil_types.spec_behavior
+
+let add_cost_annotation requires rel cost_id cost spec =
+ let post = mk_fun_cost_pred rel cost_id cost in
+ add_spec (make_requires requires) post spec ;
+ Cil.ChangeDoChildrenPost (spec, identity)
+
+let add_cost_incr_annotation cost_id fundec =
+ let rel = Cil_types.Req in
+ let cost =
+ Logic_const.tvar (Cil_const.make_logic_var "incr" Cil_types.Linteger) in
+ add_cost_annotation Requires.empty rel cost_id cost fundec
+
+let add_regular_fun_annotation cost_id requires cost spec =
+ if AbsCost.is_concrete cost then
+ let cost = AbsCost.to_ext cost in
+ let rel = Cil_types.Rle in
+ if Domain.is_concrete cost then
+ add_cost_annotation requires rel cost_id (Domain.to_cil_term cost) spec
+ else Cil.DoChildren
+ else Cil.DoChildren
+
+let add_fundec_annotation static_env costs fun_name spec =
+ assert (Costs.mem fun_name costs) ;
+ let cost = Costs.find_cost fun_name costs in
+ let requires = Costs.find_requires fun_name costs in
+ let cost_id = StaticEnv.cost_id static_env in
+ let cost_incr = StaticEnv.cost_incr static_env in
+ if fun_name = cost_incr then add_cost_incr_annotation cost_id spec
+ else add_regular_fun_annotation cost_id requires cost spec
+
+class add_annotations static_env costs prj =
+object (self) inherit Visitor.frama_c_copy prj as super
+
+ val mutable current_fun_name : string = ""
+
+ method vstmt_aux stmt = match stmt.Cil_types.skind with
+ | Cil_types.Loop _
+ when StaticEnv.mem_loop_start current_fun_name stmt.Cil_types.sid
+ static_env ->
+ let cost_varinfo = StaticEnv.cost_varinfo static_env in
+ (* only use with costs correctly set and initialized *)
+ assert (Costs.mem_loop_point current_fun_name stmt.Cil_types.sid costs) ;
+ let tmp_loop =
+ StaticEnv.find_tmp_loop current_fun_name stmt.Cil_types.sid
+ static_env in
+ let annots =
+ Costs.find_loop_annots current_fun_name stmt.Cil_types.sid costs in
+ add_loop_annots self stmt (LoopAnnots.to_cil annots) ;
+ let change = add_tmp_loop_init cost_varinfo tmp_loop in
+ Cil.ChangeDoChildrenPost (stmt, change)
+ | _ -> Cil.DoChildren
+
+ method vfunc fundec =
+ let fun_name = fundec.Cil_types.svar.Cil_types.vname in
+ current_fun_name <- fun_name ;
+ if fun_name = StaticEnv.cost_incr static_env then Cil.DoChildren
+ else
+ let formals = StaticEnv.formals fun_name static_env in
+ Cil.ChangeDoChildrenPost (fundec, add_tmp_formals_init formals)
+
+ method vspec spec = match self#current_kf with
+ | None -> Cil.JustCopy
+ | Some kf ->
+ match kf.Cil_types.fundec with
+ | Cil_types.Definition (fundec, _) ->
+ let fun_name = fundec.Cil_types.svar.Cil_types.vname in
+ add_fundec_annotation static_env costs fun_name spec
+ | Cil_types.Declaration (_, f, _, _) ->
+ let fun_name = f.Cil_types.vname in
+ add_fundec_annotation static_env costs fun_name spec
+
+end
+
+let add_annotations static_env costs =
+ let add_annotations_prj =
+ File.create_project_from_visitor
+ "add_annotations" (new add_annotations static_env costs) in
+ let f () =
+ Kernel.CodeOutput.set (StaticEnv.fname static_env) ;
+ File.pretty_ast () in
+ Project.on add_annotations_prj f ()
+
+
+(*** Save results ***)
+
+let save_results static_env costs =
+ let fname = StaticEnv.f_old_name static_env in
+ let f fun_name cost_info res =
+ let cost = CostInfo.cost cost_info in
+ res ^
+ (if AbsCost.is_concrete cost then
+ fun_name ^ " " ^ (Domain.to_string (AbsCost.to_ext cost)) ^ "\n"
+ else "") in
+ let s = Costs.fold f costs "" in
+ let save_file =
+ try Filename.chop_extension fname
+ with Invalid_argument "Filename.chop_extension" -> fname in
+ let save_file = save_file ^ ".cost_results" in
+ try
+ let oc = open_out save_file in
+ output_string oc s ;
+ close_out oc
+ with Sys_error _ ->
+ Printf.eprintf "Could not save plug-in results in file %s.\n%!" save_file
+
+
+(*** Main ***)
+
+let cost ((fname, _), f_old_name, {Cerco.cost_id = cost_id;
+ cost_incr = cost_incr;
+ extern_costs = extern_costs} , _) =
+ try
+ Kernel.Files.set [fname] ;
+ File.init_from_cmdline () ;
+ if !debug then Printf.printf "Make CFG\n%!" ;
+ make_CFG () ;
+ if !debug then print_CFG () ;
+ if !debug then Printf.printf "Initialize\n%!" ;
+ let static_env =
+ initialize "__tmp" fname f_old_name cost_id cost_incr extern_costs in
+ if !debug then Printf.printf "Compute costs\n%!" ;
+ let costs = compute_costs static_env in
+ if !debug then Printf.printf "%s\n%!" (Costs.to_string costs) ;
+ if !debug then Printf.printf "Solve costs\n%!" ;
+ let costs = solve_costs static_env costs in
+ if !debug then Printf.printf "Costs:\n%s\n%!" (Costs.to_string costs) ;
+ if !debug then Printf.printf "Save results\n%!" ;
+ save_results static_env costs ;
+ if !debug then Printf.printf "Add annotations\n%!" ;
+ add_annotations static_env costs
+ with e -> Printf.eprintf "** ERROR: %s.\n%!" (string_of_exception e)
--- /dev/null
+
+open Parameters
+open Cil_types
+open Simplify_terms
+module Varinfo = Cil_datatype.Varinfo
+module Logic_var = Cil_datatype.Logic_var
+module Stmt = Cil_datatype.Stmt
+module Term = Cil_datatype.Term
+module Logic_label = Cil_datatype.Logic_label
+
+(** This module defines the main analysis of the plug-in. Its actions are:
+ - build the CFG of the program;
+ - compute the cost of each function depending on the costs of the others
+ at the same time add the needed invariant and at the cost of each function
+*)
+
+
+(*** Helpers ***)
+
+let identity x = x
+
+let string_of_list sep f l =
+ let rec aux = function
+ | [] -> ""
+ | [e] -> f e
+ | e :: l -> (f e) ^ sep ^ (aux l) in
+ aux l
+
+let integer_term term = Logic_const.term term Linteger
+
+let tinteger i =
+ let cint64 = CInt64 (My_bigint.of_int i, IInt, None) in
+ let iterm = TConst cint64 in
+ integer_term iterm
+
+let cil_logic_int_var x =
+ Logic_const.tvar (Cil_const.make_logic_var x Linteger)
+
+let current_kf obj = match obj#current_kf with
+ | None -> raise (Failure "Compute.current_kf")
+ | Some kf -> kf
+
+let add_loop_annot obj stmt annot =
+ let annot = User annot in
+ let kf =
+ Cil.get_original_kernel_function (Cil.copy_visit ()) (current_kf obj) in
+ Queue.add (fun () -> Annotations.add kf stmt [Ast.self] annot)
+ obj#get_filling_actions
+
+let add_loop_annots obj stmt annots = List.iter (add_loop_annot obj stmt) annots
+
+let mk_invariant pred =
+ Logic_const.new_code_annotation (AInvariant ([], true, pred))
+
+let mk_variant term =
+ Logic_const.new_code_annotation (AVariant (term, None))
+
+let mk_fun_cost_pred rel cost_id cost =
+ let cost_var = Cil_const.make_logic_var cost_id Linteger in
+ let cost_var = Logic_const.tvar cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let new_cost = TBinOp (PlusA, old_cost, cost) in
+ let new_cost = integer_term new_cost in
+ Logic_const.prel (rel, cost_var, new_cost)
+
+let rec exp_is_var name e = match (remove_casts e).enode with
+ | Lval (Var v, _) -> v.vname = name
+ | Info (e, _) -> exp_is_var name e
+ | _ -> false
+
+let has_fun_type varinfo = match varinfo.vtype with
+ | TFun _ -> true
+ | _ -> false
+
+let formals_of_varinfo varinfo = match varinfo.vtype with
+ | TFun (_, args, _, _) ->
+ List.map (fun (x, t, _) -> Cil.makeVarinfo false true x t)
+ (Cil.argsToList args)
+ | _ -> assert false (* do not use on these arguments *)
+
+let dummy_location = (Lexing.dummy_pos, Lexing.dummy_pos)
+
+let dummy_varinfo = Cil.makeVarinfo false false "" (TVoid [])
+
+let make_list n a =
+ let rec aux acc i = if i >= n then acc else aux (a :: acc) (i+1) in
+ aux [] 0
+
+let rec stmt_subs stmt =
+ let added = match stmt.skind with
+ | If (_, block1, block2, _)
+ | TryFinally (block1, block2, _)
+ | TryExcept (block1, _, block2, _) ->
+ (block_subs block1) @ (block_subs block2)
+ | Switch (_, block, _, _)
+ | Loop (_, block, _, _, _)
+ | Block block -> block_subs block
+ | UnspecifiedSequence l ->
+ List.map (fun (stmt, _, _, _, _) -> stmt) l
+ | _ -> [] in
+ stmt :: added
+
+and block_subs block = List.flatten (List.map stmt_subs block.bstmts)
+
+let rec first_stmt block = match block.bstmts with
+ | [] -> None
+ | stmt :: _ -> match stmt.skind with
+ | Block block -> first_stmt block
+ | _ -> Some stmt
+
+let stmt_is_break stmt = match stmt.skind with
+ | Break _ -> true
+ | _ -> false
+
+let starts_with_break block = match first_stmt block with
+ | Some stmt ->
+ (match stmt.skind with
+ | Goto (stmt_ref, _) -> stmt_is_break !stmt_ref
+ | _ -> stmt_is_break stmt)
+ | _ -> false
+
+let rec last = function
+ | [] -> None
+ | [e] -> Some e
+ | _ :: l -> last l
+
+let rec last_stmt block = match last block.bstmts with
+ | None -> None
+ | Some stmt -> match stmt.skind with
+ | Block block -> last_stmt block
+ | _ -> Some stmt
+
+class print_CFG = object inherit Visitor.frama_c_inplace as super
+
+ method vfunc func =
+ Format.printf "*** %s ***\n\n%!" func.svar.vname ;
+ List.iter
+ (fun stmt ->
+ Format.printf "%d: %a\n--> %!" stmt.sid Cil.d_stmt stmt ;
+ List.iter (fun stmt -> Format.printf "%d %!" stmt.sid)
+ stmt.succs ;
+ Format.printf "\n\n%!")
+ func.sallstmts ;
+ Format.printf "\n\n%!" ;
+ Cil.SkipChildren
+
+end
+
+let print_CFG () =
+ Visitor.visitFramacFile (new print_CFG) (Ast.get ())
+
+(*** Make CFG ***)
+
+class make_CFG = object inherit Visitor.frama_c_inplace as super
+
+ method vfile file =
+ Cfg.clearFileCFG ~clear_id:false file ;
+ Cfg.computeFileCFG file ;
+ Cil.SkipChildren
+
+end
+
+let make_CFG () =
+ Visitor.visitFramacFile (new make_CFG) (Ast.get ())
+
+(** Extract variant *)
+
+let rec extract_added_value counter e = match e.enode with
+ | BinOp (PlusA, e1, e2, _) when exp_is_var counter e1 ->
+ Some (counter, e2)
+ | BinOp (MinusA, e1, e2, typ)
+ when exp_is_var counter e1 ->
+ let enode = UnOp (Neg, e2, typ) in
+ let e2 = { e2 with enode = enode } in
+ Some (counter, e2)
+ | CastE (_, e) -> extract_added_value counter e
+ | _ ->
+ if !debug then
+ Format.printf
+ "Could not find added increment value for counter %s in %a.\n%!"
+ counter Cil.d_exp e ;
+ None
+
+let extract_increment block =
+ let open Misc.Option in
+ last_stmt block >>=
+ (fun stmt -> match stmt.skind with
+ | Instr (Set ((Var v, _), e, _)) ->
+ extract_added_value v.vname e
+ | _ ->
+ if !debug then
+ Format.printf
+ "Could not find increment instruction; found %a instead.\n%!"
+ Cil.d_stmt stmt ;
+ None)
+
+let gen_variant counter rel guard increment =
+ let counter = term_of_exp counter in
+ let guard = term_of_exp guard in
+ let increment = term_of_exp increment in
+ let guard = match rel with
+ | Lt | Gt | Ne -> guard
+ | Le | Ge | Eq -> make_binop PlusA (Cil.lconstant My_bigint.one) guard
+ | _ -> assert false (* not implemented TODO be gentle *) in
+ let variant = make_binop MinusA guard counter in
+ let variant =
+ if no_division_in_generated_variant
+ then make_binop Mult variant (make_sign increment)
+ else make_binop Div variant increment in
+ simplify_term variant
+
+let opposite = function
+ | Lt -> Gt
+ | Gt -> Lt
+ | Le -> Ge
+ | Ge -> Le
+ | Eq -> Eq
+ | Ne -> Ne
+ | _ -> assert false (* not implemented TODO be gentle *)
+
+
+let extract_guard block (counter, increment) =
+ let open Misc.Option in
+ first_stmt block >>=
+ (fun stmt -> match stmt.skind with
+ | If (e, _, block, _) when starts_with_break block ->
+ (match e.enode with
+ | BinOp (rel, e1, e2, _)
+ when exp_is_var counter e1 (* && Domain.is_supported_rel rel *) ->
+ (*Some (counter, rel, e2, increment)*)
+ Some (gen_variant e1 rel e2 increment)
+ | BinOp (rel, e1, e2, _)
+ when exp_is_var counter e2 (* && Domain.is_supported_rel rel *) ->
+ (* let rel = rel in *)
+ (* let rel = Domain.opposite rel in *)
+ (* Some (counter, rel, e1, increment) *)
+ let rel = opposite rel in
+ Some (gen_variant e2 rel e1 increment)
+ | _ ->
+ if !debug then
+ Format.printf "Unsupported guard condition %a on counter %s.\n%!"
+ Cil.d_exp e counter ;
+ None)
+ | If (_, _, block, _) ->
+ if !debug then
+ Format.printf "Loop not guarded by a break:\n%a\n%!" Cil.d_block block ;
+ None
+ | _ ->
+ if !debug then Format.printf "Loop not guarded:\n%a\n%!" Cil.d_stmt stmt ;
+ None)
+
+let extract_variant body =
+ let open Misc.Option in
+ extract_increment body >>= extract_guard body
+
+let rec find_variant = function
+ | [] -> None
+ | {annot_content = AVariant (t,_)}::_ -> Some t
+ | _::l -> find_variant l
+
+
+(** Function computing cost of special instruction *)
+
+type env =
+ { env_fun_cost : term Varinfo.Hashtbl.t;
+ env_cost_incr_name : string; (* TODO put the varinfo *)
+ env_cost_var : logic_var;
+ mutable env_loop_name : unit -> string;
+ }
+
+let init_loop_name env file =
+ let i = ref 0 in
+ let f () =
+ incr i;
+ Format.sprintf "__cost_%s_loop_%i" file !i in
+ env.env_loop_name <- f
+
+let dumb_env_loop_name () : string = assert false
+
+let linteger t = Logic_const.term t Linteger
+
+(** Create a function which compute the cost of a loop.
+It uses the variant as the strictly decreasing positive argument.
+The cost depend of the other arguments \vec x.
+
+\bcost if the cost of the body of the loop (must be always positive!)
+\phi compute the modification of \vec x by one turn of the loop
+
+f(v,\vec x) =
+ if v < 0 then 0
+ else (f(v-1,\phi(\vec x)) + \bcost(\vec x))
+
+It also create some needed lemmas:
+ - f is always positive
+
+or simplifying lemmas:
+ - simpler (eg. algebraic) formulation of f:
+ * \vec x = \empty, \phi = identity, \bcost = c >= 0
+ f(v) = c (v + 1)
+ * \phi = identity
+ f(v,\vec x) = \bcost(\vec x) * (v + 1)
+ * \phi(\vec x) = x_1 + 1,x_2,...,x_n
+ \bcost(\vec x) = max(c x_1,0) + \phi(x_2,...,x_n)
+ \phi(x_2,...,x_n) >= 0, c >= 0
+ f(v,\vec x) = \phi(x_2,...,x_n) (v + 1)
+ + c * [y(y+1) - (max(y-v-1,0)(y-v)]/2
+*)
+let create_fun_loop env dep bcost =
+ let v = Cil_const.make_logic_var "v" Linteger in
+ let tv = Logic_const.tvar v in
+ let xargs = List.map fst dep in (** \vec x *)
+ let mod_dep = List.map snd dep in (** \phi *)
+ let args = v::xargs in
+ let targs = List.map Logic_const.tvar args in
+ (** The function *)
+ let signature = Larrow (List.map (fun _ -> Linteger) args, Linteger) in
+ let new_loop_name = env.env_loop_name () in
+ let li = { l_var_info = Cil_const.make_logic_var new_loop_name signature;
+ l_labels = [];
+ l_tparams = [];
+ l_type = Some Linteger;
+ l_profile = args;
+ l_body = LBnone (* temporary *) } in
+ let lzero = Cil.lzero () in
+ let tvminusone =
+ linteger (TBinOp(MinusA, tv, Cil.lconstant (My_bigint.one))) in
+ (* let body = linteger (Tapp(li,[],tvminusone::mod_dep)) in *)
+ let body = linteger (tapp li (tvminusone::mod_dep)) in
+ let body = linteger (TBinOp(PlusA, body, bcost)) in
+ let body =
+ Tif(linteger (TBinOp(Lt, tv, lzero)), lzero, body) in
+ li.l_body <- LBterm (linteger body);
+ (** Axiom positive *)
+ let lemma = Logic_const.unamed
+ (Pforall(args,
+ Logic_const.unamed
+ (Prel (Rge, linteger (Tapp(li, [], targs)), lzero)))) in
+ let lemma = Dlemma (new_loop_name ^ "_is_positive", false, [], [], lemma,
+ Cil_datatype.Location.unknown) in
+ (** Register them as global (in reverse order) *)
+ Globals.Annotations.add_generated lemma;
+ Globals.Annotations.add_generated
+ (Dfun_or_pred (li, Cil_datatype.Location.unknown));
+ li
+
+(** TODO: extend it to some more interesting cases *)
+let cost_loop_term_simple env kern_fun stmt lab_before_loop variant cost_body =
+ (** The number of iteration is bounded by the variant + 1, because
+ the variant must be positive at the *start* of an iteration *)
+ let variant = make_binop PlusA variant (Cil.lconstant (My_bigint.one)) in
+ (** Simple version, just do the multiplication *)
+ let nbr_iteration = make_at lab_before_loop variant in
+ (** the nbr_iteration must be positive *)
+ let nbr_iteration = make_max nbr_iteration (Cil.lzero ()) in
+ let sum = make_binop Mult nbr_iteration cost_body in
+
+ (** make the cost invariant of the loop *)
+ let remaining_nbr_iteration = make_max variant (Cil.lzero ()) in
+ (** ensures cost <= \old(cost) +
+ ([nbr_iteration]-[remaining_nbr_iteration]) * [cost_body] *)
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = make_at lab_before_loop cost_var in
+ let cost_iterations =
+ make_binop Mult
+ (make_binop MinusA nbr_iteration remaining_nbr_iteration)
+ cost_body in
+ let new_cost = make_binop PlusA old_cost cost_iterations in
+ let new_cost = simplify_term new_cost in
+ let invariant = Logic_const.prel (Rle, cost_var, new_cost) in
+ let annot =
+ Logic_const.new_code_annotation
+ (AInvariant ([time_cost_behavior],true,invariant)) in
+ Annotations.add kern_fun stmt [Ast.self] (User annot);
+ sum
+
+let cost_loop_term_complexe
+ env kern_fun stmt lab_before_loop variant deps cost_body =
+ (** the nbr_iteration must be positive *)
+ let variant = make_max variant (Cil.lzero ()) in
+ let args = List.map fst deps in (** \phi *)
+ let targs = List.map Logic_const.tvar args in
+ let fl = create_fun_loop env deps cost_body in
+ let app = linteger (tapp fl (variant::targs)) in
+ let sum = make_at lab_before_loop app in
+
+ (** make the cost invariant of the loop *)
+ (** ensures cost <= \old(cost) +
+ ([nbr_iteration]-[remaining_nbr_iteration]) * [cost_body] *)
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = make_at lab_before_loop cost_var in
+ let cost_iterations = make_binop MinusA sum app in
+ let new_cost = make_binop PlusA old_cost cost_iterations in
+ let new_cost = simplify_term new_cost in
+ let invariant = Logic_const.prel (Rle, cost_var, new_cost) in
+ let annot =
+ Logic_const.new_code_annotation
+ (AInvariant ([time_cost_behavior],true,invariant)) in
+ Annotations.add kern_fun stmt [Ast.self] (User annot);
+ sum
+
+let cost_loop_term env kern_fun stmt lab_before_loop variant deps cost_body =
+(*
+ let const_during_loop = List.for_all (fun (_,_) -> (** TODO *) false) deps in
+ if const_during_loop
+ then cost_loop_term_simple env kern_fun stmt lab_before_loop variant cost_body
+ else cost_loop_term_complexe
+ env kern_fun stmt lab_before_loop variant deps cost_body
+*)
+ let cost_body = simplify_term cost_body in
+ match cost_body.term_node with
+ | TConst _ ->
+ cost_loop_term_simple env kern_fun stmt lab_before_loop variant cost_body
+ | _ ->
+ cost_loop_term_complexe
+ env kern_fun stmt lab_before_loop variant deps cost_body
+
+
+(** computing cost of fundec which contain a call to funvar *)
+let cost_of_fun_call env funvar args =
+ (** can't fail since we use the callgraph *)
+ let cost = Varinfo.Hashtbl.find env.env_fun_cost funvar in
+ (* match cost.term_node with *)
+ (* | TConst (CInt64 (_,_,_)) -> cost *)
+ (* | _ -> *)
+ (** arguments of the function *)
+ let formals = Cil.getFormalsDecl funvar in
+(* (** The real arguments are binded using a let and the formal argument are
+ replaced by fresh variable *)
+ let letvars = List.map
+ (fun vi -> Cil.make_temp_logic_var (Ctype vi.vtype))
+ formals in
+ let subst = List.fold_left2 (fun map vi v ->
+ Varinfo.Map.add vi v map) Varinfo.Map.empty formals letvars in
+ let cost =
+ Visitor.visitFramacTerm (new subst_lval subst (Project.current ()))
+ cost in
+ let cost = List.fold_left2 (fun tlet v arg ->
+ let logic_info = { l_var_info = v; l_type = None; l_tparams = [];
+ l_labels = []; l_profile = [];
+ l_body = LBnone; } in
+ let arg = term_of_exp arg in
+ let tlet =
+ Logic_const.term (Tlet (logic_info, arg))
+ tlet.term_type in
+ tlet)
+ cost letvars args in*)
+ let subst = List.fold_left2 (fun map vi arg ->
+ try
+ Varinfo.Map.add vi (term_of_exp arg) map
+ with Untranslatable_expr _ -> map (** TODO verify that this formal doesn't
+ appear in the cost of the function *)
+ ) Varinfo.Map.empty formals args in
+ let cost = remove_logic_label Logic_const.pre_label cost in
+ let cost =
+ Visitor.visitFramacTerm (new subst_lval subst (Project.current ()))
+ cost in
+ cost
+
+(** Compute the "wp" of a stmt, in fact just make some substitution *)
+let stmt_wp stmt term =
+ (** try to propagate \at(i,Label) *)
+ match stmt.skind with
+ | Instr (Set ((Var vi,_),e,_)) ->
+ begin
+ try
+ let t = term_of_exp e in
+ let subst = Varinfo.Map.singleton vi t in
+ let term =
+ Visitor.visitFramacTerm
+ (new subst_with_label stmt subst (Project.current ()))
+ term in
+ term
+ with exn ->
+ if !debug then Format.eprintf "can't convert exp %a to term: %a.@."
+ Cil.defaultCilPrinter#pExp e print_exception exn;
+ term
+ end
+ | _ -> term
+
+let rec stmts_wp bad_stmts stop_stmts stmt term =
+ if !debug then
+ Format.printf "stmts_wp sid: %i,@ bad_stmts: %a,@ stop_stmts: %a,@\n"
+ stmt.sid
+ Stmt.Set.pretty bad_stmts
+ Stmt.Set.pretty stop_stmts;
+ (** statement in last statement *)
+ if Stmt.Set.mem stmt stop_stmts
+ then Some term
+ else if Stmt.Set.mem stmt bad_stmts
+ then None
+ else
+ (** successors *)
+ let succs_bad_stmts =
+ match stmt.skind with
+ | Loop (_,_,_,_,_) -> Stmt.Set.add stmt bad_stmts
+ | _ -> bad_stmts in
+ (** Cost of the successors of the instruction *)
+ let cost_succs =
+ stmts_wp_succs succs_bad_stmts stop_stmts stmt.succs term in
+ match cost_succs with
+ | [] -> None (** can't go in a good state so count nothing *)
+ | (a::l) -> (** TODO take care of conditions *)
+ assert (l = []);
+ let a' = stmt_wp stmt a in
+ if !debug then
+ Format.printf "[WP]stmt:@,%a@.a:@,%a@.a':@,%a@."
+ Cil.defaultCilPrinter#pStmt stmt
+ Cil.defaultCilPrinter#pTerm a
+ Cil.defaultCilPrinter#pTerm a';
+ Some a'
+
+and stmts_wp_succs bad_stmts stop_stmts stmts term =
+ let fold acc stmt =
+ match stmts_wp bad_stmts stop_stmts stmt term with
+ | None -> acc
+ | Some t -> t::acc in
+ List.fold_left fold [] stmts
+
+
+(** We go through the cfg we assume that:
+ - all functions called have a cost already computed
+ - no implicit loop (goto), all are explicit Loop
+ - all loops have an invariant (given by the user or previously computed for
+ for-loops)
+
+ We iterate on the cfg except when arriving on a loop where we compute the
+ body alone and after that go to the next statements (the break statement)
+
+ break_statement in which statement to stop the sum (for loop)
+ *)
+
+
+let rec find_variant = function
+ | [] -> None
+ | {annot_content = AVariant (t,_)}::_ -> Some t
+ | _::l -> find_variant l
+
+(** TODO: cache the statement already done after if-then-else
+ (otherwise exponential) *)
+(** return None if no path arrive to a good_statement or don't go through
+ a bad_statetement *)
+let rec cfg_sum env kern_fun bad_stmts stop_stmts stmt =
+ if !debug then
+ Format.printf "sid: %i,@ bad_stmts: %a,@ stop_stmts: %a,@\n"
+ stmt.sid
+ Stmt.Set.pretty bad_stmts
+ Stmt.Set.pretty stop_stmts;
+ (** statement in last statement *)
+ if Stmt.Set.mem stmt stop_stmts
+ then Some (Cil.lzero ())
+ else if Stmt.Set.mem stmt bad_stmts
+ then None
+ else
+ (** successors *)
+ let succs_bad_stmts =
+ match stmt.skind with
+ | Loop (_,_,_,_,_) -> Stmt.Set.add stmt bad_stmts
+ | _ -> bad_stmts in
+ (** Cost of the successors of the instruction *)
+ let cost_succs =
+ cfg_sum_succs env kern_fun succs_bad_stmts stop_stmts
+ stmt.succs in
+ match cost_succs with
+ | None -> None (** can't go in a good state so count nothing *)
+ | Some cost_succs ->
+ (** Cost of the instruction *)
+ let cost_instr =
+ match stmt.skind with
+ (* (\** call to cost_incr *\) *) (** cost_incr is an usual function *)
+ (* | Instr *)
+ (* (Call (None, *)
+ (* { enode = *)
+ (* Lval (Var var, _)} , *)
+ (* [cost], _)) *)
+ (* when var.vname = env.env_cost_incr_name -> *)
+ (* term_of_cost_expr cost *)
+ (** function call *)
+ | Instr
+ (Call (_, { enode =
+ Lval (Var var, _)},
+ args,_)) ->
+ cost_of_fun_call env var args
+ (** loops *)
+ | Loop (_,body,_,_,_) ->
+ cost_loop env kern_fun bad_stmts stop_stmts stmt body
+ | _ -> Cil.lzero () in
+ (** normalize the cost of the instruction regarding the labels *)
+ let labels = NormAtLabels.labels_stmt_pre stmt in
+ let cost_instr = NormAtLabels.preproc_annot_term labels cost_instr in
+ let cost_succs = stmt_wp stmt cost_succs in
+ let sum = make_binop PlusA cost_instr cost_succs in
+ (** remove the at that point to this statement we don't know the value at
+ this point perhaps we will know before ( use Here?? ) *)
+ let sum =
+ Visitor.visitFramacTerm
+ (new remove_stmt_label stmt (Project.current ()))
+ sum in
+ if !debug then
+ Format.printf "Stmt %i sum=%a@."
+ stmt.sid Term.pretty sum;
+ Some sum
+
+and cfg_sum_succs env kern_fun bad_stmts stop_stmts stmts =
+ let fold cost stmt =
+ let cost_succ = cfg_sum env kern_fun bad_stmts stop_stmts stmt in
+ make_max_opt cost cost_succ in
+ List.fold_left fold None stmts
+
+and cost_loop env kern_fun bad_stmts stop_stmts stmt body =
+ (** the first one perhaps not needed *)
+ let bad_stmts = Stmt.Set.union bad_stmts stop_stmts in
+ let stop_stmts = Stmt.Set.singleton stmt in
+ let cost_body =
+ cfg_sum_succs env kern_fun bad_stmts stop_stmts stmt.succs in
+ let cost_body = match cost_body with
+ | None -> (* no cycle in fact *) Cil.lzero ()
+ | Some cost -> simplify_term cost in
+ (** compute free variable and compute their modification by the loop body *)
+ let deps = freevar Logic_var.Set.empty cost_body in
+ let deps =
+ let fold e acc =
+ let result =
+ stmts_wp_succs bad_stmts stop_stmts stmt.succs (Logic_const.tvar e) in
+ match result with
+ | [] -> assert false (** No cycle? impossible it find one before *)
+ | t::l ->
+ assert (l = []); (* TODO *)
+ (e, t)::acc in
+ Logic_var.Set.fold fold deps [] in
+ (** this stmt is the continue *)
+ let annots = Annotations.get_filter Logic_utils.is_variant stmt in
+ let variant = match annots with
+ | [] -> (** TODO put it somewhere else *)
+ begin match extract_variant body with
+ | None ->
+ Format.printf
+ "Can't@ compute@ cost@ without@ variant@ for@ statement:@,%a@."
+ Stmt.pretty stmt; exit 1
+ | Some variant ->
+ let annot =
+ Logic_const.new_code_annotation (AVariant (variant,None)) in
+ Annotations.add kern_fun stmt [Ast.self] (User annot);
+ variant end
+ | ( User { annot_content =
+ AVariant (v,_) }
+ | AI (_, { annot_content =
+ AVariant (v,_) }) (** usefule case ? *)
+ )
+ :: _ ->
+ let v = NormAtLabels.preproc_annot_term
+ (NormAtLabels.labels_loop_inv stmt) v in
+ let v = remove_logic_label Logic_const.here_label v in
+ v
+ | _ -> assert false (* result of the filter *)
+ in
+ if stmt.labels = [] then
+ stmt.labels <- (** ugly but... *)
+ Label("__stmt_"^(string_of_int stmt.sid),Cil.builtinLoc,false)::
+ stmt.labels;
+ let label_before_loop = StmtLabel (ref stmt) in
+ cost_loop_term env kern_fun stmt label_before_loop variant deps cost_body
+
+let make_leq_cost env sum =
+ (** ensures cost <= \old(cost) + [sum] *)
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let new_cost = Logic_const.term
+ (Cil_types.TBinOp (Cil_types.PlusA, old_cost, sum)) Linteger in
+ let post = Logic_const.prel (Rle, cost_var, new_cost) in
+ let post = Logic_const.new_predicate post in
+ post
+
+let fun_sum env vi kernel_fun =
+ let fst_stmt = Kernel_function.find_first_stmt kernel_fun in
+ let last_stmt = Kernel_function.find_return kernel_fun in
+ let bad_stmts = Stmt.Set.empty in
+ let stop_stmts = Stmt.Set.singleton last_stmt in
+ let sum = cfg_sum env kernel_fun bad_stmts stop_stmts fst_stmt in
+ let sum = match sum with
+ | None -> assert false (* Oups return not achievable?? *)
+ (* Infinity!! *)
+ | Some sum ->
+ let sum = simplify_term sum in
+ let sum = Logic_const.told sum in (** add old and push it *)
+ let labels = NormAtLabels.labels_fct_post in
+ let sum = NormAtLabels.preproc_annot_term labels sum in
+ sum in
+ if !debug then
+ Format.printf "@[<hov 3>sum of %a: %a@]@."
+ Cil.defaultCilPrinter#pVar vi
+ Cil.defaultCilPrinter#pTerm sum;
+(** add postcondition about cost *)
+ let mod_funspec funspec =
+ let post = make_leq_cost env sum in
+ let behavior =
+ Cil.mk_behavior ~name:time_cost_behavior ~post_cond:[Normal, post] () in
+ {funspec with spec_behavior = behavior::funspec.spec_behavior;}
+ in
+ Kernel_function.set_spec kernel_fun mod_funspec;
+ sum
+
+(** Before computing the sum check that the user doesn't specify the cost.
+ In this case use it *)
+let fun_sum env vi =
+ init_loop_name env "fun_sum";
+ let kernel_fun = Globals.Functions.get vi in
+ let funspec = Kernel_function.get_spec kernel_fun in
+ let rec find_cost = function
+ | [] -> None
+ | {b_name = name;
+ b_requires = [];
+ b_assumes = []; (** TODO? allow more general contract? *)
+ (** ensores __cost <= \old(__cost) + t; *)
+ b_post_cond = [_,{ip_content=Prel
+ (Rle,
+ {term_node = (TLval(TVar cost_var,TNoOffset))},
+ {term_node = TBinOp(PlusA,{term_node = Tat(
+ {term_node = (TLval(TVar cost_var2,TNoOffset))}, old_label)},
+ t)})}]
+ }::_ when name = time_cost_behavior &&
+ Logic_var.equal cost_var env.env_cost_var &&
+ Logic_var.equal cost_var2 env.env_cost_var &&
+ Logic_label.equal old_label Logic_const.old_label
+ -> Some t
+ | _::l -> find_cost l in
+ match find_cost funspec.spec_behavior with
+ | None -> fun_sum env vi kernel_fun
+ | Some sum ->
+ if !debug then
+ Format.printf "@[<hov 3>User sum of %a: %a@]@."
+ Cil.defaultCilPrinter#pVar vi
+ Cil.defaultCilPrinter#pTerm sum;
+ let labels = NormAtLabels.labels_fct_post in
+ let sum = NormAtLabels.preproc_annot_term labels sum in
+ sum
+
+let initialize _tmp_prefix _fname cost_var cost_incr _extern_costs =
+ (** TODO? use extern_costs for initializing env_fun_cost ? *)
+ let callgraph = Callgraph.computeGraph (Ast.get ()) in
+ if !debug then
+ Printf.printf "callgraph size: %a\n%!" Callgraph.printGraph callgraph;
+ let env = { env_fun_cost = Varinfo.Hashtbl.create 10;
+ env_cost_incr_name = cost_incr;
+ env_cost_var = cost_var;
+ env_loop_name = dumb_env_loop_name} in
+ let rec iter : 'a. 'a -> Callgraph.callnode -> unit = fun _ callnode ->
+ match callnode.Callgraph.cnInfo with
+ | Callgraph.NIVar (vi,{contents = true }) ->
+ if not (Varinfo.Hashtbl.mem env.env_fun_cost vi) then begin
+ Inthash.iter iter callnode.Callgraph.cnCallees;
+ let sum = fun_sum env vi in
+ Varinfo.Hashtbl.add env.env_fun_cost vi sum
+ end
+ | _ -> () (** put an undefined constant here for top *)
+ in
+ (** add the cost of cost_incr *)
+ let cost_incr = Hashtbl.find callgraph cost_incr in
+ let cost_incr = match cost_incr.Callgraph.cnInfo with
+ | Callgraph.NIVar (vi,_) -> vi
+ | _ -> assert false (* cost_incr must be at least declared *) in
+ let arg_cost_incr = List.hd (Cil.getFormalsDecl cost_incr) in
+ let sum_cost_incr = Logic_const.tvar (Cil.cvar_to_lvar arg_cost_incr) in
+ let post_cost_incr = make_leq_cost env sum_cost_incr in
+ Kernel_function.set_spec (Globals.Functions.get cost_incr) (fun funspec ->
+ let assigns =
+ Writes [Logic_const.(new_identified_term (tvar cost_var)), FromAny] in
+ let behavior =
+ Cil.mk_behavior ~name:time_cost_behavior
+ ~post_cond:[Normal, post_cost_incr]
+ ~assigns () in
+ {funspec with spec_behavior = behavior::funspec.spec_behavior;} );
+ Varinfo.Hashtbl.add env.env_fun_cost cost_incr sum_cost_incr;
+ (** make the other functions *)
+ Hashtbl.iter iter callgraph
+
+
+(*** Main ***)
+
+let cost ((fname, _), _, cost_time, _) =
+ try
+ if !debug then Printf.printf "Initialize Cost\n%!" ;
+ let cost_var =
+ Cil.cvar_to_lvar (Globals.Vars.find_from_astinfo
+ cost_time.Cerco.cost_id VGlobal) in
+ initialize "__tmp" fname cost_var
+ cost_time.Cerco.cost_incr cost_time.Cerco.extern_costs;
+ with e -> Format.eprintf "** ERROR: %a.@." print_exception_raise e
--- /dev/null
+open Parameters
+open Cil_types
+open Simplify_terms
+module Varinfo = Cil_datatype.Varinfo
+module Stmt = Cil_datatype.Stmt
+module Term = Cil_datatype.Term
+module Logic_label = Cil_datatype.Logic_label
+
+
+(** This module defines the main analysis of the plug-in. Its actions are:
+ - build the CFG of the program;
+ - initialize the static environment of analysis (parameters of the
+ functions, number of loops, etc);
+ - compute the cost of each function depending on the costs of the others;
+ - try to solve the inequations formed from the previous step so as to obtain
+ an independent cost for each function;
+ - save the results;
+ - add the annotations on the program. *)
+
+
+(** Function computing cost of special instruction *)
+
+type env =
+ { env_fun_cost : term Varinfo.Hashtbl.t;
+ env_cost_incr_name : string; (* TODO put the varinfo *)
+ env_cost_var_max : logic_var;
+ env_cost_var : logic_var;
+ }
+
+
+let cost_loop env kern_fun stmt lab_before_loop cost_body =
+ (** invariant cost_max <= max(\old(cost_max), \old(cost) + [cost_body])
+ invariant cost = \old(cost)
+ *)
+ (** first *)
+ let cost_var_max = Logic_const.tvar env.env_cost_var_max in
+ let old_cost_max = make_at lab_before_loop cost_var_max in
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = make_at lab_before_loop cost_var in
+ let cost_iterations = make_binop PlusA old_cost cost_body in
+ let invariant = if Term.equal old_cost cost_iterations
+ then Logic_const.prel (Req, cost_var_max, old_cost_max)
+ else
+ let new_cost = make_max old_cost_max cost_iterations in
+ let new_cost = simplify_term new_cost in
+ Logic_const.prel (Rle, cost_var_max, new_cost) in
+ let annot =
+ Logic_const.new_code_annotation
+ (AInvariant ([stack_cost_behavior],true,invariant)) in
+ Annotations.add kern_fun stmt [Ast.self] (User annot);
+ (** second *)
+ let invariant = Logic_const.prel (Req, cost_var, old_cost) in
+ let annot =
+ Logic_const.new_code_annotation
+ (AInvariant ([stack_cost_behavior],true,invariant)) in
+ Annotations.add kern_fun stmt [Ast.self] (User annot);
+ cost_body
+
+(** computing cost of fundec which contain a call to funvar *)
+let cost_of_fun_call env funvar args =
+ (** can't fail since we use the callgraph *)
+ let cost = Varinfo.Hashtbl.find env.env_fun_cost funvar in
+ (* match cost.term_node with *)
+ (* | TConst (CInt64 (_,_,_)) -> cost *)
+ (* | _ -> *)
+ (** arguments of the function *)
+ let formals = Cil.getFormalsDecl funvar in
+(* (** The real arguments are binded using a let and the formal argument are
+ replaced by fresh variable *)
+ let letvars = List.map
+ (fun vi -> Cil.make_temp_logic_var (Ctype vi.vtype))
+ formals in
+ let subst = List.fold_left2 (fun map vi v ->
+ Varinfo.Map.add vi v map) Varinfo.Map.empty formals letvars in
+ let cost =
+ Visitor.visitFramacTerm (new subst_lval subst (Project.current ()))
+ cost in
+ let cost = List.fold_left2 (fun tlet v arg ->
+ let logic_info = { l_var_info = v; l_type = None; l_tparams = [];
+ l_labels = []; l_profile = [];
+ l_body = LBnone; } in
+ let arg = term_of_exp arg in
+ let tlet =
+ Logic_const.term (Tlet (logic_info, arg))
+ tlet.term_type in
+ tlet)
+ cost letvars args in*)
+ let subst = List.fold_left2 (fun map vi arg ->
+ try
+ Varinfo.Map.add vi (term_of_exp arg) map
+ with Untranslatable_expr _ -> map (** TODO verify that this formal doesn't
+ appear in the cost of the function *)
+ ) Varinfo.Map.empty formals args in
+ let cost = remove_logic_label Logic_const.pre_label cost in
+ let cost =
+ Visitor.visitFramacTerm (new subst_lval subst (Project.current ()))
+ cost in
+ cost
+
+
+(** We go through the cfg we assume that:
+ - all functions called have a cost already computed
+ - no implicit loop (goto), all are explicit Loop
+ - all loops have an invariant (given by the user or previously computed for
+ for-loops)
+
+ We iterate on the cfg except when arriving on a loop where we compute the
+ body alone and after that go to the next statements (the break statement)
+
+ break_statement in which statement to stop the sum (for loop)
+ *)
+
+
+let rec find_variant = function
+ | [] -> None
+ | {annot_content = AVariant (t,_)}::_ -> Some t
+ | _::l -> find_variant l
+
+(** TODO: cache the statement already done after if-then-else
+ (otherwise exponential) *)
+(** return None if no path arrive to a good_statement or don't go through
+ a bad_statetement *)
+let rec cfg_sum env kern_fun bad_stmts stop_stmts stmt =
+ if !debug then
+ Format.printf "sid: %i,@ bad_stmts: %a,@ stop_stmts: %a,@\n"
+ stmt.sid
+ Stmt.Set.pretty bad_stmts
+ Stmt.Set.pretty stop_stmts;
+ (** statement in last statement *)
+ if Stmt.Set.mem stmt stop_stmts
+ then Some (Cil.lzero ())
+ else if Stmt.Set.mem stmt bad_stmts
+ then None
+ else
+ (** successors *)
+ let succs_bad_stmts =
+ match stmt.skind with
+ | Loop (_,_,_,_,_) -> Stmt.Set.add stmt bad_stmts
+ | _ -> bad_stmts in
+ (** Cost of the successors of the instruction *)
+ let cost_succs =
+ cfg_sum_succs env kern_fun succs_bad_stmts stop_stmts
+ stmt.succs in
+ match cost_succs with
+ | None -> None (** can't go in a good state so count nothing *)
+ | Some cost_succs ->
+ (** normalize the cost of the instruction regarding the labels *)
+ let labels = NormAtLabels.labels_stmt_pre stmt in
+ (** Cost of the instruction *)
+
+ let sum =
+ match stmt.skind with
+ (* (\** call to cost_incr *\) *)
+ (** cost_stack_incr is not an usual function *)
+ | Instr
+ (Call (None,
+ { enode =
+ Lval (Var var, _)} ,
+ [cost], _))
+ when var.vname = env.env_cost_incr_name ->
+ make_binop PlusA cost_succs
+ (make_max (Cil.lzero ()) (term_of_cost_expr cost))
+ (** function call *)
+ | Instr
+ (Call (_, { enode =
+ Lval (Var var, _)},
+ args,_)) ->
+ let cost_instr = NormAtLabels.preproc_annot_term labels
+ (cost_of_fun_call env var args) in
+ make_max cost_succs cost_instr
+ (** loops *)
+ | Loop (_,_,_,_,_) ->
+ (** the first one perhaps not needed *)
+ let bad_stmts = Stmt.Set.union bad_stmts stop_stmts in
+ let stop_stmts = Stmt.Set.singleton stmt in
+ let cost_body =
+ cfg_sum_succs env kern_fun bad_stmts stop_stmts stmt.succs in
+ let cost_body = match cost_body with
+ | None -> (* no cycle in fact *) Cil.lzero ()
+ | Some cost -> simplify_term cost in
+ if stmt.labels = [] then
+ stmt.labels <- (** ugly but... *)
+ Label("__stmt_"^(string_of_int stmt.sid),Cil.builtinLoc,false)::
+ stmt.labels;
+ let label_before_loop = StmtLabel (ref stmt) in
+ let cost_instr =
+ cost_loop env kern_fun stmt label_before_loop cost_body in
+ let cost_instr = NormAtLabels.preproc_annot_term labels cost_instr in
+ make_max cost_instr cost_succs
+ | _ -> cost_succs in
+ (** try to propagate \at(i,Label) *)
+ let sum = match stmt.skind with
+ | Instr (Set ((Var vi,_),e,_)) ->
+ begin try
+ let t = term_of_exp e in
+ let subst = Varinfo.Map.singleton vi t in
+ let sum =
+ Visitor.visitFramacTerm
+ (new subst_with_label stmt subst (Project.current ()))
+ sum in
+ sum
+ with exn ->
+ if !debug then Format.eprintf "can't convert exp %a to term: %a.@."
+ Cil.defaultCilPrinter#pExp e print_exception exn;
+ sum end
+ | _ -> sum
+ in
+ (** remove the at that point to this statement we don't know the value at
+ this point perhaps we will know before ( use Here?? ) *)
+ let sum =
+ Visitor.visitFramacTerm
+ (new remove_stmt_label stmt (Project.current ()))
+ sum in
+ Some sum
+
+and cfg_sum_succs env kern_fun bad_stmts stop_stmts stmts =
+ let fold cost stmt =
+ let cost_succ = cfg_sum env kern_fun bad_stmts stop_stmts stmt in
+ make_max_opt cost cost_succ in
+ List.fold_left fold None stmts
+
+let make_leq_cost env sum =
+ (** ensures cost_max <= max(\old(cost_max), [sum] + cost) *)
+ let cost_var_max = Logic_const.tvar env.env_cost_var_max in
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let old_cost_max = Logic_const.told cost_var_max in
+ let expr = make_binop PlusA sum old_cost in
+ let expr = make_max old_cost_max expr in
+ let post = Logic_const.prel (Rle, cost_var_max, expr) in
+ let post = Logic_const.new_predicate post in
+ post
+
+let make_eq_cost env =
+ (** ensures cost = old cost *)
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let post = Logic_const.prel (Req, cost_var, old_cost) in
+ let post = Logic_const.new_predicate post in
+ post
+
+
+let fun_sum env vi =
+ let kernel_fun = Globals.Functions.get vi in
+ let fst_stmt = Kernel_function.find_first_stmt kernel_fun in
+ let last_stmt = Kernel_function.find_return kernel_fun in
+ let bad_stmts = Stmt.Set.empty in
+ let stop_stmts = Stmt.Set.singleton last_stmt in
+ let sum = cfg_sum env kernel_fun bad_stmts stop_stmts fst_stmt in
+ let sum = match sum with
+ | None -> assert false (* Oups return not achievable?? *)
+ (* Infinity!! *)
+ | Some sum ->
+ let sum = simplify_term sum in
+ let sum = Logic_const.told sum in (** add old and push it *)
+ let labels = NormAtLabels.labels_fct_post in
+ let sum = NormAtLabels.preproc_annot_term labels sum in
+ sum in
+ if !debug then
+ Format.printf "@[<hov 3>sum of %a: %a@]@."
+ Cil.defaultCilPrinter#pVar vi
+ Cil.defaultCilPrinter#pTerm sum;
+(** add postcondition about cost *)
+ let mod_funspec funspec =
+ let post = make_leq_cost env sum in
+ let post2 = make_eq_cost env in
+ let behavior =
+ Cil.mk_behavior ~name:stack_cost_behavior ~post_cond:[Normal, post;
+ Normal, post2] () in
+ {funspec with spec_behavior = behavior::funspec.spec_behavior;}
+ in
+ Kernel_function.set_spec kernel_fun mod_funspec;
+ sum
+
+
+let initialize _tmp_prefix _fname
+ cost_var cost_var_max cost_incr _extern_costs =
+ (** TODO? use extern_costs for initializing env_fun_cost ? *)
+ let callgraph = Callgraph.computeGraph (Ast.get ()) in
+ if !debug then
+ Printf.printf "callgraph size: %a\n%!" Callgraph.printGraph callgraph;
+ let env = { env_fun_cost = Varinfo.Hashtbl.create 10;
+ env_cost_incr_name = cost_incr;
+ env_cost_var_max = cost_var_max;
+ env_cost_var = cost_var
+ } in
+ let rec iter : 'a. 'a -> Callgraph.callnode -> unit = fun _ callnode ->
+ match callnode.Callgraph.cnInfo with
+ | Callgraph.NIVar (vi,{contents = true }) ->
+ if not (Varinfo.Hashtbl.mem env.env_fun_cost vi) then begin
+ Inthash.iter iter callnode.Callgraph.cnCallees;
+ let sum = fun_sum env vi in
+ Varinfo.Hashtbl.add env.env_fun_cost vi sum
+ end
+ | _ -> () (** put an undefined constant here for top *)
+ in
+ (** add the cost of cost_incr *)
+ let cost_incr = Hashtbl.find callgraph cost_incr in
+ let cost_incr = match cost_incr.Callgraph.cnInfo with
+ | Callgraph.NIVar (vi,_) -> vi
+ | _ -> assert false (* cost_incr must be at least declared *) in
+ let arg_cost_incr = List.hd (Cil.getFormalsDecl cost_incr) in
+ let sum_cost_incr = Logic_const.tvar (Cil.cvar_to_lvar arg_cost_incr) in
+ let post_cost_incr = make_leq_cost env sum_cost_incr in
+ let post_cost_incr2 =
+ (** ensures cost = cost + incr *)
+ let cost_var = Logic_const.tvar env.env_cost_var in
+ let old_cost = Logic_const.told cost_var in
+ let expr = make_binop PlusA sum_cost_incr old_cost in
+ let post = Logic_const.prel (Req, cost_var, expr) in
+ let post = Logic_const.new_predicate post in
+ post in
+ Kernel_function.set_spec (Globals.Functions.get cost_incr) (fun funspec ->
+ let assigns =
+ Writes [Logic_const.(new_identified_term (tvar cost_var_max)), FromAny;
+ Logic_const.(new_identified_term (tvar cost_var)), FromAny] in
+ let behavior =
+ Cil.mk_behavior ~name:stack_cost_behavior
+ ~post_cond:[Normal, post_cost_incr;Normal, post_cost_incr2]
+ ~assigns () in
+ {funspec with spec_behavior = behavior::funspec.spec_behavior;} );
+ Varinfo.Hashtbl.add env.env_fun_cost cost_incr sum_cost_incr;
+ (** make the other functions *)
+ Hashtbl.iter iter callgraph
+
+(** Save file *)
+let save_file fname =
+ Kernel.CodeOutput.set fname ;
+ File.pretty_ast ()
+
+(*** Main ***)
+
+exception NoStackInst
+
+let cost ((fname, _), _, _cost_time, cost_stack) =
+ match cost_stack with
+ | None -> ()
+ | Some (cost_stack_max, cost_stack_id) ->
+ try
+ if !debug then Printf.printf "Initialize stack size\n%!" ;
+ let cost_var_max =
+ try
+ Cil.cvar_to_lvar (Globals.Vars.find_from_astinfo
+ cost_stack_max.Cerco.cost_id VGlobal)
+ with _ -> raise NoStackInst in
+ let cost_var =
+ Cil.cvar_to_lvar (Globals.Vars.find_from_astinfo
+ cost_stack_id VGlobal) in
+ initialize "__tmp" fname
+ cost_var cost_var_max
+ cost_stack_max.Cerco.cost_incr
+ cost_stack_max.Cerco.extern_costs;
+ with
+ | NoStackInst ->
+ Format.eprintf "No stack information found.\n%!"
+ | e -> Format.eprintf "** ERROR: %a.@." print_exception_raise e
--- /dev/null
+(**************************************************************************)
+(* *)
+(* This file is part of Frama-C. *)
+(* *)
+(* Copyright (C) 2007-2011 *)
+(* CEA (Commissariat à l'énergie atomique et aux énergies *)
+(* alternatives) *)
+(* *)
+(* you can redistribute it and/or modify it under the terms of the GNU *)
+(* Lesser General Public License as published by the Free Software *)
+(* Foundation, version 2.1. *)
+(* *)
+(* It 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 Lesser General Public License for more details. *)
+(* *)
+(* See the GNU Lesser General Public License version 2.1 *)
+(* for more details (enclosed in the file licenses/LGPLv2.1). *)
+(* *)
+(**************************************************************************)
+
+(** This is the main module of the plug-in. It makes itself available in
+ Frama-C and apply the cost synthesis on every input file. *)
+
+
+module Self =
+ Plugin.Register
+ (struct
+ let name = "cost synthesis"
+ let shortname = "cost"
+ let module_name = "Cost.Self"
+ let help = "synthesis of the execution cost of each function"
+ let is_dynamic = true
+ end)
+
+
+module Enabled = Self.False
+ (struct
+ let module_name = "Cost.Enabled"
+ let option_name = "-cost"
+ let help = "makes a synthesis of the execution cost of each function"
+ let kind = `Tuning
+ end)
+
+module Lustre = Self.False
+ (struct
+ let option_name = "-cost-lustre"
+ let help = "input file is a Lustre file"
+ let kind = `Tuning
+ end)
+
+module Lustre_verify = Self.False
+ (struct
+ let option_name = "-cost-lustre-verify"
+ let help =
+ "input file is a Lustre file, verification of the results requested"
+ let kind = `Tuning
+ end)
+
+module Lustre_test = Self.False
+ (struct
+ let option_name = "-cost-lustre-test"
+ let help =
+ "input file is a Lustre file, testing of the results requested"
+ let kind = `Tuning
+ end)
+
+module Old_computation = Self.False
+ (struct
+ let option_name = "-cost-old-computation"
+ let help =
+ "Compute the cost formula by the old way"
+ let kind = `Tuning
+ end)
+
+module Output_suffix = Self.String
+ (struct
+ let option_name = "-cost-output"
+ let help =
+ "Choose the prefix to output the annotation (without -annotated.c)"
+ let kind = `Tuning
+ let arg_name = ""
+ let default = ""
+ end)
+
+module Acc_prog = Self.String
+ (struct
+ let option_name = "-cost-acc"
+ let help =
+ "Specify which program must be used for annotation (default: acc)"
+ let kind = `Tuning
+ let arg_name = ""
+ let default = "acc"
+ end)
+
+module Already_instrumented = Self.False
+ (struct
+ let option_name = "-cost-already-instrumented"
+ let help = "input file is already instrumented"
+ let kind = `Tuning
+ end)
+
+
+(** The main function: apply CerCo's compiler and the cost synthesis on each
+ input file. *)
+
+(** Save file *)
+let save_file fname =
+ Kernel.CodeOutput.set fname ;
+ File.pretty_ast ()
+
+let run () =
+ if Enabled.get () then
+ let lustre_option = Lustre.get () in
+ let lustre_verify_option = Lustre_verify.get () in
+ let lustre_test_option = Lustre_test.get () in
+ let acc_name = Acc_prog.get () in
+ let user_output_filename = Output_suffix.get () in
+ let debug = Self.Debug.get () <> 0 in
+ Compute.debug := debug;
+ Parameters.debug := debug;
+ let files : Cabs.file list = Ast.UntypedFiles.get () in
+ let run_one ((f_name,_) as file) =
+ let (_,new_name,_,_) as file =
+ if Already_instrumented.get () then
+ let default_time = { Cerco.cost_id = "__cost";
+ cost_incr = "__cost_incr";
+ extern_costs = Misc.String.Map.empty;
+ } in
+ let default_stack_max = Some ({ Cerco.cost_id = "__stack_size_max";
+ cost_incr = "__stack_size_incr";
+ extern_costs = Misc.String.Map.empty;
+ },"__stack_size") in
+ let new_name =
+ (if user_output_filename <> "" then user_output_filename else
+ (Filename.chop_extension f_name))^"-annotated.c" in
+ (file,new_name,default_time,default_stack_max)
+ else
+ let (((fname,_),_,_,_) as file) = Cerco.apply
+ acc_name lustre_option lustre_verify_option lustre_test_option
+ user_output_filename file in
+ Kernel.Files.set [fname] ;
+ File.init_from_cmdline () ;
+ file
+ in
+ if Old_computation.get ()
+ then Compute.cost file
+ else begin
+ save_file "toto1.c";
+ if debug then Printf.printf "Make CFG\n%!" ;
+ Compute_simple.make_CFG () ;
+ save_file "toto2.c";
+ if debug then Compute_simple.print_CFG () ;
+ Compute_simple.cost file;
+ Compute_simple_stack_size.cost file;
+ Simplify_terms.add_def_max_logic_info ();
+ if debug then Printf.printf "Save file\n%!" ;
+ save_file new_name
+ end in
+ List.iter run_one files
+
+let () = Db.Main.extend run
--- /dev/null
+
+(** This module describes the values manipulated by the plug-in. *)
+
+exception Unknown_cost of string
+exception Unknown_prototype of string
+
+
+let string_of_mset to_list sep f mset =
+ let filter (_, occ) = occ <> 0 in
+ let f' (elt, occ) =
+ if occ = 1 then (f elt)
+ else Printf.sprintf "%d*%s" occ (f elt) in
+ Misc.List.to_string sep f' (List.filter filter (to_list mset))
+
+type prototypes = string list Misc.String.Map.t
+
+
+module type S = sig
+
+ type relation
+ val is_large : relation -> bool
+ val has_lower_type : relation -> bool
+
+ type t
+
+ val top : t
+ val of_int : int -> t
+ val of_var : string -> t
+ val add : t -> t -> t
+ val minus : t -> t -> t
+ val mul : t -> t -> t
+ val div : t -> t -> t
+ val max : t -> t -> t
+ val cond : t -> relation -> t -> t -> t -> t
+ val join : t -> t -> t
+ val widen : t -> t -> t
+ val narrow : t -> t -> t
+
+ val le : t -> t -> bool
+
+ val replace_vars : t Misc.String.Map.t -> t -> t
+
+ val to_string : t -> string
+ val string_of_relation : relation -> string
+
+ val compare : t -> t -> int
+
+end
+
+
+module Make (S : S) = struct
+
+ let s_add_list = function
+ | [] -> S.of_int 0
+ | e :: l -> List.fold_left S.add e l
+
+ module Args = struct
+
+ type t = S.t list
+
+ let compare = Misc.List.compare S.compare
+
+ let le args1 args2 =
+ if List.length args1 <> List.length args2 then false
+ else
+ let f res arg1 arg2 = res && (S.le arg1 arg2) in
+ List.fold_left2 f true args1 args2
+
+ let replace_vars replacements = List.map (S.replace_vars replacements)
+
+ let to_string = Misc.List.to_string ", " S.to_string
+
+ end
+
+
+ module Externs = struct
+
+ module M = Misc.String.MSet
+ include M
+
+ let add = union
+
+ let le = subset
+
+ let replace_vars _ externs = externs
+
+ let to_string = string_of_mset to_list " + " (fun x -> x)
+
+ let to_ext externs =
+ let f x occ ext = S.add (S.mul (S.of_int occ) (S.of_var x)) ext in
+ fold f externs (S.of_int 0)
+
+ end
+
+
+ module FunCall = struct
+
+ type t =
+ { caller : string ;
+ id : int ;
+ callee : string ;
+ args : Args.t }
+ let compare = Pervasives.compare
+
+ let caller fun_call = fun_call.caller
+ let id fun_call = fun_call.id
+ let callee fun_call = fun_call.callee
+ let args fun_call = fun_call.args
+
+ let make caller id callee args = { caller ; id ; callee ; args }
+
+ let apply f f_caller f_id f_callee f_args fun_call =
+ let caller_res = f_caller (caller fun_call) in
+ let id_res = f_id (id fun_call) in
+ let callee_res = f_callee (callee fun_call) in
+ let args_res = f_args (args fun_call) in
+ f caller_res id_res callee_res args_res
+
+ let apply2 f f_caller f_id f_callee f_args fun_call1 fun_call2 =
+ let caller_res = f_caller (caller fun_call1) (caller fun_call2) in
+ let id_res = f_id (id fun_call1) (id fun_call2) in
+ let callee_res = f_callee (callee fun_call1) (callee fun_call2) in
+ let args_res = f_args (args fun_call1) (args fun_call2) in
+ f caller_res id_res callee_res args_res
+
+ let le =
+ let f b1 b2 b3 b4 = b1 && b2 && b3 && b4 in
+ apply2 f (=) (=) (=) Args.le
+
+ let replace_vars replacement =
+ apply make Misc.id Misc.id Misc.id (Args.replace_vars replacement)
+
+ let reduce
+ to_list is_solved replace_vars of_fun_call
+ prototypes costs fun_call =
+ let callee = callee fun_call in
+ let args = args fun_call in
+ if Misc.String.Map.mem callee prototypes then
+ let formals = Misc.String.Map.find callee prototypes in
+ if List.length formals = List.length args then
+ let replacements =
+ Misc.String.Map.of_list (List.combine formals args) in
+ if Misc.String.Map.mem callee costs then
+ let cost' = Misc.String.Map.find callee costs in
+ if is_solved cost' then to_list (replace_vars replacements cost')
+ else [of_fun_call fun_call]
+ else raise (Unknown_cost callee)
+ else
+ raise
+ (Failure ("FunCall.reduce: formals and actuals for " ^
+ "function " ^ callee ^ " have different sizes."))
+ else raise (Unknown_prototype callee)
+
+ let to_string fun_call =
+ Printf.sprintf "%s@[%s,%d](%s)"
+ (callee fun_call) (caller fun_call) (id fun_call)
+ (Args.to_string (args fun_call))
+
+ end
+
+ module FunCalls = struct
+
+ module M = Multiset.Make (FunCall)
+ include M
+
+ let singleton_ fun_call = M.add fun_call empty
+
+ let singleton caller id callee args =
+ singleton (FunCall.make caller id callee args)
+
+ let add = union
+
+ let le1 fun_call occ fun_calls =
+ let f fun_call' occ' = (FunCall.le fun_call fun_call') && (occ <= occ') in
+ exists f fun_calls
+
+ let le fun_calls1 fun_calls2 =
+ let f fun_call occ = le1 fun_call occ fun_calls2 in
+ for_all f fun_calls1
+
+ let called_funs fun_calls =
+ let f fun_call _ called_funs =
+ Misc.String.Set.add (FunCall.callee fun_call) called_funs in
+ fold f fun_calls Misc.String.Set.empty
+
+ let replace_vars replacements fun_calls =
+ let f fun_call _ fun_calls =
+ let fun_call = FunCall.replace_vars replacements fun_call in
+ add (singleton_ fun_call) fun_calls in
+ fold f fun_calls empty
+
+ let to_string = string_of_mset to_list " + " FunCall.to_string
+
+ end
+
+
+ module rec LoopCost : sig
+ type t
+ val compare : t -> t -> int
+ val make : string -> int -> S.relation -> S.t -> S.t -> S.t -> Cost.t -> t
+ val le : t -> t -> bool
+ val called_funs : t -> Misc.String.Set.t
+ val replace_vars : S.t Misc.String.Map.t -> t -> t
+ val reduce : prototypes -> Cost.t Misc.String.Map.t -> t -> t
+ val to_string : t -> string
+ val to_ext : t -> S.t
+ end = struct
+
+ type t =
+ { fun_name : string ;
+ id : int ;
+ relation : S.relation ;
+ init_value : S.t ;
+ exit_value : S.t ;
+ increment : S.t ;
+ body_cost : Cost.t }
+
+ let make fun_name id relation init_value exit_value increment body_cost =
+ { fun_name ; id ; relation ; init_value ; exit_value ; increment ;
+ body_cost }
+
+ let fun_name loop_cost = loop_cost.fun_name
+ let id loop_cost = loop_cost.id
+ let relation loop_cost = loop_cost.relation
+ let init_value loop_cost = loop_cost.init_value
+ let exit_value loop_cost = loop_cost.exit_value
+ let increment loop_cost = loop_cost.increment
+ let body_cost loop_cost = loop_cost.body_cost
+
+ let compare = Pervasives.compare
+
+ let apply f
+ f_fun_name f_id f_relation f_init_value f_exit_value f_increment
+ f_body_cost loop_cost =
+ let fun_name_res = f_fun_name (fun_name loop_cost) in
+ let id_res = f_id (id loop_cost) in
+ let relation_res = f_relation (relation loop_cost) in
+ let init_value_res = f_init_value (init_value loop_cost) in
+ let exit_value_res = f_exit_value (exit_value loop_cost) in
+ let increment_res = f_increment (increment loop_cost) in
+ let body_cost_res = f_body_cost (body_cost loop_cost) in
+ f
+ fun_name_res id_res relation_res init_value_res exit_value_res
+ increment_res body_cost_res
+
+ let apply2 f
+ f_fun_name f_id f_relation f_init_value f_exit_value f_increment
+ f_body_cost loop_cost1 loop_cost2 =
+ let fun_name_res =
+ f_fun_name (fun_name loop_cost1) (fun_name loop_cost2) in
+ let id_res = f_id (id loop_cost1) (id loop_cost2) in
+ let relation_res =
+ f_relation (relation loop_cost1) (relation loop_cost2) in
+ let init_value_res =
+ f_init_value (init_value loop_cost1) (init_value loop_cost2) in
+ let exit_value_res =
+ f_exit_value (exit_value loop_cost1) (exit_value loop_cost2) in
+ let increment_res =
+ f_increment (increment loop_cost1) (increment loop_cost2) in
+ let body_cost_res =
+ f_body_cost (body_cost loop_cost1) (body_cost loop_cost2) in
+ f
+ fun_name_res id_res relation_res init_value_res exit_value_res
+ increment_res body_cost_res
+
+ let le =
+ let f b1 b2 b3 b4 b5 b6 b7 = b1 && b2 && b3 && b4 && b5 && b6 && b7 in
+ apply2 f (=) (=) (=) S.le S.le S.le Cost.le
+
+ let called_funs loop_cost = Cost.called_funs (body_cost loop_cost)
+
+ let replace_vars replacements =
+ let arg_replace_vars = S.replace_vars replacements in
+ apply make Misc.id Misc.id Misc.id arg_replace_vars arg_replace_vars
+ arg_replace_vars (Cost.replace_vars replacements)
+
+ let reduce prototypes costs =
+ apply make Misc.id Misc.id Misc.id Misc.id Misc.id Misc.id
+ (Cost.reduce prototypes costs)
+
+ let to_string loop_cost =
+ Printf.sprintf "%s@%d(%s %s %s %s (%s))"
+ (fun_name loop_cost)
+ (id loop_cost)
+ (S.string_of_relation (relation loop_cost))
+ (S.to_string (init_value loop_cost))
+ (S.to_string (exit_value loop_cost))
+ (S.to_string (increment loop_cost))
+ (Cost.to_string (body_cost loop_cost))
+
+ let to_ext loop_cost =
+ let rel = relation loop_cost in
+ let init_value = init_value loop_cost in
+ let exit_value = exit_value loop_cost in
+ let increment = increment loop_cost in
+ let body_cost = body_cost loop_cost in
+ let rel_op = if S.has_lower_type rel then S.minus else S.add in
+ let rel_added = S.of_int (if S.is_large rel then 0 else 1) in
+ let iteration_nb = rel_op increment rel_added in
+ let iteration_nb = S.minus iteration_nb init_value in
+ let iteration_nb = S.add exit_value iteration_nb in
+ let iteration_nb = S.div iteration_nb increment in
+ let body_cost = Cost.to_ext body_cost in
+ let cond_body_cost =
+ S.cond init_value rel exit_value body_cost (S.of_int 0) in
+ S.mul iteration_nb cond_body_cost
+
+ end
+
+
+ and LoopCosts : sig
+ type t
+ val empty : t
+ val singleton :
+ string -> int -> S.relation -> S.t -> S.t -> S.t -> Cost.t -> t
+ val add : t -> t -> t
+ val replace_vars : S.t Misc.String.Map.t -> t -> t
+ val called_funs : t -> Misc.String.Set.t
+ val reduce : prototypes -> Cost.t Misc.String.Map.t -> t -> t
+ val to_string : t -> string
+ val le : t -> t -> bool
+ val to_ext : t -> S.t
+ end = struct
+
+ module M = Multiset.Make (LoopCost)
+ include M
+
+ let singleton_ loop_cost = M.add loop_cost empty
+
+ let singleton
+ fun_name id relation init_value exit_value increment body_cost =
+ let loop_cost =
+ LoopCost.make
+ fun_name id relation init_value exit_value increment body_cost in
+ singleton_ loop_cost
+
+ let add = union
+
+ let le1 loop_cost occ loop_costs =
+ let f loop_cost' occ' res =
+ res || ((LoopCost.le loop_cost loop_cost') && (occ <= occ')) in
+ fold f loop_costs false
+
+ let le loop_costs1 loop_costs2 =
+ let f loop_cost occ res = res && le1 loop_cost occ loop_costs2 in
+ fold f loop_costs1 true
+
+ let called_funs loop_costs =
+ let f loop_cost _ called_funs =
+ Misc.String.Set.union (LoopCost.called_funs loop_cost) called_funs in
+ fold f loop_costs Misc.String.Set.empty
+
+ let replace_vars replacements loop_costs =
+ let f loop_cost _ loop_costs =
+ let loop_cost = LoopCost.replace_vars replacements loop_cost in
+ add (singleton_ loop_cost) loop_costs in
+ fold f loop_costs empty
+
+ let reduce prototypes replacements loop_costs =
+ let f loop_cost occ loop_costs =
+ add_occ (LoopCost.reduce prototypes replacements loop_cost) occ
+ loop_costs in
+ fold f loop_costs empty
+
+ let to_string = string_of_mset to_list " + " LoopCost.to_string
+
+ let to_ext loop_costs =
+ let f loop_cost occ ext =
+ S.add (S.mul (S.of_int occ) (LoopCost.to_ext loop_cost)) ext in
+ fold f loop_costs (S.of_int 0)
+
+ end
+
+
+ and Base : sig
+ type t
+ val compare : t -> t -> int
+ val of_int : int -> t
+ val of_extern : string -> t
+ val of_fun_call_ : FunCall.t -> t
+ val of_fun_call : string -> int -> string -> Args.t -> t
+ val of_loop_cost :
+ string -> int -> S.relation -> S.t -> S.t -> S.t -> Cost.t -> t
+ val add : t -> t -> t
+ val called_funs : t -> Misc.String.Set.t
+ val replace_vars : S.t Misc.String.Map.t -> t -> t
+ val reduce : prototypes -> Cost.t Misc.String.Map.t -> t -> Base.t list
+ val le : t -> t -> bool
+ val to_string : t -> string
+ val to_ext : t -> S.t
+ end = struct
+
+ type t =
+ { constant : int ;
+ externs : Externs.t ;
+ fun_calls : FunCalls.t ;
+ loop_costs : LoopCosts.t }
+
+ let make constant externs fun_calls loop_costs =
+ { constant ; externs ; fun_calls ; loop_costs }
+
+ let compare = Pervasives.compare
+
+ let constant base = base.constant
+ let externs base = base.externs
+ let fun_calls base = base.fun_calls
+ let loop_costs base = base.loop_costs
+
+ let set_fun_calls fun_calls base = { base with fun_calls }
+ let set_loop_costs loop_costs base = { base with loop_costs }
+
+ let to_string base =
+ Printf.sprintf "%d + (%s) + (%s) + (%s)"
+ (constant base)
+ (Externs.to_string (externs base))
+ (FunCalls.to_string (fun_calls base))
+ (LoopCosts.to_string (loop_costs base))
+
+ let of_int i = make i Externs.empty FunCalls.empty LoopCosts.empty
+
+ let of_extern x =
+ make 0 (Externs.singleton x) FunCalls.empty LoopCosts.empty
+
+ let of_fun_call_ fun_call =
+ make 0 Externs.empty (FunCalls.singleton_ fun_call) LoopCosts.empty
+
+ let of_fun_call caller id callee args =
+ let fun_call = FunCall.make caller id callee args in
+ of_fun_call_ fun_call
+
+ let of_loop_cost
+ fun_name id relation init_value exit_value increment body_cost =
+ let loop_costs =
+ LoopCosts.singleton
+ fun_name id relation init_value exit_value increment body_cost in
+ make 0 Externs.empty FunCalls.empty loop_costs
+
+ let apply f f_constant f_externs f_fun_calls f_loop_costs base =
+ let constant_res = f_constant (constant base) in
+ let externs_res = f_externs (externs base) in
+ let fun_calls_res = f_fun_calls (fun_calls base) in
+ let loop_costs_res = f_loop_costs (loop_costs base) in
+ f constant_res externs_res fun_calls_res loop_costs_res
+
+ let apply2 f f_constant f_externs f_fun_calls f_loop_costs base1 base2 =
+ let constant_res = f_constant (constant base1) (constant base2) in
+ let externs_res = f_externs (externs base1) (externs base2) in
+ let fun_calls_res = f_fun_calls (fun_calls base1) (fun_calls base2) in
+ let loop_costs_res = f_loop_costs (loop_costs base1) (loop_costs base2) in
+ f constant_res externs_res fun_calls_res loop_costs_res
+
+ let add = apply2 make (+) Externs.add FunCalls.add LoopCosts.add
+
+ let le =
+ let f b1 b2 b3 b4 = b1 && b2 && b3 && b4 in
+ apply2 f (<=) Externs.le FunCalls.le LoopCosts.le
+
+ let replace_vars replacements =
+ apply make Misc.id
+ (Externs.replace_vars replacements)
+ (FunCalls.replace_vars replacements)
+ (LoopCosts.replace_vars replacements)
+
+ let called_funs base =
+ Misc.String.Set.union
+ (FunCalls.called_funs (fun_calls base))
+ (LoopCosts.called_funs (loop_costs base))
+
+ let reduce prototypes costs base =
+ let f fun_call occ base_list =
+ let added_bases =
+ FunCall.reduce
+ Cost.to_list Cost.is_solved Cost.replace_vars of_fun_call_
+ prototypes costs fun_call in
+ let added_bases =
+ if added_bases = [] then [of_int 0] else added_bases in
+ let added_bases =
+ let f base = Misc.repeat occ (add base) (of_int 0) in
+ List.map f added_bases in
+ let f_base_list res added_base =
+ res @ (List.map (add added_base) base_list) in
+ List.fold_left f_base_list [] added_bases in
+ let loop_costs = LoopCosts.reduce prototypes costs (loop_costs base) in
+ let base = set_loop_costs loop_costs base in
+ let base' = set_fun_calls FunCalls.empty base in
+ FunCalls.fold f (fun_calls base) [base']
+
+ let to_ext base =
+ let f_fun_calls fun_calls =
+ if not (FunCalls.is_empty fun_calls) then
+ raise (Failure "Base.to_ext: function calls")
+ else S.of_int 0 in
+ let f ext1 ext2 ext3 ext4 = s_add_list [ext1 ; ext2 ; ext3 ; ext4] in
+ apply f S.of_int Externs.to_ext f_fun_calls LoopCosts.to_ext base
+
+ end
+
+
+ and Cost : sig
+ type t
+ val of_int : int -> t
+ val of_extern : string -> t
+ val of_fun_call : string -> int -> string -> Args.t -> t
+ val of_loop_cost :
+ string -> int -> S.relation -> S.t -> S.t -> S.t -> Cost.t -> t
+ val of_base : Base.t -> t
+ val empty : t
+ val add : t -> t -> t
+ val join : t -> t -> t
+ val widen : t -> t -> t
+ val narrow : t -> t -> t
+ val called_funs : t -> Misc.String.Set.t
+ val has_fun_calls : t -> bool
+ val replace_vars : S.t Misc.String.Map.t -> t -> t
+ val reduce : prototypes -> Cost.t Misc.String.Map.t -> t -> t
+ val is_solved : t -> bool
+ val to_list : t -> Base.t list
+ val to_string : t -> string
+ val le : t -> t -> bool
+ val to_ext : t -> S.t
+ end = struct
+
+ module M = Eset.Make (Base)
+ include M
+
+ let to_string cost =
+ if is_empty cost then "0"
+ else Misc.List.to_string " max " Base.to_string (to_list cost)
+
+ let of_base base = singleton base
+
+ let of_int i = of_base (Base.of_int i)
+
+ let of_extern x = of_base (Base.of_extern x)
+
+ let of_fun_call caller id callee args =
+ of_base (Base.of_fun_call caller id callee args)
+
+ let of_loop_cost
+ fun_name loop_id relation init_value exit_value increment body_cost =
+ of_base
+ (Base.of_loop_cost
+ fun_name loop_id relation init_value exit_value increment body_cost)
+
+ let join1 base cost =
+ let f_exists base' = Base.le base base' in
+ if exists f_exists cost then cost
+ else
+ let f_absorb base' = Base.le base' base in
+ M.add base (M.diff cost (M.filter f_absorb cost))
+
+ let add cost1 cost2 =
+ if is_empty cost1 then cost2
+ else
+ if is_empty cost2 then cost1
+ else
+ let f2 base1 base2 = join1 (Base.add base1 base2) in
+ let f1 base1 = fold (f2 base1) cost2 in
+ fold f1 cost1 empty
+
+ let join cost1 cost2 =
+ if is_empty cost1 then cost2
+ else
+ if is_empty cost2 then cost1
+ else fold join1 cost1 cost2
+
+ let widen = join
+
+ let narrow = join (* TODO: improve *)
+
+ let mem base cost =
+ let f base' res = res || (Base.le base base') in
+ fold f cost false
+
+ let le cost1 cost2 =
+ let f base res = res && (mem base cost2) in
+ fold f cost1 true
+
+
+ let called_funs cost =
+ let f base called_funs =
+ Misc.String.Set.union (Base.called_funs base) called_funs in
+ fold f cost Misc.String.Set.empty
+
+ let has_fun_calls cost = not (Misc.String.Set.is_empty (called_funs cost))
+
+ let replace_vars replacements cost =
+ let f base cost = join1 (Base.replace_vars replacements base) cost in
+ fold f cost empty
+
+ let reduce prototypes costs cost =
+ let f base cost =
+ let base_list = Base.reduce prototypes costs base in
+ let f_join cost base = join1 base cost in
+ List.fold_left f_join cost base_list in
+ fold f cost empty
+
+ let is_solved cost = not (has_fun_calls cost)
+
+ let to_ext cost =
+ if is_empty cost then S.of_int 0
+ else
+ let f base ext = S.max (Base.to_ext base) ext in
+ let base = choose cost in
+ let cost = remove base cost in
+ fold f cost (Base.to_ext base)
+
+ end
+
+
+ type t = Top | C of Cost.t
+
+
+ let to_string = function
+ | Top -> "top"
+ | C cost -> Cost.to_string cost
+
+
+ let of_int i = C (Cost.of_int i)
+
+ let of_extern fun_name = C (Cost.of_extern fun_name)
+
+ let of_fun_call caller id callee args =
+ C (Cost.of_fun_call caller id callee args)
+
+ let of_loop_cost
+ fun_name loop_id relation init_value exit_value increment body_cost =
+ C (Cost.of_loop_cost
+ fun_name loop_id relation init_value exit_value increment body_cost)
+
+
+ let is_top = function Top -> true | _ -> false
+
+ let extract = function
+ | Top -> raise (Failure "Cost_value.extract")
+ | C cost -> cost
+
+ let top = Top
+
+ let bot = of_int 0
+
+
+ let top_absorbs f = function
+ | Top -> Top
+ | C cost -> C (f cost)
+
+ let top_absorbs2 f cost1 cost2 = match cost1, cost2 with
+ | Top, _ | _, Top -> Top
+ | C cost1, C cost2 -> C (f cost1 cost2)
+
+
+ let add = top_absorbs2 Cost.add
+
+ let join = top_absorbs2 Cost.join
+
+ let widen = top_absorbs2 Cost.widen
+
+ let narrow cost1 cost2 = match cost1, cost2 with
+ | cost, Top | Top, cost -> cost
+ | C cost1, C cost2 -> C (Cost.narrow cost1 cost2)
+
+ let le cost1 cost2 = match cost1, cost2 with
+ | _, Top -> true
+ | Top, _ -> false
+ | C cost1, C cost2 -> Cost.le cost1 cost2
+
+
+ let reduce_ prototypes costs cost =
+ let called_funs = Cost.called_funs cost in
+ let costs =
+ let f fun_name _ = Misc.String.Set.mem fun_name called_funs in
+ Misc.String.Map.filter f costs in
+ let f fun_name cost costs = match cost, costs with
+ | _, None -> None
+ | Top, _ -> None
+ | C cost, Some costs -> Some (Misc.String.Map.add fun_name cost costs) in
+ match Misc.String.Map.fold f costs (Some Misc.String.Map.empty) with
+ | None -> Top
+ | Some costs -> C (Cost.reduce prototypes costs cost)
+
+ let reduce prototypes costs = function
+ | Top -> Top
+ | C cost -> reduce_ prototypes costs cost
+
+ let reduces prototypes costs =
+ Misc.String.Map.map (reduce prototypes costs) costs
+
+
+ let replace_vars replacements = top_absorbs (Cost.replace_vars replacements)
+
+
+ let has_fun_calls = function
+ | Top -> false
+ | C cost -> Cost.has_fun_calls cost
+
+
+ let is_concrete cost = (not (is_top cost)) && (not (has_fun_calls cost))
+
+ let to_ext = function
+ | Top -> S.top
+ | C cost -> Cost.to_ext cost
+
+
+end
--- /dev/null
+
+module type OrderedType = sig
+ include Map.OrderedType
+end
+
+module type S = sig
+ include Map.S
+
+ val merge_f : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
+ val split_couple : ('a * 'b) t -> 'a t * 'b t
+ val combine : 'a t -> 'b t -> ('a * 'b) t
+ val error_find : key -> 'a t -> exn -> 'a
+ val of_list : (key * 'a) list -> 'a t
+ val to_list : 'a t -> (key * 'a) list
+end
+
+module Make (Ord : OrderedType) : S with type key = Ord.t = struct
+ include Map.Make (Ord)
+
+ let merge_f f map1 map2 =
+ let f_merge _ e1 e2 = match e1, e2 with
+ | None, None -> None
+ | Some e, None | None, Some e -> Some e
+ | Some e1, Some e2 -> Some (f e1 e2) in
+ merge f_merge map1 map2
+
+ let split_couple map =
+ let f key (a, b) (resa, resb) = (add key a resa, add key b resb) in
+ fold f map (empty, empty)
+
+ let combine mapa mapb =
+ let f key a res =
+ if mem key mapb then add key (a, find key mapb) res
+ else res in
+ fold f mapa empty
+
+ let error_find x map error = if mem x map then find x map else raise error
+
+ let of_list l =
+ let f map (key, binding) = add key binding map in
+ List.fold_left f empty l
+
+ let to_list = bindings
+end
+
+
+module type S1 = sig
+ type key
+ type img
+ type t
+ val empty : t
+ val is_empty : t -> bool
+ val mem : key -> t -> bool
+ val add : key -> img -> t -> t
+ val singleton : key -> img -> t
+ val remove : key -> t -> t
+ val merge_f : (img -> img -> img) -> t -> t -> t
+ val merge : (key -> img option -> img option -> img option) -> t -> t -> t
+ val compare : t -> t -> int
+ val equal : t -> t -> bool
+ val iter : (key -> img -> unit) -> t -> unit
+ val fold : (key -> img -> 'b -> 'b) -> t -> 'b -> 'b
+ val for_all : (key -> img -> bool) -> t -> bool
+ val exists : (key -> img -> bool) -> t -> bool
+ val filter : (key -> img -> bool) -> t -> t
+ val partition : (key -> img -> bool) -> t -> t * t
+ val cardinal : t -> int
+ val bindings : t -> (key * img) list
+ val min_binding : t -> key * img
+ val max_binding : t -> key * img
+ val choose : t -> key * img
+ val split : key -> t -> t * img option * t
+ val find : key -> t -> img
+ val map : (img -> img) -> t -> t
+ val mapi : (key -> img -> img) -> t -> t
+ val error_find : key -> t -> exn -> img
+ val of_list : (key * img) list -> t
+ val to_list : t -> (key * img) list
+end
+
+module Make1 (Key : OrderedType) (Img : OrderedType)
+ : S1 with type key = Key.t and type img = Img.t =
+struct
+
+ module M = Make (Key)
+
+ type key = M.key
+ type img = Img.t
+ type t = img M.t
+
+ let empty = M.empty
+ let is_empty = M.is_empty
+ let mem = M.mem
+ let add = M.add
+ let singleton = M.singleton
+ let remove = M.remove
+ let merge_f = M.merge_f
+ let merge = M.merge
+ let compare = M.compare Img.compare
+ let equal = M.equal (fun img1 img2 -> Img.compare img1 img2 = 0)
+ let iter = M.iter
+ let fold = M.fold
+ let for_all = M.for_all
+ let exists = M.exists
+ let filter = M.filter
+ let partition = M.partition
+ let cardinal = M.cardinal
+ let bindings = M.bindings
+ let min_binding = M.min_binding
+ let max_binding = M.max_binding
+ let choose = M.choose
+ let split = M.split
+ let find = M.find
+ let map = M.map
+ let mapi = M.mapi
+ let error_find = M.error_find
+ let of_list = M.of_list
+ let to_list = M.to_list
+
+end
--- /dev/null
+
+module type OrderedType = Set.OrderedType
+
+module type S = sig
+ include Set.S
+
+ val of_list : elt list -> t
+ val to_list : t -> elt list
+ val disjoint : t -> t -> bool
+ val is_subset : t -> t -> bool
+end
+
+module Make (Ord : OrderedType) : S with type elt = Ord.t = struct
+ module M = Set.Make (Ord)
+ include M
+
+ let to_list = elements
+ let of_list l = List.fold_right M.add l M.empty
+ let disjoint s1 s2 = M.inter s1 s2 = M.empty
+
+ let is_subset set1 set2 =
+ let f x res = res && (mem x set2) in
+ fold f set1 true
+end
--- /dev/null
+
+(** This module provides extended functions for some datatypes. *)
+
+
+module List = struct
+
+ (** [split_nth n l] returns the list of elements of [l] before the [n]th
+ (exclusive, starting at 0) and those after. Raises [Failure
+ "Misc.List.split_nth"] if [n] is negative. *)
+
+ let split_nth n l =
+ if n >= 0 then raise (Failure "Misc.List.split_nth")
+ else
+ let rec aux i acc = function
+ | [] -> (List.rev acc, [])
+ | l when i = n -> (List.rev acc, l)
+ | e :: l -> aux (i+1) (e :: acc) l in
+ aux 0 [] l
+
+ let to_string sep f l =
+ let rec aux = function
+ | [] -> ""
+ | [e] -> f e
+ | e :: l -> (f e) ^ sep ^ (aux l) in
+ aux l
+
+ let rec fold_left3 f res l1 l2 l3 = match l1, l2, l3 with
+ | [], [], [] -> res
+ | e1 :: l1, e2 :: l2, e3 :: l3 -> fold_left3 f (f res e1 e2 e3) l1 l2 l3
+ | _ -> raise (Invalid_argument "Misc.List.fold_left3")
+
+ let foldi f l b =
+ let rec aux i acc = function
+ | [] -> acc
+ | e :: l -> aux (i+1) (f i e acc) l in
+ aux 0 b l
+
+ let pos e l =
+ let f i e' res = if e = e' then Some i else res in
+ foldi f l None
+
+ let sub_unordered l1 l2 = List.for_all (fun e -> List.mem e l2) l1
+
+ let eq_unordered l1 l2 = (sub_unordered l1 l2) && (sub_unordered l2 l1)
+
+ let compare cmp_a l1 l2 =
+ let f res e1 e2 = match res with
+ | None when cmp_a e1 e2 = 0 -> None
+ | None -> Some (cmp_a e1 e2)
+ | _ -> res in
+ let size1 = List.length l1 in
+ let size2 = List.length l2 in
+ if size1 < size2 then -1
+ else
+ if size2 < size1 then 1
+ else
+ match List.fold_left2 f None l1 l2 with
+ | None -> 0
+ | Some i -> i
+
+end
+
+module Option = struct
+
+ let extract = function
+ | Some a -> a
+ | None -> raise (Invalid_argument "Misc.Option.extract")
+
+ let return (i : 'a) : 'a option = Some i
+
+ let (>>=) a f = match a with
+ | None -> None
+ | Some a -> f a
+
+ let (>>) a f = match a with
+ | None -> None
+ | Some a -> Some (f a)
+
+end
+
+module Int = struct
+ module OrdInt = struct type t = int let compare = Pervasives.compare end
+ module Set = Eset.Make (OrdInt)
+ module Map = Emap.Make (OrdInt)
+ module CMap = CompleteMap.Make (struct include Map let keys = None end)
+end
+
+module String = struct
+ module Set = Eset.Make (String)
+ module Map = Emap.Make (String)
+ module CMap = CompleteMap.Make (struct include Map let keys = None end)
+ module MSet = Multiset.Make (String)
+end
+
+let compare_couple cmp_a cmp_b (a, b) (a', b') =
+ let res_a = cmp_a a a' in
+ if res_a = 0 then cmp_b b b'
+ else res_a
+
+let string_of_bool = function
+ | true -> "true"
+ | false -> "false"
+
+let id x = x
+
+let rec repeat n f a =
+ if n <= 0 then a
+ else repeat (n-1) f (f a)
--- /dev/null
+
+module type OrderedType = Eset.OrderedType
+
+module type S = sig
+
+ type elt
+ type t
+
+ val compare : t -> t -> int
+ val empty : t
+ val is_empty : t -> bool
+ val singleton : elt -> t
+ val upd : elt -> int -> t -> t
+ val add : elt -> t -> t
+ val add_occ : elt -> int -> t -> t
+ val find : elt -> t -> int
+ val union : t -> t -> t
+ val merge_f : (int -> int -> int) -> t -> t -> t
+ val fold : (elt -> int -> 'a -> 'a) -> t -> 'a -> 'a
+ val for_all : (elt -> int -> bool) -> t -> bool
+ val exists : (elt -> int -> bool) -> t -> bool
+ val subset : t -> t -> bool
+ val to_list : t -> (elt * int) list
+
+end
+
+module OrdInt = struct
+ type t = int let compare = Pervasives.compare
+end
+
+module Make (Ord : OrderedType) : S with type elt = Ord.t = struct
+
+ module M = Emap.Make1 (Ord) (OrdInt)
+ include M
+
+ type elt = Ord.t
+
+ let compare = M.compare
+
+ let singleton x = M.add x 1 empty
+
+ let upd = M.add
+
+ let add_occ x occ mset =
+ let occ' = if mem x mset then find x mset else 0 in
+ upd x (occ+occ') mset
+
+ let add x mset = add_occ x 1 mset
+
+ let find x mset = if mem x mset then M.find x mset else 0
+
+ let union = merge_f (+)
+
+ let subset mset1 mset2 =
+ let f x occ res = res && (occ <= find x mset2) in
+ M.fold f mset1 true
+
+end
--- /dev/null
+(**************************************************************************)
+(* *)
+(* This file is part of WP plug-in of Frama-C. *)
+(* *)
+(* Copyright (C) 2007-2011 *)
+(* CEA (Commissariat a l'énergie atomique et aux énergies *)
+(* alternatives) *)
+(* *)
+(* you can redistribute it and/or modify it under the terms of the GNU *)
+(* Lesser General Public License as published by the Free Software *)
+(* Foundation, version 2.1. *)
+(* *)
+(* It 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 Lesser General Public License for more details. *)
+(* *)
+(* See the GNU Lesser General Public License version 2.1 *)
+(* for more details (enclosed in the file licenses/LGPLv2.1). *)
+(* *)
+(**************************************************************************)
+
+
+open Cil_types
+
+(** Copied from clabels.ml *)
+(*TODO [LC] : Use extension of Clabels instead *)
+let mk_logic_label s =
+ LogicLabel (Some s, "cost!stmt_"^(string_of_int s.sid))
+
+
+type label_mapping = Cil_types.logic_label -> Cil_types.logic_label
+
+
+(** push the Tat down to the 'data' operations.
+* This can be useful in cases like \at (x + \at(y, Ly), Lx) because
+* it gives \at(x, Lx) + \at(y, Ly) so there is no more \at imbrications.
+ * Also try to "normalize" label :
+ * - remove Here because its meaning change when propagating,
+ * - remove Old because its meaning depend on where it comes from.
+* *)
+class norm_at label_map = object(self)
+ inherit Visitor.generic_frama_c_visitor (Project.current()) (Cil.copy_visit())
+
+ val mutable current_label = None
+
+ method private change_label label =
+ let label = label_map label in
+ let old_label = current_label in
+ current_label <- Some label; old_label
+
+ method private restore_term old_label x =
+ current_label <- old_label;
+ let x = match x.term_node with
+ | Ttypeof x -> (* Ttypeof is used as a dummy unary construct *) x
+ | _ -> assert false
+ in x
+
+ method private restore_pred old_label x =
+ current_label <- old_label;
+ let x = match x.content with
+ | Pnot x -> (* Pnot is used as a dummy unary construct *) x
+ | _ -> assert false
+ in x
+
+
+ method vterm t =
+ match t.term_node with
+ | Tat (t, l) ->
+ let old_label = self#change_label l in
+ let new_t = {t with term_node = Ttypeof t} in
+ Cil.ChangeDoChildrenPost (new_t, self#restore_term old_label)
+ | TAddrOf (h, _) | TLval (h, _) | TStartOf (h, _) ->
+ let old_label = current_label in
+ let at_label = match h with
+ | TResult _ -> Some Logic_const.post_label
+ | _ -> old_label
+ in
+ current_label <- None;
+ let post t =
+ current_label <- old_label;
+ match at_label with
+ | Some label -> {t with term_node = Tat (t, label)}
+ | None -> t
+ in Cil.ChangeDoChildrenPost (t, post)
+ (** logic function without label *)
+ | Tapp ({l_labels=[]},[],_) -> Cil.DoChildren
+ | Tapp (_,[],_) ->
+ begin match current_label with
+ | None -> Cil.DoChildren
+ | Some lab ->
+ let post = function
+ | {term_node=Tapp(predicate,[],args)} as t ->
+ { t with term_node=Tapp(predicate,[lab,lab],args) }
+ | _ -> assert false
+ in
+ Cil.ChangeDoChildrenPost (t,post)
+ end
+ | Tapp _ ->
+ let post = function
+ | {term_node=Tapp(predicate,labels,args)} as t ->
+ let new_labels =
+ List.map
+ (fun (logic_lab, stmt_lab) -> logic_lab, label_map stmt_lab)
+ labels
+ in { t with term_node=Tapp(predicate,new_labels,args) }
+ | _ -> assert false
+ in
+ Cil.ChangeDoChildrenPost (t,post)
+ | _ -> Cil.DoChildren
+
+ method vpredicate_named p = match p.content with
+ | Pat (p, l) ->
+ let old_label = self#change_label l in
+ let new_p = {p with content = Pnot p} in
+ Cil.ChangeDoChildrenPost (new_p, self#restore_pred old_label)
+ (** logic function without label *)
+ | Papp ({l_labels=[]},[],_) -> Cil.DoChildren
+ | Papp (_,[],_) ->
+ begin match current_label with
+ | None -> Cil.DoChildren
+ | Some lab ->
+ let post = function
+ | {content=Papp(predicate,[],args)} as p ->
+ { p with content=Papp(predicate,[lab,lab],args) }
+ | _ -> assert false
+ in
+ Cil.ChangeDoChildrenPost (p,post)
+ end
+ | Papp _ ->
+ let post = function
+ | {content=Papp(predicate,labels,args)} as p ->
+ let new_labels =
+ List.map
+ (fun (logic,stmt) -> logic, label_map stmt)
+ labels
+ in { p with content=Papp(predicate,new_labels,args) }
+ | _ -> assert false
+ in
+ Cil.ChangeDoChildrenPost (p,post)
+ | _ -> Cil.DoChildren
+end
+
+exception LabelError of logic_label
+
+let labels_empty l = raise (LabelError l)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Function Contracts --- *)
+(* -------------------------------------------------------------------------- *)
+
+let labels_fct_pre = function
+ | LogicLabel (None, ("Pre" | "Here")) -> Logic_const.pre_label
+ | l -> raise (LabelError l)
+
+
+let labels_fct_post = function
+ | LogicLabel (None, ("Pre" | "Old")) -> Logic_const.pre_label
+ | LogicLabel (None, ("Post" | "Here")) -> Logic_const.post_label
+ | l -> raise (LabelError l)
+
+let labels_fct_assigns = function
+ | LogicLabel (None, "Post") -> Logic_const.post_label
+ | LogicLabel (None, ("Pre" | "Old")) -> Logic_const.pre_label
+ | l -> raise (LabelError l)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Statements Contracts --- *)
+(* -------------------------------------------------------------------------- *)
+let labels_stmt_pre s = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *)
+ | LogicLabel (None, "Here") -> mk_logic_label s
+ | LogicLabel (Some s, _) -> mk_logic_label s
+ | StmtLabel rs -> mk_logic_label !rs
+ | l -> raise (LabelError l)
+
+let labels_stmt_post s l_post = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *)
+ | LogicLabel (None, "Old") -> mk_logic_label s (* contract pre-state *)
+ | LogicLabel (None, ("Here" | "Post")) as l ->
+ begin match l_post with Some l -> l
+ | None -> (* TODO ? *) raise (LabelError l)
+ end
+ | LogicLabel (Some s, _) -> mk_logic_label s
+ | StmtLabel rs -> mk_logic_label !rs
+ | l -> raise (LabelError l)
+
+let labels_stmt_assigns s l_post = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label (* fct pre-state *)
+ | LogicLabel (None, ("Here" | "Old")) -> (* contract pre-state *)
+ mk_logic_label s
+ | LogicLabel (None, "Post") -> labels_stmt_post s l_post Logic_const.post_label
+ | LogicLabel (Some s, _) -> mk_logic_label s
+ | StmtLabel rs -> mk_logic_label !rs
+ | l -> raise (LabelError l)
+
+(* -------------------------------------------------------------------------- *)
+(* --- User Assertions in Functions Code --- *)
+(* -------------------------------------------------------------------------- *)
+
+let labels_assert_before s = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label
+ | LogicLabel (None, "Here") -> mk_logic_label s
+ | LogicLabel (Some s, _) -> mk_logic_label s
+ | StmtLabel rs -> mk_logic_label !rs
+ | l -> raise (LabelError l)
+
+let labels_assert_after s l_post = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label
+ | LogicLabel (None, "Here") ->
+ labels_stmt_post s l_post Logic_const.post_label
+ | LogicLabel (Some s, _) -> mk_logic_label s
+ | StmtLabel rs -> mk_logic_label !rs
+ | l -> raise (LabelError l)
+
+let labels_loop_inv _s = function
+ | LogicLabel (None, "Pre") -> Logic_const.pre_label
+ | LogicLabel (None, "Here") -> Logic_const.here_label
+ | LogicLabel (None, ("Old" | "Post")) as l -> raise (LabelError l)
+ | l -> l
+
+let labels_loop_assigns s l = labels_loop_inv s l
+
+(* -------------------------------------------------------------------------- *)
+(* --- User Defined Predicates --- *)
+(* -------------------------------------------------------------------------- *)
+
+let labels_predicate lab_pairs = fun l ->
+ try List.assoc l lab_pairs
+ with Not_found -> l
+
+let labels_axiom = function
+ | LogicLabel (None, ("Pre"|"Old"|"Post")) as l -> raise (LabelError l)
+ | LogicLabel (None, _) as l -> l
+ | l -> raise (LabelError l)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Apply Normalization --- *)
+(* -------------------------------------------------------------------------- *)
+
+(** @raise LabelError if there is a label in [p] that is incompatible
+* with the [labels] translation *)
+let preproc_annot labels p =
+ let visitor = new norm_at labels in
+ Visitor.visitFramacPredicateNamed visitor p
+
+let preproc_annot_term labels t =
+ let visitor = new norm_at labels in
+ Visitor.visitFramacTerm visitor t
+
+
+(** @raise LabelError if there is a label in [p] that is incompatible
+* with the [labels] translation *)
+let preproc_assigns labels asgns =
+ let visitor = new norm_at labels in
+ List.map (Visitor.visitFramacFrom visitor) asgns
+
+let preproc_label labels l = labels l
--- /dev/null
+(**************************************************************************)
+(* *)
+(* This file is part of WP plug-in of Frama-C. *)
+(* *)
+(* Copyright (C) 2007-2011 *)
+(* CEA (Commissariat a l'énergie atomique et aux énergies *)
+(* alternatives) *)
+(* *)
+(* you can redistribute it and/or modify it under the terms of the GNU *)
+(* Lesser General Public License as published by the Free Software *)
+(* Foundation, version 2.1. *)
+(* *)
+(* It 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 Lesser General Public License for more details. *)
+(* *)
+(* See the GNU Lesser General Public License version 2.1 *)
+(* for more details (enclosed in the file licenses/LGPLv2.1). *)
+(* *)
+(**************************************************************************)
+
+open Cil_types
+
+type label_mapping
+
+val labels_empty : label_mapping
+val labels_fct_pre : label_mapping
+val labels_fct_post : label_mapping
+val labels_fct_assigns : label_mapping
+val labels_assert_before : stmt -> label_mapping
+val labels_assert_after : stmt -> logic_label option -> label_mapping
+val labels_loop_inv : stmt -> label_mapping
+val labels_loop_assigns : stmt -> label_mapping
+val labels_stmt_pre : stmt -> label_mapping
+val labels_stmt_post : stmt -> logic_label option -> label_mapping
+val labels_stmt_assigns : stmt -> logic_label option -> label_mapping
+val labels_predicate : (logic_label * logic_label) list -> label_mapping
+val labels_axiom : label_mapping
+
+val preproc_annot : label_mapping -> predicate named -> predicate named
+val preproc_annot_term : label_mapping -> term -> term
+
+val preproc_assigns :
+ label_mapping -> identified_term from list -> identified_term from list
+
+val preproc_label : label_mapping -> logic_label -> logic_label
+
+(** from clabels.mli *)
+(** create a virtual label to a statement (it can have no label) *)
+val mk_logic_label : Cil_types.stmt -> Cil_types.logic_label
--- /dev/null
+
+(** Parameters *)
+let remove_casts_in_annotations = true
+let put_const_at_the_top_in_annotations = true
+
+(** Less precise cost *)
+let no_division_in_generated_variant = false
+
+(** name of the behavior generated *)
+let time_cost_behavior = "time_cost"
+
+(** name of the behavior generated *)
+let stack_cost_behavior = "stack_cost"
+
+
+(*** Debug flag ***)
+
+let debug = ref false
+
+
+
+
+
--- /dev/null
+(** This module gives utility functions for creating terms and
+ simplifying them *)
+
+open Parameters
+open Cil_types
+module Varinfo = Cil_datatype.Varinfo
+module Stmt = Cil_datatype.Stmt
+module Term = Cil_datatype.Term
+module Logic_label = Cil_datatype.Logic_label
+
+(** {Add needed logic function} *)
+
+let get_max_logic_info, add_def_max_logic_info =
+ (* TODO the name can collide with other logic function *)
+ let module M = State_builder.Option_ref(Cil_datatype.Logic_info)
+ (struct
+ let name = "max_logic_fun"
+ let dependencies = [Annotations.self]
+ let kind = `Internal
+ end) in
+ let create () =
+ let x = Cil_const.make_logic_var "x" Linteger in
+ let y = Cil_const.make_logic_var "y" Linteger in
+ let tx = Logic_const.tvar x in let ty = Logic_const.tvar y in
+ let body =
+ let cond = Logic_const.term (TBinOp (Gt,tx,ty)) Linteger in
+ let term = Logic_const.term (Tif (cond,tx,ty)) Linteger in
+ term in
+ let signature = Larrow ([Linteger;Linteger],Linteger) in
+ let li = { l_var_info = Cil_const.make_logic_var "__max" signature;
+ l_labels = [];
+ l_tparams = [];
+ l_type = Some Linteger;
+ l_profile = [x;y];
+ l_body = LBterm body } in
+ li
+ in
+ (fun () -> M.memo create),
+ (fun () ->
+ match M.get_option () with
+ | None -> ()
+ | Some li ->
+ Globals.Annotations.add_generated
+ (Dfun_or_pred (li, Cil_datatype.Location.unknown)))
+
+
+(** {2 Simplify casts} *)
+(** Casts may get in the way when looking for a loop counter, just remove
+ them. *)
+
+let rec remove_casts e = match e.enode with
+ | Lval lval ->
+ { e with enode = Lval (remove_casts_lval lval) }
+ | SizeOfE e ->
+ { e with enode = SizeOfE (remove_casts e) }
+ | AlignOfE e ->
+ { e with enode = AlignOfE (remove_casts e) }
+ | UnOp (unop, e, typ) ->
+ { e with enode = UnOp (unop, remove_casts e, typ) }
+ | BinOp (binop, e1, e2, typ) ->
+ let enode =
+ BinOp (binop, remove_casts e1, remove_casts e2, typ) in
+ { e with enode }
+ | CastE (_, e) -> remove_casts e
+ | AddrOf lval ->
+ { e with enode = AddrOf (remove_casts_lval lval) }
+ | StartOf lval ->
+ { e with enode = StartOf (remove_casts_lval lval) }
+ | Info (e, info) ->
+ { e with enode = Info (remove_casts e, info) }
+ | _ -> e
+
+and remove_casts_lval (lhost, offset) =
+ (remove_casts_lhost lhost, remove_casts_offset offset)
+
+and remove_casts_lhost = function
+ | Mem e -> Mem (remove_casts e)
+ | lhost -> lhost
+
+and remove_casts_offset = function
+ | Field (fieldinfo, offset) ->
+ Field (fieldinfo, remove_casts_offset offset)
+ | Index (e, offset) ->
+ Index (remove_casts e, remove_casts_offset offset)
+ | offset -> offset
+
+
+(** {2 Simplify and convert terms} *)
+
+
+(*** Exceptions ***)
+exception Untranslatable_expr of exp
+
+let print_exception_raise fmt = function
+ | Untranslatable_expr exp ->
+ Format.fprintf fmt "Can't convert exp %a to term.@."
+ Cil.defaultCilPrinter#pExp exp;
+ | e -> raise e
+
+let print_exception fmt exn =
+ try
+ print_exception_raise fmt exn
+ with _ -> Format.fprintf fmt "%s" (Printexc.to_string exn)
+
+
+(** raised when a function call contains something that can't be translated to
+ term *)
+
+(** cost of incr_cost (cost of all the instruction until the next one) *)
+let rec term_of_exp e =
+ let open Cil_types in
+ match e.enode with
+ | Const (CInt64 _ as c) ->
+ Logic_const.term (TConst c) (Ctype (Cil.typeOf e))
+ | Lval (Var varinfo, offset) ->
+ let logic_var = Cil.cvar_to_lvar varinfo in
+ let offset = term_offset_of_offset offset in
+ Logic_const.term (TLval (TVar logic_var, offset)) (Ctype (Cil.typeOf e))
+ | Info (e, _) -> term_of_exp e
+ | UnOp (unop, e, typ) ->
+ Logic_const.term (TUnOp (unop, term_of_exp e)) (Ctype typ)
+ | BinOp (binop, e1, e2, typ) ->
+ Logic_const.term (TBinOp (binop, term_of_exp e1, term_of_exp e2))
+ (Ctype typ)
+ | CastE (typ, e) ->
+ Logic_const.term (TCastE (typ, term_of_exp e)) (Ctype typ)
+ | _ -> raise (Untranslatable_expr e)
+
+and term_offset_of_offset = function
+ | NoOffset -> TNoOffset
+ | Field (fi, offset) ->
+ TField(fi, term_offset_of_offset offset)
+ | Index (exp, offset) ->
+ TIndex(term_of_exp exp, term_offset_of_offset offset)
+
+let term_of_exp e =
+ let e = if remove_casts_in_annotations then remove_casts e else e in
+ term_of_exp e
+
+(** Same as before but use integer for all the types *)
+let term_of_cost_expr e =
+ match e.enode with
+ | Const (CInt64 _ as c) ->
+ Logic_const.term (TConst c) Linteger
+ (** TODO: convert the other function use integer when needed *)
+ | _ -> raise (Untranslatable_expr e)
+
+(** Operation simplifying (** same as termFoldConst ? *) *)
+
+let make_at label x =
+ let open Cil_types in
+ match x.term_node with
+ | TConst (CInt64 (_,_,_)) -> x
+ | _ -> Logic_const.tat (x,label)
+
+(** Use only for cost *)
+let make_max x y =
+ match x, y with
+ (** two constants *)
+ | {term_node = TConst (CInt64 (xn,_,_))},
+ {term_node = TConst (CInt64 (yn,_,_))} ->
+ (Cil.lconstant (My_bigint.max xn yn))
+ (* (\** one null *\) *) (* correct but dangerous *)
+ (* | {term_node = TConst (CInt64 (zero,_,_))}, other *)
+ (* | other, {term_node = TConst (CInt64 (zero,_,_))} *)
+ (* when My_bigint.is_zero zero -> other *)
+ (** generic case *)
+ | x, y ->
+ Logic_const.term (Tapp (get_max_logic_info (), [], [x;y])) Linteger
+
+let make_max_opt x y =
+ match x, y with
+ (** one inaccessible *)
+ | None, other | other, None -> other
+ | Some x, Some y -> Some (make_max x y)
+
+let make_sign = function
+ (** two constants *)
+ | {term_node = TConst (CInt64 (xn,_,_))} ->
+ if My_bigint.ge xn My_bigint.zero
+ then (Cil.lconstant (My_bigint.one))
+ else (Cil.lconstant (My_bigint.minus_one))
+ (* (\** one null *\) *) (* correct but dangerous *)
+ (* | {term_node = TConst (CInt64 (zero,_,_))}, other *)
+ (* | other, {term_node = TConst (CInt64 (zero,_,_))} *)
+ (* when My_bigint.is_zero zero -> other *)
+ (** generic case *)
+ | x ->
+ let cond = Logic_const.term (TBinOp (Ge,x,Cil.lzero ())) Linteger in
+ let term = Logic_const.term (Tif (cond,
+ (Cil.lconstant (My_bigint.one)),
+ (Cil.lconstant (My_bigint.minus_one))))
+ Linteger in
+ term
+
+let make_unop unop x =
+ match unop, x.term_node with
+ | Neg, TUnOp(Neg,y) -> y
+ | Neg, TConst (CInt64 (xn,_,_)) -> Cil.lconstant (My_bigint.neg xn)
+ | _ -> Logic_const.term (TUnOp (unop,x)) Linteger
+
+let make_binop binop x y =
+ match binop, x.term_node, y.term_node with
+ | PlusA, TConst (CInt64 (xn,_,_)), TConst (CInt64 (yn,_,_)) ->
+ Cil.lconstant (My_bigint.add xn yn)
+ | PlusA, TConst (CInt64 (zero,_,_)), _ when My_bigint.is_zero zero -> y
+ | PlusA, _, TConst (CInt64 (zero,_,_)) when My_bigint.is_zero zero -> x
+
+ | MinusA, TConst (CInt64 (xn,_,_)), TConst (CInt64 (yn,_,_)) ->
+ Cil.lconstant (My_bigint.sub xn yn)
+ | MinusA, TConst (CInt64 (zero,_,_)), _ when My_bigint.is_zero zero ->
+ make_unop Neg y
+ | MinusA, _, TConst (CInt64 (zero,_,_)) when My_bigint.is_zero zero -> x
+ | Mult, TConst (CInt64 (xn,_,_)), TConst (CInt64 (yn,_,_)) ->
+ Cil.lconstant (My_bigint.mul xn yn)
+ | Mult, TConst (CInt64 (zero,_,_)), _ when My_bigint.is_zero zero -> x
+ | Mult, _, TConst (CInt64 (zero,_,_)) when My_bigint.is_zero zero -> y
+ | Mult, TConst (CInt64 (one,_,_)), _ when My_bigint.is_one one -> y
+ | Mult, _, TConst (CInt64 (one,_,_)) when My_bigint.is_one one -> x
+ | Div, TConst (CInt64 (xn,_,_)), TConst (CInt64 (yn,_,_)) ->
+ Cil.lconstant (My_bigint.div xn yn)
+ (* | Div, TConst (CInt64 (zero,_,_)), _ when My_bigint.is_zero zero -> x *)
+ (* | Div, _, TConst (CInt64 (zero,_,_)) when My_bigint.is_zero zero -> y *)
+ | Div, _, TConst (CInt64 (one,_,_)) when My_bigint.is_one one -> x
+ | Div, _, TConst (CInt64 (minus_one,_,_))
+ when My_bigint.equal My_bigint.minus_one minus_one ->
+ make_unop Neg x
+ | _ -> Logic_const.term (TBinOp (binop,x,y)) Linteger
+
+let simplify_term_top t =
+ match t.term_node with
+ | TBinOp(binop,x,y) -> make_binop binop x y
+ | TUnOp(unop,x) -> make_unop unop x
+ | Tif({term_node =
+ TBinOp ((Lt|Le|Gt|Ge|Eq|Ne) as rel,
+ {term_node = TConst (CInt64 (xn,_,_))},
+ {term_node = TConst (CInt64 (yn,_,_))})},t1,t2) ->
+ let b = match rel with
+ | Lt -> My_bigint.lt xn yn
+ | Gt -> My_bigint.gt xn yn
+ | Le -> My_bigint.le xn yn
+ | Ge -> My_bigint.ge xn yn
+ | Eq -> My_bigint.equal xn yn
+ | Ne -> not (My_bigint.equal xn yn)
+ | _ -> assert false in
+ if b then t1 else t2
+ | Tapp(f, [], [{term_node = TConst (CInt64 (xn,_,_))} as xt;
+ {term_node = TConst (CInt64 (yn,_,_))} as yt]) when
+ Cil_datatype.Logic_info.equal f (get_max_logic_info ()) ->
+ if My_bigint.gt xn yn then xt else yt
+ | _ -> t
+
+class simplify_term prj =
+object inherit Visitor.frama_c_copy prj as super
+ method vterm term = Cil.ChangeDoChildrenPost(term,simplify_term_top)
+end
+
+let rec top_const_form t =
+ match t.term_node with
+ | TConst _ -> t, (Cil.lzero ())
+ | TUnOp(unop,x) ->
+ let cx,x = top_const_form x in
+ begin match unop with
+ | Neg -> make_unop unop cx, make_unop unop x
+ | _ -> (Cil.lzero ()),
+ Logic_const.term (TUnOp (unop,make_binop PlusA cx x)) Linteger end
+ | TBinOp(binop,x,y) ->
+ let cx,x = top_const_form x in
+ let cy,y = top_const_form y in
+ begin match binop with
+ | PlusA -> make_binop binop cx cy, make_binop binop x y
+ | MinusA -> make_binop binop cx cy, make_binop binop x y
+ | Mult -> make_binop binop cx cy,
+ make_binop PlusA (make_binop binop x y)
+ (make_binop PlusA (make_binop binop cx y)
+ (make_binop binop cy x))
+ | _ -> (Cil.lzero ()),
+ Logic_const.term (TBinOp (binop, make_binop PlusA cx x,
+ make_binop PlusA cy y)) Linteger end
+ | Tif(t1,t2,t3) ->
+ let c1,t1 = top_const_form t1 in
+ let c2,t2 = top_const_form t2 in
+ let c3,t3 = top_const_form t3 in
+ Cil.lzero (),
+ Logic_const.term (Tif(make_binop PlusA c1 t1,
+ make_binop PlusA c2 t2,
+ make_binop PlusA c3 t3)) Linteger
+ | Tapp(f, labs, l) ->
+ Cil.lzero (),
+ Logic_const.term
+ (Tapp(f, labs, List.map (fun t -> let c,t = top_const_form t in
+ make_binop PlusA c t) l))
+ Linteger
+ | _ -> (Cil.lzero ()),t
+
+
+let top_const_form t =
+ let ct,t = top_const_form t in
+ make_binop PlusA ct t
+
+let simplify_term term =
+ let term =
+ Visitor.visitFramacTerm (new simplify_term (Project.current ())) term in
+ if put_const_at_the_top_in_annotations then top_const_form term else term
+
+
+(** {2 Simply labels} *)
+
+class subst_lval subst prj =
+object inherit Visitor.frama_c_copy prj as super
+ method vterm term =
+ let open Cil_types in
+ match term.term_node with
+ | TLval (TVar {lv_origin = Some vi},TNoOffset)
+ when Varinfo.Map.mem vi subst ->
+ Cil.ChangeTo (Varinfo.Map.find vi subst)
+ | _ -> Cil.DoChildren
+
+end
+
+class subst_with_label stmt_label subst prj =
+object inherit Visitor.frama_c_copy prj as super
+ method vterm term =
+ let open Cil_types in
+ match term.term_node with
+ | TLval (TVar {lv_origin = Some vi},TNoOffset) (**TODO other offset *)
+ when Varinfo.Map.mem vi subst ->
+ Cil.ChangeTo (Varinfo.Map.find vi subst)
+ | Tat _ -> Cil.JustCopy (* don't touch if we don't see it *)
+ | _ -> Cil.ChangeDoChildrenPost(term,simplify_term_top)
+
+end
+
+class remove_stmt_label stmt_label prj =
+object inherit Visitor.frama_c_copy prj as super
+ method vterm term =
+ let open Cil_types in
+ match term.term_node with
+ | Tat(t, (LogicLabel (Some stmt,_)))
+ when Stmt.equal stmt stmt_label ->
+ Cil.ChangeTo t
+ | Tapp(li,l,t) ->
+ let rec filter_label l =
+ match l with
+ | [] -> l
+ (** TODO understand what the differences between la and lb *)
+ | (( LogicLabel(Some stmt,_),_) | (_,LogicLabel(Some stmt,_)))::ll
+ when Stmt.equal stmt stmt_label -> filter_label ll
+ | a::ll ->
+ let ll' = filter_label ll in
+ if ll == ll' then l else a::ll' in
+ let l' = filter_label l in
+ if l == l' then Cil.DoChildren
+ else Cil.ChangeDoChildrenPost
+ ({term with term_node = Tapp(li,l',t)},fun x -> x)
+ | _ -> Cil.DoChildren
+end
+
+
+class remove_logic_label lab prj =
+object inherit Visitor.frama_c_copy prj as super
+ method vterm term =
+ let open Cil_types in
+ match term.term_node with
+ | Tat(t, label)
+ when Logic_label.equal label lab ->
+ Cil.ChangeTo t
+ | Tapp(li,l,t) ->
+ let rec filter_label l =
+ match l with
+ | [] -> l
+ (** TODO understand what the differences between la and lb *)
+ | (label1,label2)::ll
+ when Logic_label.equal label1 lab ||
+ Logic_label.equal label2 lab -> filter_label ll
+ | a::ll ->
+ let ll' = filter_label ll in
+ if ll == ll' then l else a::ll' in
+ let l' = filter_label l in
+ if l == l' then Cil.DoChildren
+ else Cil.ChangeDoChildrenPost
+ ({term with term_node = Tapp(li,l',t)},fun x -> x)
+ | _ -> Cil.DoChildren
+end
+
+let remove_logic_label lab cost =
+ Visitor.visitFramacTerm
+ (new remove_logic_label lab (Project.current ()))
+ cost
+
+
+let rec freevar acc t =
+ match t.term_node with
+ | TConst _ -> acc
+ | TUnOp(_,x) -> freevar acc x
+ | TBinOp(_,x,y) -> freevar (freevar acc x) y
+ | Tif(t1,t2,t3) -> freevar (freevar (freevar acc t1) t2) t3
+ | Tapp(_, _, l) -> List.fold_left freevar acc l
+ | Tat(t,_) -> freevar acc t
+ | (TLval(TVar lv,_)) -> Cil_datatype.Logic_var.Set.add lv acc
+ | _ -> assert false
+
+
+let tapp li args =
+ let cast lv t =
+ match lv.lv_type with
+ | Ctype typ ->
+ (** the main handle cases is t is an integer, lv an is int so we
+ need a cast (int)t *)
+ (* if Logic_utils.is_same_type lv.lv_type t.term_type *)
+ (* then t *)
+ (* else *) Logic_const.term (TCastE(typ,t)) lv.lv_type
+ | _ -> t in
+ let args = List.map2 cast li.l_profile args in
+ Tapp(li,[],args)
--- /dev/null
+/*\r
+ * Author : Paul Kocher\r
+ * E-mail : pck@netcom.com\r
+ * Date : 1997\r
+ * Description: C implementation of the Blowfish algorithm.\r
+ */\r
+\r
+#include "blowfish.h"\r
+\r
+\r
+\r
+#define N 16\r
+\r
+\r
+\r
+static unsigned long F(BLOWFISH_CTX *ctx, unsigned long x);\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+static const unsigned long ORIG_P[16 + 2] = {\r
+\r
+ 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,\r
+\r
+ 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,\r
+\r
+ 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,\r
+\r
+ 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,\r
+\r
+ 0x9216D5D9L, 0x8979FB1BL\r
+\r
+};\r
+\r
+\r
+\r
+static const unsigned long ORIG_S[4][256] = {\r
+\r
+ { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,\r
+\r
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,\r
+\r
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,\r
+\r
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,\r
+\r
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,\r
+\r
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,\r
+\r
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,\r
+\r
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,\r
+\r
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,\r
+\r
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,\r
+\r
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,\r
+\r
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,\r
+\r
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,\r
+\r
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,\r
+\r
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,\r
+\r
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,\r
+\r
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,\r
+\r
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,\r
+\r
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,\r
+\r
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,\r
+\r
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,\r
+\r
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,\r
+\r
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,\r
+\r
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,\r
+\r
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,\r
+\r
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,\r
+\r
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,\r
+\r
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,\r
+\r
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,\r
+\r
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,\r
+\r
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,\r
+\r
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,\r
+\r
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,\r
+\r
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,\r
+\r
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,\r
+\r
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,\r
+\r
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,\r
+\r
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,\r
+\r
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,\r
+\r
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,\r
+\r
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,\r
+\r
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,\r
+\r
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,\r
+\r
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,\r
+\r
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,\r
+\r
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,\r
+\r
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,\r
+\r
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,\r
+\r
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,\r
+\r
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,\r
+\r
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,\r
+\r
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,\r
+\r
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,\r
+\r
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,\r
+\r
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,\r
+\r
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,\r
+\r
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,\r
+\r
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,\r
+\r
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,\r
+\r
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,\r
+\r
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,\r
+\r
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,\r
+\r
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,\r
+\r
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },\r
+\r
+ { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,\r
+\r
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,\r
+\r
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,\r
+\r
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,\r
+\r
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,\r
+\r
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,\r
+\r
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,\r
+\r
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,\r
+\r
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,\r
+\r
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,\r
+\r
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,\r
+\r
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,\r
+\r
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,\r
+\r
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,\r
+\r
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,\r
+\r
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,\r
+\r
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,\r
+\r
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,\r
+\r
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,\r
+\r
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,\r
+\r
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,\r
+\r
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,\r
+\r
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,\r
+\r
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,\r
+\r
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,\r
+\r
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,\r
+\r
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,\r
+\r
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,\r
+\r
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,\r
+\r
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,\r
+\r
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,\r
+\r
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,\r
+\r
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,\r
+\r
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,\r
+\r
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,\r
+\r
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,\r
+\r
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,\r
+\r
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,\r
+\r
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,\r
+\r
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,\r
+\r
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,\r
+\r
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,\r
+\r
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,\r
+\r
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,\r
+\r
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,\r
+\r
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,\r
+\r
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,\r
+\r
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,\r
+\r
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,\r
+\r
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,\r
+\r
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,\r
+\r
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,\r
+\r
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,\r
+\r
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,\r
+\r
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,\r
+\r
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,\r
+\r
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,\r
+\r
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,\r
+\r
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,\r
+\r
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,\r
+\r
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,\r
+\r
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,\r
+\r
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,\r
+\r
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },\r
+\r
+ { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,\r
+\r
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,\r
+\r
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,\r
+\r
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,\r
+\r
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,\r
+\r
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,\r
+\r
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,\r
+\r
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,\r
+\r
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,\r
+\r
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,\r
+\r
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,\r
+\r
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,\r
+\r
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,\r
+\r
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,\r
+\r
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,\r
+\r
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,\r
+\r
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,\r
+\r
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,\r
+\r
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,\r
+\r
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,\r
+\r
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,\r
+\r
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,\r
+\r
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,\r
+\r
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,\r
+\r
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,\r
+\r
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,\r
+\r
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,\r
+\r
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,\r
+\r
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,\r
+\r
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,\r
+\r
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,\r
+\r
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,\r
+\r
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,\r
+\r
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,\r
+\r
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,\r
+\r
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,\r
+\r
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,\r
+\r
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,\r
+\r
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,\r
+\r
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,\r
+\r
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,\r
+\r
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,\r
+\r
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,\r
+\r
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,\r
+\r
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,\r
+\r
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,\r
+\r
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,\r
+\r
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,\r
+\r
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,\r
+\r
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,\r
+\r
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,\r
+\r
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,\r
+\r
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,\r
+\r
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,\r
+\r
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,\r
+\r
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,\r
+\r
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,\r
+\r
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,\r
+\r
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,\r
+\r
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,\r
+\r
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,\r
+\r
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,\r
+\r
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,\r
+\r
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },\r
+\r
+ { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,\r
+\r
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,\r
+\r
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,\r
+\r
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,\r
+\r
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,\r
+\r
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,\r
+\r
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,\r
+\r
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,\r
+\r
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,\r
+\r
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,\r
+\r
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,\r
+\r
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,\r
+\r
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,\r
+\r
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,\r
+\r
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,\r
+\r
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,\r
+\r
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,\r
+\r
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,\r
+\r
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,\r
+\r
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,\r
+\r
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,\r
+\r
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,\r
+\r
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,\r
+\r
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,\r
+\r
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,\r
+\r
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,\r
+\r
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,\r
+\r
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,\r
+\r
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,\r
+\r
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,\r
+\r
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,\r
+\r
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,\r
+\r
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,\r
+\r
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,\r
+\r
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,\r
+\r
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,\r
+\r
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,\r
+\r
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,\r
+\r
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,\r
+\r
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,\r
+\r
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,\r
+\r
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,\r
+\r
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,\r
+\r
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,\r
+\r
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,\r
+\r
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,\r
+\r
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,\r
+\r
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,\r
+\r
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,\r
+\r
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,\r
+\r
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,\r
+\r
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,\r
+\r
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,\r
+\r
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,\r
+\r
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,\r
+\r
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,\r
+\r
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,\r
+\r
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,\r
+\r
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,\r
+\r
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,\r
+\r
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,\r
+\r
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,\r
+\r
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,\r
+\r
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }\r
+\r
+};\r
+\r
+\r
+\r
+\r
+\r
+unsigned long F(BLOWFISH_CTX *ctx, unsigned long x) {\r
+\r
+ unsigned short a, b, c, d;\r
+\r
+ unsigned long y;\r
+\r
+\r
+\r
+ d = x & 0x00FF;\r
+\r
+ x >>= 8;\r
+\r
+ c = x & 0x00FF;\r
+\r
+ x >>= 8;\r
+\r
+ b = x & 0x00FF;\r
+\r
+ x >>= 8;\r
+\r
+ a = x & 0x00FF;\r
+\r
+ y = ctx->S[0][a] + ctx->S[1][b];\r
+\r
+ y = y ^ ctx->S[2][c];\r
+\r
+ y = y + ctx->S[3][d];\r
+\r
+\r
+\r
+ return y;\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+void Blowfish_Encrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long\r
+*xr) {\r
+\r
+ unsigned long Xl;\r
+\r
+ unsigned long Xr;\r
+\r
+ unsigned long temp;\r
+\r
+ short i;\r
+\r
+\r
+\r
+ Xl = *xl;\r
+\r
+ Xr = *xr;\r
+\r
+\r
+\r
+ for (i = 0; i < N; ++i) {\r
+\r
+ Xl = Xl ^ ctx->P[i];\r
+\r
+ Xr = F(ctx, Xl) ^ Xr;\r
+\r
+\r
+\r
+ temp = Xl;\r
+\r
+ Xl = Xr;\r
+\r
+ Xr = temp;\r
+\r
+ }\r
+\r
+\r
+\r
+ temp = Xl;\r
+\r
+ Xl = Xr;\r
+\r
+ Xr = temp;\r
+\r
+\r
+\r
+ Xr = Xr ^ ctx->P[N];\r
+\r
+ Xl = Xl ^ ctx->P[N + 1];\r
+\r
+\r
+\r
+ *xl = Xl;\r
+\r
+ *xr = Xr;\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long\r
+*xr) {\r
+\r
+ unsigned long Xl;\r
+\r
+ unsigned long Xr;\r
+\r
+ unsigned long temp;\r
+\r
+ short i;\r
+\r
+\r
+\r
+ Xl = *xl;\r
+\r
+ Xr = *xr;\r
+\r
+\r
+\r
+ for (i = N + 1; i > 1; --i) {\r
+\r
+ Xl = Xl ^ ctx->P[i];\r
+\r
+ Xr = F(ctx, Xl) ^ Xr;\r
+\r
+\r
+\r
+ /* Exchange Xl and Xr */\r
+\r
+ temp = Xl;\r
+\r
+ Xl = Xr;\r
+\r
+ Xr = temp;\r
+\r
+ }\r
+\r
+\r
+\r
+ /* Exchange Xl and Xr */\r
+\r
+ temp = Xl;\r
+\r
+ Xl = Xr;\r
+\r
+ Xr = temp;\r
+\r
+\r
+\r
+ Xr = Xr ^ ctx->P[1];\r
+\r
+ Xl = Xl ^ ctx->P[0];\r
+\r
+\r
+\r
+ *xl = Xl;\r
+\r
+ *xr = Xr;\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) {\r
+\r
+ int i, j, k;\r
+\r
+ unsigned long data, datal, datar;\r
+\r
+\r
+\r
+ for (i = 0; i < 4; i++) {\r
+\r
+ for (j = 0; j < 256; j++)\r
+\r
+ ctx->S[i][j] = ORIG_S[i][j];\r
+\r
+ }\r
+\r
+\r
+\r
+ j = 0;\r
+\r
+ for (i = 0; i < N + 2; ++i) {\r
+\r
+ data = 0x00000000;\r
+\r
+ for (k = 0; k < 4; ++k) {\r
+\r
+ data = (data << 8) | key[j];\r
+\r
+ j = j + 1;\r
+\r
+ if (j >= keyLen)\r
+\r
+ j = 0;\r
+\r
+ }\r
+\r
+ ctx->P[i] = ORIG_P[i] ^ data;\r
+\r
+ }\r
+\r
+\r
+\r
+ datal = 0x00000000;\r
+\r
+ datar = 0x00000000;\r
+\r
+\r
+\r
+ for (i = 0; i < N + 2; i += 2) {\r
+\r
+ Blowfish_Encrypt(ctx, &datal, &datar);\r
+\r
+ ctx->P[i] = datal;\r
+\r
+ ctx->P[i + 1] = datar;\r
+\r
+ }\r
+\r
+\r
+\r
+ for (i = 0; i < 4; ++i) {\r
+\r
+ for (j = 0; j < 256; j += 2) {\r
+\r
+ Blowfish_Encrypt(ctx, &datal, &datar);\r
+\r
+ ctx->S[i][j] = datal;\r
+\r
+ ctx->S[i][j + 1] = datar;\r
+\r
+ }\r
+\r
+ }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+int Blowfish_Test(BLOWFISH_CTX *ctx) {\r
+\r
+ unsigned long L = 1, R = 2;\r
+\r
+\r
+\r
+ Blowfish_Init (ctx, (unsigned char*)"TESTKEY", 7);\r
+\r
+ Blowfish_Encrypt(ctx, &L, &R);\r
+\r
+ if (L != 0xDF333FD2L || R != 0x30A71BB4L)\r
+\r
+ return (-1);\r
+\r
+ Blowfish_Decrypt(ctx, &L, &R);\r
+\r
+ if (L != 1 || R != 2)\r
+\r
+ return (-1);\r
+\r
+ return (0);\r
+\r
+}\r
+\r
+\r
+\r
--- /dev/null
+/*\r
+ * Author : Paul Kocher\r
+ * E-mail : pck@netcom.com\r
+ * Date : 1997\r
+ * Description: C implementation of the Blowfish algorithm.\r
+ */\r
+\r
+#define MAXKEYBYTES 56 /* 448 bits */\r
+\r
+\r
+\r
+typedef struct {\r
+\r
+ unsigned long P[16 + 2];\r
+\r
+ unsigned long S[4][256];\r
+\r
+} BLOWFISH_CTX;\r
+\r
+\r
+\r
+void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen);\r
+\r
+void Blowfish_Encrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long\r
+*xr);\r
+\r
+void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long\r
+*xr);\r
+\r
+int Blowfish_Test(BLOWFISH_CTX *ctx); /* 0=ok, -1=bad */\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+
+#define SIZE 5
+
+void swap (int tab[], int i, int j) {
+ int t;
+ t = tab[i] ; tab[i] = tab[j] ; tab[j] = t;
+ return;
+}
+
+void bubble_sort(int tab[], int size) {
+ int i, j, min, min_index;
+
+ for (i = 0 ; i < size ; i++) {
+ min_index = i;
+ min = tab[min_index];
+ for (j = i + 1 ; j < size ; j++) {
+ if (tab[j] < min) {
+ min_index = j;
+ min = tab[min_index];
+ }
+ }
+ swap(tab, i, min_index);
+ }
+ return;
+}
+
+/*
+void print_tab (int tab[], int size) {
+ int i;
+
+ for (i = 0 ; i < size ; i++) {
+ print_sint(tab[i]);
+ space();
+ }
+ newline();
+}
+
+int main () {
+ int tab[SIZE] = {26, -21, 43, -62, 8};
+
+ bubble_sort(tab, SIZE);
+ print_tab(tab, SIZE);
+
+ return 0;
+}
+*/
--- /dev/null
+/********************************************************************\\r
+* *\r
+* C specification of the threeway block cipher *\r
+* *\r
+\********************************************************************/\r
+/*file i/o main function by Pate Williams 1996*/\r
+\r
+#include <ctype.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#define STRT_E 0x0b0b /* round constant of first encryption round */\r
+#define STRT_D 0xb1b1 /* round constant of first decryption round */\r
+#define NMBR 11 /* number of rounds is 11 */\r
+\r
+#define BLK_SIZE 12 /*number of bytes per block*/\r
+\r
+typedef unsigned long int word32 ;\r
+ /* the program only works correctly if long = 32bits */\r
+\r
+void mu(word32 *a) /* inverts the order of the bits of a */\r
+{\r
+int i ;\r
+word32 b[3] ;\r
+\r
+b[0] = b[1] = b[2] = 0 ;\r
+for( i=0 ; i<32 ; i++ )\r
+ {\r
+ b[0] <<= 1 ; b[1] <<= 1 ; b[2] <<= 1 ;\r
+ if(a[0]&1) b[2] |= 1 ;\r
+ if(a[1]&1) b[1] |= 1 ;\r
+ if(a[2]&1) b[0] |= 1 ;\r
+ a[0] >>= 1 ; a[1] >>= 1 ; a[2] >>= 1 ;\r
+ }\r
+\r
+a[0] = b[0] ; a[1] = b[1] ; a[2] = b[2] ;\r
+}\r
+\r
+void gamma(word32 *a) /* the nonlinear step */\r
+{\r
+word32 b[3] ;\r
+\r
+b[0] = a[0] ^ (a[1]|(~a[2])) ;\r
+b[1] = a[1] ^ (a[2]|(~a[0])) ;\r
+b[2] = a[2] ^ (a[0]|(~a[1])) ;\r
+\r
+a[0] = b[0] ; a[1] = b[1] ; a[2] = b[2] ;\r
+}\r
+\r
+void theta(word32 *a) /* the linear step */\r
+{\r
+word32 b[3];\r
+\r
+b[0] = a[0] ^ (a[0]>>16) ^ (a[1]<<16) ^ (a[1]>>16) ^ (a[2]<<16) ^\r
+ (a[1]>>24) ^ (a[2]<<8) ^ (a[2]>>8) ^ (a[0]<<24) ^\r
+ (a[2]>>16) ^ (a[0]<<16) ^ (a[2]>>24) ^ (a[0]<<8) ;\r
+b[1] = a[1] ^ (a[1]>>16) ^ (a[2]<<16) ^ (a[2]>>16) ^ (a[0]<<16) ^\r
+ (a[2]>>24) ^ (a[0]<<8) ^ (a[0]>>8) ^ (a[1]<<24) ^\r
+ (a[0]>>16) ^ (a[1]<<16) ^ (a[0]>>24) ^ (a[1]<<8) ;\r
+b[2] = a[2] ^ (a[2]>>16) ^ (a[0]<<16) ^ (a[0]>>16) ^ (a[1]<<16) ^\r
+ (a[0]>>24) ^ (a[1]<<8) ^ (a[1]>>8) ^ (a[2]<<24) ^\r
+ (a[1]>>16) ^ (a[2]<<16) ^ (a[1]>>24) ^ (a[2]<<8) ;\r
+\r
+a[0] = b[0] ; a[1] = b[1] ; a[2] = b[2] ;\r
+}\r
+\r
+void pi_1(word32 *a)\r
+{\r
+a[0] = (a[0]>>10) ^ (a[0]<<22);\r
+a[2] = (a[2]<<1) ^ (a[2]>>31);\r
+}\r
+\r
+void pi_2(word32 *a)\r
+{\r
+a[0] = (a[0]<<1) ^ (a[0]>>31);\r
+a[2] = (a[2]>>10) ^ (a[2]<<22);\r
+}\r
+\r
+void rho(word32 *a) /* the round function */\r
+{\r
+theta(a) ;\r
+pi_1(a) ;\r
+gamma(a) ;\r
+pi_2(a) ;\r
+}\r
+\r
+void rndcon_gen(word32 strt,word32 *rtab)\r
+{ /* generates the round constants */\r
+int i ;\r
+\r
+for(i=0 ; i<=NMBR ; i++ )\r
+ {\r
+ rtab[i] = strt ;\r
+ strt <<= 1 ;\r
+ if( strt&0x10000 ) strt ^= 0x11011 ;\r
+ }\r
+}\r
+\r
+void encrypt(word32 *a, word32 *k)\r
+{\r
+char i ;\r
+word32 rcon[NMBR+1] ;\r
+\r
+rndcon_gen(STRT_E,rcon) ;\r
+for( i=0 ; i<NMBR ; i++ )\r
+ {\r
+ a[0] ^= k[0] ^ (rcon[i]<<16) ;\r
+ a[1] ^= k[1] ;\r
+ a[2] ^= k[2] ^ rcon[i] ;\r
+ rho(a) ;\r
+ }\r
+a[0] ^= k[0] ^ (rcon[NMBR]<<16) ;\r
+a[1] ^= k[1] ;\r
+a[2] ^= k[2] ^ rcon[NMBR] ;\r
+theta(a) ;\r
+}\r
+\r
+void decrypt(word32 *a, word32 *k)\r
+{\r
+char i ;\r
+word32 ki[3] ; /* the `inverse' key */\r
+word32 rcon[NMBR+1] ; /* the `inverse' round constants */\r
+\r
+ki[0] = k[0] ; ki[1] = k[1] ; ki[2] = k[2] ;\r
+theta(ki) ;\r
+mu(ki) ;\r
+\r
+rndcon_gen(STRT_D,rcon) ;\r
+\r
+mu(a) ;\r
+for( i=0 ; i<NMBR ; i++ )\r
+ {\r
+ a[0] ^= ki[0] ^ (rcon[i]<<16) ;\r
+ a[1] ^= ki[1] ;\r
+ a[2] ^= ki[2] ^ rcon[i] ;\r
+ rho(a) ;\r
+ }\r
+a[0] ^= ki[0] ^ (rcon[NMBR]<<16) ;\r
+a[1] ^= ki[1] ;\r
+a[2] ^= ki[2] ^ rcon[NMBR] ;\r
+theta(a) ;\r
+mu(a) ;\r
+}\r
--- /dev/null
+/*
+ * In writing this program, I've had to guess a few pices of information:
+ *
+ * 1. Which bits of the key are loaded into which bits of the shift register
+ * 2. Which order the frame sequence number is shifted into the SR (MSB
+ * first or LSB first)
+ * 3. The position of the feedback taps on R2 and R3 (R1 is known).
+ * 4. The position of the clock control taps. These are on the `middle' one,
+ * I've assumed to be 9 on R1, 11 on R2, 11 on R3.
+ */
+
+/*
+ * Look at the `middle' stage of each of the 3 shift registers.
+ * Either 0, 1, 2 or 3 of these 3 taps will be set high.
+ * If 0 or 1 or one of them are high, return true. This will cause each of
+ * the middle taps to be inverted before being used as a clock control. In
+ * all cases either 2 or 3 of the clock enable lines will be active. Thus,
+ * at least two shift registers change on every clock-tick and the system
+ * never becomes stuck.
+ */
+
+static int threshold(r1, r2, r3)
+unsigned int r1;
+unsigned int r2;
+unsigned int r3;
+{
+int total;
+
+ total = (((r1 >> 9) & 0x1) == 1) +
+ (((r2 >> 11) & 0x1) == 1) +
+ (((r3 >> 11) & 0x1) == 1);
+
+ if (total > 1)
+ return (0);
+ else
+ return (1);
+}
+
+unsigned long clock_r1(ctl, r1)
+int ctl;
+unsigned long r1;
+{
+unsigned long feedback;
+
+ /*
+ * Primitive polynomial x**19 + x**5 + x**2 + x + 1
+ */
+
+ ctl ^= ((r1 >> 9) & 0x1);
+ if (ctl)
+ {
+ feedback = (r1 >> 18) ^ (r1 >> 17) ^ (r1 >> 16) ^ (r1 >> 13);
+ r1 = (r1 << 1) & 0x7ffff;
+ if (feedback & 0x01)
+ r1 ^= 0x01;
+ }
+ return (r1);
+}
+
+unsigned long clock_r2(ctl, r2)
+int ctl;
+unsigned long r2;
+{
+unsigned long feedback;
+
+
+ /*
+ * Primitive polynomial x**22 + x**9 + x**5 + x + 1
+ */
+
+ ctl ^= ((r2 >> 11) & 0x1);
+ if (ctl)
+ {
+ feedback = (r2 >> 21) ^ (r2 >> 20) ^ (r2 >> 16) ^ (r2 >> 12);
+ r2 = (r2 << 1) & 0x3fffff;
+ if (feedback & 0x01)
+ r2 ^= 0x01;
+ }
+ return (r2);
+}
+
+unsigned long clock_r3(ctl, r3)
+int ctl;
+unsigned long r3;
+{
+unsigned long feedback;
+
+ /*
+ * Primitive polynomial x**23 + x**5 + x**4 + x + 1
+ */
+
+ ctl ^= ((r3 >> 11) & 0x1);
+ if (ctl)
+ {
+ feedback = (r3 >> 22) ^ (r3 >> 21) ^ (r3 >> 18) ^ (r3 >> 17);
+ r3 = (r3 << 1) & 0x7fffff;
+ if (feedback & 0x01)
+ r3 ^= 0x01;
+ }
+ return (r3);
+}
+
+int keystream(key, frame, alice, bob)
+unsigned char *key; /* 64 bit session key */
+unsigned long frame; /* 22 bit frame sequence number */
+unsigned char *alice; /* 114 bit Alice to Bob key stream */
+unsigned char *bob; /* 114 bit Bob to Alice key stream */
+{
+unsigned long r1; /* 19 bit shift register */
+unsigned long r2; /* 22 bit shift register */
+unsigned long r3; /* 23 bit shift register */
+int i; /* counter for loops */
+int clock_ctl; /* xored with clock enable on each shift register */
+unsigned char *ptr; /* current position in keystream */
+unsigned char byte; /* byte of keystream being assembled */
+unsigned int bits; /* number of bits of keystream in byte */
+unsigned int bit; /* bit output from keystream generator */
+
+ /* Initialise shift registers from session key */
+
+ r1 = (key[0] | (key[1] << 8) | (key[2] << 16) ) & 0x7ffff;
+ r2 = ((key[2] >> 3) | (key[3] << 5) | (key[4] << 13) | (key[5] << 21)) & 0x3fffff;
+ r3 = ((key[5] >> 1) | (key[6] << 7) | (key[7] << 15) ) & 0x7fffff;
+
+
+ /* Merge frame sequence number into shift register state, by xor'ing it
+ * into the feedback path
+ */
+
+ for (i=0;i<22;i++)
+ {
+ clock_ctl = threshold(r1, r2, r2);
+ r1 = clock_r1(clock_ctl, r1);
+ r2 = clock_r2(clock_ctl, r2);
+ r3 = clock_r3(clock_ctl, r3);
+ if (frame & 1)
+ {
+ r1 ^= 1;
+ r2 ^= 1;
+ r3 ^= 1;
+ }
+ frame = frame >> 1;
+ }
+
+ /* Run shift registers for 100 clock ticks to allow frame number to
+ * be diffused into all the bits of the shift registers
+ */
+
+ for (i=0;i<100;i++)
+ {
+ clock_ctl = threshold(r1, r2, r2);
+ r1 = clock_r1(clock_ctl, r1);
+ r2 = clock_r2(clock_ctl, r2);
+ r3 = clock_r3(clock_ctl, r3);
+ }
+
+ /* Produce 114 bits of Alice->Bob key stream */
+
+ ptr = alice;
+ bits = 0;
+ byte = 0;
+ for (i=0;i<114;i++)
+ {
+ clock_ctl = threshold(r1, r2, r2);
+ r1 = clock_r1(clock_ctl, r1);
+ r2 = clock_r2(clock_ctl, r2);
+ r3 = clock_r3(clock_ctl, r3);
+
+ bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
+ byte = (byte << 1) | bit;
+ bits++;
+ if (bits == 8)
+ {
+ *ptr = byte;
+ ptr++;
+ bits = 0;
+ byte = 0;
+ }
+ }
+ if (bits)
+ *ptr = byte;
+
+ /* Run shift registers for another 100 bits to hide relationship between
+ * Alice->Bob key stream and Bob->Alice key stream.
+ */
+
+ for (i=0;i<100;i++)
+ {
+ clock_ctl = threshold(r1, r2, r2);
+ r1 = clock_r1(clock_ctl, r1);
+ r2 = clock_r2(clock_ctl, r2);
+ r3 = clock_r3(clock_ctl, r3);
+ }
+
+ /* Produce 114 bits of Bob->Alice key stream */
+
+ ptr = bob;
+ bits = 0;
+ byte = 0;
+ for (i=0;i<114;i++)
+ {
+ clock_ctl = threshold(r1, r2, r2);
+ r1 = clock_r1(clock_ctl, r1);
+ r2 = clock_r2(clock_ctl, r2);
+ r3 = clock_r3(clock_ctl, r3);
+
+ bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
+ byte = (byte << 1) | bit;
+ bits++;
+ if (bits == 8)
+ {
+ *ptr = byte;
+ ptr++;
+ bits = 0;
+ byte = 0;
+ }
+ }
+ if (bits)
+ *ptr = byte;
+
+ return (0);
+
+}
+
+
+
--- /dev/null
+
+int fact (int n) {
+ int i, res = 1;
+
+ for (i = 1 ; i <= n ; i++) res *= i;
+
+ return res;
+}
+
+int main () {
+ return (fact(10));
+}
--- /dev/null
+
+int is_sorted (int *tab, int size) {
+ int i, res = 1;
+
+ for (i = 0 ; i < size-1 ; i++) if (tab[i] > tab[i+1]) res = 0;
+
+ return res;
+}
--- /dev/null
+/*\r
+ $Id: random.c,v $\r
+\r
+ This program is public domain and was written by William S. England\r
+ (Oct 1988). It is based on an article by:\r
+\r
+ Stephen K. Park and Keith W. Miller. RANDOM NUMBER GENERATORS:\r
+ GOOD ONES ARE HARD TO FIND. Communications of the ACM,\r
+ New York, NY.,October 1988 p.1192\r
+\r
+ Modifications;\r
+\r
+ $Log: random.c,v $\r
+\r
+######\r
+\r
+ The following is a portable c program for generating random numbers.\r
+ The modulus and multiplier have been extensively tested and should\r
+ not be changed except by someone who is a professional Lehmer generator\r
+ writer. THIS GENERATOR REPRESENTS THE MINIMUM STANDARD AGAINST WHICH\r
+ OTHER GENERATORS SHOULD BE JUDGED. ("Quote from the referenced article's\r
+ authors. WSE" )\r
+*/\r
+\r
+/*\r
+** These are pre-calculated below to compensate for c \r
+** compilers that may overflow when building the code.\r
+**\r
+** q = (m / a)\r
+** r = (m % a)\r
+*/\r
+\r
+/*\r
+** To build the generator with the original ACM\r
+** article's numbers use -DORIGINAL_NUMBERS when compiling.\r
+**\r
+** Original_numbers are the original published m and q in the\r
+** ACM article above. John Burton has furnished numbers for\r
+** a reportedly better generator. The new numbers are now\r
+** used in this program by default.\r
+*/\r
+\r
+#ifndef ORIGINAL_NUMBERS\r
+#define m (unsigned long)2147483647\r
+#define q (unsigned long)44488\r
+\r
+#define a (unsigned int)48271\r
+#define r (unsigned int)3399\r
+\r
+#define successfulltest 399268537\r
+#endif\r
+\r
+#ifdef ORIGINAL_NUMBERS\r
+#define m (unsigned long)2147483647\r
+#define q (unsigned long)127773\r
+\r
+#define a (unsigned int)16807\r
+#define r (unsigned int)2836\r
+\r
+#define successfulltest 1043618065\r
+#endif\r
+\r
+/*\r
+** F(z) = (az)%m\r
+** = az-m(az/m)\r
+**\r
+** F(z) = G(z)+mT(z)\r
+** G(z) = a(z%q)- r(z/q)\r
+** T(z) = (z/q) - (az/m)\r
+**\r
+** F(z) = a(z%q)- rz/q+ m((z/q) - a(z/m))\r
+** = a(z%q)- rz/q+ m(z/q) - az\r
+*/\r
+\r
+unsigned long seed;\r
+\r
+void srand( /* unsigned long*/ initial_seed)\r
+unsigned long initial_seed;\r
+{\r
+ seed = initial_seed;\r
+ return;\r
+}\r
+/*\r
+**\r
+*/\r
+unsigned long rand(/*void*/){\r
+\r
+register\r
+int lo, hi, test;\r
+\r
+ hi = seed/q;\r
+ lo = seed%q;\r
+\r
+ test = a*lo - r*hi;\r
+\r
+ if (test > 0)\r
+ seed = test;\r
+ else\r
+ seed = test+ m;\r
+\r
+ return seed;\r
+}\r
+\r
+#ifdef TESTRAND\r
+#include <stdio.h> \r
+/* \r
+** The result of running this program should be\r
+** "successfulltest". If this program does not yield this\r
+** value then your compiler has not implemented this\r
+** program correctly.\r
+** \r
+** To compile with test option under unix use; 'cc -DTESTRAND random.c'\r
+**\r
+** Be sure to compile without test option for use in applications.\r
+** ( Now why did I have to say that ??? )\r
+*/\r
+\r
+main(/*void*/)\r
+{\r
+unsigned \r
+long n_rand;\r
+\r
+register int i;\r
+int success = 0;\r
+\r
+ srand(1);\r
+\r
+ for( i = 1; i <= 10001; i++){\r
+ n_rand = rand();\r
+\r
+ if( i> 9998) \r
+ printf("Sequence %5i, Seed= %10i\n", i, seed ); \r
+\r
+ if( i == 10000) \r
+ if( seed == successfulltest ) \r
+ success = 1;\r
+ }\r
+\r
+ if (success){\r
+ printf("The random number generator works correctly.\n\n");\r
+ exit(0);\r
+ }else{\r
+ printf("The random number generator DOES NOT WORK!\n\n");\r
+ exit(1);\r
+ }\r
+}\r
+#endif\r
--- /dev/null
+
+#define SIZE 5
+
+int sum (int tab[], int size) {
+ int i, res = 0;
+
+ for (i = 0 ; i < size ; i++) res += tab[i];
+
+ return res;
+}
+
+int main () {
+ int tab[5] = { 3, 18, -9, 23, 17 };
+ return (sum(tab, SIZE));
+}
--- /dev/null
+RES = frama-c_lustre
+
+all:
+ ocamlbuild main.native
+ cp main.native $(RES)
+
+install:
+ mkdir -p @prefix@/bin
+ cp $(RES) @prefix@/bin
+
+clean:
+ rm -rf _build *~ main.native
+
+distclean: clean
+ rm -rf $(RES)
+
+.PHONY = install clean distclean
--- /dev/null
+Presentation
+--------------
+
+This is a wrapper of the Frama-C plug-in Cost for Lustre that makes the
+synthesis of the results of the CerCo compiler on Lustre files.
+
+ Requirements
+--------------
+
+ - Frama-C Nitrogen
+ - Ocaml >= 3.12
+ - Cost plug-in
+ - CerCo
+ - Lustre compiler
+ - Jessie plug-in and simplify (for verification only)
+
+ Compilation
+-------------
+
+ You can compile the wrapper using the following command:
+
+ % make
+
+ (assuming that you are located at the root of the source tree)
+
+ Installation
+--------------
+
+ You can install the wrapper using the following command:
+
+ % make install
+
+ You may need administrative rights.
+
+ Usage
+-------
+
+ You can run the wrapper for Lustre on a node "node" of a Lustre file
+ "file.lus" using the following command:
+
+ % frama-c_lustre file.lus node
+
+ The result will be in file "file-annotated.c" in the same directory if the
+ name is fresh. Otherwise an integer suffix will be added to the base name of
+ the output file.
+
+ For a complete description of the options, use the command:
+
+ % frama-c_lustre -help
--- /dev/null
+<*>: use_str
--- /dev/null
+let exit_flag = ref true
+
+let exit_if_error () = exit_flag := true
+
+let resume_if_error () = exit_flag := false
+
+exception Error of Position.t list * string
+
+let print_error positions msg =
+ Printf.sprintf "%s%s"
+ (String.concat "\n"
+ (List.map (fun p -> Position.string_of_pos p ^": ") positions))
+ msg
+
+let error_alert positions msg =
+ if !exit_flag then (
+ output_string stderr (print_error positions msg);
+ exit 1
+ )
+ else raise (Error (positions, msg))
+
+let global_error kind msg =
+ error_alert [] (Printf.sprintf "Global Error (%s):\n %s\n" kind msg)
+
+let error kind pos msg =
+ error_alert [pos] (Printf.sprintf "Error (%s):\n %s\n" kind msg)
+
+let error2 kind pos1 pos2 msg =
+ error_alert [pos1; pos2] (Printf.sprintf "Error (%s):\n %s\n" kind msg)
+
+let warning kind msg =
+ let mem_flag = !exit_flag in
+ exit_flag := false;
+ (try
+ error_alert [] (Printf.sprintf "Warning (%s):\n %s\n" kind msg)
+ with Error (positions, msg) ->
+ output_string stderr (print_error positions msg));
+ exit_flag := mem_flag
--- /dev/null
+(** This module provides a uniform way of reporting (located) error message. *)
+
+(** [exit_if_error ()] forces the program to stop if an error is encountered.
+ (This is the default behavior.) *)
+val exit_if_error: unit -> unit
+
+(** [resume_if_error ()] makes the program throw the exception {!Error}
+ if an error is encountered. *)
+val resume_if_error: unit -> unit
+
+exception Error of Position.t list * string
+
+(** [print_error positions msg] formats an error message. *)
+val print_error : Position.t list -> string -> string
+
+(** [error k p msg] prints [msg] with [k] as a message prefix and stops
+ the program. *)
+val error : string -> Position.t -> string -> 'a
+
+(** [error2 k p1 p2 msg] prints two positions instead of one. *)
+val error2 : string -> Position.t -> Position.t -> string -> 'a
+
+(** [global_error k msg] prints [msg] with [k] as a message prefix and stops
+ the program. *)
+val global_error : string -> string -> 'a
+
+(** [warning k msg] prints [msg] with [k] as a message prefix, but do
+ not stop the program. *)
+val warning : string -> string -> unit
--- /dev/null
+
+
+let error_prefix = "Main"
+let error = Error.global_error error_prefix
+
+
+let log_file = Filename.temp_file "log" ""
+
+
+let print_verbose i s =
+ if Options.get_verbose_level () >= i then Printf.printf "%s%!" s
+let print_verbose1 = print_verbose 1
+let print_verbose2 = print_verbose 2
+
+
+let exec cmd error_callback error_msg success_callback success_msg =
+ print_verbose2 (" -> executing command \"" ^ cmd ^ "\"...\n") ;
+ let res = Sys.command cmd in
+ if res <> 0 then (error_callback () ; error error_msg)
+ else
+ (print_verbose1 (success_msg ^ "\n") ;
+ success_callback ())
+
+
+let has_extension filename =
+ try ignore (Filename.chop_extension filename) ; true
+ with Invalid_argument ("Filename.chop_extension") -> false
+
+let lustre_compilation filename node =
+ print_verbose1
+ ("Compiling node " ^ node ^ " of Lustre file " ^ filename ^ "...\n") ;
+ let filename_quote = Filename.quote filename in
+ let base =
+ if has_extension filename then Filename.chop_extension filename
+ else filename in
+ let base =
+ Misc.fresh_base base
+ [".c" ; "-annotated.c" ; ".s" ; ".hex" ; ".cerco" ; ".cost_results" ;
+ ".jessie_results" ; "-annotated_test.c" ; "-annotated_test.s" ;
+ "-annotated_test.hex" ; "-annotated_test.results"] in
+ let res_file = base ^ ".c" in
+ let res_file_quote = Filename.quote res_file in
+ let cmd =
+ "lus2c " ^ filename_quote ^ " " ^ node ^ " -o " ^ res_file_quote ^ " >> " ^
+ log_file in
+ let error_callback () = () in
+ let error_msg =
+ "Failed to compile node " ^ node ^ " of Lustre file " ^ filename ^ "." in
+ let success_callback () = res_file in
+ let success_msg = "Done. Result is in file " ^ res_file ^ "." in
+ exec cmd error_callback error_msg success_callback success_msg
+
+
+let extract_inputs_booleans filename =
+ print_verbose1
+ ("Extracting boolean inputs from file " ^ filename ^ "...\n") ;
+ try
+ let ic = open_in filename in
+ let rec inputs_booleans b =
+ try
+ let str_inputs = Str.regexp " *//INPUTS *" in
+ (* let str_registers = Str.regexp " *//REGISTERS *" in *)
+ let is_input_start s =
+ Str.string_match str_inputs s 0
+ (* || Str.string_match str_registers s 0 *) in
+ let str_outputs = Str.regexp " *//OUTPUTS *" in
+ let str_acc = Str.regexp ".*}.*" in
+ let is_input_end s =
+ Str.string_match str_outputs s 0 ||
+ Str.string_match str_acc s 0 in
+ let str_boolean = Str.regexp " _boolean .*;" in
+ let str_input = Str.regexp " [^ ]* .*;" in
+ let extract_input s =
+ let i = String.index_from s 3 ' ' in
+ String.sub s (i+1) (String.length s - (i+2)) in
+ let s = input_line ic in
+ let (added_input, added_boolean) =
+ let extract cond = if b && cond then [extract_input s] else [] in
+ (extract (Str.string_match str_input s 0),
+ extract (Str.string_match str_boolean s 0)) in
+ let next_b = (b || (is_input_start s)) && (not (is_input_end s)) in
+ let (inputs, booleans) = inputs_booleans next_b in
+ (added_input @ inputs, added_boolean @ booleans)
+ with End_of_file -> close_in ic ; ([], []) in
+ let res = inputs_booleans false in
+ print_verbose1 "Done.\n" ;
+ res
+ with Sys_error _ ->
+ error ("Could not extract boolean inputs from file " ^ filename ^ ".")
+
+
+let framac_option () =
+ "-cost-lustre " ^
+ (if Options.test_requested () then "-cost-lustre-test " else "") ^
+ (if Options.verify_requested () then "-cost-lustre-verify " else "")
+
+let cost_plugin filename =
+ print_verbose1 ("Running Cost plug-in on file " ^ filename ^ "...\n") ;
+ let filename_quote = Filename.quote filename in
+ let base =
+ if has_extension filename then Filename.chop_extension filename
+ else filename in
+ let annotated_file = base ^ "-annotated.c" in
+ let results_file = base ^ ".cost_results" in
+ let hex_file = base ^ ".hex" in
+ let cerco_file = base ^ ".cerco" in
+ let option = framac_option () in
+ let cmd = "frama-c -cost " ^ option ^ filename_quote ^ " >> " ^
+ log_file in
+ let error_callback () = () in
+ let error_msg = "Failed to run Cost plug-in on file " ^ filename ^ "." in
+ let success_callback () = (annotated_file, results_file, cerco_file) in
+ let success_msg =
+ "Done. Annotations are in file " ^ annotated_file ^
+ ", object code is in file " ^ hex_file ^
+ ", cost results are in file " ^ results_file ^
+ (if Options.test_requested () then
+ ", CerCo information is in file " ^ cerco_file
+ else "") ^
+ "." in
+ exec cmd error_callback error_msg success_callback success_msg
+
+
+let print_step_result filename =
+ print_verbose1 ("Reading the cost results in file " ^ filename ^ "...\n") ;
+ let ic = open_in filename in
+ let rec aux () =
+ try
+ let s = input_line ic in
+ if String.contains s ' ' then
+ let i = String.index s ' ' in
+ let fun_name = String.sub s 0 i in
+ let cost = String.sub s (i+1) ((String.length s) - (i+1)) in
+ let suffix = "_step" in
+ let l = String.length fun_name in
+ let l' = String.length suffix in
+ if l > l' && String.sub s (l - l') l' = suffix then
+ (print_verbose1 "Done.\n" ;
+ Printf.printf
+ "WCET of %s: %s (not verified).\n%!"
+ fun_name cost ;
+ (fun_name, cost))
+ else aux ()
+ else error ("Bad format of result file " ^ filename ^ ".")
+ with End_of_file ->
+ error "No step function found or its cost could not be computed." in
+ aux ()
+
+
+let prover () =
+ if Options.gui_requested () then ""
+ else "-jessie-atp " ^ (Options.get_prover ()) ^ " "
+
+let jessie filename =
+ print_verbose1 ("Running Frama-C/Jessie on file " ^ filename ^ "...\n") ;
+ let filename_quote = Filename.quote filename in
+ let base =
+ if has_extension filename then Filename.chop_extension filename
+ else filename in
+ let res_file = base ^ ".jessie_results" in
+ let timeout = string_of_int (Options.get_timeout ()) in
+ let cmd =
+ "TIMEOUT=" ^ timeout ^ " frama-c -jessie -jessie-behavior default " ^
+ "-jessie-why-opt=\"-fast-wp\" " ^ (prover ()) ^
+ filename_quote ^ " >> " ^ res_file in
+ let error_callback () = () in
+ let error_msg = "Failed to run Frama-C/Jessie on file " ^ filename ^ "." in
+ let success_callback () = res_file in
+ let success_msg = "Done. Results are in file " ^ res_file ^ "." in
+ exec cmd error_callback error_msg success_callback success_msg
+
+let string_starts_with prefix s =
+ let l = String.length prefix in
+ (l <= String.length s) && (String.sub s 0 l = prefix)
+
+let read_jessie_results filename =
+ if not (Options.gui_requested ()) then
+ begin
+ print_verbose1
+ ("Reading Frama-C/Jessie results in file " ^ filename ^ "...\n" ) ;
+ let print_failed () = Printf.printf "Failed to prove the result.\n%!" in
+ try
+ let ic = open_in filename in
+ let rec aux () =
+ let s = input_line ic in
+ if string_starts_with "valid" s then
+ let regexp = Str.regexp (".*100%.*") in
+ if Str.string_match regexp s 0 then
+ (print_verbose1 "Done.\n" ;
+ Printf.printf "WCET is proven correct.\n%!")
+ else print_failed ()
+ else aux () in
+ aux ()
+ with Sys_error _ | End_of_file -> print_failed ()
+ end
+
+let verification filename =
+ Printf.printf "Verifying the result (this may take some time)...\n%!" ;
+ let res_file = jessie filename in
+ read_jessie_results res_file
+
+
+let cerco_test_info (inputs, booleans) step_fun step_cost cerco_file =
+ print_verbose1
+ ("Adding step function information to CerCo file " ^ cerco_file ^ "...\n") ;
+ try
+ let ic = open_in cerco_file in
+ let rec contents () =
+ try let s = input_line ic in s ^ "\n" ^ (contents ())
+ with End_of_file -> close_in ic ; "" in
+ let contents = step_fun ^ "\n" ^ step_cost ^ "\n" ^ contents () ^ "\n" in
+ let f contents s = contents ^ s ^ "\n" in
+ let contents = (List.fold_left f contents inputs) ^ "\n" in
+ let contents = List.fold_left f contents booleans in
+ let oc = open_out cerco_file in
+ output_string oc contents ;
+ close_out oc ;
+ print_verbose1 "Done.\n" ;
+ cerco_file
+ with Sys_error _ ->
+ error ("Could not add step function information to CerCo file " ^
+ cerco_file ^ ".")
+
+let cerco_test_file filename cerco_test_info =
+ print_verbose1 ("Adding a main to file " ^ filename ^ "...\n") ;
+ let filename_quote = Filename.quote filename in
+ let base =
+ if has_extension filename then Filename.chop_extension filename
+ else filename in
+ let res_base = base ^ "_test" in
+ let res_c = res_base ^ ".c" in
+ let cmd =
+ "acc -o " ^ res_base ^ " -lustre-test " ^ cerco_test_info ^
+ " -lustre-test-cases " ^ (string_of_int (Options.get_test_cases ())) ^
+ " -lustre-test-cycles " ^ (string_of_int (Options.get_test_cycles ())) ^
+ " -lustre-test-min-int " ^ (string_of_int (Options.get_test_min_int ())) ^
+ " -lustre-test-max-int " ^ (string_of_int (Options.get_test_max_int ())) ^
+ " " ^ filename_quote ^ " >> " ^ log_file in
+ let error_callback () = () in
+ let error_msg = "Failed to add a main to file " ^ filename ^ "." in
+ let success_callback () = res_c in
+ let success_msg = "Done. Result is in files " ^ res_c ^ "." in
+ exec cmd error_callback error_msg success_callback success_msg
+
+let test_exec filename =
+ print_verbose1 ("Simulating the generated code in file " ^ filename ^
+ "...\n") ;
+ let filename_quote = Filename.quote filename in
+ let base =
+ if has_extension filename then Filename.chop_extension filename
+ else filename in
+ let res_file = base ^ ".results" in
+ let cmd = "acc -l Clight -i " ^ filename_quote ^ " > " ^ res_file in
+ let error_callback () = () in
+ let error_msg = "Failed to run acc on file " ^ filename ^ "." in
+ let success_callback () = res_file in
+ let success_msg = "Done. Results are in file " ^ res_file ^ "." in
+ exec cmd error_callback error_msg success_callback success_msg
+
+let read_test_results filename =
+ print_verbose1
+ ("Reading simulation results in file " ^ filename ^ "...\n" ) ;
+ try
+ let ic = open_in filename in
+ Misc.repeat 2 (fun () -> ignore (input_line ic)) () ;
+ let wcet = int_of_string (input_line ic) in
+ let min = int_of_string (input_line ic) in
+ let max = int_of_string (input_line ic) in
+ let average = int_of_string (input_line ic) in
+ let wcet_correct = max <= wcet in
+ print_verbose1 "Done.\n" ;
+ Printf.printf "Estimated WCET: %d\nMinimum: %d\nMaximum: %d\nAverage: %d\nEstimated WCET is %scorrect for these executions.\n%!"
+ wcet min max average (if wcet_correct then "" else "in")
+ with Sys_error _ | End_of_file | Failure "int_of_string" ->
+ error "Failed to test the result."
+
+let test filename inputs_booleans step_fun step_cost cerco_file =
+ Printf.printf "Testing the result (this may take some time)...\n%!" ;
+ let cerco_test_info =
+ cerco_test_info inputs_booleans step_fun step_cost cerco_file in
+ let cerco_test_file = cerco_test_file filename cerco_test_info in
+ let test_results = test_exec cerco_test_file in
+ read_test_results test_results
+
+
+let _ =
+ let args = OptionsParsing.results () in
+ if List.length args < 2 then error OptionsParsing.usage_msg
+ else
+ begin
+ let lustre_file = List.nth args 0 in
+ let node = List.nth args 1 in
+ print_verbose1
+ ("*** Processing node " ^ node ^ " of Lustre file " ^ lustre_file ^
+ ". ***\n") ;
+ let c_file = lustre_compilation lustre_file node in
+ let inputs_booleans = extract_inputs_booleans c_file in
+ let (c_annotated_file, cost_results_file, cerco_file) =
+ cost_plugin c_file in
+ let (step_fun, step_cost) = print_step_result cost_results_file in
+ if Options.verify_requested () then verification c_annotated_file ;
+ if Options.test_requested () then
+ test c_annotated_file inputs_booleans step_fun step_cost cerco_file ;
+ end
--- /dev/null
+module LexingExt = struct
+
+ open Lexing
+
+ let new_line lexbuf =
+ lexbuf.lex_curr_p <- {
+ lexbuf.lex_curr_p with
+ pos_bol = 0;
+ pos_lnum = lexbuf.lex_curr_p.pos_lnum + 1
+ }
+
+end
+
+module ListExt = struct
+
+ let inv_assoc l = List.map (fun (x, y) -> (y, x)) l
+
+ exception EmptyList
+
+ let last l = try List.hd (List.rev l) with _ -> raise EmptyList
+
+ let cut_last l =
+ let rec aux l = function
+ | [] -> raise EmptyList
+ | [ x ] -> (x, List.rev l)
+ | x :: xs -> aux (x :: l) xs
+ in
+ aux [] l
+
+ let multi_set_of_list l =
+ let h = Hashtbl.create 13 in
+ let incr_occ x =
+ let o = try Hashtbl.find h x with Not_found -> 0 in
+ Hashtbl.replace h x (o + 1)
+ in
+ List.iter incr_occ l;
+ Hashtbl.fold (fun k v accu -> (k, v) :: accu) h []
+
+ let hashtbl_of_assoc l =
+ let h = Hashtbl.create 13 in
+ List.iter (fun (k, v) -> Hashtbl.add h k v) l;
+ h
+
+ exception Conflict
+ let assoc_union l1 l2 =
+ let h1 = hashtbl_of_assoc l1 in
+ l1
+ @ List.filter
+ (fun (k, v1) ->
+ try
+ let v2 = Hashtbl.find h1 k in
+ if v1 <> v2 then raise Conflict;
+ false
+ with _ -> true) l2
+
+ let assoc_diff l1 l2 =
+ let h1 = hashtbl_of_assoc l1 in
+ let h2 = hashtbl_of_assoc l2 in
+ let diff h1 h2 f =
+ Hashtbl.fold
+ (fun k v1 accu ->
+ let v2 =
+ try Some (Hashtbl.find h2 k)
+ with Not_found -> None
+ in
+ if Some v1 <> v2 then
+ if f then
+ (k, (Some v1, v2)) :: accu
+ else
+ (k, (v2, Some v1)) :: accu
+ else
+ accu)
+ h1 []
+ in
+ let d1 = diff h1 h2 true in
+ let d2 = diff h2 h1 false in
+ try assoc_union d1 d2
+ with Conflict -> assert false
+
+ let transitive_forall2 p l =
+ let rec aux = function
+ | [] -> None
+ | [x] -> None
+ | x1 :: ((x2 :: _) as xs) ->
+ if not (p x1 x2) then Some (x1, x2) else aux xs
+ in
+ aux l
+
+end
+
+module ArgExt = struct
+
+ let extra_doc s = "", Arg.Unit ignore, s
+
+end
+
+module SysExt = struct
+
+ let safe_remove name =
+ try Sys.remove name with Sys_error _ -> ()
+
+ let rec alternative name =
+ if not (Sys.file_exists name) then
+ name
+ else
+ let dirname = Filename.dirname name in
+ let filename = Filename.basename name in
+ let r = Str.regexp "\\([0-9]+\\)-\\(.*\\)" in
+ let filename =
+ if Str.string_match r filename 0 then
+ let i = int_of_string (Str.matched_group 1 filename) in
+ Printf.sprintf "%02d-%s" (i + 1) (Str.matched_group 2 filename)
+ else
+ "01-" ^ filename
+ in
+ alternative (Filename.concat dirname filename)
+
+end
+
+
+let fresh_file prefix suffix =
+ let string_of_complement = function
+ | None -> ""
+ | Some i -> string_of_int i in
+ let next_complement = function
+ | None -> Some 0
+ | Some i -> Some (i+1) in
+ let rec aux complement =
+ let filename = prefix ^ (string_of_complement complement) ^ suffix in
+ if not (Sys.file_exists filename) then filename
+ else aux (next_complement complement) in
+ aux None
+
+let exists_exts base exts =
+ let f res ext = res || (Sys.file_exists (base ^ ext)) in
+ List.fold_left f false exts
+
+let fresh_base base exts =
+ let string_of_complement = function
+ | None -> ""
+ | Some i -> string_of_int i in
+ let next_complement = function
+ | None -> Some 0
+ | Some i -> Some (i+1) in
+ let rec aux complement =
+ let new_base = base ^ (string_of_complement complement) in
+ if not (exists_exts new_base exts) then new_base
+ else aux (next_complement complement) in
+ aux None
+
+let rec repeat n f a =
+ if n = 0 then a
+ else repeat (n-1) f (f a)
--- /dev/null
+(** This module extends the standard library of Objective Caml. *)
+
+module LexingExt : sig
+
+ (** [new_line lexbuf] update lexbuf to increment its line
+ counter. *)
+ val new_line : Lexing.lexbuf -> unit
+
+end
+
+module ListExt : sig
+
+ (** [inv_assoc l] inverses a bijective associative list [l]. *)
+ val inv_assoc : ('a * 'b) list -> ('b * 'a) list
+
+ exception EmptyList
+
+ (** [last l] returns the last element of a list.
+ Raise [EmptyList] if there is no such thing in [l]. *)
+ val last : 'a list -> 'a
+
+ (** [cut_last l] returns the last element of a list [l] and the
+ elements that come before it in [l].
+ Raise [EmptyList] if there is no such thing in [l]. *)
+ val cut_last : 'a list -> 'a * 'a list
+
+ (** [multi_set_of_list l] returns an associative list that
+ relates every element of [l] to its frequency in [l]. *)
+ val multi_set_of_list : 'a list -> ('a * int) list
+
+ (** [hashtbl_of_assoc l] converts an associative list into
+ an hash table. *)
+ val hashtbl_of_assoc : ('a * 'b) list -> ('a, 'b) Hashtbl.t
+
+ (** [assoc_diff l1 l2] returns the difference between two
+ associative lists. *)
+ val assoc_diff : ('a * 'b) list -> ('a * 'b) list
+ -> ('a * ('b option * 'b option)) list
+
+ (** [transitive_forall2 p l] checks that the binary predicate [p] is
+ true between each successive elements of [l]. If this is false,
+ the function returns the first pair of elements that falsify [p]. *)
+ val transitive_forall2 : ('a -> 'a -> bool) -> 'a list -> ('a * 'a) option
+
+end
+
+module ArgExt : sig
+
+ (** [extra_doc s] adds an extra line of documentation for an
+ Arg.spec row. *)
+ val extra_doc : string -> (Arg.key * Arg.spec * Arg.doc)
+
+end
+
+module SysExt : sig
+
+ (** [safe_remove filename] deletes a file named [filename],
+ but do not crash if a system error happens. (For instance,
+ if the file does not exist.) *)
+ val safe_remove : string -> unit
+
+ (** [alternative filename] finds an alternative name different
+ from [filename] that is not already used. *)
+ val alternative : string -> string
+
+end
+
+
+val fresh_file : string -> string -> string
+
+val fresh_base : string -> string list -> string
+
+val repeat : int -> ('a -> 'a) -> 'a -> 'a
--- /dev/null
+open Misc.ArgExt
+
+let timeout = ref 0
+let set_timeout i = timeout := i
+let get_timeout () = !timeout
+
+let prover = ref "simplify"
+let set_prover s = prover := s
+let get_prover () = !prover
+
+let gui_flag = ref false
+let request_gui = (:=) gui_flag
+let gui_requested () = !gui_flag
+
+let verbose_level = ref 0
+let set_verbose_level i = verbose_level := i
+let get_verbose_level () = !verbose_level
+
+let verify_flag = ref false
+let request_verify = (:=) verify_flag
+let verify_requested () = !verify_flag
+
+let test_flag = ref false
+let request_test = (:=) test_flag
+let test_requested () = !test_flag
+
+let test_cases = ref 10
+let set_test_cases i = test_cases := i
+let get_test_cases () = !test_cases
+
+let test_cycles = ref 10
+let set_test_cycles i = test_cycles := i
+let get_test_cycles () = !test_cycles
+
+let test_min_int = ref (-1000)
+let set_test_min_int i = test_min_int := i
+let get_test_min_int () = !test_min_int
+
+let test_max_int = ref 1000
+let set_test_max_int i = test_max_int := i
+let get_test_max_int () = !test_max_int
+
+let options = OptionsParsing.register [
+
+ "-v", Arg.Int set_verbose_level,
+ " Verbosity, from 0 (lowest) to 2 (highest).";
+ extra_doc " [default is 0]";
+
+ "-verify", Arg.Set verify_flag,
+ " Verify the results with Frama-C/Jessie.";
+
+ "-timeout", Arg.Int set_timeout,
+ " Timeout in seconds for verification. 0 means no timeout.";
+ extra_doc " [default is 0]";
+
+ "-prover", Arg.String set_prover,
+ " Select a prover for verification through why.";
+ extra_doc " Needs the -verify option.";
+ extra_doc " [default is simplify]";
+
+ "-gui", Arg.Set gui_flag,
+ " Do not select a prover: run a graphical user interface instead.";
+ extra_doc " Needs the -verify option.";
+
+ "-test", Arg.Set test_flag,
+ " Test the results.";
+
+ "-test-cases", Arg.Int set_test_cases,
+ " Number of test cases.";
+ extra_doc " Needs the -test option.";
+ extra_doc " [default is 10]";
+
+ "-test-cycles", Arg.Int set_test_cycles,
+ " Number of cycles for each test case.";
+ extra_doc " Needs the -test option.";
+ extra_doc " [default is 10]";
+
+ "-test-min-int", Arg.Int set_test_min_int,
+ " Random int minimum value.";
+ extra_doc " Needs the -test option.";
+ extra_doc " [default is -1000]";
+
+ "-test-max-int", Arg.Int set_test_max_int,
+ " Random int maximum value.";
+ extra_doc " Needs the -test option.";
+ extra_doc " [default is 1000]";
+]
--- /dev/null
+(** This module defines the wrapper general options. *)
+
+(** {2 Timeout} *)
+val set_timeout : int -> unit
+val get_timeout : unit -> int
+
+(** {2 Timeout} *)
+val set_prover : string -> unit
+val get_prover : unit -> string
+
+(** {2 Timeout} *)
+val request_gui : bool -> unit
+val gui_requested : unit -> bool
+
+(** {2 Verbosity} *)
+val set_verbose_level : int -> unit
+val get_verbose_level : unit -> int
+
+(** {2 Verification request} *)
+val request_verify : bool -> unit
+val verify_requested : unit -> bool
+
+(** {2 Test request} *)
+val request_test : bool -> unit
+val test_requested : unit -> bool
+
+(** {2 Test cases number} *)
+val set_test_cases : int -> unit
+val get_test_cases : unit -> int
+
+(** {2 Test cycles number} *)
+val set_test_cycles : int -> unit
+val get_test_cycles : unit -> int
+
+(** {2 Random int minimum value} *)
+val set_test_min_int : int -> unit
+val get_test_min_int : unit -> int
+
+(** {2 Random int maximum value} *)
+val set_test_max_int : int -> unit
+val get_test_max_int : unit -> int
--- /dev/null
+let options = ref []
+
+let register o =
+ options := o @ !options
+
+let usage_msg =
+ "Usage: "
+ ^ (Filename.basename Sys.executable_name)
+ ^ " [options] file.lus node"
+
+let results () =
+ let extra_arguments = ref [] in
+ Arg.parse (Arg.align !options)
+ (fun s -> extra_arguments := s :: !extra_arguments)
+ usage_msg;
+ List.rev !extra_arguments
--- /dev/null
+open Lexing
+
+type t =
+ {
+ start_p : Lexing.position;
+ end_p : Lexing.position
+ }
+
+type position = t
+
+type 'a located =
+ {
+ value : 'a;
+ position : t;
+ }
+
+let value { value = v } =
+ v
+
+let position { position = p } =
+ p
+
+let destruct p =
+ (p.value, p.position)
+
+let with_pos p v =
+ {
+ value = v;
+ position = p;
+ }
+
+let with_poss p1 p2 v =
+ with_pos { start_p = p1; end_p = p2 } v
+
+let map f v =
+ {
+ value = f v.value;
+ position = v.position;
+ }
+
+let iter f { value = v } =
+ f v
+
+let mapd f v =
+ let w1, w2 = f v.value in
+ let pos = v.position in
+ ({ value = w1; position = pos }, { value = w2; position = pos })
+
+let dummy =
+ {
+ start_p = Lexing.dummy_pos;
+ end_p = Lexing.dummy_pos
+ }
+
+let unknown_pos v =
+ {
+ value = v;
+ position = dummy
+ }
+
+let start_of_position p = p.start_p
+
+let end_of_position p = p.end_p
+
+let filename_of_position p =
+ p.start_p.Lexing.pos_fname
+
+let line p =
+ p.pos_lnum
+
+let column p =
+ p.pos_cnum - p.pos_bol
+
+let characters p1 p2 =
+ (column p1, p2.pos_cnum - p1.pos_bol) (* intentionally [p1.pos_bol] *)
+
+let join x1 x2 =
+ {
+ start_p = if x1 = dummy then x2.start_p else x1.start_p;
+ end_p = if x2 = dummy then x1.end_p else x2.end_p
+ }
+
+let lex_join x1 x2 =
+ {
+ start_p = x1;
+ end_p = x2
+ }
+
+let join_located l1 l2 f =
+ {
+ value = f l1.value l2.value;
+ position = join l1.position l2.position;
+ }
+
+let string_of_lex_pos p =
+ let c = p.pos_cnum - p.pos_bol in
+ (string_of_int p.pos_lnum)^":"^(string_of_int c)
+
+let string_of_pos p =
+ let filename = filename_of_position p in
+ let l = line p.start_p in
+ let c1, c2 = characters p.start_p p.end_p in
+ if filename = "" then
+ Printf.sprintf "Line %d, characters %d-%d" l c1 c2
+ else
+ Printf.sprintf "File \"%s\", line %d, characters %d-%d" filename l c1 c2
+
+let pos_or_undef = function
+ | None -> dummy
+ | Some x -> x
+
+let cpos lexbuf =
+ {
+ start_p = Lexing.lexeme_start_p lexbuf;
+ end_p = Lexing.lexeme_end_p lexbuf;
+ }
+
+let with_cpos lexbuf v =
+ with_pos (cpos lexbuf) v
+
+let string_of_cpos lexbuf =
+ string_of_pos (cpos lexbuf)
+
+let joinf f t1 t2 =
+ join (f t1) (f t2)
+
+let ljoinf f =
+ List.fold_left (fun p t -> join p (f t)) dummy
+
+let join_located_list ls f =
+ {
+ value = f (List.map (fun l -> l.value) ls);
+ position = ljoinf (fun x -> x.position) ls
+ }
--- /dev/null
+(** Extension of standard library's positions. *)
+
+(** {2 Extended lexing positions} *)
+
+(** Abstract type for pairs of positions in the lexing stream. *)
+type t
+type position = t
+
+(** Decoration of a value with a position. *)
+type 'a located =
+ {
+ value : 'a;
+ position : t;
+ }
+
+(** [value dv] returns the raw value that underlies the
+ decorated value [dv]. *)
+val value: 'a located -> 'a
+
+(** [position dv] returns the position that decorates the
+ decorated value [dv]. *)
+val position: 'a located -> t
+
+(** [destruct dv] returns the couple of position and value
+ of a decorated value [dv]. *)
+val destruct: 'a located -> 'a * t
+
+(** [with_pos p v] decorates [v] with a position [p]. *)
+val with_pos : t -> 'a -> 'a located
+
+(** [with_cpos p v] decorates [v] with a lexical position [p]. *)
+val with_cpos: Lexing.lexbuf -> 'a -> 'a located
+
+(** [with_poss start stop v] decorates [v] with a position [(start, stop)]. *)
+val with_poss : Lexing.position -> Lexing.position -> 'a -> 'a located
+
+(** [unknown_pos x] decorates [v] with an unknown position. *)
+val unknown_pos : 'a -> 'a located
+
+(** This value is used when an object does not come from a particular
+ input location. *)
+val dummy: t
+
+(** [map f v] extends the decoration from [v] to [f v]. *)
+val map: ('a -> 'b) -> 'a located -> 'b located
+
+(** [iter f dv] applies [f] to the value inside [dv]. *)
+val iter: ('a -> unit) -> 'a located -> unit
+
+(** [mapd f v] extends the decoration from [v] to both members of the pair
+ [f v]. *)
+val mapd: ('a -> 'b1 * 'b2) -> 'a located -> 'b1 located * 'b2 located
+
+(** {2 Accessors} *)
+
+(** [column p] returns the number of characters from the
+ beginning of the line of the Lexing.position [p]. *)
+val column : Lexing.position -> int
+
+(** [column p] returns the line number of to the Lexing.position [p]. *)
+val line : Lexing.position -> int
+
+(** [characters p1 p2] returns the character interval
+ between [p1] and [p2] assuming they are located in the same
+ line. *)
+val characters : Lexing.position -> Lexing.position -> int * int
+
+(** [start_of_position p] returns the beginning of a position [p]. *)
+val start_of_position: t -> Lexing.position
+
+(** [end_of_position p] returns the end of a position [p]. *)
+val end_of_position: t -> Lexing.position
+
+(** [filename_of_position p] returns the filename of a position [p]. *)
+val filename_of_position: t -> string
+
+(** {2 Position handling} *)
+
+(** [join p1 p2] returns a position that starts where [p1]
+ starts and stops where [p2] stops. *)
+val join : t -> t -> t
+
+(** [lex_join l1 l2] returns a position that starts at [l1] and stops
+ at [l2]. *)
+val lex_join : Lexing.position -> Lexing.position -> t
+
+(** [string_of_lex_pos p] returns a string representation for
+ the lexing position [p]. *)
+val string_of_lex_pos : Lexing.position -> string
+
+(** [string_of_pos p] returns the standard (Emacs-like) representation
+ of the position [p]. *)
+val string_of_pos : t -> string
+
+(** [pos_or_undef po] is the identity function except if po = None,
+ in that case, it returns [undefined_position]. *)
+val pos_or_undef : t option -> t
+
+(** {2 Interaction with the lexer runtime} *)
+
+(** [cpos lexbuf] returns the current position of the lexer. *)
+val cpos : Lexing.lexbuf -> t
+
+(** [string_of_cpos p] returns a string representation of
+ the lexer's current position. *)
+val string_of_cpos : Lexing.lexbuf -> string
--- /dev/null
+
+gen :
+ @lustre parity.lus verif_parity -v
+ @ocmin verif_parity.oc -v
+ @poc verif_parity_min.oc
+
+genmin :
+ @lustre parity.lus verif_parity -v -demand
+ @poc verif_parity.oc
+
+verif :
+ @lesar parity.lus verif_parity -v
+
+clean :
+ /bin/rm -f *.ec *.oc *.c *.h *.bak
--- /dev/null
+Modified : Jan 9 1995
+Modified : Jul 1 1997
+
+
+A verification program illustrating the use of arrays and recursive nodes.
+The goal is to compare a combinatorial operator "P", computing the parity bit
+of a bit-string, to a sequential version "parity".
+
+The size of the bit-string is a constant of the program, here 8.
+
+The node XOR implements exclusive "or"
+
+The combinatorial parity-bit operator is recursive
+- applied to a bit-string of size 1, it returns the value of its unique bit.
+- applied to a bit-string of longer size n, it returns the exclusive "or" of
+ the last bit of the string and the result of P applied to the n-1 first bits.
+
+The sequential parity-bit operator proceeds by shifting its parameter b. At
+any cycle
+ - the parity-bit is the exclusive "or" of its preceding value and the
+ leftmost bit of b.
+ - the array b is shifted to the left (and completed by "false" on the right)
+
+In order to know when the whole array has been processed, an auxiliary array
+"todo" is used. All its elements but the rightmost are initialized to false.
+It is shifted to the left at any cycle, until its only "true" element becomes
+the leftmost. Then the variable "done" becomes true, and the parity-bit has
+been computed.
+
+The verification program compares the result of the combinatorial operator
+with the one of the sequential operator, when the computation of the last
+one is terminated.
+
+The Makefile gives 3 ways for verification :
+ GenThenMin => generate full automaton then minimize
+ GenMin => generate minimal automaton
+ Verif => use the verification tool
--- /dev/null
+const size=8;
+
+node XOR(a,b:bool) returns (Xor:bool);
+let
+ Xor = if a then not b else b;
+tel
+
+node P(const n: int; B: bool^n) returns (p:bool);
+let
+ p = with n=1 then B[0]
+ else XOR(B[n-1] , P(n-1,B[0..n-2]));
+tel
+
+node parity (input: bool^size)
+returns (parity,done: bool);
+var b, todo: bool^size;
+let
+ b[0..(size-2)] = input[0..(size-2)] ->
+ pre(b[1..(size-1)]);
+ b[size-1] = input[size-1] -> false;
+ todo[0..(size-2)] = false^(size-1) ->
+ pre(todo[1..(size-1)]);
+ todo[size-1] = true -> false;
+ done = todo[0];
+ parity = b[0] -> XOR(pre(parity) , b[0]);
+tel
+
+node verif_parity (input: bool^size)
+returns(ok: bool);
+var comb, seq, done: bool;
+let
+ ok = not done or (comb = seq);
+ comb = P(size,input) -> pre(comb);
+ (seq,done) = parity(input);
+tel