xdelta3-3.0.7/0002755000176500017650000000000012155072575012360 5ustar debdevdebdevxdelta3-3.0.7/aclocal.m40000644000176500017650000010527212144343061014212 0ustar debdevdebdev# generated automatically by aclocal 1.12.6 -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.12' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.12.6], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.12.6])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated. For more info, see: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl dnl Support for Objective C++ was only introduced in Autoconf 2.65, dnl but we still cater to Autoconf 2.62. m4_ifdef([AC_PROG_OBJCXX], [AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/ax_check_aligned_access_required.m4]) xdelta3-3.0.7/xdelta3.h0000644000176500017650000013371412144342741014075 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010, 2011, 2012, 2013. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* To know more about Xdelta, start by reading xdelta3.c. If you are * ready to use the API, continue reading here. There are two * interfaces -- xd3_encode_input and xd3_decode_input -- plus a dozen * or so related calls. This interface is styled after Zlib. */ #ifndef _XDELTA3_H_ #define _XDELTA3_H_ #define _POSIX_SOURCE #define _ISOC99_SOURCE #define _C99_SOURCE #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /****************************************************************/ /* Default configured value of stream->winsize. If the program * supplies xd3_encode_input() with data smaller than winsize the * stream will automatically buffer the input, otherwise the input * buffer is used directly. */ #ifndef XD3_DEFAULT_WINSIZE #define XD3_DEFAULT_WINSIZE (1U << 23) #endif /* Default total size of the source window used in xdelta3-main.h */ #ifndef XD3_DEFAULT_SRCWINSZ #define XD3_DEFAULT_SRCWINSZ (1U << 26) #endif /* When Xdelta requests a memory allocation for certain buffers, it * rounds up to units of at least this size. The code assumes (and * asserts) that this is a power-of-two. */ #ifndef XD3_ALLOCSIZE #define XD3_ALLOCSIZE (1U<<14) #endif /* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect * decoders against malicious files. The decoder will never decode a * window larger than this. If the file specifies VCD_TARGET the * decoder may require two buffers of this size. * * 8-16MB is reasonable, probably don't need to go larger. */ #ifndef XD3_HARDMAXWINSIZE #define XD3_HARDMAXWINSIZE (1U<<24) #endif /* The IOPT_SIZE value sets the size of a buffer used to batch * overlapping copy instructions before they are optimized by picking * the best non-overlapping ranges. The larger this buffer, the * longer a forced xd3_srcwin_setup() decision is held off. Setting * this value to 0 causes an unlimited buffer to be used. */ #ifndef XD3_DEFAULT_IOPT_SIZE #define XD3_DEFAULT_IOPT_SIZE (1U<<15) #endif /* The maximum distance backward to search for small matches */ #ifndef XD3_DEFAULT_SPREVSZ #define XD3_DEFAULT_SPREVSZ (1U<<18) #endif /* The default compression level */ #ifndef XD3_DEFAULT_LEVEL #define XD3_DEFAULT_LEVEL 3 #endif #ifndef XD3_DEFAULT_SECONDARY_LEVEL #define XD3_DEFAULT_SECONDARY_LEVEL 6 #endif #ifndef XD3_USE_LARGEFILE64 #define XD3_USE_LARGEFILE64 1 #endif /* Sizes and addresses within VCDIFF windows are represented as usize_t * * For source-file offsets and total file sizes, total input and * output counts, the xoff_t type is used. The decoder and encoder * generally check for overflow of the xoff_t size (this is tested at * the 32bit boundary [xdelta3-test.h]). */ #ifndef _WIN32 #include #else #define WIN32_LEAN_AND_MEAN #if XD3_USE_LARGEFILE64 /* 64 bit file offsets: uses GetFileSizeEx and SetFilePointerEx. * requires Win2000 or newer version of WinNT */ #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #else /* 32 bit (DWORD) file offsets: uses GetFileSize and * SetFilePointer. compatible with win9x-me and WinNT4 */ #define WINVER 0x0400 #define _WIN32_WINNT 0x0400 #endif #include #ifdef _MSC_VER #define inline typedef signed int ssize_t; #if _MSC_VER < 1600 typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; typedef ULONGLONG uint64_t; #else /* For MSVC10 and above */ #include #endif #else /* mingw32, lcc and watcom provide a proper header */ #include #endif #endif typedef uint32_t usize_t; #if XD3_USE_LARGEFILE64 #define __USE_FILE_OFFSET64 1 /* GLIBC: for 64bit fileops, ... ? */ #ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif typedef uint64_t xoff_t; #define SIZEOF_XOFF_T 8 #define SIZEOF_USIZE_T 4 #ifndef WIN32 #if SIZEOF_SIZE_T == 8 #define Q "z" #else #define Q "ll" #endif #else #define Q "I64" #endif #else typedef uint32_t xoff_t; #define SIZEOF_XOFF_T 4 #define SIZEOF_USIZE_T 4 #define Q #endif #define USE_UINT32 (SIZEOF_USIZE_T == 4 || \ SIZEOF_XOFF_T == 4 || REGRESSION_TEST) #define USE_UINT64 (SIZEOF_USIZE_T == 8 || \ SIZEOF_XOFF_T == 8 || REGRESSION_TEST) #ifndef UNALIGNED_OK #ifdef HAVE_ALIGNED_ACCESS_REQUIRED #define UNALIGNED_OK 0 #else /* This generally includes all Windows builds. */ #define UNALIGNED_OK 1 #endif #endif /**********************************************************************/ /* Whether to build the encoder, otherwise only build the decoder. */ #ifndef XD3_ENCODER #define XD3_ENCODER 1 #endif /* The code returned when main() fails, also defined in system includes. */ #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif /* REGRESSION TEST enables the "xdelta3 test" command, which runs a series of self-tests. */ #ifndef REGRESSION_TEST #define REGRESSION_TEST 0 #endif /* XD3_DEBUG=1 enables assertions and various statistics. Levels > 1 * enable some additional output only useful during development and * debugging. */ #ifndef XD3_DEBUG #define XD3_DEBUG 0 #endif #ifndef PYTHON_MODULE #define PYTHON_MODULE 0 #endif #ifndef SWIG_MODULE #define SWIG_MODULE 0 #endif /* There are three string matching functions supplied: one fast, one * slow (default), and one soft-configurable. To disable any of * these, use the following definitions. */ #ifndef XD3_BUILD_SLOW #define XD3_BUILD_SLOW 1 #endif #ifndef XD3_BUILD_FAST #define XD3_BUILD_FAST 1 #endif #ifndef XD3_BUILD_FASTER #define XD3_BUILD_FASTER 1 #endif #ifndef XD3_BUILD_FASTEST #define XD3_BUILD_FASTEST 1 #endif #ifndef XD3_BUILD_SOFT #define XD3_BUILD_SOFT 1 #endif #ifndef XD3_BUILD_DEFAULT #define XD3_BUILD_DEFAULT 1 #endif #if XD3_DEBUG #include #endif /* XPRINT. Debug output and VCDIFF_TOOLS functions report to stderr. * I have used an irregular style to abbreviate [fprintf(stderr, "] as * [DP(RINT "]. */ #define DP fprintf #define RINT stderr, typedef struct _xd3_stream xd3_stream; typedef struct _xd3_source xd3_source; typedef struct _xd3_hash_cfg xd3_hash_cfg; typedef struct _xd3_smatcher xd3_smatcher; typedef struct _xd3_rinst xd3_rinst; typedef struct _xd3_dinst xd3_dinst; typedef struct _xd3_hinst xd3_hinst; typedef struct _xd3_winst xd3_winst; typedef struct _xd3_rpage xd3_rpage; typedef struct _xd3_addr_cache xd3_addr_cache; typedef struct _xd3_output xd3_output; typedef struct _xd3_desect xd3_desect; typedef struct _xd3_iopt_buflist xd3_iopt_buflist; typedef struct _xd3_rlist xd3_rlist; typedef struct _xd3_sec_type xd3_sec_type; typedef struct _xd3_sec_cfg xd3_sec_cfg; typedef struct _xd3_sec_stream xd3_sec_stream; typedef struct _xd3_config xd3_config; typedef struct _xd3_code_table_desc xd3_code_table_desc; typedef struct _xd3_code_table_sizes xd3_code_table_sizes; typedef struct _xd3_slist xd3_slist; typedef struct _xd3_whole_state xd3_whole_state; typedef struct _xd3_wininfo xd3_wininfo; /* The stream configuration has three callbacks functions, all of * which may be supplied with NULL values. If config->getblk is * provided as NULL, the stream returns XD3_GETSRCBLK. */ typedef void* (xd3_alloc_func) (void *opaque, size_t items, usize_t size); typedef void (xd3_free_func) (void *opaque, void *address); typedef int (xd3_getblk_func) (xd3_stream *stream, xd3_source *source, xoff_t blkno); /* These are internal functions to delay construction of encoding * tables and support alternate code tables. See the comments & code * enabled by GENERIC_ENCODE_TABLES. */ typedef const xd3_dinst* (xd3_code_table_func) (void); typedef int (xd3_comp_table_func) (xd3_stream *stream, const uint8_t **data, usize_t *size); #if XD3_DEBUG #define XD3_ASSERT(x) \ do { if (! (x)) { DP(RINT "%s:%d: XD3 assertion failed: %s\n", __FILE__, __LINE__, #x); \ abort (); } } while (0) #else #define XD3_ASSERT(x) (void)0 #endif /* XD3_DEBUG */ #ifndef max #define max(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef min #define min(x,y) ((x) < (y) ? (x) : (y)) #endif /**************************************************************** PUBLIC ENUMS ******************************************************************/ /* These are the five ordinary status codes returned by the * xd3_encode_input() and xd3_decode_input() state machines. */ typedef enum { /* An application must be prepared to handle these five return * values from either xd3_encode_input or xd3_decode_input, except * in the case of no-source compression, in which case XD3_GETSRCBLK * is never returned. More detailed comments for these are given in * xd3_encode_input and xd3_decode_input comments, below. */ XD3_INPUT = -17703, /* need input */ XD3_OUTPUT = -17704, /* have output */ XD3_GETSRCBLK = -17705, /* need a block of source input (with no * xd3_getblk function), a chance to do * non-blocking read. */ XD3_GOTHEADER = -17706, /* (decode-only) after the initial VCDIFF & first window header */ XD3_WINSTART = -17707, /* notification: returned before a window is * processed, giving a chance to * XD3_SKIP_WINDOW or not XD3_SKIP_EMIT that * window. */ XD3_WINFINISH = -17708, /* notification: returned after encode/decode & output for a window */ XD3_TOOFARBACK = -17709, /* (encoder only) may be returned by getblk() if the block is too old */ XD3_INTERNAL = -17710, /* internal error */ XD3_INVALID = -17711, /* invalid config */ XD3_INVALID_INPUT = -17712, /* invalid input/decoder error */ XD3_NOSECOND = -17713, /* when secondary compression finds no improvement. */ XD3_UNIMPLEMENTED = -17714 /* currently VCD_TARGET */ } xd3_rvalues; /* special values in config->flags */ typedef enum { XD3_JUST_HDR = (1 << 1), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_SKIP_WINDOW = (1 << 2), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_SKIP_EMIT = (1 << 3), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_FLUSH = (1 << 4), /* flush the stream buffer to prepare for xd3_stream_close(). */ XD3_SEC_DJW = (1 << 5), /* use DJW static huffman */ XD3_SEC_FGK = (1 << 6), /* use FGK adaptive huffman */ XD3_SEC_LZMA = (1 << 24), /* use LZMA secondary */ XD3_SEC_TYPE = (XD3_SEC_DJW | XD3_SEC_FGK | XD3_SEC_LZMA), XD3_SEC_NODATA = (1 << 7), /* disable secondary compression of the data section. */ XD3_SEC_NOINST = (1 << 8), /* disable secondary compression of the inst section. */ XD3_SEC_NOADDR = (1 << 9), /* disable secondary compression of the addr section. */ XD3_SEC_NOALL = (XD3_SEC_NODATA | XD3_SEC_NOINST | XD3_SEC_NOADDR), XD3_ADLER32 = (1 << 10), /* enable checksum computation in the encoder. */ XD3_ADLER32_NOVER = (1 << 11), /* disable checksum verification in the decoder. */ XD3_ALT_CODE_TABLE = (1 << 12), /* for testing th e alternate code table encoding. */ XD3_NOCOMPRESS = (1 << 13), /* disable ordinary data * compression feature, only search * the source, not the target. */ XD3_BEGREEDY = (1 << 14), /* disable the "1.5-pass * algorithm", instead use greedy * matching. Greedy is off by * default. */ XD3_ADLER32_RECODE = (1 << 15), /* used by "recode". */ /* 4 bits to set the compression level the same as the command-line * setting -1 through -9 (-0 corresponds to the XD3_NOCOMPRESS flag, * and is independent of compression level). This is for * convenience, especially with xd3_encode_memory(). */ XD3_COMPLEVEL_SHIFT = 20, /* 20 - 23 */ XD3_COMPLEVEL_MASK = (0xF << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_1 = (1 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_2 = (2 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_3 = (3 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_6 = (6 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_9 = (9 << XD3_COMPLEVEL_SHIFT) } xd3_flags; /* The values of this enumeration are set in xd3_config using the * smatch_cfg variable. It can be set to default, slow, fast, etc., * and soft. */ typedef enum { XD3_SMATCH_DEFAULT = 0, /* Flags may contain XD3_COMPLEVEL bits, else default. */ XD3_SMATCH_SLOW = 1, XD3_SMATCH_FAST = 2, XD3_SMATCH_FASTER = 3, XD3_SMATCH_FASTEST = 4, XD3_SMATCH_SOFT = 5 } xd3_smatch_cfg; /********************************************************************* PRIVATE ENUMS **********************************************************************/ /* stream->match_state is part of the xd3_encode_input state machine * for source matching: * * 1. the XD3_GETSRCBLK block-read mechanism means reentrant matching * 2. this state spans encoder windows: a match and end-of-window * will continue in the next 3. the initial target byte and source * byte are a presumed match, to avoid some computation in case the * inputs are identical. */ typedef enum { MATCH_TARGET = 0, /* in this state, attempt to match the start of * the target with the previously set source * address (initially 0). */ MATCH_BACKWARD = 1, /* currently expanding a match backward in the source/target. */ MATCH_FORWARD = 2, /* currently expanding a match forward in the source/target. */ MATCH_SEARCHING = 3 /* currently searching for a match. */ } xd3_match_state; /* The xd3_encode_input state machine steps through these states in * the following order. The matcher is reentrant and returns * XD3_INPUT whenever it requires more data. After receiving * XD3_INPUT, if the application reads EOF it should call * xd3_stream_close(). */ typedef enum { ENC_INIT = 0, /* xd3_encode_input has never been called. */ ENC_INPUT = 1, /* waiting for xd3_avail_input () to be called. */ ENC_SEARCH = 2, /* currently searching for matches. */ ENC_INSTR = 3, /* currently formatting output. */ ENC_FLUSH = 4, /* currently emitting output. */ ENC_POSTOUT = 5, /* after an output section. */ ENC_POSTWIN = 6, /* after all output sections. */ ENC_ABORTED = 7 /* abort. */ } xd3_encode_state; /* The xd3_decode_input state machine steps through these states in * the following order. The matcher is reentrant and returns * XD3_INPUT whenever it requires more data. After receiving * XD3_INPUT, if the application reads EOF it should call * xd3_stream_close(). * * 0-8: the VCDIFF header * 9-18: the VCDIFF window header * 19-21: the three primary sections: data, inst, addr * 22: producing output: returns XD3_OUTPUT, possibly XD3_GETSRCBLK, * 23: return XD3_WINFINISH, set state=9 to decode more input */ typedef enum { DEC_VCHEAD = 0, /* VCDIFF header */ DEC_HDRIND = 1, /* header indicator */ DEC_SECONDID = 2, /* secondary compressor ID */ DEC_TABLEN = 3, /* code table length */ DEC_NEAR = 4, /* code table near */ DEC_SAME = 5, /* code table same */ DEC_TABDAT = 6, /* code table data */ DEC_APPLEN = 7, /* application data length */ DEC_APPDAT = 8, /* application data */ DEC_WININD = 9, /* window indicator */ DEC_CPYLEN = 10, /* copy window length */ DEC_CPYOFF = 11, /* copy window offset */ DEC_ENCLEN = 12, /* length of delta encoding */ DEC_TGTLEN = 13, /* length of target window */ DEC_DELIND = 14, /* delta indicator */ DEC_DATALEN = 15, /* length of ADD+RUN data */ DEC_INSTLEN = 16, /* length of instruction data */ DEC_ADDRLEN = 17, /* length of address data */ DEC_CKSUM = 18, /* window checksum */ DEC_DATA = 19, /* data section */ DEC_INST = 20, /* instruction section */ DEC_ADDR = 21, /* address section */ DEC_EMIT = 22, /* producing data */ DEC_FINISH = 23, /* window finished */ DEC_ABORTED = 24 /* xd3_abort_stream */ } xd3_decode_state; /************************************************************ internal types ************************************************************/ /* instruction lists used in the IOPT buffer */ struct _xd3_rlist { xd3_rlist *next; xd3_rlist *prev; }; /* the raw encoding of an instruction used in the IOPT buffer */ struct _xd3_rinst { uint8_t type; uint8_t xtra; uint8_t code1; uint8_t code2; usize_t pos; usize_t size; xoff_t addr; xd3_rlist link; }; /* the code-table form of an single- or double-instruction */ struct _xd3_dinst { uint8_t type1; uint8_t size1; uint8_t type2; uint8_t size2; }; /* the decoded form of a single (half) instruction. */ struct _xd3_hinst { uint8_t type; uint32_t size; /* TODO: why decode breaks if this is usize_t? */ uint32_t addr; /* TODO: why decode breaks if this is usize_t? */ }; /* the form of a whole-file instruction */ struct _xd3_winst { uint8_t type; /* RUN, ADD, COPY */ uint8_t mode; /* 0, VCD_SOURCE, VCD_TARGET */ usize_t size; xoff_t addr; xoff_t position; /* absolute position of this inst */ }; /* used by the encoder to buffer output in sections. list of blocks. */ struct _xd3_output { uint8_t *base; usize_t next; usize_t avail; xd3_output *next_page; }; /* used by the decoder to buffer input in sections. */ struct _xd3_desect { const uint8_t *buf; const uint8_t *buf_max; uint32_t size; /* TODO: why decode breaks if this is usize_t? */ usize_t pos; /* used in xdelta3-decode.h */ uint8_t *copied1; usize_t alloc1; /* used in xdelta3-second.h */ uint8_t *copied2; usize_t alloc2; }; /* the VCDIFF address cache, see the RFC */ struct _xd3_addr_cache { usize_t s_near; usize_t s_same; usize_t next_slot; /* the circular index for near */ usize_t *near_array; /* array of size s_near */ usize_t *same_array; /* array of size s_same*256 */ }; /* the IOPT buffer list is just a list of buffers, which may be allocated * during encode when using an unlimited buffer. */ struct _xd3_iopt_buflist { xd3_rinst *buffer; xd3_iopt_buflist *next; }; /* This is the record of a pre-compiled configuration, a subset of xd3_config. */ struct _xd3_smatcher { const char *name; int (*string_match) (xd3_stream *stream); usize_t large_look; usize_t large_step; usize_t small_look; usize_t small_chain; usize_t small_lchain; usize_t max_lazy; usize_t long_enough; }; /* hash table size & power-of-two hash function. */ struct _xd3_hash_cfg { usize_t size; usize_t shift; usize_t mask; }; /* the sprev list */ struct _xd3_slist { usize_t last_pos; }; /* window info (for whole state) */ struct _xd3_wininfo { xoff_t offset; usize_t length; uint32_t adler32; }; /* whole state for, e.g., merge */ struct _xd3_whole_state { usize_t addslen; uint8_t *adds; usize_t adds_alloc; usize_t instlen; xd3_winst *inst; usize_t inst_alloc; usize_t wininfolen; xd3_wininfo *wininfo; usize_t wininfo_alloc; xoff_t length; }; /******************************************************************** public types *******************************************************************/ /* Settings for the secondary compressor. */ struct _xd3_sec_cfg { int data_type; /* Which section. (set automatically) */ usize_t ngroups; /* Number of DJW Huffman groups. */ usize_t sector_size; /* Sector size. */ int inefficient; /* If true, ignore efficiency check [avoid XD3_NOSECOND]. */ }; /* This is the user-visible stream configuration. */ struct _xd3_config { usize_t winsize; /* The encoder window size. */ usize_t sprevsz; /* How far back small string matching goes */ usize_t iopt_size; /* entries in the instruction-optimizing buffer */ xd3_getblk_func *getblk; /* The three callbacks. */ xd3_alloc_func *alloc; xd3_free_func *freef; void *opaque; /* Not used. */ int flags; /* stream->flags are initialized * from xd3_config & never * modified by the library. Use * xd3_set_flags to modify flags * settings mid-stream. */ xd3_sec_cfg sec_data; /* Secondary compressor config: data */ xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for soft config */ xd3_smatcher smatcher_soft; }; /* The primary source file object. You create one of these objects and * initialize the first four fields. This library maintains the next * 5 fields. The configured getblk implementation is responsible for * setting the final 3 fields when called (and/or when XD3_GETSRCBLK * is returned). */ struct _xd3_source { /* you set */ usize_t blksize; /* block size */ const char *name; /* its name, for debug/print purposes */ void *ioh; /* opaque handle */ xoff_t max_winsize; /* maximum visible buffer */ /* getblk sets */ xoff_t curblkno; /* current block number: client sets after getblk request */ usize_t onblk; /* number of bytes on current block: client sets, must be >= 0 and <= blksize */ const uint8_t *curblk; /* current block array: client sets after getblk request */ /* xd3 sets */ usize_t srclen; /* length of this source window */ xoff_t srcbase; /* offset of this source window in the source itself */ int shiftby; /* for power-of-two blocksizes */ int maskby; /* for power-of-two blocksizes */ xoff_t cpyoff_blocks; /* offset of dec_cpyoff in blocks */ usize_t cpyoff_blkoff; /* offset of copy window in blocks, remainder */ xoff_t getblkno; /* request block number: xd3 sets current getblk request */ /* See xd3_getblk() */ xoff_t max_blkno; /* Maximum block, if eof is known, * otherwise, equals frontier_blkno * (initially 0). */ xoff_t frontier_blkno; /* If eof is unknown, the next * source position to be read. * Otherwise, equal to * max_blkno. */ usize_t onlastblk; /* Number of bytes on max_blkno */ int eof_known; /* Set to true when the first * partial block is read. */ }; /* The primary xd3_stream object, used for encoding and decoding. You * may access only two fields: avail_out, next_out. Use the methods * above to operate on xd3_stream. */ struct _xd3_stream { /* input state */ const uint8_t *next_in; /* next input byte */ usize_t avail_in; /* number of bytes available at next_in */ xoff_t total_in; /* how many bytes in */ /* output state */ uint8_t *next_out; /* next output byte */ usize_t avail_out; /* number of bytes available at next_out */ usize_t space_out; /* total out space */ xoff_t current_window; /* number of windows encoded/decoded */ xoff_t total_out; /* how many bytes out */ /* to indicate an error, xd3 sets */ const char *msg; /* last error message, NULL if no error */ /* source configuration */ xd3_source *src; /* source array */ /* encoder memory configuration */ usize_t winsize; /* suggested window size */ usize_t sprevsz; /* small string, previous window size (power of 2) */ usize_t sprevmask; /* small string, previous window size mask */ usize_t iopt_size; usize_t iopt_unlimited; /* general configuration */ xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */ xd3_alloc_func *alloc; /* malloc function */ xd3_free_func *free; /* free function */ void* opaque; /* private data object passed to alloc, free, and getblk */ int flags; /* various options */ /* secondary compressor configuration */ xd3_sec_cfg sec_data; /* Secondary compressor config: data */ xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ xd3_smatcher smatcher; usize_t *large_table; /* table of large checksums */ xd3_hash_cfg large_hash; /* large hash config */ usize_t *small_table; /* table of small checksums */ xd3_slist *small_prev; /* table of previous offsets, circular linked list */ int small_reset; /* true if small table should be reset */ xd3_hash_cfg small_hash; /* small hash config */ xd3_addr_cache acache; /* the vcdiff address cache */ xd3_encode_state enc_state; /* state of the encoder */ usize_t taroff; /* base offset of the target input */ usize_t input_position; /* current input position */ usize_t min_match; /* current minimum match length, avoids redundent matches */ usize_t unencoded_offset; /* current input, first * unencoded offset. this value * is <= the first instruction's * position in the iopt buffer, * if there is at least one * match in the buffer. */ /* SRCWIN */ int srcwin_decided; /* boolean: true if srclen and srcbase have been decided. */ int srcwin_decided_early; /* boolean: true if srclen and srcbase were decided early. */ xoff_t srcwin_cksum_pos; /* Source checksum position */ /* MATCH */ xd3_match_state match_state; /* encoder match state */ xoff_t match_srcpos; /* current match source position relative to srcbase */ xoff_t match_last_srcpos; /* previously attempted * srcpos, to avoid loops. */ xoff_t match_minaddr; /* smallest matching address to * set window params (reset each * window xd3_encode_reset) */ xoff_t match_maxaddr; /* largest matching address to * set window params (reset each * window xd3_encode_reset) */ usize_t match_back; /* match extends back so far */ usize_t match_maxback; /* match extends back maximum */ usize_t match_fwd; /* match extends forward so far */ usize_t match_maxfwd; /* match extends forward maximum */ xoff_t maxsrcaddr; /* address of the last source match (across windows) */ uint8_t *buf_in; /* for saving buffered input */ usize_t buf_avail; /* amount of saved input */ const uint8_t *buf_leftover; /* leftover content of next_in (i.e., user's buffer) */ usize_t buf_leftavail; /* amount of leftover content */ xd3_output *enc_current; /* current output buffer */ xd3_output *enc_free; /* free output buffers */ xd3_output *enc_heads[4]; /* array of encoded outputs: head of chain */ xd3_output *enc_tails[4]; /* array of encoded outputs: tail of chain */ uint32_t recode_adler32; /* set the adler32 checksum * during "recode". */ xd3_rlist iopt_used; /* instruction optimizing buffer */ xd3_rlist iopt_free; xd3_rinst *iout; /* next single instruction */ xd3_iopt_buflist *iopt_alloc; const uint8_t *enc_appheader; /* application header to encode */ usize_t enc_appheadsz; /* application header size */ /* decoder stuff */ xd3_decode_state dec_state; /* current DEC_XXX value */ usize_t dec_hdr_ind; /* VCDIFF header indicator */ usize_t dec_win_ind; /* VCDIFF window indicator */ usize_t dec_del_ind; /* VCDIFF delta indicator */ uint8_t dec_magic[4]; /* First four bytes */ usize_t dec_magicbytes; /* Magic position. */ usize_t dec_secondid; /* Optional secondary compressor ID. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_codetblsz; /* Optional code table: length. */ uint8_t *dec_codetbl; /* Optional code table: storage. */ usize_t dec_codetblbytes; /* Optional code table: position. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_appheadsz; /* Optional application header: size. */ uint8_t *dec_appheader; /* Optional application header: storage */ usize_t dec_appheadbytes; /* Optional application header: position. */ usize_t dec_cksumbytes; /* Optional checksum: position. */ uint8_t dec_cksum[4]; /* Optional checksum: storage. */ uint32_t dec_adler32; /* Optional checksum: value. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_cpylen; /* length of copy window (VCD_SOURCE or VCD_TARGET) */ xoff_t dec_cpyoff; /* offset of copy window (VCD_SOURCE or VCD_TARGET) */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_enclen; /* length of delta encoding */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_tgtlen; /* length of target window */ #if USE_UINT64 uint64_t dec_64part; /* part of a decoded uint64_t */ #endif #if USE_UINT32 uint32_t dec_32part; /* part of a decoded uint32_t */ #endif xoff_t dec_winstart; /* offset of the start of current target window */ xoff_t dec_window_count; /* == current_window + 1 in DEC_FINISH */ usize_t dec_winbytes; /* bytes of the three sections so far consumed */ usize_t dec_hdrsize; /* VCDIFF + app header size */ const uint8_t *dec_tgtaddrbase; /* Base of decoded target addresses (addr >= dec_cpylen). */ const uint8_t *dec_cpyaddrbase; /* Base of decoded copy addresses (addr < dec_cpylen). */ usize_t dec_position; /* current decoder position counting the cpylen offset */ usize_t dec_maxpos; /* maximum decoder position counting the cpylen offset */ xd3_hinst dec_current1; /* current instruction */ xd3_hinst dec_current2; /* current instruction */ uint8_t *dec_buffer; /* Decode buffer */ uint8_t *dec_lastwin; /* In case of VCD_TARGET, the last target window. */ usize_t dec_lastlen; /* length of the last target window */ xoff_t dec_laststart; /* offset of the start of last target window */ usize_t dec_lastspace; /* allocated space of last target window, for reuse */ xd3_desect inst_sect; /* staging area for decoding window sections */ xd3_desect addr_sect; xd3_desect data_sect; xd3_code_table_func *code_table_func; xd3_comp_table_func *comp_table_func; const xd3_dinst *code_table; const xd3_code_table_desc *code_table_desc; xd3_dinst *code_table_alloc; /* secondary compression */ const xd3_sec_type *sec_type; xd3_sec_stream *sec_stream_d; xd3_sec_stream *sec_stream_i; xd3_sec_stream *sec_stream_a; /* state for reconstructing whole files (e.g., for merge), this only * supports loading USIZE_T_MAX instructions, adds, etc. */ xd3_whole_state whole_target; /* statistics */ xoff_t n_scpy; xoff_t n_tcpy; xoff_t n_add; xoff_t n_run; xoff_t l_scpy; xoff_t l_tcpy; xoff_t l_add; xoff_t l_run; usize_t i_slots_used; #if XD3_DEBUG usize_t large_ckcnt; /* memory usage */ usize_t alloc_cnt; usize_t free_cnt; #endif }; /************************************************************************** PUBLIC FUNCTIONS **************************************************************************/ /* This function configures an xd3_stream using the provided in-memory * input buffer, source buffer, output buffer, and flags. The output * array must be large enough or else ENOSPC will be returned. This * is the simplest in-memory encoding interface. */ int xd3_encode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buffer, usize_t *output_size, usize_t avail_output, int flags); /* The reverse of xd3_encode_memory. */ int xd3_decode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buf, usize_t *output_size, usize_t avail_output, int flags); /* This function encodes an in-memory input using a pre-configured * xd3_stream. This allows the caller to set a variety of options * which are not available in the xd3_encode/decode_memory() * functions. * * The output array must be large enough to hold the output or else * ENOSPC is returned. The source (if any) should be set using * xd3_set_source_and_size() with a single-block xd3_source. This * calls the underlying non-blocking interfaces, * xd3_encode/decode_input(), handling the necessary input/output * states. This method may be considered a reference for any * application using xd3_encode_input() directly. * * xd3_stream stream; * xd3_config config; * xd3_source src; * * memset (& src, 0, sizeof (src)); * memset (& stream, 0, sizeof (stream)); * memset (& config, 0, sizeof (config)); * * if (source != NULL) * { * src.size = source_size; * src.blksize = source_size; * src.curblkno = 0; * src.onblk = source_size; * src.curblk = source; * src.max_winsize = source_size; * xd3_set_source(&stream, &src); * } * * config.flags = flags; * config.winsize = input_size; * * ... set smatcher, appheader, encoding-table, compression-level, etc. * * xd3_config_stream(&stream, &config); * xd3_encode_stream(&stream, ...); * xd3_free_stream(&stream); */ int xd3_encode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t avail_output); /* The reverse of xd3_encode_stream. */ int xd3_decode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t avail_size); /* This is the non-blocking interface. * * Handling input and output states is the same for encoding or * decoding using the xd3_avail_input() and xd3_consume_output() * routines, inlined below. * * Return values: * * XD3_INPUT: the process requires more input: call * xd3_avail_input() then repeat * * XD3_OUTPUT: the process has more output: read stream->next_out, * stream->avail_out, then call xd3_consume_output(), * then repeat * * XD3_GOTHEADER: (decoder-only) notification returned following the * VCDIFF header and first window header. the decoder * may use the header to configure itself. * * XD3_WINSTART: a general notification returned once for each * window except the 0-th window, which is implied by * XD3_GOTHEADER. It is recommended to use a * switch-stmt such as: * * ... * again: * switch ((ret = xd3_decode_input (stream))) { * case XD3_GOTHEADER: { * assert(stream->current_window == 0); * stuff; * } * // fallthrough * case XD3_WINSTART: { * something(stream->current_window); * goto again; * } * ... * * XD3_WINFINISH: a general notification, following the complete * input & output of a window. at this point, * stream->total_in and stream->total_out are consistent * for either encoding or decoding. * * XD3_GETSRCBLK: If the xd3_getblk() callback is NULL, this value * is returned to initiate a non-blocking source read. */ int xd3_decode_input (xd3_stream *stream); int xd3_encode_input (xd3_stream *stream); /* The xd3_config structure is used to initialize a stream - all data * is copied into stream so config may be a temporary variable. See * the [documentation] or comments on the xd3_config structure. */ int xd3_config_stream (xd3_stream *stream, xd3_config *config); /* Since Xdelta3 doesn't open any files, xd3_close_stream is just an * error check that the stream is in a proper state to be closed: this * means the encoder is flushed and the decoder is at a window * boundary. The application is responsible for freeing any of the * resources it supplied. */ int xd3_close_stream (xd3_stream *stream); /* This arranges for closes the stream to succeed. Does not free the * stream.*/ void xd3_abort_stream (xd3_stream *stream); /* xd3_free_stream frees all memory allocated for the stream. The * application is responsible for freeing any of the resources it * supplied. */ void xd3_free_stream (xd3_stream *stream); /* This function informs the encoder or decoder that source matching * (i.e., delta-compression) is possible. For encoding, this should * be called before the first xd3_encode_input. A NULL source is * ignored. For decoding, this should be called before the first * window is decoded, but the appheader may be read first * (XD3_GOTHEADER). After decoding the header, call xd3_set_source() * if you have a source file. Note: if (stream->dec_win_ind & VCD_SOURCE) * is true, it means the first window expects there to be a source file. */ int xd3_set_source (xd3_stream *stream, xd3_source *source); /* If the source size is known, call this instead of xd3_set_source(). * to avoid having stream->getblk called (and/or to avoid XD3_GETSRCBLK). * * Follow these steps: xd3_source source; memset(&source, 0, sizeof(source)); source.blksize = size; source.onblk = size; source.curblk = buf; source.curblkno = 0; int ret = xd3_set_source_and_size(&stream, &source, size); ... */ int xd3_set_source_and_size (xd3_stream *stream, xd3_source *source, xoff_t source_size); /* This should be called before the first call to xd3_encode_input() * to include application-specific data in the VCDIFF header. */ void xd3_set_appheader (xd3_stream *stream, const uint8_t *data, usize_t size); /* xd3_get_appheader may be called in the decoder after XD3_GOTHEADER. * For convenience, the decoder always adds a single byte padding to * the end of the application header, which is set to zero in case the * application header is a string. */ int xd3_get_appheader (xd3_stream *stream, uint8_t **data, usize_t *size); /* To generate a VCDIFF encoded delta with xd3_encode_init() from * another format, use: * * xd3_encode_init_partial() -- initialze encoder state (w/o hash tables) * xd3_init_cache() -- reset VCDIFF address cache * xd3_found_match() -- to report a copy instruction * * set stream->enc_state to ENC_INSTR and call xd3_encode_input as usual. */ int xd3_encode_init_partial (xd3_stream *stream); void xd3_init_cache (xd3_addr_cache* acache); int xd3_found_match (xd3_stream *stream, usize_t pos, usize_t size, xoff_t addr, int is_source); /* Gives an error string for xdelta3-speficic errors, returns NULL for system errors */ const char* xd3_strerror (int ret); /* For convenience, zero & initialize the xd3_config structure with specified flags. */ static inline void xd3_init_config (xd3_config *config, int flags) { memset (config, 0, sizeof (*config)); config->flags = flags; } /* This supplies some input to the stream. * * For encoding, if the input is larger than the configured window * size (xd3_config.winsize), the entire input will be consumed and * encoded anyway. If you wish to strictly limit the window size, * limit the buffer passed to xd3_avail_input to the window size. * * For encoding, if the input is smaller than the configured window * size (xd3_config.winsize), the library will create a window-sized * buffer and accumulate input until a full-sized window can be * encoded. XD3_INPUT will be returned. The input must remain valid * until the next time xd3_encode_input() returns XD3_INPUT. * * For decoding, the input will be consumed entirely before XD3_INPUT * is returned again. */ static inline void xd3_avail_input (xd3_stream *stream, const uint8_t *idata, usize_t isize) { /* Even if isize is zero, the code expects a non-NULL idata. Why? * It uses this value to determine whether xd3_avail_input has ever * been called. If xd3_encode_input is called before * xd3_avail_input it will return XD3_INPUT right away without * allocating a stream->winsize buffer. This is to avoid an * unwanted allocation. */ XD3_ASSERT (idata != NULL || isize == 0); stream->next_in = idata; stream->avail_in = isize; } /* This acknowledges receipt of output data, must be called after any * XD3_OUTPUT return. */ static inline void xd3_consume_output (xd3_stream *stream) { stream->avail_out = 0; } /* These are set for each XD3_WINFINISH return. */ static inline int xd3_encoder_used_source (xd3_stream *stream) { return stream->src != NULL && stream->src->srclen > 0; } static inline xoff_t xd3_encoder_srcbase (xd3_stream *stream) { return stream->src->srcbase; } static inline usize_t xd3_encoder_srclen (xd3_stream *stream) { return stream->src->srclen; } /* Checks for legal flag changes. */ static inline void xd3_set_flags (xd3_stream *stream, int flags) { /* The bitwise difference should contain only XD3_FLUSH or XD3_SKIP_WINDOW */ XD3_ASSERT(((flags ^ stream->flags) & ~(XD3_FLUSH | XD3_SKIP_WINDOW)) == 0); stream->flags = flags; } /* Gives some extra information about the latest library error, if any * is known. */ static inline const char* xd3_errstring (xd3_stream *stream) { return stream->msg ? stream->msg : ""; } /* 64-bit divisions are expensive, which is why we require a * power-of-two source->blksize. To relax this restriction is * relatively easy, see the history for xd3_blksize_div(). */ static inline void xd3_blksize_div (const xoff_t offset, const xd3_source *source, xoff_t *blkno, usize_t *blkoff) { *blkno = (xoff_t) (offset >> source->shiftby); *blkoff = (usize_t) (offset & source->maskby); XD3_ASSERT (*blkoff < source->blksize); } static inline void xd3_blksize_add (xoff_t *blkno, usize_t *blkoff, const xd3_source *source, const usize_t add) { usize_t blkdiff; /* Does not check for overflow, checked in xdelta3-decode.h. */ *blkoff += add; blkdiff = *blkoff >> source->shiftby; if (blkdiff) { *blkno += blkdiff; *blkoff &= source->maskby; } XD3_ASSERT (*blkoff < source->blksize); } #define XD3_NOOP 0U #define XD3_ADD 1U #define XD3_RUN 2U #define XD3_CPY 3U /* XD3_CPY rtypes are represented as (XD3_CPY + * copy-mode value) */ #if XD3_DEBUG #define IF_DEBUG(x) x #else #define IF_DEBUG(x) #endif #if XD3_DEBUG > 1 #define IF_DEBUG1(x) x #else #define IF_DEBUG1(x) #endif #if XD3_DEBUG > 2 #define IF_DEBUG2(x) x #else #define IF_DEBUG2(x) #endif #define SIZEOF_ARRAY(x) (sizeof(x) / sizeof(x[0])) #endif /* _XDELTA3_H_ */ xdelta3-3.0.7/xdelta3-test.h0000644000176500017650000022732412143366472015061 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library Copyright (C) 2001, * 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012. * Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This is public-domain Mersenne Twister code, * attributed to Michael Brundage. Thanks! * http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation.html */ static const uint32_t TEST_SEED1 = 5489UL; #define MT_LEN 624 #define MT_IA 397 static const uint32_t UPPER_MASK = 0x80000000; static const uint32_t LOWER_MASK = 0x7FFFFFFF; static const uint32_t MATRIX_A = 0x9908B0DF; #ifndef SHELL_TESTS #define SHELL_TESTS 1 #endif typedef struct mtrand mtrand; struct mtrand { int mt_index_; uint32_t mt_buffer_[MT_LEN]; }; int test_compare_files (const char* tgt, const char *rec); void mt_init(mtrand *mt, uint32_t seed); uint32_t mt_random (mtrand *mt); int test_setup (void); void mt_init(mtrand *mt, uint32_t seed) { int i; mt->mt_buffer_[0] = seed; mt->mt_index_ = MT_LEN; for (i = 1; i < MT_LEN; i++) { /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt->mt_buffer_[i] = (1812433253UL * (mt->mt_buffer_[i-1] ^ (mt->mt_buffer_[i-1] >> 30)) + i); } } uint32_t mt_random (mtrand *mt) { uint32_t y; unsigned long mag01[2]; mag01[0] = 0; mag01[1] = MATRIX_A; if (mt->mt_index_ >= MT_LEN) { int kk; for (kk = 0; kk < MT_LEN - MT_IA; kk++) { y = (mt->mt_buffer_[kk] & UPPER_MASK) | (mt->mt_buffer_[kk + 1] & LOWER_MASK); mt->mt_buffer_[kk] = mt->mt_buffer_[kk + MT_IA] ^ (y >> 1) ^ mag01[y & 0x1UL]; } for (;kk < MT_LEN - 1; kk++) { y = (mt->mt_buffer_[kk] & UPPER_MASK) | (mt->mt_buffer_[kk + 1] & LOWER_MASK); mt->mt_buffer_[kk] = mt->mt_buffer_[kk + (MT_IA - MT_LEN)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } y = (mt->mt_buffer_[MT_LEN - 1] & UPPER_MASK) | (mt->mt_buffer_[0] & LOWER_MASK); mt->mt_buffer_[MT_LEN - 1] = mt->mt_buffer_[MT_IA - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mt->mt_index_ = 0; } y = mt->mt_buffer_[mt->mt_index_++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } static mtrand static_mtrand; #include static uint32_t mt_exp_rand (uint32_t mean, uint32_t max_value) { double mean_d = mean; double erand = log (1.0 / (mt_random (&static_mtrand) / (double)UINT32_MAX)); uint32_t x = (uint32_t) (mean_d * erand + 0.5); return min (x, max_value); } #if SHELL_TESTS #include #endif #define MSG_IS(x) (stream->msg != NULL && strcmp ((x), stream->msg) == 0) static const usize_t TWO_MEGS_AND_DELTA = (3 << 20); static const usize_t ADDR_CACHE_ROUNDS = 10000; static const usize_t TEST_FILE_MEAN = 16384; static const double TEST_ADD_MEAN = 128; static const double TEST_ADD_MAX = 512; static const double TEST_ADD_RATIO = 0.1; static const double TEST_EPSILON = 0.25; #define TESTBUFSIZE (1024 * 16) #define TESTFILESIZE (1024) static char TEST_TARGET_FILE[TESTFILESIZE]; static char TEST_SOURCE_FILE[TESTFILESIZE]; static char TEST_DELTA_FILE[TESTFILESIZE]; static char TEST_RECON_FILE[TESTFILESIZE]; static char TEST_RECON2_FILE[TESTFILESIZE]; static char TEST_COPY_FILE[TESTFILESIZE]; static char TEST_NOPERM_FILE[TESTFILESIZE]; #define CHECK(cond) if (!(cond)) { XPR(NT "check failure: " #cond); abort(); } #if SHELL_TESTS /* Use a fixed soft config so that test values are fixed. See also * test_compress_text(). */ static const char* test_softcfg_str = "-C9,3,4,8,2,36,70"; #endif /*********************************************************************** TEST HELPERS ***********************************************************************/ static void DOT (void) { XPR(NTR "."); } static int do_cmd (xd3_stream *stream, const char *buf) { int ret; if ((ret = system (buf)) != 0) { if (WIFEXITED (ret)) { stream->msg = "command exited non-zero"; IF_DEBUG1 (XPR(NT "command was: %s\n", buf)); } else { stream->msg = "abnormal command termination"; } return XD3_INTERNAL; } return 0; } static int do_fail (xd3_stream *stream, const char *buf) { int ret; ret = system (buf); if (! WIFEXITED (ret) || WEXITSTATUS (ret) != 1) { stream->msg = "command should have not succeeded"; XPR(NT "command was %s\n", buf); return XD3_INTERNAL; } return 0; } /* Test that the exponential distribution actually produces its mean. */ static int test_random_numbers (xd3_stream *stream, int ignore) { usize_t i; usize_t sum = 0; usize_t mean = 50; usize_t n_rounds = 1000000; double average, error; double allowed_error = 0.1; mt_init (& static_mtrand, 0x9f73f7fe); for (i = 0; i < n_rounds; i += 1) { sum += mt_exp_rand (mean, USIZE_T_MAX); } average = (double) sum / (double) n_rounds; error = average - (double) mean; if (error < allowed_error && error > -allowed_error) { return 0; } /*XPR(NT "error is %f\n", error);*/ stream->msg = "random distribution looks broken"; return XD3_INTERNAL; } static void test_unlink (char* file) { int ret; if ((ret = unlink (file)) != 0 && errno != ENOENT) { XPR(NT "unlink %s failed: %s\n", file, strerror(ret)); } } static void test_cleanup (void) { #if 1 test_unlink (TEST_TARGET_FILE); test_unlink (TEST_SOURCE_FILE); test_unlink (TEST_DELTA_FILE); test_unlink (TEST_RECON_FILE); test_unlink (TEST_RECON2_FILE); test_unlink (TEST_COPY_FILE); test_unlink (TEST_NOPERM_FILE); #endif } int test_setup (void) { static int x = 0; x++; snprintf_func (TEST_TARGET_FILE, TESTFILESIZE, "/tmp/xdtest.target.%d", x); snprintf_func (TEST_SOURCE_FILE, TESTFILESIZE, "/tmp/xdtest.source.%d", x); snprintf_func (TEST_DELTA_FILE, TESTFILESIZE, "/tmp/xdtest.delta.%d", x); snprintf_func (TEST_RECON_FILE, TESTFILESIZE, "/tmp/xdtest.recon.%d", x); snprintf_func (TEST_RECON2_FILE, TESTFILESIZE, "/tmp/xdtest.recon2.%d", x); snprintf_func (TEST_COPY_FILE, TESTFILESIZE, "/tmp/xdtest.copy.%d", x); snprintf_func (TEST_NOPERM_FILE, TESTFILESIZE, "/tmp/xdtest.noperm.%d", x); test_cleanup(); return 0; } static int test_make_inputs (xd3_stream *stream, xoff_t *ss_out, xoff_t *ts_out) { usize_t ts = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; usize_t ss = (mt_random (&static_mtrand) % TEST_FILE_MEAN) + TEST_FILE_MEAN / 2; uint8_t *buf = (uint8_t*) malloc (ts + ss), *sbuf = buf, *tbuf = buf + ss; usize_t sadd = 0, sadd_max = (usize_t)(ss * TEST_ADD_RATIO); FILE *tf = NULL, *sf = NULL; usize_t i, j; int ret; if (buf == NULL) { return ENOMEM; } if ((tf = fopen (TEST_TARGET_FILE, "w")) == NULL || (ss_out != NULL && (sf = fopen (TEST_SOURCE_FILE, "w")) == NULL)) { stream->msg = "write failed"; ret = get_errno (); goto failure; } if (ss_out != NULL) { for (i = 0; i < ss; ) { sbuf[i++] = (uint8_t) mt_random (&static_mtrand); } } /* Then modify the data to produce copies, everything not copied is * an add. The following logic produces the TEST_ADD_RATIO. The * variable SADD contains the number of adds so far, which should * not exceed SADD_MAX. */ /* XPR(NT "ss = %u ts = %u\n", ss, ts); */ for (i = 0; i < ts; ) { usize_t left = ts - i; usize_t next = mt_exp_rand ((uint32_t) TEST_ADD_MEAN, (uint32_t) TEST_ADD_MAX); usize_t add_left = sadd_max - sadd; double add_prob = (left == 0) ? 0 : (add_left / (double) left); int do_copy; next = min (left, next); do_copy = (next > add_left || (mt_random (&static_mtrand) / \ (double)USIZE_T_MAX) >= add_prob); if (ss_out == NULL) { do_copy &= (i > 0); } else { do_copy &= (ss - next) > 0; } if (do_copy) { /* Copy */ size_t offset = mt_random (&static_mtrand) % ((ss_out == NULL) ? i : (ss - next)); /* XPR(NT "[%u] copy %u at %u ", i, next, offset); */ for (j = 0; j < next; j += 1) { char c = ((ss_out == NULL) ? tbuf : sbuf)[offset + j]; /* XPR(NT "%x%x", (c >> 4) & 0xf, c & 0xf); */ tbuf[i++] = c; } /* XPR(NT "\n"); */ } else { /* Add */ /* XPR(NT "[%u] add %u ", i, next); */ for (j = 0; j < next; j += 1) { char c = (char) mt_random (&static_mtrand); /* XPR(NT "%x%x", (c >> 4) & 0xf, c & 0xf); */ tbuf[i++] = c; } /* XPR(NT "\n"); */ sadd += next; } } /* XPR(NT "sadd = %u max = %u\n", sadd, sadd_max); */ if ((fwrite (tbuf, 1, ts, tf) != ts) || (ss_out != NULL && (fwrite (sbuf, 1, ss, sf) != ss))) { stream->msg = "write failed"; ret = get_errno (); goto failure; } if ((ret = fclose (tf)) || (ss_out != NULL && (ret = fclose (sf)))) { stream->msg = "close failed"; ret = get_errno (); goto failure; } if (ts_out) { (*ts_out) = ts; } if (ss_out) { (*ss_out) = ss; } failure: free (buf); return ret; } int test_compare_files (const char* tgt, const char *rec) { FILE *orig, *recons; static uint8_t obuf[TESTBUFSIZE], rbuf[TESTBUFSIZE]; xoff_t offset = 0; size_t i; size_t oc, rc; xoff_t diffs = 0; if ((orig = fopen (tgt, "r")) == NULL) { XPR(NT "open %s failed\n", tgt); return get_errno (); } if ((recons = fopen (rec, "r")) == NULL) { XPR(NT "open %s failed\n", rec); return get_errno (); } for (;;) { oc = fread (obuf, 1, TESTBUFSIZE, orig); rc = fread (rbuf, 1, TESTBUFSIZE, recons); if (oc != rc) { return XD3_INTERNAL; } if (oc == 0) { break; } for (i = 0; i < oc; i += 1) { if (obuf[i] != rbuf[i]) { XPR(NT "byte %u (read %u @ %"Q"u) %d != %d\n", (int)i, (int)oc, offset, obuf[i], rbuf[i]); diffs++; return XD3_INTERNAL; } } offset += oc; } fclose (orig); fclose (recons); if (diffs != 0) { return XD3_INTERNAL; } return 0; } static int test_save_copy (const char *origname) { char buf[TESTBUFSIZE]; int ret; snprintf_func (buf, TESTBUFSIZE, "cp -f %s %s", origname, TEST_COPY_FILE); if ((ret = system (buf)) != 0) { return XD3_INTERNAL; } return 0; } static int test_file_size (const char* file, xoff_t *size) { struct stat sbuf; int ret; (*size) = 0; if (stat (file, & sbuf) < 0) { ret = get_errno (); XPR(NT "stat failed: %s: %s\n", file, strerror (ret)); return ret; } if (! S_ISREG (sbuf.st_mode)) { ret = XD3_INTERNAL; XPR(NT "not a regular file: %s: %s\n", file, strerror (ret)); return ret; } (*size) = sbuf.st_size; return 0; } /*********************************************************************** READ OFFSET ***********************************************************************/ /* Common test for read_integer errors: encodes a 64-bit value and * then attempts to read as a 32-bit value. If TRUNC is non-zero, * attempts to get errors by shortening the input, otherwise it should * overflow. Expects XD3_INTERNAL and MSG. */ static int test_read_integer_error (xd3_stream *stream, usize_t trunto, const char *msg) { uint64_t eval = 1ULL << 34; uint32_t rval; xd3_output *buf = NULL; const uint8_t *max; const uint8_t *inp; int ret; buf = xd3_alloc_output (stream, buf); if ((ret = xd3_emit_uint64_t (stream, & buf, eval))) { goto fail; } again: inp = buf->base; max = buf->base + buf->next - trunto; if ((ret = xd3_read_uint32_t (stream, & inp, max, & rval)) != XD3_INVALID_INPUT || !MSG_IS (msg)) { ret = XD3_INTERNAL; } else if (trunto && trunto < buf->next) { trunto += 1; goto again; } else { ret = 0; } fail: xd3_free_output (stream, buf); return ret; } /* Test integer overflow using the above routine. */ static int test_decode_integer_overflow (xd3_stream *stream, int unused) { return test_read_integer_error (stream, 0, "overflow in read_intger"); } /* Test integer EOI using the above routine. */ static int test_decode_integer_end_of_input (xd3_stream *stream, int unused) { return test_read_integer_error (stream, 1, "end-of-input in read_integer"); } /* Test that emit_integer/decode_integer/sizeof_integer/read_integer * work on correct inputs. Tests powers of (2^7), plus or minus, up * to the maximum value. */ #define TEST_ENCODE_DECODE_INTEGER(TYPE,ONE,MAX) \ xd3_output *rbuf = NULL; \ xd3_output *dbuf = NULL; \ TYPE values[64]; \ usize_t nvalues = 0; \ usize_t i; \ int ret = 0; \ \ for (i = 0; i < (sizeof (TYPE) * 8); i += 7) \ { \ values[nvalues++] = (ONE << i) - ONE; \ values[nvalues++] = (ONE << i); \ values[nvalues++] = (ONE << i) + ONE; \ } \ \ values[nvalues++] = MAX-ONE; \ values[nvalues++] = MAX; \ \ rbuf = xd3_alloc_output (stream, rbuf); \ dbuf = xd3_alloc_output (stream, dbuf); \ \ for (i = 0; i < nvalues; i += 1) \ { \ const uint8_t *max; \ const uint8_t *inp; \ TYPE val; \ \ DOT (); \ rbuf->next = 0; \ \ if ((ret = xd3_emit_ ## TYPE (stream, & rbuf, values[i])) || \ (ret = xd3_emit_ ## TYPE (stream, & dbuf, values[i]))) \ { \ goto fail; \ } \ \ inp = rbuf->base; \ max = rbuf->base + rbuf->next; \ \ if (rbuf->next != xd3_sizeof_ ## TYPE (values[i])) \ { \ ret = XD3_INTERNAL; \ goto fail; \ } \ \ if ((ret = xd3_read_ ## TYPE (stream, & inp, max, & val))) \ { \ goto fail; \ } \ \ if (val != values[i]) \ { \ ret = XD3_INTERNAL; \ goto fail; \ } \ \ DOT (); \ } \ \ stream->next_in = dbuf->base; \ stream->avail_in = dbuf->next; \ \ for (i = 0; i < nvalues; i += 1) \ { \ TYPE val; \ \ if ((ret = xd3_decode_ ## TYPE (stream, & val))) \ { \ goto fail; \ } \ \ if (val != values[i]) \ { \ ret = XD3_INTERNAL; \ goto fail; \ } \ } \ \ if (stream->avail_in != 0) \ { \ ret = XD3_INTERNAL; \ goto fail; \ } \ \ fail: \ xd3_free_output (stream, rbuf); \ xd3_free_output (stream, dbuf); \ \ return ret static int test_encode_decode_uint32_t (xd3_stream *stream, int unused) { TEST_ENCODE_DECODE_INTEGER(uint32_t,1U,UINT32_MAX); } static int test_encode_decode_uint64_t (xd3_stream *stream, int unused) { TEST_ENCODE_DECODE_INTEGER(uint64_t,1ULL,UINT64_MAX); } static int test_usize_t_overflow (xd3_stream *stream, int unused) { if (USIZE_T_OVERFLOW (USIZE_T_MAX, 0)) { goto fail; } if (USIZE_T_OVERFLOW (0, USIZE_T_MAX)) { goto fail; } if (USIZE_T_OVERFLOW (USIZE_T_MAX / 2, USIZE_T_MAX / 2)) { goto fail; } if (USIZE_T_OVERFLOW (USIZE_T_MAX / 2, USIZE_T_MAX / 2 + 1)) { goto fail; } if (! USIZE_T_OVERFLOW (USIZE_T_MAX, 1)) { goto fail; } if (! USIZE_T_OVERFLOW (1, USIZE_T_MAX)) { goto fail; } if (! USIZE_T_OVERFLOW (USIZE_T_MAX / 2 + 1, USIZE_T_MAX / 2 + 1)) { goto fail; } return 0; fail: stream->msg = "incorrect overflow computation"; return XD3_INTERNAL; } static int test_forward_match (xd3_stream *stream, int unused) { usize_t i; uint8_t buf1[256], buf2[256]; memset(buf1, 0, 256); memset(buf2, 0, 256); for (i = 0; i < 256; i++) { CHECK(xd3_forward_match(buf1, buf2, i) == (int)i); } for (i = 0; i < 255; i++) { buf2[i] = 1; CHECK(xd3_forward_match(buf1, buf2, 256) == (int)i); buf2[i] = 0; } return 0; } /*********************************************************************** Address cache ***********************************************************************/ static int test_address_cache (xd3_stream *stream, int unused) { int ret; usize_t i; usize_t offset; usize_t *addrs; uint8_t *big_buf, *buf_max; const uint8_t *buf; xd3_output *outp; uint8_t *modes; int mode_counts[16]; stream->acache.s_near = stream->code_table_desc->near_modes; stream->acache.s_same = stream->code_table_desc->same_modes; if ((ret = xd3_encode_init_partial (stream))) { return ret; } addrs = (usize_t*) xd3_alloc (stream, sizeof (usize_t), ADDR_CACHE_ROUNDS); modes = (uint8_t*) xd3_alloc (stream, sizeof (uint8_t), ADDR_CACHE_ROUNDS); memset (mode_counts, 0, sizeof (mode_counts)); memset (modes, 0, ADDR_CACHE_ROUNDS); addrs[0] = 0; mt_init (& static_mtrand, 0x9f73f7fc); /* First pass: encode addresses */ xd3_init_cache (& stream->acache); for (offset = 1; offset < ADDR_CACHE_ROUNDS; offset += 1) { double p; usize_t addr; usize_t prev_i; usize_t nearby; p = (mt_random (&static_mtrand) / (double)USIZE_T_MAX); prev_i = mt_random (&static_mtrand) % offset; nearby = (mt_random (&static_mtrand) % 256) % offset; nearby = max (1U, nearby); if (p < 0.1) { addr = addrs[offset-nearby]; } else if (p < 0.4) { addr = min (addrs[prev_i] + nearby, offset-1); } else { addr = prev_i; } if ((ret = xd3_encode_address (stream, addr, offset, & modes[offset]))) { return ret; } addrs[offset] = addr; mode_counts[modes[offset]] += 1; } /* Copy addresses into a contiguous buffer. */ big_buf = (uint8_t*) xd3_alloc (stream, xd3_sizeof_output (ADDR_HEAD (stream)), 1); for (offset = 0, outp = ADDR_HEAD (stream); outp != NULL; offset += outp->next, outp = outp->next_page) { memcpy (big_buf + offset, outp->base, outp->next); } buf_max = big_buf + offset; buf = big_buf; /* Second pass: decode addresses */ xd3_init_cache (& stream->acache); for (offset = 1; offset < ADDR_CACHE_ROUNDS; offset += 1) { uint32_t addr; if ((ret = xd3_decode_address (stream, offset, modes[offset], & buf, buf_max, & addr))) { return ret; } if (addr != addrs[offset]) { stream->msg = "incorrect decoded address"; return XD3_INTERNAL; } } /* Check that every byte, mode was used. */ if (buf != buf_max) { stream->msg = "address bytes not used"; return XD3_INTERNAL; } for (i = 0; i < (2 + stream->acache.s_same + stream->acache.s_near); i += 1) { if (mode_counts[i] == 0) { stream->msg = "address mode not used"; return XD3_INTERNAL; } } xd3_free (stream, modes); xd3_free (stream, addrs); xd3_free (stream, big_buf); return 0; } /*********************************************************************** Encode and decode with single bit error ***********************************************************************/ /* It compresses from 256 to around 185 bytes. * Avoids matching addresses that are a single-bit difference. * Avoids matching address 0. */ static const uint8_t test_text[] = "this is a story\n" "abouttttttttttt\n" "- his is a stor\n" "- about nothing " " all. boutique -" "his story is a -" "about " "what happens all" " the time what -" "am I ttttttt the" " person said, so" " what, per son -" " gory story is -" " about nothing -" "tttttt to test -" "his sto nothing"; static const uint8_t test_apphead[] = "header test"; static int test_compress_text (xd3_stream *stream, uint8_t *encoded, usize_t *encoded_size) { int ret; xd3_config cfg; int oflags = stream->flags; int flags = stream->flags | XD3_FLUSH; xd3_free_stream (stream); xd3_init_config (& cfg, flags); /* This configuration is fixed so that the "expected non-error" the counts in * decompress_single_bit_errors are too. See test_coftcfg_str. */ cfg.smatch_cfg = XD3_SMATCH_SOFT; cfg.smatcher_soft.name = "test"; cfg.smatcher_soft.large_look = 64; /* no source, not used */ cfg.smatcher_soft.large_step = 64; /* no source, not used */ cfg.smatcher_soft.small_look = 4; cfg.smatcher_soft.small_chain = 128; cfg.smatcher_soft.small_lchain = 16; cfg.smatcher_soft.max_lazy = 8; cfg.smatcher_soft.long_enough = 128; xd3_config_stream (stream, & cfg); (*encoded_size) = 0; xd3_set_appheader (stream, test_apphead, (usize_t) strlen ((char*) test_apphead)); if ((ret = xd3_encode_stream (stream, test_text, sizeof (test_text), encoded, encoded_size, 4*sizeof (test_text)))) { goto fail; } if ((ret = xd3_close_stream (stream))) { goto fail; } fail: xd3_free_stream (stream); xd3_init_config (& cfg, oflags); xd3_config_stream (stream, & cfg); return ret; } static int test_decompress_text (xd3_stream *stream, uint8_t *enc, usize_t enc_size, usize_t test_desize) { xd3_config cfg; char decoded[sizeof (test_text)]; uint8_t *apphead; usize_t apphead_size; usize_t decoded_size; const char *msg; int ret; usize_t pos = 0; int flags = stream->flags; usize_t take; input: /* Test decoding test_desize input bytes at a time */ take = min (enc_size - pos, test_desize); CHECK(take > 0); xd3_avail_input (stream, enc + pos, take); again: ret = xd3_decode_input (stream); pos += take; take = 0; switch (ret) { case XD3_OUTPUT: break; case XD3_WINSTART: case XD3_GOTHEADER: goto again; case XD3_INPUT: if (pos < enc_size) { goto input; } /* else fallthrough */ case XD3_WINFINISH: default: goto fail; } CHECK(ret == XD3_OUTPUT); CHECK(pos == enc_size); if (stream->avail_out != sizeof (test_text)) { stream->msg = "incorrect output size"; ret = XD3_INTERNAL; goto fail; } decoded_size = stream->avail_out; memcpy (decoded, stream->next_out, stream->avail_out); xd3_consume_output (stream); if ((ret = xd3_get_appheader (stream, & apphead, & apphead_size))) { goto fail; } if (apphead_size != strlen ((char*) test_apphead) || memcmp (apphead, test_apphead, strlen ((char*) test_apphead)) != 0) { stream->msg = "incorrect appheader"; ret = XD3_INTERNAL; goto fail; } if ((ret = xd3_decode_input (stream)) != XD3_WINFINISH || (ret = xd3_close_stream (stream)) != 0) { goto fail; } if (decoded_size != sizeof (test_text) || memcmp (decoded, test_text, sizeof (test_text)) != 0) { stream->msg = "incorrect output text"; ret = EIO; } fail: msg = stream->msg; xd3_free_stream (stream); xd3_init_config (& cfg, flags); xd3_config_stream (stream, & cfg); stream->msg = msg; return ret; } static int test_decompress_single_bit_error (xd3_stream *stream, int expected_non_failures) { int ret; usize_t i; uint8_t encoded[4*sizeof (test_text)]; /* make room for alt code table */ usize_t encoded_size; int non_failures = 0; int cksum = (stream->flags & XD3_ADLER32) != 0; //#define DEBUG_TEST_FAILURES #ifndef DEBUG_TEST_FAILURES #define TEST_FAILURES() #else /* For checking non-failure cases by hand, enable this macro and run * xdelta printdelta with print_cpymode disabled. Every non-failure * should change a copy address mode, which doesn't cause a failure * because the address cache starts out with all zeros. ./xdelta3 test for i in test_text.xz.*; do ./xdelta3 printdelta $i > $i.out; diff $i.out test_text.xz.0.out; done */ system ("rm -rf test_text.*"); { char buf[TESTBUFSIZE]; FILE *f; snprintf_func (buf, TESTBUFSIZE, "test_text"); f = fopen (buf, "w"); fwrite (test_text,1,sizeof (test_text),f); fclose (f); } #define TEST_FAILURES() \ do { \ char buf[TESTBUFSIZE]; \ FILE *f; \ snprintf_func (buf, TESTBUFSIZE, "test_text.xz.%d", non_failures); \ f = fopen (buf, "w"); \ fwrite (encoded,1,encoded_size,f); \ fclose (f); \ } while (0) #endif stream->sec_data.inefficient = 1; stream->sec_inst.inefficient = 1; stream->sec_addr.inefficient = 1; /* Encode text, test correct input */ if ((ret = test_compress_text (stream, encoded, & encoded_size))) { /*stream->msg = "without error: encode failure";*/ return ret; } if ((ret = test_decompress_text (stream, encoded, encoded_size, sizeof (test_text) / 4))) { /*stream->msg = "without error: decode failure";*/ return ret; } TEST_FAILURES(); for (i = 0; i < encoded_size*8; i += 1) { /* Single bit error. */ encoded[i/8] ^= 1 << (i%8); if ((ret = test_decompress_text (stream, encoded, encoded_size, sizeof (test_text))) == 0) { non_failures += 1; #ifdef DEBUG_TEST_FAILURES XPR(NT "%u[%u] non-failure %u\n", i/8, i%8, non_failures); #endif TEST_FAILURES(); } else { /*XPR(NT "%u[%u] failure: %s\n", i/8, i%8, stream->msg);*/ } /* decompress_text returns EIO when the final memcmp() fails, but that * should never happen with checksumming on. */ if (cksum && ret == EIO) { /*XPR(NT "%u[%u] cksum mismatch\n", i/8, i%8);*/ stream->msg = "checksum mismatch"; return XD3_INTERNAL; } /* Undo single bit error. */ encoded[i/8] ^= 1 << (i%8); } /* Test correct input again */ if ((ret = test_decompress_text (stream, encoded, encoded_size, 1))) { /*stream->msg = "without error: decode failure";*/ return ret; } /* Check expected non-failures */ if (non_failures != expected_non_failures) { XPR(NT "non-failures %u; expected %u", non_failures, expected_non_failures); stream->msg = "incorrect"; return XD3_INTERNAL; } DOT (); return 0; } /*********************************************************************** Secondary compression tests ***********************************************************************/ #if SECONDARY_ANY typedef int (*sec_dist_func) (xd3_stream *stream, xd3_output *data); static int sec_dist_func1 (xd3_stream *stream, xd3_output *data); static int sec_dist_func2 (xd3_stream *stream, xd3_output *data); static int sec_dist_func3 (xd3_stream *stream, xd3_output *data); static int sec_dist_func4 (xd3_stream *stream, xd3_output *data); static int sec_dist_func5 (xd3_stream *stream, xd3_output *data); static int sec_dist_func6 (xd3_stream *stream, xd3_output *data); static int sec_dist_func7 (xd3_stream *stream, xd3_output *data); static int sec_dist_func8 (xd3_stream *stream, xd3_output *data); static int sec_dist_func9 (xd3_stream *stream, xd3_output *data); static int sec_dist_func10 (xd3_stream *stream, xd3_output *data); static int sec_dist_func11 (xd3_stream *stream, xd3_output *data); static sec_dist_func sec_dists[] = { sec_dist_func1, sec_dist_func2, sec_dist_func3, sec_dist_func4, sec_dist_func5, sec_dist_func6, sec_dist_func7, sec_dist_func8, sec_dist_func9, sec_dist_func10, sec_dist_func11, }; /* Test ditsribution: 100 bytes of the same character (13). */ static int sec_dist_func1 (xd3_stream *stream, xd3_output *data) { int i, ret; for (i = 0; i < 100; i += 1) { if ((ret = xd3_emit_byte (stream, & data, 13))) { return ret; } } return 0; } /* Test ditsribution: uniform covering half the alphabet. */ static int sec_dist_func2 (xd3_stream *stream, xd3_output *data) { int i, ret; for (i = 0; i < ALPHABET_SIZE; i += 1) { if ((ret = xd3_emit_byte (stream, & data, i%(ALPHABET_SIZE/2)))) { return ret; } } return 0; } /* Test ditsribution: uniform covering the entire alphabet. */ static int sec_dist_func3 (xd3_stream *stream, xd3_output *data) { int i, ret; for (i = 0; i < ALPHABET_SIZE; i += 1) { if ((ret = xd3_emit_byte (stream, & data, i%ALPHABET_SIZE))) { return ret; } } return 0; } /* Test distribution: An exponential distribution covering half the alphabet */ static int sec_dist_func4 (xd3_stream *stream, xd3_output *data) { int i, ret, x; for (i = 0; i < ALPHABET_SIZE*20; i += 1) { x = mt_exp_rand (10, ALPHABET_SIZE/2); if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } } return 0; } /* Test distribution: An exponential distribution covering the entire alphabet */ static int sec_dist_func5 (xd3_stream *stream, xd3_output *data) { int i, ret, x; for (i = 0; i < ALPHABET_SIZE*20; i += 1) { x = mt_exp_rand (10, ALPHABET_SIZE-1); if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } } return 0; } /* Test distribution: An uniform random distribution covering half the alphabet */ static int sec_dist_func6 (xd3_stream *stream, xd3_output *data) { int i, ret, x; for (i = 0; i < ALPHABET_SIZE*20; i += 1) { x = mt_random (&static_mtrand) % (ALPHABET_SIZE/2); if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } } return 0; } /* Test distribution: An uniform random distribution covering the entire alphabet */ static int sec_dist_func7 (xd3_stream *stream, xd3_output *data) { int i, ret, x; for (i = 0; i < ALPHABET_SIZE*200; i += 1) { x = mt_random (&static_mtrand) % ALPHABET_SIZE; if ((ret = xd3_emit_byte (stream, & data, x))) { return ret; } } return 0; } /* Test distribution: A small number of frequent characters, difficult * to divide into many groups */ static int sec_dist_func8 (xd3_stream *stream, xd3_output *data) { int i, ret; for (i = 0; i < ALPHABET_SIZE*5; i += 1) { if ((ret = xd3_emit_byte (stream, & data, 0))) { return ret; } if ((ret = xd3_emit_byte (stream, & data, 64))) { return ret; } if ((ret = xd3_emit_byte (stream, & data, 128))) { return ret; } if ((ret = xd3_emit_byte (stream, & data, 255))) { return ret; } } return 0; } /* Test distribution: One that causes many FGK block promotions (found a bug) */ static int sec_dist_func9 (xd3_stream *stream, xd3_output *data) { int i, ret; int ramp = 0; int rcount = 0; int prom = 0; int pcount = 0; /* 200 was long enough to trigger it--only when stricter checking * that counted all blocks was turned on, but it seems I deleted * this code. (missing fgk_free_block on line 398). */ for (i = 0; i < ALPHABET_SIZE*200; i += 1) { repeat: if (ramp < ALPHABET_SIZE) { /* Initially Nth symbol has (N+1) frequency */ if (rcount <= ramp) { rcount += 1; if ((ret = xd3_emit_byte (stream, & data, ramp))) { return ret; } continue; } ramp += 1; rcount = 0; goto repeat; } /* Thereafter, promote least freq to max freq */ if (pcount == ALPHABET_SIZE) { pcount = 0; prom = (prom + 1) % ALPHABET_SIZE; } pcount += 1; if ((ret = xd3_emit_byte (stream, & data, prom))) { return ret; } } return 0; } /* Test distribution: freq[i] == i*i, creates a 21-bit code length, fixed in 3.0r. */ static int sec_dist_func10 (xd3_stream *stream, xd3_output *data) { int i, j, ret; for (i = 0; i < ALPHABET_SIZE; i += 1) { for (j = 0; j <= (i*i); j += 1) { if ((ret = xd3_emit_byte (stream, & data, i))) { return ret; } } } return 0; } /* Test distribution: fibonacci */ static int sec_dist_func11 (xd3_stream *stream, xd3_output *data) { int sum0 = 0; int sum1 = 1; int i, j, ret; for (i = 0; i < 33; ++i) { for (j = 0; j < (sum0 + sum1); ++j) { if ((ret = xd3_emit_byte (stream, & data, i))) { return ret; } } sum0 = sum1; sum1 = j; } return 0; } static int test_secondary_decode (xd3_stream *stream, const xd3_sec_type *sec, usize_t input_size, usize_t compress_size, const uint8_t *dec_input, const uint8_t *dec_correct, uint8_t *dec_output) { int ret; xd3_sec_stream *dec_stream; const uint8_t *dec_input_used, *dec_input_end; uint8_t *dec_output_used, *dec_output_end; if ((dec_stream = sec->alloc (stream)) == NULL) { return ENOMEM; } if ((ret = sec->init (stream, dec_stream, 0)) != 0) { goto fail; } dec_input_used = dec_input; dec_input_end = dec_input + compress_size; dec_output_used = dec_output; dec_output_end = dec_output + input_size; if ((ret = sec->decode (stream, dec_stream, & dec_input_used, dec_input_end, & dec_output_used, dec_output_end))) { goto fail; } if (dec_input_used != dec_input_end) { stream->msg = "unused input"; ret = XD3_INTERNAL; goto fail; } if (dec_output_used != dec_output_end) { stream->msg = "unfinished output"; ret = XD3_INTERNAL; goto fail; } if (memcmp (dec_output, dec_correct, input_size) != 0) { stream->msg = "incorrect output"; ret = XD3_INTERNAL; goto fail; } fail: sec->destroy (stream, dec_stream); return ret; } static int test_secondary (xd3_stream *stream, const xd3_sec_type *sec, usize_t groups) { usize_t test_i; int ret; xd3_output *in_head, *out_head, *p; usize_t p_off, input_size, compress_size; uint8_t *dec_input = NULL, *dec_output = NULL, *dec_correct = NULL; xd3_sec_stream *enc_stream; xd3_sec_cfg cfg; memset (& cfg, 0, sizeof (cfg)); cfg.inefficient = 1; for (cfg.ngroups = 1; cfg.ngroups <= groups; cfg.ngroups += 1) { XPR(NTR "\n..."); for (test_i = 0; test_i < SIZEOF_ARRAY (sec_dists); test_i += 1) { mt_init (& static_mtrand, 0x9f73f7fc); in_head = xd3_alloc_output (stream, NULL); out_head = xd3_alloc_output (stream, NULL); enc_stream = sec->alloc (stream); dec_input = NULL; dec_output = NULL; dec_correct = NULL; if (in_head == NULL || out_head == NULL || enc_stream == NULL) { goto nomem; } if ((ret = sec_dists[test_i] (stream, in_head))) { goto fail; } if ((ret = sec->init (stream, enc_stream, 1)) != 0) { goto fail; } /* Encode data */ if ((ret = sec->encode (stream, enc_stream, in_head, out_head, & cfg))) { XPR(NT "test %u: encode: %s", test_i, stream->msg); goto fail; } /* Calculate sizes, allocate contiguous arrays for decoding */ input_size = xd3_sizeof_output (in_head); compress_size = xd3_sizeof_output (out_head); XPR(NTR "%.3f", 8.0 * (double) compress_size / (double) input_size); if ((dec_input = (uint8_t*) xd3_alloc (stream, compress_size, 1)) == NULL || (dec_output = (uint8_t*) xd3_alloc (stream, input_size, 1)) == NULL || (dec_correct = (uint8_t*) xd3_alloc (stream, input_size, 1)) == NULL) { goto nomem; } /* Fill the compressed data array */ for (p_off = 0, p = out_head; p != NULL; p_off += p->next, p = p->next_page) { memcpy (dec_input + p_off, p->base, p->next); } CHECK(p_off == compress_size); /* Fill the input data array */ for (p_off = 0, p = in_head; p != NULL; p_off += p->next, p = p->next_page) { memcpy (dec_correct + p_off, p->base, p->next); } CHECK(p_off == input_size); if ((ret = test_secondary_decode (stream, sec, input_size, compress_size, dec_input, dec_correct, dec_output))) { XPR(NT "test %u: decode: %s", test_i, stream->msg); goto fail; } /* Single-bit error test, only cover the first 10 bytes. * Some non-failures are expected in the Huffman case: * Changing the clclen array, for example, may not harm the * decoding. Really looking for faults here. */ { int i; int bytes = min (compress_size, 10U); for (i = 0; i < bytes * 8; i += 1) { dec_input[i/8] ^= 1 << (i%8); if ((ret = test_secondary_decode (stream, sec, input_size, compress_size, dec_input, dec_correct, dec_output)) == 0) { /*XPR(NT "test %u: decode single-bit [%u/%u] error non-failure", test_i, i/8, i%8);*/ } dec_input[i/8] ^= 1 << (i%8); if ((i % (2*bytes)) == (2*bytes)-1) { DOT (); } } ret = 0; } if (0) { nomem: ret = ENOMEM; } fail: sec->destroy (stream, enc_stream); xd3_free_output (stream, in_head); xd3_free_output (stream, out_head); xd3_free (stream, dec_input); xd3_free (stream, dec_output); xd3_free (stream, dec_correct); if (ret != 0) { return ret; } } } return 0; } IF_FGK (static int test_secondary_fgk (xd3_stream *stream, usize_t gp) { return test_secondary (stream, & fgk_sec_type, gp); }) IF_DJW (static int test_secondary_huff (xd3_stream *stream, usize_t gp) { return test_secondary (stream, & djw_sec_type, gp); }) IF_LZMA (static int test_secondary_lzma (xd3_stream *stream, usize_t gp) { return test_secondary (stream, & lzma_sec_type, gp); }) #endif /*********************************************************************** TEST INSTRUCTION TABLE ***********************************************************************/ /* Test that xd3_choose_instruction() does the right thing for its code * table. */ static int test_choose_instruction (xd3_stream *stream, int ignore) { int i; stream->code_table = (*stream->code_table_func) (); for (i = 0; i < 256; i += 1) { const xd3_dinst *d = stream->code_table + i; xd3_rinst prev, inst; CHECK(d->type1 > 0); memset (& prev, 0, sizeof (prev)); memset (& inst, 0, sizeof (inst)); if (d->type2 == 0) { inst.type = d->type1; if ((inst.size = d->size1) == 0) { inst.size = TESTBUFSIZE; } XD3_CHOOSE_INSTRUCTION (stream, NULL, & inst); if (inst.code2 != 0 || inst.code1 != i) { stream->msg = "wrong single instruction"; return XD3_INTERNAL; } } else { prev.type = d->type1; prev.size = d->size1; inst.type = d->type2; inst.size = d->size2; XD3_CHOOSE_INSTRUCTION (stream, & prev, & inst); if (prev.code2 != i) { stream->msg = "wrong double instruction"; return XD3_INTERNAL; } } } return 0; } /*********************************************************************** TEST INSTRUCTION TABLE CODING ***********************************************************************/ #if GENERIC_ENCODE_TABLES /* Test that encoding and decoding a code table works */ static int test_encode_code_table (xd3_stream *stream, int ignore) { int ret; const uint8_t *comp_data; usize_t comp_size; if ((ret = xd3_compute_alternate_table_encoding (stream, & comp_data, & comp_size))) { return ret; } stream->acache.s_near = __alternate_code_table_desc.near_modes; stream->acache.s_same = __alternate_code_table_desc.same_modes; if ((ret = xd3_apply_table_encoding (stream, comp_data, comp_size))) { return ret; } if (memcmp (stream->code_table, xd3_alternate_code_table (), sizeof (xd3_dinst) * 256) != 0) { stream->msg = "wrong code table reconstruction"; return XD3_INTERNAL; } return 0; } #endif /*********************************************************************** 64BIT STREAMING ***********************************************************************/ /* This test encodes and decodes a series of 1 megabyte windows, each * containing a long run of zeros along with a single xoff_t size * record to indicate the sequence. */ static int test_streaming (xd3_stream *in_stream, uint8_t *encbuf, uint8_t *decbuf, uint8_t *delbuf, usize_t megs) { xd3_stream estream, dstream; int ret; usize_t i, delsize, decsize; xd3_config cfg; xd3_init_config (& cfg, in_stream->flags); cfg.flags |= XD3_COMPLEVEL_6; if ((ret = xd3_config_stream (& estream, & cfg)) || (ret = xd3_config_stream (& dstream, & cfg))) { goto fail; } for (i = 0; i < megs; i += 1) { ((usize_t*) encbuf)[0] = i; if ((i % 200) == 199) { DOT (); } if ((ret = xd3_process_stream (1, & estream, xd3_encode_input, 0, encbuf, 1 << 20, delbuf, & delsize, 1 << 20))) { in_stream->msg = estream.msg; goto fail; } if ((ret = xd3_process_stream (0, & dstream, xd3_decode_input, 0, delbuf, delsize, decbuf, & decsize, 1 << 20))) { in_stream->msg = dstream.msg; goto fail; } if (decsize != 1 << 20 || memcmp (encbuf, decbuf, 1 << 20) != 0) { in_stream->msg = "wrong result"; ret = XD3_INTERNAL; goto fail; } } if ((ret = xd3_close_stream (& estream)) || (ret = xd3_close_stream (& dstream))) { goto fail; } fail: xd3_free_stream (& estream); xd3_free_stream (& dstream); return ret; } /* Run tests of data streaming of over and around 4GB of data. */ static int test_compressed_stream_overflow (xd3_stream *stream, int ignore) { int ret; int i; uint8_t *buf; if ((buf = (uint8_t*) malloc (TWO_MEGS_AND_DELTA)) == NULL) { return ENOMEM; } memset (buf, 0, TWO_MEGS_AND_DELTA); for (i = 0; i < (2 << 20); i += 256) { int j; int off = mt_random(& static_mtrand) % 10; for (j = 0; j < 256; j++) { buf[i + j] = j + off; } } /* Test overflow of a 32-bit file offset. */ if (SIZEOF_XOFF_T == 4) { ret = test_streaming (stream, buf, buf + (1 << 20), buf + (2 << 20), (1 << 12) + 1); if (ret == XD3_INVALID_INPUT && MSG_IS ("decoder file offset overflow")) { ret = 0; } else { XPR(NT XD3_LIB_ERRMSG (stream, ret)); stream->msg = "expected overflow condition"; ret = XD3_INTERNAL; goto fail; } } /* Test transfer of exactly 32bits worth of data. */ if ((ret = test_streaming (stream, buf, buf + (1 << 20), buf + (2 << 20), 1 << 12))) { goto fail; } fail: free (buf); return ret; } /*********************************************************************** COMMAND LINE ***********************************************************************/ #if SHELL_TESTS /* For each pair of command templates in the array below, test that * encoding and decoding commands work. Also check for the expected * size delta, which should be approximately TEST_ADD_RATIO times the * file size created by test_make_inputs. Due to differences in the * application header, it is suppressed (-A) so that all delta files * are the same. */ static int test_command_line_arguments (xd3_stream *stream, int ignore) { int i, ret; static const char* cmdpairs[] = { /* standard input, output */ "%s %s -A < %s > %s", "%s -d < %s > %s", "%s %s -A -e < %s > %s", "%s -d < %s > %s", "%s %s -A= encode < %s > %s", "%s decode < %s > %s", "%s %s -A -q encode < %s > %s", "%s -qdq < %s > %s", /* file input, standard output */ "%s %s -A= %s > %s", "%s -d %s > %s", "%s %s -A -e %s > %s", "%s -d %s > %s", "%s %s encode -A= %s > %s", "%s decode %s > %s", /* file input, output */ "%s %s -A= %s %s", "%s -d %s %s", "%s %s -A -e %s %s", "%s -d %s %s", "%s %s -A= encode %s %s", "%s decode %s %s", /* option placement */ "%s %s -A -f %s %s", "%s -f -d %s %s", "%s %s -e -A= %s %s", "%s -d -f %s %s", "%s %s -f encode -A= %s %s", "%s -f decode -f %s %s", }; char ecmd[TESTBUFSIZE], dcmd[TESTBUFSIZE]; int pairs = SIZEOF_ARRAY (cmdpairs) / 2; xoff_t tsize; xoff_t dsize; double ratio; mt_init (& static_mtrand, 0x9f73f7fc); for (i = 0; i < pairs; i += 1) { test_setup (); if ((ret = test_make_inputs (stream, NULL, & tsize))) { return ret; } snprintf_func (ecmd, TESTBUFSIZE, cmdpairs[2*i], program_name, test_softcfg_str, TEST_TARGET_FILE, TEST_DELTA_FILE); snprintf_func (dcmd, TESTBUFSIZE, cmdpairs[2*i+1], program_name, TEST_DELTA_FILE, TEST_RECON_FILE); /* Encode and decode. */ if ((ret = system (ecmd)) != 0) { XPR(NT "encode command: %s\n", ecmd); stream->msg = "encode cmd failed"; return XD3_INTERNAL; } if ((ret = system (dcmd)) != 0) { XPR(NT "decode command: %s\n", dcmd); stream->msg = "decode cmd failed"; return XD3_INTERNAL; } /* Compare the target file. */ if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) { return ret; } if ((ret = test_file_size (TEST_DELTA_FILE, & dsize))) { return ret; } ratio = (double) dsize / (double) tsize; /* Check that it is not too small, not too large. */ if (ratio >= TEST_ADD_RATIO + TEST_EPSILON) { XPR(NT "test encode with size ratio %.4f, " "expected < %.4f (%"Q"u, %"Q"u)\n", ratio, TEST_ADD_RATIO + TEST_EPSILON, dsize, tsize); stream->msg = "strange encoding"; return XD3_INTERNAL; } if (ratio <= TEST_ADD_RATIO * (1.0 - 2 * TEST_EPSILON)) { XPR(NT "test encode with size ratio %.4f, " "expected > %.4f\n", ratio, TEST_ADD_RATIO - TEST_EPSILON); stream->msg = "strange encoding"; return XD3_INTERNAL; } /* Also check that test_compare_files works. The delta and original should * not be identical. */ if ((ret = test_compare_files (TEST_DELTA_FILE, TEST_TARGET_FILE)) == 0) { stream->msg = "broken test_compare_files"; return XD3_INTERNAL; } test_cleanup (); DOT (); } return 0; } static int check_vcdiff_header (xd3_stream *stream, const char *input, const char *line_start, const char *matches, int yes_or_no) { int ret; char vcmd[TESTBUFSIZE], gcmd[TESTBUFSIZE]; snprintf_func (vcmd, TESTBUFSIZE, "%s printhdr -f %s %s", program_name, input, TEST_RECON2_FILE); if ((ret = system (vcmd)) != 0) { XPR(NT "printhdr command: %s\n", vcmd); stream->msg = "printhdr cmd failed"; return XD3_INTERNAL; } snprintf_func (gcmd, TESTBUFSIZE, "grep \"%s.*%s.*\" %s > /dev/null", line_start, matches, TEST_RECON2_FILE); if (yes_or_no) { if ((ret = do_cmd (stream, gcmd))) { XPR(NT "%s\n", gcmd); return ret; } } else { if ((ret = do_fail (stream, gcmd))) { XPR(NT "%s\n", gcmd); return ret; } } return 0; } static int test_recode_command2 (xd3_stream *stream, int has_source, int variant, int change) { int has_adler32 = (variant & 0x1) != 0; int has_apphead = (variant & 0x2) != 0; int has_secondary = (variant & 0x4) != 0; int change_adler32 = (change & 0x1) != 0; int change_apphead = (change & 0x2) != 0; int change_secondary = (change & 0x4) != 0; int recoded_adler32 = change_adler32 ? !has_adler32 : has_adler32; int recoded_apphead = change_apphead ? !has_apphead : has_apphead; int recoded_secondary = change_secondary ? !has_secondary : has_secondary; char ecmd[TESTBUFSIZE], recmd[TESTBUFSIZE], dcmd[TESTBUFSIZE]; xoff_t tsize, ssize; int ret; test_setup (); if ((ret = test_make_inputs (stream, has_source ? & ssize : NULL, & tsize))) { return ret; } /* First encode */ snprintf_func (ecmd, TESTBUFSIZE, "%s %s -f %s %s %s %s %s %s %s", program_name, test_softcfg_str, has_adler32 ? "" : "-n ", has_apphead ? "-A=encode_apphead " : "-A= ", has_secondary ? "-S djw " : "-S none ", has_source ? "-s " : "", has_source ? TEST_SOURCE_FILE : "", TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = system (ecmd)) != 0) { XPR(NT "encode command: %s\n", ecmd); stream->msg = "encode cmd failed"; return XD3_INTERNAL; } /* Now recode */ snprintf_func (recmd, TESTBUFSIZE, "%s recode %s -f %s %s %s %s %s", program_name, test_softcfg_str, recoded_adler32 ? "" : "-n ", !change_apphead ? "" : (recoded_apphead ? "-A=recode_apphead " : "-A= "), recoded_secondary ? "-S djw " : "-S none ", TEST_DELTA_FILE, TEST_COPY_FILE); if ((ret = system (recmd)) != 0) { XPR(NT "recode command: %s\n", recmd); stream->msg = "recode cmd failed"; return XD3_INTERNAL; } /* Check recode changes. */ if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF window indicator", "VCD_SOURCE", has_source))) { return ret; } if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF header indicator", "VCD_SECONDARY", recoded_secondary))) { return ret; } if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF window indicator", "VCD_ADLER32", /* Recode can't generate an adler32 * checksum, it can only preserve it or * remove it. */ has_adler32 && recoded_adler32))) { return ret; } if (!change_apphead) { if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF header indicator", "VCD_APPHEADER", has_apphead))) { return ret; } if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF application header", "encode_apphead", has_apphead))) { return ret; } } else { if ((ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF header indicator", "VCD_APPHEADER", recoded_apphead))) { return ret; } if (recoded_apphead && (ret = check_vcdiff_header (stream, TEST_COPY_FILE, "VCDIFF application header", "recode_apphead", 1))) { return ret; } } /* Now decode */ snprintf_func (dcmd, TESTBUFSIZE, "%s -fd %s %s %s %s ", program_name, has_source ? "-s " : "", has_source ? TEST_SOURCE_FILE : "", TEST_COPY_FILE, TEST_RECON_FILE); if ((ret = system (dcmd)) != 0) { XPR(NT "decode command: %s\n", dcmd); stream->msg = "decode cmd failed"; return XD3_INTERNAL; } /* Now compare. */ if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) { return ret; } return 0; } static int test_recode_command (xd3_stream *stream, int ignore) { /* Things to test: * - with and without a source file (recode does not change) * * (recode may or may not change -- 8 variations) * - with and without adler32 * - with and without app header * - with and without secondary */ int has_source; int variant; int change; int ret; for (has_source = 0; has_source < 2; has_source++) { for (variant = 0; variant < 8; variant++) { for (change = 0; change < 8; change++) { if ((ret = test_recode_command2 (stream, has_source, variant, change))) { return ret; } } DOT (); } } return 0; } #endif /*********************************************************************** EXTERNAL I/O DECOMPRESSION/RECOMPRESSION ***********************************************************************/ #if EXTERNAL_COMPRESSION /* This performs one step of the test_externally_compressed_io * function described below. It builds a pipe containing both Xdelta * and external compression/decompression that should not modify the * data passing through. */ static int test_compressed_pipe (xd3_stream *stream, main_extcomp *ext, char* buf, const char* comp_options, const char* decomp_options, int do_ext_recomp, const char* msg) { int ret; char decomp_buf[TESTBUFSIZE]; if (do_ext_recomp) { snprintf_func (decomp_buf, TESTBUFSIZE, " | %s %s", ext->decomp_cmdname, ext->decomp_options); } else { decomp_buf[0] = 0; } snprintf_func (buf, TESTBUFSIZE, "%s %s < %s | %s %s | %s %s%s > %s", ext->recomp_cmdname, ext->recomp_options, TEST_TARGET_FILE, program_name, comp_options, program_name, decomp_options, decomp_buf, TEST_RECON_FILE); if ((ret = system (buf)) != 0) { stream->msg = msg; return XD3_INTERNAL; } if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) { return XD3_INTERNAL; } DOT (); return 0; } /* We want to test that a pipe such as: * * --> | gzip -cf | xdelta3 -cf | xdelta3 -dcf | gzip -dcf | --> * * is transparent, i.e., does not modify the stream of data. However, * we also want to verify that at the center the data is properly * compressed, i.e., that we do not just have a re-compressed gzip * format, that we have an VCDIFF format. We do this in two steps. * First test the above pipe, then test with suppressed output * recompression (-D). The result should be the original input: * * --> | gzip -cf | xdelta3 -cf | xdelta3 -Ddcf | --> * * Finally we want to test that -D also disables input decompression: * * --> | gzip -cf | xdelta3 -Dcf | xdelta3 -Ddcf | gzip -dcf | --> */ static int test_externally_compressed_io (xd3_stream *stream, int ignore) { usize_t i; int ret; char buf[TESTBUFSIZE]; mt_init (& static_mtrand, 0x9f73f7fc); if ((ret = test_make_inputs (stream, NULL, NULL))) { return ret; } for (i = 0; i < SIZEOF_ARRAY (extcomp_types); i += 1) { main_extcomp *ext = & extcomp_types[i]; /* Test for the existence of the external command first, if not skip. */ snprintf_func (buf, TESTBUFSIZE, "%s %s < /dev/null > /dev/null", ext->recomp_cmdname, ext->recomp_options); if ((ret = system (buf)) != 0) { XPR(NT "%s=0", ext->recomp_cmdname); continue; } if ((ret = test_compressed_pipe (stream, ext, buf, "-cfq", "-dcfq", 1, "compression failed: identity pipe")) || (ret = test_compressed_pipe (stream, ext, buf, "-cfq", "-Rdcfq", 0, "compression failed: without recompression")) || (ret = test_compressed_pipe (stream, ext, buf, "-Dcfq", "-Rdcfq", 1, "compression failed: without decompression"))) { return ret; } } return 0; } /* This tests the proper functioning of external decompression for * source files. The source and target files are identical and * compressed by gzip. Decoding such a delta with recompression * disbaled (-R) should produce the original, uncompressed * source/target file. Then it checks with output recompression * enabled--in this case the output should be a compressed copy of the * original source/target file. Then it checks that encoding with * decompression disabled works--the compressed files are identical * and decoding them should always produce a compressed output, * regardless of -R since the encoded delta file had decompression * disabled.. */ static int test_source_decompression (xd3_stream *stream, int ignore) { int ret; char buf[TESTBUFSIZE]; const main_extcomp *ext; xoff_t dsize; mt_init (& static_mtrand, 0x9f73f7fc); test_setup (); if ((ret = test_make_inputs (stream, NULL, NULL))) { return ret; } /* Use gzip. */ if ((ext = main_get_compressor ("G")) == NULL) { XPR(NT "skipped"); return 0; } /* Save an uncompressed copy. */ if ((ret = test_save_copy (TEST_TARGET_FILE))) { return ret; } /* Compress the source. */ snprintf_func (buf, TESTBUFSIZE, "%s -1 %s < %s > %s", ext->recomp_cmdname, ext->recomp_options, TEST_COPY_FILE, TEST_SOURCE_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Compress the target. */ snprintf_func (buf, TESTBUFSIZE, "%s -9 %s < %s > %s", ext->recomp_cmdname, ext->recomp_options, TEST_COPY_FILE, TEST_TARGET_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Now the two identical files are compressed. Delta-encode the target, * with decompression. */ snprintf_func (buf, TESTBUFSIZE, "%s -e -vfq -s%s %s %s", program_name, TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Check that the compressed file is small (b/c inputs are * identical). */ if ((ret = test_file_size (TEST_DELTA_FILE, & dsize))) { return ret; } /* Deltas for identical files should be very small. */ if (dsize > 200) { XPR(NT "external compression did not happen\n"); stream->msg = "external compression did not happen"; return XD3_INTERNAL; } /* Decode the delta file with recompression disabled, should get an * uncompressed file out. */ snprintf_func (buf, TESTBUFSIZE, "%s -v -dq -R -s%s %s %s", program_name, TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } if ((ret = test_compare_files (TEST_COPY_FILE, TEST_RECON_FILE))) { return ret; } /* Decode the delta file with recompression, should get a compressed file * out. But we can't compare compressed files directly. */ snprintf_func (buf, TESTBUFSIZE, "%s -v -dqf -s%s %s %s", program_name, TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } snprintf_func (buf, TESTBUFSIZE, "%s %s < %s > %s", ext->decomp_cmdname, ext->decomp_options, TEST_RECON_FILE, TEST_RECON2_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } if ((ret = test_compare_files (TEST_COPY_FILE, TEST_RECON2_FILE))) { return ret; } /* Encode with decompression disabled */ snprintf_func (buf, TESTBUFSIZE, "%s -e -D -vfq -s%s %s %s", program_name, TEST_SOURCE_FILE, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Decode the delta file with decompression disabled, should get the * identical compressed file out. */ snprintf_func (buf, TESTBUFSIZE, "%s -d -D -vfq -s%s %s %s", program_name, TEST_SOURCE_FILE, TEST_DELTA_FILE, TEST_RECON_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } if ((ret = test_compare_files (TEST_TARGET_FILE, TEST_RECON_FILE))) { return ret; } test_cleanup(); return 0; } #endif /*********************************************************************** FORCE, STDOUT ***********************************************************************/ /* This tests that output will not overwrite an existing file unless * -f was specified. The test is for encoding (the same code handles * it for decoding). */ static int test_force_behavior (xd3_stream *stream, int ignore) { int ret; char buf[TESTBUFSIZE]; /* Create empty target file */ test_setup (); snprintf_func (buf, TESTBUFSIZE, "cp /dev/null %s", TEST_TARGET_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Encode to delta file */ snprintf_func (buf, TESTBUFSIZE, "%s -e %s %s", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Encode again, should fail. */ snprintf_func (buf, TESTBUFSIZE, "%s -q -e %s %s ", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_fail (stream, buf))) { return ret; } /* Force it, should succeed. */ snprintf_func (buf, TESTBUFSIZE, "%s -f -e %s %s", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } test_cleanup(); return 0; } /* This checks the proper operation of the -c flag. When specified * the default output becomes stdout, otherwise the input must be * provided (encode) or it may be defaulted (decode w/ app header). */ static int test_stdout_behavior (xd3_stream *stream, int ignore) { int ret; char buf[TESTBUFSIZE]; test_setup(); snprintf_func (buf, TESTBUFSIZE, "cp /dev/null %s", TEST_TARGET_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Without -c, encode writes to delta file */ snprintf_func (buf, TESTBUFSIZE, "%s -e %s %s", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* With -c, encode writes to stdout */ snprintf_func (buf, TESTBUFSIZE, "%s -e -c %s > %s", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Without -c, decode writes to target file name, but it fails because the * file exists. */ snprintf_func (buf, TESTBUFSIZE, "%s -q -d %s ", program_name, TEST_DELTA_FILE); if ((ret = do_fail (stream, buf))) { return ret; } /* With -c, decode writes to stdout */ snprintf_func (buf, TESTBUFSIZE, "%s -d -c %s > /dev/null", program_name, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } test_cleanup(); return 0; } /* This tests that the no-output flag (-J) works. */ static int test_no_output (xd3_stream *stream, int ignore) { int ret; char buf[TESTBUFSIZE]; test_setup (); snprintf_func (buf, TESTBUFSIZE, "touch %s && chmod 0000 %s", TEST_NOPERM_FILE, TEST_NOPERM_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } if ((ret = test_make_inputs (stream, NULL, NULL))) { return ret; } /* Try no_output encode w/out unwritable output file */ snprintf_func (buf, TESTBUFSIZE, "%s -q -f -e %s %s", program_name, TEST_TARGET_FILE, TEST_NOPERM_FILE); if ((ret = do_fail (stream, buf))) { return ret; } snprintf_func (buf, TESTBUFSIZE, "%s -J -e %s %s", program_name, TEST_TARGET_FILE, TEST_NOPERM_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } /* Now really write the delta to test decode no-output */ snprintf_func (buf, TESTBUFSIZE, "%s -e %s %s", program_name, TEST_TARGET_FILE, TEST_DELTA_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } snprintf_func (buf, TESTBUFSIZE, "%s -q -f -d %s %s", program_name, TEST_DELTA_FILE, TEST_NOPERM_FILE); if ((ret = do_fail (stream, buf))) { return ret; } snprintf_func (buf, TESTBUFSIZE, "%s -J -d %s %s", program_name, TEST_DELTA_FILE, TEST_NOPERM_FILE); if ((ret = do_cmd (stream, buf))) { return ret; } test_cleanup (); return 0; } /*********************************************************************** Source identical optimization ***********************************************************************/ /* Computing a delta should be fastest when the two inputs are * identical, this checks it. The library is called to compute a * delta between a 10000 byte file, 1000 byte winsize, 500 byte source * blocksize. The same buffer is used for both source and target. */ static int test_identical_behavior (xd3_stream *stream, int ignore) { #define IDB_TGTSZ 10000 /* Not a power of two b/c of hard-coded expectations below. */ #define IDB_BLKSZ 512 #define IDB_WINSZ 1000 #define IDB_DELSZ 1000 #define IDB_WINCNT (IDB_TGTSZ / IDB_WINSZ) int ret, i; uint8_t buf[IDB_TGTSZ]; uint8_t del[IDB_DELSZ]; uint8_t rec[IDB_TGTSZ]; xd3_source source; int nextencwin = 0; int winstarts = 0, winfinishes = 0; usize_t delpos = 0, recsize; xd3_config config; memset(&source, 0, sizeof(source)); for (i = 0; i < IDB_TGTSZ; i += 1) { buf[i] = (uint8_t) mt_random (&static_mtrand); } stream->winsize = IDB_WINSZ; source.blksize = IDB_BLKSZ; source.name = ""; source.curblk = NULL; source.curblkno = 0; if ((ret = xd3_set_source (stream, & source))) { goto fail; } /* Compute an delta between identical source and targets. */ for (;;) { ret = xd3_encode_input (stream); if (ret == XD3_INPUT) { xd3_avail_input (stream, buf + (IDB_WINSZ * nextencwin), IDB_WINSZ); nextencwin += 1; continue; } if (ret == XD3_GETSRCBLK) { source.curblkno = source.getblkno; source.onblk = IDB_BLKSZ; source.curblk = buf + source.getblkno * IDB_BLKSZ; continue; } if (ret == XD3_WINSTART) { winstarts++; continue; } if (ret == XD3_WINFINISH) { winfinishes++; if (winfinishes == IDB_WINCNT) { break; } continue; } if (ret != XD3_OUTPUT) { goto fail; } CHECK(delpos + stream->avail_out <= IDB_DELSZ); memcpy (del + delpos, stream->next_out, stream->avail_out); delpos += stream->avail_out; xd3_consume_output (stream); } CHECK(winfinishes == IDB_WINCNT); CHECK(winstarts == IDB_WINCNT); CHECK(nextencwin == IDB_WINCNT); /* Reset. */ memset(&source, 0, sizeof(source)); source.blksize = IDB_TGTSZ; source.onblk = IDB_TGTSZ; source.curblk = buf; source.curblkno = 0; if ((ret = xd3_close_stream (stream))) { goto fail; } xd3_free_stream (stream); xd3_init_config (& config, 0); if ((ret = xd3_config_stream (stream, & config))) { goto fail; } if ((ret = xd3_set_source_and_size (stream, & source, IDB_TGTSZ))) { goto fail; } /* Decode. */ if ((ret = xd3_decode_stream (stream, del, delpos, rec, & recsize, IDB_TGTSZ))) { goto fail; } /* Check result size and data. */ if (recsize != IDB_TGTSZ) { stream->msg = "wrong size reconstruction"; goto fail; } if (memcmp (rec, buf, IDB_TGTSZ) != 0) { stream->msg = "wrong data reconstruction"; goto fail; } /* Check that there was one copy per window. */ IF_DEBUG (if (stream->n_scpy != IDB_WINCNT || stream->n_add != 0 || stream->n_run != 0) { stream->msg = "wrong copy count"; goto fail; }); /* Check that no checksums were computed because the initial match was presumed. */ IF_DEBUG (if (stream->large_ckcnt != 0) { stream->msg = "wrong checksum behavior"; goto fail; }); ret = 0; fail: return ret; } /*********************************************************************** String matching test ***********************************************************************/ /* Check particular matching behaviors by calling * xd3_string_match_soft directly with specific arguments. */ typedef struct _string_match_test string_match_test; typedef enum { SM_NONE = 0, SM_LAZY = (1 << 1), } string_match_flags; struct _string_match_test { const char *input; int flags; const char *result; }; static const string_match_test match_tests[] = { /* nothing */ { "1234567890", SM_NONE, "" }, /* basic run, copy */ { "11111111112323232323", SM_NONE, "R0/10 C12/8@10" }, /* no run smaller than MIN_RUN=8 */ { "1111111", SM_NONE, "C1/6@0" }, { "11111111", SM_NONE, "R0/8" }, /* simple promotion: the third copy address depends on promotion */ { "ABCDEF_ABCDEF^ABCDEF", SM_NONE, "C7/6@0 C14/6@7" }, /* { "ABCDEF_ABCDEF^ABCDEF", SM_PROMOTE, "C7/6@0 C14/6@0" }, forgotten */ /* simple lazy: there is a better copy starting with "23 X" than "123 " */ { "123 23 XYZ 123 XYZ", SM_NONE, "C11/4@0" }, { "123 23 XYZ 123 XYZ", SM_LAZY, "C11/4@0 C12/6@4" }, /* trylazy: no lazy matches unless there are at least two characters beyond * the first match */ { "2123_121212", SM_LAZY, "C7/4@5" }, { "2123_1212123", SM_LAZY, "C7/4@5" }, { "2123_1212123_", SM_LAZY, "C7/4@5 C8/5@0" }, /* trylazy: no lazy matches if the copy is >= MAXLAZY=10 */ { "2123_121212123_", SM_LAZY, "C7/6@5 C10/5@0" }, { "2123_12121212123_", SM_LAZY, "C7/8@5 C12/5@0" }, { "2123_1212121212123_", SM_LAZY, "C7/10@5" }, /* lazy run: check a run overlapped by a longer copy */ { "11111112 111111112 1", SM_LAZY, "C1/6@0 R9/8 C10/10@0" }, /* lazy match: match_length,run_l >= min_match tests, shouldn't get any * copies within the run, no run within the copy */ { "^________^________ ", SM_LAZY, "R1/8 C9/9@0" }, /* chain depth: it only goes back 10. this checks that the 10th match hits * and the 11th misses. */ { "1234 1234_1234-1234=1234+1234[1234]1234{1234}1234<1234 ", SM_NONE, "C5/4@0 C10/4@5 C15/4@10 C20/4@15 C25/4@20 C30/4@25 C35/4@30 C40/4@35 C45/4@40 C50/5@0" }, { "1234 1234_1234-1234=1234+1234[1234]1234{1234}1234<1234>1234 ", SM_NONE, "C5/4@0 C10/4@5 C15/4@10 C20/4@15 C25/4@20 C30/4@25 C35/4@30 C40/4@35 C45/4@40 C50/4@45 C55/4@50" }, /* ssmatch test */ { "ABCDE___ABCDE*** BCDE***", SM_NONE, "C8/5@0 C17/4@1" }, /*{ "ABCDE___ABCDE*** BCDE***", SM_SSMATCH, "C8/5@0 C17/7@9" }, forgotten */ }; static int test_string_matching (xd3_stream *stream, int ignore) { usize_t i; int ret; xd3_config config; char rbuf[TESTBUFSIZE]; for (i = 0; i < SIZEOF_ARRAY (match_tests); i += 1) { const string_match_test *test = & match_tests[i]; char *rptr = rbuf; usize_t len = (usize_t) strlen (test->input); xd3_free_stream (stream); xd3_init_config (& config, 0); config.smatch_cfg = XD3_SMATCH_SOFT; config.smatcher_soft.large_look = 4; config.smatcher_soft.large_step = 4; config.smatcher_soft.small_look = 4; config.smatcher_soft.small_chain = 10; config.smatcher_soft.small_lchain = 10; config.smatcher_soft.max_lazy = (test->flags & SM_LAZY) ? 10 : 0; config.smatcher_soft.long_enough = 10; if ((ret = xd3_config_stream (stream, & config))) { return ret; } if ((ret = xd3_encode_init_full (stream))) { return ret; } xd3_avail_input (stream, (uint8_t*)test->input, len); if ((ret = stream->smatcher.string_match (stream))) { return ret; } *rptr = 0; while (! xd3_rlist_empty (& stream->iopt_used)) { xd3_rinst *inst = xd3_rlist_pop_front (& stream->iopt_used); switch (inst->type) { case XD3_RUN: *rptr++ = 'R'; break; case XD3_CPY: *rptr++ = 'C'; break; default: CHECK(0); } snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%d/%d", inst->pos, inst->size); rptr += strlen (rptr); if (inst->type == XD3_CPY) { *rptr++ = '@'; snprintf_func (rptr, rbuf+TESTBUFSIZE-rptr, "%"Q"d", inst->addr); rptr += strlen (rptr); } *rptr++ = ' '; xd3_rlist_push_back (& stream->iopt_free, inst); } if (rptr != rbuf) { rptr -= 1; *rptr = 0; } if (strcmp (rbuf, test->result) != 0) { XPR(NT "test %u: expected %s: got %s", i, test->result, rbuf); stream->msg = "wrong result"; return XD3_INTERNAL; } } return 0; } /* * This is a test for many overlapping instructions. It must be a lazy * matcher. */ static int test_iopt_flush_instructions (xd3_stream *stream, int ignore) { int ret, i; usize_t tpos = 0; usize_t delta_size, recon_size; xd3_config config; uint8_t target[TESTBUFSIZE]; uint8_t delta[TESTBUFSIZE]; uint8_t recon[TESTBUFSIZE]; xd3_free_stream (stream); xd3_init_config (& config, 0); config.smatch_cfg = XD3_SMATCH_SOFT; config.smatcher_soft.large_look = 16; config.smatcher_soft.large_step = 16; config.smatcher_soft.small_look = 4; config.smatcher_soft.small_chain = 128; config.smatcher_soft.small_lchain = 16; config.smatcher_soft.max_lazy = 8; config.smatcher_soft.long_enough = 128; if ((ret = xd3_config_stream (stream, & config))) { return ret; } for (i = 1; i < 250; i++) { target[tpos++] = i; target[tpos++] = i+1; target[tpos++] = i+2; target[tpos++] = i+3; target[tpos++] = 0; } for (i = 1; i < 253; i++) { target[tpos++] = i; } if ((ret = xd3_encode_stream (stream, target, tpos, delta, & delta_size, sizeof (delta)))) { return ret; } xd3_free_stream(stream); if ((ret = xd3_config_stream (stream, & config))) { return ret; } if ((ret = xd3_decode_stream (stream, delta, delta_size, recon, & recon_size, sizeof (recon)))) { return ret; } CHECK(tpos == recon_size); CHECK(memcmp(target, recon, recon_size) == 0); return 0; } /* * This tests the 32/64bit ambiguity for source-window matching. */ static int test_source_cksum_offset (xd3_stream *stream, int ignore) { xd3_source source; // Inputs are: struct { xoff_t cpos; // stream->srcwin_cksum_pos; xoff_t ipos; // stream->total_in; xoff_t size; // stream->src->size; usize_t input; // input 32-bit offset xoff_t output; // output 64-bit offset } cksum_test[] = { // If cpos is <= 2^32 { 1, 1, 1, 1, 1 }, #if XD3_USE_LARGEFILE64 // cpos ipos size input output // 0x____xxxxxULL, 0x____xxxxxULL, 0x____xxxxxULL, 0x___xxxxxUL, 0x____xxxxxULL { 0x100100000ULL, 0x100000000ULL, 0x100200000ULL, 0x00000000UL, 0x100000000ULL }, { 0x100100000ULL, 0x100000000ULL, 0x100200000ULL, 0xF0000000UL, 0x0F0000000ULL }, { 0x100200000ULL, 0x100100000ULL, 0x100200000ULL, 0x00300000UL, 0x000300000ULL }, { 25771983104ULL, 25770000000ULL, 26414808769ULL, 2139216707UL, 23614053187ULL }, #endif { 0, 0, 0, 0, 0 }, }, *test_ptr; stream->src = &source; for (test_ptr = cksum_test; test_ptr->cpos; test_ptr++) { xoff_t r; stream->srcwin_cksum_pos = test_ptr->cpos; stream->total_in = test_ptr->ipos; r = xd3_source_cksum_offset(stream, test_ptr->input); CHECK(r == test_ptr->output); } return 0; } static int test_in_memory (xd3_stream *stream, int ignore) { // test_text is 256 bytes uint8_t ibuf[sizeof(test_text)]; uint8_t dbuf[sizeof(test_text)]; uint8_t obuf[sizeof(test_text)]; usize_t size = sizeof(test_text); usize_t dsize, osize; int r1, r2; int eflags = SECONDARY_DJW ? XD3_SEC_DJW : 0; memcpy(ibuf, test_text, size); memset(ibuf + 128, 0, 16); r1 = xd3_encode_memory(ibuf, size, test_text, size, dbuf, &dsize, size, eflags); r2 = xd3_decode_memory(dbuf, dsize, test_text, size, obuf, &osize, size, 0); if (r1 != 0 || r2 != 0 || dsize >= (size/2) || dsize < 1 || osize != size) { stream->msg = "encode/decode size error"; return XD3_INTERNAL; } if (memcmp(obuf, ibuf, size) != 0) { stream->msg = "encode/decode data error"; return XD3_INTERNAL; } return 0; } /*********************************************************************** TEST MAIN ***********************************************************************/ static int xd3_selftest (void) { #define DO_TEST(fn,flags,arg) \ do { \ xd3_stream stream; \ xd3_config config; \ xd3_init_config (& config, flags); \ XPR(NT "testing " #fn "%s...", \ flags ? (" (" #flags ")") : ""); \ if ((ret = xd3_config_stream (& stream, & config) == 0) && \ (ret = test_ ## fn (& stream, arg)) == 0) { \ XPR(NTR " success\n"); \ } else { \ XPR(NTR " failed: %s: %s\n", xd3_errstring (& stream), \ xd3_mainerror (ret)); } \ xd3_free_stream (& stream); \ if (ret != 0) { goto failure; } \ } while (0) int ret; DO_TEST (random_numbers, 0, 0); DO_TEST (decode_integer_end_of_input, 0, 0); DO_TEST (decode_integer_overflow, 0, 0); DO_TEST (encode_decode_uint32_t, 0, 0); DO_TEST (encode_decode_uint64_t, 0, 0); DO_TEST (usize_t_overflow, 0, 0); DO_TEST (forward_match, 0, 0); DO_TEST (address_cache, 0, 0); IF_GENCODETBL (DO_TEST (address_cache, XD3_ALT_CODE_TABLE, 0)); DO_TEST (string_matching, 0, 0); DO_TEST (choose_instruction, 0, 0); DO_TEST (identical_behavior, 0, 0); DO_TEST (in_memory, 0, 0); IF_GENCODETBL (DO_TEST (choose_instruction, XD3_ALT_CODE_TABLE, 0)); IF_GENCODETBL (DO_TEST (encode_code_table, 0, 0)); DO_TEST (iopt_flush_instructions, 0, 0); DO_TEST (source_cksum_offset, 0, 0); DO_TEST (decompress_single_bit_error, 0, 3); DO_TEST (decompress_single_bit_error, XD3_ADLER32, 3); IF_LZMA (DO_TEST (decompress_single_bit_error, XD3_SEC_LZMA, 54)); IF_FGK (DO_TEST (decompress_single_bit_error, XD3_SEC_FGK, 3)); IF_DJW (DO_TEST (decompress_single_bit_error, XD3_SEC_DJW, 8)); /* There are many expected non-failures for ALT_CODE_TABLE because * not all of the instruction codes are used. */ IF_GENCODETBL ( DO_TEST (decompress_single_bit_error, XD3_ALT_CODE_TABLE, 224)); #if SHELL_TESTS DO_TEST (force_behavior, 0, 0); DO_TEST (stdout_behavior, 0, 0); DO_TEST (no_output, 0, 0); DO_TEST (command_line_arguments, 0, 0); #if EXTERNAL_COMPRESSION DO_TEST (source_decompression, 0, 0); DO_TEST (externally_compressed_io, 0, 0); #endif DO_TEST (recode_command, 0, 0); #endif IF_LZMA (DO_TEST (secondary_lzma, 0, 1)); IF_DJW (DO_TEST (secondary_huff, 0, DJW_MAX_GROUPS)); IF_FGK (DO_TEST (secondary_fgk, 0, 1)); DO_TEST (compressed_stream_overflow, 0, 0); IF_LZMA (DO_TEST (compressed_stream_overflow, XD3_SEC_LZMA, 0)); failure: test_cleanup (); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; #undef DO_TEST } xdelta3-3.0.7/xdelta3-lzma.h0000644000176500017650000001067212144343217015032 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2012, 2013. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Note: The use of the _easy_ decoder means we're not calling the * xd3_stream malloc hooks. TODO(jmacd) Fix if anyone cares. */ #ifndef _XDELTA3_LZMA_H_ #define _XDELTA3_LZMA_H_ #include typedef struct _xd3_lzma_stream xd3_lzma_stream; struct _xd3_lzma_stream { lzma_stream lzma; lzma_options_lzma options; lzma_filter filters[2]; }; xd3_sec_stream* xd3_lzma_alloc (xd3_stream *stream) { return (xd3_sec_stream*) xd3_alloc (stream, sizeof (xd3_lzma_stream), 1); } void xd3_lzma_destroy (xd3_stream *stream, xd3_sec_stream *sec_stream) { xd3_lzma_stream *ls = (xd3_lzma_stream*) sec_stream; lzma_end (&ls->lzma); xd3_free (stream, ls); } int xd3_lzma_init (xd3_stream *stream, xd3_lzma_stream *sec, int is_encode) { int ret; memset (&sec->lzma, 0, sizeof(sec->lzma)); if (is_encode) { int preset = (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT; if (lzma_lzma_preset(&sec->options, preset)) { stream->msg = "invalid lzma preset"; return XD3_INVALID; } sec->filters[0].id = LZMA_FILTER_LZMA2; sec->filters[0].options = &sec->options; sec->filters[1].id = LZMA_VLI_UNKNOWN; ret = lzma_stream_encoder (&sec->lzma, &sec->filters[0], LZMA_CHECK_NONE); } else { ret = lzma_stream_decoder (&sec->lzma, UINT64_MAX, LZMA_TELL_NO_CHECK); } if (ret != LZMA_OK) { stream->msg = "lzma stream init failed"; return XD3_INTERNAL; } return 0; } int xd3_decode_lzma (xd3_stream *stream, xd3_lzma_stream *sec, const uint8_t **input_pos, const uint8_t *const input_end, uint8_t **output_pos, const uint8_t *const output_end) { uint8_t *output = *output_pos; const uint8_t *input = *input_pos; size_t avail_in = input_end - input; size_t avail_out = output_end - output; sec->lzma.avail_in = avail_in; sec->lzma.next_in = input; sec->lzma.avail_out = avail_out; sec->lzma.next_out = output; while (1) { int lret = lzma_code (&sec->lzma, LZMA_RUN); switch (lret) { case LZMA_NO_CHECK: case LZMA_OK: if (sec->lzma.avail_out == 0) { (*output_pos) = sec->lzma.next_out; (*input_pos) = sec->lzma.next_in; return 0; } break; default: stream->msg = "lzma decoding error"; return XD3_INTERNAL; } } } #if XD3_ENCODER int xd3_encode_lzma (xd3_stream *stream, xd3_lzma_stream *sec, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg) { lzma_action action = LZMA_RUN; cfg->inefficient = 1; /* Can't skip windows */ sec->lzma.next_in = NULL; sec->lzma.avail_in = 0; sec->lzma.next_out = (output->base + output->next); sec->lzma.avail_out = (output->avail - output->next); while (1) { int lret; if (sec->lzma.avail_in == 0 && input != NULL) { sec->lzma.avail_in = input->next; sec->lzma.next_in = input->base; if ((input = input->next_page) == NULL) { action = LZMA_SYNC_FLUSH; } } lret = lzma_code (&sec->lzma, action); size_t nwrite = (output->avail - output->next) - sec->lzma.avail_out; if (nwrite != 0) { output->next += nwrite; if (output->next == output->avail) { if ((output = xd3_alloc_output (stream, output)) == NULL) { return ENOMEM; } sec->lzma.next_out = output->base; sec->lzma.avail_out = output->avail; } } switch (lret) { case LZMA_OK: break; case LZMA_STREAM_END: return 0; default: stream->msg = "lzma encoding error"; return XD3_INTERNAL; } } return 0; } #endif /* XD3_ENCODER */ #endif /* _XDELTA3_LZMA_H_ */ xdelta3-3.0.7/xdelta3-internal.h0000644000176500017650000001225612143366454015712 0ustar debdevdebdev/* xdelta3 - delta compression tools and library * Copyright (C) 2011, 2012 Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef XDELTA3_INTERNAL_H__ #define XDELTA3_INTERNAL_H__ #include "xdelta3.h" typedef struct _main_file main_file; typedef struct _main_extcomp main_extcomp; void main_buffree (void *ptr); void* main_bufalloc (size_t size); void main_file_init (main_file *xfile); int main_file_close (main_file *xfile); void main_file_cleanup (main_file *xfile); int main_file_isopen (main_file *xfile); int main_file_open (main_file *xfile, const char* name, int mode); int main_file_exists (main_file *xfile); int xd3_whole_append_window (xd3_stream *stream); int xd3_main_cmdline (int argc, char **argv); int main_file_read (main_file *ifile, uint8_t *buf, size_t size, size_t *nread, const char *msg); int main_file_write (main_file *ofile, uint8_t *buf, usize_t size, const char *msg); int test_compare_files (const char* f0, const char* f1); usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno); xoff_t xd3_source_eof(const xd3_source *src); uint32_t xd3_large_cksum_update (uint32_t cksum, const uint8_t *base, usize_t look); int xd3_encode_init_full (xd3_stream *stream); #if PYTHON_MODULE || SWIG_MODULE || NOT_MAIN int xd3_main_cmdline (int argc, char **argv); #endif /* main_file->mode values */ typedef enum { XO_READ = 0, XO_WRITE = 1 } main_file_modes; struct _main_file { #if XD3_STDIO FILE *file; #elif XD3_POSIX int file; #elif XD3_WIN32 HANDLE file; #endif int mode; /* XO_READ and XO_WRITE */ const char *filename; /* File name or /dev/stdin, * /dev/stdout, /dev/stderr. */ char *filename_copy; /* File name or /dev/stdin, * /dev/stdout, /dev/stderr. */ const char *realname; /* File name or /dev/stdin, * /dev/stdout, /dev/stderr. */ const main_extcomp *compressor; /* External compression struct. */ int flags; /* RD_FIRST, RD_NONEXTERNAL, ... */ xoff_t nread; /* for input position */ xoff_t nwrite; /* for output position */ uint8_t *snprintf_buf; /* internal snprintf() use */ int size_known; /* Set by main_set_souze */ xoff_t source_position; /* for avoiding seek in getblk_func */ int seek_failed; /* after seek fails once, try FIFO */ }; /* According to the internet, Windows vsnprintf() differs from most * Unix implementations regarding the terminating 0 when the boundary * condition is met. It doesn't matter here, we don't rely on the * trailing 0. Besides, both Windows and DJGPP vsnprintf return -1 * upon truncation, which isn't C99 compliant. To overcome this, * recent MinGW runtimes provided their own vsnprintf (notice the * absence of the '_' prefix) but they were initially buggy. So, * always use the native '_'-prefixed version with Win32. */ #ifdef _WIN32 #define vsnprintf_func(str,size,fmt,args) \ _vsnprintf_s(str,size,size-1,fmt,args) #define snprintf_func(str,size,fmt,...) \ _snprintf_s(str,size,size-1,fmt,__VA_ARGS__) #else #define vsnprintf_func vsnprintf #define snprintf_func snprintf #endif #define short_sprintf(sb,fmt,...) \ snprintf_func((sb).buf,sizeof((sb).buf),fmt,__VA_ARGS__) /* Type used for short snprintf calls. */ typedef struct { char buf[48]; } shortbuf; /* Prior to SVN 303 this function was only defined in DJGPP and WIN32 * environments and other platforms would use the builtin snprintf() * with an arrangement of macros below. In OS X 10.6, Apply made * snprintf() a macro, which defeated those macros (since snprintf * would be evaluated before its argument macros were expanded, * therefore always define xsnprintf_func. */ #undef PRINTF_ATTRIBUTE #ifdef __GNUC__ /* Let's just assume no one uses gcc 2.x! */ #define PRINTF_ATTRIBUTE(x,y) __attribute__ ((__format__ (__printf__, x, y))) #else #define PRINTF_ATTRIBUTE(x,y) #endif /* Underlying xprintf() */ int xsnprintf_func (char *str, int n, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); /* XPR(NT "", ...) (used by main) prefixes an "xdelta3: " to the output. */ void xprintf(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); #define XPR xprintf #define NT "xdelta3: " #define NTR "" #ifndef UINT32_MAX #define UINT32_MAX 4294967295U #endif #ifndef UINT64_MAX #define UINT64_MAX 18446744073709551615ULL #endif #endif // XDELTA3_INTERNAL_H__ xdelta3-3.0.7/README0000644000176500017650000000205312105354541013225 0ustar debdevdebdevXdelta 3.x readme.txt Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Thanks for downloading Xdelta! This directory contains the Xdelta3 command-line interface (CLI) and source distribution for VCDIFF differential compression, a.k.a. delta compression. The latest information and downloads are available here: http://xdelta.org/ http://code.google.com/p/xdelta/ The command-line syntax: http://code.google.com/p/xdelta/wiki/CommandLineSyntax Run 'xdelta3 -h' for brief help. Run 'xdelta3 test' for built-in tests. Sample commands (like gzip, -e means encode, -d means decode) xdelta3 -9 -S djw -e -vfs OLD_FILE NEW_FILE DELTA_FILE xdelta3 -d -vfs OLD_FILE DELTA_FILE DECODED_FILE File bug reports and browse open support issues here: http://code.google.com/p/xdelta/issues/list The source distribution contains the C/C++/Python APIs, Unix, Microsoft VC++ and Cygwin builds. Xdelta3 is covered under the terms of the GPL, see COPYING. Commercial inquiries welcome, please contact xdelta3-3.0.7/xdelta3-merge.h0000644000176500017650000003265112105354541015166 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XDELTA3_MERGE_H_ #define _XDELTA3_MERGE_H_ int xd3_merge_inputs (xd3_stream *stream, xd3_whole_state *source, xd3_whole_state *input); static int xd3_whole_state_init (xd3_stream *stream) { XD3_ASSERT (stream->whole_target.adds == NULL); XD3_ASSERT (stream->whole_target.inst == NULL); XD3_ASSERT (stream->whole_target.wininfo == NULL); XD3_ASSERT (stream->whole_target.length == 0); stream->whole_target.adds_alloc = XD3_ALLOCSIZE; stream->whole_target.inst_alloc = XD3_ALLOCSIZE; stream->whole_target.wininfo_alloc = XD3_ALLOCSIZE; if ((stream->whole_target.adds = (uint8_t*) xd3_alloc (stream, stream->whole_target.adds_alloc, 1)) == NULL || (stream->whole_target.inst = (xd3_winst*) xd3_alloc (stream, stream->whole_target.inst_alloc, 1)) == NULL || (stream->whole_target.wininfo = (xd3_wininfo*) xd3_alloc (stream, stream->whole_target.wininfo_alloc, 1)) == NULL) { return ENOMEM; } return 0; } static void xd3_swap_whole_state (xd3_whole_state *a, xd3_whole_state *b) { xd3_whole_state tmp; XD3_ASSERT (a->inst != NULL && a->adds != NULL); XD3_ASSERT (b->inst != NULL && b->adds != NULL); XD3_ASSERT (b->wininfo != NULL && b->wininfo != NULL); memcpy (&tmp, a, sizeof (xd3_whole_state)); memcpy (a, b, sizeof (xd3_whole_state)); memcpy (b, &tmp, sizeof (xd3_whole_state)); } static int xd3_realloc_buffer (xd3_stream *stream, usize_t current_units, usize_t unit_size, usize_t new_units, usize_t *alloc_size, void **alloc_ptr) { usize_t needed; usize_t new_alloc; usize_t cur_size; uint8_t *new_buf; needed = (current_units + new_units) * unit_size; if (needed <= *alloc_size) { return 0; } cur_size = current_units * unit_size; new_alloc = xd3_round_blksize (needed * 2, XD3_ALLOCSIZE); if ((new_buf = (uint8_t*) xd3_alloc (stream, new_alloc, 1)) == NULL) { return ENOMEM; } if (cur_size != 0) { memcpy (new_buf, *alloc_ptr, cur_size); } if (*alloc_ptr != NULL) { xd3_free (stream, *alloc_ptr); } *alloc_size = new_alloc; *alloc_ptr = new_buf; return 0; } /* allocate one new output instruction */ static int xd3_whole_alloc_winst (xd3_stream *stream, xd3_winst **winstp) { int ret; if ((ret = xd3_realloc_buffer (stream, stream->whole_target.instlen, sizeof (xd3_winst), 1, & stream->whole_target.inst_alloc, (void**) & stream->whole_target.inst))) { return ret; } *winstp = &stream->whole_target.inst[stream->whole_target.instlen++]; return 0; } static int xd3_whole_alloc_adds (xd3_stream *stream, usize_t count) { return xd3_realloc_buffer (stream, stream->whole_target.addslen, 1, count, & stream->whole_target.adds_alloc, (void**) & stream->whole_target.adds); } static int xd3_whole_alloc_wininfo (xd3_stream *stream, xd3_wininfo **wininfop) { int ret; if ((ret = xd3_realloc_buffer (stream, stream->whole_target.wininfolen, sizeof (xd3_wininfo), 1, & stream->whole_target.wininfo_alloc, (void**) & stream->whole_target.wininfo))) { return ret; } *wininfop = &stream->whole_target.wininfo[stream->whole_target.wininfolen++]; return 0; } static int xd3_whole_append_inst (xd3_stream *stream, xd3_hinst *inst) { int ret; xd3_winst *winst; if ((ret = xd3_whole_alloc_winst (stream, &winst))) { return ret; } winst->type = inst->type; winst->mode = 0; winst->size = inst->size; winst->position = stream->whole_target.length; stream->whole_target.length += inst->size; if (((inst->type == XD3_ADD) || (inst->type == XD3_RUN)) && (ret = xd3_whole_alloc_adds (stream, (inst->type == XD3_RUN ? 1 : inst->size)))) { return ret; } switch (inst->type) { case XD3_RUN: winst->addr = stream->whole_target.addslen; stream->whole_target.adds[stream->whole_target.addslen++] = *stream->data_sect.buf++; break; case XD3_ADD: winst->addr = stream->whole_target.addslen; memcpy (stream->whole_target.adds + stream->whole_target.addslen, stream->data_sect.buf, inst->size); stream->data_sect.buf += inst->size; stream->whole_target.addslen += inst->size; break; default: if (inst->addr < stream->dec_cpylen) { winst->mode = SRCORTGT (stream->dec_win_ind); winst->addr = stream->dec_cpyoff + inst->addr; } else { winst->addr = (stream->dec_winstart + inst->addr - stream->dec_cpylen); } break; } return 0; } int xd3_whole_append_window (xd3_stream *stream) { int ret; xd3_wininfo *wininfo; if ((ret = xd3_whole_alloc_wininfo (stream, &wininfo))) { return ret; } wininfo->length = stream->dec_tgtlen; wininfo->offset = stream->dec_winstart; wininfo->adler32 = stream->dec_adler32; while (stream->inst_sect.buf < stream->inst_sect.buf_max) { if ((ret = xd3_decode_instruction (stream))) { return ret; } if ((stream->dec_current1.type != XD3_NOOP) && (ret = xd3_whole_append_inst (stream, & stream->dec_current1))) { return ret; } if ((stream->dec_current2.type != XD3_NOOP) && (ret = xd3_whole_append_inst (stream, & stream->dec_current2))) { return ret; } } return 0; } /* xd3_merge_input_output applies *source to *stream, returns the * result in stream. */ int xd3_merge_input_output (xd3_stream *stream, xd3_whole_state *source) { int ret; xd3_stream tmp_stream; memset (& tmp_stream, 0, sizeof (tmp_stream)); if ((ret = xd3_config_stream (& tmp_stream, NULL)) || (ret = xd3_whole_state_init (& tmp_stream)) || (ret = xd3_merge_inputs (& tmp_stream, source, & stream->whole_target))) { XPR(NT XD3_LIB_ERRMSG (&tmp_stream, ret)); return ret; } /* the output is in tmp_stream.whole_state, swap into input */ xd3_swap_whole_state (& stream->whole_target, & tmp_stream.whole_target); /* total allocation counts are preserved */ xd3_free_stream (& tmp_stream); return 0; } static int xd3_merge_run (xd3_stream *stream, xd3_whole_state *target, xd3_winst *iinst) { int ret; xd3_winst *oinst; if ((ret = xd3_whole_alloc_winst (stream, &oinst)) || (ret = xd3_whole_alloc_adds (stream, 1))) { return ret; } oinst->type = iinst->type; oinst->mode = iinst->mode; oinst->size = iinst->size; oinst->addr = stream->whole_target.addslen; XD3_ASSERT (stream->whole_target.length == iinst->position); oinst->position = stream->whole_target.length; stream->whole_target.length += iinst->size; stream->whole_target.adds[stream->whole_target.addslen++] = target->adds[iinst->addr]; return 0; } static int xd3_merge_add (xd3_stream *stream, xd3_whole_state *target, xd3_winst *iinst) { int ret; xd3_winst *oinst; if ((ret = xd3_whole_alloc_winst (stream, &oinst)) || (ret = xd3_whole_alloc_adds (stream, iinst->size))) { return ret; } oinst->type = iinst->type; oinst->mode = iinst->mode; oinst->size = iinst->size; oinst->addr = stream->whole_target.addslen; XD3_ASSERT (stream->whole_target.length == iinst->position); oinst->position = stream->whole_target.length; stream->whole_target.length += iinst->size; memcpy(stream->whole_target.adds + stream->whole_target.addslen, target->adds + iinst->addr, iinst->size); stream->whole_target.addslen += iinst->size; return 0; } static int xd3_merge_target_copy (xd3_stream *stream, xd3_winst *iinst) { int ret; xd3_winst *oinst; if ((ret = xd3_whole_alloc_winst (stream, &oinst))) { return ret; } XD3_ASSERT (stream->whole_target.length == iinst->position); memcpy (oinst, iinst, sizeof (*oinst)); return 0; } static int xd3_merge_find_position (xd3_stream *stream, xd3_whole_state *source, xoff_t address, usize_t *inst_num) { usize_t low; usize_t high; if (address >= source->length) { stream->msg = "Invalid copy offset in merge"; return XD3_INVALID_INPUT; } low = 0; high = source->instlen; while (low != high) { xoff_t mid_lpos; xoff_t mid_hpos; usize_t mid = low + (high - low) / 2; mid_lpos = source->inst[mid].position; if (address < mid_lpos) { high = mid; continue; } mid_hpos = mid_lpos + source->inst[mid].size; if (address >= mid_hpos) { low = mid + 1; continue; } *inst_num = mid; return 0; } stream->msg = "Internal error in merge"; return XD3_INTERNAL; } static int xd3_merge_source_copy (xd3_stream *stream, xd3_whole_state *source, const xd3_winst *iinst_orig) { int ret; xd3_winst iinst; usize_t sinst_num; memcpy (& iinst, iinst_orig, sizeof (iinst)); XD3_ASSERT (iinst.mode == VCD_SOURCE); if ((ret = xd3_merge_find_position (stream, source, iinst.addr, &sinst_num))) { return ret; } while (iinst.size > 0) { xd3_winst *sinst; xd3_winst *minst; usize_t sinst_offset; usize_t sinst_left; usize_t this_take; XD3_ASSERT (sinst_num < source->instlen); sinst = &source->inst[sinst_num]; XD3_ASSERT (iinst.addr >= sinst->position); sinst_offset = (usize_t)(iinst.addr - sinst->position); XD3_ASSERT (sinst->size > sinst_offset); sinst_left = sinst->size - sinst_offset; this_take = min (iinst.size, sinst_left); XD3_ASSERT (this_take > 0); if ((ret = xd3_whole_alloc_winst (stream, &minst))) { return ret; } minst->size = this_take; minst->type = sinst->type; minst->position = iinst.position; minst->mode = 0; switch (sinst->type) { case XD3_RUN: if ((ret = xd3_whole_alloc_adds (stream, 1))) { return ret; } minst->addr = stream->whole_target.addslen; stream->whole_target.adds[stream->whole_target.addslen++] = source->adds[sinst->addr]; break; case XD3_ADD: if ((ret = xd3_whole_alloc_adds (stream, this_take))) { return ret; } minst->addr = stream->whole_target.addslen; memcpy(stream->whole_target.adds + stream->whole_target.addslen, source->adds + sinst->addr + sinst_offset, this_take); stream->whole_target.addslen += this_take; break; default: if (sinst->mode != 0) { minst->mode = sinst->mode; minst->addr = sinst->addr + sinst_offset; } else { // TODO: this is slow because of the recursion, which // could reach a depth equal to the number of target // copies, and this is compression-inefficient because // it can produce duplicate adds. xd3_winst tinst; tinst.type = XD3_CPY; tinst.mode = iinst.mode; tinst.addr = sinst->addr + sinst_offset; tinst.size = this_take; tinst.position = iinst.position; // The instruction allocated in this frame will not be used. stream->whole_target.instlen -= 1; if ((ret = xd3_merge_source_copy (stream, source, &tinst))) { return ret; } } break; } iinst.position += this_take; iinst.addr += this_take; iinst.size -= this_take; sinst_num += 1; } return 0; } /* xd3_merge_inputs() applies *input to *source, returns its result in * stream. */ int xd3_merge_inputs (xd3_stream *stream, xd3_whole_state *source, xd3_whole_state *input) { int ret = 0; usize_t i; size_t input_i; for (i = 0; i < input->wininfolen; ++i) { xd3_wininfo *copyinfo; if ((ret = xd3_whole_alloc_wininfo (stream, ©info))) { return ret; } *copyinfo = input->wininfo[i]; } /* iterate over each instruction. */ for (input_i = 0; ret == 0 && input_i < input->instlen; ++input_i) { xd3_winst *iinst = &input->inst[input_i]; switch (iinst->type) { case XD3_RUN: ret = xd3_merge_run (stream, input, iinst); break; case XD3_ADD: ret = xd3_merge_add (stream, input, iinst); break; default: /* TODO: VCD_TARGET support is completely untested all * throughout. */ if (iinst->mode == 0 || iinst->mode == VCD_TARGET) { ret = xd3_merge_target_copy (stream, iinst); } else { ret = xd3_merge_source_copy (stream, source, iinst); } /* The whole_target.length is not updated in the xd3_merge*copy * routine because of recursion in xd3_merge_source_copy. */ stream->whole_target.length += iinst->size; break; } } return ret; } #endif xdelta3-3.0.7/xdelta3-cfgs.h0000644000176500017650000001017612105354541015007 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /****************************************************************** SOFT string matcher ******************************************************************/ #if XD3_BUILD_SOFT #define TEMPLATE soft #define LLOOK stream->smatcher.large_look #define LSTEP stream->smatcher.large_step #define SLOOK stream->smatcher.small_look #define SCHAIN stream->smatcher.small_chain #define SLCHAIN stream->smatcher.small_lchain #define MAXLAZY stream->smatcher.max_lazy #define LONGENOUGH stream->smatcher.long_enough #define SOFTCFG 1 #include "xdelta3.c" #undef SOFTCFG #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif #define SOFTCFG 0 /************************************************************ FASTEST string matcher **********************************************************/ #if XD3_BUILD_FASTEST #define TEMPLATE fastest #define LLOOK 9 #define LSTEP 26 #define SLOOK 4U #define SCHAIN 1 #define SLCHAIN 1 #define MAXLAZY 6 #define LONGENOUGH 6 #include "xdelta3.c" #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif /************************************************************ FASTER string matcher **********************************************************/ #if XD3_BUILD_FASTER #define TEMPLATE faster #define LLOOK 9 #define LSTEP 15 #define SLOOK 4U #define SCHAIN 1 #define SLCHAIN 1 #define MAXLAZY 18 #define LONGENOUGH 18 #include "xdelta3.c" #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif /****************************************************** FAST string matcher ********************************************************/ #if XD3_BUILD_FAST #define TEMPLATE fast #define LLOOK 9 #define LSTEP 8 #define SLOOK 4U #define SCHAIN 4 #define SLCHAIN 1 #define MAXLAZY 18 #define LONGENOUGH 35 #include "xdelta3.c" #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif /************************************************** SLOW string matcher **************************************************************/ #if XD3_BUILD_SLOW #define TEMPLATE slow #define LLOOK 9 #define LSTEP 2 #define SLOOK 4U #define SCHAIN 44 #define SLCHAIN 13 #define MAXLAZY 90 #define LONGENOUGH 70 #include "xdelta3.c" #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif /******************************************************** DEFAULT string matcher ************************************************************/ #if XD3_BUILD_DEFAULT #define TEMPLATE default #define LLOOK 9 #define LSTEP 3 #define SLOOK 4U #define SCHAIN 8 #define SLCHAIN 2 #define MAXLAZY 36 #define LONGENOUGH 70 #include "xdelta3.c" #undef TEMPLATE #undef LLOOK #undef SLOOK #undef LSTEP #undef SCHAIN #undef SLCHAIN #undef MAXLAZY #undef LONGENOUGH #endif xdelta3-3.0.7/xdelta3.c0000644000176500017650000047053412144342750014074 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010, 2011, 2012, 2013. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------- Xdelta 3 The goal of this library is to to implement both the (stand-alone) data-compression and delta-compression aspects of VCDIFF encoding, and to support a programming interface that works like Zlib (http://www.gzip.org/zlib.html). See RFC3284: The VCDIFF Generic Differencing and Compression Data Format. VCDIFF is a unified encoding that combines data-compression and delta-encoding ("differencing"). VCDIFF has a detailed byte-code instruction set with many features. The instruction format supports an immediate size operand for small COPYs and ADDs (e.g., under 18 bytes). There are also instruction "modes", which are used to compress COPY addresses by using two address caches. An instruction mode refers to slots in the NEAR and SAME caches for recent addresses. NEAR remembers the previous 4 (by default) COPY addresses, and SAME catches frequent re-uses of the same address using a 3-way (by default) 256-entry associative cache of [ADDR mod 256], the encoded byte. A hit in the NEAR/SAME cache requires 0/1 ADDR bytes. VCDIFF has a default instruction table, but an alternate instruction tables may themselves be be delta-compressed and included in the encoding header. This allows even more freedom. There are 9 instruction modes in the default code table, 4 near, 3 same, VCD_SELF (absolute encoding) and VCD_HERE (relative to the current position). ---------------------------------------------------------------------- Algorithms Aside from the details of encoding and decoding, there are a bunch of algorithms needed. 1. STRING-MATCH. A two-level fingerprinting approach is used. A single loop computes the two checksums -- small and large -- at successive offsets in the TARGET file. The large checksum is more accurate and is used to discover SOURCE matches, which are potentially very long. The small checksum is used to discover copies within the TARGET. Small matching, which is more expensive, usually dominates the large STRING-MATCH costs in this code - the more exhaustive the search, the better the results. Either of the two string-matching mechanisms may be disabled. 2. INSTRUCTION SELECTION. The IOPT buffer here represents a queue used to store overlapping copy instructions. There are two possible optimizations that go beyond a greedy search. Both of these fall into the category of "non-greedy matching" optimizations. The first optimization stems from backward SOURCE-COPY matching. When a new SOURCE-COPY instruction covers a previous instruction in the target completely, it is erased from the queue. Randal Burns originally analyzed these algorithms and did a lot of related work (\cite the 1.5-pass algorithm). The second optimization comes by the encoding of common very-small COPY and ADD instructions, for which there are special DOUBLE-code instructions, which code two instructions in a single byte. The cost of bad instruction-selection overhead is relatively high for data-compression, relative to delta-compression, so this second optimization is fairly important. With "lazy" matching (the name used in Zlib for a similar optimization), the string-match algorithm searches after a match for potential overlapping copy instructions. In Xdelta and by default, VCDIFF, the minimum match size is 4 bytes, whereas Zlib searches with a 3-byte minimum. This feature, combined with double instructions, provides a nice challenge. Search in this file for "black magic", a heuristic. 3. STREAM ALIGNMENT. Stream alignment is needed to compress large inputs in constant space. See xd3_srcwin_move_point(). 4. WINDOW SELECTION. When the IOPT buffer flushes, in the first call to xd3_iopt_finish_encoding containing any kind of copy instruction, the parameters of the source window must be decided: the offset into the source and the length of the window. Since the IOPT buffer is finite, the program may be forced to fix these values before knowing the best offset/length. 5. SECONDARY COMPRESSION. VCDIFF supports a secondary encoding to be applied to the individual sections of the data format, which are ADDRess, INSTruction, and DATA. Several secondary compressor variations are implemented here, although none is standardized yet. One is an adaptive huffman algorithm -- the FGK algorithm (Faller, Gallager, and Knuth, 1985). This compressor is extremely slow. The other is a simple static Huffman routine, which is the base case of a semi-adaptive scheme published by D.J. Wheeler and first widely used in bzip2 (by Julian Seward). This is a very interesting algorithm, originally published in nearly cryptic form by D.J. Wheeler. !!!NOTE!!! Because these are not standardized, secondary compression remains off by default. ftp://ftp.cl.cam.ac.uk/users/djw3/bred3.{c,ps} -------------------------------------------------------------------- Other Features 1. USER CONVENIENCE For user convenience, it is essential to recognize Gzip-compressed files and automatically Gzip-decompress them prior to delta-compression (or else no delta-compression will be achieved unless the user manually decompresses the inputs). The compressed represention competes with Xdelta, and this must be hidden from the command-line user interface. The Xdelta-1.x encoding was simple, not compressed itself, so Xdelta-1.x uses Zlib internally to compress the representation. This implementation supports external compression, which implements the necessary fork() and pipe() mechanics. There is a tricky step involved to support automatic detection of a compressed input in a non-seekable input. First you read a bit of the input to detect magic headers. When a compressed format is recognized, exec() the external compression program and create a second child process to copy the original input stream. [Footnote: There is a difficulty related to using Gzip externally. It is not possible to decompress and recompress a Gzip file transparently. If FILE.GZ had a cryptographic signature, then, after: (1) Gzip-decompression, (2) Xdelta-encoding, (3) Gzip-compression the signature could be broken. The only way to solve this problem is to guess at Gzip's compression level or control it by other means. I recommend that specific implementations of any compression scheme store information needed to exactly re-compress the input, that way external compression is transparent - however, this won't happen here until it has stabilized.] 2. APPLICATION-HEADER This feature was introduced in RFC3284. It allows any application to include a header within the VCDIFF file format. This allows general inter-application data exchange with support for application-specific extensions to communicate metadata. 3. VCDIFF CHECKSUM An optional checksum value is included with each window, which can be used to validate the final result. This verifies the correct source file was used for decompression as well as the obvious advantage: checking the implementation (and underlying) correctness. 4. LIGHT WEIGHT The code makes efforts to avoid copying data more than necessary. The code delays many initialization tasks until the first use, it optimizes for identical (perfectly matching) inputs. It does not compute any checksums until the first lookup misses. Memory usage is reduced. String-matching is templatized (by slightly gross use of CPP) to hard-code alternative compile-time defaults. The code has few outside dependencies. ---------------------------------------------------------------------- The default rfc3284 instruction table: (see RFC for the explanation) TYPE SIZE MODE TYPE SIZE MODE INDEX -------------------------------------------------------------------- 1. Run 0 0 Noop 0 0 0 2. Add 0, [1,17] 0 Noop 0 0 [1,18] 3. Copy 0, [4,18] 0 Noop 0 0 [19,34] 4. Copy 0, [4,18] 1 Noop 0 0 [35,50] 5. Copy 0, [4,18] 2 Noop 0 0 [51,66] 6. Copy 0, [4,18] 3 Noop 0 0 [67,82] 7. Copy 0, [4,18] 4 Noop 0 0 [83,98] 8. Copy 0, [4,18] 5 Noop 0 0 [99,114] 9. Copy 0, [4,18] 6 Noop 0 0 [115,130] 10. Copy 0, [4,18] 7 Noop 0 0 [131,146] 11. Copy 0, [4,18] 8 Noop 0 0 [147,162] 12. Add [1,4] 0 Copy [4,6] 0 [163,174] 13. Add [1,4] 0 Copy [4,6] 1 [175,186] 14. Add [1,4] 0 Copy [4,6] 2 [187,198] 15. Add [1,4] 0 Copy [4,6] 3 [199,210] 16. Add [1,4] 0 Copy [4,6] 4 [211,222] 17. Add [1,4] 0 Copy [4,6] 5 [223,234] 18. Add [1,4] 0 Copy 4 6 [235,238] 19. Add [1,4] 0 Copy 4 7 [239,242] 20. Add [1,4] 0 Copy 4 8 [243,246] 21. Copy 4 [0,8] Add 1 0 [247,255] -------------------------------------------------------------------- Reading the source: Overview This file includes itself in several passes to macro-expand certain sections with variable forms. Just read ahead, there's only a little confusion. I know this sounds ugly, but hard-coding some of the string-matching parameters results in a 10-15% increase in string-match performance. The only time this hurts is when you have unbalanced #if/endifs. A single compilation unit tames the Makefile. In short, this is to allow the above-described hack without an explodingMakefile. The single compilation unit includes the core library features, configurable string-match templates, optional main() command-line tool, misc optional features, and a regression test. Features are controled with CPP #defines, see Makefile.am. The initial __XDELTA3_C_HEADER_PASS__ starts first, the _INLINE_ and _TEMPLATE_ sections follow. Easy stuff first, hard stuff last. Optional features include: xdelta3-main.h The command-line interface, external compression support, POSIX-specific, info & VCDIFF-debug tools. xdelta3-second.h The common secondary compression routines. xdelta3-decoder.h All decoding routines. xdelta3-djw.h The semi-adaptive huffman secondary encoder. xdelta3-fgk.h The adaptive huffman secondary encoder. xdelta3-test.h The unit test covers major algorithms, encoding and decoding. There are single-bit error decoding tests. There are 32/64-bit file size boundary tests. There are command-line tests. There are compression tests. There are external compression tests. There are string-matching tests. There should be more tests... Additional headers include: xdelta3.h The public header file. xdelta3-cfgs.h The default settings for default, built-in encoders. These are hard-coded at compile-time. There is also a single soft-coded string matcher for experimenting with arbitrary values. xdelta3-list.h A cyclic list template Misc little debug utilities: badcopy.c Randomly modifies an input file based on two parameters: (1) the probability that a byte in the file is replaced with a pseudo-random value, and (2) the mean change size. Changes are generated using an expoential distribution which approximates the expected error_prob distribution. -------------------------------------------------------------------- This file itself is unusually large. I hope to defend this layout with lots of comments. Everything in this file is related to encoding and decoding. I like it all together - the template stuff is just a hack. */ #ifndef __XDELTA3_C_HEADER_PASS__ #define __XDELTA3_C_HEADER_PASS__ #include "xdelta3.h" /*********************************************************************** STATIC CONFIGURATION ***********************************************************************/ #ifndef XD3_MAIN /* the main application */ #define XD3_MAIN 0 #endif #ifndef VCDIFF_TOOLS #define VCDIFF_TOOLS XD3_MAIN #endif #ifndef SECONDARY_FGK /* one from the algorithm preservation department: */ #define SECONDARY_FGK 0 /* adaptive Huffman routines */ #endif #ifndef SECONDARY_DJW /* semi-adaptive/static Huffman for the eventual */ #define SECONDARY_DJW 0 /* standardization, off by default until such time. */ #endif #ifndef SECONDARY_LZMA #ifdef HAVE_LZMA_H #define SECONDARY_LZMA 1 #else #define SECONDARY_LZMA 0 #endif #endif #ifndef GENERIC_ENCODE_TABLES /* These three are the RFC-spec app-specific */ #define GENERIC_ENCODE_TABLES 0 /* code features. This is tested but not */ #endif /* recommended unless there's a real use. */ #ifndef GENERIC_ENCODE_TABLES_COMPUTE #define GENERIC_ENCODE_TABLES_COMPUTE 0 #endif #ifndef GENERIC_ENCODE_TABLES_COMPUTE_PRINT #define GENERIC_ENCODE_TABLES_COMPUTE_PRINT 0 #endif #if XD3_ENCODER #define IF_ENCODER(x) x #else #define IF_ENCODER(x) #endif /***********************************************************************/ /* header indicator bits */ #define VCD_SECONDARY (1U << 0) /* uses secondary compressor */ #define VCD_CODETABLE (1U << 1) /* supplies code table data */ #define VCD_APPHEADER (1U << 2) /* supplies application data */ #define VCD_INVHDR (~0x7U) /* window indicator bits */ #define VCD_SOURCE (1U << 0) /* copy window in source file */ #define VCD_TARGET (1U << 1) /* copy window in target file */ #define VCD_ADLER32 (1U << 2) /* has adler32 checksum */ #define VCD_INVWIN (~0x7U) #define VCD_SRCORTGT (VCD_SOURCE | VCD_TARGET) /* delta indicator bits */ #define VCD_DATACOMP (1U << 0) #define VCD_INSTCOMP (1U << 1) #define VCD_ADDRCOMP (1U << 2) #define VCD_INVDEL (~0x7U) typedef enum { VCD_DJW_ID = 1, VCD_LZMA_ID = 2, VCD_FGK_ID = 16 /* Note: these are not standard IANA-allocated IDs! */ } xd3_secondary_ids; typedef enum { SEC_NOFLAGS = 0, /* Note: SEC_COUNT_FREQS Not implemented (to eliminate 1st Huffman pass) */ SEC_COUNT_FREQS = (1 << 0) } xd3_secondary_flags; typedef enum { DATA_SECTION, /* These indicate which section to the secondary * compressor. */ INST_SECTION, /* The header section is not compressed, therefore not * listed here. */ ADDR_SECTION } xd3_section_type; typedef unsigned int xd3_rtype; /***********************************************************************/ #include "xdelta3-list.h" XD3_MAKELIST(xd3_rlist, xd3_rinst, link); /***********************************************************************/ #define SECONDARY_MIN_SAVINGS 2 /* Secondary compression has to save at least this many bytes. */ #define SECONDARY_MIN_INPUT 10 /* Secondary compression needs at least this many bytes. */ #define VCDIFF_MAGIC1 0xd6 /* 1st file byte */ #define VCDIFF_MAGIC2 0xc3 /* 2nd file byte */ #define VCDIFF_MAGIC3 0xc4 /* 3rd file byte */ #define VCDIFF_VERSION 0x00 /* 4th file byte */ #define VCD_SELF 0 /* 1st address mode */ #define VCD_HERE 1 /* 2nd address mode */ #define CODE_TABLE_STRING_SIZE (6 * 256) /* Should fit a code table string. */ #define CODE_TABLE_VCDIFF_SIZE (6 * 256) /* Should fit a compressed code * table string */ #define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK || SECONDARY_LZMA) #define ALPHABET_SIZE 256 /* Used in test code--size of the secondary * compressor alphabet. */ #define HASH_PERMUTE 1 /* The input is permuted by random nums */ #define ADLER_LARGE_CKSUM 1 /* Adler checksum vs. RK checksum */ #define HASH_CKOFFSET 1U /* Table entries distinguish "no-entry" from * offset 0 using this offset. */ #define MIN_SMALL_LOOK 2U /* Match-optimization stuff. */ #define MIN_LARGE_LOOK 2U #define MIN_MATCH_OFFSET 1U #define MAX_MATCH_SPLIT 18U /* VCDIFF code table: 18 is the default limit * for direct-coded ADD sizes */ #define LEAST_MATCH_INCR 0 /* The least number of bytes an overlapping * match must beat the preceding match by. This * is a bias for the lazy match optimization. A * non-zero value means that an adjacent match * has to be better by more than the step * between them. 0. */ #define MIN_MATCH 4U /* VCDIFF code table: MIN_MATCH=4 */ #define MIN_ADD 1U /* 1 */ #define MIN_RUN 8U /* The shortest run, if it is shorter than this * an immediate add/copy will be just as good. * ADD1/COPY6 = 1I+1D+1A bytes, RUN18 = * 1I+1D+1A. */ #define MAX_MODES 9 /* Maximum number of nodes used for * compression--does not limit decompression. */ #define ENC_SECTS 4 /* Number of separate output sections. */ #define HDR_TAIL(s) ((s)->enc_tails[0]) #define DATA_TAIL(s) ((s)->enc_tails[1]) #define INST_TAIL(s) ((s)->enc_tails[2]) #define ADDR_TAIL(s) ((s)->enc_tails[3]) #define HDR_HEAD(s) ((s)->enc_heads[0]) #define DATA_HEAD(s) ((s)->enc_heads[1]) #define INST_HEAD(s) ((s)->enc_heads[2]) #define ADDR_HEAD(s) ((s)->enc_heads[3]) #define TOTAL_MODES(x) (2+(x)->acache.s_same+(x)->acache.s_near) /* Template instances. */ #if XD3_BUILD_SLOW #define IF_BUILD_SLOW(x) x #else #define IF_BUILD_SLOW(x) #endif #if XD3_BUILD_FAST #define IF_BUILD_FAST(x) x #else #define IF_BUILD_FAST(x) #endif #if XD3_BUILD_FASTER #define IF_BUILD_FASTER(x) x #else #define IF_BUILD_FASTER(x) #endif #if XD3_BUILD_FASTEST #define IF_BUILD_FASTEST(x) x #else #define IF_BUILD_FASTEST(x) #endif #if XD3_BUILD_SOFT #define IF_BUILD_SOFT(x) x #else #define IF_BUILD_SOFT(x) #endif #if XD3_BUILD_DEFAULT #define IF_BUILD_DEFAULT(x) x #else #define IF_BUILD_DEFAULT(x) #endif /* Consume N bytes of input, only used by the decoder. */ #define DECODE_INPUT(n) \ do { \ stream->total_in += (xoff_t) (n); \ stream->avail_in -= (n); \ stream->next_in += (n); \ } while (0) /* Update the run-length state */ #define NEXTRUN(c) do { if ((c) == run_c) { run_l += 1; } \ else { run_c = (c); run_l = 1; } } while (0) /* This CPP-conditional stuff can be cleaned up... */ #if REGRESSION_TEST #define IF_REGRESSION(x) x #else #define IF_REGRESSION(x) #endif /***********************************************************************/ #if XD3_ENCODER static void* xd3_alloc0 (xd3_stream *stream, usize_t elts, usize_t size); static xd3_output* xd3_alloc_output (xd3_stream *stream, xd3_output *old_output); static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts); static void xd3_free_output (xd3_stream *stream, xd3_output *output); static int xd3_emit_byte (xd3_stream *stream, xd3_output **outputp, uint8_t code); static int xd3_emit_bytes (xd3_stream *stream, xd3_output **outputp, const uint8_t *base, usize_t size); static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_rinst *second, usize_t code); static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, usize_t code); static usize_t xd3_sizeof_output (xd3_output *output); static void xd3_encode_reset (xd3_stream *stream); static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos); static int xd3_source_extend_match (xd3_stream *stream); static int xd3_srcwin_setup (xd3_stream *stream); static usize_t xd3_iopt_last_matched (xd3_stream *stream); static int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, uint32_t num); static usize_t xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_offset); static int xd3_string_match_init (xd3_stream *stream); static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg, const usize_t ln); static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp); static int xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point); static int xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c); static usize_t xd3_checksum_hash (const xd3_hash_cfg *cfg, const usize_t cksum); static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low); static void xd3_scksum_insert (xd3_stream *stream, usize_t inx, usize_t scksum, usize_t pos); #if XD3_DEBUG static void xd3_verify_run_state (xd3_stream *stream, const uint8_t *inp, usize_t x_run_l, uint8_t *x_run_c); static void xd3_verify_large_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum); static void xd3_verify_small_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum); #endif /* XD3_DEBUG */ #endif /* XD3_ENCODER */ static int xd3_decode_allocate (xd3_stream *stream, usize_t size, uint8_t **copied1, usize_t *alloc1); static void xd3_compute_code_table_string (const xd3_dinst *code_table, uint8_t *str); static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size); static void xd3_free (xd3_stream *stream, void *ptr); static int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint32_t *valp); #if REGRESSION_TEST static int xd3_selftest (void); #endif /***********************************************************************/ #define UINT32_OFLOW_MASK 0xfe000000U #define UINT64_OFLOW_MASK 0xfe00000000000000ULL #if SIZEOF_USIZE_T == 4 #define USIZE_T_MAX UINT32_MAX #define xd3_decode_size xd3_decode_uint32_t #define xd3_emit_size xd3_emit_uint32_t #define xd3_sizeof_size xd3_sizeof_uint32_t #define xd3_read_size xd3_read_uint32_t #elif SIZEOF_USIZE_T == 8 #define USIZE_T_MAX UINT64_MAX #define xd3_decode_size xd3_decode_uint64_t #define xd3_emit_size xd3_emit_uint64_t #define xd3_sizeof_size xd3_sizeof_uint64_t #define xd3_read_size xd3_read_uint64_t #endif #if SIZEOF_XOFF_T == 4 #define XOFF_T_MAX UINT32_MAX #define xd3_decode_offset xd3_decode_uint32_t #define xd3_emit_offset xd3_emit_uint32_t #elif SIZEOF_XOFF_T == 8 #define XOFF_T_MAX UINT64_MAX #define xd3_decode_offset xd3_decode_uint64_t #define xd3_emit_offset xd3_emit_uint64_t #endif #define USIZE_T_OVERFLOW(a,b) ((USIZE_T_MAX - (usize_t) (a)) < (usize_t) (b)) #define XOFF_T_OVERFLOW(a,b) ((XOFF_T_MAX - (xoff_t) (a)) < (xoff_t) (b)) const char* xd3_strerror (int ret) { switch (ret) { case XD3_INPUT: return "XD3_INPUT"; case XD3_OUTPUT: return "XD3_OUTPUT"; case XD3_GETSRCBLK: return "XD3_GETSRCBLK"; case XD3_GOTHEADER: return "XD3_GOTHEADER"; case XD3_WINSTART: return "XD3_WINSTART"; case XD3_WINFINISH: return "XD3_WINFINISH"; case XD3_TOOFARBACK: return "XD3_TOOFARBACK"; case XD3_INTERNAL: return "XD3_INTERNAL"; case XD3_INVALID: return "XD3_INVALID"; case XD3_INVALID_INPUT: return "XD3_INVALID_INPUT"; case XD3_NOSECOND: return "XD3_NOSECOND"; case XD3_UNIMPLEMENTED: return "XD3_UNIMPLEMENTED"; } return NULL; } /***********************************************************************/ #define xd3_sec_data(s) ((s)->sec_stream_d) #define xd3_sec_inst(s) ((s)->sec_stream_i) #define xd3_sec_addr(s) ((s)->sec_stream_a) struct _xd3_sec_type { int id; const char *name; xd3_secondary_flags flags; /* xd3_sec_stream is opaque to the generic code */ xd3_sec_stream* (*alloc) (xd3_stream *stream); void (*destroy) (xd3_stream *stream, xd3_sec_stream *sec); int (*init) (xd3_stream *stream, xd3_sec_stream *sec_stream, int is_encode); int (*decode) (xd3_stream *stream, xd3_sec_stream *sec_stream, const uint8_t **input, const uint8_t *input_end, uint8_t **output, const uint8_t *output_end); #if XD3_ENCODER int (*encode) (xd3_stream *stream, xd3_sec_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg); #endif }; #define BIT_STATE_ENCODE_INIT { 0, 1 } #define BIT_STATE_DECODE_INIT { 0, 0x100 } typedef struct _bit_state bit_state; struct _bit_state { usize_t cur_byte; usize_t cur_mask; }; #if SECONDARY_ANY == 0 #define IF_SEC(x) #define IF_NSEC(x) x #else /* yuck */ #define IF_SEC(x) x #define IF_NSEC(x) static int xd3_decode_secondary (xd3_stream *stream, xd3_desect *sect, xd3_sec_stream **sec_streamp); #if XD3_ENCODER static int xd3_encode_secondary (xd3_stream *stream, xd3_output **head, xd3_output **tail, xd3_sec_stream **sec_streamp, xd3_sec_cfg *cfg, int *did_it); #endif #endif /* SECONDARY_ANY */ #if SECONDARY_FGK extern const xd3_sec_type fgk_sec_type; #define IF_FGK(x) x #define FGK_CASE(s) \ s->sec_type = & fgk_sec_type; \ break; #else #define IF_FGK(x) #define FGK_CASE(s) \ s->msg = "unavailable secondary compressor: FGK Adaptive Huffman"; \ return XD3_INTERNAL; #endif #if SECONDARY_DJW extern const xd3_sec_type djw_sec_type; #define IF_DJW(x) x #define DJW_CASE(s) \ s->sec_type = & djw_sec_type; \ break; #else #define IF_DJW(x) #define DJW_CASE(s) \ s->msg = "unavailable secondary compressor: DJW Static Huffman"; \ return XD3_INTERNAL; #endif #if SECONDARY_LZMA extern const xd3_sec_type lzma_sec_type; #define IF_LZMA(x) x #define LZMA_CASE(s) \ s->sec_type = & lzma_sec_type; \ break; #else #define IF_LZMA(x) #define LZMA_CASE(s) \ s->msg = "unavailable secondary compressor: LZMA"; \ return XD3_INTERNAL; #endif /***********************************************************************/ #include "xdelta3-hash.h" /* Process template passes - this includes xdelta3.c several times. */ #define __XDELTA3_C_TEMPLATE_PASS__ #include "xdelta3-cfgs.h" #undef __XDELTA3_C_TEMPLATE_PASS__ /* Process the inline pass. */ #define __XDELTA3_C_INLINE_PASS__ #include "xdelta3.c" #undef __XDELTA3_C_INLINE_PASS__ /* Secondary compression */ #if SECONDARY_ANY #include "xdelta3-second.h" #endif #if SECONDARY_FGK #include "xdelta3-fgk.h" const xd3_sec_type fgk_sec_type = { VCD_FGK_ID, "FGK Adaptive Huffman", SEC_NOFLAGS, (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc, (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy, (int (*)(xd3_stream*, xd3_sec_stream*, int)) fgk_init, (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, uint8_t**, const uint8_t*)) xd3_decode_fgk, IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, xd3_output*, xd3_sec_cfg*)) xd3_encode_fgk) }; #endif #if SECONDARY_DJW #include "xdelta3-djw.h" const xd3_sec_type djw_sec_type = { VCD_DJW_ID, "Static Huffman", SEC_COUNT_FREQS, (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc, (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy, (int (*)(xd3_stream*, xd3_sec_stream*, int)) djw_init, (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, uint8_t**, const uint8_t*)) xd3_decode_huff, IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, xd3_output*, xd3_sec_cfg*)) xd3_encode_huff) }; #endif #if SECONDARY_LZMA #include "xdelta3-lzma.h" const xd3_sec_type lzma_sec_type = { VCD_LZMA_ID, "lzma", SEC_NOFLAGS, (xd3_sec_stream* (*)(xd3_stream*)) xd3_lzma_alloc, (void (*)(xd3_stream*, xd3_sec_stream*)) xd3_lzma_destroy, (int (*)(xd3_stream*, xd3_sec_stream*, int)) xd3_lzma_init, (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, uint8_t**, const uint8_t*)) xd3_decode_lzma, IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, xd3_output*, xd3_sec_cfg*)) xd3_encode_lzma) }; #endif #if XD3_MAIN || PYTHON_MODULE || SWIG_MODULE || NOT_MAIN #include "xdelta3-main.h" #endif #if REGRESSION_TEST #include "xdelta3-test.h" #endif #endif /* __XDELTA3_C_HEADER_PASS__ */ #ifdef __XDELTA3_C_INLINE_PASS__ const uint16_t __single_hash[256] = { /* Random numbers generated using SLIB's pseudo-random number generator. * This hashes the input alphabet. */ 0xbcd1, 0xbb65, 0x42c2, 0xdffe, 0x9666, 0x431b, 0x8504, 0xeb46, 0x6379, 0xd460, 0xcf14, 0x53cf, 0xdb51, 0xdb08, 0x12c8, 0xf602, 0xe766, 0x2394, 0x250d, 0xdcbb, 0xa678, 0x02af, 0xa5c6, 0x7ea6, 0xb645, 0xcb4d, 0xc44b, 0xe5dc, 0x9fe6, 0x5b5c, 0x35f5, 0x701a, 0x220f, 0x6c38, 0x1a56, 0x4ca3, 0xffc6, 0xb152, 0x8d61, 0x7a58, 0x9025, 0x8b3d, 0xbf0f, 0x95a3, 0xe5f4, 0xc127, 0x3bed, 0x320b, 0xb7f3, 0x6054, 0x333c, 0xd383, 0x8154, 0x5242, 0x4e0d, 0x0a94, 0x7028, 0x8689, 0x3a22, 0x0980, 0x1847, 0xb0f1, 0x9b5c, 0x4176, 0xb858, 0xd542, 0x1f6c, 0x2497, 0x6a5a, 0x9fa9, 0x8c5a, 0x7743, 0xa8a9, 0x9a02, 0x4918, 0x438c, 0xc388, 0x9e2b, 0x4cad, 0x01b6, 0xab19, 0xf777, 0x365f, 0x1eb2, 0x091e, 0x7bf8, 0x7a8e, 0x5227, 0xeab1, 0x2074, 0x4523, 0xe781, 0x01a3, 0x163d, 0x3b2e, 0x287d, 0x5e7f, 0xa063, 0xb134, 0x8fae, 0x5e8e, 0xb7b7, 0x4548, 0x1f5a, 0xfa56, 0x7a24, 0x900f, 0x42dc, 0xcc69, 0x02a0, 0x0b22, 0xdb31, 0x71fe, 0x0c7d, 0x1732, 0x1159, 0xcb09, 0xe1d2, 0x1351, 0x52e9, 0xf536, 0x5a4f, 0xc316, 0x6bf9, 0x8994, 0xb774, 0x5f3e, 0xf6d6, 0x3a61, 0xf82c, 0xcc22, 0x9d06, 0x299c, 0x09e5, 0x1eec, 0x514f, 0x8d53, 0xa650, 0x5c6e, 0xc577, 0x7958, 0x71ac, 0x8916, 0x9b4f, 0x2c09, 0x5211, 0xf6d8, 0xcaaa, 0xf7ef, 0x287f, 0x7a94, 0xab49, 0xfa2c, 0x7222, 0xe457, 0xd71a, 0x00c3, 0x1a76, 0xe98c, 0xc037, 0x8208, 0x5c2d, 0xdfda, 0xe5f5, 0x0b45, 0x15ce, 0x8a7e, 0xfcad, 0xaa2d, 0x4b5c, 0xd42e, 0xb251, 0x907e, 0x9a47, 0xc9a6, 0xd93f, 0x085e, 0x35ce, 0xa153, 0x7e7b, 0x9f0b, 0x25aa, 0x5d9f, 0xc04d, 0x8a0e, 0x2875, 0x4a1c, 0x295f, 0x1393, 0xf760, 0x9178, 0x0f5b, 0xfa7d, 0x83b4, 0x2082, 0x721d, 0x6462, 0x0368, 0x67e2, 0x8624, 0x194d, 0x22f6, 0x78fb, 0x6791, 0xb238, 0xb332, 0x7276, 0xf272, 0x47ec, 0x4504, 0xa961, 0x9fc8, 0x3fdc, 0xb413, 0x007a, 0x0806, 0x7458, 0x95c6, 0xccaa, 0x18d6, 0xe2ae, 0x1b06, 0xf3f6, 0x5050, 0xc8e8, 0xf4ac, 0xc04c, 0xf41c, 0x992f, 0xae44, 0x5f1b, 0x1113, 0x1738, 0xd9a8, 0x19ea, 0x2d33, 0x9698, 0x2fe9, 0x323f, 0xcde2, 0x6d71, 0xe37d, 0xb697, 0x2c4f, 0x4373, 0x9102, 0x075d, 0x8e25, 0x1672, 0xec28, 0x6acb, 0x86cc, 0x186e, 0x9414, 0xd674, 0xd1a5 }; /**************************************************************** Instruction tables *****************************************************************/ /* The following code implements a parametrized description of the * code table given above for a few reasons. It is not necessary for * implementing the standard, to support compression with variable * tables, so an implementation is only required to know the default * code table to begin decompression. (If the encoder uses an * alternate table, the table is included in compressed form inside * the VCDIFF file.) * * Before adding variable-table support there were two functions which * were hard-coded to the default table above. * xd3_compute_default_table() would create the default table by * filling a 256-elt array of xd3_dinst values. The corresponding * function, xd3_choose_instruction(), would choose an instruction * based on the hard-coded parameters of the default code table. * * Notes: The parametrized code table description here only generates * tables of a certain regularity similar to the default table by * allowing to vary the distribution of single- and * double-instructions and change the number of near and same copy * modes. More exotic tables are only possible by extending this * code. * * For performance reasons, both the parametrized and non-parametrized * versions of xd3_choose_instruction remain. The parametrized * version is only needed for testing multi-table decoding support. * If ever multi-table encoding is required, this can be optimized by * compiling static functions for each table. */ /* The XD3_CHOOSE_INSTRUCTION calls xd3_choose_instruction with the * table description when GENERIC_ENCODE_TABLES are in use. The * IF_GENCODETBL macro enables generic-code-table specific code. */ #if GENERIC_ENCODE_TABLES #define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (stream->code_table_desc, prev, inst) #define IF_GENCODETBL(x) x #else #define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (prev, inst) #define IF_GENCODETBL(x) #endif /* This structure maintains information needed by * xd3_choose_instruction to compute the code for a double instruction * by first indexing an array of code_table_sizes by copy mode, then * using (offset + (muliplier * X)) */ struct _xd3_code_table_sizes { uint8_t cpy_max; uint8_t offset; uint8_t mult; }; /* This contains a complete description of a code table. */ struct _xd3_code_table_desc { /* Assumes a single RUN instruction */ /* Assumes that MIN_MATCH is 4 */ uint8_t add_sizes; /* Number of immediate-size single adds (default 17) */ uint8_t near_modes; /* Number of near copy modes (default 4) */ uint8_t same_modes; /* Number of same copy modes (default 3) */ uint8_t cpy_sizes; /* Number of immediate-size single copies (default 15) */ uint8_t addcopy_add_max; /* Maximum add size for an add-copy double instruction, all modes (default 4) */ uint8_t addcopy_near_cpy_max; /* Maximum cpy size for an add-copy double instruction, up through VCD_NEAR modes (default 6) */ uint8_t addcopy_same_cpy_max; /* Maximum cpy size for an add-copy double instruction, VCD_SAME modes (default 4) */ uint8_t copyadd_add_max; /* Maximum add size for a copy-add double instruction, all modes (default 1) */ uint8_t copyadd_near_cpy_max; /* Maximum cpy size for a copy-add double instruction, up through VCD_NEAR modes (default 4) */ uint8_t copyadd_same_cpy_max; /* Maximum cpy size for a copy-add double instruction, VCD_SAME modes (default 4) */ xd3_code_table_sizes addcopy_max_sizes[MAX_MODES]; xd3_code_table_sizes copyadd_max_sizes[MAX_MODES]; }; /* The rfc3284 code table is represented: */ static const xd3_code_table_desc __rfc3284_code_table_desc = { 17, /* add sizes */ 4, /* near modes */ 3, /* same modes */ 15, /* copy sizes */ 4, /* add-copy max add */ 6, /* add-copy max cpy, near */ 4, /* add-copy max cpy, same */ 1, /* copy-add max add */ 4, /* copy-add max cpy, near */ 4, /* copy-add max cpy, same */ /* addcopy */ { {6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{4,235,1},{4,239,1},{4,243,1} }, /* copyadd */ { {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},{4,253,1},{4,254,1},{4,255,1} }, }; #if GENERIC_ENCODE_TABLES /* An alternate code table for testing (5 near, 0 same): * * TYPE SIZE MODE TYPE SIZE MODE INDEX * --------------------------------------------------------------- * 1. Run 0 0 Noop 0 0 0 * 2. Add 0, [1,23] 0 Noop 0 0 [1,24] * 3. Copy 0, [4,20] 0 Noop 0 0 [25,42] * 4. Copy 0, [4,20] 1 Noop 0 0 [43,60] * 5. Copy 0, [4,20] 2 Noop 0 0 [61,78] * 6. Copy 0, [4,20] 3 Noop 0 0 [79,96] * 7. Copy 0, [4,20] 4 Noop 0 0 [97,114] * 8. Copy 0, [4,20] 5 Noop 0 0 [115,132] * 9. Copy 0, [4,20] 6 Noop 0 0 [133,150] * 10. Add [1,4] 0 Copy [4,6] 0 [151,162] * 11. Add [1,4] 0 Copy [4,6] 1 [163,174] * 12. Add [1,4] 0 Copy [4,6] 2 [175,186] * 13. Add [1,4] 0 Copy [4,6] 3 [187,198] * 14. Add [1,4] 0 Copy [4,6] 4 [199,210] * 15. Add [1,4] 0 Copy [4,6] 5 [211,222] * 16. Add [1,4] 0 Copy [4,6] 6 [223,234] * 17. Copy 4 [0,6] Add [1,3] 0 [235,255] * --------------------------------------------------------------- */ static const xd3_code_table_desc __alternate_code_table_desc = { 23, /* add sizes */ 5, /* near modes */ 0, /* same modes */ 17, /* copy sizes */ 4, /* add-copy max add */ 6, /* add-copy max cpy, near */ 0, /* add-copy max cpy, same */ 3, /* copy-add max add */ 4, /* copy-add max cpy, near */ 0, /* copy-add max cpy, same */ /* addcopy */ { {6,151,3},{6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{0,0,0},{0,0,0} }, /* copyadd */ { {4,235,1},{4,238,1},{4,241,1},{4,244,1},{4,247,1},{4,250,1},{4,253,1},{0,0,0},{0,0,0} }, }; #endif /* Computes code table entries of TBL using the specified description. */ static void xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl) { usize_t size1, size2, mode; usize_t cpy_modes = 2 + desc->near_modes + desc->same_modes; xd3_dinst *d = tbl; (d++)->type1 = XD3_RUN; (d++)->type1 = XD3_ADD; for (size1 = 1; size1 <= desc->add_sizes; size1 += 1, d += 1) { d->type1 = XD3_ADD; d->size1 = size1; } for (mode = 0; mode < cpy_modes; mode += 1) { (d++)->type1 = XD3_CPY + mode; for (size1 = MIN_MATCH; size1 < MIN_MATCH + desc->cpy_sizes; size1 += 1, d += 1) { d->type1 = XD3_CPY + mode; d->size1 = size1; } } for (mode = 0; mode < cpy_modes; mode += 1) { for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1) { usize_t max = (mode < 2U + desc->near_modes) ? desc->addcopy_near_cpy_max : desc->addcopy_same_cpy_max; for (size2 = MIN_MATCH; size2 <= max; size2 += 1, d += 1) { d->type1 = XD3_ADD; d->size1 = size1; d->type2 = XD3_CPY + mode; d->size2 = size2; } } } for (mode = 0; mode < cpy_modes; mode += 1) { usize_t max = (mode < 2U + desc->near_modes) ? desc->copyadd_near_cpy_max : desc->copyadd_same_cpy_max; for (size1 = MIN_MATCH; size1 <= max; size1 += 1) { for (size2 = 1; size2 <= desc->copyadd_add_max; size2 += 1, d += 1) { d->type1 = XD3_CPY + mode; d->size1 = size1; d->type2 = XD3_ADD; d->size2 = size2; } } } XD3_ASSERT (d - tbl == 256); } /* This function generates the static default code table. */ static const xd3_dinst* xd3_rfc3284_code_table (void) { static xd3_dinst __rfc3284_code_table[256]; if (__rfc3284_code_table[0].type1 != XD3_RUN) { xd3_build_code_table (& __rfc3284_code_table_desc, __rfc3284_code_table); } return __rfc3284_code_table; } #if XD3_ENCODER #if GENERIC_ENCODE_TABLES /* This function generates the alternate code table. */ static const xd3_dinst* xd3_alternate_code_table (void) { static xd3_dinst __alternate_code_table[256]; if (__alternate_code_table[0].type1 != XD3_RUN) { xd3_build_code_table (& __alternate_code_table_desc, __alternate_code_table); } return __alternate_code_table; } /* This function computes the ideal second instruction INST based on * preceding instruction PREV. If it is possible to issue a double * instruction based on this pair it sets PREV->code2, otherwise it * sets INST->code1. */ static void xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_rinst *inst) { switch (inst->type) { case XD3_RUN: /* The 0th instruction is RUN */ inst->code1 = 0; break; case XD3_ADD: if (inst->size > desc->add_sizes) { /* The first instruction is non-immediate ADD */ inst->code1 = 1; } else { /* The following ADD_SIZES instructions are immediate ADDs */ inst->code1 = 1 + inst->size; /* Now check for a possible COPY-ADD double instruction */ if (prev != NULL) { int prev_mode = prev->type - XD3_CPY; /* If previous is a copy. Note: as long as the previous * is not a RUN instruction, it should be a copy because * it cannot be an add. This check is more clear. */ if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) { const xd3_code_table_sizes *sizes = & desc->copyadd_max_sizes[prev_mode]; /* This check and the inst->size-<= above are == in the default table. */ if (prev->size <= sizes->cpy_max) { /* The second and third exprs are 0 in the default table. */ prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_MATCH)) + (inst->size - MIN_ADD); } } } } break; default: { int mode = inst->type - XD3_CPY; /* The large copy instruction is offset by the run, large add, * and immediate adds, then multipled by the number of * immediate copies plus one (the large copy) (i.e., if there * are 15 immediate copy instructions then there are 16 copy * instructions per mode). */ inst->code1 = 2 + desc->add_sizes + (1 + desc->cpy_sizes) * mode; /* Now if the copy is short enough for an immediate instruction. */ if (inst->size < MIN_MATCH + desc->cpy_sizes && /* TODO: there needs to be a more comprehensive test for this * boundary condition, merge is now exercising code in which * size < MIN_MATCH is possible and it's unclear if the above * size < (MIN_MATCH + cpy_sizes) should be a <= from inspection * of the default table version below. */ inst->size >= MIN_MATCH) { inst->code1 += inst->size + 1 - MIN_MATCH; /* Now check for a possible ADD-COPY double instruction. */ if ( (prev != NULL) && (prev->type == XD3_ADD) && (prev->size <= desc->addcopy_add_max) ) { const xd3_code_table_sizes *sizes = & desc->addcopy_max_sizes[mode]; if (inst->size <= sizes->cpy_max) { prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_ADD)) + (inst->size - MIN_MATCH); } } } } } } #else /* GENERIC_ENCODE_TABLES */ /* This version of xd3_choose_instruction is hard-coded for the default table. */ static void xd3_choose_instruction (xd3_rinst *prev, xd3_rinst *inst) { switch (inst->type) { case XD3_RUN: inst->code1 = 0; break; case XD3_ADD: inst->code1 = 1; if (inst->size <= 17) { inst->code1 += inst->size; if ( (inst->size == 1) && (prev != NULL) && (prev->size == 4) && (prev->type >= XD3_CPY) ) { prev->code2 = 247 + (prev->type - XD3_CPY); } } break; default: { int mode = inst->type - XD3_CPY; XD3_ASSERT (inst->type >= XD3_CPY && inst->type < 12); inst->code1 = 19 + 16 * mode; if (inst->size <= 18 && inst->size >= 4) { inst->code1 += inst->size - 3; if ( (prev != NULL) && (prev->type == XD3_ADD) && (prev->size <= 4) ) { if ( (inst->size <= 6) && (mode <= 5) ) { prev->code2 = 163 + (mode * 12) + (3 * (prev->size - 1)) + (inst->size - 4); XD3_ASSERT (prev->code2 <= 234); } else if ( (inst->size == 4) && (mode >= 6) ) { prev->code2 = 235 + ((mode - 6) * 4) + (prev->size - 1); XD3_ASSERT (prev->code2 <= 246); } } } XD3_ASSERT (inst->code1 <= 162); } break; } } #endif /* GENERIC_ENCODE_TABLES */ /*********************************************************************** Instruction table encoder/decoder ***********************************************************************/ #if GENERIC_ENCODE_TABLES #if GENERIC_ENCODE_TABLES_COMPUTE == 0 /* In this case, we hard-code the result of * compute_code_table_encoding for each alternate code table, * presuming that saves time/space. This has been 131 bytes, but * secondary compression was turned off. */ static const uint8_t __alternate_code_table_compressed[178] = {0xd6,0xc3,0xc4,0x00,0x00,0x01,0x8a,0x6f,0x40,0x81,0x27,0x8c,0x00,0x00,0x4a,0x4a,0x0d,0x02,0x01,0x03, 0x01,0x03,0x00,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04, 0x04,0x04,0x04,0x00,0x04,0x05,0x06,0x01,0x02,0x03,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x05,0x05,0x05, 0x06,0x06,0x06,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x02,0x00,0x18,0x13,0x63,0x00,0x1b,0x00,0x54, 0x00,0x15,0x23,0x6f,0x00,0x28,0x13,0x54,0x00,0x15,0x01,0x1a,0x31,0x23,0x6c,0x0d,0x23,0x48,0x00,0x15, 0x93,0x6f,0x00,0x28,0x04,0x23,0x51,0x04,0x32,0x00,0x2b,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, 0x12,0x00,0x12,0x53,0x57,0x9c,0x07,0x43,0x6f,0x00,0x34,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00, 0x0c,0x00,0x0c,0x00,0x15,0x00,0x82,0x6f,0x00,0x15,0x12,0x0c,0x00,0x03,0x03,0x00,0x06,0x00,}; static int xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) { (*data) = __alternate_code_table_compressed; (*size) = sizeof (__alternate_code_table_compressed); return 0; } #else /* The alternate code table will be computed and stored here. */ static uint8_t __alternate_code_table_compressed[CODE_TABLE_VCDIFF_SIZE]; static usize_t __alternate_code_table_compressed_size; /* This function generates a delta describing the code table for * encoding within a VCDIFF file. This function is NOT thread safe * because it is only intended that this function is used to generate * statically-compiled strings. "comp_string" must be sized * CODE_TABLE_VCDIFF_SIZE. */ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *code_table, uint8_t *comp_string, usize_t *comp_string_size) { /* Use DJW secondary compression if it is on by default. This saves * about 20 bytes. */ uint8_t dflt_string[CODE_TABLE_STRING_SIZE]; uint8_t code_string[CODE_TABLE_STRING_SIZE]; xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); xd3_compute_code_table_string (code_table, code_string); return xd3_encode_memory (code_string, CODE_TABLE_STRING_SIZE, dflt_string, CODE_TABLE_STRING_SIZE, comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE, /* flags */ 0); } /* Compute a delta between alternate and rfc3284 tables. As soon as * another alternate table is added, this code should become generic. * For now there is only one alternate table for testing. */ static int xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) { int ret; if (__alternate_code_table_compressed[0] == 0) { if ((ret = xd3_compute_code_table_encoding (stream, xd3_alternate_code_table (), __alternate_code_table_compressed, & __alternate_code_table_compressed_size))) { return ret; } /* During development of a new code table, enable this variable to print * the new static contents and determine its size. At run time the * table will be filled in appropriately, but at least it should have * the proper size beforehand. */ #if GENERIC_ENCODE_TABLES_COMPUTE_PRINT { int i; DP(RINT, "\nstatic const usize_t __alternate_code_table_compressed_size = %u;\n", __alternate_code_table_compressed_size); DP(RINT, "static const uint8_t __alternate_code_table_compressed[%u] =\n{", __alternate_code_table_compressed_size); for (i = 0; i < __alternate_code_table_compressed_size; i += 1) { DP(RINT, "0x%02x,", __alternate_code_table_compressed[i]); if ((i % 20) == 19) { DP(RINT, "\n"); } } DP(RINT, "};\n"); } #endif } (*data) = __alternate_code_table_compressed; (*size) = __alternate_code_table_compressed_size; return 0; } #endif /* GENERIC_ENCODE_TABLES_COMPUTE != 0 */ #endif /* GENERIC_ENCODE_TABLES */ #endif /* XD3_ENCODER */ /* This function generates the 1536-byte string specified in sections 5.4 and * 7 of rfc3284, which is used to represent a code table within a VCDIFF * file. */ void xd3_compute_code_table_string (const xd3_dinst *code_table, uint8_t *str) { int i, s; XD3_ASSERT (CODE_TABLE_STRING_SIZE == 6 * 256); for (s = 0; s < 6; s += 1) { for (i = 0; i < 256; i += 1) { switch (s) { case 0: *str++ = (code_table[i].type1 >= XD3_CPY ? XD3_CPY : code_table[i].type1); break; case 1: *str++ = (code_table[i].type2 >= XD3_CPY ? XD3_CPY : code_table[i].type2); break; case 2: *str++ = (code_table[i].size1); break; case 3: *str++ = (code_table[i].size2); break; case 4: *str++ = (code_table[i].type1 >= XD3_CPY ? code_table[i].type1 - XD3_CPY : 0); break; case 5: *str++ = (code_table[i].type2 >= XD3_CPY ? code_table[i].type2 - XD3_CPY : 0); break; } } } } /* This function translates the code table string into the internal representation. The * stream's near and same-modes should already be set. */ static int xd3_apply_table_string (xd3_stream *stream, const uint8_t *code_string) { int i, s; int modes = TOTAL_MODES (stream); xd3_dinst *code_table; if ((code_table = stream->code_table_alloc = (xd3_dinst*) xd3_alloc (stream, (usize_t) sizeof (xd3_dinst), 256)) == NULL) { return ENOMEM; } for (s = 0; s < 6; s += 1) { for (i = 0; i < 256; i += 1) { switch (s) { case 0: if (*code_string > XD3_CPY) { stream->msg = "invalid code-table opcode"; return XD3_INTERNAL; } code_table[i].type1 = *code_string++; break; case 1: if (*code_string > XD3_CPY) { stream->msg = "invalid code-table opcode"; return XD3_INTERNAL; } code_table[i].type2 = *code_string++; break; case 2: if (*code_string != 0 && code_table[i].type1 == XD3_NOOP) { stream->msg = "invalid code-table size"; return XD3_INTERNAL; } code_table[i].size1 = *code_string++; break; case 3: if (*code_string != 0 && code_table[i].type2 == XD3_NOOP) { stream->msg = "invalid code-table size"; return XD3_INTERNAL; } code_table[i].size2 = *code_string++; break; case 4: if (*code_string >= modes) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } if (*code_string != 0 && code_table[i].type1 != XD3_CPY) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } code_table[i].type1 += *code_string++; break; case 5: if (*code_string >= modes) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } if (*code_string != 0 && code_table[i].type2 != XD3_CPY) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } code_table[i].type2 += *code_string++; break; } } } stream->code_table = code_table; return 0; } /* This function applies a code table delta and returns an actual code table. */ static int xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t size) { uint8_t dflt_string[CODE_TABLE_STRING_SIZE]; uint8_t code_string[CODE_TABLE_STRING_SIZE]; usize_t code_size; int ret; xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); if ((ret = xd3_decode_memory (data, size, dflt_string, CODE_TABLE_STRING_SIZE, code_string, &code_size, CODE_TABLE_STRING_SIZE, 0))) { return ret; } if (code_size != sizeof (code_string)) { in_stream->msg = "corrupt code-table encoding"; return XD3_INTERNAL; } return xd3_apply_table_string (in_stream, code_string); } /***********************************************************************/ static inline void xd3_swap_uint8p (uint8_t** p1, uint8_t** p2) { uint8_t *t = (*p1); (*p1) = (*p2); (*p2) = t; } static inline void xd3_swap_usize_t (usize_t* p1, usize_t* p2) { usize_t t = (*p1); (*p1) = (*p2); (*p2) = t; } /* It's not constant time, but it computes the log. */ static int xd3_check_pow2 (xoff_t value, usize_t *logof) { xoff_t x = 1; usize_t nolog; if (logof == NULL) { logof = &nolog; } *logof = 0; for (; x != 0; x <<= 1, *logof += 1) { if (x == value) { return 0; } } return XD3_INTERNAL; } static size_t xd3_pow2_roundup (size_t x) { size_t i = 1; while (x > i) { i <<= 1U; } return i; } static xoff_t xd3_xoff_roundup (xoff_t x) { xoff_t i = 1; while (x > i) { i <<= 1U; } return i; } static usize_t xd3_round_blksize (usize_t sz, usize_t blksz) { usize_t mod = sz & (blksz-1); XD3_ASSERT (xd3_check_pow2 (blksz, NULL) == 0); return mod ? (sz + (blksz - mod)) : sz; } /*********************************************************************** Adler32 stream function: code copied from Zlib, defined in RFC1950 ***********************************************************************/ #define A32_BASE 65521L /* Largest prime smaller than 2^16 */ #define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define A32_DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define A32_DO2(buf,i) A32_DO1(buf,i); A32_DO1(buf,i+1); #define A32_DO4(buf,i) A32_DO2(buf,i); A32_DO2(buf,i+2); #define A32_DO8(buf,i) A32_DO4(buf,i); A32_DO4(buf,i+4); #define A32_DO16(buf) A32_DO8(buf,0); A32_DO8(buf,8); static unsigned long adler32 (unsigned long adler, const uint8_t *buf, usize_t len) { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; int k; while (len > 0) { k = (len < A32_NMAX) ? len : A32_NMAX; len -= k; while (k >= 16) { A32_DO16(buf); buf += 16; k -= 16; } if (k != 0) { do { s1 += *buf++; s2 += s1; } while (--k); } s1 %= A32_BASE; s2 %= A32_BASE; } return (s2 << 16) | s1; } /*********************************************************************** Run-length function ***********************************************************************/ #if XD3_ENCODER static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp) { usize_t i; usize_t run_l = 0; uint8_t run_c = 0; for (i = 0; i < slook; i += 1) { NEXTRUN(seg[i]); } (*run_cp) = run_c; return run_l; } #endif /*********************************************************************** Basic encoder/decoder functions ***********************************************************************/ static inline int xd3_decode_byte (xd3_stream *stream, usize_t *val) { if (stream->avail_in == 0) { stream->msg = "further input required"; return XD3_INPUT; } (*val) = stream->next_in[0]; DECODE_INPUT (1); return 0; } static inline int xd3_decode_bytes (xd3_stream *stream, uint8_t *buf, usize_t *pos, usize_t size) { usize_t want; usize_t take; /* Note: The case where (*pos == size) happens when a zero-length * appheader or code table is transmitted, but there is nothing in * the standard against that. */ while (*pos < size) { if (stream->avail_in == 0) { stream->msg = "further input required"; return XD3_INPUT; } want = size - *pos; take = min (want, stream->avail_in); memcpy (buf + *pos, stream->next_in, (size_t) take); DECODE_INPUT (take); (*pos) += take; } return 0; } #if XD3_ENCODER static inline int xd3_emit_byte (xd3_stream *stream, xd3_output **outputp, uint8_t code) { xd3_output *output = (*outputp); if (output->next == output->avail) { xd3_output *aoutput; if ((aoutput = xd3_alloc_output (stream, output)) == NULL) { return ENOMEM; } output = (*outputp) = aoutput; } output->base[output->next++] = code; return 0; } static inline int xd3_emit_bytes (xd3_stream *stream, xd3_output **outputp, const uint8_t *base, usize_t size) { xd3_output *output = (*outputp); do { usize_t take; if (output->next == output->avail) { xd3_output *aoutput; if ((aoutput = xd3_alloc_output (stream, output)) == NULL) { return ENOMEM; } output = (*outputp) = aoutput; } take = min (output->avail - output->next, size); memcpy (output->base + output->next, base, (size_t) take); output->next += take; size -= take; base += take; } while (size > 0); return 0; } #endif /* XD3_ENCODER */ /********************************************************************* Integer encoder/decoder functions **********************************************************************/ #define DECODE_INTEGER_TYPE(PART,OFLOW) \ while (stream->avail_in != 0) \ { \ usize_t next = stream->next_in[0]; \ \ DECODE_INPUT(1); \ \ if (PART & OFLOW) \ { \ stream->msg = "overflow in decode_integer"; \ return XD3_INVALID_INPUT; \ } \ \ PART = (PART << 7) | (next & 127); \ \ if ((next & 128) == 0) \ { \ (*val) = PART; \ PART = 0; \ return 0; \ } \ } \ \ stream->msg = "further input required"; \ return XD3_INPUT #define READ_INTEGER_TYPE(TYPE, OFLOW) \ TYPE val = 0; \ const uint8_t *inp = (*inpp); \ usize_t next; \ \ do \ { \ if (inp == max) \ { \ stream->msg = "end-of-input in read_integer"; \ return XD3_INVALID_INPUT; \ } \ \ if (val & OFLOW) \ { \ stream->msg = "overflow in read_intger"; \ return XD3_INVALID_INPUT; \ } \ \ next = (*inp++); \ val = (val << 7) | (next & 127); \ } \ while (next & 128); \ \ (*valp) = val; \ (*inpp) = inp; \ \ return 0 #define EMIT_INTEGER_TYPE() \ /* max 64-bit value in base-7 encoding is 9.1 bytes */ \ uint8_t buf[10]; \ usize_t bufi = 10; \ \ /* This loop performs division and turns on all MSBs. */ \ do \ { \ buf[--bufi] = (num & 127) | 128; \ num >>= 7U; \ } \ while (num != 0); \ \ /* Turn off MSB of the last byte. */ \ buf[9] &= 127; \ \ return xd3_emit_bytes (stream, output, buf + bufi, 10 - bufi) #define IF_SIZEOF32(x) if (num < (1U << (7 * (x)))) return (x); #define IF_SIZEOF64(x) if (num < (1ULL << (7 * (x)))) return (x); #if USE_UINT32 static inline uint32_t xd3_sizeof_uint32_t (uint32_t num) { IF_SIZEOF32(1); IF_SIZEOF32(2); IF_SIZEOF32(3); IF_SIZEOF32(4); return 5; } static inline int xd3_decode_uint32_t (xd3_stream *stream, uint32_t *val) { DECODE_INTEGER_TYPE (stream->dec_32part, UINT32_OFLOW_MASK); } static inline int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint32_t *valp) { READ_INTEGER_TYPE (uint32_t, UINT32_OFLOW_MASK); } #if XD3_ENCODER static inline int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, uint32_t num) { EMIT_INTEGER_TYPE (); } #endif #endif #if USE_UINT64 static inline int xd3_decode_uint64_t (xd3_stream *stream, uint64_t *val) { DECODE_INTEGER_TYPE (stream->dec_64part, UINT64_OFLOW_MASK); } #if XD3_ENCODER static inline int xd3_emit_uint64_t (xd3_stream *stream, xd3_output **output, uint64_t num) { EMIT_INTEGER_TYPE (); } #endif /* These are tested but not used */ #if REGRESSION_TEST static int xd3_read_uint64_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint64_t *valp) { READ_INTEGER_TYPE (uint64_t, UINT64_OFLOW_MASK); } static uint32_t xd3_sizeof_uint64_t (uint64_t num) { IF_SIZEOF64(1); IF_SIZEOF64(2); IF_SIZEOF64(3); IF_SIZEOF64(4); IF_SIZEOF64(5); IF_SIZEOF64(6); IF_SIZEOF64(7); IF_SIZEOF64(8); IF_SIZEOF64(9); return 10; } #endif #endif /*********************************************************************** Address cache stuff ***********************************************************************/ static int xd3_alloc_cache (xd3_stream *stream) { if (stream->acache.near_array != NULL) { xd3_free (stream, stream->acache.near_array); } if (stream->acache.same_array != NULL) { xd3_free (stream, stream->acache.same_array); } if (((stream->acache.s_near > 0) && (stream->acache.near_array = (usize_t*) xd3_alloc (stream, stream->acache.s_near, (usize_t) sizeof (usize_t))) == NULL) || ((stream->acache.s_same > 0) && (stream->acache.same_array = (usize_t*) xd3_alloc (stream, stream->acache.s_same * 256, (usize_t) sizeof (usize_t))) == NULL)) { return ENOMEM; } return 0; } void xd3_init_cache (xd3_addr_cache* acache) { if (acache->s_near > 0) { memset (acache->near_array, 0, acache->s_near * sizeof (usize_t)); acache->next_slot = 0; } if (acache->s_same > 0) { memset (acache->same_array, 0, acache->s_same * 256 * sizeof (usize_t)); } } static void xd3_update_cache (xd3_addr_cache* acache, usize_t addr) { if (acache->s_near > 0) { acache->near_array[acache->next_slot] = addr; acache->next_slot = (acache->next_slot + 1) % acache->s_near; } if (acache->s_same > 0) { acache->same_array[addr % (acache->s_same*256)] = addr; } } #if XD3_ENCODER /* OPT: this gets called a lot, can it be optimized? */ static int xd3_encode_address (xd3_stream *stream, usize_t addr, usize_t here, uint8_t* mode) { usize_t d, bestd; usize_t i, bestm, ret; xd3_addr_cache* acache = & stream->acache; #define SMALLEST_INT(x) do { if (((x) & ~127U) == 0) { goto good; } } while (0) /* Attempt to find the address mode that yields the smallest integer value * for "d", the encoded address value, thereby minimizing the encoded size * of the address. */ bestd = addr; bestm = VCD_SELF; XD3_ASSERT (addr < here); SMALLEST_INT (bestd); if ((d = here-addr) < bestd) { bestd = d; bestm = VCD_HERE; SMALLEST_INT (bestd); } for (i = 0; i < acache->s_near; i += 1) { /* Note: If we used signed computation here, we'd could compte d * and then check (d >= 0 && d < bestd). */ if (addr >= acache->near_array[i]) { d = addr - acache->near_array[i]; if (d < bestd) { bestd = d; bestm = i+2; /* 2 counts the VCD_SELF, VCD_HERE modes */ SMALLEST_INT (bestd); } } } if (acache->s_same > 0 && acache->same_array[d = addr%(acache->s_same*256)] == addr) { bestd = d%256; /* 2 + s_near offsets past the VCD_NEAR modes */ bestm = acache->s_near + 2 + d/256; if ((ret = xd3_emit_byte (stream, & ADDR_TAIL (stream), bestd))) { return ret; } } else { good: if ((ret = xd3_emit_size (stream, & ADDR_TAIL (stream), bestd))) { return ret; } } xd3_update_cache (acache, addr); (*mode) += bestm; return 0; } #endif static int xd3_decode_address (xd3_stream *stream, usize_t here, usize_t mode, const uint8_t **inpp, const uint8_t *max, uint32_t *valp) { int ret; usize_t same_start = 2 + stream->acache.s_near; if (mode < same_start) { if ((ret = xd3_read_size (stream, inpp, max, valp))) { return ret; } switch (mode) { case VCD_SELF: break; case VCD_HERE: (*valp) = here - (*valp); break; default: (*valp) += stream->acache.near_array[mode - 2]; break; } } else { if (*inpp == max) { stream->msg = "address underflow"; return XD3_INVALID_INPUT; } mode -= same_start; (*valp) = stream->acache.same_array[mode*256 + (**inpp)]; (*inpp) += 1; } xd3_update_cache (& stream->acache, *valp); return 0; } /*********************************************************************** Alloc/free ***********************************************************************/ static void* __xd3_alloc_func (void* opaque, size_t items, usize_t size) { return malloc (items * (size_t) size); } static void __xd3_free_func (void* opaque, void* address) { free (address); } static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size) { void *a = stream->alloc (stream->opaque, elts, size); if (a != NULL) { IF_DEBUG (stream->alloc_cnt += 1); IF_DEBUG2 (DP(RINT "[stream %p malloc] size %u ptr %p\n", stream, elts * size, a)); } else { stream->msg = "out of memory"; } return a; } static void xd3_free (xd3_stream *stream, void *ptr) { if (ptr != NULL) { IF_DEBUG (stream->free_cnt += 1); XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); IF_DEBUG2 (DP(RINT "[stream %p free] %p\n", stream, ptr)); stream->free (stream->opaque, ptr); } } #if XD3_ENCODER static void* xd3_alloc0 (xd3_stream *stream, usize_t elts, usize_t size) { void *a = xd3_alloc (stream, elts, size); if (a != NULL) { memset (a, 0, (size_t) (elts * size)); } return a; } static xd3_output* xd3_alloc_output (xd3_stream *stream, xd3_output *old_output) { xd3_output *output; uint8_t *base; if (stream->enc_free != NULL) { output = stream->enc_free; stream->enc_free = output->next_page; } else { if ((output = (xd3_output*) xd3_alloc (stream, 1, (usize_t) sizeof (xd3_output))) == NULL) { return NULL; } if ((base = (uint8_t*) xd3_alloc (stream, XD3_ALLOCSIZE, sizeof (uint8_t))) == NULL) { xd3_free (stream, output); return NULL; } output->base = base; output->avail = XD3_ALLOCSIZE; } output->next = 0; if (old_output) { old_output->next_page = output; } output->next_page = NULL; return output; } static usize_t xd3_sizeof_output (xd3_output *output) { usize_t s = 0; for (; output; output = output->next_page) { s += output->next; } return s; } static void xd3_freelist_output (xd3_stream *stream, xd3_output *output) { xd3_output *tmp; while (output) { tmp = output; output = output->next_page; tmp->next = 0; tmp->next_page = stream->enc_free; stream->enc_free = tmp; } } static void xd3_free_output (xd3_stream *stream, xd3_output *output) { xd3_output *next; again: if (output == NULL) { return; } next = output->next_page; xd3_free (stream, output->base); xd3_free (stream, output); output = next; goto again; } #endif /* XD3_ENCODER */ void xd3_free_stream (xd3_stream *stream) { xd3_iopt_buflist *blist = stream->iopt_alloc; while (blist != NULL) { xd3_iopt_buflist *tmp = blist; blist = blist->next; xd3_free (stream, tmp->buffer); xd3_free (stream, tmp); } xd3_free (stream, stream->large_table); xd3_free (stream, stream->small_table); xd3_free (stream, stream->small_prev); #if XD3_ENCODER { int i; for (i = 0; i < ENC_SECTS; i += 1) { xd3_free_output (stream, stream->enc_heads[i]); } xd3_free_output (stream, stream->enc_free); } #endif xd3_free (stream, stream->acache.near_array); xd3_free (stream, stream->acache.same_array); xd3_free (stream, stream->inst_sect.copied1); xd3_free (stream, stream->addr_sect.copied1); xd3_free (stream, stream->data_sect.copied1); xd3_free (stream, stream->dec_buffer); xd3_free (stream, (uint8_t*) stream->dec_lastwin); xd3_free (stream, stream->buf_in); xd3_free (stream, stream->dec_appheader); xd3_free (stream, stream->dec_codetbl); xd3_free (stream, stream->code_table_alloc); #if SECONDARY_ANY xd3_free (stream, stream->inst_sect.copied2); xd3_free (stream, stream->addr_sect.copied2); xd3_free (stream, stream->data_sect.copied2); if (stream->sec_type != NULL) { stream->sec_type->destroy (stream, stream->sec_stream_d); stream->sec_type->destroy (stream, stream->sec_stream_i); stream->sec_type->destroy (stream, stream->sec_stream_a); } #endif xd3_free (stream, stream->whole_target.adds); xd3_free (stream, stream->whole_target.inst); xd3_free (stream, stream->whole_target.wininfo); XD3_ASSERT (stream->alloc_cnt == stream->free_cnt); memset (stream, 0, sizeof (xd3_stream)); } #if (XD3_DEBUG > 1 || VCDIFF_TOOLS) static const char* xd3_rtype_to_string (xd3_rtype type, int print_mode) { switch (type) { case XD3_NOOP: return "NOOP "; case XD3_RUN: return "RUN "; case XD3_ADD: return "ADD "; default: break; } if (! print_mode) { return "CPY "; } switch (type) { case XD3_CPY + 0: return "CPY_0"; case XD3_CPY + 1: return "CPY_1"; case XD3_CPY + 2: return "CPY_2"; case XD3_CPY + 3: return "CPY_3"; case XD3_CPY + 4: return "CPY_4"; case XD3_CPY + 5: return "CPY_5"; case XD3_CPY + 6: return "CPY_6"; case XD3_CPY + 7: return "CPY_7"; case XD3_CPY + 8: return "CPY_8"; case XD3_CPY + 9: return "CPY_9"; default: return "CPY>9"; } } #endif /**************************************************************** Stream configuration ******************************************************************/ int xd3_config_stream(xd3_stream *stream, xd3_config *config) { int ret; xd3_config defcfg; xd3_smatcher *smatcher = &stream->smatcher; if (config == NULL) { config = & defcfg; memset (config, 0, sizeof (*config)); } /* Initial setup: no error checks yet */ memset (stream, 0, sizeof (*stream)); stream->winsize = config->winsize ? config->winsize : XD3_DEFAULT_WINSIZE; stream->sprevsz = config->sprevsz ? config->sprevsz : XD3_DEFAULT_SPREVSZ; if (config->iopt_size == 0) { stream->iopt_size = XD3_ALLOCSIZE / sizeof(xd3_rinst); stream->iopt_unlimited = 1; } else { stream->iopt_size = config->iopt_size; } stream->getblk = config->getblk; stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func; stream->free = config->freef ? config->freef : __xd3_free_func; stream->opaque = config->opaque; stream->flags = config->flags; /* Secondary setup. */ stream->sec_data = config->sec_data; stream->sec_inst = config->sec_inst; stream->sec_addr = config->sec_addr; stream->sec_data.data_type = DATA_SECTION; stream->sec_inst.data_type = INST_SECTION; stream->sec_addr.data_type = ADDR_SECTION; /* Check static sizes. */ if (sizeof (usize_t) != SIZEOF_USIZE_T || sizeof (xoff_t) != SIZEOF_XOFF_T || (ret = xd3_check_pow2(XD3_ALLOCSIZE, NULL))) { stream->msg = "incorrect compilation: wrong integer sizes"; return XD3_INTERNAL; } /* Check/set secondary compressor. */ switch (stream->flags & XD3_SEC_TYPE) { case 0: if (stream->flags & XD3_SEC_NOALL) { stream->msg = "XD3_SEC flags require a secondary compressor type"; return XD3_INTERNAL; } break; case XD3_SEC_FGK: FGK_CASE (stream); case XD3_SEC_DJW: DJW_CASE (stream); case XD3_SEC_LZMA: LZMA_CASE (stream); default: stream->msg = "too many secondary compressor types set"; return XD3_INTERNAL; } /* Check/set encoder code table. */ switch (stream->flags & XD3_ALT_CODE_TABLE) { case 0: stream->code_table_desc = & __rfc3284_code_table_desc; stream->code_table_func = xd3_rfc3284_code_table; break; #if GENERIC_ENCODE_TABLES case XD3_ALT_CODE_TABLE: stream->code_table_desc = & __alternate_code_table_desc; stream->code_table_func = xd3_alternate_code_table; stream->comp_table_func = xd3_compute_alternate_table_encoding; break; #endif default: stream->msg = "alternate code table support was not compiled"; return XD3_INTERNAL; } /* Check sprevsz */ if (smatcher->small_chain == 1 && smatcher->small_lchain == 1) { stream->sprevsz = 0; } else { if ((ret = xd3_check_pow2 (stream->sprevsz, NULL))) { stream->msg = "sprevsz is required to be a power of two"; return XD3_INTERNAL; } stream->sprevmask = stream->sprevsz - 1; } /* Default scanner settings. */ #if XD3_ENCODER switch (config->smatch_cfg) { IF_BUILD_SOFT(case XD3_SMATCH_SOFT: { *smatcher = config->smatcher_soft; smatcher->string_match = __smatcher_soft.string_match; smatcher->name = __smatcher_soft.name; if (smatcher->large_look < MIN_MATCH || smatcher->large_step < 1 || smatcher->small_look < MIN_MATCH) { stream->msg = "invalid soft string-match config"; return XD3_INVALID; } break; }) IF_BUILD_DEFAULT(case XD3_SMATCH_DEFAULT: *smatcher = __smatcher_default; break;) IF_BUILD_SLOW(case XD3_SMATCH_SLOW: *smatcher = __smatcher_slow; break;) IF_BUILD_FASTEST(case XD3_SMATCH_FASTEST: *smatcher = __smatcher_fastest; break;) IF_BUILD_FASTER(case XD3_SMATCH_FASTER: *smatcher = __smatcher_faster; break;) IF_BUILD_FAST(case XD3_SMATCH_FAST: *smatcher = __smatcher_fast; break;) default: stream->msg = "invalid string match config type"; return XD3_INTERNAL; } if (config->smatch_cfg == XD3_SMATCH_DEFAULT && (stream->flags & XD3_COMPLEVEL_MASK) != 0) { int level = (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT; switch (level) { case 1: IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; break;) case 2: IF_BUILD_FASTER(*smatcher = __smatcher_faster; break;) case 3: case 4: case 5: IF_BUILD_FAST(*smatcher = __smatcher_fast; break;) case 6: IF_BUILD_DEFAULT(*smatcher = __smatcher_default; break;) default: IF_BUILD_SLOW(*smatcher = __smatcher_slow; break;) IF_BUILD_DEFAULT(*smatcher = __smatcher_default; break;) IF_BUILD_FAST(*smatcher = __smatcher_fast; break;) IF_BUILD_FASTER(*smatcher = __smatcher_faster; break;) IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; break;) } } #endif return 0; } /*********************************************************** Getblk interface ***********************************************************/ inline xoff_t xd3_source_eof(const xd3_source *src) { xoff_t r = (src->blksize * src->max_blkno) + (xoff_t)src->onlastblk; return r; } inline usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno) { usize_t r = (blkno == src->max_blkno ? src->onlastblk : src->blksize); return r; } /* This function interfaces with the client getblk function, checks * its results, updates frontier_blkno, max_blkno, onlastblk, eof_known. */ static int xd3_getblk (xd3_stream *stream, xoff_t blkno) { int ret; xd3_source *source = stream->src; if (source->curblk == NULL || blkno != source->curblkno) { source->getblkno = blkno; if (stream->getblk == NULL) { stream->msg = "getblk source input"; return XD3_GETSRCBLK; } ret = stream->getblk (stream, source, blkno); if (ret != 0) { IF_DEBUG1 (DP(RINT "[getblk] app error blkno %"Q"u: %s\n", blkno, xd3_strerror (ret))); return ret; } } if (blkno >= source->frontier_blkno) { if (blkno > source->max_blkno) { source->max_blkno = blkno; source->onlastblk = source->onblk; } if (source->onblk == source->blksize) { source->frontier_blkno = blkno + 1; IF_DEBUG2 (DP(RINT "[getblk] full source blkno %"Q"u: " "source length unknown %"Q"u\n", blkno, xd3_source_eof (source))); } else { if (!source->eof_known) { IF_DEBUG2 (DP(RINT "[getblk] eof block has %d bytes; " "source length known %"Q"u\n", xd3_bytes_on_srcblk (source, blkno), xd3_source_eof (source))); source->eof_known = 1; } source->frontier_blkno = blkno; } } XD3_ASSERT (source->curblk != NULL); IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk %u blksize %u\n", blkno, source->onblk, source->blksize)); if (blkno == source->max_blkno) { /* In case the application sets the source as 1 block w/ a preset buffer. */ source->onlastblk = source->onblk; if (source->onblk == source->blksize) { source->frontier_blkno = blkno + 1; } } return 0; } /*********************************************************** Stream open/close ***************************************************************/ int xd3_set_source (xd3_stream *stream, xd3_source *src) { usize_t shiftby; stream->src = src; src->srclen = 0; src->srcbase = 0; /* Enforce power-of-two blocksize so that source-block number * calculations are cheap. */ if (xd3_check_pow2 (src->blksize, &shiftby) != 0) { src->blksize = xd3_pow2_roundup(src->blksize); xd3_check_pow2 (src->blksize, &shiftby); IF_DEBUG1 (DP(RINT "raising src_blksz to %u\n", src->blksize)); } src->shiftby = shiftby; src->maskby = (1 << shiftby) - 1; if (xd3_check_pow2 (src->max_winsize, NULL) != 0) { src->max_winsize = xd3_xoff_roundup(src->max_winsize); IF_DEBUG1 (DP(RINT "raising src_maxsize to %u\n", src->blksize)); } src->max_winsize = max(src->max_winsize, XD3_ALLOCSIZE); return 0; } int xd3_set_source_and_size (xd3_stream *stream, xd3_source *user_source, xoff_t source_size) { int ret = xd3_set_source (stream, user_source); if (ret == 0) { stream->src->eof_known = 1; IF_DEBUG2 (DP(RINT "[set source] size known %"Q"u\n", source_size)); xd3_blksize_div(source_size, stream->src, &stream->src->max_blkno, &stream->src->onlastblk); } return ret; } void xd3_abort_stream (xd3_stream *stream) { stream->dec_state = DEC_ABORTED; stream->enc_state = ENC_ABORTED; } int xd3_close_stream (xd3_stream *stream) { if (stream->enc_state != 0 && stream->enc_state != ENC_ABORTED) { if (stream->buf_leftover != NULL) { stream->msg = "encoding is incomplete"; return XD3_INTERNAL; } if (stream->enc_state == ENC_POSTWIN) { #if XD3_ENCODER xd3_encode_reset (stream); #endif stream->current_window += 1; stream->enc_state = ENC_INPUT; } /* If encoding, should be ready for more input but not actually have any. */ if (stream->enc_state != ENC_INPUT || stream->avail_in != 0) { stream->msg = "encoding is incomplete"; return XD3_INTERNAL; } } else { switch (stream->dec_state) { case DEC_VCHEAD: case DEC_WININD: /* TODO: Address the zero-byte ambiguity. Does the encoder * emit a window or not? If so, then catch an error here. * If not, need another routine to say * decode_at_least_one_if_empty. */ case DEC_ABORTED: break; default: /* If decoding, should be ready for the next window. */ stream->msg = "EOF in decode"; return XD3_INTERNAL; } } return 0; } /************************************************************** Application header ****************************************************************/ int xd3_get_appheader (xd3_stream *stream, uint8_t **data, usize_t *size) { if (stream->dec_state < DEC_WININD) { stream->msg = "application header not available"; return XD3_INTERNAL; } (*data) = stream->dec_appheader; (*size) = stream->dec_appheadsz; return 0; } /********************************************************** Decoder stuff *************************************************/ #include "xdelta3-decode.h" /**************************************************************** Encoder stuff *****************************************************************/ #if XD3_ENCODER void xd3_set_appheader (xd3_stream *stream, const uint8_t *data, usize_t size) { stream->enc_appheader = data; stream->enc_appheadsz = size; } #if XD3_DEBUG static int xd3_iopt_check (xd3_stream *stream) { usize_t ul = xd3_rlist_length (& stream->iopt_used); usize_t fl = xd3_rlist_length (& stream->iopt_free); return (ul + fl + (stream->iout ? 1 : 0)) == stream->iopt_size; } #endif static xd3_rinst* xd3_iopt_free (xd3_stream *stream, xd3_rinst *i) { xd3_rinst *n = xd3_rlist_remove (i); xd3_rlist_push_back (& stream->iopt_free, i); return n; } static void xd3_iopt_free_nonadd (xd3_stream *stream, xd3_rinst *i) { if (i->type != XD3_ADD) { xd3_rlist_push_back (& stream->iopt_free, i); } } /* When an instruction is ready to flush from the iopt buffer, this * function is called to produce an encoding. It writes the * instruction plus size, address, and data to the various encoding * sections. */ static int xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst) { int ret; /* Check for input overflow. */ XD3_ASSERT (inst->pos + inst->size <= stream->avail_in); switch (inst->type) { case XD3_CPY: { /* the address may have an offset if there is a source window. */ usize_t addr; xd3_source *src = stream->src; if (src != NULL) { /* If there is a source copy, the source must have its * source window decided before we can encode. This can * be bad -- we have to make this decision even if no * source matches have been found. */ if (stream->srcwin_decided == 0) { if ((ret = xd3_srcwin_setup (stream))) { return ret; } } else { stream->srcwin_decided_early = (!stream->src->eof_known || (stream->srcwin_cksum_pos < xd3_source_eof (stream->src))); } /* xtra field indicates the copy is from the source */ if (inst->xtra) { XD3_ASSERT (inst->addr >= src->srcbase); XD3_ASSERT (inst->addr + inst->size <= src->srcbase + src->srclen); addr = (usize_t)(inst->addr - src->srcbase); stream->n_scpy += 1; stream->l_scpy += (xoff_t) inst->size; } else { /* with source window: target copy address is offset * by taroff. */ addr = stream->taroff + (usize_t) inst->addr; stream->n_tcpy += 1; stream->l_tcpy += (xoff_t) inst->size; } } else { addr = (usize_t) inst->addr; stream->n_tcpy += 1; stream->l_tcpy += inst->size; } /* Note: used to assert inst->size >= MIN_MATCH, but not true * for merge operations & identical match heuristics. */ /* the "here" position is always offset by taroff */ if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, & inst->type))) { return ret; } IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt copy:%d] pos %"Q"u-%"Q"u addr %"Q"u-%"Q"u size %u\n", cnt++, stream->total_in + inst->pos, stream->total_in + inst->pos + inst->size, inst->addr, inst->addr + inst->size, inst->size); }); break; } case XD3_RUN: { XD3_ASSERT (inst->size >= MIN_MATCH); if ((ret = xd3_emit_byte (stream, & DATA_TAIL (stream), inst->xtra))) { return ret; } stream->n_run += 1; stream->l_run += inst->size; IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt run:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); }); break; } case XD3_ADD: { if ((ret = xd3_emit_bytes (stream, & DATA_TAIL (stream), stream->next_in + inst->pos, inst->size))) { return ret; } stream->n_add += 1; stream->l_add += inst->size; IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt add:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); }); break; } } /* This is the only place stream->unencoded_offset is incremented. */ XD3_ASSERT (stream->unencoded_offset == inst->pos); stream->unencoded_offset += inst->size; inst->code2 = 0; XD3_CHOOSE_INSTRUCTION (stream, stream->iout, inst); if (stream->iout != NULL) { if (stream->iout->code2 != 0) { if ((ret = xd3_emit_double (stream, stream->iout, inst, stream->iout->code2))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); xd3_iopt_free_nonadd (stream, inst); stream->iout = NULL; return 0; } else { if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); } } stream->iout = inst; return 0; } /* This possibly encodes an add instruction, iadd, which must remain * on the stack until the following call to * xd3_iopt_finish_encoding. */ static int xd3_iopt_add (xd3_stream *stream, usize_t pos, xd3_rinst *iadd) { int ret; usize_t off = stream->unencoded_offset; if (pos > off) { iadd->type = XD3_ADD; iadd->pos = off; iadd->size = pos - off; if ((ret = xd3_iopt_finish_encoding (stream, iadd))) { return ret; } } return 0; } /* This function calls xd3_iopt_finish_encoding to finish encoding an * instruction, and it may also produce an add instruction for an * unmatched region. */ static int xd3_iopt_add_encoding (xd3_stream *stream, xd3_rinst *inst) { int ret; xd3_rinst iadd; if ((ret = xd3_iopt_add (stream, inst->pos, & iadd))) { return ret; } if ((ret = xd3_iopt_finish_encoding (stream, inst))) { return ret; } return 0; } /* Generates a final add instruction to encode the remaining input. */ static int xd3_iopt_add_finalize (xd3_stream *stream) { int ret; xd3_rinst iadd; if ((ret = xd3_iopt_add (stream, stream->avail_in, & iadd))) { return ret; } if (stream->iout) { if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); stream->iout = NULL; } return 0; } /* Compact the instruction buffer by choosing the best non-overlapping * instructions when lazy string-matching. There are no ADDs in the * iopt buffer because those are synthesized in xd3_iopt_add_encoding * and during xd3_iopt_add_finalize. */ static int xd3_iopt_flush_instructions (xd3_stream *stream, int force) { xd3_rinst *r1 = xd3_rlist_front (& stream->iopt_used); xd3_rinst *r2; xd3_rinst *r3; usize_t r1end; usize_t r2end; usize_t r2off; usize_t r2moff; usize_t gap; usize_t flushed; int ret; XD3_ASSERT (xd3_iopt_check (stream)); /* Note: once tried to skip this step if it's possible to assert * there are no overlapping instructions. Doesn't work because * xd3_opt_erase leaves overlapping instructions. */ while (! xd3_rlist_end (& stream->iopt_used, r1) && ! xd3_rlist_end (& stream->iopt_used, r2 = xd3_rlist_next (r1))) { r1end = r1->pos + r1->size; /* If the instructions do not overlap, continue. */ if (r1end <= r2->pos) { r1 = r2; continue; } r2end = r2->pos + r2->size; /* The min_match adjustments prevent this. */ XD3_ASSERT (r2end > (r1end + LEAST_MATCH_INCR)); /* If r3 is available... */ if (! xd3_rlist_end (& stream->iopt_used, r3 = xd3_rlist_next (r2))) { /* If r3 starts before r1 finishes or just about, r2 is irrelevant */ if (r3->pos <= r1end + 1) { xd3_iopt_free (stream, r2); continue; } } else if (! force) { /* Unless force, end the loop when r3 is not available. */ break; } r2off = r2->pos - r1->pos; r2moff = r2end - r1end; gap = r2end - r1->pos; /* If the two matches overlap almost entirely, choose the better match * and discard the other. The else branch can still create inefficient * copies, e.g., a 4-byte copy that takes 4 bytes to encode, which * xd3_smatch() wouldn't allow by its crude efficiency check. However, * in this case there are adjacent copies which mean the add would cost * one extra byte. Allow the inefficiency here. */ if (gap < 2*MIN_MATCH || r2moff <= 2 || r2off <= 2) { /* Only one match should be used, choose the longer one. */ if (r1->size < r2->size) { xd3_iopt_free (stream, r1); r1 = r2; } else { /* We are guaranteed that r1 does not overlap now, so advance past r2 */ r1 = xd3_iopt_free (stream, r2); } continue; } else { /* Shorten one of the instructions -- could be optimized * based on the address cache. */ usize_t average; usize_t newsize; usize_t adjust1; XD3_ASSERT (r1end > r2->pos && r2end > r1->pos); /* Try to balance the length of both instructions, but avoid * making both longer than MAX_MATCH_SPLIT . */ average = gap / 2; newsize = min (MAX_MATCH_SPLIT, gap - average); /* Should be possible to simplify this code. */ if (newsize > r1->size) { /* shorten r2 */ adjust1 = r1end - r2->pos; } else if (newsize > r2->size) { /* shorten r1 */ adjust1 = r1end - r2->pos; XD3_ASSERT (r1->size > adjust1); r1->size -= adjust1; /* don't shorten r2 */ adjust1 = 0; } else { /* shorten r1 */ adjust1 = r1->size - newsize; if (r2->pos > r1end - adjust1) { adjust1 -= r2->pos - (r1end - adjust1); } XD3_ASSERT (r1->size > adjust1); r1->size -= adjust1; /* shorten r2 */ XD3_ASSERT (r1->pos + r1->size >= r2->pos); adjust1 = r1->pos + r1->size - r2->pos; } /* Fallthrough above if-else, shorten r2 */ XD3_ASSERT (r2->size > adjust1); r2->size -= adjust1; r2->pos += adjust1; r2->addr += adjust1; XD3_ASSERT (r1->size >= MIN_MATCH); XD3_ASSERT (r2->size >= MIN_MATCH); r1 = r2; } } XD3_ASSERT (xd3_iopt_check (stream)); /* If forcing, pick instructions until the list is empty, otherwise * this empties 50% of the queue. */ for (flushed = 0; ! xd3_rlist_empty (& stream->iopt_used); ) { xd3_rinst *renc = xd3_rlist_pop_front (& stream->iopt_used); if ((ret = xd3_iopt_add_encoding (stream, renc))) { return ret; } if (! force) { if (++flushed > stream->iopt_size / 2) { break; } /* If there are only two instructions remaining, break, * because they were not optimized. This means there were * more than 50% eliminated by the loop above. */ r1 = xd3_rlist_front (& stream->iopt_used); if (xd3_rlist_end(& stream->iopt_used, r1) || xd3_rlist_end(& stream->iopt_used, r2 = xd3_rlist_next (r1)) || xd3_rlist_end(& stream->iopt_used, r3 = xd3_rlist_next (r2))) { break; } } } XD3_ASSERT (xd3_iopt_check (stream)); XD3_ASSERT (!force || xd3_rlist_length (& stream->iopt_used) == 0); return 0; } static int xd3_iopt_get_slot (xd3_stream *stream, xd3_rinst** iptr) { xd3_rinst *i; int ret; if (xd3_rlist_empty (& stream->iopt_free)) { if (stream->iopt_unlimited) { usize_t elts = XD3_ALLOCSIZE / sizeof(xd3_rinst); if ((ret = xd3_alloc_iopt (stream, elts))) { return ret; } stream->iopt_size += elts; } else { if ((ret = xd3_iopt_flush_instructions (stream, 0))) { return ret; } XD3_ASSERT (! xd3_rlist_empty (& stream->iopt_free)); } } i = xd3_rlist_pop_back (& stream->iopt_free); xd3_rlist_push_back (& stream->iopt_used, i); (*iptr) = i; ++stream->i_slots_used; return 0; } /* A copy is about to be emitted that extends backwards to POS, * therefore it may completely cover some existing instructions in the * buffer. If an instruction is completely covered by this new match, * erase it. If the new instruction is covered by the previous one, * return 1 to skip it. */ static void xd3_iopt_erase (xd3_stream *stream, usize_t pos, usize_t size) { while (! xd3_rlist_empty (& stream->iopt_used)) { xd3_rinst *r = xd3_rlist_back (& stream->iopt_used); /* Verify that greedy is working. The previous instruction * should end before the new one begins. */ XD3_ASSERT ((stream->flags & XD3_BEGREEDY) == 0 || (r->pos + r->size <= pos)); /* Verify that min_match is working. The previous instruction * should end before the new one ends. */ XD3_ASSERT ((stream->flags & XD3_BEGREEDY) != 0 || (r->pos + r->size < pos + size)); /* See if the last instruction starts before the new * instruction. If so, there is nothing to erase. */ if (r->pos < pos) { return; } /* Otherwise, the new instruction covers the old one, delete it and repeat. */ xd3_rlist_remove (r); xd3_rlist_push_back (& stream->iopt_free, r); --stream->i_slots_used; } } /* This function tells the last matched input position. */ static usize_t xd3_iopt_last_matched (xd3_stream *stream) { xd3_rinst *r; if (xd3_rlist_empty (& stream->iopt_used)) { return 0; } r = xd3_rlist_back (& stream->iopt_used); return r->pos + r->size; } /********************************************************* Emit routines ***********************************************************/ static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, usize_t code) { int has_size = stream->code_table[code].size1 == 0; int ret; IF_DEBUG2 (DP(RINT "[emit1] %u %s (%u) code %u\n", single->pos, xd3_rtype_to_string ((xd3_rtype) single->type, 0), single->size, code)); if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) { return ret; } if (has_size) { if ((ret = xd3_emit_size (stream, & INST_TAIL (stream), single->size))) { return ret; } } return 0; } static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_rinst *second, usize_t code) { int ret; /* All double instructions use fixed sizes, so all we need to do is * output the instruction code, no sizes. */ XD3_ASSERT (stream->code_table[code].size1 != 0 && stream->code_table[code].size2 != 0); if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) { return ret; } IF_DEBUG2 (DP(RINT "[emit2]: %u %s (%u) %s (%u) code %u\n", first->pos, xd3_rtype_to_string ((xd3_rtype) first->type, 0), first->size, xd3_rtype_to_string ((xd3_rtype) second->type, 0), second->size, code)); return 0; } /* This enters a potential run instruction into the iopt buffer. The * position argument is relative to the target window. */ static int xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c) { xd3_rinst* ri; int ret; if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } ri->type = XD3_RUN; ri->xtra = *run_c; ri->pos = pos; ri->size = size; return 0; } /* This enters a potential copy instruction into the iopt buffer. The * position argument is relative to the target window.. */ int xd3_found_match (xd3_stream *stream, usize_t pos, usize_t size, xoff_t addr, int is_source) { xd3_rinst* ri; int ret; if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } ri->type = XD3_CPY; ri->xtra = is_source; ri->pos = pos; ri->size = size; ri->addr = addr; return 0; } static int xd3_emit_hdr (xd3_stream *stream) { int ret; int use_secondary = stream->sec_type != NULL; int use_adler32 = stream->flags & (XD3_ADLER32 | XD3_ADLER32_RECODE); int vcd_source = xd3_encoder_used_source (stream); usize_t win_ind = 0; usize_t del_ind = 0; usize_t enc_len; usize_t tgt_len; usize_t data_len; usize_t inst_len; usize_t addr_len; if (stream->current_window == 0) { usize_t hdr_ind = 0; int use_appheader = stream->enc_appheader != NULL; int use_gencodetbl = GENERIC_ENCODE_TABLES && (stream->code_table_desc != & __rfc3284_code_table_desc); if (use_secondary) { hdr_ind |= VCD_SECONDARY; } if (use_gencodetbl) { hdr_ind |= VCD_CODETABLE; } if (use_appheader) { hdr_ind |= VCD_APPHEADER; } if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC1)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC2)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC3)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_VERSION)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), hdr_ind)) != 0) { return ret; } /* Secondary compressor ID */ #if SECONDARY_ANY if (use_secondary && (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->sec_type->id))) { return ret; } #endif /* Compressed code table */ if (use_gencodetbl) { usize_t code_table_size; const uint8_t *code_table_data; if ((ret = stream->comp_table_func (stream, & code_table_data, & code_table_size))) { return ret; } if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), code_table_size + 2)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->code_table_desc->near_modes)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->code_table_desc->same_modes)) || (ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), code_table_data, code_table_size))) { return ret; } } /* Application header */ if (use_appheader) { if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), stream->enc_appheadsz)) || (ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), stream->enc_appheader, stream->enc_appheadsz))) { return ret; } } } /* try to compress this window */ #if SECONDARY_ANY if (use_secondary) { int data_sec = 0; int inst_sec = 0; int addr_sec = 0; # define ENCODE_SECONDARY_SECTION(UPPER,LOWER) \ ((stream->flags & XD3_SEC_NO ## UPPER) == 0 && \ (ret = xd3_encode_secondary (stream, \ & UPPER ## _HEAD (stream), \ & UPPER ## _TAIL (stream), \ & xd3_sec_ ## LOWER (stream), \ & stream->sec_ ## LOWER, \ & LOWER ## _sec))) if (ENCODE_SECONDARY_SECTION (DATA, data) || ENCODE_SECONDARY_SECTION (INST, inst) || ENCODE_SECONDARY_SECTION (ADDR, addr)) { return ret; } del_ind |= (data_sec ? VCD_DATACOMP : 0); del_ind |= (inst_sec ? VCD_INSTCOMP : 0); del_ind |= (addr_sec ? VCD_ADDRCOMP : 0); } #endif /* if (vcd_target) { win_ind |= VCD_TARGET; } */ if (vcd_source) { win_ind |= VCD_SOURCE; } if (use_adler32) { win_ind |= VCD_ADLER32; } /* window indicator */ if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), win_ind))) { return ret; } /* source window */ if (vcd_source) { /* or (vcd_target) { ... } */ if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), stream->src->srclen)) || (ret = xd3_emit_offset (stream, & HDR_TAIL (stream), stream->src->srcbase))) { return ret; } } tgt_len = stream->avail_in; data_len = xd3_sizeof_output (DATA_HEAD (stream)); inst_len = xd3_sizeof_output (INST_HEAD (stream)); addr_len = xd3_sizeof_output (ADDR_HEAD (stream)); /* The enc_len field is a redundency for future extensions.*/ enc_len = (1 + (xd3_sizeof_size (tgt_len) + xd3_sizeof_size (data_len) + xd3_sizeof_size (inst_len) + xd3_sizeof_size (addr_len)) + data_len + inst_len + addr_len + (use_adler32 ? 4 : 0)); if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), enc_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), tgt_len)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), del_ind)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), data_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), inst_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), addr_len))) { return ret; } if (use_adler32) { uint8_t send[4]; uint32_t a32; if (stream->flags & XD3_ADLER32) { a32 = adler32 (1L, stream->next_in, stream->avail_in); } else { a32 = stream->recode_adler32; } /* Four bytes. */ send[0] = (uint8_t) (a32 >> 24); send[1] = (uint8_t) (a32 >> 16); send[2] = (uint8_t) (a32 >> 8); send[3] = (uint8_t) (a32 & 0x000000FFU); if ((ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), send, 4))) { return ret; } } return 0; } /**************************************************************** Encode routines ****************************************************************/ static int xd3_encode_buffer_leftover (xd3_stream *stream) { usize_t take; usize_t room; /* Allocate the buffer. */ if (stream->buf_in == NULL && (stream->buf_in = (uint8_t*) xd3_alloc (stream, stream->winsize, 1)) == NULL) { return ENOMEM; } IF_DEBUG2 (DP(RINT "[leftover] flush?=%s\n", (stream->flags & XD3_FLUSH) ? "yes" : "no")); /* Take leftover input first. */ if (stream->buf_leftover != NULL) { XD3_ASSERT (stream->buf_avail == 0); XD3_ASSERT (stream->buf_leftavail < stream->winsize); IF_DEBUG2 (DP(RINT "[leftover] previous %u avail %u\n", stream->buf_leftavail, stream->avail_in)); memcpy (stream->buf_in, stream->buf_leftover, stream->buf_leftavail); stream->buf_leftover = NULL; stream->buf_avail = stream->buf_leftavail; } /* Copy into the buffer. */ room = stream->winsize - stream->buf_avail; take = min (room, stream->avail_in); memcpy (stream->buf_in + stream->buf_avail, stream->next_in, take); stream->buf_avail += take; if (take < stream->avail_in) { /* Buffer is full */ stream->buf_leftover = stream->next_in + take; stream->buf_leftavail = stream->avail_in - take; } else if ((stream->buf_avail < stream->winsize) && !(stream->flags & XD3_FLUSH)) { /* Buffer has space */ IF_DEBUG2 (DP(RINT "[leftover] emptied %u\n", take)); return XD3_INPUT; } /* Use the buffer: */ IF_DEBUG2 (DP(RINT "[leftover] take %u remaining %u\n", take, stream->buf_leftavail)); stream->next_in = stream->buf_in; stream->avail_in = stream->buf_avail; stream->buf_avail = 0; return 0; } /* Allocates one block of xd3_rlist elements */ static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts) { usize_t i; xd3_iopt_buflist* last = (xd3_iopt_buflist*) xd3_alloc (stream, sizeof (xd3_iopt_buflist), 1); if (last == NULL || (last->buffer = (xd3_rinst*) xd3_alloc (stream, sizeof (xd3_rinst), elts)) == NULL) { return ENOMEM; } last->next = stream->iopt_alloc; stream->iopt_alloc = last; for (i = 0; i < elts; i += 1) { xd3_rlist_push_back (& stream->iopt_free, & last->buffer[i]); } return 0; } /* This function allocates all memory initially used by the encoder. */ static int xd3_encode_init (xd3_stream *stream, int full_init) { int i; if (full_init) { int large_comp = (stream->src != NULL); int small_comp = ! (stream->flags & XD3_NOCOMPRESS); /* Memory allocations for checksum tables are delayed until * xd3_string_match_init in the first call to string_match--that way * identical or short inputs require no table allocation. */ if (large_comp) { usize_t hash_values = (stream->src->max_winsize / stream->smatcher.large_step); xd3_size_hashtable (stream, hash_values, & stream->large_hash); } if (small_comp) { /* TODO: This is under devel: used to have min(sprevsz) here, which sort * of makes sense, but observed fast performance w/ larger tables, which * also sort of makes sense. @@@ */ usize_t hash_values = stream->winsize; xd3_size_hashtable (stream, hash_values, & stream->small_hash); } } /* data buffers */ for (i = 0; i < ENC_SECTS; i += 1) { if ((stream->enc_heads[i] = stream->enc_tails[i] = xd3_alloc_output (stream, NULL)) == NULL) { return ENOMEM; } } /* iopt buffer */ xd3_rlist_init (& stream->iopt_used); xd3_rlist_init (& stream->iopt_free); if (xd3_alloc_iopt (stream, stream->iopt_size) != 0) { goto fail; } XD3_ASSERT (xd3_rlist_length (& stream->iopt_free) == stream->iopt_size); XD3_ASSERT (xd3_rlist_length (& stream->iopt_used) == 0); /* address cache, code table */ stream->acache.s_near = stream->code_table_desc->near_modes; stream->acache.s_same = stream->code_table_desc->same_modes; stream->code_table = stream->code_table_func (); return xd3_alloc_cache (stream); fail: return ENOMEM; } int xd3_encode_init_full (xd3_stream *stream) { return xd3_encode_init (stream, 1); } int xd3_encode_init_partial (xd3_stream *stream) { return xd3_encode_init (stream, 0); } /* Called after the ENC_POSTOUT state, this puts the output buffers * back into separate lists and re-initializes some variables. (The * output lists were spliced together during the ENC_FLUSH state.) */ static void xd3_encode_reset (xd3_stream *stream) { int i; xd3_output *olist; stream->avail_in = 0; stream->small_reset = 1; stream->i_slots_used = 0; if (stream->src != NULL) { stream->src->srcbase = 0; stream->src->srclen = 0; stream->srcwin_decided = 0; stream->srcwin_decided_early = 0; stream->match_minaddr = 0; stream->match_maxaddr = 0; stream->taroff = 0; } /* Reset output chains. */ olist = stream->enc_heads[0]; for (i = 0; i < ENC_SECTS; i += 1) { XD3_ASSERT (olist != NULL); stream->enc_heads[i] = olist; stream->enc_tails[i] = olist; olist = olist->next_page; stream->enc_heads[i]->next = 0; stream->enc_heads[i]->next_page = NULL; stream->enc_tails[i]->next_page = NULL; stream->enc_tails[i] = stream->enc_heads[i]; } xd3_freelist_output (stream, olist); } /* The main encoding routine. */ int xd3_encode_input (xd3_stream *stream) { int ret, i; if (stream->dec_state != 0) { stream->msg = "encoder/decoder transition"; return XD3_INTERNAL; } switch (stream->enc_state) { case ENC_INIT: /* Only reached on first time through: memory setup. */ if ((ret = xd3_encode_init_full (stream))) { return ret; } stream->enc_state = ENC_INPUT; case ENC_INPUT: /* If there is no input yet, just return. This checks for * next_in == NULL, not avail_in == 0 since zero bytes is a * valid input. There is an assertion in xd3_avail_input() that * next_in != NULL for this reason. By returning right away we * avoid creating an input buffer before the caller has supplied * its first data. It is possible for xd3_avail_input to be * called both before and after the first call to * xd3_encode_input(). */ if (stream->next_in == NULL) { return XD3_INPUT; } enc_flush: /* See if we should buffer the input: either if there is already * a leftover buffer, or if the input is short of winsize * without flush. The label at this point is reached by a goto * below, when there is leftover input after postout. */ if ((stream->buf_leftover != NULL) || (stream->buf_avail != 0) || (stream->avail_in < stream->winsize && ! (stream->flags & XD3_FLUSH))) { if ((ret = xd3_encode_buffer_leftover (stream))) { return ret; } } /* Initalize the address cache before each window. */ xd3_init_cache (& stream->acache); stream->input_position = 0; stream->min_match = MIN_MATCH; stream->unencoded_offset = 0; stream->enc_state = ENC_SEARCH; IF_DEBUG2 (DP(RINT "[WINSTART:%"Q"u] input bytes %u offset %"Q"u\n", stream->current_window, stream->avail_in, stream->total_in)); return XD3_WINSTART; case ENC_SEARCH: IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %u %s\n", stream->match_state, stream->avail_in, stream->src ? "source" : "no source")); /* Reentrant matching. */ if (stream->src != NULL) { switch (stream->match_state) { case MATCH_TARGET: /* Try matching forward at the start of the target. * This is entered the first time through, to check for * a perfect match, and whenever there is a source match * that extends to the end of the previous window. The * match_srcpos field is initially zero and later set * during xd3_source_extend_match. */ if (stream->avail_in > 0) { /* This call can't fail because the source window is * unrestricted. */ ret = xd3_source_match_setup (stream, stream->match_srcpos); XD3_ASSERT (ret == 0); stream->match_state = MATCH_FORWARD; } else { stream->match_state = MATCH_SEARCHING; stream->match_fwd = 0; } XD3_ASSERT (stream->match_fwd == 0); case MATCH_FORWARD: case MATCH_BACKWARD: if (stream->avail_in != 0) { if ((ret = xd3_source_extend_match (stream)) != 0) { return ret; } /* The search has to make forward progress here * or else it can get stuck in a match-backward * (getsrcblk) then match-forward (getsrcblk), * find insufficient match length, then repeat * exactly the same search. */ stream->input_position += stream->match_fwd; } case MATCH_SEARCHING: /* Continue string matching. (It's possible that the * initial match continued through the entire input, in * which case we're still in MATCH_FORWARD and should * remain so for the next input window.) */ break; } } /* String matching... */ if (stream->avail_in != 0 && (ret = stream->smatcher.string_match (stream))) { return ret; } stream->enc_state = ENC_INSTR; case ENC_INSTR: /* Note: Jump here to encode VCDIFF deltas w/o using this * string-matching code. Merging code code enters here. */ /* Flush the instrution buffer, then possibly add one more * instruction, then emit the header. */ if ((ret = xd3_iopt_flush_instructions (stream, 1)) || (ret = xd3_iopt_add_finalize (stream))) { return ret; } stream->enc_state = ENC_FLUSH; case ENC_FLUSH: /* Note: main_recode_func() bypasses string-matching by setting * ENC_FLUSH. */ if ((ret = xd3_emit_hdr (stream))) { return ret; } /* Begin output. */ stream->enc_current = HDR_HEAD (stream); /* Chain all the outputs together. After doing this, it looks * as if there is only one section. The other enc_heads are set * to NULL to avoid freeing them more than once. */ for (i = 1; i < ENC_SECTS; i += 1) { stream->enc_tails[i-1]->next_page = stream->enc_heads[i]; stream->enc_heads[i] = NULL; } enc_output: stream->enc_state = ENC_POSTOUT; stream->next_out = stream->enc_current->base; stream->avail_out = stream->enc_current->next; stream->total_out += (xoff_t) stream->avail_out; /* If there is any output in this buffer, return it, otherwise * fall through to handle the next buffer or finish the window * after all buffers have been output. */ if (stream->avail_out > 0) { /* This is the only place xd3_encode returns XD3_OUTPUT */ return XD3_OUTPUT; } case ENC_POSTOUT: if (stream->avail_out != 0) { stream->msg = "missed call to consume output"; return XD3_INTERNAL; } /* Continue outputting one buffer at a time, until the next is NULL. */ if ((stream->enc_current = stream->enc_current->next_page) != NULL) { goto enc_output; } stream->total_in += (xoff_t) stream->avail_in; stream->enc_state = ENC_POSTWIN; IF_DEBUG2 (DP(RINT "[WINFINISH:%"Q"u] in=%"Q"u\n", stream->current_window, stream->total_in)); return XD3_WINFINISH; case ENC_POSTWIN: xd3_encode_reset (stream); stream->current_window += 1; stream->enc_state = ENC_INPUT; /* If there is leftover input to flush, repeat. */ if (stream->buf_leftover != NULL) { goto enc_flush; } /* Ready for more input. */ return XD3_INPUT; default: stream->msg = "invalid state"; return XD3_INTERNAL; } } #endif /* XD3_ENCODER */ /***************************************************************** Client convenience functions ******************************************************************/ static int xd3_process_stream (int is_encode, xd3_stream *stream, int (*func) (xd3_stream *), int close_stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { usize_t ipos = 0; usize_t n = min(stream->winsize, input_size); (*output_size) = 0; stream->flags |= XD3_FLUSH; xd3_avail_input (stream, input + ipos, n); ipos += n; for (;;) { int ret; switch((ret = func (stream))) { case XD3_OUTPUT: { /* memcpy below */ break; } case XD3_INPUT: { n = min(stream->winsize, input_size - ipos); if (n == 0) { goto done; } xd3_avail_input (stream, input + ipos, n); ipos += n; continue; } case XD3_GOTHEADER: { /* ignore */ continue; } case XD3_WINSTART: { /* ignore */ continue; } case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: { stream->msg = "stream requires source input"; return XD3_INTERNAL; } case 0: { /* xd3_encode_input/xd3_decode_input never return 0 */ stream->msg = "invalid return: 0"; return XD3_INTERNAL; } default: return ret; } if (*output_size + stream->avail_out > output_size_max) { stream->msg = "insufficient output space"; return ENOSPC; } memcpy (output + *output_size, stream->next_out, stream->avail_out); *output_size += stream->avail_out; xd3_consume_output (stream); } done: return (close_stream == 0) ? 0 : xd3_close_stream (stream); } static int xd3_process_memory (int is_encode, int (*func) (xd3_stream *), int close_stream, const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { xd3_stream stream; xd3_config config; xd3_source src; int ret; memset (& stream, 0, sizeof (stream)); memset (& config, 0, sizeof (config)); if (input == NULL || output == NULL) { stream.msg = "invalid input/output buffer"; ret = XD3_INTERNAL; goto exit; } config.flags = flags; if (is_encode) { config.winsize = min(input_size, (usize_t) XD3_DEFAULT_WINSIZE); config.iopt_size = min(input_size / 32, XD3_DEFAULT_IOPT_SIZE); config.iopt_size = max(config.iopt_size, 128U); config.sprevsz = xd3_pow2_roundup (config.winsize); } if ((ret = xd3_config_stream (&stream, &config)) != 0) { goto exit; } if (source != NULL) { memset (& src, 0, sizeof (src)); src.blksize = source_size; src.onblk = source_size; src.curblk = source; src.curblkno = 0; src.max_winsize = source_size; if ((ret = xd3_set_source_and_size (&stream, &src, source_size)) != 0) { goto exit; } } if ((ret = xd3_process_stream (is_encode, & stream, func, 1, input, input_size, output, output_size, output_size_max)) != 0) { goto exit; } exit: if (ret != 0) { IF_DEBUG2 (DP(RINT "process_memory: %d: %s\n", ret, stream.msg)); } xd3_free_stream(&stream); return ret; } int xd3_decode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { return xd3_process_stream (0, stream, & xd3_decode_input, 1, input, input_size, output, output_size, output_size_max); } int xd3_decode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { return xd3_process_memory (0, & xd3_decode_input, 1, input, input_size, source, source_size, output, output_size, output_size_max, flags); } #if XD3_ENCODER int xd3_encode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { return xd3_process_stream (1, stream, & xd3_encode_input, 1, input, input_size, output, output_size, output_size_max); } int xd3_encode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { return xd3_process_memory (1, & xd3_encode_input, 1, input, input_size, source, source_size, output, output_size, output_size_max, flags); } #endif /************************************************************* String matching helpers *************************************************************/ #if XD3_ENCODER /* Do the initial xd3_string_match() checksum table setup. * Allocations are delayed until first use to avoid allocation * sometimes (e.g., perfect matches, zero-length inputs). */ static int xd3_string_match_init (xd3_stream *stream) { const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS); const int DO_LARGE = (stream->src != NULL); if (DO_LARGE && stream->large_table == NULL) { if ((stream->large_table = (usize_t*) xd3_alloc0 (stream, stream->large_hash.size, sizeof (usize_t))) == NULL) { return ENOMEM; } } if (DO_SMALL) { /* Subsequent calls can return immediately after checking reset. */ if (stream->small_table != NULL) { /* The target hash table is reinitialized once per window. */ /* TODO: This would not have to be reinitialized if absolute * offsets were being stored. */ if (stream->small_reset) { stream->small_reset = 0; memset (stream->small_table, 0, sizeof (usize_t) * stream->small_hash.size); } return 0; } if ((stream->small_table = (usize_t*) xd3_alloc0 (stream, stream->small_hash.size, sizeof (usize_t))) == NULL) { return ENOMEM; } /* If there is a previous table needed. */ if (stream->smatcher.small_lchain > 1 || stream->smatcher.small_chain > 1) { if ((stream->small_prev = (xd3_slist*) xd3_alloc (stream, stream->sprevsz, sizeof (xd3_slist))) == NULL) { return ENOMEM; } } } return 0; } #if XD3_USE_LARGEFILE64 /* This function handles the 32/64bit ambiguity -- file positions are 64bit * but the hash table for source-offsets is 32bit. */ static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low) { xoff_t scp = stream->srcwin_cksum_pos; xoff_t s0 = scp >> 32; usize_t sr = (usize_t) scp; if (s0 == 0) { return low; } /* This should not be >= because srcwin_cksum_pos is the next * position to index. */ if (low > sr) { return (--s0 << 32) | low; } return (s0 << 32) | low; } #else static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low) { return (xoff_t) low; } #endif /* This function sets up the stream->src fields srcbase, srclen. The * call is delayed until these values are needed to encode a copy * address. At this point the decision has to be made. */ static int xd3_srcwin_setup (xd3_stream *stream) { xd3_source *src = stream->src; xoff_t length, x; /* Check the undecided state. */ XD3_ASSERT (src->srclen == 0 && src->srcbase == 0); /* Avoid repeating this call. */ stream->srcwin_decided = 1; /* If the stream is flushing, then the iopt buffer was able to * contain the complete encoding. If no copies were issued no * source window is actually needed. This prevents the VCDIFF * header from including source base/len. xd3_emit_hdr checks for * srclen == 0. */ if (stream->enc_state == ENC_INSTR && stream->match_maxaddr == 0) { goto done; } /* Check for overflow, srclen is usize_t - this can't happen unless * XD3_DEFAULT_SRCBACK and related parameters are extreme - should * use smaller windows. */ length = stream->match_maxaddr - stream->match_minaddr; x = (xoff_t) USIZE_T_MAX; if (length > x) { stream->msg = "source window length overflow (not 64bit)"; return XD3_INTERNAL; } /* If ENC_INSTR, then we know the exact source window to use because * no more copies can be issued. */ if (stream->enc_state == ENC_INSTR) { src->srcbase = stream->match_minaddr; src->srclen = (usize_t) length; XD3_ASSERT (src->srclen); goto done; } /* Otherwise, we have to make a guess. More copies may still be * issued, but we have to decide the source window base and length * now. */ src->srcbase = stream->match_minaddr; src->srclen = max ((usize_t) length, stream->avail_in + (stream->avail_in >> 2)); /* OPT: If we know the source size, it might be possible to reduce * srclen. */ XD3_ASSERT (src->srclen); done: /* Set the taroff. This convenience variable is used even when stream->src == NULL. */ stream->taroff = src->srclen; return 0; } /* Sets the bounding region for a newly discovered source match, prior * to calling xd3_source_extend_match(). This sets the match_maxfwd, * match_maxback variables. Note: srcpos is an absolute position * (xoff_t) but the match_maxfwd, match_maxback variables are usize_t. * Returns 0 if the setup succeeds, or 1 if the source position lies * outside an already-decided srcbase/srclen window. */ static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) { xd3_source *src = stream->src; usize_t greedy_or_not; xoff_t frontier_pos; stream->match_maxback = 0; stream->match_maxfwd = 0; stream->match_back = 0; stream->match_fwd = 0; /* This avoids a non-blocking endless loop caused by scanning * backwards across a block boundary, only to find not enough * matching bytes to beat the current min_match due to a better lazy * target match: the re-entry to xd3_string_match() repeats the same * long match because the input position hasn't changed. TODO: if * ever duplicates are added to the source hash table, this logic * won't suffice to avoid loops. See testing/regtest.cc's * TestNonBlockingProgress test! */ if (srcpos != 0 && srcpos == stream->match_last_srcpos) { IF_DEBUG2(DP(RINT "[match_setup] looping failure\n")); goto bad; } /* Implement src->max_winsize, which prevents the encoder from seeking * back further than the LRU cache maintaining FIFO discipline, (to * avoid seeking). */ frontier_pos = stream->src->frontier_blkno * stream->src->blksize; IF_DEBUG2(DP(RINT "[match_setup] frontier_pos %"Q"u, srcpos %"Q"u, " "src->max_winsize %"Q"u\n", frontier_pos, srcpos, stream->src->max_winsize)); if (srcpos < frontier_pos && frontier_pos - srcpos > stream->src->max_winsize) { IF_DEBUG1(DP(RINT "[match_setup] rejected due to src->max_winsize " "distance eof=%"Q"u srcpos=%"Q"u maxsz=%"Q"u\n", xd3_source_eof (stream->src), srcpos, stream->src->max_winsize)); goto bad; } /* Going backwards, the 1.5-pass algorithm allows some * already-matched input may be covered by a longer source match. * The greedy algorithm does not allow this. */ if (stream->flags & XD3_BEGREEDY) { /* The greedy algorithm allows backward matching to the last matched position. */ greedy_or_not = xd3_iopt_last_matched (stream); } else { /* The 1.5-pass algorithm allows backward matching to go back as * far as the unencoded offset, which is updated as instructions * pass out of the iopt buffer. If this (default) is chosen, it * means xd3_iopt_erase may be called to eliminate instructions * when a covering source match is found. */ greedy_or_not = stream->unencoded_offset; } /* Backward target match limit. */ XD3_ASSERT (stream->input_position >= greedy_or_not); stream->match_maxback = stream->input_position - greedy_or_not; /* Forward target match limit. */ XD3_ASSERT (stream->avail_in > stream->input_position); stream->match_maxfwd = stream->avail_in - stream->input_position; /* Now we take the source position into account. It depends whether * the srclen/srcbase have been decided yet. */ if (stream->srcwin_decided == 0) { /* Unrestricted case: the match can cover the entire source, * 0--src->size. We compare the usize_t * match_maxfwd/match_maxback against the xoff_t * src->size/srcpos values and take the min. */ if (srcpos < (xoff_t) stream->match_maxback) { stream->match_maxback = (usize_t) srcpos; } if (stream->src->eof_known) { xoff_t srcavail = xd3_source_eof (stream->src) - srcpos; if (srcavail < (xoff_t) stream->match_maxfwd) { stream->match_maxfwd = (usize_t) srcavail; } } IF_DEBUG2(DP(RINT "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "unrestricted maxback %u maxfwd %u\n", srcpos, stream->total_in + stream->input_position, stream->match_maxback, stream->match_maxfwd)); goto good; } /* Decided some source window. */ XD3_ASSERT (src->srclen > 0); /* Restricted case: fail if the srcpos lies outside the source window */ if ((srcpos < src->srcbase) || (srcpos > (src->srcbase + (xoff_t) src->srclen))) { IF_DEBUG1(DP(RINT "[match_setup] restricted source window failure\n")); goto bad; } else { usize_t srcavail; srcavail = (usize_t) (srcpos - src->srcbase); if (srcavail < stream->match_maxback) { stream->match_maxback = srcavail; } srcavail = (usize_t) (src->srcbase + (xoff_t) src->srclen - srcpos); if (srcavail < stream->match_maxfwd) { stream->match_maxfwd = srcavail; } IF_DEBUG1(DP(RINT "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "restricted maxback %u maxfwd %u\n", srcpos, stream->total_in + stream->input_position, stream->match_maxback, stream->match_maxfwd)); goto good; } good: stream->match_state = MATCH_BACKWARD; stream->match_srcpos = srcpos; stream->match_last_srcpos = srcpos; return 0; bad: stream->match_state = MATCH_SEARCHING; return 1; } static inline int xd3_forward_match(const uint8_t *s1c, const uint8_t *s2c, int n) { int i = 0; #if UNALIGNED_OK int nint = n / sizeof(int); if (nint >> 3) { int j = 0; const int *s1 = (const int*)s1c; const int *s2 = (const int*)s2c; int nint_8 = nint - 8; while (i <= nint_8 && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++]) { } i = (i - 1) * sizeof(int); } #endif while (i < n && s1c[i] == s2c[i]) { i++; } return i; } /* This function expands the source match backward and forward. It is * reentrant, since xd3_getblk may return XD3_GETSRCBLK, so most * variables are kept in xd3_stream. There are two callers of this * function, the string_matching routine when a checksum match is * discovered, and xd3_encode_input whenever a continuing (or initial) * match is suspected. The two callers do different things with the * input_position, thus this function leaves that variable untouched. * If a match is taken the resulting stream->match_fwd is left * non-zero. */ static int xd3_source_extend_match (xd3_stream *stream) { int ret; xd3_source *src = stream->src; xoff_t matchoff; /* matchoff is the current right/left-boundary of the source match being tested. */ usize_t streamoff; /* streamoff is the current right/left-boundary of the input match being tested. */ xoff_t tryblk; /* tryblk, tryoff are the block, offset position of matchoff */ usize_t tryoff; usize_t tryrem; /* tryrem is the number of matchable bytes */ usize_t matched; IF_DEBUG2(DP(RINT "[extend match] srcpos %"Q"u\n", stream->match_srcpos)); XD3_ASSERT (src != NULL); /* Does it make sense to compute backward match AFTER forward match? */ if (stream->match_state == MATCH_BACKWARD) { /* Note: this code is practically duplicated below, substituting * match_fwd/match_back and direction. TODO: Consolidate? */ matchoff = stream->match_srcpos - stream->match_back; streamoff = stream->input_position - stream->match_back; xd3_blksize_div (matchoff, src, &tryblk, &tryoff); /* this loops backward over source blocks */ while (stream->match_back < stream->match_maxback) { /* see if we're backing across a source block boundary */ if (tryoff == 0) { tryoff = src->blksize; tryblk -= 1; } if ((ret = xd3_getblk (stream, tryblk))) { /* if search went too far back, continue forward. */ if (ret == XD3_TOOFARBACK) { break; } /* could be a XD3_GETSRCBLK failure. */ return ret; } tryrem = min (tryoff, stream->match_maxback - stream->match_back); IF_DEBUG2(DP(RINT "[maxback] maxback %u trysrc %"Q"u/%u tgt %u tryrem %u\n", stream->match_maxback, tryblk, tryoff, streamoff, tryrem)); /* TODO: This code can be optimized similar to xd3_match_forward() */ for (; tryrem != 0; tryrem -= 1, stream->match_back += 1) { if (src->curblk[tryoff-1] != stream->next_in[streamoff-1]) { goto doneback; } tryoff -= 1; streamoff -= 1; } } doneback: stream->match_state = MATCH_FORWARD; } XD3_ASSERT (stream->match_state == MATCH_FORWARD); matchoff = stream->match_srcpos + stream->match_fwd; streamoff = stream->input_position + stream->match_fwd; xd3_blksize_div (matchoff, src, & tryblk, & tryoff); /* Note: practically the same code as backwards case above: same comments */ while (stream->match_fwd < stream->match_maxfwd) { if (tryoff == src->blksize) { tryoff = 0; tryblk += 1; } if ((ret = xd3_getblk (stream, tryblk))) { /* if search went too far back, continue forward. */ if (ret == XD3_TOOFARBACK) { break; } /* could be a XD3_GETSRCBLK failure. */ return ret; } tryrem = min(stream->match_maxfwd - stream->match_fwd, src->onblk - tryoff); if (tryrem == 0) { /* Generally, this means we have a power-of-two size source * and we just found the end-of-file, in this case it's an * empty block. */ XD3_ASSERT (src->onblk < src->blksize); break; } matched = xd3_forward_match(src->curblk + tryoff, stream->next_in + streamoff, tryrem); tryoff += matched; streamoff += matched; stream->match_fwd += matched; if (tryrem != matched) { break; } } stream->match_state = MATCH_SEARCHING; /* If the match ends short of the last instruction end, we probably * don't want it. There is the possibility that a copy ends short * of the last copy but also goes further back, in which case we * might want it. This code does not implement such: if so we would * need more complicated xd3_iopt_erase logic. */ if (stream->match_fwd < stream->min_match) { stream->match_fwd = 0; } else { usize_t total = stream->match_fwd + stream->match_back; /* Correct the variables to remove match_back from the equation. */ usize_t target_position = stream->input_position - stream->match_back; usize_t match_length = stream->match_back + stream->match_fwd; xoff_t match_position = stream->match_srcpos - stream->match_back; xoff_t match_end = stream->match_srcpos + stream->match_fwd; /* At this point we may have to erase any iopt-buffer * instructions that are fully covered by a backward-extending * copy. */ if (stream->match_back > 0) { xd3_iopt_erase (stream, target_position, total); } stream->match_back = 0; /* Update ranges. The first source match occurs with both values set to 0. */ if (stream->match_maxaddr == 0 || match_position < stream->match_minaddr) { stream->match_minaddr = match_position; } if (match_end > stream->match_maxaddr) { /* Note: per-window */ stream->match_maxaddr = match_end; } if (match_end > stream->maxsrcaddr) { /* Note: across windows */ stream->maxsrcaddr = match_end; } IF_DEBUG2 ({ static int x = 0; DP(RINT "[source match:%d] (%s) [ %u bytes ]\n", x++, stream->total_in + target_position, stream->total_in + target_position + match_length, match_position, match_position + match_length, (stream->total_in + target_position == match_position) ? "same" : "diff", match_length); }); if ((ret = xd3_found_match (stream, /* decoder position */ target_position, /* length */ match_length, /* address */ match_position, /* is_source */ 1))) { return ret; } /* If the match ends with the available input: */ if (target_position + match_length == stream->avail_in) { /* Setup continuing match for the next window. */ stream->match_state = MATCH_TARGET; stream->match_srcpos = match_end; } } return 0; } /* Update the small hash. Values in the small_table are offset by * HASH_CKOFFSET (1) to distinguish empty buckets from real offsets. */ static void xd3_scksum_insert (xd3_stream *stream, usize_t inx, usize_t scksum, usize_t pos) { /* If we are maintaining previous duplicates. */ if (stream->small_prev) { usize_t last_pos = stream->small_table[inx]; xd3_slist *pos_list = & stream->small_prev[pos & stream->sprevmask]; /* Note last_pos is offset by HASH_CKOFFSET. */ pos_list->last_pos = last_pos; } /* Enter the new position into the hash bucket. */ stream->small_table[inx] = pos + HASH_CKOFFSET; } #if XD3_DEBUG static int xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0, const uint8_t *inp_max, usize_t cmp_len) { usize_t i; for (i = 0; i < cmp_len; i += 1) { XD3_ASSERT (ref0[i] == inp0[i]); } if (inp0 + cmp_len < inp_max) { XD3_ASSERT (inp0[i] != ref0[i]); } return 1; } #endif /* XD3_DEBUG */ /* When the hash table indicates a possible small string match, it * calls this routine to find the best match. The first matching * position is taken from the small_table, HASH_CKOFFSET is subtracted * to get the actual position. After checking that match, if previous * linked lists are in use (because stream->smatcher.small_chain > 1), * previous matches are tested searching for the longest match. If * (stream->min_match > MIN_MATCH) then a lazy match is in effect. */ static usize_t xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_offset) { usize_t cmp_len; usize_t match_length = 0; usize_t chain = (stream->min_match == MIN_MATCH ? stream->smatcher.small_chain : stream->smatcher.small_lchain); const uint8_t *inp_max = stream->next_in + stream->avail_in; const uint8_t *inp; const uint8_t *ref; SMALL_HASH_DEBUG1 (stream, stream->next_in + stream->input_position); XD3_ASSERT (stream->min_match + stream->input_position <= stream->avail_in); base -= HASH_CKOFFSET; again: IF_DEBUG2 (DP(RINT "smatch at base=%u inp=%u cksum=%u\n", base, stream->input_position, scksum)); /* For small matches, we can always go to the end-of-input because * the matching position must be less than the input position. */ XD3_ASSERT (base < stream->input_position); ref = stream->next_in + base; inp = stream->next_in + stream->input_position; SMALL_HASH_DEBUG2 (stream, ref); /* Expand potential match forward. */ while (inp < inp_max && *inp == *ref) { ++inp; ++ref; } cmp_len = (usize_t)(inp - (stream->next_in + stream->input_position)); /* Verify correctness */ XD3_ASSERT (xd3_check_smatch (stream->next_in + base, stream->next_in + stream->input_position, inp_max, cmp_len)); /* Update longest match */ if (cmp_len > match_length) { ( match_length) = cmp_len; (*match_offset) = base; /* Stop if we match the entire input or have a long_enough match. */ if (inp == inp_max || cmp_len >= stream->smatcher.long_enough) { goto done; } } /* If we have not reached the chain limit, see if there is another previous position. */ while (--chain != 0) { /* Calculate the previous offset. */ usize_t prev_pos = stream->small_prev[base & stream->sprevmask].last_pos; usize_t diff_pos; if (prev_pos == 0) { break; } prev_pos -= HASH_CKOFFSET; if (prev_pos > base) { break; } base = prev_pos; XD3_ASSERT (stream->input_position > base); diff_pos = stream->input_position - base; /* Stop searching if we go beyond sprevsz, since those entries * are for unrelated checksum entries. */ if (diff_pos & ~stream->sprevmask) { break; } goto again; } done: /* Crude efficiency test: if the match is very short and very far back, it's * unlikely to help, but the exact calculation requires knowing the state of * the address cache and adjacent instructions, which we can't do here. * Rather than encode a probably inefficient copy here and check it later * (which complicates the code a lot), do this: */ if (match_length == 4 && stream->input_position - (*match_offset) >= 1<<14) { /* It probably takes >2 bytes to encode an address >= 2^14 from here */ return 0; } if (match_length == 5 && stream->input_position - (*match_offset) >= 1<<21) { /* It probably takes >3 bytes to encode an address >= 2^21 from here */ return 0; } /* It's unlikely that a window is large enough for the (match_length == 6 && * address >= 2^28) check */ return match_length; } #if XD3_DEBUG static void xd3_verify_small_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum) { uint32_t state; uint32_t cksum = xd3_scksum (&state, inp, stream->smatcher.small_look); XD3_ASSERT (cksum == x_cksum); } static void xd3_verify_large_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum) { uint32_t cksum = xd3_lcksum (inp, stream->smatcher.large_look); XD3_ASSERT (cksum == x_cksum); } static void xd3_verify_run_state (xd3_stream *stream, const uint8_t *inp, usize_t x_run_l, uint8_t *x_run_c) { usize_t slook = stream->smatcher.small_look; uint8_t run_c; usize_t run_l = xd3_comprun (inp, slook, &run_c); XD3_ASSERT (run_l == 0 || run_c == *x_run_c); XD3_ASSERT (x_run_l > slook || run_l == x_run_l); } #endif /* XD3_DEBUG */ /* This function computes more source checksums to advance the window. * Called at every entrance to the string-match loop and each time * stream->input_position reaches the value returned as * *next_move_point. NB: this is one of the most expensive functions * in this code and also the most critical for good compression. * TODO: optimize the inner loop */ static int xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) { xoff_t logical_input_cksum_pos; xoff_t source_size; if (stream->src->eof_known) { source_size = xd3_source_eof (stream->src); XD3_ASSERT(stream->srcwin_cksum_pos <= source_size); if (stream->srcwin_cksum_pos == source_size) { *next_move_point = USIZE_T_MAX; return 0; } } /* Begin by advancing at twice the input rate, up to half the * maximum window size. */ logical_input_cksum_pos = min((stream->total_in + stream->input_position) * 2, (stream->total_in + stream->input_position) + (stream->src->max_winsize / 2)); /* If srcwin_cksum_pos is already greater, wait until the difference * is met. */ if (stream->srcwin_cksum_pos > logical_input_cksum_pos) { *next_move_point = stream->input_position + (usize_t)(stream->srcwin_cksum_pos - logical_input_cksum_pos); return 0; } /* A long match may have extended past srcwin_cksum_pos. Don't * start checksumming already-matched source data. */ if (stream->maxsrcaddr > stream->srcwin_cksum_pos) { stream->srcwin_cksum_pos = stream->maxsrcaddr; } if (logical_input_cksum_pos < stream->srcwin_cksum_pos) { logical_input_cksum_pos = stream->srcwin_cksum_pos; } /* Advance at least one source block. With the command-line * defaults this means: * * if (src->size <= src->max_winsize), index the entire source at once * using the position of the first non-match. This is good for * small inputs, especially when the content may have moved anywhere * in the file (e.g., tar files). * * if (src->size > src->max_winsize), index at least one block ahead * of the logical position. This is good for different reasons: * when a long match spanning several source blocks is encountered, * this avoids computing checksums for those blocks. */ logical_input_cksum_pos += stream->src->blksize; while (stream->srcwin_cksum_pos < logical_input_cksum_pos && (!stream->src->eof_known || stream->srcwin_cksum_pos < xd3_source_eof (stream->src))) { xoff_t blkno; xoff_t blkbaseoffset; usize_t blkrem; ssize_t oldpos; /* Using ssize_t because of a */ ssize_t blkpos; /* do { blkpos-- } while (blkpos >= oldpos); */ int ret; xd3_blksize_div (stream->srcwin_cksum_pos, stream->src, &blkno, &blkrem); oldpos = blkrem; if ((ret = xd3_getblk (stream, blkno))) { /* TOOFARBACK should never occur here, since we read forward. */ if (ret == XD3_TOOFARBACK) { ret = XD3_INTERNAL; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] async getblk return for %"Q"u\n", blkno)); return ret; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] T=%"Q"u{%"Q"u} S=%"Q"u EOF=%"Q"u %s\n", stream->total_in + stream->input_position, logical_input_cksum_pos, stream->srcwin_cksum_pos, xd3_source_eof (stream->src), stream->src->eof_known ? "known" : "unknown")); blkpos = xd3_bytes_on_srcblk (stream->src, blkno); if (blkpos < (ssize_t) stream->smatcher.large_look) { stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; IF_DEBUG1 (DP(RINT "[srcwin_move_point] continue (end-of-block)\n")); continue; } /* This inserts checksums for the entire block, in reverse, * starting from the end of the block. This logic does not test * stream->srcwin_cksum_pos because it always advances it to the * start of the next block. * * oldpos is the srcwin_cksum_pos within this block. blkpos is * the number of bytes available. Each iteration inspects * large_look bytes then steps back large_step bytes. The * if-stmt above ensures at least one large_look of data. */ blkpos -= stream->smatcher.large_look; blkbaseoffset = stream->src->blksize * blkno; do { uint32_t cksum = xd3_lcksum (stream->src->curblk + blkpos, stream->smatcher.large_look); usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); stream->large_table[hval] = (usize_t) (blkbaseoffset + (xoff_t)(blkpos + HASH_CKOFFSET)); IF_DEBUG (stream->large_ckcnt += 1); blkpos -= stream->smatcher.large_step; } while (blkpos >= oldpos); stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] exited loop T=%"Q"u{%"Q"u} " "S=%"Q"u EOF=%"Q"u %s\n", stream->total_in + stream->input_position, logical_input_cksum_pos, stream->srcwin_cksum_pos, xd3_source_eof (stream->src), stream->src->eof_known ? "known" : "unknown")); if (stream->src->eof_known) { source_size = xd3_source_eof (stream->src); if (stream->srcwin_cksum_pos >= source_size) { /* This invariant is needed for xd3_source_cksum_offset() */ stream->srcwin_cksum_pos = source_size; *next_move_point = USIZE_T_MAX; IF_DEBUG1 (DP(RINT "[srcwin_move_point] finished with source input\n")); return 0; } } /* How long until this function should be called again. */ XD3_ASSERT(stream->srcwin_cksum_pos >= logical_input_cksum_pos); *next_move_point = stream->input_position + 1 + (usize_t)(stream->srcwin_cksum_pos - logical_input_cksum_pos); return 0; } #endif /* XD3_ENCODER */ /******************************************************************** TEMPLATE pass *********************************************************************/ #endif /* __XDELTA3_C_INLINE_PASS__ */ #ifdef __XDELTA3_C_TEMPLATE_PASS__ #if XD3_ENCODER /******************************************************************** Templates *******************************************************************/ /* Template macros */ #define XD3_TEMPLATE(x) XD3_TEMPLATE2(x,TEMPLATE) #define XD3_TEMPLATE2(x,n) XD3_TEMPLATE3(x,n) #define XD3_TEMPLATE3(x,n) x ## n #define XD3_STRINGIFY(x) XD3_STRINGIFY2(x) #define XD3_STRINGIFY2(x) #x static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream); static const xd3_smatcher XD3_TEMPLATE(__smatcher_) = { XD3_STRINGIFY(TEMPLATE), XD3_TEMPLATE(xd3_string_match_), #if SOFTCFG == 1 0, 0, 0, 0, 0, 0, 0 #else LLOOK, LSTEP, SLOOK, SCHAIN, SLCHAIN, MAXLAZY, LONGENOUGH #endif }; static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) { const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS); const int DO_LARGE = (stream->src != NULL); const int DO_RUN = (1); const uint8_t *inp; uint32_t scksum = 0; uint32_t scksum_state = 0; uint32_t lcksum = 0; usize_t sinx; usize_t linx; uint8_t run_c; usize_t run_l; int ret; usize_t match_length; usize_t match_offset = 0; usize_t next_move_point; /* If there will be no compression due to settings or short input, * skip it entirely. */ if (! (DO_SMALL || DO_LARGE || DO_RUN) || stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } if ((ret = xd3_string_match_init (stream))) { return ret; } /* The restartloop label is reached when the incremental loop state * needs to be reset. */ restartloop: /* If there is not enough input remaining for any kind of match, skip it. */ if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } /* Now reset the incremental loop state: */ /* The min_match variable is updated to avoid matching the same lazy * match over and over again. For example, if you find a (small) * match of length 9 at one position, you will likely find a match * of length 8 at the next position. */ if (xd3_iopt_last_matched (stream) > stream->input_position) { stream->min_match = max(MIN_MATCH, 1 + xd3_iopt_last_matched(stream) - stream->input_position); } else { stream->min_match = MIN_MATCH; } /* The current input byte. */ inp = stream->next_in + stream->input_position; /* Small match state. */ if (DO_SMALL) { scksum = xd3_scksum (&scksum_state, inp, SLOOK); } /* Run state. */ if (DO_RUN) { run_l = xd3_comprun (inp, SLOOK, & run_c); } /* Large match state. We continue the loop even after not enough * bytes for LLOOK remain, so always check stream->input_position in * DO_LARGE code. */ if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) { /* Source window: next_move_point is the point that * stream->input_position must reach before computing more * source checksum. */ if ((ret = xd3_srcwin_move_point (stream, & next_move_point))) { return ret; } lcksum = xd3_lcksum (inp, LLOOK); } /* TRYLAZYLEN: True if a certain length match should be followed by * lazy search. This checks that LEN is shorter than MAXLAZY and * that there is enough leftover data to consider lazy matching. * "Enough" is set to 2 since the next match will start at the next * offset, it must match two extra characters. */ #define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) \ && (POS) + (LEN) <= (MAX) - 2) /* HANDLELAZY: This statement is called each time an instruciton is * emitted (three cases). If the instruction is large enough, the * loop is restarted, otherwise lazy matching may ensue. */ #define HANDLELAZY(mlen) \ if (TRYLAZYLEN ((mlen), (stream->input_position), (stream->avail_in))) \ { stream->min_match = (mlen) + LEAST_MATCH_INCR; goto updateone; } \ else \ { stream->input_position += (mlen); goto restartloop; } /* Now loop over one input byte at a time until a match is found... */ for (;; inp += 1, stream->input_position += 1) { /* Now we try three kinds of string match in order of expense: * run, large match, small match. */ /* Expand the start of a RUN. The test for (run_l == SLOOK) * avoids repeating this check when we pass through a run area * performing lazy matching. The run is only expanded once when * the min_match is first reached. If lazy matching is * performed, the run_l variable will remain inconsistent until * the first non-running input character is reached, at which * time the run_l may then again grow to SLOOK. */ if (DO_RUN && run_l == SLOOK) { usize_t max_len = stream->avail_in - stream->input_position; IF_DEBUG (xd3_verify_run_state (stream, inp, run_l, &run_c)); while (run_l < max_len && inp[run_l] == run_c) { run_l += 1; } /* Output a RUN instruction. */ if (run_l >= stream->min_match && run_l >= MIN_RUN) { if ((ret = xd3_emit_run (stream, stream->input_position, run_l, &run_c))) { return ret; } HANDLELAZY (run_l); } } /* If there is enough input remaining. */ if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) { if ((stream->input_position >= next_move_point) && (ret = xd3_srcwin_move_point (stream, & next_move_point))) { return ret; } linx = xd3_checksum_hash (& stream->large_hash, lcksum); IF_DEBUG (xd3_verify_large_state (stream, inp, lcksum)); if (stream->large_table[linx] != 0) { /* the match_setup will fail if the source window has * been decided and the match lies outside it. * OPT: Consider forcing a window at this point to * permit a new source window. */ xoff_t adj_offset = xd3_source_cksum_offset(stream, stream->large_table[linx] - HASH_CKOFFSET); if (xd3_source_match_setup (stream, adj_offset) == 0) { if ((ret = xd3_source_extend_match (stream))) { return ret; } /* Update stream position. match_fwd is zero if no * match. */ if (stream->match_fwd > 0) { HANDLELAZY (stream->match_fwd); } } } } /* Small matches. */ if (DO_SMALL) { sinx = xd3_checksum_hash (& stream->small_hash, scksum); /* Verify incremental state in debugging mode. */ IF_DEBUG (xd3_verify_small_state (stream, inp, scksum)); /* Search for the longest match */ if (stream->small_table[sinx] != 0) { match_length = xd3_smatch (stream, stream->small_table[sinx], scksum, & match_offset); } else { match_length = 0; } /* Insert a hash for this string. */ xd3_scksum_insert (stream, sinx, scksum, stream->input_position); /* Maybe output a COPY instruction */ if (match_length >= stream->min_match) { IF_DEBUG2 ({ static int x = 0; DP(RINT "[target match:%d] " "(-%d) [ %u bytes ]\n", x++, stream->input_position, stream->input_position + match_length, match_offset, match_offset + match_length, stream->input_position - match_offset, match_length); }); if ((ret = xd3_found_match (stream, /* decoder position */ stream->input_position, /* length */ match_length, /* address */ (xoff_t) match_offset, /* is_source */ 0))) { return ret; } /* Copy instruction. */ HANDLELAZY (match_length); } } /* The logic above prevents excess work during lazy matching by * increasing min_match to avoid smaller matches. Each time we * advance stream->input_position by one, the minimum match * shortens as well. */ if (stream->min_match > MIN_MATCH) { stream->min_match -= 1; } updateone: /* See if there are no more incremental cksums to compute. */ if (stream->input_position + SLOOK == stream->avail_in) { goto loopnomore; } /* Compute next RUN, CKSUM */ if (DO_RUN) { NEXTRUN (inp[SLOOK]); } if (DO_SMALL) { scksum = xd3_small_cksum_update (&scksum_state, inp, SLOOK); } if (DO_LARGE && (stream->input_position + LLOOK < stream->avail_in)) { lcksum = xd3_large_cksum_update (lcksum, inp, LLOOK); } } loopnomore: return 0; } #endif /* XD3_ENCODER */ #endif /* __XDELTA3_C_TEMPLATE_PASS__ */ xdelta3-3.0.7/COPYING0000644000176500017650000004313112105354541013402 0ustar debdevdebdev GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. xdelta3-3.0.7/xdelta3-second.h0000644000176500017650000001573712144343236015352 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2003, 2006, 2007, 2013. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XDELTA3_SECOND_H_ #define _XDELTA3_SECOND_H_ static inline void xd3_bit_state_encode_init (bit_state *bits) { bits->cur_byte = 0; bits->cur_mask = 1; } static inline int xd3_decode_bits (xd3_stream *stream, bit_state *bits, const uint8_t **input, const uint8_t *input_max, usize_t nbits, usize_t *valuep) { usize_t value = 0; usize_t vmask = 1 << nbits; if (bits->cur_mask == 0x100) { goto next_byte; } for (;;) { do { vmask >>= 1; if (bits->cur_byte & bits->cur_mask) { value |= vmask; } bits->cur_mask <<= 1; if (vmask == 1) { goto done; } } while (bits->cur_mask != 0x100); next_byte: if (*input == input_max) { stream->msg = "secondary decoder end of input"; return XD3_INTERNAL; } bits->cur_byte = *(*input)++; bits->cur_mask = 1; } done: IF_DEBUG2 (DP(RINT "(d) %u ", value)); (*valuep) = value; return 0; } #if REGRESSION_TEST /* There may be extra bits at the end of secondary decompression, this macro * checks for non-zero bits. This is overly strict, but helps pass the * single-bit-error regression test. */ static int xd3_test_clean_bits (xd3_stream *stream, bit_state *bits) { for (; bits->cur_mask != 0x100; bits->cur_mask <<= 1) { if (bits->cur_byte & bits->cur_mask) { stream->msg = "secondary decoder garbage"; return XD3_INTERNAL; } } return 0; } #endif static int xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp, int is_encode) { if (*sec_streamp == NULL) { int ret; if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL) { stream->msg = "error initializing secondary stream"; return XD3_INVALID; } if ((ret = stream->sec_type->init (stream, *sec_streamp, is_encode)) != 0) { return ret; } } return 0; } static int xd3_decode_secondary (xd3_stream *stream, xd3_desect *sect, xd3_sec_stream **sec_streamp) { uint32_t dec_size; uint8_t *out_used; int ret; if ((ret = xd3_get_secondary (stream, sec_streamp, 0)) != 0) { return ret; } /* Decode the size, allocate the buffer. */ if ((ret = xd3_read_size (stream, & sect->buf, sect->buf_max, & dec_size)) || (ret = xd3_decode_allocate (stream, dec_size, & sect->copied2, & sect->alloc2))) { return ret; } out_used = sect->copied2; if ((ret = stream->sec_type->decode (stream, *sec_streamp, & sect->buf, sect->buf_max, & out_used, out_used + dec_size))) { return ret; } if (sect->buf != sect->buf_max) { stream->msg = "secondary decoder finished with unused input"; return XD3_INTERNAL; } if (out_used != sect->copied2 + dec_size) { stream->msg = "secondary decoder short output"; return XD3_INTERNAL; } sect->buf = sect->copied2; sect->buf_max = sect->copied2 + dec_size; sect->size = dec_size; return 0; } #if XD3_ENCODER static inline int xd3_encode_bit (xd3_stream *stream, xd3_output **output, bit_state *bits, usize_t bit) { int ret; if (bit) { bits->cur_byte |= bits->cur_mask; } /* OPT: Might help to buffer more than 8 bits at once. */ if (bits->cur_mask == 0x80) { if ((ret = xd3_emit_byte (stream, output, bits->cur_byte)) != 0) { return ret; } bits->cur_mask = 1; bits->cur_byte = 0; } else { bits->cur_mask <<= 1; } return 0; } static inline int xd3_flush_bits (xd3_stream *stream, xd3_output **output, bit_state *bits) { return (bits->cur_mask == 1) ? 0 : xd3_emit_byte (stream, output, bits->cur_byte); } static inline int xd3_encode_bits (xd3_stream *stream, xd3_output **output, bit_state *bits, usize_t nbits, usize_t value) { int ret; usize_t mask = 1 << nbits; XD3_ASSERT (nbits > 0); XD3_ASSERT (nbits < sizeof (usize_t) * 8); XD3_ASSERT (value < mask); do { mask >>= 1; if ((ret = xd3_encode_bit (stream, output, bits, value & mask))) { return ret; } } while (mask != 1); IF_DEBUG2 (DP(RINT "(e) %u ", value)); return 0; } static int xd3_encode_secondary (xd3_stream *stream, xd3_output **head, xd3_output **tail, xd3_sec_stream **sec_streamp, xd3_sec_cfg *cfg, int *did_it) { xd3_output *tmp_head; xd3_output *tmp_tail; usize_t comp_size; usize_t orig_size; int ret; orig_size = xd3_sizeof_output (*head); if (orig_size < SECONDARY_MIN_INPUT) { return 0; } if ((ret = xd3_get_secondary (stream, sec_streamp, 1)) != 0) { return ret; } tmp_head = xd3_alloc_output (stream, NULL); /* Encode the size, encode the data. Encoding the size makes it * simpler, but is a little gross. Should not need the entire * section in contiguous memory, but it is much easier this way. */ if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) || (ret = stream->sec_type->encode (stream, *sec_streamp, *head, tmp_head, cfg))) { goto getout; } /* If the secondary compressor determines it's no good, it returns * XD3_NOSECOND. */ /* Setup tmp_tail, comp_size */ tmp_tail = tmp_head; comp_size = tmp_head->next; while (tmp_tail->next_page != NULL) { tmp_tail = tmp_tail->next_page; comp_size += tmp_tail->next; } XD3_ASSERT (comp_size == xd3_sizeof_output (tmp_head)); XD3_ASSERT (tmp_tail != NULL); if (comp_size < (orig_size - SECONDARY_MIN_SAVINGS) || cfg->inefficient) { IF_DEBUG1(DP(RINT "secondary saved %u bytes: %u -> %u (%0.2f%%)\n", orig_size - comp_size, orig_size, comp_size, 100.0 * (double) comp_size / (double) orig_size)); xd3_free_output (stream, *head); *head = tmp_head; *tail = tmp_tail; *did_it = 1; } else { getout: if (ret == XD3_NOSECOND) { ret = 0; } xd3_free_output (stream, tmp_head); } return ret; } #endif /* XD3_ENCODER */ #endif /* _XDELTA3_SECOND_H_ */ xdelta3-3.0.7/xdelta3-fgk.h0000644000176500017650000005366612105354541014647 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* For demonstration purposes only. */ #ifndef _XDELTA3_FGK_h_ #define _XDELTA3_FGK_h_ /* An implementation of the FGK algorithm described by D.E. Knuth in * "Dynamic Huffman Coding" in Journal of Algorithms 6. */ /* A 32bit counter (fgk_weight) is used as the frequency counter for * nodes in the huffman tree. TODO: Need oto test for overflow and/or * reset stats. */ typedef struct _fgk_stream fgk_stream; typedef struct _fgk_node fgk_node; typedef struct _fgk_block fgk_block; typedef unsigned int fgk_bit; typedef uint32_t fgk_weight; struct _fgk_block { union { fgk_node *un_leader; fgk_block *un_freeptr; } un; }; #define block_leader un.un_leader #define block_freeptr un.un_freeptr /* The code can also support fixed huffman encoding/decoding. */ #define IS_ADAPTIVE 1 /* weight is a count of the number of times this element has been seen * in the current encoding/decoding. parent, right_child, and * left_child are pointers defining the tree structure. right and * left point to neighbors in an ordered sequence of weights. The * left child of a node is always guaranteed to have weight not * greater than its sibling. fgk_blockLeader points to the element * with the same weight as itself which is closest to the next * increasing weight block. */ struct _fgk_node { fgk_weight weight; fgk_node *parent; fgk_node *left_child; fgk_node *right_child; fgk_node *left; fgk_node *right; fgk_block *my_block; }; /* alphabet_size is the a count of the number of possible leaves in * the huffman tree. The number of total nodes counting internal * nodes is ((2 * alphabet_size) - 1). zero_freq_count is the number * of elements remaining which have zero frequency. zero_freq_exp and * zero_freq_rem satisfy the equation zero_freq_count = * 2^zero_freq_exp + zero_freq_rem. root_node is the root of the * tree, which is initialized to a node with zero frequency and * contains the 0th such element. free_node contains a pointer to the * next available fgk_node space. alphabet contains all the elements * and is indexed by N. remaining_zeros points to the head of the * list of zeros. */ struct _fgk_stream { usize_t alphabet_size; usize_t zero_freq_count; usize_t zero_freq_exp; usize_t zero_freq_rem; usize_t coded_depth; usize_t total_nodes; usize_t total_blocks; fgk_bit *coded_bits; fgk_block *block_array; fgk_block *free_block; fgk_node *decode_ptr; fgk_node *remaining_zeros; fgk_node *alphabet; fgk_node *root_node; fgk_node *free_node; }; /*********************************************************************/ /* Encoder */ /*********************************************************************/ static fgk_stream* fgk_alloc (xd3_stream *stream /*, usize_t alphabet_size */); static int fgk_init (xd3_stream *stream, fgk_stream *h, int is_encode); static int fgk_encode_data (fgk_stream *h, usize_t n); static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h); static int xd3_encode_fgk (xd3_stream *stream, fgk_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg); /*********************************************************************/ /* Decoder */ /*********************************************************************/ static inline int fgk_decode_bit (fgk_stream *h, fgk_bit b); static int fgk_decode_data (fgk_stream *h); static void fgk_destroy (xd3_stream *stream, fgk_stream *h); static int xd3_decode_fgk (xd3_stream *stream, fgk_stream *sec_stream, const uint8_t **input, const uint8_t *const input_end, uint8_t **output, const uint8_t *const output_end); /*********************************************************************/ /* Private */ /*********************************************************************/ static unsigned int fgk_find_nth_zero (fgk_stream *h, usize_t n); static usize_t fgk_nth_zero (fgk_stream *h, usize_t n); static void fgk_update_tree (fgk_stream *h, usize_t n); static fgk_node* fgk_increase_zero_weight (fgk_stream *h, usize_t n); static void fgk_eliminate_zero (fgk_stream* h, fgk_node *node); static void fgk_move_right (fgk_stream *h, fgk_node *node); static void fgk_promote (fgk_stream *h, fgk_node *node); static void fgk_init_node (fgk_node *node, usize_t i, usize_t size); static fgk_block* fgk_make_block (fgk_stream *h, fgk_node *l); static void fgk_free_block (fgk_stream *h, fgk_block *b); static void fgk_factor_remaining (fgk_stream *h); static inline void fgk_swap_ptrs (fgk_node **one, fgk_node **two); /*********************************************************************/ /* Basic Routines */ /*********************************************************************/ /* returns an initialized huffman encoder for an alphabet with the * given size. returns NULL if enough memory cannot be allocated */ static fgk_stream* fgk_alloc (xd3_stream *stream /*, int alphabet_size0 */) { usize_t alphabet_size0 = ALPHABET_SIZE; fgk_stream *h; if ((h = (fgk_stream*) xd3_alloc (stream, 1, sizeof (fgk_stream))) == NULL) { return NULL; } h->total_nodes = (2 * alphabet_size0) - 1; h->total_blocks = (2 * h->total_nodes); h->alphabet = (fgk_node*) xd3_alloc (stream, h->total_nodes, sizeof (fgk_node)); h->block_array = (fgk_block*) xd3_alloc (stream, h->total_blocks, sizeof (fgk_block)); h->coded_bits = (fgk_bit*) xd3_alloc (stream, alphabet_size0, sizeof (fgk_bit)); if (h->coded_bits == NULL || h->alphabet == NULL || h->block_array == NULL) { fgk_destroy (stream, h); return NULL; } h->alphabet_size = alphabet_size0; return h; } static int fgk_init (xd3_stream *stream, fgk_stream *h, int is_encode) { usize_t ui; ssize_t si; h->root_node = h->alphabet; h->decode_ptr = h->root_node; h->free_node = h->alphabet + h->alphabet_size; h->remaining_zeros = h->alphabet; h->coded_depth = 0; h->zero_freq_count = h->alphabet_size + 2; /* after two calls to factor_remaining, zero_freq_count == alphabet_size */ fgk_factor_remaining(h); /* set ZFE and ZFR */ fgk_factor_remaining(h); /* set ZFDB according to prev state */ IF_DEBUG (memset (h->alphabet, 0, sizeof (h->alphabet[0]) * h->total_nodes)); for (ui = 0; ui < h->total_blocks-1; ui += 1) { h->block_array[ui].block_freeptr = &h->block_array[ui + 1]; } h->block_array[h->total_blocks - 1].block_freeptr = NULL; h->free_block = h->block_array; /* Zero frequency nodes are inserted in the first alphabet_size * positions, with Value, weight, and a pointer to the next zero * frequency node. */ for (si = h->alphabet_size - 1; si >= 0; si -= 1) { fgk_init_node (h->alphabet + si, (usize_t) si, h->alphabet_size); } return 0; } static void fgk_swap_ptrs(fgk_node **one, fgk_node **two) { fgk_node *tmp = *one; *one = *two; *two = tmp; } /* Takes huffman transmitter h and n, the nth elt in the alphabet, and * returns the number of required to encode n. */ static int fgk_encode_data (fgk_stream* h, usize_t n) { fgk_node *target_ptr = h->alphabet + n; XD3_ASSERT (n < h->alphabet_size); h->coded_depth = 0; /* First encode the binary representation of the nth remaining * zero frequency element in reverse such that bit, which will be * encoded from h->coded_depth down to 0 will arrive in increasing * order following the tree path. If there is only one left, it * is not neccesary to encode these bits. */ if (IS_ADAPTIVE && target_ptr->weight == 0) { unsigned int where, shift; int bits; where = fgk_find_nth_zero(h, n); shift = 1; if (h->zero_freq_rem == 0) { bits = h->zero_freq_exp; } else { bits = h->zero_freq_exp + 1; } while (bits > 0) { h->coded_bits[h->coded_depth++] = (shift & where) && 1; bits -= 1; shift <<= 1; }; target_ptr = h->remaining_zeros; } /* The path from root to node is filled into coded_bits in reverse so * that it is encoded in the right order */ while (target_ptr != h->root_node) { h->coded_bits[h->coded_depth++] = (target_ptr->parent->right_child == target_ptr); target_ptr = target_ptr->parent; } if (IS_ADAPTIVE) { fgk_update_tree(h, n); } return h->coded_depth; } /* Should be called as many times as fgk_encode_data returns. */ static inline fgk_bit fgk_get_encoded_bit (fgk_stream *h) { XD3_ASSERT (h->coded_depth > 0); return h->coded_bits[--h->coded_depth]; } /* This procedure updates the tree after alphabet[n] has been encoded * or decoded. */ static void fgk_update_tree (fgk_stream *h, usize_t n) { fgk_node *incr_node; if (h->alphabet[n].weight == 0) { incr_node = fgk_increase_zero_weight (h, n); } else { incr_node = h->alphabet + n; } while (incr_node != h->root_node) { fgk_move_right (h, incr_node); fgk_promote (h, incr_node); incr_node->weight += 1; /* incr the parent */ incr_node = incr_node->parent; /* repeat */ } h->root_node->weight += 1; } static void fgk_move_right (fgk_stream *h, fgk_node *move_fwd) { fgk_node **fwd_par_ptr, **back_par_ptr; fgk_node *move_back, *tmp; move_back = move_fwd->my_block->block_leader; if (move_fwd == move_back || move_fwd->parent == move_back || move_fwd->weight == 0) { return; } move_back->right->left = move_fwd; if (move_fwd->left) { move_fwd->left->right = move_back; } tmp = move_fwd->right; move_fwd->right = move_back->right; if (tmp == move_back) { move_back->right = move_fwd; } else { tmp->left = move_back; move_back->right = tmp; } tmp = move_back->left; move_back->left = move_fwd->left; if (tmp == move_fwd) { move_fwd->left = move_back; } else { tmp->right = move_fwd; move_fwd->left = tmp; } if (move_fwd->parent->right_child == move_fwd) { fwd_par_ptr = &move_fwd->parent->right_child; } else { fwd_par_ptr = &move_fwd->parent->left_child; } if (move_back->parent->right_child == move_back) { back_par_ptr = &move_back->parent->right_child; } else { back_par_ptr = &move_back->parent->left_child; } fgk_swap_ptrs (&move_fwd->parent, &move_back->parent); fgk_swap_ptrs (fwd_par_ptr, back_par_ptr); move_fwd->my_block->block_leader = move_fwd; } /* Shifts node, the leader of its block, into the next block. */ static void fgk_promote (fgk_stream *h, fgk_node *node) { fgk_node *my_left, *my_right; fgk_block *cur_block; my_right = node->right; my_left = node->left; cur_block = node->my_block; if (node->weight == 0) { return; } /* if left is right child, parent of remaining zeros case (?), means parent * has same weight as right child. */ if (my_left == node->right_child && node->left_child && node->left_child->weight == 0) { XD3_ASSERT (node->left_child == h->remaining_zeros); XD3_ASSERT (node->right_child->weight == (node->weight+1)); /* child weight was already incremented */ if (node->weight == (my_right->weight - 1) && my_right != h->root_node) { fgk_free_block (h, cur_block); node->my_block = my_right->my_block; my_left->my_block = my_right->my_block; } return; } if (my_left == h->remaining_zeros) { return; } /* true if not the leftmost node */ if (my_left->my_block == cur_block) { my_left->my_block->block_leader = my_left; } else { fgk_free_block (h, cur_block); } /* node->parent != my_right */ if ((node->weight == (my_right->weight - 1)) && (my_right != h->root_node)) { node->my_block = my_right->my_block; } else { node->my_block = fgk_make_block (h, node); } } /* When an element is seen the first time this is called to remove it from the list of * zero weight elements and introduce a new internal node to the tree. */ static fgk_node* fgk_increase_zero_weight (fgk_stream *h, usize_t n) { fgk_node *this_zero, *new_internal, *zero_ptr; this_zero = h->alphabet + n; if (h->zero_freq_count == 1) { /* this is the last one */ this_zero->right_child = NULL; if (this_zero->right->weight == 1) { this_zero->my_block = this_zero->right->my_block; } else { this_zero->my_block = fgk_make_block (h, this_zero); } h->remaining_zeros = NULL; return this_zero; } zero_ptr = h->remaining_zeros; new_internal = h->free_node++; new_internal->parent = zero_ptr->parent; new_internal->right = zero_ptr->right; new_internal->weight = 0; new_internal->right_child = this_zero; new_internal->left = this_zero; if (h->remaining_zeros == h->root_node) { /* This is the first element to be coded */ h->root_node = new_internal; this_zero->my_block = fgk_make_block (h, this_zero); new_internal->my_block = fgk_make_block (h, new_internal); } else { new_internal->right->left = new_internal; if (zero_ptr->parent->right_child == zero_ptr) { zero_ptr->parent->right_child = new_internal; } else { zero_ptr->parent->left_child = new_internal; } if (new_internal->right->weight == 1) { new_internal->my_block = new_internal->right->my_block; } else { new_internal->my_block = fgk_make_block (h, new_internal); } this_zero->my_block = new_internal->my_block; } fgk_eliminate_zero (h, this_zero); new_internal->left_child = h->remaining_zeros; this_zero->right = new_internal; this_zero->left = h->remaining_zeros; this_zero->parent = new_internal; this_zero->left_child = NULL; this_zero->right_child = NULL; h->remaining_zeros->parent = new_internal; h->remaining_zeros->right = this_zero; return this_zero; } /* When a zero frequency element is encoded, it is followed by the * binary representation of the index into the remaining elements. * Sets a cache to the element before it so that it can be removed * without calling this procedure again. */ static unsigned int fgk_find_nth_zero (fgk_stream* h, usize_t n) { fgk_node *target_ptr = h->alphabet + n; fgk_node *head_ptr = h->remaining_zeros; unsigned int idx = 0; while (target_ptr != head_ptr) { head_ptr = head_ptr->right_child; idx += 1; } return idx; } /* Splices node out of the list of zeros. */ static void fgk_eliminate_zero (fgk_stream* h, fgk_node *node) { if (h->zero_freq_count == 1) { return; } fgk_factor_remaining(h); if (node->left_child == NULL) { h->remaining_zeros = h->remaining_zeros->right_child; h->remaining_zeros->left_child = NULL; } else if (node->right_child == NULL) { node->left_child->right_child = NULL; } else { node->right_child->left_child = node->left_child; node->left_child->right_child = node->right_child; } } static void fgk_init_node (fgk_node *node, usize_t i, usize_t size) { if (i < size - 1) { node->right_child = node + 1; } else { node->right_child = NULL; } if (i >= 1) { node->left_child = node - 1; } else { node->left_child = NULL; } node->weight = 0; node->parent = NULL; node->right = NULL; node->left = NULL; node->my_block = NULL; } /* The data structure used is an array of blocks, which are unions of * free pointers and huffnode pointers. free blocks are a linked list * of free blocks, the front of which is h->free_block. The used * blocks are pointers to the head of each block. */ static fgk_block* fgk_make_block (fgk_stream *h, fgk_node* lead) { fgk_block *ret = h->free_block; XD3_ASSERT (h->free_block != NULL); h->free_block = h->free_block->block_freeptr; ret->block_leader = lead; return ret; } /* Restores the block to the front of the free list. */ static void fgk_free_block (fgk_stream *h, fgk_block *b) { b->block_freeptr = h->free_block; h->free_block = b; } /* sets zero_freq_count, zero_freq_rem, and zero_freq_exp to satsity * the equation given above. */ static void fgk_factor_remaining (fgk_stream *h) { unsigned int i; i = (--h->zero_freq_count); h->zero_freq_exp = 0; while (i > 1) { h->zero_freq_exp += 1; i >>= 1; } i = 1 << h->zero_freq_exp; h->zero_freq_rem = h->zero_freq_count - i; } /* receives a bit at a time and returns true when a complete code has * been received. */ static inline int fgk_decode_bit (fgk_stream* h, fgk_bit b) { XD3_ASSERT (b == 1 || b == 0); if (IS_ADAPTIVE && h->decode_ptr->weight == 0) { usize_t bitsreq; if (h->zero_freq_rem == 0) { bitsreq = h->zero_freq_exp; } else { bitsreq = h->zero_freq_exp + 1; } h->coded_bits[h->coded_depth] = b; h->coded_depth += 1; return h->coded_depth >= bitsreq; } else { if (b) { h->decode_ptr = h->decode_ptr->right_child; } else { h->decode_ptr = h->decode_ptr->left_child; } if (h->decode_ptr->left_child == NULL) { /* If the weight is non-zero, finished. */ if (h->decode_ptr->weight != 0) { return 1; } /* zero_freq_count is dropping to 0, finished. */ return h->zero_freq_count == 1; } else { return 0; } } } static usize_t fgk_nth_zero (fgk_stream* h, usize_t n) { fgk_node *ret = h->remaining_zeros; /* ERROR: if during this loop (ret->right_child == NULL) then the * encoder's zero count is too high. Could return an error code * now, but is probably unnecessary overhead, since the caller * should check integrity anyway. */ for (; n != 0 && ret->right_child != NULL; n -= 1) { ret = ret->right_child; } return (usize_t)(ret - h->alphabet); } /* once fgk_decode_bit returns 1, this retrieves an index into the * alphabet otherwise this returns 0, indicating more bits are * required. */ static int fgk_decode_data (fgk_stream* h) { usize_t elt = (usize_t)(h->decode_ptr - h->alphabet); if (IS_ADAPTIVE && h->decode_ptr->weight == 0) { usize_t i = 0; usize_t n = 0; if (h->coded_depth > 0) { for (; i < h->coded_depth - 1; i += 1) { n |= h->coded_bits[i]; n <<= 1; } } n |= h->coded_bits[i]; elt = fgk_nth_zero(h, n); } h->coded_depth = 0; if (IS_ADAPTIVE) { fgk_update_tree(h, elt); } h->decode_ptr = h->root_node; return elt; } static void fgk_destroy (xd3_stream *stream, fgk_stream *h) { if (h != NULL) { xd3_free (stream, h->alphabet); xd3_free (stream, h->coded_bits); xd3_free (stream, h->block_array); xd3_free (stream, h); } } /*********************************************************************/ /* Xdelta */ /*********************************************************************/ static int xd3_encode_fgk (xd3_stream *stream, fgk_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg) { bit_state bstate = BIT_STATE_ENCODE_INIT; xd3_output *cur_page; int ret; /* OPT: quit compression early if it looks bad */ for (cur_page = input; cur_page; cur_page = cur_page->next_page) { const uint8_t *inp = cur_page->base; const uint8_t *inp_max = inp + cur_page->next; while (inp < inp_max) { usize_t bits = fgk_encode_data (sec_stream, *inp++); while (bits--) { if ((ret = xd3_encode_bit (stream, & output, & bstate, fgk_get_encoded_bit (sec_stream)))) { return ret; } } } } return xd3_flush_bits (stream, & output, & bstate); } static int xd3_decode_fgk (xd3_stream *stream, fgk_stream *sec_stream, const uint8_t **input_pos, const uint8_t *const input_max, uint8_t **output_pos, const uint8_t *const output_max) { bit_state bstate; uint8_t *output = *output_pos; const uint8_t *input = *input_pos; for (;;) { if (input == input_max) { stream->msg = "secondary decoder end of input"; return XD3_INTERNAL; } bstate.cur_byte = *input++; for (bstate.cur_mask = 1; bstate.cur_mask != 0x100; bstate.cur_mask <<= 1) { int done = fgk_decode_bit (sec_stream, (bstate.cur_byte & bstate.cur_mask) ? 1U : 0U); if (! done) { continue; } *output++ = fgk_decode_data (sec_stream); if (output == output_max) { /* During regression testing: */ IF_REGRESSION ({ int ret; bstate.cur_mask <<= 1; if ((ret = xd3_test_clean_bits (stream, & bstate))) { return ret; } }); (*output_pos) = output; (*input_pos) = input; return 0; } } } } #endif /* _XDELTA3_FGK_ */ xdelta3-3.0.7/xdelta3.wxs0000644000176500017650000001124312105354541014455 0ustar debdevdebdev xdelta3-3.0.7/testing/0002755000176500017650000000000012144343472014030 5ustar debdevdebdevxdelta3-3.0.7/testing/cmp.h0000644000176500017650000000221212105354541014747 0ustar debdevdebdev/* -*- Mode: C++ -*- */ static size_t CmpDifferentBlockBytes(const Block &a, const Block &b) { size_t total = 0; size_t i = 0; size_t m = min(a.Size(), b.Size()); for (; i < m; i++) { if (a[i] != b[i]) { total++; } } total += a.Size() - i; total += b.Size() - i; return total; } static xoff_t CmpDifferentBytes(const FileSpec &a, const FileSpec &b) { Block block_a, block_b; xoff_t total = 0; typename FileSpec::iterator a_i(a), b_i(b); for (; !a_i.Done() && !b_i.Done(); a_i.Next(), b_i.Next()) { a_i.Get(&block_a); b_i.Get(&block_b); total += CmpDifferentBlockBytes(block_a, block_b); } for (; !a_i.Done(); a_i.Next()) { total += a_i.BytesOnBlock(); } for (; !b_i.Done(); b_i.Next()) { total += b_i.BytesOnBlock(); } return total; } static size_t CmpDifferentBlockBytesAtOffset(const Block &a, const FileSpec &b_spec, xoff_t offset) { Block b; size_t size = a.Size(); CHECK_LE(offset, b_spec.Size()); if (b_spec.Size() < offset + size) { size = b_spec.Size() - offset; } b_spec.Get(&b, offset, size); return CmpDifferentBlockBytes(a, b); } xdelta3-3.0.7/testing/segment.h0000644000176500017650000000425212105354541015640 0ustar debdevdebdev// -*- Mode: C++ -*- class Segment { public: Segment(size_t size, MTRandom *rand) : size_(size), seed_(rand->Rand32()), seed_offset_(0), data_(NULL) { CHECK_GT(size_, 0); } Segment(size_t size, uint32_t seed) : size_(size), seed_(seed), seed_offset_(0), data_(NULL) { CHECK_GT(size_, 0); } Segment(size_t size, uint8_t *data) : size_(size), seed_(0), seed_offset_(0), data_(data) { CHECK_GT(size_, 0); } size_t Size() const { return size_; } Segment Subseg(size_t start, size_t size) const { CHECK_LE(start + size, size_); if (data_) { return Segment(size, data_ + start); } else { return Segment(size, seed_, seed_offset_ + start); } } void Fill(size_t seg_offset, size_t size, uint8_t *data) const { CHECK_LE(seg_offset + size, size_); if (data_) { memcpy(data, data_ + seg_offset, size); } else { size_t skip = seg_offset + seed_offset_; MTRandom gen(seed_); MTRandom8 gen8(&gen); while (skip--) { gen8.Rand8(); } for (size_t i = 0; i < size; i++) { data[i] = gen8.Rand8(); } } } string ToString() const { string r; if (data_) { for (size_t i = 0; i < size_; i++) { char buf[10]; sprintf(buf, "%02x ", data_[i]); r.append(buf); } } else { char buf[256]; sprintf(buf, "size=%ld,seed=%ud,skip=%ld", size_, seed_, seed_offset_); r.append(buf); } return r; } private: // Used by Subseg() Segment(size_t size, uint32_t seed, size_t seed_offset) : size_(size), seed_(seed), seed_offset_(seed_offset), data_(NULL) { CHECK_GT(size_, 0); } size_t size_; // Size of this segment // For random segments uint32_t seed_; // Seed used for generating byte sequence size_t seed_offset_; // Seed positions the sequence this many bytes // before its beginning. // For literal segments (data is not owned) uint8_t *data_; }; typedef map SegmentMap; typedef typename SegmentMap::const_iterator ConstSegmentMapIterator; typedef typename SegmentMap::iterator SegmentMapIterator; xdelta3-3.0.7/testing/regtest.cc0000644000176500017650000006767312144071013016022 0ustar debdevdebdev/* -*- Mode: C++ -*- */ #include "test.h" #include "random.h" #include "sizes.h" template class Regtest { public: typedef typename Constants::Sizes Sizes; struct Options { Options() : encode_srcwin_maxsz(1<<20), block_size(Constants::BLOCK_SIZE), size_known(false) { } size_t encode_srcwin_maxsz; size_t block_size; bool size_known; }; #include "segment.h" #include "modify.h" #include "file.h" #include "cmp.h" #include "delta.h" void InMemoryEncodeDecode(const FileSpec &source_file, const FileSpec &target_file, Block *coded_data, const Options &options = Options()) { xd3_stream encode_stream; xd3_config encode_config; xd3_source encode_source; xd3_stream decode_stream; xd3_config decode_config; xd3_source decode_source; xoff_t verified_bytes = 0; xoff_t encoded_bytes = 0; if (coded_data) { coded_data->Reset(); } memset(&encode_stream, 0, sizeof (encode_stream)); memset(&encode_source, 0, sizeof (encode_source)); memset(&decode_stream, 0, sizeof (decode_stream)); memset(&decode_source, 0, sizeof (decode_source)); xd3_init_config(&encode_config, XD3_ADLER32); xd3_init_config(&decode_config, XD3_ADLER32); encode_config.winsize = Constants::WINDOW_SIZE; // TODO! the smatcher setup isn't working, // if (options.large_cksum_step) { // encode_config.smatch_cfg = XD3_SMATCH_SOFT; // encode_config.smatcher_soft.large_step = options.large_cksum_step; // } // if (options.large_cksum_size) { // encode_config.smatch_cfg = XD3_SMATCH_SOFT; // encode_config.smatcher_soft.large_look = options.large_cksum_size; // } CHECK_EQ(0, xd3_config_stream (&encode_stream, &encode_config)); CHECK_EQ(0, xd3_config_stream (&decode_stream, &decode_config)); encode_source.blksize = options.block_size; decode_source.blksize = options.block_size; encode_source.max_winsize = options.encode_srcwin_maxsz; decode_source.max_winsize = options.encode_srcwin_maxsz; if (!options.size_known) { xd3_set_source (&encode_stream, &encode_source); xd3_set_source (&decode_stream, &decode_source); } else { xd3_set_source_and_size (&encode_stream, &encode_source, source_file.Size()); xd3_set_source_and_size (&decode_stream, &decode_source, source_file.Size()); } BlockIterator source_iterator(source_file, options.block_size); BlockIterator target_iterator(target_file, Constants::READ_SIZE); Block encode_source_block, decode_source_block; Block decoded_block, target_block; bool encoding = true; bool done = false; bool done_after_input = false; IF_DEBUG1 (XPR(NTR "source %"Q"u[%"Q"u] target %"Q"u[%lu] winsize %lu\n", source_file.Size(), options.block_size, target_file.Size(), Constants::READ_SIZE, Constants::WINDOW_SIZE)); while (!done) { target_iterator.Get(&target_block); xoff_t blks = target_iterator.Blocks(); IF_DEBUG2(XPR(NTR "target in %s: %llu..%llu %"Q"u(%"Q"u) verified %"Q"u\n", encoding ? "encoding" : "decoding", target_iterator.Offset(), target_iterator.Offset() + target_block.Size(), target_iterator.Blkno(), blks, verified_bytes)); if (blks == 0 || target_iterator.Blkno() == (blks - 1)) { xd3_set_flags(&encode_stream, XD3_FLUSH | encode_stream.flags); } xd3_avail_input(&encode_stream, target_block.Data(), target_block.Size()); encoded_bytes += target_block.Size(); process: int ret; const char *msg; if (encoding) { ret = xd3_encode_input(&encode_stream); msg = encode_stream.msg; } else { ret = xd3_decode_input(&decode_stream); msg = decode_stream.msg; } (void) msg; switch (ret) { case XD3_OUTPUT: if (encoding) { if (coded_data != NULL) { // Optional encoded-output to the caller coded_data->Append(encode_stream.next_out, encode_stream.avail_out); } // Feed this data to the decoder. xd3_avail_input(&decode_stream, encode_stream.next_out, encode_stream.avail_out); xd3_consume_output(&encode_stream); encoding = false; } else { decoded_block.Append(decode_stream.next_out, decode_stream.avail_out); xd3_consume_output(&decode_stream); } goto process; case XD3_GETSRCBLK: { xd3_source *src = (encoding ? &encode_source : &decode_source); Block *block = (encoding ? &encode_source_block : &decode_source_block); if (encoding) { IF_DEBUG1(XPR(NTR "[srcblock] %"Q"u last srcpos %"Q"u " "encodepos %"Q"u\n", encode_source.getblkno, encode_stream.match_last_srcpos, encode_stream.input_position + encode_stream.total_in)); } source_iterator.SetBlock(src->getblkno); source_iterator.Get(block); src->curblkno = src->getblkno; src->onblk = block->Size(); src->curblk = block->Data(); goto process; } case XD3_INPUT: if (!encoding) { encoding = true; goto process; } else { if (done_after_input) { done = true; continue; } if (target_block.Size() < target_iterator.BlockSize()) { encoding = false; } else { target_iterator.Next(); } continue; } case XD3_WINFINISH: if (encoding) { if (encode_stream.flags & XD3_FLUSH) { done_after_input = true; } encoding = false; } else { CHECK_EQ(0, CmpDifferentBlockBytesAtOffset(decoded_block, target_file, verified_bytes)); verified_bytes += decoded_block.Size(); decoded_block.Reset(); encoding = true; } goto process; case XD3_WINSTART: case XD3_GOTHEADER: goto process; default: XPR(NTR "%s = %s %s\n", encoding ? "E " : " D", xd3_strerror(ret), msg == NULL ? "" : msg); CHECK_EQ(0, ret); CHECK_EQ(-1, ret); } } CHECK_EQ(target_file.Size(), encoded_bytes); CHECK_EQ(target_file.Size(), verified_bytes); CHECK_EQ(0, xd3_close_stream(&decode_stream)); CHECK_EQ(0, xd3_close_stream(&encode_stream)); xd3_free_stream(&encode_stream); xd3_free_stream(&decode_stream); } void MainEncodeDecode(const TmpFile &source_file, const TmpFile &target_file, ExtFile *coded_data, const Options &options) { vector ecmd; char buf[16]; snprintf(buf, sizeof(buf), "-B%"Q"u", options.encode_srcwin_maxsz); ecmd.push_back("xdelta3"); ecmd.push_back(buf); ecmd.push_back("-s"); ecmd.push_back(source_file.Name()); ecmd.push_back(target_file.Name()); ecmd.push_back(coded_data->Name()); ecmd.push_back(NULL); CHECK_EQ(0, xd3_main_cmdline(ecmd.size() - 1, const_cast(&ecmd[0]))); vector dcmd; ExtFile recon_file; dcmd.push_back("xdelta3"); ecmd.push_back(buf); dcmd.push_back("-d"); dcmd.push_back("-s"); dcmd.push_back(source_file.Name()); dcmd.push_back(coded_data->Name()); dcmd.push_back(recon_file.Name()); dcmd.push_back(NULL); CHECK_EQ(0, xd3_main_cmdline(dcmd.size() - 1, const_cast(&dcmd[0]))); CHECK_EQ(0, test_compare_files(recon_file.Name(), target_file.Name())); } ////////////////////////////////////////////////////////////////////// void TestRandomNumbers() { MTRandom rand; int rounds = 1<<20; uint64_t usum = 0; uint64_t esum = 0; for (int i = 0; i < rounds; i++) { usum += rand.Rand32(); esum += rand.ExpRand32(1024); } double allowed_error = 0.01; uint32_t umean = usum / rounds; uint32_t emean = esum / rounds; uint32_t uexpect = UINT32_MAX / 2; uint32_t eexpect = 1024; if (umean < uexpect * (1.0 - allowed_error) || umean > uexpect * (1.0 + allowed_error)) { XPR(NT "uniform mean error: %u != %u\n", umean, uexpect); abort(); } if (emean < eexpect * (1.0 - allowed_error) || emean > eexpect * (1.0 + allowed_error)) { XPR(NT "exponential mean error: %u != %u\n", emean, eexpect); abort(); } } void TestRandomFile() { MTRandom rand1; FileSpec spec1(&rand1); BlockIterator bi(spec1); spec1.GenerateFixedSize(0); CHECK_EQ(0, spec1.Size()); CHECK_EQ(0, spec1.Segments()); CHECK_EQ(0, spec1.Blocks()); bi.SetBlock(0); CHECK_EQ(0, bi.BytesOnBlock()); spec1.GenerateFixedSize(1); CHECK_EQ(1, spec1.Size()); CHECK_EQ(1, spec1.Segments()); CHECK_EQ(1, spec1.Blocks()); bi.SetBlock(0); CHECK_EQ(1, bi.BytesOnBlock()); spec1.GenerateFixedSize(Constants::BLOCK_SIZE); CHECK_EQ(Constants::BLOCK_SIZE, spec1.Size()); CHECK_EQ(1, spec1.Segments()); CHECK_EQ(1, spec1.Blocks()); bi.SetBlock(0); CHECK_EQ(Constants::BLOCK_SIZE, bi.BytesOnBlock()); bi.SetBlock(1); CHECK_EQ(0, bi.BytesOnBlock()); spec1.GenerateFixedSize(Constants::BLOCK_SIZE + 1); CHECK_EQ(Constants::BLOCK_SIZE + 1, spec1.Size()); CHECK_EQ(2, spec1.Segments()); CHECK_EQ(2, spec1.Blocks()); bi.SetBlock(0); CHECK_EQ(Constants::BLOCK_SIZE, bi.BytesOnBlock()); bi.SetBlock(1); CHECK_EQ(1, bi.BytesOnBlock()); spec1.GenerateFixedSize(Constants::BLOCK_SIZE * 2); CHECK_EQ(Constants::BLOCK_SIZE * 2, spec1.Size()); CHECK_EQ(2, spec1.Segments()); CHECK_EQ(2, spec1.Blocks()); bi.SetBlock(0); CHECK_EQ(Constants::BLOCK_SIZE, bi.BytesOnBlock()); bi.SetBlock(1); CHECK_EQ(Constants::BLOCK_SIZE, bi.BytesOnBlock()); } void TestFirstByte() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(0); spec1.GenerateFixedSize(1); CHECK_EQ(0, CmpDifferentBytes(spec0, spec0)); CHECK_EQ(0, CmpDifferentBytes(spec1, spec1)); CHECK_EQ(1, CmpDifferentBytes(spec0, spec1)); CHECK_EQ(1, CmpDifferentBytes(spec1, spec0)); spec0.GenerateFixedSize(1); spec0.ModifyTo(Modify1stByte(), &spec1); CHECK_EQ(1, CmpDifferentBytes(spec0, spec1)); spec0.GenerateFixedSize(Constants::BLOCK_SIZE + 1); spec0.ModifyTo(Modify1stByte(), &spec1); CHECK_EQ(1, CmpDifferentBytes(spec0, spec1)); SizeIterator si(&rand, Constants::TEST_ROUNDS); for (; !si.Done(); si.Next()) { size_t size = si.Get(); if (size == 0) { continue; } spec0.GenerateFixedSize(size); spec0.ModifyTo(Modify1stByte(), &spec1); InMemoryEncodeDecode(spec0, spec1, NULL); } } void TestModifyMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); struct { size_t size; size_t addr; } test_cases[] = { { Constants::BLOCK_SIZE, 0 }, { Constants::BLOCK_SIZE / 2, 1 }, { Constants::BLOCK_SIZE, 1 }, { Constants::BLOCK_SIZE * 2, 1 }, }; for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { ChangeList cl1; cl1.push_back(Change(Change::MODIFY, test_cases[i].size, test_cases[i].addr)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size(), spec1.Size()); size_t diff = CmpDifferentBytes(spec0, spec1); CHECK_LE(diff, test_cases[i].size); // There is a 1/256 probability of the changed byte matching the // original value. The following allows double the probability to // pass. CHECK_GE(diff, test_cases[i].size - (2 * test_cases[i].size / 256)); InMemoryEncodeDecode(spec0, spec1, NULL); } } void TestAddMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 2); // TODO: fix this test (for all block sizes)! it's broken because // the same byte could be added? struct { size_t size; size_t addr; size_t expected_adds; } test_cases[] = { { 1, 0, 2 /* 1st byte, last byte (short block) */ }, { 1, 1, 3 /* 1st 2 bytes, last byte */ }, { 1, Constants::BLOCK_SIZE - 1, 2 /* changed, last */ }, { 1, Constants::BLOCK_SIZE, 2 /* changed, last */ }, { 1, Constants::BLOCK_SIZE + 1, 3 /* changed + 1st of 2nd block, last */ }, { 1, 2 * Constants::BLOCK_SIZE, 1 /* last byte */ }, }; for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { ChangeList cl1; cl1.push_back(Change(Change::ADD, test_cases[i].size, test_cases[i].addr)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); Block coded; InMemoryEncodeDecode(spec0, spec1, &coded); Delta delta(coded); CHECK_EQ(test_cases[i].expected_adds, delta.AddedBytes()); } } void TestDeleteMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 4); struct { size_t size; size_t addr; } test_cases[] = { // Note: an entry { Constants::BLOCK_SIZE, 0 }, // does not work because the xd3_srcwin_move_point logic won't // find a copy if it occurs >= double its size into the file. { Constants::BLOCK_SIZE / 2, 0 }, { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2 }, { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE / 2 }, { Constants::BLOCK_SIZE * 2, Constants::BLOCK_SIZE * 3 / 2 }, { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 2 }, }; for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { ChangeList cl1; cl1.push_back(Change(Change::DELETE, test_cases[i].size, test_cases[i].addr)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size() - test_cases[i].size, spec1.Size()); Block coded; InMemoryEncodeDecode(spec0, spec1, &coded); Delta delta(coded); CHECK_EQ(0, delta.AddedBytes()); } } void TestCopyMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); struct { size_t size; size_t from; size_t to; } test_cases[] = { // Copy is difficult to write tests for because where Xdelta finds // copies, it does not enter checksums. So these tests copy data from // later to earlier so that checksumming will start. { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, Constants::BLOCK_SIZE, }, }; for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { ChangeList cl1; cl1.push_back(Change(Change::COPY, test_cases[i].size, test_cases[i].from, test_cases[i].to)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size() + test_cases[i].size, spec1.Size()); Block coded; InMemoryEncodeDecode(spec0, spec1, &coded); Delta delta(coded); CHECK_EQ(0, delta.AddedBytes()); } } void TestMoveMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); struct { size_t size; size_t from; size_t to; } test_cases[] = { // This is easier to test than Copy but has the same trouble as Delete. { Constants::BLOCK_SIZE / 2, Constants::BLOCK_SIZE / 2, 0 }, { Constants::BLOCK_SIZE / 2, 0, Constants::BLOCK_SIZE / 2 }, { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE }, { Constants::BLOCK_SIZE, 2 * Constants::BLOCK_SIZE, Constants::BLOCK_SIZE }, { Constants::BLOCK_SIZE * 3 / 2, Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 3 / 2 }, // This is a no-op { Constants::BLOCK_SIZE, Constants::BLOCK_SIZE * 2, 3 * Constants::BLOCK_SIZE }, }; for (size_t i = 0; i < SIZEOF_ARRAY(test_cases); i++) { ChangeList cl1; cl1.push_back(Change(Change::MOVE, test_cases[i].size, test_cases[i].from, test_cases[i].to)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size(), spec1.Size()); Block coded; InMemoryEncodeDecode(spec0, spec1, &coded); Delta delta(coded); CHECK_EQ(0, delta.AddedBytes()); } } void TestOverwriteMutator() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE); ChangeList cl1; cl1.push_back(Change(Change::COPYOVER, 10, 0, 20)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size(), spec1.Size()); Block b0, b1; BlockIterator(spec0).Get(&b0); BlockIterator(spec1).Get(&b1); CHECK(memcmp(b0.Data(), b1.Data() + 20, 10) == 0); CHECK(memcmp(b0.Data(), b1.Data(), 20) == 0); CHECK(memcmp(b0.Data() + 30, b1.Data() + 30, Constants::BLOCK_SIZE - 30) == 0); cl1.clear(); cl1.push_back(Change(Change::COPYOVER, 10, 20, (xoff_t)0)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); CHECK_EQ(spec0.Size(), spec1.Size()); BlockIterator(spec0).Get(&b0); BlockIterator(spec1).Get(&b1); CHECK(memcmp(b0.Data() + 20, b1.Data(), 10) == 0); CHECK(memcmp(b0.Data() + 10, b1.Data() + 10, Constants::BLOCK_SIZE - 10) == 0); } // Note: this test is written to expose a problem, but the problem was // only exposed with BLOCK_SIZE = 128. void TestNonBlockingProgress() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); FileSpec spec2(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 3); // This is a lazy target match Change ct(Change::COPYOVER, 22, Constants::BLOCK_SIZE + 50, Constants::BLOCK_SIZE + 20); // This is a source match just after the block boundary, shorter // than the lazy target match. Change cs1(Change::COPYOVER, 16, Constants::BLOCK_SIZE + 51, Constants::BLOCK_SIZE - 1); // This overwrites the original source bytes. Change cs2(Change::MODIFY, 108, Constants::BLOCK_SIZE + 20); // This changes the first blocks Change c1st(Change::MODIFY, Constants::BLOCK_SIZE - 2, 0); ChangeList csl; csl.push_back(cs1); csl.push_back(cs2); csl.push_back(c1st); spec0.ModifyTo(ChangeListMutator(csl), &spec1); ChangeList ctl; ctl.push_back(ct); ctl.push_back(c1st); spec0.ModifyTo(ChangeListMutator(ctl), &spec2); InMemoryEncodeDecode(spec1, spec2, NULL); } void TestEmptyInMemory() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); Block block; spec0.GenerateFixedSize(0); spec1.GenerateFixedSize(0); InMemoryEncodeDecode(spec0, spec1, &block); Delta delta(block); CHECK_LT(0, block.Size()); CHECK_EQ(1, delta.Windows()); } void TestBlockInMemory() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); Block block; spec0.GenerateFixedSize(Constants::BLOCK_SIZE); spec1.GenerateFixedSize(Constants::BLOCK_SIZE); InMemoryEncodeDecode(spec0, spec1, &block); Delta delta(block); CHECK_EQ(spec1.Blocks(Constants::WINDOW_SIZE), delta.Windows()); } void TestHalfBlockCopy() { MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 4); // Create a half-block copy, 2.5 blocks apart, from the second half // of the source version to the first half of the target version. // 0 1 2 3 // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbbb] // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] ChangeList cl1; cl1.push_back(Change(Change::MODIFY, Constants::BLOCK_SIZE / 2, // size 0)); cl1.push_back(Change(Change::COPYOVER, Constants::BLOCK_SIZE / 2, // size Constants::BLOCK_SIZE * 3, // offset Constants::BLOCK_SIZE / 2)); cl1.push_back(Change(Change::MODIFY, Constants::BLOCK_SIZE * 3, Constants::BLOCK_SIZE)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); const int onecopy_adds = 4 * Constants::BLOCK_SIZE - Constants::BLOCK_SIZE / 2; const int nocopy_adds = 4 * Constants::BLOCK_SIZE; // Note the case b=4 is contrived: the caller should use a single block // containing the entire source, if possible. for (int b = 1; b <= 4; b++) { Options options; options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * b; Block block0; Block block1; InMemoryEncodeDecode(spec0, spec1, &block0, options); InMemoryEncodeDecode(spec1, spec0, &block1, options); Delta delta0(block0); Delta delta1(block1); // The first block never copies from the last source block, by // design, because if the last source block is available when // the first target block is ready, the caller is expected to // use a single block. CHECK_EQ(nocopy_adds, delta0.AddedBytes()); if (Constants::BLOCK_SIZE < 8192 || b > 2) { // For small-block inputs, the entire file is read into one // block (the min source window size is 16kB). // // For large blocks, at least 3 blocks of source window are // needed. CHECK_EQ(onecopy_adds, delta1.AddedBytes()); } else { // When there are fewer than 3 source blocks. CHECK_EQ(nocopy_adds, delta1.AddedBytes()); } // XPR(NT "0=%zu 1=%zu\n", delta0.AddedBytes(), delta1.AddedBytes()); } Options options; options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4; options.block_size = Constants::BLOCK_SIZE * 4; // Test the whole-buffer case. Block block0; Block block1; InMemoryEncodeDecode(spec0, spec1, &block0, options); InMemoryEncodeDecode(spec1, spec0, &block1, options); Delta delta0(block0); Delta delta1(block1); // This <= >= are only for blocksize = 512, which has irregular readsize. CHECK_LE(onecopy_adds, delta0.AddedBytes()); CHECK_GE(onecopy_adds + 1, delta0.AddedBytes()); CHECK_EQ(onecopy_adds, delta1.AddedBytes()); // XPR(NT "0=%zu 1=%zu\n", delta0.AddedBytes(), delta1.AddedBytes()); } void FourWayMergeTest(const FileSpec &spec0, const FileSpec &spec1, const FileSpec &spec2, const FileSpec &spec3) { TmpFile f0, f1, f2, f3; ExtFile d01, d12, d23; Options options; options.encode_srcwin_maxsz = std::max(spec0.Size(), options.encode_srcwin_maxsz); spec0.WriteTmpFile(&f0); spec1.WriteTmpFile(&f1); spec2.WriteTmpFile(&f2); spec3.WriteTmpFile(&f3); MainEncodeDecode(f0, f1, &d01, options); MainEncodeDecode(f1, f2, &d12, options); MainEncodeDecode(f2, f3, &d23, options); // Merge 2 ExtFile out; vector mcmd; mcmd.push_back("xdelta3"); mcmd.push_back("merge"); mcmd.push_back("-m"); mcmd.push_back(d01.Name()); mcmd.push_back(d12.Name()); mcmd.push_back(out.Name()); mcmd.push_back(NULL); // XPR(NTR "Running one merge: %s\n", CommandToString(mcmd).c_str()); CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, const_cast(&mcmd[0]))); ExtFile recon; vector tcmd; tcmd.push_back("xdelta3"); tcmd.push_back("-d"); tcmd.push_back("-s"); tcmd.push_back(f0.Name()); tcmd.push_back(out.Name()); tcmd.push_back(recon.Name()); tcmd.push_back(NULL); // XPR(NTR "Running one recon! %s\n", CommandToString(tcmd).c_str()); CHECK_EQ(0, xd3_main_cmdline(tcmd.size() - 1, const_cast(&tcmd[0]))); // XPR(NTR "Should equal! %s\n", f2.Name()); CHECK(recon.EqualsSpec(spec2)); // Merge 3 ExtFile out3; vector mcmd3; mcmd3.push_back("xdelta3"); mcmd3.push_back("merge"); mcmd3.push_back("-m"); mcmd3.push_back(d01.Name()); mcmd3.push_back("-m"); mcmd3.push_back(d12.Name()); mcmd3.push_back(d23.Name()); mcmd3.push_back(out3.Name()); mcmd3.push_back(NULL); // XPR(NTR "Running one 3-merge: %s\n", CommandToString(mcmd3).c_str()); CHECK_EQ(0, xd3_main_cmdline(mcmd3.size() - 1, const_cast(&mcmd3[0]))); ExtFile recon3; vector tcmd3; tcmd3.push_back("xdelta3"); tcmd3.push_back("-d"); tcmd3.push_back("-s"); tcmd3.push_back(f0.Name()); tcmd3.push_back(out3.Name()); tcmd3.push_back(recon3.Name()); tcmd3.push_back(NULL); // XPR(NTR "Running one 3-recon %s\n", CommandToString(tcmd3).c_str()); CHECK_EQ(0, xd3_main_cmdline(tcmd3.size() - 1, const_cast(&tcmd3[0]))); // XPR(NTR "Should equal %s\n", f3.Name()); CHECK(recon3.EqualsSpec(spec3)); } void TestMergeCommand1() { /* Repeat random-input testing for a number of iterations. * Test 2, 3, and 4-file scenarios (i.e., 1, 2, and 3-delta merges). */ MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); FileSpec spec2(&rand); FileSpec spec3(&rand); SizeIterator si0(&rand, 10); for (; !si0.Done(); si0.Next()) { size_t size0 = si0.Get(); SizeIterator si1(&rand, 10); for (; !si1.Done(); si1.Next()) { size_t change1 = si1.Get(); if (change1 == 0) { continue; } // XPR(NTR "S0 = %lu\n", size0); // XPR(NTR "C1 = %lu\n", change1); // XPR(NTR "."); size_t add1_pos = size0 ? rand.Rand32() % size0 : 0; size_t del2_pos = size0 ? rand.Rand32() % size0 : 0; spec0.GenerateFixedSize(size0); ChangeList cl1, cl2, cl3; size_t change3 = change1; size_t change3_pos; if (change3 >= size0) { change3 = size0; change3_pos = 0; } else { change3_pos = rand.Rand32() % (size0 - change3); } cl1.push_back(Change(Change::ADD, change1, add1_pos)); cl2.push_back(Change(Change::DELETE, change1, del2_pos)); cl3.push_back(Change(Change::MODIFY, change3, change3_pos)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); spec1.ModifyTo(ChangeListMutator(cl2), &spec2); spec2.ModifyTo(ChangeListMutator(cl3), &spec3); FourWayMergeTest(spec0, spec1, spec2, spec3); FourWayMergeTest(spec3, spec2, spec1, spec0); } } } void TestMergeCommand2() { /* Same as above, different mutation pattern. */ /* TODO: run this with large sizes too */ /* TODO: run this with small sizes too */ MTRandom rand; FileSpec spec0(&rand); FileSpec spec1(&rand); FileSpec spec2(&rand); FileSpec spec3(&rand); SizeIterator si0(&rand, 10); for (; !si0.Done(); si0.Next()) { size_t size0 = si0.Get(); SizeIterator si1(&rand, 10); for (; !si1.Done(); si1.Next()) { size_t size1 = si1.Get(); SizeIterator si2(&rand, 10); for (; !si2.Done(); si2.Next()) { size_t size2 = si2.Get(); SizeIterator si3(&rand, 10); for (; !si3.Done(); si3.Next()) { size_t size3 = si3.Get(); // We're only interested in three sizes, strictly decreasing. */ if (size3 >= size2 || size2 >= size1 || size1 >= size0) { continue; } // XPR(NTR "S0 = %lu\n", size0); // XPR(NTR "S1 = %lu\n", size1); // XPR(NTR "S2 = %lu\n", size2); // XPR(NTR "S3 = %lu\n", size3); // XPR(NTR "."); spec0.GenerateFixedSize(size0); ChangeList cl1, cl2, cl3; cl1.push_back(Change(Change::DELETE, size0 - size1, 0)); cl2.push_back(Change(Change::DELETE, size0 - size2, 0)); cl3.push_back(Change(Change::DELETE, size0 - size3, 0)); spec0.ModifyTo(ChangeListMutator(cl1), &spec1); spec0.ModifyTo(ChangeListMutator(cl2), &spec2); spec0.ModifyTo(ChangeListMutator(cl3), &spec3); FourWayMergeTest(spec0, spec1, spec2, spec3); FourWayMergeTest(spec3, spec2, spec1, spec0); } } } } } }; // class Regtest #define TEST(x) XPR(NTR #x "...\n"); regtest.x() // These tests are primarily tests of the testing framework itself. template void UnitTest() { Regtest regtest; TEST(TestRandomNumbers); TEST(TestRandomFile); TEST(TestFirstByte); TEST(TestModifyMutator); TEST(TestAddMutator); TEST(TestDeleteMutator); TEST(TestCopyMutator); TEST(TestMoveMutator); TEST(TestOverwriteMutator); } // These are Xdelta tests. template void MainTest() { XPR(NT "Blocksize %"Q"u readsize %"Q"u windowsize %"Q"u\n", T::BLOCK_SIZE, T::READ_SIZE, T::WINDOW_SIZE); Regtest regtest; TEST(TestEmptyInMemory); TEST(TestBlockInMemory); TEST(TestNonBlockingProgress); TEST(TestHalfBlockCopy); TEST(TestMergeCommand1); TEST(TestMergeCommand2); } #undef TEST int main(int argc, char **argv) { vector mcmd; string pn; const char *sp = strrchr(argv[0], '/'); if (sp != NULL) { pn.append(argv[0], sp - argv[0] + 1); } pn.append("xdelta3"); mcmd.push_back(pn.c_str()); mcmd.push_back("test"); mcmd.push_back(NULL); UnitTest(); MainTest(); MainTest(); MainTest(); MainTest(); MainTest(); CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, const_cast(&mcmd[0]))); return 0; } xdelta3-3.0.7/testing/delta.h0000644000176500017650000000275012105354541015270 0ustar debdevdebdev// Mode: -*- C++ -*- class Delta { public: Delta(const Block &block) { int ret; xd3_config config; memset(&stream_, 0, sizeof (stream_)); memset(&config, 0, sizeof (config)); xd3_init_config(&config, XD3_SKIP_EMIT | XD3_ADLER32_NOVER); CHECK_EQ(0, xd3_config_stream (&stream_, &config)); xd3_avail_input (&stream_, block.Data(), block.Size()); bool done = false; while (!done) { ret = xd3_decode_input(&stream_); switch (ret) { case XD3_INPUT: done = true; break; case XD3_OUTPUT: CHECK_EQ(0, xd3_whole_append_window (&stream_)); break; case XD3_GOTHEADER: case XD3_WINSTART: case XD3_WINFINISH: break; default: DP(RINT "error code %s\n", xd3_strerror (ret)); abort(); } } } ~Delta() { xd3_free_stream(&stream_); } xoff_t AddedBytes() const { return stream_.whole_target.addslen; } xoff_t Windows() const { return stream_.whole_target.wininfolen; } void Print() const { for (size_t i = 0; i < stream_.whole_target.instlen; i++) { xd3_winst &winst = stream_.whole_target.inst[i]; switch (winst.type) { case XD3_RUN: DP(RINT "%"Q"u run %u\n", winst.position, winst.size); break; case XD3_ADD: DP(RINT "%"Q"u add %u\n", winst.position, winst.size); break; default: DP(RINT "%"Q"u copy %u @ %"Q"u (mode %u)\n", winst.position, winst.size, winst.addr, winst.mode); break; } } } private: xd3_stream stream_; }; xdelta3-3.0.7/testing/test.h0000644000176500017650000000276512143366406015171 0ustar debdevdebdev// -*- Mode: C++ -*- extern "C" { #include "../xdelta3.h" #include "../xdelta3-internal.h" } #include #include #include #define CHECK_EQ(x,y) CHECK_OP(x,y,==) #define CHECK_NE(x,y) CHECK_OP(x,y,!=) #define CHECK_LT(x,y) CHECK_OP(x,y,<) #define CHECK_GT(x,y) CHECK_OP(x,y,>) #define CHECK_LE(x,y) CHECK_OP(x,y,<=) #define CHECK_GE(x,y) CHECK_OP(x,y,>=) #define CHECK_OP(x,y,OP) \ do { \ typeof(x) _x(x); \ typeof(x) _y(y); \ if (!(_x OP _y)) { \ cerr << __FILE__ << ":" << __LINE__ << " Check failed: " << #x " " #OP " " #y << endl; \ cerr << __FILE__ << ":" << __LINE__ << " Expected: " << _x << endl; \ cerr << __FILE__ << ":" << __LINE__ << " Actual: " << _y << endl; \ abort(); \ } } while (false) #undef CHECK #define CHECK(x) \ do {if (!(x)) { \ cerr << __FILE__ << ":" << __LINE__ << " Check failed: " << #x << endl; \ abort(); \ } } while (false) #define DCHECK(x) using std::string; #include using std::vector; inline string CommandToString(const vector &v) { string s(v[0]); for (size_t i = 1; i < v.size() && v[i] != NULL; i++) { s.append(" "); s.append(v[i]); } return s; } #include using std::cerr; using std::endl; using std::ostream; #include using std::map; using std::pair; #include using std::list; template pair make_pair(const T& t, const U& u) { return pair(t, u); } using std::min; using std::max; xdelta3-3.0.7/testing/file.h0000644000176500017650000001662412144212764015126 0ustar debdevdebdev/* -*- Mode: C++ -*- */ class Block; class BlockIterator; class TmpFile; class Block { public: Block() : data_(NULL), data_size_(0), size_(0) { } ~Block() { if (data_) { delete [] data_; } } size_t Size() const { return size_; } uint8_t operator[](size_t i) const { CHECK_LT(i, size_); return data_[i]; } uint8_t* Data() const { if (data_ == NULL) { CHECK_EQ(0, size_); data_size_ = 1; data_ = new uint8_t[1]; } return data_; } // For writing to blocks void Append(const uint8_t *data, size_t size) { if (data_ == NULL) { CHECK_EQ(0, size_); CHECK_EQ(0, data_size_); data_ = new uint8_t[Constants::BLOCK_SIZE]; data_size_ = Constants::BLOCK_SIZE; } if (size_ + size > data_size_) { uint8_t *tmp = data_; while (size_ + size > data_size_) { data_size_ *= 2; } data_ = new uint8_t[data_size_]; memcpy(data_, tmp, size_); delete tmp; } memcpy(data_ + size_, data, size); size_ += size; } // For cleaing a block void Reset() { size_ = 0; } void Print() const { xoff_t pos = 0; for (size_t i = 0; i < Size(); i++) { if (pos % 16 == 0) { DP(RINT "%5"Q"x: ", pos); } DP(RINT "%02x ", (*this)[i]); if (pos % 16 == 15) { DP(RINT "\n"); } pos++; } DP(RINT "\n"); } void WriteTmpFile(TmpFile *f) const { f->Append(this); } void SetSize(size_t size) { size_ = size; if (data_size_ < size) { if (data_) { delete [] data_; } data_ = new uint8_t[size]; data_size_ = size; } } private: friend class BlockIterator; mutable uint8_t *data_; mutable size_t data_size_; size_t size_; }; class FileSpec { public: FileSpec(MTRandom *rand) : rand_(rand) { } // Generates a file with a known size void GenerateFixedSize(xoff_t size) { Reset(); for (xoff_t p = 0; p < size; ) { xoff_t t = min(Constants::BLOCK_SIZE, size - p); table_.insert(make_pair(p, Segment(t, rand_))); p += t; } } // Generates a file with exponential-random distributed size void GenerateRandomSize(xoff_t mean) { GenerateFixedSize(rand_->ExpRand(mean)); } // Returns the size of the file xoff_t Size() const { if (table_.empty()) { return 0; } ConstSegmentMapIterator i = --table_.end(); return i->first + i->second.Size(); } // Returns the number of blocks xoff_t Blocks(size_t blksize = Constants::BLOCK_SIZE) const { if (table_.empty()) { return 0; } return ((Size() - 1) / blksize) + 1; } // Returns the number of segments xoff_t Segments() const { return table_.size(); } // Create a mutation according to "what". void ModifyTo(const Mutator &mutator, FileSpec *modify) const { modify->Reset(); mutator.Mutate(&modify->table_, &table_, rand_); modify->CheckSegments(); } void CheckSegments() const { for (ConstSegmentMapIterator iter(table_.begin()); iter != table_.end(); ) { ConstSegmentMapIterator iter0(iter++); if (iter == table_.end()) { break; } CHECK_EQ(iter0->first + iter0->second.Size(), iter->first); } } void Reset() { table_.clear(); } void Print() const { for (ConstSegmentMapIterator iter(table_.begin()); iter != table_.end(); ++iter) { const Segment &seg = iter->second; cerr << "Segment at " << iter->first << " (" << seg.ToString() << ")" << endl; } } void PrintData() const { Block block; for (BlockIterator iter(*this); !iter.Done(); iter.Next()) { iter.Get(&block); block.Print(); } } void WriteTmpFile(TmpFile *f) const { Block block; for (BlockIterator iter(*this); !iter.Done(); iter.Next()) { iter.Get(&block); f->Append(&block); } } void Get(Block *block, xoff_t offset, size_t size) const { size_t got = 0; block->SetSize(size); ConstSegmentMapIterator pos = table_.upper_bound(offset); if (pos == table_.begin()) { CHECK_EQ(0, Size()); return; } --pos; while (got < size) { CHECK(pos != table_.end()); CHECK_GE(offset, pos->first); const Segment &seg = pos->second; // The position of this segment may start before this block starts, // and then the position of the data may be offset from the seeding // position. size_t seg_offset = offset - pos->first; size_t advance = min(seg.Size() - seg_offset, size - got); seg.Fill(seg_offset, advance, block->Data() + got); got += advance; offset += advance; ++pos; } } typedef BlockIterator iterator; private: friend class BlockIterator; MTRandom *rand_; SegmentMap table_; }; class BlockIterator { public: explicit BlockIterator(const FileSpec& spec) : spec_(spec), blkno_(0), blksize_(Constants::BLOCK_SIZE) { } BlockIterator(const FileSpec& spec, size_t blksize) : spec_(spec), blkno_(0), blksize_(blksize) { } bool Done() const { return blkno_ >= spec_.Blocks(blksize_); } void Next() { blkno_++; } xoff_t Blkno() const { return blkno_; } xoff_t Blocks() const { return spec_.Blocks(blksize_); } xoff_t Offset() const { return blkno_ * blksize_; } void SetBlock(xoff_t blkno) { blkno_ = blkno; } void Get(Block *block) const { spec_.Get(block, blkno_ * blksize_, BytesOnBlock()); } size_t BytesOnBlock() const { xoff_t blocks = spec_.Blocks(blksize_); xoff_t size = spec_.Size(); DCHECK((blkno_ < blocks) || (blkno_ == blocks && size % blksize_ == 0)); if (blkno_ == blocks) { return 0; } if (blkno_ + 1 == blocks) { return ((size - 1) % blksize_) + 1; } return blksize_; } size_t BlockSize() const { return blksize_; } private: const FileSpec& spec_; xoff_t blkno_; size_t blksize_; }; class ExtFile { public: ExtFile() { static int static_counter = 0; char buf[32]; snprintf(buf, 32, "/tmp/regtest.%d", static_counter++); filename_.append(buf); unlink(filename_.c_str()); } ~ExtFile() { unlink(filename_.c_str()); } const char* Name() const { return filename_.c_str(); } // Check whether a real file matches a file spec. bool EqualsSpec(const FileSpec &spec) const { main_file t; main_file_init(&t); CHECK_EQ(0, main_file_open(&t, Name(), XO_READ)); Block tblock; Block sblock; for (BlockIterator iter(spec); !iter.Done(); iter.Next()) { iter.Get(&sblock); tblock.SetSize(sblock.Size()); size_t tread; CHECK_EQ(0, main_file_read(&t, tblock.Data(), tblock.Size(), &tread, "read failed")); CHECK_EQ(0, CmpDifferentBlockBytes(tblock, sblock)); } CHECK_EQ(0, main_file_close(&t)); main_file_cleanup(&t); return true; } protected: string filename_; }; class TmpFile : public ExtFile { public: TmpFile() { main_file_init(&file_); CHECK_EQ(0, main_file_open(&file_, Name(), XO_WRITE)); } ~TmpFile() { main_file_cleanup(&file_); } void Append(const Block *block) { CHECK_EQ(0, main_file_write(&file_, block->Data(), block->Size(), "tmpfile write failed")); } const char* Name() const { if (main_file_isopen(&file_)) { CHECK_EQ(0, main_file_close(&file_)); } return ExtFile::Name(); } private: mutable main_file file_; }; xdelta3-3.0.7/testing/regtest_c.c0000644000176500017650000000006112105354541016142 0ustar debdevdebdev/* -*- Mode: C++ -*- */ #include "../xdelta3.c" xdelta3-3.0.7/testing/xdelta3-regtest.py0000755000176500017650000010442312105354541017422 0ustar debdevdebdev#!/usr/bin/python2.6 # xdelta 3 - delta compression tools and library # Copyright (C) 2003, 2006, 2007, 2008. Joshua P. MacDonald # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # TODO: test 1.5 vs. greedy import os, sys, math, re, time, types, array, random import xdelta3 #RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS' #RCSDIR = '/tmp/PRCS_read_copy' #SAMPLEDIR = "/tmp/WESNOTH_tmp/diff" #RCSDIR = 'G:/jmacd/PRCS_copy' #SAMPLEDIR = "C:/sample_data/Wesnoth/tar" RCSDIR = '/Users/jmacd/src/ftp.kernel.org' SAMPLEDIR = '/Users/jmacd/src/xdelta3/linux' # MIN_SIZE = 0 TIME_TOO_SHORT = 0.050 SKIP_TRIALS = 2 MIN_TRIALS = 3 MAX_TRIALS = 15 # 10 = fast 1.5 = slow MIN_STDDEV_PCT = 1.5 # How many results per round MAX_RESULTS = 500 TEST_ROUNDS = 10 KEEP_P = (0.5) # For RCS testing, what percent to select FILE_P = (0.50) # For run-speed tests MIN_RUN = 1000 * 1000 * 1 MAX_RUN = 1000 * 1000 * 10 # Testwide defaults ALL_ARGS = [ '-q' # '-vv' ] # The first 7 args go to -C SOFT_CONFIG_CNT = 7 CONFIG_ORDER = [ 'large_look', 'large_step', 'small_look', 'small_chain', 'small_lchain', 'max_lazy', 'long_enough', # > SOFT_CONFIG_CNT 'nocompress', 'winsize', 'srcwinsize', 'sprevsz', 'iopt', 'djw', 'altcode', ] CONFIG_ARGMAP = { 'winsize' : '-W', 'srcwinsize' : '-B', 'sprevsz' : '-P', 'iopt' : '-I', 'nocompress' : '-N', 'djw' : '-Sdjw', 'altcode' : '-T', } def INPUT_SPEC(rand): return { # Time/space costs: # -C 1,2,3,4,5,6,7 'large_look' : lambda d: rand.choice([9, 10, 11, 12]), 'large_step' : lambda d: rand.choice([25, 26, 27, 28, 29, 30]), 'small_look' : lambda d: rand.choice([4]), 'small_chain' : lambda d: rand.choice([1]), 'small_lchain' : lambda d: rand.choice([1]), 'max_lazy' : lambda d: rand.choice([4, 5, 6, 7, 8, 9, 10 ]), # Note: long_enough only refers to small matching and has no effect if # small_chain == 1. 'long_enough' : lambda d: rand.choice([4]), # -N 'nocompress' : lambda d: rand.choice(['false']), # -T 'altcode' : lambda d: rand.choice(['false']), # -S djw 'djw' : lambda d: rand.choice(['false']), # Memory costs: # -W 'winsize' : lambda d: 8 * (1<<20), # -B 'srcwinsize' : lambda d: 64 * (1<<20), # -I 0 is unlimited 'iopt' : lambda d: 0, # -P only powers of two 'sprevsz' : lambda d: rand.choice([x * (1<<16) for x in [4]]), } #end # TMPDIR = '/tmp/xd3regtest.%d' % os.getpid() RUNFILE = os.path.join(TMPDIR, 'run') DFILE = os.path.join(TMPDIR, 'output') RFILE = os.path.join(TMPDIR, 'recon') CMPTMP1 = os.path.join(TMPDIR, 'cmptmp1') CMPTMP2 = os.path.join(TMPDIR, 'cmptmp2') HEAD_STATE = 0 BAR_STATE = 1 REV_STATE = 2 DATE_STATE = 3 # IGNORE_FILENAME = re.compile('.*\\.(gif|jpg).*') # rcs output RE_TOTREV = re.compile('total revisions: (\\d+)') RE_BAR = re.compile('----------------------------') RE_REV = re.compile('revision (.+)') RE_DATE = re.compile('date: ([^;]+);.*') # xdelta output RE_HDRSZ = re.compile('VCDIFF header size: +(\\d+)') RE_EXTCOMP = re.compile('XDELTA ext comp.*') def c2str(c): return ' '.join(['%s' % x for x in c]) #end def SumList(l): return reduce(lambda x,y: x+y, l) #end # returns (total, mean, stddev, q2 (median), # (q3-q1)/2 ("semi-interquartile range"), max-min (spread)) class StatList: def __init__(self,l,desc): cnt = len(l) assert(cnt > 1) l.sort() self.cnt = cnt self.l = l self.total = SumList(l) self.mean = self.total / float(self.cnt) self.s = math.sqrt(SumList([(x-self.mean) * (x - self.mean) for x in l]) / float(self.cnt-1)) self.q0 = l[0] self.q1 = l[int(self.cnt/4.0+0.5)] self.q2 = l[int(self.cnt/2.0+0.5)] self.q3 = l[min(self.cnt-1,int((3.0*self.cnt)/4.0+0.5))] self.q4 = l[self.cnt-1] self.siqr = (self.q3-self.q1)/2.0; self.spread = (self.q4-self.q0) if len(l) == 1: self.str = '%s %s' % (desc, l[0]) else: self.str = '%s mean %.1f: 25%-ile %d %d %d %d %d' % \ (desc, self.mean, self.q0, self.q1, self.q2, self.q3, self.q4) #end #end def RunCommand(args, ok = [0]): #print 'run command %s' % (' '.join(args)) p = os.spawnvp(os.P_WAIT, args[0], args) if p not in ok: raise CommandError(args, 'exited %d' % p) #end #end def RunCommandIO(args,infn,outfn): p = os.fork() if p == 0: os.dup2(os.open(infn,os.O_RDONLY),0) os.dup2(os.open(outfn,os.O_CREAT|os.O_TRUNC|os.O_WRONLY),1) os.execvp(args[0], args) else: s = os.waitpid(p,0) o = os.WEXITSTATUS(s[1]) if not os.WIFEXITED(s[1]) or o != 0: raise CommandError(args, 'exited %d' % o) #end #end #end class TimedTest: def __init__(self, target, source, runnable, skip_trials = SKIP_TRIALS, min_trials = MIN_TRIALS, max_trials = MAX_TRIALS, min_stddev_pct = MIN_STDDEV_PCT): self.target = target self.source = source self.runnable = runnable self.skip_trials = skip_trials self.min_trials = min(min_trials, max_trials) self.max_trials = max_trials self.min_stddev_pct = min_stddev_pct self.encode_time = self.DoTest(DFILE, lambda x: x.Encode(self.target, self.source, DFILE)) self.encode_size = runnable.EncodeSize(DFILE) self.decode_time = self.DoTest(RFILE, lambda x: x.Decode(DFILE, self.source, RFILE), ) runnable.Verify(self.target, RFILE) #end def DoTest(self, fname, func): trials = 0 measured = [] while 1: try: os.remove(fname) except OSError: pass start_time = time.time() start_clock = time.clock() func(self.runnable) total_clock = (time.clock() - start_clock) total_time = (time.time() - start_time) elap_time = max(total_time, 0.0000001) elap_clock = max(total_clock, 0.0000001) trials = trials + 1 # skip some of the first trials if trials > self.skip_trials: measured.append((elap_clock, elap_time)) #print 'measurement total: %.1f ms' % (total_time * 1000.0) # at least so many if trials < (self.skip_trials + self.min_trials): #print 'continue: need more trials: %d' % trials continue # compute %variance done = 0 if self.skip_trials + self.min_trials <= 2: measured = measured + measured; done = 1 #end time_stat = StatList([x[1] for x in measured], 'elap time') sp = float(time_stat.s) / float(time_stat.mean) # what if MAX_TRIALS is exceeded? too_many = (trials - self.skip_trials) >= self.max_trials good = (100.0 * sp) < self.min_stddev_pct if done or too_many or good: trials = trials - self.skip_trials if not done and not good: #print 'too many trials: %d' % trials pass #clock = StatList([x[0] for x in measured], 'elap clock') return time_stat #end #end #end #end def Decimals(start, end): l = [] step = start while 1: r = range(step, step * 10, step) l = l + r if step * 10 >= end: l.append(step * 10) break step = step * 10 return l #end # This tests the raw speed of 0-byte inputs def RunSpeedTest(): for L in Decimals(MIN_RUN, MAX_RUN): SetFileSize(RUNFILE, L) trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<20)])) ReportSpeed(L, trx, '1MB ') trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<19)])) ReportSpeed(L, trx, '512k') trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<18)])) ReportSpeed(L, trx, '256k') trm = TimedTest(RUNFILE, None, Xdelta3Mod1(RUNFILE)) ReportSpeed(L, trm, 'swig') trg = TimedTest(RUNFILE, None, GzipRun1()) ReportSpeed(L,trg,'gzip') #end #end def SetFileSize(F,L): fd = os.open(F, os.O_CREAT | os.O_WRONLY) os.ftruncate(fd,L) assert os.fstat(fd).st_size == L os.close(fd) #end def ReportSpeed(L,tr,desc): print '%s run length %u: size %u: time %.3f ms: decode %.3f ms' % \ (desc, L, tr.encode_size, tr.encode_time.mean * 1000.0, tr.decode_time.mean * 1000.0) #end class Xdelta3RunClass: def __init__(self, extra): self.extra = extra #end def __str__(self): return ' '.join(self.extra) #end def New(self): return Xdelta3Runner(self.extra) #end #end class Xdelta3Runner: # Use "forkexec" to get special command-line only features like # external compression support. def __init__(self, extra, forkexec=False): self.forkexec = forkexec self.extra = extra #end def Encode(self, target, source, output): args = (ALL_ARGS + self.extra + ['-e']) if source: args.append('-s') args.append(source) #end args = args + [target, output] self.Main(args) #end def Decode(self, input, source, output): args = (ALL_ARGS + ['-d']) if source: args.append('-s') args.append(source) #end args = args + [input, output] self.Main(args) #end def Verify(self, target, recon): if target[-3:] == ".gz": RunCommandIO(('gzip', '-dc'), target, CMPTMP1) RunCommandIO(('gzip', '-dc'), recon, CMPTMP2) RunCommand(('cmp', CMPTMP1, CMPTMP2)) else: RunCommand(('cmp', target, recon)) #end def EncodeSize(self, output): return os.stat(output).st_size #end def Main(self, args): try: if self.forkexec: RunCommand(['../xdelta3'] + args) else: xdelta3.xd3_main_cmdline(args) except Exception, e: raise CommandError(args, "xdelta3.main exception: %s" % e) #end #end #end class Xdelta3Mod1: def __init__(self, file): self.target_data = open(file, 'r').read() #end def Encode(self, ignore1, ignore2, ignore3): r1, encoded = xdelta3.xd3_encode_memory(self.target_data, None, 1000000, 1<<10) if r1 != 0: raise CommandError('memory', 'encode failed: %s' % r1) #end self.encoded = encoded #end def Decode(self, ignore1, ignore2, ignore3): r2, data1 = xdelta3.xd3_decode_memory(self.encoded, None, len(self.target_data)) if r2 != 0: raise CommandError('memory', 'decode failed: %s' % r1) #end self.decoded = data1 #end def Verify(self, ignore1, ignore2): if self.target_data != self.decoded: raise CommandError('memory', 'bad decode') #end #end def EncodeSize(self, ignore1): return len(self.encoded) #end #end class GzipRun1: def Encode(self, target, source, output): assert source == None RunCommandIO(['gzip', '-cf'], target, output) #end def Decode(self, input, source, output): assert source == None RunCommandIO(['gzip', '-dcf'], input, output) #end def Verify(self, target, recon): RunCommand(('cmp', target, recon)) #end def EncodeSize(self, output): return os.stat(output).st_size #end #end class Xdelta1RunClass: def __str__(self): return 'xdelta1' #end def New(self): return Xdelta1Runner() #end #end class Xdelta1Runner: def Encode(self, target, source, output): assert source != None args = ['xdelta1', 'delta', '-q', source, target, output] RunCommand(args, [0, 1]) #end def Decode(self, input, source, output): assert source != None args = ['xdelta1', 'patch', '-q', input, source, output] # Note: for dumb historical reasons, xdelta1 returns 1 or 0 RunCommand(args) #end def Verify(self, target, recon): RunCommand(('cmp', target, recon)) #end def EncodeSize(self, output): return os.stat(output).st_size #end #end # exceptions class SkipRcsException: def __init__(self,reason): self.reason = reason #end #end class NotEnoughVersions: def __init__(self): pass #end #end class CommandError: def __init__(self,cmd,str): if type(cmd) is types.TupleType or \ type(cmd) is types.ListType: cmd = reduce(lambda x,y: '%s %s' % (x,y),cmd) #end print 'command was: ',cmd print 'command failed: ',str print 'have fun debugging' #end #end class RcsVersion: def __init__(self,vstr): self.vstr = vstr #end def __cmp__(self,other): return cmp(self.date, other.date) #end def __str__(self): return str(self.vstr) #end #end class RcsFile: def __init__(self, fname): self.fname = fname self.versions = [] self.state = HEAD_STATE #end def SetTotRev(self,s): self.totrev = int(s) #end def Rev(self,s): self.rev = RcsVersion(s) if len(self.versions) >= self.totrev: raise SkipRcsException('too many versions (in log messages)') #end self.versions.append(self.rev) #end def Date(self,s): self.rev.date = s #end def Match(self, line, state, rx, gp, newstate, f): if state == self.state: m = rx.match(line) if m: if f: f(m.group(gp)) #end self.state = newstate return 1 #end #end return None #end def Sum1Rlog(self): f = os.popen('rlog '+self.fname, "r") l = f.readline() while l: if self.Match(l, HEAD_STATE, RE_TOTREV, 1, BAR_STATE, self.SetTotRev): pass elif self.Match(l, BAR_STATE, RE_BAR, 1, REV_STATE, None): pass elif self.Match(l, REV_STATE, RE_REV, 1, DATE_STATE, self.Rev): pass elif self.Match(l, DATE_STATE, RE_DATE, 1, BAR_STATE, self.Date): pass #end l = f.readline() #end c = f.close() if c != None: raise c #end #end def Sum1(self): st = os.stat(self.fname) self.rcssize = st.st_size self.Sum1Rlog() if self.totrev != len(self.versions): raise SkipRcsException('wrong version count') #end self.versions.sort() #end def Checkout(self,n): v = self.versions[n] out = open(self.Verf(n), "w") cmd = 'co -ko -p%s %s' % (v.vstr, self.fname) total = 0 (inf, stream, err) = os.popen3(cmd, "r") inf.close() buf = stream.read() while buf: total = total + len(buf) out.write(buf) buf = stream.read() #end v.vsize = total estr = '' buf = err.read() while buf: estr = estr + buf buf = err.read() #end if stream.close(): raise CommandError(cmd, 'checkout failed: %s\n%s\n%s' % (v.vstr, self.fname, estr)) #end out.close() err.close() #end def Vdate(self,n): return self.versions[n].date #end def Vstr(self,n): return self.versions[n].vstr #end def Verf(self,n): return os.path.join(TMPDIR, 'input.%d' % n) #end def FilePairsByDate(self, runclass): if self.totrev < 2: raise NotEnoughVersions() #end self.Checkout(0) ntrials = [] if self.totrev < 2: return vtrials #end for v in range(0,self.totrev-1): if v > 1: os.remove(self.Verf(v-1)) #end self.Checkout(v+1) if os.stat(self.Verf(v)).st_size < MIN_SIZE or \ os.stat(self.Verf(v+1)).st_size < MIN_SIZE: continue #end result = TimedTest(self.Verf(v+1), self.Verf(v), runclass.New()) target_size = os.stat(self.Verf(v+1)).st_size ntrials.append(result) #end os.remove(self.Verf(self.totrev-1)) os.remove(self.Verf(self.totrev-2)) return ntrials #end def AppendVersion(self, f, n): self.Checkout(n) rf = open(self.Verf(n), "r") data = rf.read() f.write(data) rf.close() return len(data) #end class RcsFinder: def __init__(self): self.subdirs = [] self.rcsfiles = [] self.others = [] self.skipped = [] self.biground = 0 #end def Scan1(self,dir): dents = os.listdir(dir) subdirs = [] rcsfiles = [] others = [] for dent in dents: full = os.path.join(dir, dent) if os.path.isdir(full): subdirs.append(full) elif dent[len(dent)-2:] == ",v": rcsfiles.append(RcsFile(full)) else: others.append(full) #end #end self.subdirs = self.subdirs + subdirs self.rcsfiles = self.rcsfiles + rcsfiles self.others = self.others + others return subdirs #end def Crawl(self, dir): subdirs = [dir] while subdirs: s1 = self.Scan1(subdirs[0]) subdirs = subdirs[1:] + s1 #end #end def Summarize(self): good = [] for rf in self.rcsfiles: try: rf.Sum1() if rf.totrev < 2: raise SkipRcsException('too few versions (< 2)') #end except SkipRcsException, e: #print 'skipping file %s: %s' % (rf.fname, e.reason) self.skipped.append(rf) else: good.append(rf) #end self.rcsfiles = good #end def AllPairsByDate(self, runclass): results = [] good = [] for rf in self.rcsfiles: try: results = results + rf.FilePairsByDate(runclass) except SkipRcsException: print 'file %s has compressed versions: skipping' % (rf.fname) except NotEnoughVersions: print 'testing %s on %s: not enough versions' % (runclass, rf.fname) else: good.append(rf) #end self.rcsfiles = good self.ReportPairs(runclass, results) return results #end def ReportPairs(self, name, results): encode_time = 0 decode_time = 0 encode_size = 0 for r in results: encode_time += r.encode_time.mean decode_time += r.decode_time.mean encode_size += r.encode_size #end print '%s rcs: encode %.2f s: decode %.2f s: size %d' % \ (name, encode_time, decode_time, encode_size) #end def MakeBigFiles(self, rand): f1 = open(TMPDIR + "/big.1", "w") f2 = open(TMPDIR + "/big.2", "w") population = [] for file in self.rcsfiles: if len(file.versions) < 2: continue population.append(file) #end f1sz = 0 f2sz = 0 fcount = int(len(population) * FILE_P) assert fcount > 0 for file in rand.sample(population, fcount): m = IGNORE_FILENAME.match(file.fname) if m != None: continue #end r1, r2 = rand.sample(xrange(0, len(file.versions)), 2) f1sz += file.AppendVersion(f1, r1) f2sz += file.AppendVersion(f2, r2) #m.update('%s,%s,%s ' % (file.fname[len(RCSDIR):], #file.Vstr(r1), file.Vstr(r2))) #end testkey = 'rcs%d' % self.biground self.biground = self.biground + 1 print '%s; source %u bytes; target %u bytes' % (testkey, f1sz, f2sz) f1.close() f2.close() return (TMPDIR + "/big.1", TMPDIR + "/big.2", testkey) #end def Generator(self): return lambda rand: self.MakeBigFiles(rand) #end #end # find a set of RCS files for testing def GetTestRcsFiles(): rcsf = RcsFinder() rcsf.Crawl(RCSDIR) if len(rcsf.rcsfiles) == 0: raise CommandError('', 'no RCS files') #end rcsf.Summarize() print "rcsfiles: rcsfiles %d; subdirs %d; others %d; skipped %d" % ( len(rcsf.rcsfiles), len(rcsf.subdirs), len(rcsf.others), len(rcsf.skipped)) print StatList([x.rcssize for x in rcsf.rcsfiles], "rcssize").str print StatList([x.totrev for x in rcsf.rcsfiles], "totrev").str return rcsf #end class SampleDataTest: def __init__(self, dirs): dirs_in = dirs self.pairs = [] while dirs: d = dirs[0] dirs = dirs[1:] l = os.listdir(d) files = [] for e in l: p = os.path.join(d, e) if os.path.isdir(p): dirs.append(p) else: files.append(p) #end #end if len(files) > 1: files.sort() for x in xrange(len(files)): for y in xrange(len(files)): self.pairs.append((files[x], files[y], '%s-%s' % (files[x], files[y]))) #end #end #end #end print "Sample data test using %d file pairs in %s" % ( len(self.pairs), dirs_in) #end def Generator(self): return lambda rand: rand.choice(self.pairs) #end #end # configs are represented as a list of values, # program takes a list of strings: def ConfigToArgs(config): args = [ '-C', ','.join([str(x) for x in config[0:SOFT_CONFIG_CNT]])] for i in range(SOFT_CONFIG_CNT, len(CONFIG_ORDER)): key = CONFIG_ARGMAP[CONFIG_ORDER[i]] val = config[i] if val == 'true' or val == 'false': if val == 'true': args.append('%s' % key) #end else: args.append('%s=%s' % (key, val)) #end #end return args #end # class RandomTest: def __init__(self, tnum, tinput, config, syntuple = None): self.mytinput = tinput[2] self.myconfig = config self.tnum = tnum if syntuple != None: self.runtime = syntuple[0] self.compsize = syntuple[1] self.decodetime = None else: args = ConfigToArgs(config) result = TimedTest(tinput[1], tinput[0], Xdelta3Runner(args)) self.runtime = result.encode_time.mean self.compsize = result.encode_size self.decodetime = result.decode_time.mean #end self.score = None self.time_pos = None self.size_pos = None self.score_pos = None #end def __str__(self): decodestr = ' %s' % self.decodetime return 'time %.6f%s size %d%s << %s >>%s' % ( self.time(), ((self.time_pos != None) and (" (%s)" % self.time_pos) or ""), self.size(), ((self.size_pos != None) and (" (%s)" % self.size_pos) or ""), c2str(self.config()), decodestr) #end def time(self): return self.runtime #end def size(self): return self.compsize #end def config(self): return self.myconfig #end def score(self): return self.score #end def tinput(self): return self.mytinput #end #end def PosInAlist(l, e): for i in range(0, len(l)): if l[i][1] == e: return i; #end #end return -1 #end # Generates a set of num_results test configurations, given the list of # retest-configs. def RandomTestConfigs(rand, input_configs, num_results): outputs = input_configs[:] have_set = dict([(c,c) for c in input_configs]) # Compute a random configuration def RandomConfig(): config = [] cmap = {} for key in CONFIG_ORDER: val = cmap[key] = (INPUT_SPEC(rand)[key])(cmap) config.append(val) #end return tuple(config) #end while len(outputs) < num_results: newc = None for i in xrange(100): c = RandomConfig() if have_set.has_key(c): continue #end have_set[c] = c newc = c break if newc is None: print 'stopped looking for configs at %d' % len(outputs) break #end outputs.append(c) #end outputs.sort() return outputs #end def RunOptimizationLoop(rand, generator, rounds): configs = [] for rnum in xrange(rounds): configs = RandomTestConfigs(rand, configs, MAX_RESULTS) tinput = generator(rand) tests = [] for x in xrange(len(configs)): t = RandomTest(x, tinput, configs[x]) print 'Round %d test %d: %s' % (rnum, x, t) tests.append(t) #end results = ScoreTests(tests) for r in results: c = r.config() if not test_all_config_results.has_key(c): test_all_config_results[c] = [r] else: test_all_config_results[c].append(r) #end #end #GraphResults('expt%d' % rnum, results) #GraphSummary('sum%d' % rnum, results) # re-test some fraction configs = [r.config() for r in results[0:int(MAX_RESULTS * KEEP_P)]] #end #end # TODO: cleanup test_all_config_results = {} def ScoreTests(results): scored = [] timed = [] sized = [] t_min = float(min([test.time() for test in results])) #t_max = float(max([test.time() for test in results])) s_min = float(min([test.size() for test in results])) #s_max = float(max([test.size() for test in results])) for test in results: # Hyperbolic function. Smaller scores still better red = 0.999 # minimum factors for each dimension are 1/1000 test.score = ((test.size() - s_min * red) * (test.time() - t_min * red)) scored.append((test.score, test)) timed.append((test.time(), test)) sized.append((test.size(), test)) #end scored.sort() timed.sort() sized.sort() best_by_size = [] best_by_time = [] pos = 0 for (score, test) in scored: pos += 1 test.score_pos = pos #end scored = [x[1] for x in scored] for test in scored: test.size_pos = PosInAlist(sized, test) test.time_pos = PosInAlist(timed, test) #end for test in scored: c = test.config() s = 0.0 print 'H-Score: %0.9f %s' % (test.score, test) #end return scored #end def GraphResults(desc, results): f = open("data-%s.csv" % desc, "w") for r in results: f.write("%0.9f\t%d\t# %s\n" % (r.time(), r.size(), r)) #end f.close() os.system("./plot.sh data-%s.csv plot-%s.jpg" % (desc, desc)) #end def GraphSummary(desc, results_ignore): test_population = 0 config_ordered = [] # drops duplicate test/config pairs (TODO: don't retest them) for config, cresults in test_all_config_results.items(): input_config_map = {} uniq = [] for test in cresults: assert test.config() == config test_population += 1 key = test.tinput() if not input_config_map.has_key(key): input_config_map[key] = {} #end if input_config_map[key].has_key(config): print 'skipping repeat test %s vs. %s' % (input_config_map[key][config], test) continue #end input_config_map[key][config] = test uniq.append(test) #end config_ordered.append(uniq) #end # sort configs descending by number of tests config_ordered.sort(lambda x, y: len(y) - len(x)) print 'population %d: %d configs %d results' % \ (test_population, len(config_ordered), len(config_ordered[0])) if config_ordered[0] == 1: return #end # a map from test-key to test-list w/ various configs input_set = {} osize = len(config_ordered) for i in xrange(len(config_ordered)): config = config_ordered[i][0].config() config_tests = config_ordered[i] #print '%s has %d tested inputs' % (config, len(config_tests)) if len(input_set) == 0: input_set = dict([(t.tinput(), [t]) for t in config_tests]) continue #end # a map from test-key to test-list w/ various configs update_set = {} for r in config_tests: t = r.tinput() if input_set.has_key(t): update_set[t] = input_set[t] + [r] else: #print 'config %s does not have test %s' % (config, t) pass #end #end if len(update_set) <= 1: break #end input_set = update_set # continue if there are more w/ the same number of inputs if i < (len(config_ordered) - 1) and \ len(config_ordered[i + 1]) == len(config_tests): continue #end # synthesize results for multi-test inputs config_num = None # map of config to sum(various test-keys) smap = {} for (key, tests) in input_set.items(): if config_num == None: # config_num should be the same in all elements config_num = len(tests) smap = dict([(r.config(), (r.time(), r.size())) for r in tests]) else: # compuate the per-config sum of time/size assert config_num == len(tests) smap = dict([(r.config(), (smap[r.config()][0] + r.time(), smap[r.config()][1] + r.size())) for r in tests]) #end #end if config_num == 1: continue #end if len(input_set) == osize: break #end summary = '%s-%d' % (desc, len(input_set)) osize = len(input_set) print 'generate %s w/ %d configs' % (summary, config_num) syn = [RandomTest(0, (None, None, summary), config, syntuple = (smap[config][0], smap[config][1])) for config in smap.keys()] syn = ScoreTests(syn) #print 'smap is %s' % (smap,) #print 'syn is %s' % (' and '.join([str(x) for x in syn])) #GraphResults(summary, syn) #end #end def RunRegressionTest(pairs, rounds): for args in [ [], ['-S=djw'], ['-B=412907520'], ['-B 412907520', ], ]: print "Args %s" % (args) for (file1, file2, testkey) in pairs: ttest = TimedTest(file1, file2, Xdelta3Runner(args, forkexec=True), skip_trials = 0, min_trials = 1, max_trials = 1) print "Source %s\nTarget %s\nEncode %s\nDecode %s\nSize %s\n\n" % ( file1, file2, ttest.encode_time.str, ttest.decode_time.str, ttest.encode_size) #end #end if __name__ == "__main__": try: RunCommand(['rm', '-rf', TMPDIR]) os.mkdir(TMPDIR) #rcsf = GetTestRcsFiles() #generator = rcsf.Generator() sample = SampleDataTest([SAMPLEDIR]) generator = sample.Generator() rand = random.Random(135135135135135) RunRegressionTest(sample.pairs, TEST_ROUNDS) #RunSpeedTest() # the idea below is to add the default configurations and # xdelta1 to the optimization loop: #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-1', '-3', '-6'])) #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9'])) #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw'])) #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-1', '-S', 'djw'])) #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-T'])) #x1r = rcsf.AllPairsByDate(Xdelta1RunClass()) except CommandError: pass else: RunCommand(['rm', '-rf', TMPDIR]) pass #end #end xdelta3-3.0.7/testing/sizes.h0000644000176500017650000000546612105354541015343 0ustar debdevdebdev// -*- Mode: C++ -*- template class SizeIterator { public: SizeIterator(MTRandom *rand, size_t howmany) : rand_(rand), count_(0), fixed_(U::sizes), fixed_size_(SIZEOF_ARRAY(U::sizes)), howmany_(howmany) { } T Get() { if (count_ < fixed_size_) { return fixed_[count_]; } return rand_->Rand() % U::max_value; } bool Done() { return count_ >= fixed_size_ && count_ >= howmany_; } void Next() { count_++; } private: MTRandom *rand_; size_t count_; T* fixed_; size_t fixed_size_; size_t howmany_; }; // Small sizes class SmallSizes { public: static size_t sizes[]; static size_t max_value; }; size_t SmallSizes::sizes[] = { 0, 1, 128 / 4, 3333, 128 - (128 / 3), 128, 128 + (128 / 3), 2 * 128 - (128 / 3), 2 * 128, 2 * 128 + (128 / 3), }; size_t SmallSizes::max_value = 128 * 3; // Large sizes class LargeSizes { public: static size_t sizes[]; static size_t max_value; }; size_t LargeSizes::sizes[] = { 1 << 20, 1 << 18, 1 << 16, }; size_t LargeSizes::max_value = 1<<20; // Base constants struct BaseConstants { static const size_t TEST_ROUNDS; }; const size_t BaseConstants::TEST_ROUNDS = 10; // Regtest<> arguments struct SmallBlock : public BaseConstants { static const xoff_t BLOCK_SIZE; static const size_t WINDOW_SIZE; static const size_t READ_SIZE; typedef SmallSizes Sizes; }; const size_t SmallBlock::READ_SIZE = 1<<7; const xoff_t SmallBlock::BLOCK_SIZE = 1<<7; const size_t SmallBlock::WINDOW_SIZE = 1<<7; struct LargeBlock : public BaseConstants { static const xoff_t BLOCK_SIZE; static const size_t WINDOW_SIZE; static const size_t READ_SIZE; typedef LargeSizes Sizes; }; const size_t LargeBlock::READ_SIZE = (1 << 13); const xoff_t LargeBlock::BLOCK_SIZE = (1 << 13); const size_t LargeBlock::WINDOW_SIZE = (1 << 13); struct MixedBlock : public BaseConstants { static const xoff_t BLOCK_SIZE; static const size_t WINDOW_SIZE; static const size_t READ_SIZE; typedef SmallSizes Sizes; }; const size_t MixedBlock::READ_SIZE = 1<<6; const xoff_t MixedBlock::BLOCK_SIZE = 1<<7; const size_t MixedBlock::WINDOW_SIZE = 1<<8; struct OversizeBlock : public BaseConstants { static const xoff_t BLOCK_SIZE; static const size_t WINDOW_SIZE; static const size_t READ_SIZE; typedef SmallSizes Sizes; }; const size_t OversizeBlock::READ_SIZE = (1<<6) + (1<<7); const xoff_t OversizeBlock::BLOCK_SIZE = 1<<8; const size_t OversizeBlock::WINDOW_SIZE = 1<<7; struct PrimeBlock : public BaseConstants { static const xoff_t BLOCK_SIZE; static const size_t WINDOW_SIZE; static const size_t READ_SIZE; typedef SmallSizes Sizes; }; const size_t PrimeBlock::READ_SIZE = 71; const xoff_t PrimeBlock::BLOCK_SIZE = 512; // Must be a power-of-2 const size_t PrimeBlock::WINDOW_SIZE = 73; xdelta3-3.0.7/testing/xdelta3-test.py0000755000176500017650000001132712105354541016724 0ustar debdevdebdev#!/usr/bin/python2.7 # xdelta 3 - delta compression tools and library # Copyright (C) 2003, 2006, 2007. Joshua P. MacDonald # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import xdelta3 # the test data section is expected to be len('target') source = 'source source input0 source source' target = 'source source target source source' # # print 'encode: basic ...' result, patch = xdelta3.xd3_encode_memory(target, source, 50) assert result == 0 assert len(patch) < len(source) print 'encode: adler32 ...' result, patch_adler32 = xdelta3.xd3_encode_memory(target, source, 50, xdelta3.XD3_ADLER32) assert result == 0 assert len(patch_adler32) < len(source) assert len(patch_adler32) > len(patch) print 'encode: secondary ...' result, patch_djw = xdelta3.xd3_encode_memory(target, source, 50, xdelta3.XD3_SEC_DJW) assert result == 0 # secondary compression doesn't help assert len(patch_djw) > len(patch) print 'encode: exact ...' result, ignore = xdelta3.xd3_encode_memory(target, source, len(patch)) assert result == 0 assert len(ignore) < len(source) print 'encode: out of space ...' result, ignore = xdelta3.xd3_encode_memory(target, source, len(patch) - 1) assert result == 28 assert ignore == None print 'encode: zero space ...' result, ignore = xdelta3.xd3_encode_memory(target, source, 0) assert result == 28 assert ignore == None print 'encode: no source ...' result, zdata = xdelta3.xd3_encode_memory(target, None, 50) assert result == 0 assert len(zdata) > len(patch) print 'encode: no input ...' result, ignore = xdelta3.xd3_encode_memory(None, None, 50) assert result != 0 print 'decode: basic ...' result, target1 = xdelta3.xd3_decode_memory(patch, source, len(target)) assert result == 0 assert len(target1) == len(target) assert target1 == target print 'decode: out of space ...' result, ignore = xdelta3.xd3_decode_memory(patch, source, len(target) - 1) assert result == 28 assert ignore == None print 'decode: zero space ...' result, ignore = xdelta3.xd3_decode_memory(patch, source, 0) assert result == 28 assert ignore == None print 'decode: single byte error ...' # a few expected single-byte errors, e.g., unused address cache bits, see # xdelta3-test.h's single-bit error tests extra_count = 4 noverify_count = 0 for corrupt_pos in range(len(patch_adler32)): input = ''.join([j == corrupt_pos and '\xff' or patch_adler32[j] for j in range(len(patch_adler32))]) result, ignore = xdelta3.xd3_decode_memory(input, source, len(target), 0) assert result == -17712 assert ignore == None # without adler32 verification, the error may be in the data section which # in this case is 6 bytes 'target' result, corrupt = xdelta3.xd3_decode_memory(input, source, len(target), xdelta3.XD3_ADLER32_NOVER) if result == 0: noverify_count = noverify_count + 1 #print "got %s" % corrupt #end #end assert noverify_count == len('target') + extra_count print 'decode: no source ...' result, target2 = xdelta3.xd3_decode_memory(zdata, None, len(target)) assert result == 0 assert target == target2 # Test compression level setting via flags. assumes a 9 byte checksum # and that level 9 steps 2, level 1 steps 15: # 01234567890123456789012345678901 # level 1 only indexes 2 checksums "abcdefghi" and "ABCDEFGHI" # outputs 43 vs. 23 bytes print 'encode: compression level ...' source = '_la_la_abcdefghi_la_la_ABCDEFGHI' target = 'la_la_ABCDEFGH__la_la_abcdefgh__' result1, level1 = xdelta3.xd3_encode_memory(target, source, 50, xdelta3.XD3_COMPLEVEL_1) result9, level9 = xdelta3.xd3_encode_memory(target, source, 50, xdelta3.XD3_COMPLEVEL_9) assert result1 == 0 and result9 == 0 assert len(level1) > len(level9) # # Issue 65 print 'encode: 65 ...' source = 'Hello World' target = 'Hello everyone' result, patch = xdelta3.xd3_encode_memory(target, source, len(target)) assert result != 0 result, patch = xdelta3.xd3_encode_memory(target, source, 2 * len(target)) assert result == 0 print 'PASS' xdelta3-3.0.7/testing/modify.h0000644000176500017650000002357212143617075015501 0ustar debdevdebdev// -*- Mode: C++ -*- class Mutator { public: virtual ~Mutator() { } virtual void Mutate(SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) const = 0; }; class Change { public: enum Kind { MODIFY = 1, // Mutate a certain range w/ random or supplied data ADD = 2, // Insert random or supplied data DELETE = 3, // Delete a specified range of data COPY = 4, // Copy from one region, inserting elsewhere MOVE = 5, // Copy then delete copied-from range COPYOVER = 6 // Copy then delete copied-to range // ADD, DELETE, and COPY change the file size // MODIFY, MOVE, COPYOVER preserve the file size }; // Constructor for modify, add, delete. Change(Kind kind0, xoff_t size0, xoff_t addr1_0) : kind(kind0), size(size0), addr1(addr1_0), addr2(0), insert(NULL) { CHECK(kind != MOVE && kind != COPY && kind != COPYOVER); } // Constructor for modify, add w/ provided data. Change(Kind kind0, xoff_t size0, xoff_t addr1_0, Segment *insert0) : kind(kind0), size(size0), addr1(addr1_0), addr2(0), insert(insert0) { CHECK(kind != MOVE && kind != COPY && kind != COPYOVER); } // Constructor for move, copy, overwrite Change(Kind kind0, xoff_t size0, xoff_t addr1_0, xoff_t addr2_0) : kind(kind0), size(size0), addr1(addr1_0), addr2(addr2_0), insert(NULL) { CHECK(kind == MOVE || kind == COPY || kind == COPYOVER); } Kind kind; xoff_t size; xoff_t addr1; xoff_t addr2; Segment *insert; // For modify and/or add }; typedef list ChangeList; typedef typename ChangeList::const_iterator ConstChangeListIterator; typedef typename ChangeList::iterator ChangeListIterator; class ChangeListMutator : public Mutator { public: ChangeListMutator(const ChangeList &cl) : cl_(cl) { } ChangeListMutator() { } void Mutate(SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) const { // The speed of processing gigabytes of data is so slow compared with // these table-copy operations, no attempt to make this fast. SegmentMap tmp; for (ConstChangeListIterator iter(cl_.begin()); iter != cl_.end(); ++iter) { const Change &ch = *iter; tmp.clear(); Mutate(ch, &tmp, source_table, rand); tmp.swap(*table); source_table = table; } } static void Mutate(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { switch (ch.kind) { case Change::ADD: AddChange(ch, table, source_table, rand); break; case Change::MODIFY: ModifyChange(ch, table, source_table, rand); break; case Change::DELETE: DeleteChange(ch, table, source_table, rand); break; case Change::COPY: CopyChange(ch, table, source_table, rand); break; case Change::MOVE: MoveChange(ch, table, source_table, rand); break; case Change::COPYOVER: OverwriteChange(ch, table, source_table, rand); break; } } static void ModifyChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { xoff_t m_start = ch.addr1; xoff_t m_end = m_start + ch.size; xoff_t i_start = 0; xoff_t i_end = 0; for (ConstSegmentMapIterator iter(source_table->begin()); iter != source_table->end(); ++iter) { const Segment &seg = iter->second; i_start = iter->first; i_end = i_start + seg.Size(); if (i_end <= m_start || i_start >= m_end) { table->insert(table->end(), make_pair(i_start, seg)); continue; } if (i_start < m_start) { table->insert(table->end(), make_pair(i_start, seg.Subseg(0, m_start - i_start))); } // Insert the entire segment, even though it may extend into later // segments. This condition avoids inserting it during later // segments. if (m_start >= i_start) { if (ch.insert != NULL) { table->insert(table->end(), make_pair(m_start, *ch.insert)); } else { Segment part(m_end - m_start, rand); table->insert(table->end(), make_pair(m_start, part)); } } if (i_end > m_end) { table->insert(table->end(), make_pair(m_end, seg.Subseg(m_end - i_start, i_end - m_end))); } } // This check verifies that the modify does not extend past the // source_table EOF. CHECK_LE(m_end, i_end); } static void AddChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { xoff_t m_start = ch.addr1; xoff_t i_start = 0; xoff_t i_end = 0; for (ConstSegmentMapIterator iter(source_table->begin()); iter != source_table->end(); ++iter) { const Segment &seg = iter->second; i_start = iter->first; i_end = i_start + seg.Size(); if (i_end <= m_start) { table->insert(table->end(), make_pair(i_start, seg)); continue; } if (i_start > m_start) { table->insert(table->end(), make_pair(i_start + ch.size, seg)); continue; } if (i_start < m_start) { table->insert(table->end(), make_pair(i_start, seg.Subseg(0, m_start - i_start))); } if (ch.insert != NULL) { table->insert(table->end(), make_pair(m_start, *ch.insert)); } else { Segment addseg(ch.size, rand); table->insert(table->end(), make_pair(m_start, addseg)); } if (m_start < i_end) { table->insert(table->end(), make_pair(m_start + ch.size, seg.Subseg(m_start - i_start, i_end - m_start))); } } CHECK_LE(m_start, i_end); // Special case for add at end-of-input. if (m_start == i_end) { Segment addseg(ch.size, rand); table->insert(table->end(), make_pair(m_start, addseg)); } } static void DeleteChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { xoff_t m_start = ch.addr1; xoff_t m_end = m_start + ch.size; xoff_t i_start = 0; xoff_t i_end = 0; for (ConstSegmentMapIterator iter(source_table->begin()); iter != source_table->end(); ++iter) { const Segment &seg = iter->second; i_start = iter->first; i_end = i_start + seg.Size(); if (i_end <= m_start) { table->insert(table->end(), make_pair(i_start, seg)); continue; } if (i_start >= m_end) { table->insert(table->end(), make_pair(i_start - ch.size, seg)); continue; } if (i_start < m_start) { table->insert(table->end(), make_pair(i_start, seg.Subseg(0, m_start - i_start))); } if (i_end > m_end) { table->insert(table->end(), make_pair(m_end - ch.size, seg.Subseg(m_end - i_start, i_end - m_end))); } } CHECK_LT(m_start, i_end); CHECK_LE(m_end, i_end); } // A move is a copy followed by delete of the copied-from range. static void MoveChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { SegmentMap tmp; CHECK_NE(ch.addr1, ch.addr2); CopyChange(ch, &tmp, source_table, rand); Change d(Change::DELETE, ch.size, ch.addr1 < ch.addr2 ? ch.addr1 : ch.addr1 + ch.size); DeleteChange(d, table, &tmp, rand); } // An overwrite is a copy followed by a delete of the copied-to range. static void OverwriteChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) { SegmentMap tmp; CHECK_NE(ch.addr1, ch.addr2); CopyChange(ch, &tmp, source_table, rand); Change d(Change::DELETE, ch.size, ch.addr2 + ch.size); DeleteChange(d, table, &tmp, rand); } static void CopyChange(const Change &ch, SegmentMap *table, const SegmentMap *source_table, MTRandom *ignore) { xoff_t m_start = ch.addr2; xoff_t c_start = ch.addr1; xoff_t i_start = 0; xoff_t i_end = 0; // Like AddChange() with AppendCopy instead of a random segment. for (ConstSegmentMapIterator iter(source_table->begin()); iter != source_table->end(); ++iter) { const Segment &seg = iter->second; i_start = iter->first; i_end = i_start + seg.Size(); if (i_end <= m_start) { table->insert(table->end(), make_pair(i_start, seg)); continue; } if (i_start > m_start) { table->insert(table->end(), make_pair(i_start + ch.size, seg)); continue; } if (i_start < m_start) { table->insert(table->end(), make_pair(i_start, seg.Subseg(0, m_start - i_start))); } AppendCopy(table, source_table, c_start, m_start, ch.size); if (m_start < i_end) { table->insert(table->end(), make_pair(m_start + ch.size, seg.Subseg(m_start - i_start, i_end - m_start))); } } CHECK_LE(m_start, i_end); // Special case for copy to end-of-input. if (m_start == i_end) { AppendCopy(table, source_table, c_start, m_start, ch.size); } } static void AppendCopy(SegmentMap *table, const SegmentMap *source_table, xoff_t copy_offset, xoff_t append_offset, xoff_t length) { ConstSegmentMapIterator pos(source_table->upper_bound(copy_offset)); --pos; xoff_t got = 0; while (got < length) { size_t seg_offset = copy_offset - pos->first; size_t advance = min(pos->second.Size() - seg_offset, (size_t)(length - got)); table->insert(table->end(), make_pair(append_offset, pos->second.Subseg(seg_offset, advance))); got += advance; copy_offset += advance; append_offset += advance; ++pos; } } ChangeList* Changes() { return &cl_; } const ChangeList* Changes() const { return &cl_; } private: ChangeList cl_; }; class Modify1stByte : public Mutator { public: void Mutate(SegmentMap *table, const SegmentMap *source_table, MTRandom *rand) const { ChangeListMutator::Mutate(Change(Change::MODIFY, 1, 0), table, source_table, rand); } }; xdelta3-3.0.7/testing/random.h0000644000176500017650000000657612105354541015471 0ustar debdevdebdev/* -*- Mode: C++ -*- */ /* This is public-domain Mersenne Twister code, * attributed to Michael Brundage. Thanks! * http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation.html */ #undef MT_LEN #undef MT_IA class MTRandom { public: enum Constants { MT_LEN = 624, MT_IA = 397 }; static const uint32_t TEST_SEED1; static const uint32_t UPPER_MASK; static const uint32_t LOWER_MASK; static const uint32_t MATRIX_A; MTRandom() { Init(TEST_SEED1); } MTRandom(uint32_t seed) { Init(seed); } uint32_t Rand32 () { uint32_t y; static unsigned long mag01[2] = { 0 , MATRIX_A }; if (mt_index_ >= MT_LEN) { int kk; for (kk = 0; kk < MT_LEN - MT_IA; kk++) { y = (mt_buffer_[kk] & UPPER_MASK) | (mt_buffer_[kk + 1] & LOWER_MASK); mt_buffer_[kk] = mt_buffer_[kk + MT_IA] ^ (y >> 1) ^ mag01[y & 0x1UL]; } for (;kk < MT_LEN - 1; kk++) { y = (mt_buffer_[kk] & UPPER_MASK) | (mt_buffer_[kk + 1] & LOWER_MASK); mt_buffer_[kk] = mt_buffer_[kk + (MT_IA - MT_LEN)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } y = (mt_buffer_[MT_LEN - 1] & UPPER_MASK) | (mt_buffer_[0] & LOWER_MASK); mt_buffer_[MT_LEN - 1] = mt_buffer_[MT_IA - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mt_index_ = 0; } y = mt_buffer_[mt_index_++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } uint32_t ExpRand32(uint32_t mean) { double mean_d = mean; double erand = log (1.0 / (Rand32() / (double)UINT32_MAX)); uint32_t x = (uint32_t) (mean_d * erand + 0.5); return x; } uint64_t Rand64() { return ((uint64_t)Rand32() << 32) | Rand32(); } uint64_t ExpRand64(uint64_t mean) { double mean_d = mean; double erand = log (1.0 / (Rand64() / (double)UINT32_MAX)); uint64_t x = (uint64_t) (mean_d * erand + 0.5); return x; } template T Rand() { switch (sizeof(T)) { case sizeof(uint32_t): return Rand32(); case sizeof(uint64_t): return Rand64(); default: cerr << "Invalid sizeof T" << endl; abort(); } } template T ExpRand(T mean) { switch (sizeof(T)) { case sizeof(uint32_t): return ExpRand32(mean); case sizeof(uint64_t): return ExpRand64(mean); default: cerr << "Invalid sizeof T" << endl; abort(); } } private: void Init(uint32_t seed) { mt_buffer_[0] = seed; mt_index_ = MT_LEN; for (int i = 1; i < MT_LEN; i++) { /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt_buffer_[i] = (1812433253UL * (mt_buffer_[i-1] ^ (mt_buffer_[i-1] >> 30)) + i); } } int mt_index_; uint32_t mt_buffer_[MT_LEN]; }; const uint32_t MTRandom::TEST_SEED1 = 5489UL; const uint32_t MTRandom::UPPER_MASK = 0x80000000; const uint32_t MTRandom::LOWER_MASK = 0x7FFFFFFF; const uint32_t MTRandom::MATRIX_A = 0x9908B0DF; class MTRandom8 { public: MTRandom8(MTRandom *rand) : rand_(rand) { } uint8_t Rand8() { uint32_t r = rand_->Rand32(); // TODO: make this use a single byte at a time? return (r & 0xff) ^ (r >> 7) ^ (r >> 15) ^ (r >> 21); } private: MTRandom *rand_; }; xdelta3-3.0.7/xdelta3-list.h0000644000176500017650000002107312105354541015036 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __XDELTA3_LIST__ #define __XDELTA3_LIST__ #define XD3_MAKELIST(LTYPE,ETYPE,LNAME) \ \ static inline ETYPE* \ LTYPE ## _entry (LTYPE* l) \ { \ return (ETYPE*) ((char*) l - (ptrdiff_t) &((ETYPE*) 0)->LNAME); \ } \ \ static inline void \ LTYPE ## _init (LTYPE *l) \ { \ l->next = l; \ l->prev = l; \ } \ \ static inline void \ LTYPE ## _add (LTYPE *prev, LTYPE *next, LTYPE *ins) \ { \ next->prev = ins; \ prev->next = ins; \ ins->next = next; \ ins->prev = prev; \ } \ \ static inline void \ LTYPE ## _push_back (LTYPE *l, ETYPE *i) \ { \ LTYPE ## _add (l->prev, l, & i->LNAME); \ } \ \ static inline void \ LTYPE ## _del (LTYPE *next, \ LTYPE *prev) \ { \ next->prev = prev; \ prev->next = next; \ } \ \ static inline ETYPE* \ LTYPE ## _remove (ETYPE *f) \ { \ LTYPE *i = f->LNAME.next; \ LTYPE ## _del (f->LNAME.next, f->LNAME.prev); \ return LTYPE ## _entry (i); \ } \ \ static inline ETYPE* \ LTYPE ## _pop_back (LTYPE *l) \ { \ LTYPE *i = l->prev; \ LTYPE ## _del (i->next, i->prev); \ return LTYPE ## _entry (i); \ } \ \ static inline ETYPE* \ LTYPE ## _pop_front (LTYPE *l) \ { \ LTYPE *i = l->next; \ LTYPE ## _del (i->next, i->prev); \ return LTYPE ## _entry (i); \ } \ \ static inline int \ LTYPE ## _empty (LTYPE *l) \ { \ return l == l->next; \ } \ \ static inline ETYPE* \ LTYPE ## _front (LTYPE *f) \ { \ return LTYPE ## _entry (f->next); \ } \ \ static inline ETYPE* \ LTYPE ## _back (LTYPE *f) \ { \ return LTYPE ## _entry (f->prev); \ } \ \ static inline int \ LTYPE ## _end (LTYPE *f, ETYPE *i) \ { \ return f == & i->LNAME; \ } \ \ static inline ETYPE* \ LTYPE ## _next (ETYPE *f) \ { \ return LTYPE ## _entry (f->LNAME.next); \ } \ \ static inline usize_t \ LTYPE ## _length (LTYPE *l) \ { \ LTYPE *p; \ int c = 0; \ \ for (p = l->next; p != l; p = p->next) \ { \ c += 1; \ } \ \ return c; \ } \ \ typedef int unused_ ## LTYPE #endif xdelta3-3.0.7/config.h.in0000644000176500017650000000321512144343106014367 0ustar debdevdebdev/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if pointers to integers require aligned access */ #undef HAVE_ALIGNED_ACCESS_REQUIRED /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `lzma' library (-llzma). */ #undef HAVE_LIBLZMA /* Define to 1 if you have the header file. */ #undef HAVE_LZMA_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* The size of `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS xdelta3-3.0.7/m4/0002755000176500017650000000000012144343472012673 5ustar debdevdebdevxdelta3-3.0.7/m4/ax_check_aligned_access_required.m40000644000176500017650000000623712105354533021611 0ustar debdevdebdev# ==================================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_aligned_access_required.html # ==================================================================================== # # SYNOPSIS # # AC_CHECK_ALIGNED_ACCESS_REQUIRED # # DESCRIPTION # # While the x86 CPUs allow access to memory objects to be unaligned it # happens that most of the modern designs require objects to be aligned - # or they will fail with a buserror. That mode is quite known by # big-endian machines (sparc, etc) however the alpha cpu is little- # endian. # # The following function will test for aligned access to be required and # set a config.h define HAVE_ALIGNED_ACCESS_REQUIRED (name derived by # standard usage). Structures loaded from a file (or mmapped to memory) # should be accessed per-byte in that case to avoid segfault type errors. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AC_DEFUN([AX_CHECK_ALIGNED_ACCESS_REQUIRED], [AC_CACHE_CHECK([if pointers to integers require aligned access], [ax_cv_have_aligned_access_required], [AC_TRY_RUN([ #include #include int main() { char* string = malloc(40); int i; for (i=0; i < 40; i++) string[[i]] = i; { void* s = string; int* p = s+1; int* q = s+2; if (*p == *q) { return 1; } } return 0; } ], [ax_cv_have_aligned_access_required=yes], [ax_cv_have_aligned_access_required=no], [ax_cv_have_aligned_access_required=no]) ]) if test "$ax_cv_have_aligned_access_required" = yes ; then AC_DEFINE([HAVE_ALIGNED_ACCESS_REQUIRED], [1], [Define if pointers to integers require aligned access]) fi ]) xdelta3-3.0.7/configure0000755000176500017650000061633712144343071014273 0ustar debdevdebdev#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Xdelta3 3.0.7. # # Report bugs to . # # # 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 test \$(( 1 + 1 )) = 2 || 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 and $0: josh.macdonald@gmail.com about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: 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 &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='Xdelta3' PACKAGE_TARNAME='xdelta3' PACKAGE_VERSION='3.0.7' PACKAGE_STRING='Xdelta3 3.0.7' PACKAGE_BUGREPORT='josh.macdonald@gmail.com' PACKAGE_URL='http://xdelta.org/' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS DEBUG_SYMBOLS_FALSE DEBUG_SYMBOLS_TRUE EGREP GREP CPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM 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 enable_dependency_tracking enable_debug_symbols ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP' # 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_TARNAME}' 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 Xdelta3 3.0.7 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/xdelta3] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Xdelta3 3.0.7:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-debug-symbols Build with debug symbols (default is NO) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . Xdelta3 home page: . _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 Xdelta3 configure 3.0.7 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. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## --------------------------------------- ## ## Report this to josh.macdonald@gmail.com ## ## --------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 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 Xdelta3 $as_me 3.0.7, 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 #LT_INIT am__api_version='1.12' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; 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_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # 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_STRIP="${ac_tool_prefix}strip" $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 STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; 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_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_ac_ct_STRIP="strip" $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 ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk 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_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # 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_AWK="$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 AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='xdelta3' VERSION='3.0.7' # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 $as_echo_n "checking how to create a ustar tar archive... " >&6; } # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar plaintar pax cpio none' _am_tools=${am_cv_prog_tar_ustar-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x ustar -w "$$tardir"' am__tar_='pax -L -x ustar -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H ustar -L' am__tar_='find "$tardir" -print | cpio -o -H ustar -L' am__untar='cpio -i -H ustar -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_ustar}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar &5 ($am__untar &5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_ustar+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_ustar=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 $as_echo "$am_cv_prog_tar_ustar" >&6; } #AC_DISABLE_STATIC DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi 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 if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="${ac_tool_prefix}gcc" $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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; 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_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_ac_ct_CC="gcc" $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 ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="${ac_tool_prefix}cc" $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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no 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 if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $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 if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="$ac_tool_prefix$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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe 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_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_ac_ct_CC="$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 ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi 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 depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if pointers to integers require aligned access" >&5 $as_echo_n "checking if pointers to integers require aligned access... " >&6; } if ${ax_cv_have_aligned_access_required+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ax_cv_have_aligned_access_required=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { char* string = malloc(40); int i; for (i=0; i < 40; i++) string[[i]] = i; { void* s = string; int* p = s+1; int* q = s+2; if (*p == *q) { return 1; } } return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ax_cv_have_aligned_access_required=yes else ax_cv_have_aligned_access_required=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have_aligned_access_required" >&5 $as_echo "$ax_cv_have_aligned_access_required" >&6; } if test "$ax_cv_have_aligned_access_required" = yes ; then $as_echo "#define HAVE_ALIGNED_ACCESS_REQUIRED 1" >>confdefs.h fi 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 if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="${ac_tool_prefix}gcc" $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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; 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_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_ac_ct_CC="gcc" $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 ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="${ac_tool_prefix}cc" $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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; 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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no 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 if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $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 if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$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_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # 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_CC="$ac_tool_prefix$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 CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe 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_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_ac_ct_CC="$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 ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi 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 depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$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_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # 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_CXX="$ac_tool_prefix$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 CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC 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_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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_ac_ct_CXX="$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 ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi 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 depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in lzma.h do : ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" if test "x$ac_cv_header_lzma_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LZMA_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_easy_buffer_encode in -llzma" >&5 $as_echo_n "checking for lzma_easy_buffer_encode in -llzma... " >&6; } if ${ac_cv_lib_lzma_lzma_easy_buffer_encode+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzma $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lzma_easy_buffer_encode (); int main () { return lzma_easy_buffer_encode (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzma_lzma_easy_buffer_encode=yes else ac_cv_lib_lzma_lzma_easy_buffer_encode=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_easy_buffer_encode" >&5 $as_echo "$ac_cv_lib_lzma_lzma_easy_buffer_encode" >&6; } if test "x$ac_cv_lib_lzma_lzma_easy_buffer_encode" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZMA 1 _ACEOF LIBS="-llzma $LIBS" fi # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 $as_echo_n "checking size of size_t... " >&6; } if ${ac_cv_sizeof_size_t+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then : else if test "$ac_cv_type_size_t" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (size_t) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_size_t=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 $as_echo "$ac_cv_sizeof_size_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SIZE_T $ac_cv_sizeof_size_t _ACEOF #AM_PATH_PYTHON(,, [:]) #AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) #AX_PYTHON_DEVEL() #AX_PKG_SWIG(2.0.0,,) #AX_SWIG_PYTHON # Check whether --enable-debug-symbols was given. if test "${enable_debug_symbols+set}" = set; then : enableval=$enable_debug_symbols; else enableval=no fi if test ${enableval} = "yes"; then DEBUG_SYMBOLS_TRUE= DEBUG_SYMBOLS_FALSE='#' else DEBUG_SYMBOLS_TRUE='#' DEBUG_SYMBOLS_FALSE= fi ac_config_headers="$ac_config_headers config.h" 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}' DEFS=-DHAVE_CONFIG_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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DEBUG_SYMBOLS_TRUE}" && test -z "${DEBUG_SYMBOLS_FALSE}"; then as_fn_error $? "conditional \"DEBUG_SYMBOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${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 Xdelta3 $as_me 3.0.7, 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 case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _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 --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to . Xdelta3 home page: ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Xdelta3 config.status 3.0.7 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' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' 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;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --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 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _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 "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "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 test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands 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` 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 ' >$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 = "" } { 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" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" 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 # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _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 s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;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 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; 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 xdelta3-3.0.7/xdelta3-blkcache.h0000644000176500017650000003421012105354541015614 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010 * Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: This code is heavily revised from 3.0z but still needs major * refactoring. */ #include "xdelta3-internal.h" typedef struct _main_blklru main_blklru; typedef struct _main_blklru_list main_blklru_list; struct _main_blklru_list { main_blklru_list *next; main_blklru_list *prev; }; struct _main_blklru { uint8_t *blk; xoff_t blkno; usize_t size; main_blklru_list link; }; #define MAX_LRU_SIZE 32U #define XD3_MINSRCWINSZ (XD3_ALLOCSIZE * MAX_LRU_SIZE) #define XD3_MAXSRCWINSZ (1ULL << 31) XD3_MAKELIST(main_blklru_list,main_blklru,link); static usize_t lru_size = 0; static main_blklru *lru = NULL; /* array of lru_size elts */ static main_blklru_list lru_list; static int do_src_fifo = 0; /* set to avoid lru */ static int lru_hits = 0; static int lru_misses = 0; static int lru_filled = 0; static void main_lru_reset (void) { lru_size = 0; lru = NULL; do_src_fifo = 0; lru_hits = 0; lru_misses = 0; lru_filled = 0; } static void main_lru_cleanup (void) { if (lru != NULL) { main_buffree (lru[0].blk); } main_free (lru); lru = NULL; lru_hits = 0; lru_misses = 0; lru_filled = 0; } /* This is called at different times for encoding and decoding. The * encoder calls it immediately, the decoder delays until the * application header is received. */ static int main_set_source (xd3_stream *stream, xd3_cmd cmd, main_file *sfile, xd3_source *source) { int ret = 0; usize_t i; xoff_t source_size = 0; usize_t blksize; XD3_ASSERT (lru == NULL); XD3_ASSERT (stream->src == NULL); XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ); /* TODO: this code needs refactoring into FIFO, LRU, FAKE. Yuck! * This is simplified from 3.0z which had issues with sizing the * source buffer memory allocation and the source blocksize. */ /* LRU-specific */ main_blklru_list_init (& lru_list); if (allow_fake_source) { /* TODO: refactor * TOOLS/recode-specific: Check "allow_fake_source" mode looks * broken now. */ sfile->mode = XO_READ; sfile->realname = sfile->filename; sfile->nread = 0; } else { /* Either a regular file (possibly compressed) or a FIFO * (possibly compressed). */ if ((ret = main_file_open (sfile, sfile->filename, XO_READ))) { return ret; } /* If the file is regular we know it's size. If the file turns * out to be externally compressed, size_known may change. */ sfile->size_known = (main_file_stat (sfile, &source_size) == 0); } /* Note: The API requires a power-of-two blocksize and srcwinsz * (-B). The logic here will use a single block if the entire file * is known to fit into srcwinsz. */ option_srcwinsz = xd3_pow2_roundup (option_srcwinsz); /* Though called "lru", it is not LRU-specific. We always allocate * a maximum number of source block buffers. If the entire file * fits into srcwinsz, this buffer will stay as the only * (lru_size==1) source block. Otherwise, we know that at least * option_srcwinsz bytes are available. Split the source window * into buffers. */ if ((lru = (main_blklru*) main_malloc (MAX_LRU_SIZE * sizeof (main_blklru))) == NULL) { ret = ENOMEM; return ret; } memset (lru, 0, sizeof(lru[0]) * MAX_LRU_SIZE); /* Allocate the entire buffer. */ if ((lru[0].blk = (uint8_t*) main_bufalloc (option_srcwinsz)) == NULL) { ret = ENOMEM; return ret; } /* Main calls main_getblk_func() once before xd3_set_source(). This * is the point at which external decompression may begin. Set the * system for a single block. */ lru_size = 1; lru[0].blkno = (xoff_t) -1; blksize = option_srcwinsz; main_blklru_list_push_back (& lru_list, & lru[0]); XD3_ASSERT (blksize != 0); /* Initialize xd3_source. */ source->blksize = blksize; source->name = sfile->filename; source->ioh = sfile; source->curblkno = (xoff_t) -1; source->curblk = NULL; source->max_winsize = option_srcwinsz; if ((ret = main_getblk_func (stream, source, 0)) != 0) { XPR(NT "error reading source: %s: %s\n", sfile->filename, xd3_mainerror (ret)); return ret; } source->onblk = lru[0].size; /* xd3 sets onblk */ /* If the file is smaller than a block, size is known. */ if (!sfile->size_known && source->onblk < blksize) { source_size = source->onblk; sfile->size_known = 1; } /* If the size is not known or is greater than the buffer size, we * split the buffer across MAX_LRU_SIZE blocks (already allocated in * "lru"). */ if (!sfile->size_known || source_size > option_srcwinsz) { /* Modify block 0, change blocksize. */ blksize = option_srcwinsz / MAX_LRU_SIZE; source->blksize = blksize; source->onblk = blksize; /* xd3 sets onblk */ /* Note: source->max_winsize is unchanged. */ lru[0].size = blksize; lru_size = MAX_LRU_SIZE; /* Setup rest of blocks. */ for (i = 1; i < lru_size; i += 1) { lru[i].blk = lru[0].blk + (blksize * i); lru[i].blkno = i; lru[i].size = blksize; main_blklru_list_push_back (& lru_list, & lru[i]); } } if (! sfile->size_known) { /* If the size is not know, we must use FIFO discipline. */ do_src_fifo = 1; } /* Call the appropriate set_source method, handle errors, print * verbose message, etc. */ if (sfile->size_known) { ret = xd3_set_source_and_size (stream, source, source_size); } else { ret = xd3_set_source (stream, source); } if (ret) { XPR(NT XD3_LIB_ERRMSG (stream, ret)); return ret; } XD3_ASSERT (stream->src == source); XD3_ASSERT (source->blksize == blksize); if (option_verbose) { static shortbuf srcszbuf; static shortbuf srccntbuf; static shortbuf winszbuf; static shortbuf blkszbuf; static shortbuf nbufs; if (sfile->size_known) { short_sprintf (srcszbuf, "source size %s [%"Q"u]", main_format_bcnt (source_size, &srccntbuf), source_size); } else { short_sprintf (srcszbuf, "%s", "source size unknown"); } nbufs.buf[0] = 0; if (option_verbose > 1) { short_sprintf (nbufs, " #bufs %u", lru_size); } XPR(NT "source %s %s blksize %s window %s%s%s\n", sfile->filename, srcszbuf.buf, main_format_bcnt (blksize, &blkszbuf), main_format_bcnt (option_srcwinsz, &winszbuf), nbufs.buf, do_src_fifo ? " (FIFO)" : ""); } return 0; } static int main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_new) { main_blklru *blru = NULL; usize_t i; (*is_new) = 0; if (do_src_fifo) { /* Direct lookup assumes sequential scan w/o skipping blocks. */ int idx = blkno % lru_size; blru = & lru[idx]; if (blru->blkno == blkno) { (*blrup) = blru; return 0; } /* No going backwards in a sequential scan. */ if (blru->blkno != (xoff_t) -1 && blru->blkno > blkno) { return XD3_TOOFARBACK; } } else { /* Sequential search through LRU. */ for (i = 0; i < lru_size; i += 1) { blru = & lru[i]; if (blru->blkno == blkno) { main_blklru_list_remove (blru); main_blklru_list_push_back (& lru_list, blru); (*blrup) = blru; return 0; } } } if (do_src_fifo) { int idx = blkno % lru_size; blru = & lru[idx]; } else { XD3_ASSERT (! main_blklru_list_empty (& lru_list)); blru = main_blklru_list_pop_front (& lru_list); main_blklru_list_push_back (& lru_list, blru); } lru_filled += 1; (*is_new) = 1; (*blrup) = blru; blru->blkno = -1; return 0; } static int main_read_seek_source (xd3_stream *stream, xd3_source *source, xoff_t blkno) { xoff_t pos = blkno * source->blksize; main_file *sfile = (main_file*) source->ioh; main_blklru *blru; int is_new; size_t nread = 0; int ret = 0; if (!sfile->seek_failed) { ret = main_file_seek (sfile, pos); if (ret == 0) { sfile->source_position = pos; } } if (sfile->seek_failed || ret != 0) { /* For an unseekable file (or other seek error, does it * matter?) */ if (sfile->source_position > pos) { /* Could assert !IS_ENCODE(), this shouldn't happen * because of do_src_fifo during encode. */ if (!option_quiet) { XPR(NT "source can't seek backwards; requested block offset " "%"Q"u source position is %"Q"u\n", pos, sfile->source_position); } sfile->seek_failed = 1; stream->msg = "non-seekable source: " "copy is too far back (try raising -B)"; return XD3_TOOFARBACK; } /* There's a chance here, that an genuine lseek error will cause * xdelta3 to shift into non-seekable mode, entering a degraded * condition. */ if (!sfile->seek_failed && option_verbose) { XPR(NT "source can't seek, will use FIFO for %s\n", sfile->filename); if (option_verbose > 1) { XPR(NT "seek error at offset %"Q"u: %s\n", pos, xd3_mainerror (ret)); } } sfile->seek_failed = 1; if (option_verbose > 1 && pos != sfile->source_position) { XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n", pos - sfile->source_position, sfile->source_position); } while (sfile->source_position < pos) { xoff_t skip_blkno; usize_t skip_offset; xd3_blksize_div (sfile->source_position, source, &skip_blkno, &skip_offset); /* Read past unused data */ XD3_ASSERT (pos - sfile->source_position >= source->blksize); XD3_ASSERT (skip_offset == 0); if ((ret = main_getblk_lru (source, skip_blkno, & blru, & is_new))) { return ret; } XD3_ASSERT (is_new); blru->blkno = skip_blkno; if ((ret = main_read_primary_input (sfile, (uint8_t*) blru->blk, source->blksize, & nread))) { return ret; } if (nread != source->blksize) { IF_DEBUG1 (DP(RINT "[getblk] short skip block nread = %zu\n", nread)); stream->msg = "non-seekable input is short"; return XD3_INVALID_INPUT; } sfile->source_position += nread; blru->size = nread; IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u size %u\n", skip_blkno, blru->size)); XD3_ASSERT (sfile->source_position <= pos); } } return 0; } /* This is the callback for reading a block of source. This function * is blocking and it implements a small LRU. * * Note that it is possible for main_input() to handle getblk requests * in a non-blocking manner. If the callback is NULL then the caller * of xd3_*_input() must handle the XD3_GETSRCBLK return value and * fill the source in the same way. See xd3_getblk for details. To * see an example of non-blocking getblk, see xdelta-test.h. */ static int main_getblk_func (xd3_stream *stream, xd3_source *source, xoff_t blkno) { int ret = 0; xoff_t pos = blkno * source->blksize; main_file *sfile = (main_file*) source->ioh; main_blklru *blru; int is_new; int did_seek = 0; size_t nread = 0; if (allow_fake_source) { source->curblkno = blkno; source->onblk = 0; source->curblk = lru[0].blk; lru[0].size = 0; return 0; } if ((ret = main_getblk_lru (source, blkno, & blru, & is_new))) { return ret; } if (!is_new) { source->curblkno = blkno; source->onblk = blru->size; source->curblk = blru->blk; lru_hits++; return 0; } lru_misses += 1; if (pos != sfile->source_position) { /* Only try to seek when the position is wrong. This means the * decoder will fail when the source buffer is too small, but * only when the input is non-seekable. */ if ((ret = main_read_seek_source (stream, source, blkno))) { return ret; } /* Indicates that another call to main_getblk_lru() may be * needed */ did_seek = 1; } XD3_ASSERT (sfile->source_position == pos); if (did_seek && (ret = main_getblk_lru (source, blkno, & blru, & is_new))) { return ret; } if ((ret = main_read_primary_input (sfile, (uint8_t*) blru->blk, source->blksize, & nread))) { return ret; } /* Save the last block read, used to handle non-seekable files. */ sfile->source_position = pos + nread; if (option_verbose > 3) { if (blru->blkno != (xoff_t)-1) { if (blru->blkno != blkno) { XPR(NT "source block %"Q"u read %zu ejects %"Q"u (lru_hits=%u, " "lru_misses=%u, lru_filled=%u)\n", blkno, nread, blru->blkno, lru_hits, lru_misses, lru_filled); } else { XPR(NT "source block %"Q"u read %zu (lru_hits=%u, " "lru_misses=%u, lru_filled=%u)\n", blkno, nread, lru_hits, lru_misses, lru_filled); } } else { XPR(NT "source block %"Q"u read %zu (lru_hits=%u, lru_misses=%u, " "lru_filled=%u)\n", blkno, nread, lru_hits, lru_misses, lru_filled); } } source->curblk = blru->blk; source->curblkno = blkno; source->onblk = nread; blru->size = nread; blru->blkno = blkno; IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %zu pos %"Q"u " "srcpos %"Q"u\n", blkno, nread, pos, sfile->source_position)); return 0; } xdelta3-3.0.7/xdelta3.10000644000176500017650000000471212105354541013777 0ustar debdevdebdev.TH XDELTA3 "1" "August 2009" "Xdelta3" .SH NAME xdelta3 \- VCDIFF (RFC 3284) binary diff tool .SH SYNOPSIS .B xdelta3 .RI [ command ] .RI [ options ] .RI [ input .RI [ output ]] .SH DESCRIPTION .B xdelta3 is a binary diff tool that uses the VCDIFF (RFC 3284) format and compression. .SH COMMANDS .TP .BI config prints xdelta3 configuration .TP .BI decode decompress the input, also set by -d .TP .BI encode compress the input, also set by -e (default) .TP .BI test run the builtin tests .TP .BI printdelta print information about the entire delta .TP .BI printhdr print information about the first window .TP .BI printhdrs print information about all windows .TP .BI recode encode with new application/secondary settings .SH OPTIONS standard options: .TP .BI "\-0 .. \-9" compression level .TP .BI "\-c" use stdout .TP .BI "\-d" decompress .TP .BI \-e compress .TP .BI \-f force overwrite .TP .BI \-h show help .TP .BI \-q be quiet .TP .BI \-v be verbose (max 2) .TP .BI \-V show version .TP memory options: .TP .BI \-B .RI bytes source window size .TP .BI \-W .RI bytes input window size .TP .BI \-P .RI size compression duplicates window .TP .BI \-I .RI size instruction buffer size (0 = unlimited) .TP compression options: .TP .BI \-s .RI source source file to copy from (if any) .TP .BI "\-S " [djw|fgk] enable/disable secondary compression .TP .BI \-N disable small string-matching compression .TP .BI \-D disable external decompression (encode/decode) .TP .BI \-R disable external recompression (decode) .TP .BI \-n disable checksum (encode/decode) .TP .BI \-C soft config (encode, undocumented) .TP .BI "\-A " [apphead] disable/provide application header (encode) .TP .BI \-J disable output (check/compute only) .TP .BI \-T use alternate code table (test) .SH NOTES The .B XDELTA environment variable may contain extra args: .RS XDELTA="-s source-x.y.tar.gz" \\ .br tar --use-compress-program=xdelta3 -cf \\ .br target-x.z.tar.gz.vcdiff target-x.y/ .SH EXAMPLES Compress the differences between SOURCE and TARGET, yielding OUT, using "djw" secondary compression: xdelta3 -S djw -s SOURCE TARGET OUT Do the same, using standard input and output: xdelta3 -S djw -s SOURCE < TARGET > OUT To decompress OUT, using SOURCE, yielding TARGET: xdelta3 -d -s SOURCE OUT TARGET .SH AUTHOR xdelta3 was written by Josh MacDonald . .PP This manual page was written by Leo 'costela' Antunes for the Debian project (but may be used by others). xdelta3-3.0.7/Makefile.in0000644000176500017650000011500112144343067014414 0ustar debdevdebdev# Makefile.in generated by automake 1.12.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = xdelta3$(EXEEXT) noinst_PROGRAMS = xdelta3regtest$(EXEEXT) xdelta3decode$(EXEEXT) @DEBUG_SYMBOLS_TRUE@am__append_1 = -g subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure COPYING INSTALL depcomp install-sh \ ltmain.sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = \ $(top_srcdir)/m4/ax_check_aligned_access_required.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__objects_1 = am_xdelta3_OBJECTS = $(am__objects_1) xdelta3-xdelta3.$(OBJEXT) xdelta3_OBJECTS = $(am_xdelta3_OBJECTS) xdelta3_DEPENDENCIES = xdelta3_LINK = $(CCLD) $(xdelta3_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_xdelta3decode_OBJECTS = $(am__objects_1) \ xdelta3decode-xdelta3.$(OBJEXT) xdelta3decode_OBJECTS = $(am_xdelta3decode_OBJECTS) xdelta3decode_LDADD = $(LDADD) xdelta3decode_LINK = $(CCLD) $(xdelta3decode_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_xdelta3regtest_OBJECTS = $(am__objects_1) \ xdelta3regtest-regtest.$(OBJEXT) \ xdelta3regtest-regtest_c.$(OBJEXT) xdelta3regtest_OBJECTS = $(am_xdelta3regtest_OBJECTS) xdelta3regtest_DEPENDENCIES = xdelta3regtest_LINK = $(CXXLD) $(xdelta3regtest_CXXFLAGS) $(CXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ SOURCES = $(xdelta3_SOURCES) $(xdelta3decode_SOURCES) \ $(xdelta3regtest_SOURCES) DIST_SOURCES = $(xdelta3_SOURCES) $(xdelta3decode_SOURCES) \ $(xdelta3regtest_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man1_MANS) ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 common_SOURCES = \ xdelta3-blkcache.h \ xdelta3-decode.h \ xdelta3-djw.h \ xdelta3-fgk.h \ xdelta3-hash.h \ xdelta3-internal.h \ xdelta3-list.h \ xdelta3-lzma.h \ xdelta3-main.h \ xdelta3-merge.h \ xdelta3-second.h \ xdelta3-test.h \ xdelta3-cfgs.h \ xdelta3.h xdelta3_SOURCES = $(common_SOURCES) xdelta3.c xdelta3decode_SOURCES = $(common_SOURCES) xdelta3.c xdelta3regtest_SOURCES = $(common_SOURCES) \ testing/cmp.h \ testing/delta.h \ testing/file.h \ testing/modify.h \ testing/random.h \ testing/regtest.cc \ testing/regtest_c.c \ testing/segment.h \ testing/sizes.h \ testing/test.h # Note: for extra sanity checks, enable -Wconversion. Note there # are a lot of false positives. WFLAGS = -Wall -Wshadow -fno-builtin -Wextra -Wsign-compare \ -Wextra -Wno-unused-parameter C_WFLAGS = $(WFLAGS) -pedantic -std=c99 CXX_WFLAGS = $(WFLAGS) common_CFLAGS = -DGENERIC_ENCODE_TABLES=0 -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 -DXD3_MAIN=1 $(am__append_1) # For additional debugging, add -DXD3_DEBUG=1, 2, 3, ... xdelta3_CFLAGS = $(C_WFLAGS) $(common_CFLAGS) -DXD3_DEBUG=0 xdelta3_LDADD = -lm xdelta3decode_CFLAGS = \ $(C_WFLAGS) \ -DGENERIC_ENCODE_TABLES=0 \ -DREGRESSION_TEST=0 \ -DSECONDARY_DJW=0 \ -DSECONDARY_FGK=0 \ -DSECONDARY_LZMA=0 \ -DXD3_USE_LARGEFILE64=1 \ -DXD3_MAIN=1 \ -DXD3_ENCODER=0 \ -DXD3_STDIO=1 \ -DEXTERNAL_COMPRESSION=0 \ -DVCDIFF_TOOLS=0 xdelta3regtest_CXXFLAGS = \ $(CXX_WFLAGS) $(common_CFLAGS) -DNOT_MAIN=1 -DXD3_DEBUG=1 xdelta3regtest_CFLAGS = \ $(C_WFLAGS) $(common_CFLAGS) -DNOT_MAIN=1 -DXD3_DEBUG=1 xdelta3regtest_LDADD = -lm man1_MANS = xdelta3.1 EXTRA_DIST = \ draft-korn-vcdiff.txt \ README \ examples/Makefile \ examples/README \ examples/checksum_test.cc \ examples/compare_test.c \ examples/encode_decode_test.c \ examples/small_page_test.c \ examples/speed_test.c \ examples/test.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test.xcodeproj/project.pbxproj \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/InfoPlist.strings \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPad.storyboard \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPhone.storyboard \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1_to_v2.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v2.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/main.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Info.plist \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Prefix.pch \ Makefile.mingw \ Makefile.orig \ testing/xdelta3-regtest.py \ testing/xdelta3-test.py \ xdelta3.1 \ xdelta3.i \ xdelta3.vcxproj \ xdelta3.wxi \ xdelta3.wxs all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .cc .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) xdelta3$(EXEEXT): $(xdelta3_OBJECTS) $(xdelta3_DEPENDENCIES) $(EXTRA_xdelta3_DEPENDENCIES) @rm -f xdelta3$(EXEEXT) $(xdelta3_LINK) $(xdelta3_OBJECTS) $(xdelta3_LDADD) $(LIBS) xdelta3decode$(EXEEXT): $(xdelta3decode_OBJECTS) $(xdelta3decode_DEPENDENCIES) $(EXTRA_xdelta3decode_DEPENDENCIES) @rm -f xdelta3decode$(EXEEXT) $(xdelta3decode_LINK) $(xdelta3decode_OBJECTS) $(xdelta3decode_LDADD) $(LIBS) xdelta3regtest$(EXEEXT): $(xdelta3regtest_OBJECTS) $(xdelta3regtest_DEPENDENCIES) $(EXTRA_xdelta3regtest_DEPENDENCIES) @rm -f xdelta3regtest$(EXEEXT) $(xdelta3regtest_LINK) $(xdelta3regtest_OBJECTS) $(xdelta3regtest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdelta3-xdelta3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdelta3decode-xdelta3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdelta3regtest-regtest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdelta3regtest-regtest_c.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` xdelta3-xdelta3.o: xdelta3.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3_CFLAGS) $(CFLAGS) -MT xdelta3-xdelta3.o -MD -MP -MF $(DEPDIR)/xdelta3-xdelta3.Tpo -c -o xdelta3-xdelta3.o `test -f 'xdelta3.c' || echo '$(srcdir)/'`xdelta3.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3-xdelta3.Tpo $(DEPDIR)/xdelta3-xdelta3.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xdelta3.c' object='xdelta3-xdelta3.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3_CFLAGS) $(CFLAGS) -c -o xdelta3-xdelta3.o `test -f 'xdelta3.c' || echo '$(srcdir)/'`xdelta3.c xdelta3-xdelta3.obj: xdelta3.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3_CFLAGS) $(CFLAGS) -MT xdelta3-xdelta3.obj -MD -MP -MF $(DEPDIR)/xdelta3-xdelta3.Tpo -c -o xdelta3-xdelta3.obj `if test -f 'xdelta3.c'; then $(CYGPATH_W) 'xdelta3.c'; else $(CYGPATH_W) '$(srcdir)/xdelta3.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3-xdelta3.Tpo $(DEPDIR)/xdelta3-xdelta3.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xdelta3.c' object='xdelta3-xdelta3.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3_CFLAGS) $(CFLAGS) -c -o xdelta3-xdelta3.obj `if test -f 'xdelta3.c'; then $(CYGPATH_W) 'xdelta3.c'; else $(CYGPATH_W) '$(srcdir)/xdelta3.c'; fi` xdelta3decode-xdelta3.o: xdelta3.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3decode_CFLAGS) $(CFLAGS) -MT xdelta3decode-xdelta3.o -MD -MP -MF $(DEPDIR)/xdelta3decode-xdelta3.Tpo -c -o xdelta3decode-xdelta3.o `test -f 'xdelta3.c' || echo '$(srcdir)/'`xdelta3.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3decode-xdelta3.Tpo $(DEPDIR)/xdelta3decode-xdelta3.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xdelta3.c' object='xdelta3decode-xdelta3.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3decode_CFLAGS) $(CFLAGS) -c -o xdelta3decode-xdelta3.o `test -f 'xdelta3.c' || echo '$(srcdir)/'`xdelta3.c xdelta3decode-xdelta3.obj: xdelta3.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3decode_CFLAGS) $(CFLAGS) -MT xdelta3decode-xdelta3.obj -MD -MP -MF $(DEPDIR)/xdelta3decode-xdelta3.Tpo -c -o xdelta3decode-xdelta3.obj `if test -f 'xdelta3.c'; then $(CYGPATH_W) 'xdelta3.c'; else $(CYGPATH_W) '$(srcdir)/xdelta3.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3decode-xdelta3.Tpo $(DEPDIR)/xdelta3decode-xdelta3.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='xdelta3.c' object='xdelta3decode-xdelta3.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3decode_CFLAGS) $(CFLAGS) -c -o xdelta3decode-xdelta3.obj `if test -f 'xdelta3.c'; then $(CYGPATH_W) 'xdelta3.c'; else $(CYGPATH_W) '$(srcdir)/xdelta3.c'; fi` xdelta3regtest-regtest_c.o: testing/regtest_c.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CFLAGS) $(CFLAGS) -MT xdelta3regtest-regtest_c.o -MD -MP -MF $(DEPDIR)/xdelta3regtest-regtest_c.Tpo -c -o xdelta3regtest-regtest_c.o `test -f 'testing/regtest_c.c' || echo '$(srcdir)/'`testing/regtest_c.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3regtest-regtest_c.Tpo $(DEPDIR)/xdelta3regtest-regtest_c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testing/regtest_c.c' object='xdelta3regtest-regtest_c.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CFLAGS) $(CFLAGS) -c -o xdelta3regtest-regtest_c.o `test -f 'testing/regtest_c.c' || echo '$(srcdir)/'`testing/regtest_c.c xdelta3regtest-regtest_c.obj: testing/regtest_c.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CFLAGS) $(CFLAGS) -MT xdelta3regtest-regtest_c.obj -MD -MP -MF $(DEPDIR)/xdelta3regtest-regtest_c.Tpo -c -o xdelta3regtest-regtest_c.obj `if test -f 'testing/regtest_c.c'; then $(CYGPATH_W) 'testing/regtest_c.c'; else $(CYGPATH_W) '$(srcdir)/testing/regtest_c.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xdelta3regtest-regtest_c.Tpo $(DEPDIR)/xdelta3regtest-regtest_c.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testing/regtest_c.c' object='xdelta3regtest-regtest_c.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CFLAGS) $(CFLAGS) -c -o xdelta3regtest-regtest_c.obj `if test -f 'testing/regtest_c.c'; then $(CYGPATH_W) 'testing/regtest_c.c'; else $(CYGPATH_W) '$(srcdir)/testing/regtest_c.c'; fi` .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` xdelta3regtest-regtest.o: testing/regtest.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CXXFLAGS) $(CXXFLAGS) -MT xdelta3regtest-regtest.o -MD -MP -MF $(DEPDIR)/xdelta3regtest-regtest.Tpo -c -o xdelta3regtest-regtest.o `test -f 'testing/regtest.cc' || echo '$(srcdir)/'`testing/regtest.cc @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xdelta3regtest-regtest.Tpo $(DEPDIR)/xdelta3regtest-regtest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='testing/regtest.cc' object='xdelta3regtest-regtest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CXXFLAGS) $(CXXFLAGS) -c -o xdelta3regtest-regtest.o `test -f 'testing/regtest.cc' || echo '$(srcdir)/'`testing/regtest.cc xdelta3regtest-regtest.obj: testing/regtest.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CXXFLAGS) $(CXXFLAGS) -MT xdelta3regtest-regtest.obj -MD -MP -MF $(DEPDIR)/xdelta3regtest-regtest.Tpo -c -o xdelta3regtest-regtest.obj `if test -f 'testing/regtest.cc'; then $(CYGPATH_W) 'testing/regtest.cc'; else $(CYGPATH_W) '$(srcdir)/testing/regtest.cc'; fi` @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xdelta3regtest-regtest.Tpo $(DEPDIR)/xdelta3regtest-regtest.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='testing/regtest.cc' object='xdelta3regtest-regtest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xdelta3regtest_CXXFLAGS) $(CXXFLAGS) -c -o xdelta3regtest-regtest.obj `if test -f 'testing/regtest.cc'; then $(CYGPATH_W) 'testing/regtest.cc'; else $(CYGPATH_W) '$(srcdir)/testing/regtest.cc'; fi` install-man1: $(man1_MANS) @$(NORMAL_INSTALL) @list1='$(man1_MANS)'; \ list2=''; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically 'make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) config.h installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall-man: uninstall-man1 .MAKE: all install-am install-strip .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ clean-binPROGRAMS clean-cscope clean-generic \ clean-noinstPROGRAMS cscope cscopelist ctags dist dist-all \ dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-man \ uninstall-man1 # Broken, removed from distribution: # xdelta3_pywrap.c # xdelta3.py #PYFILES = xdelta3_pywrap.c xdelta3.py #XDELTA3PY = xdelta3.py #XDELTA3PYLIB = xdelta3.la #BUILT_SOURCES = $(PYFILES) #xdelta3_pywrap.c xdelta3.py : xdelta3.i # $(SWIG) -python -o xdelta3_pywrap.c xdelta3.i # OS X for some reason requires: # pythondir = $(PYTHON_SITE_PKG) # pyexecdir = $(PYTHON_SITE_PKG) #python_PYTHON = $(XDELTA3PY) #pyexec_LTLIBRARIES = $(XDELTA3PYLIB) #_xdelta3_la_SOURCES = $(srcdir)/xdelta3_pywrap.c $(xdelta3_SOURCES) #_xdelta3_la_CFLAGS = $(common_CFLAGS) -DNOT_MAIN=1 $(PYTHON_CPPFLAGS) #_xdelta3_la_LDFLAGS = -module # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: xdelta3-3.0.7/xdelta3.wxi0000644000176500017650000000057512105354541014451 0ustar debdevdebdev xdelta3-3.0.7/Makefile.mingw0000644000176500017650000001456212105354541015135 0ustar debdevdebdev# xdelta 3 - delta compression tools and library # Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald UNAME = $(shell uname) CYGWIN = $(findstring CYGWIN, $(UNAME)) MINGW = $(findstring MINGW32, $(UNAME)) PYVER = 2.5 ifneq ("$(CYGWIN)", "") SWIGTGT = xdelta3module.dll PYTGT = build/lib.cygwin-1.5.24-i686-$(PYVER)/xdelta3main.dll else ifneq ("$(MINGW)", "") # FIXME: WHAT TO DO HERE??? # FIXME: WHAT IF WE ARE CROSS-COMPILING??? endif endif SOURCES = xdelta3-cfgs.h \ xdelta3-decode.h \ xdelta3-djw.h \ xdelta3-fgk.h \ xdelta3-hash.h \ xdelta3-list.h \ xdelta3-main.h \ xdelta3-python.h \ xdelta3-second.h \ xdelta3-test.h \ xdelta3-test2.h \ xdelta3.c \ xdelta3.h TARGETS = xdelta3-debug.exe \ xdelta3.exe \ xdelta3-debug2.exe \ xdelta3-debug3.exe \ xdelta3.o \ xdelta3_wrap.o \ xdelta3-32.exe \ xdelta3-64.exe \ xdelta3-everything.exe \ xdelta3-decoder.exe xdelta3-decoder-nomain.o \ xdelta3-nosec.o xdelta3-all.o xdelta3-fgk.o \ xdelta3-noext.exe xdelta3-tools.exe \ xdelta3-notools.exe \ xdelta3_wrap.c xdelta3.py \ $(PYTGT) $(SWIGTGT) PYTHON = python WIXDIR = "/cygdrive/c/Program Files/wix2.0.4820" # FIXME: MinGW ???? CFLAGS= -Wall -Wshadow -fno-builtin XDWINFLAGS:=-DXD3_STDIO=0 -DXD3_POSIX=0 -DXD3_WIN32=1 -DEXTERNAL_COMPRESSION=0 # $Format: "REL=$Xdelta3Version$" $ REL=3.0.1 RELDIR = xdelta$(REL) EXTRA = Makefile COPYING linkxd3lib.c badcopy.c xdelta3.swig \ draft-korn-vcdiff.txt xdelta3.vcproj badcopy.vcproj \ xdelta3-regtest.py xdelta3-test.py setup.py \ examples/Makefile examples/small_page_test.c \ examples/README examples/encode_decode_test.c \ examples/compare_test.c examples/speed_test.c \ examples/test.h examples/checksum_test.cc \ xdelta3.py xdelta3_wrap.c xdelta3.wxs xdelta3.wxi \ README readme.txt SWIG_FLAGS = -DXD3_DEBUG=0 \ -DEXTERNAL_COMPRESSION=0 \ -DXD3_USE_LARGEFILE64=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DSECONDARY_DJW=1 \ -DVCDIFF_TOOLS=1 \ -DSWIG_MODULE=1 all: xdelta3-debug.exe xdelta3.exe all-py: all $(PYTGT) $(SWIGTGT) all-targets: $(TARGETS) all-targets-test: all-targets test pytgt: $(PYTGT) swigtgt: $(SWIGTGT) test: ./xdelta3-debug.exe test # FIXME: Not good when cross-compiling clean: rm -f $(TARGETS) rm -rf build Debug Release core cifs* *.stackdump *.exe \ xdelta3.ncb xdelta3.suo xdelta3.sln xdelta3.wixobj xdelta3.msi wix: xdelta3.wxs xdelta3.wxi readme.txt Release\xdelta3.exe $(WIXDIR)/candle.exe xdelta3.wxs -out xdelta3.wixobj $(WIXDIR)/light.exe xdelta3.wixobj -out xdelta3.msi # FIXME: MinGW ???? xdelta3.exe: $(SOURCES) $(CC) $(CFLAGS) -O3 xdelta3.c -lm -o xdelta3.exe \ $(XDWINFLAGS) \ -DGENERIC_ENCODE_TABLES=0 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=0 \ -DXD3_MAIN=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-debug.exe: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -lm -o xdelta3-debug.exe \ $(XDWINFLAGS) \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=1 \ -DXD3_MAIN=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-32.exe: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c -lm -o xdelta3-32.exe \ $(XDWINFLAGS) \ -DXD3_DEBUG=1 \ -DXD3_USE_LARGEFILE64=0 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_MAIN=1 xdelta3-debug2.exe: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c -o xdelta3-debug2.exe \ $(XDWINFLAGS) \ -DXD3_DEBUG=2 \ -DXD3_MAIN=1 \ -DXD3_USE_LARGEFILE64=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -lm xdelta3-debug3.exe: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -o xdelta3-debug3.exe \ $(XDWINFLAGS) \ -DXD3_MAIN=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DXD3_USE_LARGEFILE64=1 \ -DREGRESSION_TEST=1 \ -DXD3_DEBUG=3 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -lm $(PYTGT): $(SOURCES) setup.py $(PYTHON) setup.py install --verbose --compile --force xdelta3_wrap.c xdelta3.py: xdelta3.swig swig -python xdelta3.swig xdelta3.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c $(SWIG_FLAGS) -o xdelta3.o xdelta3_wrap.o: xdelta3_wrap.c $(CC) -O3 $(CFLAGS) $(SWIG_FLAGS) \ -DHAVE_CONFIG_H \ -I/usr/include/python$(PYVER) \ -I/usr/lib/python$(PYVER)/config \ -fpic \ -c xdelta3_wrap.c # FIXME: MinGW ???? xdelta3module.dll: xdelta3_wrap.o xdelta3.o gcc -shared -Wl,--enable-auto-image-base \ xdelta3.o \ xdelta3_wrap.o \ -L/usr/lib/python$(PYVER)/config \ -lpython$(PYVER) \ -o xdelta3module.dll cp $(SWIGTGT) /usr/lib/python$(PYVER)/site-packages # FIXME: MinGW ???? xdelta3-decoder.exe: $(SOURCES) $(CC) -O3 -Wall -Wshadow xdelta3.c \ -DXD3_ENCODER=0 -DXD3_MAIN=1 -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 \ $(XDWINFLAGS) -DVCDIFF_TOOLS=0 \ -o xdelta3-decoder.exe xdelta3-decoder-nomain.o: $(SOURCES) linkxd3lib.c $(CC) -O3 -Wall -Wshadow xdelta3.c linkxd3lib.c \ -DXD3_ENCODER=0 -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 \ -o xdelta3-decoder-nomain.o strip xdelta3-decoder-nomain.o # FIXME: this OK with MinGW?? What's with strip?? xdelta3-64.exe: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c \ -o xdelta3-64.exe \ $(XDWINFLAGS) \ -DXD3_MAIN=1 \ -DREGRESSION_TEST=1 \ -DXD3_DEBUG=0 \ -DXD3_USE_LARGEFILE64=1 \ -lm xdelta3-everything.exe: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c \ -o xdelta3-everything.exe \ $(XDWINFLAGS) \ -DXD3_MAIN=1 \ -DVCDIFF_TOOLS=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_FGK=1 \ -DSECONDARY_DJW=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DGENERIC_ENCODE_TABLES_COMPUTE=1 \ -DXD3_DEBUG=1 \ -lm xdelta3-nosec.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c $(XDWINFLAGS) -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 -o xdelta3-nosec.o xdelta3-all.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c $(XDWINFLAGS) -DSECONDARY_FGK=1 -DSECONDARY_DJW=1 -o xdelta3-all.o xdelta3-fgk.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c $(XDWINFLAGS) -DSECONDARY_FGK=1 -DSECONDARY_DJW=0 -o xdelta3-fgk.o xdelta3-noext.exe: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c $(XDWINFLAGS) -DEXTERNAL_COMPRESSION=0 -DXD3_MAIN=1 -o xdelta3-noext.exe xdelta3-tools.exe: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c $(XDWINFLAGS) -DXD3_MAIN=1 -o xdelta3-tools.exe xdelta3-notools.exe: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c $(XDWINFLAGS) -DXD3_MAIN=1 -DVCDIFF_TOOLS=0 -o xdelta3-notools.exe xdelta3-3.0.7/xdelta3-main.h0000644000176500017650000031256212144343175015021 0ustar debdevdebdev/* xdelta3 - delta compression tools and library * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2012, 2013 Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This is all the extra stuff you need for convenience to users in a * command line application. It contains these major components: * * 1. VCDIFF tools 2. external compression support (this is * POSIX-specific). 3. a general read/write loop that handles all of * the Xdelta decode/encode/VCDIFF-print functions 4. command-line * interpreter 5. an Xdelta application header which stores default * filename, external compression settings 6. output/error printing * 7. basic file support and OS interface */ /* TODO list: 1. do exact gzip-like filename, stdout handling. make a * .vcdiff extension, refuse to encode to stdout without -cf, etc. * 2. Allow the user to add a comment string to the app header without * disturbing the default behavior. */ /* On error handling and printing: * * The xdelta library sets stream->msg to indicate what condition * caused an internal failure, but many failures originate here and * are printed here. The return convention is 0 for success, as * throughout Xdelta code, but special attention is required here for * the operating system calls with different error handling. See the * main_file_* routines. All errors in this file have a message * printed at the time of occurance. Since some of these calls occur * within calls to the library, the error may end up being printed * again with a more general error message. */ /*********************************************************************/ #ifndef XD3_POSIX #define XD3_POSIX 0 #endif #ifndef XD3_STDIO #define XD3_STDIO 0 #endif #ifndef XD3_WIN32 #define XD3_WIN32 0 #endif #ifndef NOT_MAIN #define NOT_MAIN 0 #endif /* Combines xd3_strerror() and strerror() */ const char* xd3_mainerror(int err_num); #include "xdelta3-internal.h" int xsnprintf_func (char *str, int n, const char *fmt, ...) { va_list a; int ret; va_start (a, fmt); ret = vsnprintf_func (str, n, fmt, a); va_end (a); if (ret < 0) { ret = n; } return ret; } /* If none are set, default to posix. */ #if (XD3_POSIX + XD3_STDIO + XD3_WIN32) == 0 #undef XD3_POSIX #define XD3_POSIX 1 #endif /* Handle externally-compressed inputs. */ #ifndef EXTERNAL_COMPRESSION #define EXTERNAL_COMPRESSION 1 #endif #define PRINTHDR_SPECIAL -4378291 /* The number of soft-config variables. */ #define XD3_SOFTCFG_VARCNT 7 /* this is used as in XPR(NT XD3_LIB_ERRMSG (stream, ret)) to print an * error message from the library. */ #define XD3_LIB_ERRMSG(stream, ret) "%s: %s\n", \ xd3_errstring (stream), xd3_mainerror (ret) #if XD3_POSIX #include /* close, read, write... */ #include #include #endif #ifndef _WIN32 #include /* lots */ #include /* gettimeofday() */ #include /* stat() and fstat() */ #else #if defined(_MSC_VER) #define strtoll _strtoi64 #endif #include #include #ifndef WIFEXITED # define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0) #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff) #endif #ifndef S_ISREG //# ifdef S_IFREG //# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) //# else # define S_ISREG(m) 1 //# endif #endif /* !S_ISREG */ // For standard input/output handles static STARTUPINFO winStartupInfo; #endif /********************************************************************** ENUMS and TYPES *********************************************************************/ /* These flags (mainly pertaining to main_read() operations) are set * in the main_file->flags variable. All are related to with external * decompression support. * * RD_FIRST causes the external decompression check when the input is * first read. * * RD_NONEXTERNAL disables external decompression for reading a * compressed input, in the case of Xdelta inputs. Note: Xdelta is * supported as an external compression type, which makes is the * reason for this flag. An example to justify this is: to create a * delta between two files that are VCDIFF-compressed. Two external * Xdelta decoders are run to supply decompressed source and target * inputs to the Xdelta encoder. */ typedef enum { RD_FIRST = (1 << 0), RD_NONEXTERNAL = (1 << 1), RD_DECOMPSET = (1 << 2), RD_MAININPUT = (1 << 3), } xd3_read_flags; /* Main commands. For example, CMD_PRINTHDR is the "xdelta printhdr" * command. */ typedef enum { CMD_NONE = 0, CMD_PRINTHDR, CMD_PRINTHDRS, CMD_PRINTDELTA, CMD_RECODE, CMD_MERGE_ARG, CMD_MERGE, #if XD3_ENCODER CMD_ENCODE, #endif CMD_DECODE, CMD_TEST, CMD_CONFIG, } xd3_cmd; #if XD3_ENCODER #define CMD_DEFAULT CMD_ENCODE #define IS_ENCODE(cmd) (cmd == CMD_ENCODE) #else #define CMD_DEFAULT CMD_DECODE #define IS_ENCODE(cmd) (0) #endif typedef struct _main_merge main_merge; typedef struct _main_merge_list main_merge_list; /* Various strings and magic values used to detect and call external * compression. See below for examples. */ struct _main_extcomp { const char *recomp_cmdname; const char *recomp_options; const char *decomp_cmdname; const char *decomp_options; const char *ident; const char *magic; usize_t magic_size; int flags; }; /* Merge state: */ struct _main_merge_list { main_merge_list *next; main_merge_list *prev; }; struct _main_merge { const char *filename; main_merge_list link; }; XD3_MAKELIST(main_merge_list,main_merge,link); /* TODO: really need to put options in a struct so that internal * callers can easily reset state. */ #define DEFAULT_VERBOSE 0 /* Program options: various command line flags and options. */ static int option_stdout = 0; static int option_force = 0; static int option_verbose = DEFAULT_VERBOSE; static int option_quiet = 0; static int option_use_appheader = 1; static uint8_t* option_appheader = NULL; static int option_use_secondary = 0; static const char* option_secondary = NULL; static int option_use_checksum = 1; static int option_use_altcodetable = 0; static const char* option_smatch_config = NULL; static int option_no_compress = 0; static int option_no_output = 0; /* do not write output */ static const char *option_source_filename = NULL; static int option_level = XD3_DEFAULT_LEVEL; static usize_t option_iopt_size = XD3_DEFAULT_IOPT_SIZE; static usize_t option_winsize = XD3_DEFAULT_WINSIZE; /* Note: option_srcwinsz is restricted from [16Kb, 4Gb], because * addresses in the large hash checksum are 32 bits. The flag is read * as xoff_t, so that 4Gb != 0. */ static xoff_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; static usize_t option_sprevsz = XD3_DEFAULT_SPREVSZ; /* These variables are supressed to avoid their use w/o support. main() warns * appropriately when external compression is not enabled. */ #if EXTERNAL_COMPRESSION static int num_subprocs = 0; static int option_force2 = 0; static int option_decompress_inputs = 1; static int option_recompress_outputs = 1; #endif /* This is for comparing "printdelta" output without attention to * copy-instruction modes. */ #if VCDIFF_TOOLS static int option_print_cpymode = 1; /* Note: see reset_defaults(). */ #endif /* Static variables */ IF_DEBUG(static int main_mallocs = 0;) static char* program_name = NULL; static uint8_t* appheader_used = NULL; static uint8_t* main_bdata = NULL; static usize_t main_bsize = 0; /* Hacks for VCDIFF tools, recode command. */ static int allow_fake_source = 0; /* recode_stream is used by both recode/merge for reading vcdiff inputs */ static xd3_stream *recode_stream = NULL; /* merge_stream is used by merge commands for storing the source encoding */ static xd3_stream *merge_stream = NULL; /* This array of compressor types is compiled even if EXTERNAL_COMPRESSION is * false just so the program knows the mapping of IDENT->NAME. */ static main_extcomp extcomp_types[] = { { "bzip2", "-c", "bzip2", "-dc", "B", "BZh", 3, 0 }, { "gzip", "-c", "gzip", "-dc", "G", "\037\213", 2, 0 }, { "compress", "-c", "uncompress", "-c", "Z", "\037\235", 2, 0 }, /* TODO: add commandline support for magic-less formats */ /*{ "lzma", "-c", "lzma", "-dc", "M", "]\000", 2, 0 },*/ /* Xz is lzma with a magic number http://tukaani.org/xz/ */ { "xz", "-c", "xz", "-dc", "Y", "\xfd\x37\x7a\x58\x5a\x00", 2, 0 }, }; static int main_input (xd3_cmd cmd, main_file *ifile, main_file *ofile, main_file *sfile); static void main_get_appheader (xd3_stream *stream, main_file *ifile, main_file *output, main_file *sfile); static int main_getblk_func (xd3_stream *stream, xd3_source *source, xoff_t blkno); static void main_free (void *ptr); static void* main_malloc (size_t size); static int main_file_stat (main_file *xfile, xoff_t *size); static int main_file_seek (main_file *xfile, xoff_t pos); static int main_read_primary_input (main_file *file, uint8_t *buf, size_t size, size_t *nread); static const char* main_format_bcnt (xoff_t r, shortbuf *buf); static int main_help (void); #if XD3_ENCODER static int xd3_merge_input_output (xd3_stream *stream, xd3_whole_state *source); #endif /* The code in xdelta3-blk.h is essentially part of this unit, see * comments there. */ #include "xdelta3-blkcache.h" void (*xprintf_message_func)(const char*msg) = NULL; void xprintf (const char *fmt, ...) { char buf[1000]; va_list a; int size; va_start (a, fmt); size = vsnprintf_func (buf, 1000, fmt, a); va_end (a); if (size < 0) { size = sizeof(buf) - 1; buf[size] = 0; } if (xprintf_message_func != NULL) { xprintf_message_func(buf); } else { size_t ignore = fwrite(buf, 1, size, stderr); (void) ignore; } } static int main_version (void) { /* $Format: " XPR(NTR \"Xdelta version $Xdelta3Version$, Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, Joshua MacDonald\\n\");" $ */ XPR(NTR "Xdelta version 3.0.7, Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Joshua MacDonald\n"); XPR(NTR "Xdelta comes with ABSOLUTELY NO WARRANTY.\n"); XPR(NTR "This is free software, and you are welcome to redistribute it\n"); XPR(NTR "under certain conditions; see \"COPYING\" for details.\n"); return EXIT_SUCCESS; } static int main_config (void) { main_version (); XPR(NTR "EXTERNAL_COMPRESSION=%d\n", EXTERNAL_COMPRESSION); XPR(NTR "GENERIC_ENCODE_TABLES=%d\n", GENERIC_ENCODE_TABLES); XPR(NTR "GENERIC_ENCODE_TABLES_COMPUTE=%d\n", GENERIC_ENCODE_TABLES_COMPUTE); XPR(NTR "REGRESSION_TEST=%d\n", REGRESSION_TEST); XPR(NTR "SECONDARY_DJW=%d\n", SECONDARY_DJW); XPR(NTR "SECONDARY_FGK=%d\n", SECONDARY_FGK); XPR(NTR "UNALIGNED_OK=%d\n", UNALIGNED_OK); XPR(NTR "VCDIFF_TOOLS=%d\n", VCDIFF_TOOLS); XPR(NTR "XD3_ALLOCSIZE=%d\n", XD3_ALLOCSIZE); XPR(NTR "XD3_DEBUG=%d\n", XD3_DEBUG); XPR(NTR "XD3_ENCODER=%d\n", XD3_ENCODER); XPR(NTR "XD3_POSIX=%d\n", XD3_POSIX); XPR(NTR "XD3_STDIO=%d\n", XD3_STDIO); XPR(NTR "XD3_WIN32=%d\n", XD3_WIN32); XPR(NTR "XD3_USE_LARGEFILE64=%d\n", XD3_USE_LARGEFILE64); XPR(NTR "XD3_DEFAULT_LEVEL=%d\n", XD3_DEFAULT_LEVEL); XPR(NTR "XD3_DEFAULT_IOPT_SIZE=%d\n", XD3_DEFAULT_IOPT_SIZE); XPR(NTR "XD3_DEFAULT_SPREVSZ=%d\n", XD3_DEFAULT_SPREVSZ); XPR(NTR "XD3_DEFAULT_SRCWINSZ=%d\n", XD3_DEFAULT_SRCWINSZ); XPR(NTR "XD3_DEFAULT_WINSIZE=%d\n", XD3_DEFAULT_WINSIZE); XPR(NTR "XD3_HARDMAXWINSIZE=%d\n", XD3_HARDMAXWINSIZE); XPR(NTR "sizeof(void*)=%d\n", (int)sizeof(void*)); XPR(NTR "sizeof(int)=%d\n", (int)sizeof(int)); XPR(NTR "sizeof(size_t)=%d\n", (int)sizeof(size_t)); XPR(NTR "sizeof(uint32_t)=%d\n", (int)sizeof(uint32_t)); XPR(NTR "sizeof(uint64_t)=%d\n", (int)sizeof(uint64_t)); XPR(NTR "sizeof(usize_t)=%d\n", (int)sizeof(usize_t)); XPR(NTR "sizeof(xoff_t)=%d\n", (int)sizeof(xoff_t)); return EXIT_SUCCESS; } static void reset_defaults(void) { option_stdout = 0; option_force = 0; option_verbose = DEFAULT_VERBOSE; option_quiet = 0; option_appheader = NULL; option_use_secondary = 0; option_secondary = NULL; option_use_altcodetable = 0; option_smatch_config = NULL; option_no_compress = 0; option_no_output = 0; option_source_filename = NULL; program_name = NULL; appheader_used = NULL; main_bdata = NULL; main_bsize = 0; allow_fake_source = 0; option_smatch_config = NULL; main_lru_reset(); option_use_appheader = 1; option_use_checksum = 1; #if EXTERNAL_COMPRESSION option_force2 = 0; option_decompress_inputs = 1; option_recompress_outputs = 1; num_subprocs = 0; #endif #if VCDIFF_TOOLS option_print_cpymode = 1; #endif option_level = XD3_DEFAULT_LEVEL; option_iopt_size = XD3_DEFAULT_IOPT_SIZE; option_winsize = XD3_DEFAULT_WINSIZE; option_srcwinsz = XD3_DEFAULT_SRCWINSZ; option_sprevsz = XD3_DEFAULT_SPREVSZ; } static void* main_malloc1 (size_t size) { void* r = malloc (size); if (r == NULL) { XPR(NT "malloc: %s\n", xd3_mainerror (ENOMEM)); } return r; } void* main_bufalloc (size_t size) { #if XD3_WIN32 return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #else return main_malloc1(size); #endif } static void* main_malloc (size_t size) { void *r = main_malloc1 (size); if (r) { IF_DEBUG (main_mallocs += 1); } return r; } static void* main_alloc (void *opaque, size_t items, usize_t size) { return main_malloc1 (items * size); } static void main_free1 (void *opaque, void *ptr) { free (ptr); } static void main_free (void *ptr) { if (ptr) { IF_DEBUG (main_mallocs -= 1); main_free1 (NULL, ptr); IF_DEBUG (XD3_ASSERT(main_mallocs >= 0)); } } void main_buffree (void *ptr) { #if XD3_WIN32 VirtualFree(ptr, 0, MEM_RELEASE); #else main_free1(NULL, ptr); #endif } /* This ensures that (ret = errno) always indicates failure, in case errno was * accidentally not set. If this prints there's a bug somewhere. */ static int get_errno (void) { #ifndef _WIN32 if (errno == 0) { XPR(NT "you found a bug: expected errno != 0\n"); errno = XD3_INTERNAL; } return errno; #else DWORD err_num = GetLastError(); if (err_num == NO_ERROR) { err_num = XD3_INTERNAL; } return err_num; #endif } const char* xd3_mainerror(int err_num) { #ifndef _WIN32 const char* x = xd3_strerror (err_num); if (x != NULL) { return x; } return strerror(err_num); #else static char err_buf[256]; const char* x = xd3_strerror (err_num); if (x != NULL) { return x; } memset (err_buf, 0, 256); FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err_num, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), err_buf, 256, NULL); if (err_buf[0] != 0 && err_buf[strlen(err_buf) - 1] == '\n') { err_buf[strlen(err_buf) - 1] = 0; } return err_buf; #endif } static long get_millisecs_now (void) { #ifndef _WIN32 struct timeval tv; gettimeofday (& tv, NULL); return (tv.tv_sec) * 1000L + (tv.tv_usec) / 1000; #else SYSTEMTIME st; FILETIME ft; __int64 *pi = (__int64*)&ft; GetLocalTime(&st); SystemTimeToFileTime(&st, &ft); return (long)((*pi) / 10000); #endif } /* Always >= 1 millisec, right? */ static long get_millisecs_since (void) { static long last = 0; long now = get_millisecs_now(); long diff = now - last; last = now; return diff; } static const char* main_format_bcnt (xoff_t r, shortbuf *buf) { static const char* fmts[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" }; usize_t i; for (i = 0; i < SIZEOF_ARRAY(fmts) - 1; i += 1) { xoff_t new_r; if (r == 0) { short_sprintf (*buf, "0 %s", fmts[i]); return buf->buf; } if (r >= 1 && r < 10) { short_sprintf (*buf, "%.2f %s", (double) r, fmts[i]); return buf->buf; } if (r >= 10 && r < 100) { short_sprintf (*buf, "%.1f %s", (double) r, fmts[i]); return buf->buf; } if (r >= 100 && r < 1000) { short_sprintf (*buf, "%"Q"u %s", r, fmts[i]); return buf->buf; } new_r = r / 1024; if (new_r < 10) { short_sprintf (*buf, "%.2f %s", (double) r / 1024.0, fmts[i + 1]); return buf->buf; } if (new_r < 100) { short_sprintf (*buf, "%.1f %s", (double) r / 1024.0, fmts[i + 1]); return buf->buf; } r = new_r; } XD3_ASSERT (0); return ""; } static char* main_format_rate (xoff_t bytes, long millis, shortbuf *buf) { xoff_t r = (xoff_t)(1.0 * bytes / (1.0 * millis / 1000.0)); static shortbuf lbuf; main_format_bcnt (r, &lbuf); short_sprintf (*buf, "%s/s", lbuf.buf); return buf->buf; } static char* main_format_millis (long millis, shortbuf *buf) { if (millis < 1000) { short_sprintf (*buf, "%lu ms", millis); } else if (millis < 10000) { short_sprintf (*buf, "%.1f sec", millis / 1000.0); } else { short_sprintf (*buf, "%lu sec", millis / 1000L); } return buf->buf; } /* A safe version of strtol for xoff_t. */ static int main_strtoxoff (const char* s, xoff_t *xo, char which) { char *e; xoff_t x; XD3_ASSERT(s && *s != 0); { /* Should check LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX? */ #if SIZEOF_XOFF_T == 4 long xx = strtol (s, &e, 0); #else long long xx = strtoll (s, &e, 0); #endif if (xx < 0) { XPR(NT "-%c: negative integer: %s\n", which, s); return EXIT_FAILURE; } x = xx; } if (*e != 0) { XPR(NT "-%c: invalid integer: %s\n", which, s); return EXIT_FAILURE; } (*xo) = x; return 0; } static int main_atoux (const char* arg, xoff_t *xo, xoff_t low, xoff_t high, char which) { xoff_t x; int ret; if ((ret = main_strtoxoff (arg, & x, which))) { return ret; } if (x < low) { XPR(NT "-%c: minimum value: %"Q"u\n", which, low); return EXIT_FAILURE; } if (high != 0 && x > high) { XPR(NT "-%c: maximum value: %"Q"u\n", which, high); return EXIT_FAILURE; } (*xo) = x; return 0; } static int main_atou (const char* arg, usize_t *uo, usize_t low, usize_t high, char which) { int ret; xoff_t xo; if ((ret = main_atoux (arg, &xo, low, high, which))) { return ret; } *uo = (usize_t)xo; return 0; } /****************************************************************** FILE BASICS ******************************************************************/ /* With all the variation in file system-call semantics, arguments, * return values and error-handling for the POSIX and STDIO file APIs, * the insides of these functions make me sick, which is why these * wrappers exist. */ #define XOPEN_OPNAME (xfile->mode == XO_READ ? "read" : "write") #define XOPEN_STDIO (xfile->mode == XO_READ ? "rb" : "wb") #define XOPEN_POSIX (xfile->mode == XO_READ ? \ O_RDONLY : O_WRONLY | O_CREAT | O_TRUNC) #define XOPEN_MODE (xfile->mode == XO_READ ? 0 : 0666) #define XF_ERROR(op, name, ret) \ do { if (!option_quiet) { XPR(NT "file %s failed: %s: %s: %s\n", (op), \ XOPEN_OPNAME, (name), xd3_mainerror (ret)); } } while (0) #if XD3_STDIO #define XFNO(f) fileno(f->file) #define XSTDOUT_XF(f) { (f)->file = stdout; (f)->filename = "/dev/stdout"; } #define XSTDIN_XF(f) { (f)->file = stdin; (f)->filename = "/dev/stdin"; } #elif XD3_POSIX #define XFNO(f) f->file #define XSTDOUT_XF(f) \ { (f)->file = STDOUT_FILENO; (f)->filename = "/dev/stdout"; } #define XSTDIN_XF(f) \ { (f)->file = STDIN_FILENO; (f)->filename = "/dev/stdin"; } #elif XD3_WIN32 #define XFNO(f) -1 #define XSTDOUT_XF(f) { \ (f)->file = GetStdHandle(STD_OUTPUT_HANDLE); \ (f)->filename = "(stdout)"; \ } #define XSTDIN_XF(f) { \ (f)->file = GetStdHandle(STD_INPUT_HANDLE); \ (f)->filename = "(stdin)"; \ } #endif void main_file_init (main_file *xfile) { memset (xfile, 0, sizeof (*xfile)); #if XD3_POSIX xfile->file = -1; #endif #if XD3_WIN32 xfile->file = INVALID_HANDLE_VALUE; #endif } int main_file_isopen (main_file *xfile) { #if XD3_STDIO return xfile->file != NULL; #elif XD3_POSIX return xfile->file != -1; #elif XD3_WIN32 return xfile->file != INVALID_HANDLE_VALUE; #endif } int main_file_close (main_file *xfile) { int ret = 0; if (! main_file_isopen (xfile)) { return 0; } #if XD3_STDIO ret = fclose (xfile->file); xfile->file = NULL; #elif XD3_POSIX ret = close (xfile->file); xfile->file = -1; #elif XD3_WIN32 if (!CloseHandle(xfile->file)) { ret = get_errno (); } xfile->file = INVALID_HANDLE_VALUE; #endif if (ret != 0) { XF_ERROR ("close", xfile->filename, ret = get_errno ()); } return ret; } void main_file_cleanup (main_file *xfile) { XD3_ASSERT (xfile != NULL); if (main_file_isopen (xfile)) { main_file_close (xfile); } if (xfile->snprintf_buf != NULL) { main_free(xfile->snprintf_buf); xfile->snprintf_buf = NULL; } if (xfile->filename_copy != NULL) { main_free(xfile->filename_copy); xfile->filename_copy = NULL; } } int main_file_open (main_file *xfile, const char* name, int mode) { int ret = 0; xfile->mode = mode; XD3_ASSERT (name != NULL); XD3_ASSERT (! main_file_isopen (xfile)); if (name[0] == 0) { XPR(NT "invalid file name: empty string\n"); return XD3_INVALID; } #if XD3_STDIO xfile->file = fopen (name, XOPEN_STDIO); ret = (xfile->file == NULL) ? get_errno () : 0; #elif XD3_POSIX /* TODO: Should retry this call if interrupted, similar to read/write */ if ((ret = open (name, XOPEN_POSIX, XOPEN_MODE)) < 0) { ret = get_errno (); } else { xfile->file = ret; ret = 0; } #elif XD3_WIN32 xfile->file = CreateFile(name, (mode == XO_READ) ? GENERIC_READ : GENERIC_WRITE, FILE_SHARE_READ, NULL, (mode == XO_READ) ? OPEN_EXISTING : (option_force ? CREATE_ALWAYS : CREATE_NEW), FILE_ATTRIBUTE_NORMAL, NULL); if (xfile->file == INVALID_HANDLE_VALUE) { ret = get_errno (); } #endif if (ret) { XF_ERROR ("open", name, ret); } else { xfile->realname = name; xfile->nread = 0; } return ret; } int main_file_stat (main_file *xfile, xoff_t *size) { int ret = 0; #if XD3_WIN32 if (GetFileType(xfile->file) != FILE_TYPE_DISK) { return -1; } # if (_WIN32_WINNT >= 0x0500) { LARGE_INTEGER li; if (GetFileSizeEx(xfile->file, &li) == 0) { return get_errno (); } *size = li.QuadPart; } # else { DWORD filesize = GetFileSize(xfile->file, NULL); if (filesize == INVALID_FILE_SIZE) { return get_errno () } *size = filesize; } # endif #else struct stat sbuf; if (fstat (XFNO (xfile), & sbuf) < 0) { ret = get_errno (); return ret; } if (! S_ISREG (sbuf.st_mode)) { return ESPIPE; } (*size) = sbuf.st_size; #endif return ret; } int main_file_exists (main_file *xfile) { struct stat sbuf; return stat (xfile->filename, & sbuf) == 0 && S_ISREG (sbuf.st_mode); } #if (XD3_POSIX || EXTERNAL_COMPRESSION) /* POSIX-generic code takes a function pointer to read() or write(). * This calls the function repeatedly until the buffer is full or EOF. * The NREAD parameter is not set for write, NULL is passed. Return * is signed, < 0 indicate errors, otherwise byte count. */ typedef int (xd3_posix_func) (int fd, uint8_t *buf, usize_t size); static int xd3_posix_io (int fd, uint8_t *buf, size_t size, xd3_posix_func *func, size_t *nread) { int ret; size_t nproc = 0; while (nproc < size) { size_t tryread = min(size - nproc, 1U << 30); ssize_t result = (*func) (fd, buf + nproc, tryread); if (result < 0) { ret = get_errno (); if (ret != EAGAIN && ret != EINTR) { return ret; } continue; } if (nread != NULL && result == 0) { break; } nproc += result; } if (nread != NULL) { (*nread) = nproc; } return 0; } #endif #if XD3_WIN32 static int xd3_win32_io (HANDLE file, uint8_t *buf, size_t size, int is_read, size_t *nread) { int ret = 0; size_t nproc = 0; while (nproc < size) { DWORD nproc2 = 0; /* hmm */ DWORD nremain = size - nproc; if ((is_read ? ReadFile (file, buf + nproc, nremain, &nproc2, NULL) : WriteFile (file, buf + nproc, nremain, &nproc2, NULL)) == 0) { ret = get_errno(); if (ret != ERROR_HANDLE_EOF && ret != ERROR_BROKEN_PIPE) { return ret; } /* By falling through here, we'll break this loop in the * read case in case of eof or broken pipe. */ } nproc += nproc2; if (nread != NULL && nproc2 == 0) { break; } } if (nread != NULL) { (*nread) = nproc; } return 0; } #endif /* POSIX is unbuffered, while STDIO is buffered. main_file_read() * should always be called on blocks. */ int main_file_read (main_file *ifile, uint8_t *buf, size_t size, size_t *nread, const char *msg) { int ret = 0; #if XD3_STDIO size_t result; result = fread (buf, 1, size, ifile->file); if (result < size && ferror (ifile->file)) { ret = get_errno (); } else { *nread = result; } #elif XD3_POSIX ret = xd3_posix_io (ifile->file, buf, size, (xd3_posix_func*) &read, nread); #elif XD3_WIN32 ret = xd3_win32_io (ifile->file, buf, size, 1 /* is_read */, nread); #endif if (ret) { XPR(NT "%s: %s: %s\n", msg, ifile->filename, xd3_mainerror (ret)); } else { if (option_verbose > 4) { XPR(NT "read %s: %zu bytes\n", ifile->filename, (*nread)); } ifile->nread += (*nread); } return ret; } int main_file_write (main_file *ofile, uint8_t *buf, usize_t size, const char *msg) { int ret = 0; #if XD3_STDIO usize_t result; result = fwrite (buf, 1, size, ofile->file); if (result != size) { ret = get_errno (); } #elif XD3_POSIX ret = xd3_posix_io (ofile->file, buf, size, (xd3_posix_func*) &write, NULL); #elif XD3_WIN32 ret = xd3_win32_io (ofile->file, buf, size, 0, NULL); #endif if (ret) { XPR(NT "%s: %s: %s\n", msg, ofile->filename, xd3_mainerror (ret)); } else { if (option_verbose > 5) { XPR(NT "write %s: %u bytes\n", ofile->filename, size); } ofile->nwrite += size; } return ret; } static int main_file_seek (main_file *xfile, xoff_t pos) { int ret = 0; #if XD3_STDIO if (fseek (xfile->file, pos, SEEK_SET) != 0) { ret = get_errno (); } #elif XD3_POSIX if ((xoff_t) lseek (xfile->file, pos, SEEK_SET) != pos) { ret = get_errno (); } #elif XD3_WIN32 # if (_WIN32_WINNT >= 0x0500) LARGE_INTEGER move, out; move.QuadPart = pos; if (SetFilePointerEx(xfile->file, move, &out, FILE_BEGIN) == 0) { ret = get_errno (); } # else if (SetFilePointer(xfile->file, (LONG)pos, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { ret = get_errno (); } # endif #endif return ret; } /* This function simply writes the stream output buffer, if there is * any, for encode, decode and recode commands. (The VCDIFF tools use * main_print_func()). */ static int main_write_output (xd3_stream* stream, main_file *ofile) { int ret; if (option_no_output) { return 0; } if (stream->avail_out > 0 && (ret = main_file_write (ofile, stream->next_out, stream->avail_out, "write failed"))) { return ret; } return 0; } static int main_set_secondary_flags (xd3_config *config) { int ret; if (option_use_secondary) { /* The default secondary compressor is DJW, if it's compiled. */ if (option_secondary == NULL) { if (SECONDARY_DJW) { config->flags |= XD3_SEC_DJW; } } else { if (strcmp (option_secondary, "fgk") == 0 && SECONDARY_FGK) { config->flags |= XD3_SEC_FGK; } else if (strcmp (option_secondary, "lzma") == 0 && SECONDARY_LZMA) { config->flags |= XD3_SEC_LZMA; } else if (strncmp (option_secondary, "djw", 3) == 0 && SECONDARY_DJW) { usize_t level = XD3_DEFAULT_SECONDARY_LEVEL; config->flags |= XD3_SEC_DJW; if (strlen (option_secondary) > 3 && (ret = main_atou (option_secondary + 3, &level, 0, 9, 'S')) != 0 && !option_quiet) { return XD3_INVALID; } /* XD3_SEC_NOXXXX flags disable secondary compression on * a per-section basis. For djw, ngroups=1 indicates * minimum work, ngroups=0 uses default settings, which * is > 1 groups by default. */ if (level < 1) { config->flags |= XD3_SEC_NODATA; } if (level < 7) { config->sec_data.ngroups = 1; } else { config->sec_data.ngroups = 0; } if (level < 3) { config->flags |= XD3_SEC_NOINST; } if (level < 8) { config->sec_inst.ngroups = 1; } else { config->sec_inst.ngroups = 0; } if (level < 5) { config->flags |= XD3_SEC_NOADDR; } if (level < 9) { config->sec_addr.ngroups = 1; } else { config->sec_addr.ngroups = 0; } } else if (strcmp (option_secondary, "none") == 0 && SECONDARY_DJW) { /* No secondary */ } else { if (!option_quiet) { XPR(NT "unrecognized secondary compressor type: %s\n", option_secondary); return XD3_INVALID; } } } } return 0; } /****************************************************************** VCDIFF TOOLS *****************************************************************/ #if VCDIFF_TOOLS #include "xdelta3-merge.h" /* The following macros let VCDIFF print using main_file_write(), * for example: * * VC(UT "trying to be portable: %d\n", x)VE; */ #define SNPRINTF_BUFSIZE 1024 #define VC do { if (((ret = xsnprintf_func #define UT (char*)xfile->snprintf_buf, SNPRINTF_BUFSIZE, #define VE ) >= SNPRINTF_BUFSIZE \ && (ret = main_print_overflow(ret)) != 0) \ || (ret = main_file_write(xfile, xfile->snprintf_buf, \ (usize_t)ret, "print")) != 0) \ { return ret; } } while (0) static int main_print_overflow (int x) { XPR(NT "internal print buffer overflow: %d bytes\n", x); return XD3_INTERNAL; } /* This function prints a single VCDIFF window. */ static int main_print_window (xd3_stream* stream, main_file *xfile) { int ret; usize_t size = 0; VC(UT " Offset Code Type1 Size1 @Addr1 + Type2 Size2 @Addr2\n")VE; while (stream->inst_sect.buf < stream->inst_sect.buf_max) { usize_t code = stream->inst_sect.buf[0]; const uint8_t *addr_before = stream->addr_sect.buf; const uint8_t *inst_before = stream->inst_sect.buf; usize_t addr_bytes; usize_t inst_bytes; usize_t size_before = size; if ((ret = xd3_decode_instruction (stream))) { XPR(NT "instruction decode error at %"Q"u: %s\n", stream->dec_winstart + size, stream->msg); return ret; } addr_bytes = (usize_t)(stream->addr_sect.buf - addr_before); inst_bytes = (usize_t)(stream->inst_sect.buf - inst_before); VC(UT " %06"Q"u %03u %s %6u", stream->dec_winstart + size, option_print_cpymode ? code : 0, xd3_rtype_to_string ((xd3_rtype) stream->dec_current1.type, option_print_cpymode), stream->dec_current1.size)VE; if (stream->dec_current1.type != XD3_NOOP) { if (stream->dec_current1.type >= XD3_CPY) { if (stream->dec_current1.addr >= stream->dec_cpylen) { VC(UT " T@%-6u", stream->dec_current1.addr - stream->dec_cpylen)VE; } else { VC(UT " S@%-6"Q"u", stream->dec_cpyoff + stream->dec_current1.addr)VE; } } else { VC(UT " ")VE; } size += stream->dec_current1.size; } if (stream->dec_current2.type != XD3_NOOP) { VC(UT " %s %6u", xd3_rtype_to_string ((xd3_rtype) stream->dec_current2.type, option_print_cpymode), stream->dec_current2.size)VE; if (stream->dec_current2.type >= XD3_CPY) { if (stream->dec_current2.addr >= stream->dec_cpylen) { VC(UT " T@%-6u", stream->dec_current2.addr - stream->dec_cpylen)VE; } else { VC(UT " S@%-6"Q"u", stream->dec_cpyoff + stream->dec_current2.addr)VE; } } size += stream->dec_current2.size; } VC(UT "\n")VE; if (option_verbose && addr_bytes + inst_bytes >= (size - size_before) && (stream->dec_current1.type >= XD3_CPY || stream->dec_current2.type >= XD3_CPY)) { VC(UT " %06"Q"u (inefficiency) %u encoded as %u bytes\n", stream->dec_winstart + size_before, size - size_before, addr_bytes + inst_bytes)VE; } } if (stream->dec_tgtlen != size && (stream->flags & XD3_SKIP_WINDOW) == 0) { XPR(NT "target window size inconsistency"); return XD3_INTERNAL; } if (stream->dec_position != stream->dec_maxpos) { XPR(NT "target window position inconsistency"); return XD3_INTERNAL; } if (stream->addr_sect.buf != stream->addr_sect.buf_max) { XPR(NT "address section inconsistency"); return XD3_INTERNAL; } return 0; } static int main_print_vcdiff_file (main_file *xfile, main_file *file, const char *type) { int ret; /* Used by above macros */ if (file->filename) { VC(UT "XDELTA filename (%s): %s\n", type, file->filename)VE; } if (file->compressor) { VC(UT "XDELTA ext comp (%s): %s\n", type, file->compressor->recomp_cmdname)VE; } return 0; } /* This function prints a VCDIFF input, mainly for debugging purposes. */ static int main_print_func (xd3_stream* stream, main_file *xfile) { int ret; if (option_no_output) { return 0; } if (xfile->snprintf_buf == NULL) { if ((xfile->snprintf_buf = (uint8_t*)main_malloc(SNPRINTF_BUFSIZE)) == NULL) { return ENOMEM; } } if (stream->dec_winstart == 0) { VC(UT "VCDIFF version: 0\n")VE; VC(UT "VCDIFF header size: %d\n", stream->dec_hdrsize)VE; VC(UT "VCDIFF header indicator: ")VE; if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0) VC(UT "VCD_SECONDARY ")VE; if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) VC(UT "VCD_CODETABLE ")VE; if ((stream->dec_hdr_ind & VCD_APPHEADER) != 0) VC(UT "VCD_APPHEADER ")VE; if (stream->dec_hdr_ind == 0) VC(UT "none")VE; VC(UT "\n")VE; IF_SEC(VC(UT "VCDIFF secondary compressor: %s\n", stream->sec_type ? stream->sec_type->name : "none")VE); IF_NSEC(VC(UT "VCDIFF secondary compressor: unsupported\n")VE); if (stream->dec_hdr_ind & VCD_APPHEADER) { uint8_t *apphead; usize_t appheadsz; ret = xd3_get_appheader (stream, & apphead, & appheadsz); if (ret == 0 && appheadsz > 0) { int sq = option_quiet; main_file i, o, s; XD3_ASSERT (apphead != NULL); VC(UT "VCDIFF application header: ")VE; if ((ret = main_file_write (xfile, apphead, appheadsz, "print")) != 0) { return ret; } VC(UT "\n")VE; main_file_init (& i); main_file_init (& o); main_file_init (& s); option_quiet = 1; main_get_appheader (stream, &i, & o, & s); option_quiet = sq; if ((ret = main_print_vcdiff_file (xfile, & o, "output"))) { return ret; } if ((ret = main_print_vcdiff_file (xfile, & s, "source"))) { return ret; } main_file_cleanup (& i); main_file_cleanup (& o); main_file_cleanup (& s); } } } else { VC(UT "\n")VE; } VC(UT "VCDIFF window number: %"Q"u\n", stream->current_window)VE; VC(UT "VCDIFF window indicator: ")VE; if ((stream->dec_win_ind & VCD_SOURCE) != 0) VC(UT "VCD_SOURCE ")VE; if ((stream->dec_win_ind & VCD_TARGET) != 0) VC(UT "VCD_TARGET ")VE; if ((stream->dec_win_ind & VCD_ADLER32) != 0) VC(UT "VCD_ADLER32 ")VE; if (stream->dec_win_ind == 0) VC(UT "none")VE; VC(UT "\n")VE; if ((stream->dec_win_ind & VCD_ADLER32) != 0) { VC(UT "VCDIFF adler32 checksum: %08X\n", (usize_t)stream->dec_adler32)VE; } if (stream->dec_del_ind != 0) { VC(UT "VCDIFF delta indicator: ")VE; if ((stream->dec_del_ind & VCD_DATACOMP) != 0) VC(UT "VCD_DATACOMP ")VE; if ((stream->dec_del_ind & VCD_INSTCOMP) != 0) VC(UT "VCD_INSTCOMP ")VE; if ((stream->dec_del_ind & VCD_ADDRCOMP) != 0) VC(UT "VCD_ADDRCOMP ")VE; if (stream->dec_del_ind == 0) VC(UT "none")VE; VC(UT "\n")VE; } if (stream->dec_winstart != 0) { VC(UT "VCDIFF window at offset: %"Q"u\n", stream->dec_winstart)VE; } if (SRCORTGT (stream->dec_win_ind)) { VC(UT "VCDIFF copy window length: %u\n", (usize_t)stream->dec_cpylen)VE; VC(UT "VCDIFF copy window offset: %"Q"u\n", stream->dec_cpyoff)VE; } VC(UT "VCDIFF delta encoding length: %u\n", (usize_t)stream->dec_enclen)VE; VC(UT "VCDIFF target window length: %u\n", (usize_t)stream->dec_tgtlen)VE; VC(UT "VCDIFF data section length: %u\n", (usize_t)stream->data_sect.size)VE; VC(UT "VCDIFF inst section length: %u\n", (usize_t)stream->inst_sect.size)VE; VC(UT "VCDIFF addr section length: %u\n", (usize_t)stream->addr_sect.size)VE; ret = 0; if ((stream->flags & XD3_JUST_HDR) != 0) { /* Print a header -- finished! */ ret = PRINTHDR_SPECIAL; } else if ((stream->flags & XD3_SKIP_WINDOW) == 0) { ret = main_print_window (stream, xfile); } return ret; } static int main_recode_copy (xd3_stream* stream, xd3_output* output, xd3_desect* input) { int ret; XD3_ASSERT(output != NULL); XD3_ASSERT(output->next_page == NULL); if ((ret = xd3_decode_allocate (recode_stream, input->size, &output->base, &output->avail))) { XPR(NT XD3_LIB_ERRMSG (stream, ret)); return ret; } memcpy (output->base, /* Note: decoder advances buf, so get base of buffer with * buf_max - size */ input->buf_max - input->size, input->size); output->next = input->size; return 0; } // Re-encode one window static int main_recode_func (xd3_stream* stream, main_file *ofile) { int ret; xd3_source decode_source; XD3_ASSERT(stream->dec_state == DEC_FINISH); XD3_ASSERT(recode_stream->enc_state == ENC_INIT || recode_stream->enc_state == ENC_INPUT); // Copy partial decoder output to partial encoder inputs if ((ret = main_recode_copy (recode_stream, DATA_HEAD(recode_stream), &stream->data_sect)) || (ret = main_recode_copy (recode_stream, INST_HEAD(recode_stream), &stream->inst_sect)) || (ret = main_recode_copy (recode_stream, ADDR_HEAD(recode_stream), &stream->addr_sect))) { return ret; } // This jumps to xd3_emit_hdr() recode_stream->enc_state = ENC_FLUSH; recode_stream->avail_in = stream->dec_tgtlen; if (SRCORTGT (stream->dec_win_ind)) { recode_stream->src = & decode_source; decode_source.srclen = stream->dec_cpylen; decode_source.srcbase = stream->dec_cpyoff; } if (option_use_checksum && (stream->dec_win_ind & VCD_ADLER32) != 0) { recode_stream->flags |= XD3_ADLER32_RECODE; recode_stream->recode_adler32 = stream->dec_adler32; } if (option_use_appheader != 0 && option_appheader != NULL) { xd3_set_appheader (recode_stream, option_appheader, (usize_t) strlen ((char*) option_appheader)); } else if (option_use_appheader != 0 && option_appheader == NULL) { if (stream->dec_appheader != NULL) { xd3_set_appheader (recode_stream, stream->dec_appheader, stream->dec_appheadsz); } } // Output loop for (;;) { switch((ret = xd3_encode_input (recode_stream))) { case XD3_INPUT: { /* finished recoding one window */ stream->total_out = recode_stream->total_out; return 0; } case XD3_OUTPUT: { /* main_file_write below */ break; } case XD3_GOTHEADER: case XD3_WINSTART: case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: case 0: { return XD3_INTERNAL; } default: return ret; } if ((ret = main_write_output (recode_stream, ofile))) { return ret; } xd3_consume_output (recode_stream); } } #endif /* VCDIFF_TOOLS */ /******************************************************************* VCDIFF merging ******************************************************************/ #if VCDIFF_TOOLS /* Modifies static state. */ static int main_init_recode_stream (void) { int ret; int stream_flags = XD3_ADLER32_NOVER | XD3_SKIP_EMIT; int recode_flags; xd3_config recode_config; XD3_ASSERT (recode_stream == NULL); if ((recode_stream = (xd3_stream*) main_malloc(sizeof(xd3_stream))) == NULL) { return ENOMEM; } recode_flags = (stream_flags & XD3_SEC_TYPE); recode_config.alloc = main_alloc; recode_config.freef = main_free1; xd3_init_config(&recode_config, recode_flags); if ((ret = main_set_secondary_flags (&recode_config)) || (ret = xd3_config_stream (recode_stream, &recode_config)) || (ret = xd3_encode_init_partial (recode_stream)) || (ret = xd3_whole_state_init (recode_stream))) { XPR(NT XD3_LIB_ERRMSG (recode_stream, ret)); xd3_free_stream (recode_stream); recode_stream = NULL; return ret; } return 0; } /* This processes the sequence of -m arguments. The final input * is processed as part of the ordinary main_input() loop. */ static int main_merge_arguments (main_merge_list* merges) { int ret = 0; int count = 0; main_merge *merge = NULL; xd3_stream merge_input; if (main_merge_list_empty (merges)) { return 0; } if ((ret = xd3_config_stream (& merge_input, NULL)) || (ret = xd3_whole_state_init (& merge_input))) { XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); return ret; } merge = main_merge_list_front (merges); while (!main_merge_list_end (merges, merge)) { main_file mfile; main_file_init (& mfile); mfile.filename = merge->filename; mfile.flags = RD_NONEXTERNAL; if ((ret = main_file_open (& mfile, merge->filename, XO_READ))) { goto error; } ret = main_input (CMD_MERGE_ARG, & mfile, NULL, NULL); if (ret == 0) { if (count++ == 0) { /* The first merge source is the next merge input. */ xd3_swap_whole_state (& recode_stream->whole_target, & merge_input.whole_target); } else { /* Merge the recode_stream with merge_input. */ ret = xd3_merge_input_output (recode_stream, & merge_input.whole_target); /* Save the next merge source in merge_input. */ xd3_swap_whole_state (& recode_stream->whole_target, & merge_input.whole_target); } } main_file_cleanup (& mfile); if (recode_stream != NULL) { xd3_free_stream (recode_stream); main_free (recode_stream); recode_stream = NULL; } if (main_bdata != NULL) { main_buffree (main_bdata); main_bdata = NULL; main_bsize = 0; } if (ret != 0) { goto error; } merge = main_merge_list_next (merge); } XD3_ASSERT (merge_stream == NULL); if ((merge_stream = (xd3_stream*) main_malloc (sizeof(xd3_stream))) == NULL) { ret = ENOMEM; goto error; } if ((ret = xd3_config_stream (merge_stream, NULL)) || (ret = xd3_whole_state_init (merge_stream))) { XPR(NT XD3_LIB_ERRMSG (& merge_input, ret)); goto error; } xd3_swap_whole_state (& merge_stream->whole_target, & merge_input.whole_target); ret = 0; error: xd3_free_stream (& merge_input); return ret; } /* This processes each window of the final merge input. This routine * does not output, it buffers the entire delta into memory. */ static int main_merge_func (xd3_stream* stream, main_file *no_write) { int ret; if ((ret = xd3_whole_append_window (stream))) { return ret; } return 0; } /* This is called after all windows have been read, as a final step in * main_input(). This is only called for the final merge step. */ static int main_merge_output (xd3_stream *stream, main_file *ofile) { int ret; usize_t inst_pos = 0; xoff_t output_pos = 0; xd3_source recode_source; usize_t window_num = 0; int at_least_once = 0; /* merge_stream is set if there were arguments. this stream's input * needs to be applied to the merge_stream source. */ if ((merge_stream != NULL) && (ret = xd3_merge_input_output (stream, & merge_stream->whole_target))) { XPR(NT XD3_LIB_ERRMSG (stream, ret)); return ret; } if (option_use_appheader != 0 && option_appheader != NULL) { xd3_set_appheader (recode_stream, option_appheader, (usize_t) strlen ((char*) option_appheader)); } /* Enter the ENC_INPUT state and bypass the next_in == NULL test * and (leftover) input buffering logic. */ XD3_ASSERT(recode_stream->enc_state == ENC_INIT); recode_stream->enc_state = ENC_INPUT; recode_stream->next_in = main_bdata; recode_stream->flags |= XD3_FLUSH; /* This encodes the entire target. */ while (inst_pos < stream->whole_target.instlen || !at_least_once) { xoff_t window_start = output_pos; int window_srcset = 0; xoff_t window_srcmin = 0; xoff_t window_srcmax = 0; usize_t window_pos = 0; usize_t window_size; /* at_least_once ensures that we encode at least one window, * which handles the 0-byte case. */ at_least_once = 1; XD3_ASSERT (recode_stream->enc_state == ENC_INPUT); if ((ret = xd3_encode_input (recode_stream)) != XD3_WINSTART) { XPR(NT "invalid merge state: %s\n", xd3_mainerror (ret)); return XD3_INVALID; } /* Window sizes must match from the input to the output, so that * target copies are in-range (and so that checksums carry * over). */ XD3_ASSERT (window_num < stream->whole_target.wininfolen); window_size = stream->whole_target.wininfo[window_num].length; /* Output position should also match. */ if (output_pos != stream->whole_target.wininfo[window_num].offset) { XPR(NT "internal merge error: offset mismatch\n"); return XD3_INVALID; } if (option_use_checksum && (stream->dec_win_ind & VCD_ADLER32) != 0) { recode_stream->flags |= XD3_ADLER32_RECODE; recode_stream->recode_adler32 = stream->whole_target.wininfo[window_num].adler32; } window_num++; if (main_bsize < window_size) { main_buffree (main_bdata); main_bdata = NULL; main_bsize = 0; if ((main_bdata = (uint8_t*) main_bufalloc (window_size)) == NULL) { return ENOMEM; } main_bsize = window_size; } /* This encodes a single target window. */ while (window_pos < window_size && inst_pos < stream->whole_target.instlen) { xd3_winst *inst = &stream->whole_target.inst[inst_pos]; usize_t take = min(inst->size, window_size - window_pos); xoff_t addr; switch (inst->type) { case XD3_RUN: if ((ret = xd3_emit_run (recode_stream, window_pos, take, &stream->whole_target.adds[inst->addr]))) { return ret; } break; case XD3_ADD: /* Adds are implicit, put them into the input buffer. */ memcpy (main_bdata + window_pos, stream->whole_target.adds + inst->addr, take); break; default: /* XD3_COPY + copy mode */ if (inst->mode != 0) { if (window_srcset) { window_srcmin = min(window_srcmin, inst->addr); window_srcmax = max(window_srcmax, inst->addr + take); } else { window_srcset = 1; window_srcmin = inst->addr; window_srcmax = inst->addr + take; } addr = inst->addr; } else { XD3_ASSERT (inst->addr >= window_start); addr = inst->addr - window_start; } IF_DEBUG2 (XPR(NTR "[merge copy] winpos %u take %u addr %"Q"u mode %u\n", window_pos, take, addr, inst->mode)); if ((ret = xd3_found_match (recode_stream, window_pos, take, addr, inst->mode != 0))) { return ret; } break; } window_pos += take; output_pos += take; if (take == inst->size) { inst_pos += 1; } else { /* Modify the instruction for the next pass. */ if (inst->type != XD3_RUN) { inst->addr += take; } inst->size -= take; } } xd3_avail_input (recode_stream, main_bdata, window_pos); recode_stream->enc_state = ENC_INSTR; if (window_srcset) { recode_stream->srcwin_decided = 1; recode_stream->src = &recode_source; recode_source.srclen = (usize_t)(window_srcmax - window_srcmin); recode_source.srcbase = window_srcmin; recode_stream->taroff = recode_source.srclen; XD3_ASSERT (recode_source.srclen != 0); } else { recode_stream->srcwin_decided = 0; recode_stream->src = NULL; recode_stream->taroff = 0; } for (;;) { switch ((ret = xd3_encode_input (recode_stream))) { case XD3_INPUT: { goto done_window; } case XD3_OUTPUT: { /* main_file_write below */ break; } case XD3_GOTHEADER: case XD3_WINSTART: case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: case 0: { return XD3_INTERNAL; } default: return ret; } if ((ret = main_write_output(recode_stream, ofile))) { return ret; } xd3_consume_output (recode_stream); } done_window: (void) 0; } return 0; } #endif /******************************************************************* Input decompression, output recompression ******************************************************************/ #if EXTERNAL_COMPRESSION /* This is tricky POSIX-specific code with lots of fork(), pipe(), * dup(), waitpid(), and exec() business. Most of this code * originated in PRCS1, which did automatic package-file * decompression. It works with both XD3_POSIX and XD3_STDIO file * disciplines. * * To automatically detect compressed inputs requires a child process * to reconstruct the input stream, which was advanced in order to * detect compression, because it may not be seekable. In other * words, the main program reads part of the input stream, and if it * detects a compressed input it then forks a pipe copier process, * which copies the first-read block out of the main-program's memory, * then streams the remaining compressed input into the * input-decompression pipe. */ #include #include #include #include /* Remember which pipe FD is which. */ #define PIPE_READ_FD 0 #define PIPE_WRITE_FD 1 #define MAX_SUBPROCS 4 /* max(source + copier + output, source + copier + input + copier). */ static pid_t ext_subprocs[MAX_SUBPROCS]; /* Like write(), applies to a fd instead of a main_file, for the pipe * copier subprocess. Does not print an error, to facilitate ignoring * trailing garbage, see main_pipe_copier(). */ static int main_pipe_write (int outfd, uint8_t *exist_buf, usize_t remain) { int ret; if ((ret = xd3_posix_io (outfd, exist_buf, remain, (xd3_posix_func*) &write, NULL))) { return ret; } return 0; } /* A simple error-reporting waitpid interface. */ static int main_waitpid_check(pid_t pid) { int status; int ret = 0; if (waitpid (pid, & status, 0) < 0) { ret = get_errno (); XPR(NT "external compression [pid %d] wait: %s\n", pid, xd3_mainerror (ret)); } else if (! WIFEXITED (status)) { // SIGPIPE will be delivered to the child process whenever it // writes data after this process closes the pipe, // happens if xdelta does not require access to the entire // source file. Considered normal. if (! WIFSIGNALED (status) || WTERMSIG (status) != SIGPIPE) { ret = ECHILD; XPR(NT "external compression [pid %d] signal %d\n", pid, WIFSIGNALED (status) ? WTERMSIG (status) : WSTOPSIG (status)); } else if (option_verbose) { XPR(NT "external compression sigpipe\n"); } } else if (WEXITSTATUS (status) != 0) { ret = ECHILD; if (option_verbose > 1) { /* Presumably, the error was printed by the subprocess. */ XPR(NT "external compression [pid %d] exit %d\n", pid, WEXITSTATUS (status)); } } return ret; } /* Wait for any existing child processes to check for abnormal exit. */ static int main_external_compression_finish (void) { int i; int ret; for (i = 0; i < num_subprocs; i += 1) { if (! ext_subprocs[i]) { continue; } if ((ret = main_waitpid_check (ext_subprocs[i]))) { return ret; } ext_subprocs[i] = 0; } return 0; } /* Kills any outstanding compression process. */ static void main_external_compression_cleanup (void) { int i; for (i = 0; i < num_subprocs; i += 1) { if (! ext_subprocs[i]) { continue; } kill (ext_subprocs[i], SIGTERM); ext_subprocs[i] = 0; } } /* This runs as a forked process of main_input_decompress_setup() to * copy input to the decompression process. First, the available * input is copied out of the existing buffer, then the buffer is * reused to continue reading from the compressed input file. */ static int main_pipe_copier (uint8_t *pipe_buf, usize_t pipe_bufsize, size_t nread, main_file *ifile, int outfd) { int ret; xoff_t skipped = 0; /* Prevent SIGPIPE signals, allow EPIPE return values instead. This * is safe to comment-out, except that the -F flag will not work * properly (the parent would need to treat WTERMSIG(status) == * SIGPIPE). */ struct sigaction sa; sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); for (;;) { /* force_drain will be set when option_force and EPIPE cause us * to skip data. This is reset each time through the loop, so * the break condition below works. */ int force_drain = 0; if (nread > 0 && (ret = main_pipe_write (outfd, pipe_buf, nread))) { if (ret == EPIPE) { /* This causes the loop to continue reading until nread * == 0. */ skipped += nread; force_drain = 1; } else { XPR(NT "pipe write failed: %s\n", xd3_mainerror (ret)); return ret; } } if (nread < pipe_bufsize && !force_drain) { break; } if ((ret = main_file_read (ifile, pipe_buf, pipe_bufsize, & nread, "pipe read failed")) < 0) { return ret; } } if (option_verbose && skipped != 0) { XPR(NT "skipping %"Q"u bytes in %s\n", skipped, ifile->filename); } return 0; } /* This function is called after we have read some amount of data from * the input file and detected a compressed input. Here we start a * decompression subprocess by forking twice. The first process runs * the decompression command, the second process copies data to the * input of the first. */ static int main_input_decompress_setup (const main_extcomp *decomp, main_file *ifile, uint8_t *input_buf, usize_t input_bufsize, uint8_t *pipe_buf, usize_t pipe_bufsize, usize_t pipe_avail, size_t *nread) { /* The two pipes: input and output file descriptors. */ int outpipefd[2], inpipefd[2]; int input_fd = -1; /* The resulting input_fd (output of decompression). */ pid_t decomp_id, copier_id; /* The two subprocs. */ int ret; outpipefd[0] = outpipefd[1] = -1; inpipefd[0] = inpipefd[1] = -1; if (pipe (outpipefd) || pipe (inpipefd)) { XPR(NT "pipe failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } if ((decomp_id = fork ()) < 0) { XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } /* The first child runs the decompression process: */ if (decomp_id == 0) { if (option_verbose > 2) { XPR(NT "external decompression pid %d\n", getpid ()); } /* Setup pipes: write to the outpipe, read from the inpipe. */ if (dup2 (outpipefd[PIPE_WRITE_FD], STDOUT_FILENO) < 0 || dup2 (inpipefd[PIPE_READ_FD], STDIN_FILENO) < 0 || close (outpipefd[PIPE_READ_FD]) || close (outpipefd[PIPE_WRITE_FD]) || close (inpipefd[PIPE_READ_FD]) || close (inpipefd[PIPE_WRITE_FD]) || execlp (decomp->decomp_cmdname, decomp->decomp_cmdname, decomp->decomp_options, option_force2 ? "-f" : NULL, NULL)) { XPR(NT "child process %s failed to execute: %s\n", decomp->decomp_cmdname, xd3_mainerror (get_errno ())); } _exit (127); } XD3_ASSERT(num_subprocs < MAX_SUBPROCS); ext_subprocs[num_subprocs++] = decomp_id; if ((copier_id = fork ()) < 0) { XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } /* The second child runs the copier process: */ if (copier_id == 0) { int exitval = 0; if (option_verbose > 2) { XPR(NT "child pipe-copier pid %d\n", getpid ()); } if (close (inpipefd[PIPE_READ_FD]) || close (outpipefd[PIPE_READ_FD]) || close (outpipefd[PIPE_WRITE_FD]) || main_pipe_copier (pipe_buf, pipe_bufsize, pipe_avail, ifile, inpipefd[PIPE_WRITE_FD]) || close (inpipefd[PIPE_WRITE_FD])) { XPR(NT "child copier process failed: %s\n", xd3_mainerror (get_errno ())); exitval = 1; } _exit (exitval); } XD3_ASSERT(num_subprocs < MAX_SUBPROCS); ext_subprocs[num_subprocs++] = copier_id; /* The parent closes both pipes after duplicating the output of * compression. */ input_fd = dup (outpipefd[PIPE_READ_FD]); if (input_fd < 0 || main_file_close (ifile) || close (outpipefd[PIPE_READ_FD]) || close (outpipefd[PIPE_WRITE_FD]) || close (inpipefd[PIPE_READ_FD]) || close (inpipefd[PIPE_WRITE_FD])) { XPR(NT "dup/close failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } #if XD3_STDIO /* Note: fdopen() acquires the fd, closes it when finished. */ if ((ifile->file = fdopen (input_fd, "r")) == NULL) { XPR(NT "fdopen failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } #elif XD3_POSIX ifile->file = input_fd; #endif ifile->compressor = decomp; /* Now the input file is decompressed. */ return main_file_read (ifile, input_buf, input_bufsize, nread, "input decompression failed"); pipe_cleanup: close (input_fd); close (outpipefd[PIPE_READ_FD]); close (outpipefd[PIPE_WRITE_FD]); close (inpipefd[PIPE_READ_FD]); close (inpipefd[PIPE_WRITE_FD]); return ret; } /* This routine is called when the first buffer of input data is read * by the main program (unless input decompression is disabled by * command-line option). If it recognizes the magic number of a known * input type it invokes decompression. * * Skips decompression if the decompression type or the file type is * RD_NONEXTERNAL. * * Behaves exactly like main_file_read, otherwise. * * This function uses a separate buffer to read the first small block * of input. If a compressed input is detected, the separate buffer * is passed to the pipe copier. This avoids using the same size * buffer in both cases. */ static int main_secondary_decompress_check (main_file *file, uint8_t *input_buf, size_t input_size, size_t *nread) { int ret; usize_t i; usize_t try_read = min (input_size, XD3_ALLOCSIZE); size_t check_nread = 0; uint8_t check_buf[XD3_ALLOCSIZE]; /* TODO: stack limit */ const main_extcomp *decompressor = NULL; if ((ret = main_file_read (file, check_buf, try_read, & check_nread, "input read failed"))) { return ret; } if (file->flags & RD_DECOMPSET) { /* This allows the application header to override the magic * number, for whatever reason. */ decompressor = file->compressor; } else { for (i = 0; i < SIZEOF_ARRAY (extcomp_types); i += 1) { const main_extcomp *decomp = & extcomp_types[i]; if (check_nread > decomp->magic_size) { /* The following expr checks if we are trying to read a * VCDIFF input, in which case do not treat it as * "secondary" decompression. */ int skip_this_type = (decomp->flags & RD_NONEXTERNAL) && (file->flags & RD_NONEXTERNAL); if (skip_this_type) { continue; } if (memcmp (check_buf, decomp->magic, decomp->magic_size) == 0) { decompressor = decomp; break; } } } } if (decompressor != NULL) { if (! option_quiet) { XPR(NT "externally compressed input: %s %s%s < %s\n", decompressor->decomp_cmdname, decompressor->decomp_options, (option_force2 ? " -f" : ""), file->filename); if (file->flags & RD_MAININPUT) { XPR(NT "WARNING: the encoder is automatically decompressing the input file;\n"); XPR(NT "WARNING: the decoder will automatically recompress the output file;\n"); XPR(NT "WARNING: this may result in different compressed data and checksums\n"); XPR(NT "WARNING: despite being identical data; if this is an issue, use -D\n"); XPR(NT "WARNING: to avoid decompression and/or use -R to avoid recompression\n"); XPR(NT "WARNING: and/or manually decompress the input file; if you know the\n"); XPR(NT "WARNING: compression settings that will produce identical output\n"); XPR(NT "WARNING: you may set those flags using the environment (e.g., GZIP=-9)\n"); } } file->size_known = 0; return main_input_decompress_setup (decompressor, file, input_buf, input_size, check_buf, XD3_ALLOCSIZE, check_nread, nread); } /* Now read the rest of the input block. */ (*nread) = 0; if (check_nread == try_read) { ret = main_file_read (file, input_buf + try_read, input_size - try_read, nread, "input read failed"); } memcpy (input_buf, check_buf, check_nread); (*nread) += check_nread; return 0; } /* Initiate re-compression of the output stream. This is easier than * input decompression because we know beforehand that the stream will * be compressed, whereas the input has already been read when we * decide it should be decompressed. Thus, it only requires one * subprocess and one pipe. */ static int main_recompress_output (main_file *ofile) { pid_t recomp_id; /* One subproc. */ int pipefd[2]; /* One pipe. */ int output_fd = -1; int ret; const main_extcomp *recomp = ofile->compressor; pipefd[0] = pipefd[1] = -1; if (pipe (pipefd)) { XPR(NT "pipe failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } if ((recomp_id = fork ()) < 0) { XPR(NT "fork failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } /* The child runs the recompression process: */ if (recomp_id == 0) { if (option_verbose > 2) { XPR(NT "external recompression pid %d\n", getpid ()); } /* Setup pipes: write to the output file, read from the pipe. */ if (dup2 (XFNO (ofile), STDOUT_FILENO) < 0 || dup2 (pipefd[PIPE_READ_FD], STDIN_FILENO) < 0 || close (pipefd[PIPE_READ_FD]) || close (pipefd[PIPE_WRITE_FD]) || execlp (recomp->recomp_cmdname, recomp->recomp_cmdname, recomp->recomp_options, option_force2 ? "-f" : NULL, NULL)) { XPR(NT "child process %s failed to execute: %s\n", recomp->recomp_cmdname, xd3_mainerror (get_errno ())); } _exit (127); } XD3_ASSERT(num_subprocs < MAX_SUBPROCS); ext_subprocs[num_subprocs++] = recomp_id; /* The parent closes both pipes after duplicating the output-fd for * writing to the compression pipe. */ output_fd = dup (pipefd[PIPE_WRITE_FD]); if (output_fd < 0 || main_file_close (ofile) || close (pipefd[PIPE_READ_FD]) || close (pipefd[PIPE_WRITE_FD])) { XPR(NT "close failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } #if XD3_STDIO /* Note: fdopen() acquires the fd, closes it when finished. */ if ((ofile->file = fdopen (output_fd, "w")) == NULL) { XPR(NT "fdopen failed: %s\n", xd3_mainerror (ret = get_errno ())); goto pipe_cleanup; } #elif XD3_POSIX ofile->file = output_fd; #endif /* Now the output file will be compressed. */ return 0; pipe_cleanup: close (output_fd); close (pipefd[PIPE_READ_FD]); close (pipefd[PIPE_WRITE_FD]); return ret; } #endif /* EXTERNAL_COMPRESSION */ /* Identify the compressor that was used based on its ident string, * which is passed in the application header. */ static const main_extcomp* main_ident_compressor (const char *ident) { usize_t i; for (i = 0; i < SIZEOF_ARRAY (extcomp_types); i += 1) { if (strcmp (extcomp_types[i].ident, ident) == 0) { return & extcomp_types[i]; } } return NULL; } /* Return the main_extcomp record to use for this identifier, if possible. */ static const main_extcomp* main_get_compressor (const char *ident) { const main_extcomp *ext = main_ident_compressor (ident); if (ext == NULL) { if (! option_quiet) { XPR(NT "warning: cannot recompress output: " "unrecognized external compression ID: %s\n", ident); } return NULL; } else if (! EXTERNAL_COMPRESSION) { if (! option_quiet) { XPR(NT "warning: external support not compiled: " "original input was compressed: %s\n", ext->recomp_cmdname); } return NULL; } else { return ext; } } /********************************************************************* APPLICATION HEADER *******************************************************************/ #if XD3_ENCODER static const char* main_apphead_string (const char* x) { const char *y; if (x == NULL) { return ""; } if (strcmp (x, "/dev/stdin") == 0 || strcmp (x, "/dev/stdout") == 0 || strcmp (x, "/dev/stderr") == 0) { return "-"; } // TODO: this is not portable return (y = strrchr (x, '/')) == NULL ? x : y + 1; } static int main_set_appheader (xd3_stream *stream, main_file *input, main_file *sfile) { /* The user may disable the application header. Once the appheader * is set, this disables setting it again. */ if (appheader_used || ! option_use_appheader) { return 0; } /* The user may specify the application header, otherwise format the default header. */ if (option_appheader) { appheader_used = option_appheader; } else { const char *iname; const char *icomp; const char *sname; const char *scomp; usize_t len; iname = main_apphead_string (input->filename); icomp = (input->compressor == NULL) ? "" : input->compressor->ident; len = (usize_t) strlen (iname) + (usize_t) strlen (icomp) + 2; if (sfile->filename != NULL) { sname = main_apphead_string (sfile->filename); scomp = (sfile->compressor == NULL) ? "" : sfile->compressor->ident; len += (usize_t) strlen (sname) + (usize_t) strlen (scomp) + 2; } else { sname = scomp = ""; } if ((appheader_used = (uint8_t*) main_malloc (len)) == NULL) { return ENOMEM; } if (sfile->filename == NULL) { snprintf_func ((char*)appheader_used, len, "%s/%s", iname, icomp); } else { snprintf_func ((char*)appheader_used, len, "%s/%s/%s/%s", iname, icomp, sname, scomp); } } xd3_set_appheader (stream, appheader_used, (usize_t) strlen ((char*)appheader_used)); return 0; } #endif static void main_get_appheader_params (main_file *file, char **parsed, int output, const char *type, main_file *other) { /* Set the filename if it was not specified. If output, option_stdout (-c) * overrides. */ if (file->filename == NULL && ! (output && option_stdout) && strcmp (parsed[0], "-") != 0) { file->filename = parsed[0]; if (other->filename != NULL) { /* Take directory from the other file, if it has one. */ /* TODO: This results in nonsense names like /dev/foo.tar.gz * and probably the filename-default logic interferes with * multi-file operation and the standard file extension? * Possibly the name header is bad, should be off by default. * Possibly we just want to remember external/compression * settings. */ const char *last_slash = strrchr(other->filename, '/'); if (last_slash != NULL) { usize_t dlen = (usize_t) (last_slash - other->filename); XD3_ASSERT(file->filename_copy == NULL); file->filename_copy = (char*) main_malloc(dlen + 2 + (usize_t) strlen(file->filename)); strncpy(file->filename_copy, other->filename, dlen); file->filename_copy[dlen] = '/'; strcpy(file->filename_copy + dlen + 1, parsed[0]); file->filename = file->filename_copy; } } if (! option_quiet) { XPR(NT "using default %s filename: %s\n", type, file->filename); } } /* Set the compressor, initiate de/recompression later. */ if (file->compressor == NULL && *parsed[1] != 0) { file->flags |= RD_DECOMPSET; file->compressor = main_get_compressor (parsed[1]); } } static void main_get_appheader (xd3_stream *stream, main_file *ifile, main_file *output, main_file *sfile) { uint8_t *apphead; usize_t appheadsz; int ret; /* The user may disable the application header. Once the appheader * is set, this disables setting it again. */ if (! option_use_appheader) { return; } ret = xd3_get_appheader (stream, & apphead, & appheadsz); /* Ignore failure, it only means we haven't received a header yet. */ if (ret != 0) { return; } if (appheadsz > 0) { char *start = (char*)apphead; char *slash; int place = 0; char *parsed[4]; memset (parsed, 0, sizeof (parsed)); while ((slash = strchr (start, '/')) != NULL) { *slash = 0; parsed[place++] = start; start = slash + 1; } parsed[place++] = start; /* First take the output parameters. */ if (place == 2 || place == 4) { main_get_appheader_params (output, parsed, 1, "output", ifile); } /* Then take the source parameters. */ if (place == 4) { main_get_appheader_params (sfile, parsed+2, 0, "source", ifile); } } option_use_appheader = 0; return; } /********************************************************************* Main I/O routines **********************************************************************/ /* This function acts like the above except it may also try to * recognize a compressed input (source or target) when the first * buffer of data is read. The EXTERNAL_COMPRESSION code is called to * search for magic numbers. */ static int main_read_primary_input (main_file *file, uint8_t *buf, size_t size, size_t *nread) { #if EXTERNAL_COMPRESSION if (option_decompress_inputs && file->flags & RD_FIRST) { file->flags &= ~RD_FIRST; return main_secondary_decompress_check (file, buf, size, nread); } #endif return main_file_read (file, buf, size, nread, "input read failed"); } /* Open the main output file, sets a default file name, initiate * recompression. This function is expected to fprint any error * messages. */ static int main_open_output (xd3_stream *stream, main_file *ofile) { int ret; if (option_no_output) { return 0; } if (ofile->filename == NULL) { XSTDOUT_XF (ofile); if (option_verbose > 1) { XPR(NT "using standard output: %s\n", ofile->filename); } } else { /* Stat the file to check for overwrite. */ if (option_force == 0 && main_file_exists (ofile)) { if (!option_quiet) { XPR(NT "to overwrite output file specify -f: %s\n", ofile->filename); } return EEXIST; } if ((ret = main_file_open (ofile, ofile->filename, XO_WRITE))) { return ret; } if (option_verbose > 1) { XPR(NT "output %s\n", ofile->filename); } } #if EXTERNAL_COMPRESSION /* Do output recompression. */ if (ofile->compressor != NULL && option_recompress_outputs == 1) { if (! option_quiet) { XPR(NT "externally compressed output: %s %s%s > %s\n", ofile->compressor->recomp_cmdname, ofile->compressor->recomp_options, (option_force2 ? " -f" : ""), ofile->filename); } if ((ret = main_recompress_output (ofile))) { return ret; } } #endif return 0; } static usize_t main_get_winsize (main_file *ifile) { xoff_t file_size = 0; usize_t size = option_winsize; static shortbuf iszbuf; if (main_file_stat (ifile, &file_size) == 0) { size = (usize_t) min(file_size, (xoff_t) size); } size = max(size, XD3_ALLOCSIZE); if (option_verbose > 1) { XPR(NT "input %s window size %s\n", ifile->filename, main_format_bcnt (size, &iszbuf)); } return size; } /********************************************************************* Main routines ********************************************************************/ /* This is a generic input function. It calls the xd3_encode_input or * xd3_decode_input functions and makes calls to the various input * handling routines above, which coordinate external decompression. */ static int main_input (xd3_cmd cmd, main_file *ifile, main_file *ofile, main_file *sfile) { int ret; xd3_stream stream; size_t nread = 0; usize_t winsize; int stream_flags = 0; xd3_config config; xd3_source source; xoff_t last_total_in = 0; xoff_t last_total_out = 0; long start_time; int stdout_only = 0; int (*input_func) (xd3_stream*); int (*output_func) (xd3_stream*, main_file *); memset (& stream, 0, sizeof (stream)); memset (& source, 0, sizeof (source)); memset (& config, 0, sizeof (config)); config.alloc = main_alloc; config.freef = main_free1; config.iopt_size = option_iopt_size; config.sprevsz = option_sprevsz; do_src_fifo = 0; start_time = get_millisecs_now (); if (option_use_checksum) { stream_flags |= XD3_ADLER32; } /* main_input setup. */ switch ((int) cmd) { #if VCDIFF_TOOLS if (1) { case CMD_PRINTHDR: stream_flags |= XD3_JUST_HDR; } else if (1) { case CMD_PRINTHDRS: stream_flags |= XD3_SKIP_WINDOW; } else { case CMD_PRINTDELTA: stream_flags |= XD3_SKIP_EMIT; } ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; output_func = main_print_func; stream_flags |= XD3_ADLER32_NOVER; stdout_only = 1; break; case CMD_RECODE: case CMD_MERGE: case CMD_MERGE_ARG: /* No source will be read */ stream_flags |= XD3_ADLER32_NOVER | XD3_SKIP_EMIT; ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; if ((ret = main_init_recode_stream ())) { return EXIT_FAILURE; } if (cmd == CMD_RECODE) { output_func = main_recode_func; } else { output_func = main_merge_func; } break; #endif /* VCDIFF_TOOLS */ #if XD3_ENCODER case CMD_ENCODE: do_src_fifo = 1; input_func = xd3_encode_input; output_func = main_write_output; if (option_no_compress) { stream_flags |= XD3_NOCOMPRESS; } if (option_use_altcodetable) { stream_flags |= XD3_ALT_CODE_TABLE; } if (option_smatch_config) { const char *s = option_smatch_config; char *e; int values[XD3_SOFTCFG_VARCNT]; int got; config.smatch_cfg = XD3_SMATCH_SOFT; for (got = 0; got < XD3_SOFTCFG_VARCNT; got += 1, s = e + 1) { values[got] = strtol (s, &e, 10); if ((values[got] < 0) || (e == s) || (got < XD3_SOFTCFG_VARCNT-1 && *e == 0) || (got == XD3_SOFTCFG_VARCNT-1 && *e != 0)) { XPR(NT "invalid string match specifier (-C) %d: %s\n", got, s); return EXIT_FAILURE; } } config.smatcher_soft.large_look = values[0]; config.smatcher_soft.large_step = values[1]; config.smatcher_soft.small_look = values[2]; config.smatcher_soft.small_chain = values[3]; config.smatcher_soft.small_lchain = values[4]; config.smatcher_soft.max_lazy = values[5]; config.smatcher_soft.long_enough = values[6]; } else { if (option_verbose > 2) { XPR(NT "compression level: %d\n", option_level); } if (option_level == 0) { stream_flags |= XD3_NOCOMPRESS; config.smatch_cfg = XD3_SMATCH_FASTEST; } else if (option_level == 1) { config.smatch_cfg = XD3_SMATCH_FASTEST; } else if (option_level == 2) { config.smatch_cfg = XD3_SMATCH_FASTER; } else if (option_level <= 5) { config.smatch_cfg = XD3_SMATCH_FAST; } else if (option_level == 6) { config.smatch_cfg = XD3_SMATCH_DEFAULT; } else { config.smatch_cfg = XD3_SMATCH_SLOW; } } break; #endif case CMD_DECODE: if (option_use_checksum == 0) { stream_flags |= XD3_ADLER32_NOVER; } ifile->flags |= RD_NONEXTERNAL; input_func = xd3_decode_input; output_func = main_write_output; break; default: XPR(NT "internal error\n"); return EXIT_FAILURE; } main_bsize = winsize = main_get_winsize (ifile); if ((main_bdata = (uint8_t*) main_bufalloc (winsize)) == NULL) { return EXIT_FAILURE; } config.winsize = winsize; config.getblk = main_getblk_func; config.flags = stream_flags; if ((ret = main_set_secondary_flags (&config)) || (ret = xd3_config_stream (& stream, & config))) { XPR(NT XD3_LIB_ERRMSG (& stream, ret)); return EXIT_FAILURE; } #if VCDIFF_TOOLS if ((cmd == CMD_MERGE || cmd == CMD_MERGE_ARG) && (ret = xd3_whole_state_init (& stream))) { XPR(NT XD3_LIB_ERRMSG (& stream, ret)); return EXIT_FAILURE; } #endif if (cmd != CMD_DECODE) { /* When not decoding, set source now. The decoder delays this * step until XD3_GOTHEADER. */ if (sfile && sfile->filename != NULL) { if ((ret = main_set_source (& stream, cmd, sfile, & source))) { return EXIT_FAILURE; } XD3_ASSERT(stream.src != NULL); } } if (cmd == CMD_PRINTHDR || cmd == CMD_PRINTHDRS || cmd == CMD_PRINTDELTA || cmd == CMD_RECODE) { if (sfile->filename == NULL) { allow_fake_source = 1; sfile->filename = ""; main_set_source (& stream, cmd, sfile, & source); } } /* This times each window. */ get_millisecs_since (); /* Main input loop. */ do { xoff_t input_offset; xoff_t input_remain; usize_t try_read; input_offset = ifile->nread; input_remain = XOFF_T_MAX - input_offset; try_read = (usize_t) min ((xoff_t) config.winsize, input_remain); if ((ret = main_read_primary_input (ifile, main_bdata, try_read, & nread))) { return EXIT_FAILURE; } /* If we've reached EOF tell the stream to flush. */ if (nread < try_read) { stream.flags |= XD3_FLUSH; } #if XD3_ENCODER /* After the first main_read_primary_input completes, we know * all the information needed to encode the application * header. */ if (cmd == CMD_ENCODE && (ret = main_set_appheader (& stream, ifile, sfile))) { return EXIT_FAILURE; } #endif xd3_avail_input (& stream, main_bdata, nread); /* If we read zero bytes after encoding at least one window... */ if (nread == 0 && stream.current_window > 0) { break; } again: ret = input_func (& stream); switch (ret) { case XD3_INPUT: continue; case XD3_GOTHEADER: { XD3_ASSERT (stream.current_window == 0); /* Need to process the appheader as soon as possible. It may * contain a suggested default filename/decompression routine for * the ofile, and it may contain default/decompression routine for * the sources. */ if (cmd == CMD_DECODE) { /* May need to set the sfile->filename if none was given. */ main_get_appheader (& stream, ifile, ofile, sfile); /* Now open the source file. */ if ((sfile->filename != NULL) && (ret = main_set_source (& stream, cmd, sfile, & source))) { return EXIT_FAILURE; } } } /* FALLTHROUGH */ case XD3_WINSTART: { /* e.g., set or unset XD3_SKIP_WINDOW. */ goto again; } case XD3_OUTPUT: { /* Defer opening the output file until the stream produces its * first output for both encoder and decoder, this way we * delay long enough for the decoder to receive the * application header. (Or longer if there are skipped * windows, but I can't think of any reason not to delay * open.) */ if (ofile != NULL && ! main_file_isopen (ofile) && (ret = main_open_output (& stream, ofile)) != 0) { return EXIT_FAILURE; } if ((ret = output_func (& stream, ofile)) && (ret != PRINTHDR_SPECIAL)) { return EXIT_FAILURE; } if (ret == PRINTHDR_SPECIAL) { xd3_abort_stream (& stream); ret = EXIT_SUCCESS; goto done; } ret = 0; xd3_consume_output (& stream); goto again; } case XD3_WINFINISH: { if (IS_ENCODE (cmd) || cmd == CMD_DECODE || cmd == CMD_RECODE) { if (! option_quiet && IS_ENCODE (cmd) && main_file_isopen (sfile)) { /* Warn when no source copies are found */ if (option_verbose && ! xd3_encoder_used_source (& stream)) { XPR(NT "warning: input window %"Q"u..%"Q"u has " "no source copies\n", stream.current_window * winsize, (stream.current_window+1) * winsize); XD3_ASSERT (stream.src != NULL); } /* Limited i-buffer size affects source copies * when the sourcewin is decided early. */ if (option_verbose > 1 && stream.srcwin_decided_early && stream.i_slots_used > stream.iopt_size) { XPR(NT "warning: input position %"Q"u overflowed " "instruction buffer, needed %u (vs. %u), " "consider changing -I\n", stream.current_window * winsize, stream.i_slots_used, stream.iopt_size); } } if (option_verbose) { shortbuf rrateavg, wrateavg, tm; shortbuf rdb, wdb; shortbuf trdb, twdb; shortbuf srcpos; long millis = get_millisecs_since (); usize_t this_read = (usize_t)(stream.total_in - last_total_in); usize_t this_write = (usize_t)(stream.total_out - last_total_out); last_total_in = stream.total_in; last_total_out = stream.total_out; if (option_verbose > 1) { XPR(NT "%"Q"u: in %s (%s): out %s (%s): " "total in %s: out %s: %s: srcpos %s\n", stream.current_window, main_format_bcnt (this_read, &rdb), main_format_rate (this_read, millis, &rrateavg), main_format_bcnt (this_write, &wdb), main_format_rate (this_write, millis, &wrateavg), main_format_bcnt (stream.total_in, &trdb), main_format_bcnt (stream.total_out, &twdb), main_format_millis (millis, &tm), main_format_bcnt (sfile->source_position, &srcpos)); } else { XPR(NT "%"Q"u: in %s: out %s: total in %s: " "out %s: %s\n", stream.current_window, main_format_bcnt (this_read, &rdb), main_format_bcnt (this_write, &wdb), main_format_bcnt (stream.total_in, &trdb), main_format_bcnt (stream.total_out, &twdb), main_format_millis (millis, &tm)); } } } goto again; } default: /* input_func() error */ XPR(NT XD3_LIB_ERRMSG (& stream, ret)); if (! option_quiet && ret == XD3_INVALID_INPUT) { XPR(NT "normally this indicates that the source file is incorrect\n"); XPR(NT "please verify the source file with sha1sum or equivalent\n"); } return EXIT_FAILURE; } } while (nread == config.winsize); done: /* Close the inputs. (ifile must be open, sfile may be open) */ main_file_close (ifile); if (sfile != NULL) { main_file_close (sfile); } #if VCDIFF_TOOLS if (cmd == CMD_MERGE && (ret = main_merge_output (& stream, ofile))) { return EXIT_FAILURE; } if (cmd == CMD_MERGE_ARG) { xd3_swap_whole_state (& stream.whole_target, & recode_stream->whole_target); } #endif /* VCDIFF_TOOLS */ /* If output file is not open yet because of delayed-open, it means * we never encountered a window in the delta, but it could have had * a VCDIFF header? TODO: solve this elsewhere. For now, it prints * "nothing to output" below, but the check doesn't happen in case * of option_no_output. */ if (! option_no_output && ofile != NULL) { if (!stdout_only && ! main_file_isopen (ofile)) { XPR(NT "nothing to output: %s\n", ifile->filename); return EXIT_FAILURE; } /* Have to close the output before calling * main_external_compression_finish, or else it hangs. */ if (main_file_close (ofile) != 0) { return EXIT_FAILURE; } } #if EXTERNAL_COMPRESSION if ((ret = main_external_compression_finish ())) { XPR(NT "external compression commands failed\n"); return EXIT_FAILURE; } #endif if ((ret = xd3_close_stream (& stream))) { XPR(NT XD3_LIB_ERRMSG (& stream, ret)); return EXIT_FAILURE; } #if XD3_ENCODER if (option_verbose > 1 && cmd == CMD_ENCODE) { XPR(NT "scanner configuration: %s\n", stream.smatcher.name); XPR(NT "target hash table size: %u\n", stream.small_hash.size); if (sfile != NULL && sfile->filename != NULL) { XPR(NT "source hash table size: %u\n", stream.large_hash.size); } } if (option_verbose > 2 && cmd == CMD_ENCODE) { XPR(NT "source copies: %"Q"u (%"Q"u bytes)\n", stream.n_scpy, stream.l_scpy); XPR(NT "target copies: %"Q"u (%"Q"u bytes)\n", stream.n_tcpy, stream.l_tcpy); XPR(NT "adds: %"Q"u (%"Q"u bytes)\n", stream.n_add, stream.l_add); XPR(NT "runs: %"Q"u (%"Q"u bytes)\n", stream.n_run, stream.l_run); } #endif xd3_free_stream (& stream); if (option_verbose) { shortbuf tm; long end_time = get_millisecs_now (); xoff_t nwrite = ofile != NULL ? ofile->nwrite : 0; XPR(NT "finished in %s; input %"Q"u output %"Q"u bytes (%0.2f%%)\n", main_format_millis (end_time - start_time, &tm), ifile->nread, nwrite, 100.0 * nwrite / ifile->nread); } return EXIT_SUCCESS; } /* free memory before exit, reset single-use variables. */ static void main_cleanup (void) { if (appheader_used != NULL && appheader_used != option_appheader) { main_free (appheader_used); appheader_used = NULL; } main_buffree (main_bdata); main_bdata = NULL; main_bsize = 0; main_lru_cleanup(); if (recode_stream != NULL) { xd3_free_stream (recode_stream); main_free (recode_stream); recode_stream = NULL; } if (merge_stream != NULL) { xd3_free_stream (merge_stream); main_free (merge_stream); merge_stream = NULL; } XD3_ASSERT (main_mallocs == 0); } static void setup_environment (int argc, char **argv, int *argc_out, char ***argv_out, char ***argv_free, char **env_free) { int n, i, i0; char *p, *v = getenv("XDELTA"); if (v == NULL) { (*argc_out) = argc; (*argv_out) = argv; (*argv_free) = NULL; (*env_free) = NULL; return; } (*env_free) = (char*) main_malloc((usize_t) strlen(v) + 1); strcpy(*env_free, v); /* Space needed for extra args, at least # of spaces */ n = argc + 1; for (p = *env_free; *p != 0; ) { if (*p++ == ' ') { n++; } } (*argv_free) = (char**) main_malloc(sizeof(char*) * (n + 1)); (*argv_out) = (*argv_free); (*argv_out)[0] = argv[0]; (*argv_out)[n] = NULL; i = 1; for (p = *env_free; *p != 0; ) { (*argv_out)[i++] = p; while (*p != ' ' && *p != 0) { p++; } while (*p == ' ') { *p++ = 0; } } for (i0 = 1; i0 < argc; i0++) { (*argv_out)[i++] = argv[i0]; } /* Counting spaces is an upper bound, argv stays NULL terminated. */ (*argc_out) = i; while (i <= n) { (*argv_out)[i++] = NULL; } } #if PYTHON_MODULE || SWIG_MODULE || NOT_MAIN int xd3_main_cmdline (int argc, char **argv) #else int main (int argc, char **argv) #endif { static const char *flags = "0123456789cdefhnqvDFJNORTVs:m:B:C:E:I:L:O:M:P:W:A::S::"; xd3_cmd cmd; main_file ifile; main_file ofile; main_file sfile; main_merge_list merge_order; main_merge *merge; int my_optind; const char *my_optarg; const char *my_optstr; const char *sfilename; int env_argc; char **env_argv; char **free_argv; /* malloc() in setup_environment() */ char *free_value; /* malloc() in setup_environment() */ int ret; #ifdef _WIN32 GetStartupInfo(&winStartupInfo); setvbuf(stderr, NULL, _IONBF, 0); /* Do not buffer stderr */ #endif main_file_init (& ifile); main_file_init (& ofile); main_file_init (& sfile); main_merge_list_init (& merge_order); reset_defaults(); free_argv = NULL; free_value = NULL; setup_environment(argc, argv, &env_argc, &env_argv, &free_argv, &free_value); cmd = CMD_NONE; sfilename = NULL; my_optind = 1; argv = env_argv; argc = env_argc; program_name = env_argv[0]; takearg: my_optarg = NULL; my_optstr = argv[my_optind]; /* This doesn't use getopt() because it makes trouble for -P & python which * reenter main() and thus care about freeing all memory. I never had much * trust for getopt anyway, it's too opaque. This implements a fairly * standard non-long-option getopt with support for named operations (e.g., * "xdelta3 [encode|decode|printhdr...] < in > out"). */ if (my_optstr) { if (*my_optstr == '-') { my_optstr += 1; } else if (cmd == CMD_NONE) { goto nonflag; } else { my_optstr = NULL; } } while (my_optstr) { const char *s; my_optarg = NULL; if ((ret = *my_optstr++) == 0) { my_optind += 1; goto takearg; } /* Option handling: first check for one ':' following the option in * flags, then check for two. The syntax allows: * * 1. -Afoo defines optarg="foo" * 2. -A foo defines optarg="foo" * 3. -A "" defines optarg="" (allows empty-string) * 4. -A [EOA or -moreargs] error (mandatory case) * 5. -A [EOA -moreargs] defines optarg=NULL (optional case) * 6. -A=foo defines optarg="foo" * 7. -A= defines optarg="" (mandatory case) * 8. -A= defines optarg=NULL (optional case) * * See tests in test_command_line_arguments(). */ s = strchr (flags, ret); if (s && s[1] && s[1] == ':') { int option = s[2] && s[2] == ':'; /* Case 1, set optarg to the remaining characters. */ my_optarg = my_optstr; my_optstr = ""; /* Case 2-5 */ if (*my_optarg == 0) { /* Condition 4-5 */ int have_arg = (my_optind < (argc - 1) && *argv[my_optind+1] != '-'); if (! have_arg) { if (! option) { /* Case 4 */ XPR(NT "-%c: requires an argument\n", ret); ret = EXIT_FAILURE; goto cleanup; } /* Case 5. */ my_optarg = NULL; } else { /* Case 2-3. */ my_optarg = argv[++my_optind]; } } /* Case 6-8. */ else if (*my_optarg == '=') { /* Remove the = in all cases. */ my_optarg += 1; if (option && *my_optarg == 0) { /* Case 8. */ my_optarg = NULL; } } } switch (ret) { /* case: if no '-' was found, maybe check for a command name. */ nonflag: if (strcmp (my_optstr, "decode") == 0) { cmd = CMD_DECODE; } else if (strcmp (my_optstr, "encode") == 0) { #if XD3_ENCODER cmd = CMD_ENCODE; #else XPR(NT "encoder support not compiled\n"); return EXIT_FAILURE; #endif } else if (strcmp (my_optstr, "config") == 0) { cmd = CMD_CONFIG; } #if REGRESSION_TEST else if (strcmp (my_optstr, "test") == 0) { cmd = CMD_TEST; } #endif #if VCDIFF_TOOLS else if (strcmp (my_optstr, "printhdr") == 0) { cmd = CMD_PRINTHDR; } else if (strcmp (my_optstr, "printhdrs") == 0) { cmd = CMD_PRINTHDRS; } else if (strcmp (my_optstr, "printdelta") == 0) { cmd = CMD_PRINTDELTA; } else if (strcmp (my_optstr, "recode") == 0) { cmd = CMD_RECODE; } else if (strcmp (my_optstr, "merge") == 0) { cmd = CMD_MERGE; } #endif /* If no option was found and still no command, let the default * command be encode. The remaining args are treated as * filenames. */ if (cmd == CMD_NONE) { cmd = CMD_DEFAULT; my_optstr = NULL; break; } else { /* But if we find a command name, continue the getopt loop. */ my_optind += 1; goto takearg; } /* gzip-like options */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': option_level = ret - '0'; break; case 'f': option_force = 1; break; case 'F': #if EXTERNAL_COMPRESSION option_force2 = 1; #else XPR(NT "warning: -F option ignored, " "external compression support was not compiled\n"); break; #endif case 'v': option_verbose += 1; option_quiet = 0; break; case 'q': option_quiet = 1; option_verbose = 0; break; case 'c': option_stdout = 1; break; case 'd': if (cmd == CMD_NONE) { cmd = CMD_DECODE; } else { ret = main_help (); goto exit; } break; case 'e': #if XD3_ENCODER if (cmd == CMD_NONE) { cmd = CMD_ENCODE; } else { ret = main_help (); goto exit; } break; #else XPR(NT "encoder support not compiled\n"); return EXIT_FAILURE; #endif case 'n': option_use_checksum = 0; break; case 'N': option_no_compress = 1; break; case 'T': option_use_altcodetable = 1; break; case 'C': option_smatch_config = my_optarg; break; case 'J': option_no_output = 1; break; case 'S': if (my_optarg == NULL) { option_use_secondary = 1; option_secondary = "none"; } else { option_use_secondary = 1; option_secondary = my_optarg; } break; case 'A': if (my_optarg == NULL) { option_use_appheader = 0; } else { option_appheader = (uint8_t*) my_optarg; } break; case 'B': { xoff_t bsize; if ((ret = main_atoux (my_optarg, & bsize, XD3_MINSRCWINSZ, XD3_MAXSRCWINSZ, 'B'))) { goto exit; } option_srcwinsz = bsize; break; } case 'I': if ((ret = main_atou (my_optarg, & option_iopt_size, 0, 0, 'I'))) { goto exit; } break; case 'P': if ((ret = main_atou (my_optarg, & option_sprevsz, 0, 0, 'P'))) { goto exit; } break; case 'W': if ((ret = main_atou (my_optarg, & option_winsize, XD3_ALLOCSIZE, XD3_HARDMAXWINSIZE, 'W'))) { goto exit; } break; case 'D': #if EXTERNAL_COMPRESSION == 0 if (option_verbose > 0) { XPR(NT "warning: -D option ignored, " "external compression support was not compiled\n"); } #else option_decompress_inputs = 0; #endif break; case 'R': #if EXTERNAL_COMPRESSION == 0 if (option_verbose > 0) { XPR(NT "warning: -R option ignored, " "external compression support was not compiled\n"); } #else option_recompress_outputs = 0; #endif break; case 's': if (sfilename != NULL) { XPR(NT "specify only one source file\n"); goto cleanup; } sfilename = my_optarg; break; case 'm': if ((merge = (main_merge*) main_malloc (sizeof (main_merge))) == NULL) { goto cleanup; } main_merge_list_push_back (& merge_order, merge); merge->filename = my_optarg; break; case 'V': ret = main_version (); goto exit; default: ret = main_help (); goto exit; } } option_source_filename = sfilename; /* In case there were no arguments, set the default command. */ if (cmd == CMD_NONE) { cmd = CMD_DEFAULT; } argc -= my_optind; argv += my_optind; /* There may be up to two more arguments. */ if (argc > 2) { XPR(NT "too many filenames: %s ...\n", argv[2]); goto cleanup; } ifile.flags = RD_FIRST | RD_MAININPUT; sfile.flags = RD_FIRST; sfile.filename = option_source_filename; /* The infile takes the next argument, if there is one. But if not, infile * is set to stdin. */ if (argc > 0) { ifile.filename = argv[0]; if ((ret = main_file_open (& ifile, ifile.filename, XO_READ))) { goto cleanup; } } else { XSTDIN_XF (& ifile); } /* The ofile takes the following argument, if there is one. But if not, it * is left NULL until the application header is processed. It will be set * in main_open_output. */ if (argc > 1) { /* Check for conflicting arguments. */ if (option_stdout && ! option_quiet) { XPR(NT "warning: -c option overrides output filename: %s\n", argv[1]); } if (! option_stdout) { ofile.filename = argv[1]; } } #if VCDIFF_TOOLS if (cmd == CMD_MERGE && (ret = main_merge_arguments (&merge_order))) { goto cleanup; } #endif /* VCDIFF_TOOLS */ switch (cmd) { case CMD_PRINTHDR: case CMD_PRINTHDRS: case CMD_PRINTDELTA: #if XD3_ENCODER case CMD_ENCODE: case CMD_RECODE: case CMD_MERGE: #endif case CMD_DECODE: ret = main_input (cmd, & ifile, & ofile, & sfile); break; #if REGRESSION_TEST case CMD_TEST: main_config (); ret = xd3_selftest (); break; #endif case CMD_CONFIG: ret = main_config (); break; default: ret = main_help (); break; } if (0) { cleanup: ret = EXIT_FAILURE; exit: (void)0; } #if EXTERNAL_COMPRESSION main_external_compression_cleanup (); #endif main_file_cleanup (& ifile); main_file_cleanup (& ofile); main_file_cleanup (& sfile); while (! main_merge_list_empty (& merge_order)) { merge = main_merge_list_pop_front (& merge_order); main_free (merge); } main_free (free_argv); main_free (free_value); main_cleanup (); fflush (stdout); fflush (stderr); return ret; } static int main_help (void) { main_version(); /* Note: update wiki when command-line features change */ XPR(NTR "usage: xdelta3 [command/options] [input [output]]\n"); XPR(NTR "make patch:\n"); XPR(NTR "\n"); XPR(NTR " xdelta3.exe -e -s old_file new_file delta_file\n"); XPR(NTR "\n"); XPR(NTR "apply patch:\n"); XPR(NTR "\n"); XPR(NTR " xdelta3.exe -d -s old_file delta_file decoded_new_file\n"); XPR(NTR "\n"); XPR(NTR "special command names:\n"); XPR(NTR " config prints xdelta3 configuration\n"); XPR(NTR " decode decompress the input\n"); XPR(NTR " encode compress the input%s\n", XD3_ENCODER ? "" : " [Not compiled]"); #if REGRESSION_TEST XPR(NTR " test run the builtin tests\n"); #endif #if VCDIFF_TOOLS XPR(NTR "special commands for VCDIFF inputs:\n"); XPR(NTR " printdelta print information about the entire delta\n"); XPR(NTR " printhdr print information about the first window\n"); XPR(NTR " printhdrs print information about all windows\n"); XPR(NTR " recode encode with new application/secondary settings\n"); XPR(NTR " merge merge VCDIFF inputs (see below)\n"); #endif XPR(NTR "merge patches:\n"); XPR(NTR "\n"); XPR(NTR " xdelta3 merge -m 1.vcdiff -m 2.vcdiff 3.vcdiff merged.vcdiff\n"); XPR(NTR "\n"); XPR(NTR "standard options:\n"); XPR(NTR " -0 .. -9 compression level\n"); XPR(NTR " -c use stdout\n"); XPR(NTR " -d decompress\n"); XPR(NTR " -e compress%s\n", XD3_ENCODER ? "" : " [Not compiled]"); XPR(NTR " -f force (overwrite, ignore trailing garbage)\n"); #if EXTERNAL_COMPRESSION XPR(NTR " -F force the external-compression subprocess\n"); #endif XPR(NTR " -h show help\n"); XPR(NTR " -q be quiet\n"); XPR(NTR " -v be verbose (max 2)\n"); XPR(NTR " -V show version\n"); XPR(NTR "memory options:\n"); XPR(NTR " -B bytes source window size\n"); XPR(NTR " -W bytes input window size\n"); XPR(NTR " -P size compression duplicates window\n"); XPR(NTR " -I size instruction buffer size (0 = unlimited)\n"); XPR(NTR "compression options:\n"); XPR(NTR " -s source source file to copy from (if any)\n"); XPR(NTR " -S [djw|fgk] enable/disable secondary compression\n"); XPR(NTR " -N disable small string-matching compression\n"); XPR(NTR " -D disable external decompression (encode/decode)\n"); XPR(NTR " -R disable external recompression (decode)\n"); XPR(NTR " -n disable checksum (encode/decode)\n"); XPR(NTR " -C soft config (encode, undocumented)\n"); XPR(NTR " -A [apphead] disable/provide application header (encode)\n"); XPR(NTR " -J disable output (check/compute only)\n"); XPR(NTR " -T use alternate code table (test)\n"); XPR(NTR " -m arguments for \"merge\"\n"); XPR(NTR "the XDELTA environment variable may contain extra args:\n"); XPR(NTR " XDELTA=\"-s source-x.y.tar.gz\" \\\n"); XPR(NTR " tar --use-compress-program=xdelta3 \\\n"); XPR(NTR " -cf target-x.z.tar.gz.vcdiff target-x.y\n"); return EXIT_FAILURE; } xdelta3-3.0.7/xdelta3.i0000644000176500017650000000411512105354541014064 0ustar debdevdebdev%module xdelta3 %import cstring.i %import argcargv.i %{ #include "xdelta3.h" int xd3_main_cmdline (int ARGC, char **ARGV); %} %cstring_input_binary(const char *input, unsigned int input_size); %cstring_input_binary(const char *source, unsigned int source_size); %define %max_output_withsize(TYPEMAP, SIZE, MAXSIZE) %typemap(in) MAXSIZE (unsigned int alloc_size) { $1 = alloc_size = PyInt_AsLong(obj2); } %typemap(in,numinputs=0) (TYPEMAP, SIZE) { } %typemap(check) (TYPEMAP, SIZE) { // alloc_size input is #7th position in xd3_xxcode_memory() $1 = malloc(alloc_size7); $2 = &alloc_size7; } %typemap(argout,fragment="t_output_helper") (TYPEMAP, SIZE) { if (result == 0) { PyObject *o; // alloc_size7 now carries actual size o = PyString_FromStringAndSize($1,alloc_size7); $result = t_output_helper($result,o); } else { $result = t_output_helper($result,Py_None); } free($1); } %typemap(default) int flags { $1 = 0; } %enddef %max_output_withsize(char *output_buf, unsigned int *output_size, unsigned int max_output); int xd3_encode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buffer, usize_t *output_size, usize_t avail_output, int flags); int xd3_decode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buf, usize_t *output_size, usize_t avail_output, int flags); int xd3_main_cmdline (int ARGC, char **ARGV); /* Is this the right way? */ enum { /*XD3_JUST_HDR,*/ /*XD3_SKIP_WINDOW,*/ /*XD3_SKIP_EMIT,*/ /*XD3_FLUSH,*/ XD3_SEC_DJW, XD3_SEC_FGK, /*XD3_SEC_TYPE,*/ XD3_SEC_NODATA, XD3_SEC_NOINST, XD3_SEC_NOADDR, /*XD3_SEC_OTHER,*/ XD3_ADLER32, XD3_ADLER32_NOVER, XD3_ALT_CODE_TABLE, XD3_NOCOMPRESS, XD3_BEGREEDY, XD3_COMPLEVEL_SHIFT, XD3_COMPLEVEL_MASK, XD3_COMPLEVEL_1, XD3_COMPLEVEL_3, XD3_COMPLEVEL_6, XD3_COMPLEVEL_9, }; xdelta3-3.0.7/depcomp0000755000176500017650000005654612137373760013753 0ustar debdevdebdev#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2012-07-12.20; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # A tabulation character. tab=' ' # A newline character. nl=' ' if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' "$nl" < "$tmpdepfile" | ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependent.h'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. # However on # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\': # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... # tcc 0.9.26 (FIXME still under development at the moment of writing) # will emit a similar output, but also prepend the continuation lines # with horizontal tabulation characters. "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form 'foo.o: dependent.h', # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ < "$tmpdepfile" > "$depfile" sed ' s/[ '"$tab"'][ '"$tab"']*/ /g s/^ *// s/ *\\*$// s/^[^:]*: *// /^$/d /:$/d s/$/ :/ ' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'` tmpdepfile="$base.d" # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir="$base.d-lock" trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0 ; do # mkdir is a portable test-and-set. if mkdir $lockdir 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rm -rf $lockdir break else ## the lock is being held by a different process, ## wait until the winning process is done or we timeout while test -d $lockdir && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test "$stat" = 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' "$nl" < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: xdelta3-3.0.7/Makefile.orig0000644000176500017650000002112212105354541014742 0ustar debdevdebdev# xdelta 3 - delta compression tools and library # Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald UNAME = $(shell uname) CYGWIN = $(findstring CYGWIN, $(UNAME)) DARWIN = $(findstring Darwin, $(UNAME)) PYVER = 2.6 ifeq ("$(CYGWIN)", "") SWIGTGT = xdelta3module.so PYTGT = build/lib.macosx-10.6-universal-2.6/xdelta3main.so else SWIGTGT = xdelta3module.dll PYTGT = build/lib.cygwin-1.5.24-i686-$(PYVER)/xdelta3main.dll endif SOURCES = xdelta3-blkcache.h \ xdelta3-cfgs.h \ xdelta3-decode.h \ xdelta3-djw.h \ xdelta3-fgk.h \ xdelta3-hash.h \ xdelta3-list.h \ xdelta3-main.h \ xdelta3-merge.h \ xdelta3-python.h \ xdelta3-second.h \ xdelta3-test.h \ xdelta3.c \ xdelta3.h TARGETS = xdelta3-debug \ xdelta3-debug32 \ xdelta3-debug64 \ xdelta3 \ xdelta3-debug2 \ xdelta3-debugstdio \ xdelta3.o \ xdelta3_wrap.o \ xdelta3-32 \ xdelta3-64 \ xdelta3-everything \ xdelta3-Opg \ xdelta3-64-O \ xdelta3-Op \ xdelta3-decoder xdelta3-decoder-nomain.o \ xdelta3-nosec.o xdelta3-all.o xdelta3-fgk.o \ xdelta3-noext xdelta3-tools \ xdelta3-notools \ xdelta3_wrap.c xdelta3.py \ $(PYTGT) $(SWIGTGT) \ xdelta3-warnings PYTHON = python WIXDIR = "/cygdrive/c/Program Files/wix2.0.4820" CFLAGS= -Wall -Wshadow -fno-builtin WFLAGS= -Wextra -Wsign-compare -Wconversion -Wextra -Wno-unused-parameter # $Format: "REL=$Xdelta3Version$" $ REL=3.0.1 RELDIR = xdelta$(REL) EXTRA = Makefile COPYING linkxd3lib.c badcopy.c xdelta3.swig \ draft-korn-vcdiff.txt xdelta3.vcproj badcopy.vcproj \ testing/xdelta3-regtest.py xdelta3-test.py setup.py \ examples/Makefile examples/small_page_test.c \ examples/README examples/encode_decode_test.c \ examples/compare_test.c examples/speed_test.c \ examples/test.h examples/checksum_test.cc \ xdelta3.py xdelta3_wrap.c xdelta3.wxs xdelta3.wxi \ testing/cmp.h testing/delta.h testing/file.h \ testing/modify.h testing/random.h testing/segment.h \ testing/sizes.h testing/test.h testing/Makefile \ testing/regtest.cc README readme.txt xdelta3.1 SWIG_FLAGS = -DXD3_DEBUG=1 \ -DEXTERNAL_COMPRESSION=0 \ -DXD3_USE_LARGEFILE64=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DSECONDARY_DJW=1 \ -DVCDIFF_TOOLS=1 \ -DSWIG_MODULE=1 all: xdelta3-debug32 xdelta3-debug64 xdelta3-debug2 xdelta3 (cd testing && make) all-py: all $(PYTGT) $(SWIGTGT) all-targets: $(TARGETS) all-targets-test: all-targets test pytgt: $(PYTGT) swigtgt: $(SWIGTGT) test: ./xdelta3-debug test tar: tar --exclude ".svn" -czf /tmp/$(RELDIR)-tmp.tar.gz $(SOURCES) $(EXTRA) rm -rf /tmp/$(RELDIR) mkdir /tmp/$(RELDIR) (cd /tmp/$(RELDIR) && tar -xzf ../$(RELDIR)-tmp.tar.gz) tar -czf ./$(RELDIR).tar.gz -C /tmp $(RELDIR) +tar -tzf ./$(RELDIR).tar.gz rm -rf /tmp/$(RELDIR) zip: tar --exclude ".svn" -czf /tmp/$(RELDIR)-tmp.tar.gz $(SOURCES) $(EXTRA) rm -rf /tmp/$(RELDIR) mkdir /tmp/$(RELDIR) (cd /tmp/$(RELDIR) && tar -xzf ../$(RELDIR)-tmp.tar.gz) tar -czf ./$(RELDIR).tar.gz -C /tmp $(RELDIR) +zip -r $(RELDIR).zip /tmp/$(RELDIR) rm -rf /tmp/$(RELDIR) clean: rm -f $(TARGETS) rm -rf build Debug Release core cifs* *.stackdump *.exe *~ *.dSYM \ xdelta3.ncb xdelta3.suo xdelta3.sln xdelta3.wixobj xdelta3.msi wix: xdelta3.wxs xdelta3.wxi readme.txt Release\xdelta3.exe $(WIXDIR)/candle.exe xdelta3.wxs -out xdelta3.wixobj $(WIXDIR)/light.exe xdelta3.wixobj -out xdelta3.msi xdelta3: $(SOURCES) $(CC) $(CFLAGS) -O3 xdelta3.c -lm -o xdelta3 \ -DGENERIC_ENCODE_TABLES=0 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=0 \ -DXD3_MAIN=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-debug32: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -lm -o xdelta3-debug32 \ -arch i386 \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=1 \ -DXD3_MAIN=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-debug64: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -lm -o xdelta3-debug64 \ -arch x86_64 \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=1 \ -DXD3_MAIN=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-warnings: $(SOURCES) $(CC) -g $(CFLAGS) $(WFLAGS) xdelta3.c -lm -o xdelta3-warnings \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_DEBUG=1 \ -DXD3_MAIN=1 \ -DXD3_STDIO=1 \ -DXD3_USE_LARGEFILE64=1 xdelta3-32: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -lm -o xdelta3-32 \ -DXD3_DEBUG=1 \ -DXD3_USE_LARGEFILE64=0 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_MAIN=1 \ -DXD3_POSIX=1 xdelta3-debug2: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c -o xdelta3-debug2 \ -DXD3_DEBUG=2 \ -DXD3_MAIN=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -lm xdelta3-debugstdio: $(SOURCES) $(CC) -g $(CFLAGS) xdelta3.c -o xdelta3-debugstdio \ -DXD3_MAIN=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DXD3_USE_LARGEFILE64=1 \ -DXD3_STDIO=1 \ -DREGRESSION_TEST=1 \ -DXD3_DEBUG=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -lm $(PYTGT): $(SOURCES) setup.py $(PYTHON) setup.py install --verbose --compile --force xdelta3_wrap.c xdelta3.py: xdelta3.swig swig -python xdelta3.swig xdelta3.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c $(SWIG_FLAGS) -o xdelta3.o xdelta3_wrap.o: xdelta3_wrap.c $(CC) -O3 $(CFLAGS) $(SWIG_FLAGS) \ -DHAVE_CONFIG_H \ -I/usr/include/python$(PYVER) \ -I/usr/lib/python$(PYVER)/config \ -fpic \ -c xdelta3_wrap.c xdelta3module.dll: xdelta3_wrap.o xdelta3.o gcc -shared -Wl,--enable-auto-image-base \ xdelta3.o \ xdelta3_wrap.o \ -L/usr/lib/python$(PYVER)/config \ -lpython$(PYVER) \ -o xdelta3module.dll cp $(SWIGTGT) /usr/lib/python$(PYVER)/site-packages ifeq ("$(DARWIN)", "") xdelta3module.so: xdelta3_wrap.o xdelta3.o ld -shared xdelta3.o xdelta3_wrap.o \ -o xdelta3module.so \ /usr/lib/libpython$(PYVER).so \ -lc else xdelta3module.so: xdelta3_wrap.o xdelta3.o gcc-4.2 -Wl,-F. -bundle -undefined dynamic_lookup \ -arch x86_64 $(CFLAGS) \ xdelta3.o xdelta3_wrap.o -o xdelta3module.so cp xdelta3module.so /Library/Python/2.6/site-packages endif xdelta3-decoder: $(SOURCES) $(CC) -O3 -Wall -Wshadow xdelta3.c \ -DXD3_ENCODER=0 -DXD3_MAIN=1 -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 \ -DXD3_STDIO=1 -DEXTERNAL_COMPRESSION=0 -DVCDIFF_TOOLS=0 \ -o xdelta3-decoder xdelta3-decoder-nomain.o: $(SOURCES) linkxd3lib.c $(CC) -O3 -Wall -Wshadow xdelta3.c linkxd3lib.c \ -DXD3_ENCODER=0 -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 \ -o xdelta3-decoder-nomain.o strip xdelta3-decoder-nomain.o xdelta3-O++: $(SOURCES) $(CXX) -g -O3 $(CFLAGS) xdelta3.c \ -o xdelta3-O++ \ -DXD3_MAIN=1 \ -DSECONDARY_DJW=1 \ -DREGRESSION_TEST=1 \ -lm xdelta3-Op: $(SOURCES) $(CC) -g -O3 $(CFLAGS) xdelta3.c \ -o xdelta3-Op \ -DXD3_POSIX=1 \ -DXD3_MAIN=1 \ -DREGRESSION_TEST=1 \ -lm xdelta3-64: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c \ -o xdelta3-64 \ -DXD3_POSIX=1 \ -DXD3_MAIN=1 \ -DREGRESSION_TEST=1 \ -DXD3_DEBUG=0 \ -DXD3_USE_LARGEFILE64=1 \ -lm xdelta3-64-O: $(SOURCES) $(CC) -O3 $(CFLAGS) \ xdelta3.c \ -o xdelta3-64-O \ -DXD3_POSIX=1 \ -DXD3_MAIN=1 \ -DXD3_USE_LARGEFILE64=1 \ -lm xdelta3-everything: $(SOURCES) $(CC) -g $(CFLAGS) \ xdelta3.c \ -o xdelta3-everything \ -DXD3_MAIN=1 \ -DVCDIFF_TOOLS=1 \ -DREGRESSION_TEST=1 \ -DSECONDARY_FGK=1 \ -DSECONDARY_DJW=1 \ -DGENERIC_ENCODE_TABLES=1 \ -DGENERIC_ENCODE_TABLES_COMPUTE=1 \ -DXD3_POSIX=1 \ -DEXTERNAL_COMPRESSION=1 \ -DXD3_DEBUG=1 \ -lm xdelta3-Opg: $(SOURCES) $(CC) -pg -g -O3 $(CFLAGS) \ xdelta3.c \ -o xdelta3-Opg \ -DXD3_MAIN=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 \ -DREGRESSION_TEST=1 xdelta3-nosec.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 -o xdelta3-nosec.o xdelta3-all.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c -DSECONDARY_FGK=1 -DSECONDARY_DJW=1 -o xdelta3-all.o xdelta3-fgk.o: $(SOURCES) $(CC) -O3 $(CFLAGS) -c xdelta3.c -DSECONDARY_FGK=1 -DSECONDARY_DJW=0 -o xdelta3-fgk.o xdelta3-noext: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c -DXD3_MAIN=1 -DEXTERNAL_COMPRESSION=0 -o xdelta3-noext xdelta3-tools: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c -DXD3_MAIN=1 -o xdelta3-tools xdelta3-notools: $(SOURCES) $(CC) -O3 $(CFLAGS) xdelta3.c -DXD3_MAIN=1 -DVCDIFF_TOOLS=0 -o xdelta3-notools xdelta3-3.0.7/configure.ac0000644000176500017650000000146012144342414014633 0ustar debdevdebdevAC_INIT([Xdelta3], [3.0.7], [josh.macdonald@gmail.com], [xdelta3], [http://xdelta.org/]) AC_PREREQ([2.68]) AC_CONFIG_MACRO_DIR([m4]) #LT_INIT AM_INIT_AUTOMAKE([1.9 no-define foreign tar-ustar]) #AC_DISABLE_STATIC AX_CHECK_ALIGNED_ACCESS_REQUIRED AC_PROG_CC AC_PROG_CXX AC_CHECK_HEADERS([lzma.h]) AC_CHECK_LIB(lzma, lzma_easy_buffer_encode) AC_CHECK_SIZEOF(size_t) #AM_PATH_PYTHON(,, [:]) #AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) #AX_PYTHON_DEVEL() #AX_PKG_SWIG(2.0.0,,) #AX_SWIG_PYTHON dnl --enable-debug-symbols : build with debug symbols? AC_ARG_ENABLE(debug-symbols, AS_HELP_STRING(--enable-debug-symbols,[Build with debug symbols (default is NO)]),,enableval=no) AM_CONDITIONAL([DEBUG_SYMBOLS], [test ${enableval} = "yes"]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT xdelta3-3.0.7/missing0000755000176500017650000002415212105354541013750 0ustar debdevdebdev#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2012-01-06.13; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: xdelta3-3.0.7/INSTALL0000644000176500017650000003660512137373760013421 0ustar debdevdebdevInstallation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. xdelta3-3.0.7/Makefile.am0000644000176500017650000000760012143631316014404 0ustar debdevdebdevACLOCAL_AMFLAGS = -I m4 bin_PROGRAMS = xdelta3 noinst_PROGRAMS = xdelta3regtest xdelta3decode common_SOURCES = \ xdelta3-blkcache.h \ xdelta3-decode.h \ xdelta3-djw.h \ xdelta3-fgk.h \ xdelta3-hash.h \ xdelta3-internal.h \ xdelta3-list.h \ xdelta3-lzma.h \ xdelta3-main.h \ xdelta3-merge.h \ xdelta3-second.h \ xdelta3-test.h \ xdelta3-cfgs.h \ xdelta3.h xdelta3_SOURCES = $(common_SOURCES) xdelta3.c xdelta3decode_SOURCES = $(common_SOURCES) xdelta3.c xdelta3regtest_SOURCES = $(common_SOURCES) \ testing/cmp.h \ testing/delta.h \ testing/file.h \ testing/modify.h \ testing/random.h \ testing/regtest.cc \ testing/regtest_c.c \ testing/segment.h \ testing/sizes.h \ testing/test.h # Note: for extra sanity checks, enable -Wconversion. Note there # are a lot of false positives. WFLAGS = -Wall -Wshadow -fno-builtin -Wextra -Wsign-compare \ -Wextra -Wno-unused-parameter C_WFLAGS = $(WFLAGS) -pedantic -std=c99 CXX_WFLAGS = $(WFLAGS) common_CFLAGS = \ -DGENERIC_ENCODE_TABLES=0 \ -DREGRESSION_TEST=1 \ -DSECONDARY_DJW=1 \ -DSECONDARY_FGK=1 \ -DXD3_POSIX=1 \ -DXD3_USE_LARGEFILE64=1 \ -DXD3_MAIN=1 if DEBUG_SYMBOLS common_CFLAGS += -g endif # For additional debugging, add -DXD3_DEBUG=1, 2, 3, ... xdelta3_CFLAGS = $(C_WFLAGS) $(common_CFLAGS) -DXD3_DEBUG=0 xdelta3_LDADD = -lm xdelta3decode_CFLAGS = \ $(C_WFLAGS) \ -DGENERIC_ENCODE_TABLES=0 \ -DREGRESSION_TEST=0 \ -DSECONDARY_DJW=0 \ -DSECONDARY_FGK=0 \ -DSECONDARY_LZMA=0 \ -DXD3_USE_LARGEFILE64=1 \ -DXD3_MAIN=1 \ -DXD3_ENCODER=0 \ -DXD3_STDIO=1 \ -DEXTERNAL_COMPRESSION=0 \ -DVCDIFF_TOOLS=0 xdelta3regtest_CXXFLAGS = \ $(CXX_WFLAGS) $(common_CFLAGS) -DNOT_MAIN=1 -DXD3_DEBUG=1 xdelta3regtest_CFLAGS = \ $(C_WFLAGS) $(common_CFLAGS) -DNOT_MAIN=1 -DXD3_DEBUG=1 xdelta3regtest_LDADD = -lm man1_MANS = xdelta3.1 EXTRA_DIST = \ draft-korn-vcdiff.txt \ README \ examples/Makefile \ examples/README \ examples/checksum_test.cc \ examples/compare_test.c \ examples/encode_decode_test.c \ examples/small_page_test.c \ examples/speed_test.c \ examples/test.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test.xcodeproj/project.pbxproj \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.h \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/InfoPlist.strings \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPad.storyboard \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPhone.storyboard \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1_to_v2.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v2.bin \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/main.m \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Info.plist \ examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Prefix.pch \ Makefile.mingw \ Makefile.orig \ testing/xdelta3-regtest.py \ testing/xdelta3-test.py \ xdelta3.1 \ xdelta3.i \ xdelta3.vcxproj \ xdelta3.wxi \ xdelta3.wxs # Broken, removed from distribution: # xdelta3_pywrap.c # xdelta3.py #PYFILES = xdelta3_pywrap.c xdelta3.py #XDELTA3PY = xdelta3.py #XDELTA3PYLIB = xdelta3.la #BUILT_SOURCES = $(PYFILES) #xdelta3_pywrap.c xdelta3.py : xdelta3.i # $(SWIG) -python -o xdelta3_pywrap.c xdelta3.i # OS X for some reason requires: # pythondir = $(PYTHON_SITE_PKG) # pyexecdir = $(PYTHON_SITE_PKG) #python_PYTHON = $(XDELTA3PY) #pyexec_LTLIBRARIES = $(XDELTA3PYLIB) #_xdelta3_la_SOURCES = $(srcdir)/xdelta3_pywrap.c $(xdelta3_SOURCES) #_xdelta3_la_CFLAGS = $(common_CFLAGS) -DNOT_MAIN=1 $(PYTHON_CPPFLAGS) #_xdelta3_la_LDFLAGS = -module xdelta3-3.0.7/xdelta3-decode.h0000644000176500017650000007444412105354541015320 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XDELTA3_DECODE_H_ #define _XDELTA3_DECODE_H_ #include "xdelta3-internal.h" #define SRCORTGT(x) ((((x) & VCD_SRCORTGT) == VCD_SOURCE) ? \ VCD_SOURCE : ((((x) & VCD_SRCORTGT) == \ VCD_TARGET) ? VCD_TARGET : 0)) /* Initialize the decoder for a new window. The dec_tgtlen value is * preserved across successive window decodings, and the update to * dec_winstart is delayed until a new window actually starts. This * is to avoid throwing an error due to overflow until the last * possible moment. This makes it possible to encode exactly 4GB * through a 32-bit encoder. */ static int xd3_decode_init_window (xd3_stream *stream) { stream->dec_cpylen = 0; stream->dec_cpyoff = 0; stream->dec_cksumbytes = 0; xd3_init_cache (& stream->acache); return 0; } /* Allocates buffer space for the target window and possibly the * VCD_TARGET copy-window. Also sets the base of the two copy * segments. */ static int xd3_decode_setup_buffers (xd3_stream *stream) { /* If VCD_TARGET is set then the previous buffer may be reused. */ if (stream->dec_win_ind & VCD_TARGET) { /* But this implementation only supports copying from the last * target window. If the offset is outside that range, it can't * be done. */ if (stream->dec_cpyoff < stream->dec_laststart) { stream->msg = "unsupported VCD_TARGET offset"; return XD3_INVALID_INPUT; } /* See if the two windows are the same. This indicates the * first time VCD_TARGET is used. This causes a second buffer * to be allocated, after that the two are swapped in the * DEC_FINISH case. */ if (stream->dec_lastwin == stream->next_out) { stream->next_out = NULL; stream->space_out = 0; } // TODO: VCD_TARGET mode, this is broken stream->dec_cpyaddrbase = stream->dec_lastwin + (usize_t) (stream->dec_cpyoff - stream->dec_laststart); } /* See if the current output window is large enough. */ if (stream->space_out < stream->dec_tgtlen) { xd3_free (stream, stream->dec_buffer); stream->space_out = xd3_round_blksize (stream->dec_tgtlen, XD3_ALLOCSIZE); if ((stream->dec_buffer = (uint8_t*) xd3_alloc (stream, stream->space_out, 1)) == NULL) { return ENOMEM; } stream->next_out = stream->dec_buffer; } /* dec_tgtaddrbase refers to an invalid base address, but it is * always used with a sufficiently large instruction offset (i.e., * beyond the copy window). This condition is enforced by * xd3_decode_output_halfinst. */ stream->dec_tgtaddrbase = stream->next_out - stream->dec_cpylen; return 0; } static int xd3_decode_allocate (xd3_stream *stream, usize_t size, uint8_t **buf_ptr, usize_t *buf_alloc) { if (*buf_ptr != NULL && *buf_alloc < size) { xd3_free (stream, *buf_ptr); *buf_ptr = NULL; } if (*buf_ptr == NULL) { *buf_alloc = xd3_round_blksize (size, XD3_ALLOCSIZE); if ((*buf_ptr = (uint8_t*) xd3_alloc (stream, *buf_alloc, 1)) == NULL) { return ENOMEM; } } return 0; } static int xd3_decode_section (xd3_stream *stream, xd3_desect *section, xd3_decode_state nstate, int copy) { XD3_ASSERT (section->pos <= section->size); XD3_ASSERT (stream->dec_state != nstate); if (section->pos < section->size) { usize_t sect_take; if (stream->avail_in == 0) { return XD3_INPUT; } if ((copy == 0) && (section->pos == 0)) { /* No allocation/copy needed */ section->buf = stream->next_in; sect_take = section->size; } else { usize_t sect_need = section->size - section->pos; /* Allocate and copy */ sect_take = min (sect_need, stream->avail_in); if (section->pos == 0) { int ret; if ((ret = xd3_decode_allocate (stream, section->size, & section->copied1, & section->alloc1))) { return ret; } section->buf = section->copied1; } memcpy (section->copied1 + section->pos, stream->next_in, sect_take); } section->pos += sect_take; stream->dec_winbytes += sect_take; DECODE_INPUT (sect_take); } if (section->pos < section->size) { stream->msg = "further input required"; return XD3_INPUT; } XD3_ASSERT (section->pos == section->size); stream->dec_state = nstate; section->buf_max = section->buf + section->size; section->pos = 0; return 0; } /* Decode the size and address for half of an instruction (i.e., a * single opcode). This updates the stream->dec_position, which are * bytes already output prior to processing this instruction. Perform * bounds checking for sizes and copy addresses, which uses the * dec_position (which is why these checks are done here). */ static int xd3_decode_parse_halfinst (xd3_stream *stream, xd3_hinst *inst) { int ret; /* If the size from the instruction table is zero then read a size value. */ if ((inst->size == 0) && (ret = xd3_read_size (stream, & stream->inst_sect.buf, stream->inst_sect.buf_max, & inst->size))) { return XD3_INVALID_INPUT; } /* For copy instructions, read address. */ if (inst->type >= XD3_CPY) { IF_DEBUG2 ({ static int cnt = 0; XPR(NT "DECODE:%u: COPY at %"Q"u (winoffset %u) size %u winaddr %u\n", cnt++, stream->total_out + (stream->dec_position - stream->dec_cpylen), (stream->dec_position - stream->dec_cpylen), inst->size, inst->addr); }); if ((ret = xd3_decode_address (stream, stream->dec_position, inst->type - XD3_CPY, & stream->addr_sect.buf, stream->addr_sect.buf_max, & inst->addr))) { return ret; } /* Cannot copy an address before it is filled-in. */ if (inst->addr >= stream->dec_position) { stream->msg = "address too large"; return XD3_INVALID_INPUT; } /* Check: a VCD_TARGET or VCD_SOURCE copy cannot exceed the remaining * buffer space in its own segment. */ if (inst->addr < stream->dec_cpylen && inst->addr + inst->size > stream->dec_cpylen) { stream->msg = "size too large"; return XD3_INVALID_INPUT; } } else { IF_DEBUG2 ({ if (inst->type == XD3_ADD) { static int cnt; XPR(NT "DECODE:%d: ADD at %"Q"u (winoffset %u) size %u\n", cnt++, (stream->total_out + stream->dec_position - stream->dec_cpylen), stream->dec_position - stream->dec_cpylen, inst->size); } else { static int cnt; XD3_ASSERT (inst->type == XD3_RUN); XPR(NT "DECODE:%d: RUN at %"Q"u (winoffset %u) size %u\n", cnt++, stream->total_out + stream->dec_position - stream->dec_cpylen, stream->dec_position - stream->dec_cpylen, inst->size); } }); } /* Check: The instruction will not overflow the output buffer. */ if (stream->dec_position + inst->size > stream->dec_maxpos) { stream->msg = "size too large"; return XD3_INVALID_INPUT; } stream->dec_position += inst->size; return 0; } /* Decode a single opcode and then decode the two half-instructions. */ static int xd3_decode_instruction (xd3_stream *stream) { int ret; const xd3_dinst *inst; if (stream->inst_sect.buf == stream->inst_sect.buf_max) { stream->msg = "instruction underflow"; return XD3_INVALID_INPUT; } inst = &stream->code_table[*stream->inst_sect.buf++]; stream->dec_current1.type = inst->type1; stream->dec_current2.type = inst->type2; stream->dec_current1.size = inst->size1; stream->dec_current2.size = inst->size2; /* For each instruction with a real operation, decode the * corresponding size and addresses if necessary. Assume a * code-table may have NOOP in either position, although this is * unlikely. */ if (inst->type1 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current1))) { return ret; } if (inst->type2 != XD3_NOOP && (ret = xd3_decode_parse_halfinst (stream, & stream->dec_current2))) { return ret; } return 0; } /* Output the result of a single half-instruction. OPT: This the decoder hotspot. Modifies "hinst", see below. */ static int xd3_decode_output_halfinst (xd3_stream *stream, xd3_hinst *inst) { /* This method is reentrant for copy instructions which may return * XD3_GETSRCBLK to the caller. Each time through a copy takes the * minimum of inst->size and the available space on whichever block * supplies the data */ usize_t take = inst->size; XD3_ASSERT (inst->type != XD3_NOOP); switch (inst->type) { case XD3_RUN: { /* Only require a single data byte. */ if (stream->data_sect.buf == stream->data_sect.buf_max) { stream->msg = "data underflow"; return XD3_INVALID_INPUT; } memset (stream->next_out + stream->avail_out, stream->data_sect.buf[0], take); stream->data_sect.buf += 1; stream->avail_out += take; inst->type = XD3_NOOP; break; } case XD3_ADD: { /* Require at least TAKE data bytes. */ if (stream->data_sect.buf + take > stream->data_sect.buf_max) { stream->msg = "data underflow"; return XD3_INVALID_INPUT; } memcpy (stream->next_out + stream->avail_out, stream->data_sect.buf, take); stream->data_sect.buf += take; stream->avail_out += take; inst->type = XD3_NOOP; break; } default: { usize_t i; const uint8_t *src; uint8_t *dst; int overlap; /* See if it copies from the VCD_TARGET/VCD_SOURCE window or * the target window. Out-of-bounds checks for the addresses * and sizes are performed in xd3_decode_parse_halfinst. This * if/else must set "overlap", "src", and "dst". */ if (inst->addr < stream->dec_cpylen) { /* In both branches we are copying from outside the * current decoder window, the first (VCD_TARGET) is * unimplemented. */ overlap = 0; /* This branch sets "src". As a side-effect, we modify * "inst" so that if we reenter this method after a * XD3_GETSRCBLK response the state is correct. So if the * instruction can be fulfilled by a contiguous block of * memory then we will set: * * inst->type = XD3_NOOP; * inst->size = 0; */ if (stream->dec_win_ind & VCD_TARGET) { /* TODO: Users have requested long-distance copies of * similar material within a target (e.g., for dup * supression in backups). */ inst->size = 0; inst->type = XD3_NOOP; stream->msg = "VCD_TARGET not implemented"; return XD3_UNIMPLEMENTED; } else { /* In this case we have to read a source block, which * could return control to the caller. We need to * know the first block number needed for this * copy. */ xd3_source *source = stream->src; xoff_t block = source->cpyoff_blocks; usize_t blkoff = source->cpyoff_blkoff; const usize_t blksize = source->blksize; int ret; xd3_blksize_add (&block, &blkoff, source, inst->addr); XD3_ASSERT (blkoff < blksize); if ((ret = xd3_getblk (stream, block))) { /* could be a XD3_GETSRCBLK failure. */ if (ret == XD3_TOOFARBACK) { stream->msg = "non-seekable source in decode"; ret = XD3_INTERNAL; } return ret; } src = source->curblk + blkoff; /* This block is either full, or a partial block that * must contain enough bytes. */ if ((source->onblk != blksize) && (blkoff + take > source->onblk)) { IF_DEBUG1 (XPR(NT "[srcfile] short at blkno %"Q"u onblk " "%u blksize %u blkoff %u take %u\n", block, source->onblk, blksize, blkoff, take)); stream->msg = "source file too short"; return XD3_INVALID_INPUT; } XD3_ASSERT (blkoff != blksize); /* Check if we have enough data on this block to * finish the instruction. */ if (blkoff + take <= blksize) { inst->type = XD3_NOOP; inst->size = 0; } else { take = blksize - blkoff; inst->size -= take; inst->addr += take; /* because (blkoff + take > blksize), above */ XD3_ASSERT (inst->size != 0); } } } else { /* TODO: the memcpy/overlap optimization, etc. Overlap * here could be more specific, it's whether (inst->addr - * srclen) + inst->size > input_pos ? And is the system * memcpy really any good? */ overlap = 1; /* For a target-window copy, we know the entire range is * in-memory. The dec_tgtaddrbase is negatively offset by * dec_cpylen because the addresses start beyond that * point. */ src = stream->dec_tgtaddrbase + inst->addr; inst->type = XD3_NOOP; inst->size = 0; } dst = stream->next_out + stream->avail_out; stream->avail_out += take; if (overlap) { /* Can't just memcpy here due to possible overlap. */ for (i = take; i != 0; i -= 1) { *dst++ = *src++; } } else { memcpy (dst, src, take); } } } return 0; } static int xd3_decode_finish_window (xd3_stream *stream) { stream->dec_winbytes = 0; stream->dec_state = DEC_FINISH; stream->data_sect.pos = 0; stream->inst_sect.pos = 0; stream->addr_sect.pos = 0; return XD3_OUTPUT; } static int xd3_decode_secondary_sections (xd3_stream *secondary_stream) { #if SECONDARY_ANY int ret; #define DECODE_SECONDARY_SECTION(UPPER,LOWER) \ ((secondary_stream->dec_del_ind & VCD_ ## UPPER ## COMP) && \ (ret = xd3_decode_secondary (secondary_stream, \ & secondary_stream-> LOWER ## _sect, \ & xd3_sec_ ## LOWER (secondary_stream)))) if (DECODE_SECONDARY_SECTION (DATA, data) || DECODE_SECONDARY_SECTION (INST, inst) || DECODE_SECONDARY_SECTION (ADDR, addr)) { return ret; } #undef DECODE_SECONDARY_SECTION #endif return 0; } static int xd3_decode_sections (xd3_stream *stream) { usize_t need, more, take; int copy, ret; if ((stream->flags & XD3_JUST_HDR) != 0) { /* Nothing left to do. */ return xd3_decode_finish_window (stream); } /* To avoid copying, need this much data available */ need = (stream->inst_sect.size + stream->addr_sect.size + stream->data_sect.size); /* The window may be entirely processed. */ XD3_ASSERT (stream->dec_winbytes <= need); /* Compute how much more input is needed. */ more = (need - stream->dec_winbytes); /* How much to consume. */ take = min (more, stream->avail_in); /* See if the input is completely available, to avoid copy. */ copy = (take != more); /* If the window is skipped... */ if ((stream->flags & XD3_SKIP_WINDOW) != 0) { /* Skip the available input. */ DECODE_INPUT (take); stream->dec_winbytes += take; if (copy) { stream->msg = "further input required"; return XD3_INPUT; } return xd3_decode_finish_window (stream); } /* Process all but the DATA section. */ switch (stream->dec_state) { default: stream->msg = "internal error"; return XD3_INVALID_INPUT; case DEC_DATA: if ((ret = xd3_decode_section (stream, & stream->data_sect, DEC_INST, copy))) { return ret; } case DEC_INST: if ((ret = xd3_decode_section (stream, & stream->inst_sect, DEC_ADDR, copy))) { return ret; } case DEC_ADDR: if ((ret = xd3_decode_section (stream, & stream->addr_sect, DEC_EMIT, copy))) { return ret; } } XD3_ASSERT (stream->dec_winbytes == need); if ((ret = xd3_decode_secondary_sections (stream))) { return ret; } if (stream->flags & XD3_SKIP_EMIT) { return xd3_decode_finish_window (stream); } /* OPT: A possible optimization is to avoid allocating memory in * decode_setup_buffers and to avoid a large memcpy when the window * consists of a single VCD_SOURCE copy instruction. */ if ((ret = xd3_decode_setup_buffers (stream))) { return ret; } return 0; } static int xd3_decode_emit (xd3_stream *stream) { int ret; /* Produce output: originally structured to allow reentrant code * that fills as much of the output buffer as possible, but VCDIFF * semantics allows to copy from anywhere from the target window, so * instead allocate a sufficiently sized buffer after the target * window length is decoded. * * This code still needs to be reentrant to allow XD3_GETSRCBLK to * return control. This is handled by setting the * stream->dec_currentN instruction types to XD3_NOOP after they * have been processed. */ XD3_ASSERT (! (stream->flags & XD3_SKIP_EMIT)); XD3_ASSERT (stream->dec_tgtlen <= stream->space_out); while (stream->inst_sect.buf != stream->inst_sect.buf_max || stream->dec_current1.type != XD3_NOOP || stream->dec_current2.type != XD3_NOOP) { /* Decode next instruction pair. */ if ((stream->dec_current1.type == XD3_NOOP) && (stream->dec_current2.type == XD3_NOOP) && (ret = xd3_decode_instruction (stream))) { return ret; } /* Output dec_current1 */ while ((stream->dec_current1.type != XD3_NOOP)) { if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current1))) { return ret; } } /* Output dec_current2 */ while (stream->dec_current2.type != XD3_NOOP) { if ((ret = xd3_decode_output_halfinst (stream, & stream->dec_current2))) { return ret; } } } if (stream->avail_out != stream->dec_tgtlen) { IF_DEBUG2 (DP(RINT "AVAIL_OUT(%d) != DEC_TGTLEN(%d)\n", stream->avail_out, stream->dec_tgtlen)); stream->msg = "wrong window length"; return XD3_INVALID_INPUT; } if (stream->data_sect.buf != stream->data_sect.buf_max) { stream->msg = "extra data section"; return XD3_INVALID_INPUT; } if (stream->addr_sect.buf != stream->addr_sect.buf_max) { stream->msg = "extra address section"; return XD3_INVALID_INPUT; } /* OPT: Should cksum computation be combined with the above loop? */ if ((stream->dec_win_ind & VCD_ADLER32) != 0 && (stream->flags & XD3_ADLER32_NOVER) == 0) { uint32_t a32 = adler32 (1L, stream->next_out, stream->avail_out); if (a32 != stream->dec_adler32) { stream->msg = "target window checksum mismatch"; return XD3_INVALID_INPUT; } } /* Finished with a window. */ return xd3_decode_finish_window (stream); } int xd3_decode_input (xd3_stream *stream) { int ret; if (stream->enc_state != 0) { stream->msg = "encoder/decoder transition"; return XD3_INVALID_INPUT; } #define BYTE_CASE(expr,x,nstate) \ do { \ if ( (expr) && \ ((ret = xd3_decode_byte (stream, & (x))) != 0) ) { return ret; } \ stream->dec_state = (nstate); \ } while (0) #define OFFSET_CASE(expr,x,nstate) \ do { \ if ( (expr) && \ ((ret = xd3_decode_offset (stream, & (x))) != 0) ) { return ret; } \ stream->dec_state = (nstate); \ } while (0) #define SIZE_CASE(expr,x,nstate) \ do { \ if ( (expr) && \ ((ret = xd3_decode_size (stream, & (x))) != 0) ) { return ret; } \ stream->dec_state = (nstate); \ } while (0) switch (stream->dec_state) { case DEC_VCHEAD: { if ((ret = xd3_decode_bytes (stream, stream->dec_magic, & stream->dec_magicbytes, 4))) { return ret; } if (stream->dec_magic[0] != VCDIFF_MAGIC1 || stream->dec_magic[1] != VCDIFF_MAGIC2 || stream->dec_magic[2] != VCDIFF_MAGIC3) { stream->msg = "not a VCDIFF input"; return XD3_INVALID_INPUT; } if (stream->dec_magic[3] != 0) { stream->msg = "VCDIFF input version > 0 is not supported"; return XD3_INVALID_INPUT; } stream->dec_state = DEC_HDRIND; } case DEC_HDRIND: { if ((ret = xd3_decode_byte (stream, & stream->dec_hdr_ind))) { return ret; } if ((stream->dec_hdr_ind & VCD_INVHDR) != 0) { stream->msg = "unrecognized header indicator bits set"; return XD3_INVALID_INPUT; } stream->dec_state = DEC_SECONDID; } case DEC_SECONDID: /* Secondary compressor ID: only if VCD_SECONDARY is set */ if ((stream->dec_hdr_ind & VCD_SECONDARY) != 0) { BYTE_CASE (1, stream->dec_secondid, DEC_TABLEN); switch (stream->dec_secondid) { case VCD_FGK_ID: FGK_CASE (stream); case VCD_DJW_ID: DJW_CASE (stream); case VCD_LZMA_ID: LZMA_CASE (stream); default: stream->msg = "unknown secondary compressor ID"; return XD3_INVALID_INPUT; } } case DEC_TABLEN: /* Length of code table data: only if VCD_CODETABLE is set */ SIZE_CASE ((stream->dec_hdr_ind & VCD_CODETABLE) != 0, stream->dec_codetblsz, DEC_NEAR); /* The codetblsz counts the two NEAR/SAME bytes */ if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) { if (stream->dec_codetblsz <= 2) { stream->msg = "invalid code table size"; return ENOMEM; } stream->dec_codetblsz -= 2; } case DEC_NEAR: /* Near modes: only if VCD_CODETABLE is set */ BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, stream->acache.s_near, DEC_SAME); case DEC_SAME: /* Same modes: only if VCD_CODETABLE is set */ BYTE_CASE((stream->dec_hdr_ind & VCD_CODETABLE) != 0, stream->acache.s_same, DEC_TABDAT); case DEC_TABDAT: /* Compressed code table data */ if ((stream->dec_hdr_ind & VCD_CODETABLE) != 0) { /* Get the code table data. */ if ((stream->dec_codetbl == NULL) && (stream->dec_codetbl = (uint8_t*) xd3_alloc (stream, stream->dec_codetblsz, 1)) == NULL) { return ENOMEM; } if ((ret = xd3_decode_bytes (stream, stream->dec_codetbl, & stream->dec_codetblbytes, stream->dec_codetblsz))) { return ret; } if ((ret = xd3_apply_table_encoding (stream, stream->dec_codetbl, stream->dec_codetblbytes))) { return ret; } } else { /* Use the default table. */ stream->acache.s_near = __rfc3284_code_table_desc.near_modes; stream->acache.s_same = __rfc3284_code_table_desc.same_modes; stream->code_table = xd3_rfc3284_code_table (); } if ((ret = xd3_alloc_cache (stream))) { return ret; } stream->dec_state = DEC_APPLEN; case DEC_APPLEN: /* Length of application data */ SIZE_CASE((stream->dec_hdr_ind & VCD_APPHEADER) != 0, stream->dec_appheadsz, DEC_APPDAT); case DEC_APPDAT: /* Application data */ if (stream->dec_hdr_ind & VCD_APPHEADER) { /* Note: we add an additional byte for padding, to allow 0-termination. */ if ((stream->dec_appheader == NULL) && (stream->dec_appheader = (uint8_t*) xd3_alloc (stream, stream->dec_appheadsz+1, 1)) == NULL) { return ENOMEM; } stream->dec_appheader[stream->dec_appheadsz] = 0; if ((ret = xd3_decode_bytes (stream, stream->dec_appheader, & stream->dec_appheadbytes, stream->dec_appheadsz))) { return ret; } } /* xoff_t -> usize_t is safe because this is the first block. */ stream->dec_hdrsize = (usize_t) stream->total_in; stream->dec_state = DEC_WININD; case DEC_WININD: { /* Start of a window: the window indicator */ if ((ret = xd3_decode_byte (stream, & stream->dec_win_ind))) { return ret; } stream->current_window = stream->dec_window_count; if (XOFF_T_OVERFLOW (stream->dec_winstart, stream->dec_tgtlen)) { stream->msg = "decoder file offset overflow"; return XD3_INVALID_INPUT; } stream->dec_winstart += stream->dec_tgtlen; if ((stream->dec_win_ind & VCD_INVWIN) != 0) { stream->msg = "unrecognized window indicator bits set"; return XD3_INVALID_INPUT; } if ((ret = xd3_decode_init_window (stream))) { return ret; } stream->dec_state = DEC_CPYLEN; IF_DEBUG2 (DP(RINT "--------- TARGET WINDOW %"Q"u -----------\n", stream->current_window)); } case DEC_CPYLEN: /* Copy window length: only if VCD_SOURCE or VCD_TARGET is set */ SIZE_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpylen, DEC_CPYOFF); /* Set the initial, logical decoder position (HERE address) in * dec_position. This is set to just after the source/copy * window, as we are just about to output the first byte of * target window. */ stream->dec_position = stream->dec_cpylen; case DEC_CPYOFF: /* Copy window offset: only if VCD_SOURCE or VCD_TARGET is set */ OFFSET_CASE(SRCORTGT (stream->dec_win_ind), stream->dec_cpyoff, DEC_ENCLEN); /* Copy offset and copy length may not overflow. */ if (XOFF_T_OVERFLOW (stream->dec_cpyoff, stream->dec_cpylen)) { stream->msg = "decoder copy window overflows a file offset"; return XD3_INVALID_INPUT; } /* Check copy window bounds: VCD_TARGET window may not exceed current position. */ if ((stream->dec_win_ind & VCD_TARGET) && (stream->dec_cpyoff + (xoff_t) stream->dec_cpylen > stream->dec_winstart)) { stream->msg = "VCD_TARGET window out of bounds"; return XD3_INVALID_INPUT; } case DEC_ENCLEN: /* Length of the delta encoding */ SIZE_CASE(1, stream->dec_enclen, DEC_TGTLEN); case DEC_TGTLEN: /* Length of target window */ SIZE_CASE(1, stream->dec_tgtlen, DEC_DELIND); /* Set the maximum decoder position, beyond which we should not * decode any data. This is the maximum value for dec_position. * This may not exceed the size of a usize_t. */ if (USIZE_T_OVERFLOW (stream->dec_cpylen, stream->dec_tgtlen)) { stream->msg = "decoder target window overflows a usize_t"; return XD3_INVALID_INPUT; } /* Check for malicious files. */ if (stream->dec_tgtlen > XD3_HARDMAXWINSIZE) { stream->msg = "hard window size exceeded"; return XD3_INVALID_INPUT; } stream->dec_maxpos = stream->dec_cpylen + stream->dec_tgtlen; case DEC_DELIND: /* Delta indicator */ BYTE_CASE(1, stream->dec_del_ind, DEC_DATALEN); if ((stream->dec_del_ind & VCD_INVDEL) != 0) { stream->msg = "unrecognized delta indicator bits set"; return XD3_INVALID_INPUT; } /* Delta indicator is only used with secondary compression. */ if ((stream->dec_del_ind != 0) && (stream->sec_type == NULL)) { stream->msg = "invalid delta indicator bits set"; return XD3_INVALID_INPUT; } /* Section lengths */ case DEC_DATALEN: SIZE_CASE(1, stream->data_sect.size, DEC_INSTLEN); case DEC_INSTLEN: SIZE_CASE(1, stream->inst_sect.size, DEC_ADDRLEN); case DEC_ADDRLEN: SIZE_CASE(1, stream->addr_sect.size, DEC_CKSUM); case DEC_CKSUM: /* Window checksum. */ if ((stream->dec_win_ind & VCD_ADLER32) != 0) { int i; if ((ret = xd3_decode_bytes (stream, stream->dec_cksum, & stream->dec_cksumbytes, 4))) { return ret; } for (i = 0; i < 4; i += 1) { stream->dec_adler32 = (stream->dec_adler32 << 8) | stream->dec_cksum[i]; } } stream->dec_state = DEC_DATA; /* Check dec_enclen for redundency, otherwise it is not really used. */ { usize_t enclen_check = (1 + (xd3_sizeof_size (stream->dec_tgtlen) + xd3_sizeof_size (stream->data_sect.size) + xd3_sizeof_size (stream->inst_sect.size) + xd3_sizeof_size (stream->addr_sect.size)) + stream->data_sect.size + stream->inst_sect.size + stream->addr_sect.size + ((stream->dec_win_ind & VCD_ADLER32) ? 4 : 0)); if (stream->dec_enclen != enclen_check) { stream->msg = "incorrect encoding length (redundent)"; return XD3_INVALID_INPUT; } } /* Returning here gives the application a chance to inspect the * header, skip the window, etc. */ if (stream->current_window == 0) { return XD3_GOTHEADER; } else { return XD3_WINSTART; } case DEC_DATA: case DEC_INST: case DEC_ADDR: /* Next read the three sections. */ if ((ret = xd3_decode_sections (stream))) { return ret; } case DEC_EMIT: /* To speed VCD_SOURCE block-address calculations, the source * cpyoff_blocks and cpyoff_blkoff are pre-computed. */ if (stream->dec_win_ind & VCD_SOURCE) { xd3_source *src = stream->src; if (src == NULL) { stream->msg = "source input required"; return XD3_INVALID_INPUT; } xd3_blksize_div(stream->dec_cpyoff, src, &src->cpyoff_blocks, &src->cpyoff_blkoff); IF_DEBUG1(DP(RINT "decode cpyoff %"Q"u " "cpyblkno %"Q"u " "cpyblkoff %u " "blksize %u\n", stream->dec_cpyoff, src->cpyoff_blocks, src->cpyoff_blkoff, src->blksize)); } /* xd3_decode_emit returns XD3_OUTPUT on every success. */ if ((ret = xd3_decode_emit (stream)) == XD3_OUTPUT) { stream->total_out += (xoff_t) stream->avail_out; } return ret; case DEC_FINISH: { if (stream->dec_win_ind & VCD_TARGET) { if (stream->dec_lastwin == NULL) { stream->dec_lastwin = stream->next_out; stream->dec_lastspace = stream->space_out; } else { xd3_swap_uint8p (& stream->dec_lastwin, & stream->next_out); xd3_swap_usize_t (& stream->dec_lastspace, & stream->space_out); } } stream->dec_lastlen = stream->dec_tgtlen; stream->dec_laststart = stream->dec_winstart; stream->dec_window_count += 1; /* Note: the updates to dec_winstart & current_window are * deferred until after the next DEC_WININD byte is read. */ stream->dec_state = DEC_WININD; return XD3_WINFINISH; } default: stream->msg = "invalid state"; return XD3_INVALID_INPUT; } } #endif // _XDELTA3_DECODE_H_ xdelta3-3.0.7/install-sh0000755000176500017650000003325612105354541014362 0ustar debdevdebdev#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-01-19.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for `test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for `test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for `test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: xdelta3-3.0.7/xdelta3-djw.h0000644000176500017650000013441512105354541014654 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2002, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: This code needs a thorough round of commenting. There is * some slop in the declaration of arrays, which are maybe one element * larger than they need to be and comments would help clear it up. */ #ifndef _XDELTA3_DJW_H_ #define _XDELTA3_DJW_H_ /* The following people deserve much credit for the algorithms and * techniques contained in this file: Julian Seward Bzip2 sources, implementation of the multi-table Huffman technique. Jean-loup Gailly and Mark Adler and L. Peter Deutsch Zlib source code, RFC 1951 Daniel S. Hirschberg and Debra A. LeLewer "Efficient Decoding of Prefix Codes" Communications of the ACM, April 1990 33(4). David J. Wheeler Program bred3.c, bexp3 and accompanying documents bred3.ps, huff.ps. This contains the idea behind the multi-table Huffman and 1-2 coding techniques. ftp://ftp.cl.cam.ac.uk/users/djw3/ */ /* OPT: during the multi-table iteration, pick the worst-overall * performing table and replace it with exactly the frequencies of the * worst-overall performing sector or N-worst performing sectors. */ /* REF: See xdfs-0.222 and xdfs-0.226 for some old experiments with * the Bzip prefix coding strategy. xdfs-0.256 contains the last of * the other-format tests, including RFC1950 and the RFC1950+MTF * tests. */ #define DJW_MAX_CODELEN 20U /* Maximum length of an alphabet code. */ /* Code lengths are themselves code-length encoded, so the total number of * codes is: [RUN_0, RUN_1, 1-DJW_MAX_CODELEN] */ #define DJW_TOTAL_CODES (DJW_MAX_CODELEN+2) #define RUN_0 0U /* Symbols used in MTF+1/2 coding. */ #define RUN_1 1U /* Number of code lengths always encoded (djw_encode_basic array) */ #define DJW_BASIC_CODES 5U #define DJW_RUN_CODES 2U /* Number of run codes */ /* Offset of extra codes */ #define DJW_EXTRA_12OFFSET (DJW_BASIC_CODES + DJW_RUN_CODES) /* Number of optionally encoded code lengths (djw_encode_extra array) */ #define DJW_EXTRA_CODES 15U /* Number of bits to code [0-DJW_EXTRA_CODES] */ #define DJW_EXTRA_CODE_BITS 4U #define DJW_MAX_GROUPS 8U /* Max number of group coding tables */ #define DJW_GROUP_BITS 3U /* Number of bits to code [1-DJW_MAX_GROUPS] */ #define DJW_SECTORSZ_MULT 5U /* Multiplier for encoded sectorsz */ #define DJW_SECTORSZ_BITS 5U /* Number of bits to code group size */ #define DJW_SECTORSZ_MAX ((1U << DJW_SECTORSZ_BITS) * DJW_SECTORSZ_MULT) /* Maximum number of iterations to find group tables. */ #define DJW_MAX_ITER 6U /* Minimum number of bits an iteration must reduce coding by. */ #define DJW_MIN_IMPROVEMENT 20U /* Maximum code length of a prefix code length */ #define DJW_MAX_CLCLEN 15U /* Number of bits to code [0-DJW_MAX_CLCLEN] */ #define DJW_CLCLEN_BITS 4U #define DJW_MAX_GBCLEN 7U /* Maximum code length of a group selector */ /* Number of bits to code [0-DJW_MAX_GBCLEN] * TODO: Actually, should never have zero code lengths here, or else a group * went unused. Write a test for this: if a group goes unused, eliminate * it? */ #define DJW_GBCLEN_BITS 3U /* It has to save at least this many bits... */ #define EFFICIENCY_BITS 16U typedef struct _djw_stream djw_stream; typedef struct _djw_heapen djw_heapen; typedef struct _djw_prefix djw_prefix; typedef uint32_t djw_weight; struct _djw_heapen { uint32_t depth; uint32_t freq; uint32_t parent; }; struct _djw_prefix { usize_t scount; uint8_t *symbol; usize_t mcount; uint8_t *mtfsym; uint8_t *repcnt; }; struct _djw_stream { int unused; }; /* Each Huffman table consists of 256 "code length" (CLEN) codes, * which are themselves Huffman coded after eliminating repeats and * move-to-front coding. The prefix consists of all the CLEN codes in * djw_encode_basic plus a 4-bit value stating how many of the * djw_encode_extra codes are actually coded (the rest are presumed * zero, or unused CLEN codes). * * These values of these two arrays were arrived at by studying the * distribution of min and max clen over a collection of DATA, INST, * and ADDR inputs. The goal is to specify the order of * djw_extra_codes that is most likely to minimize the number of extra * codes that must be encoded. * * Results: 158896 sections were counted by compressing files (window * size 512K) listed with: `find / -type f ( -user jmacd -o -perm +444 * )` * * The distribution of CLEN codes for each efficient invocation of the * secondary compressor (taking the best number of groups/sector size) * was recorded. Then we look at the distribution of min and max clen * values, counting the number of times the value C_low is less than * the min and C_high is greater than the max. Values >= C_high and * <= C_low will not have their lengths coded. The results are sorted * and the least likely 15 are placed into the djw_encode_extra[] * array in order. These values are used as the initial MTF ordering. clow[1] = 155119 clow[2] = 140325 clow[3] = 84072 --- clow[4] = 7225 clow[5] = 1093 clow[6] = 215 --- chigh[4] = 1 chigh[5] = 30 chigh[6] = 218 chigh[7] = 2060 chigh[8] = 13271 --- chigh[9] = 39463 chigh[10] = 77360 chigh[11] = 118298 chigh[12] = 141360 chigh[13] = 154086 chigh[14] = 157967 chigh[15] = 158603 chigh[16] = 158864 chigh[17] = 158893 chigh[18] = 158895 chigh[19] = 158896 chigh[20] = 158896 */ static const uint8_t djw_encode_12extra[DJW_EXTRA_CODES] = { 9, 10, 3, 11, 2, 12, 13, 1, 14, 15, 16, 17, 18, 19, 20, }; static const uint8_t djw_encode_12basic[DJW_BASIC_CODES] = { 4, 5, 6, 7, 8, }; /*********************************************************************/ /* DECLS */ /*********************************************************************/ static djw_stream* djw_alloc (xd3_stream *stream); static int djw_init (xd3_stream *stream, djw_stream *h, int is_encode); static void djw_destroy (xd3_stream *stream, djw_stream *h); #if XD3_ENCODER static int xd3_encode_huff (xd3_stream *stream, djw_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg); #endif static int xd3_decode_huff (xd3_stream *stream, djw_stream *sec_stream, const uint8_t **input, const uint8_t *const input_end, uint8_t **output, const uint8_t *const output_end); /*********************************************************************/ /* HUFFMAN */ /*********************************************************************/ static djw_stream* djw_alloc (xd3_stream *stream) { return (djw_stream*) xd3_alloc (stream, sizeof (djw_stream), 1); } static int djw_init (xd3_stream *stream, djw_stream *h, int is_encode) { /* Fields are initialized prior to use. */ return 0; } static void djw_destroy (xd3_stream *stream, djw_stream *h) { xd3_free (stream, h); } /*********************************************************************/ /* HEAP */ /*********************************************************************/ static inline int heap_less (const djw_heapen *a, const djw_heapen *b) { return a->freq < b->freq || (a->freq == b->freq && a->depth < b->depth); } static inline void heap_insert (usize_t *heap, const djw_heapen *ents, usize_t p, const usize_t e) { /* Insert ents[e] into next slot heap[p] */ usize_t pp = p/2; /* P's parent */ while (heap_less (& ents[e], & ents[heap[pp]])) { heap[p] = heap[pp]; p = pp; pp = p/2; } heap[p] = e; } static inline djw_heapen* heap_extract (usize_t *heap, const djw_heapen *ents, usize_t heap_last) { usize_t smallest = heap[1]; usize_t p, pc, t; /* Caller decrements heap_last, so heap_last+1 is the replacement elt. */ heap[1] = heap[heap_last+1]; /* Re-heapify */ for (p = 1; ; p = pc) { pc = p*2; /* Reached bottom of heap */ if (pc > heap_last) { break; } /* See if second child is smaller. */ if (pc < heap_last && heap_less (& ents[heap[pc+1]], & ents[heap[pc]])) { pc += 1; } /* If pc is not smaller than p, heap property re-established. */ if (! heap_less (& ents[heap[pc]], & ents[heap[p]])) { break; } t = heap[pc]; heap[pc] = heap[p]; heap[p] = t; } return (djw_heapen*) & ents[smallest]; } #if XD3_DEBUG static void heap_check (usize_t *heap, djw_heapen *ents, usize_t heap_last) { usize_t i; for (i = 1; i <= heap_last; i += 1) { /* Heap property: child not less than parent */ XD3_ASSERT (! heap_less (& ents[heap[i]], & ents[heap[i/2]])); IF_DEBUG2 (DP(RINT "heap[%d] = %u\n", i, ents[heap[i]].freq)); } } #endif /*********************************************************************/ /* MTF, 1/2 */ /*********************************************************************/ static inline usize_t djw_update_mtf (uint8_t *mtf, usize_t mtf_i) { int k; usize_t sym = mtf[mtf_i]; for (k = mtf_i; k != 0; k -= 1) { mtf[k] = mtf[k-1]; } mtf[0] = sym; return sym; } static inline void djw_update_1_2 (int *mtf_run, usize_t *mtf_i, uint8_t *mtfsym, djw_weight *freq) { int code; do { /* Offset by 1, since any number of RUN_ symbols implies run>0... */ *mtf_run -= 1; code = (*mtf_run & 1) ? RUN_1 : RUN_0; mtfsym[(*mtf_i)++] = code; freq[code] += 1; *mtf_run >>= 1; } while (*mtf_run >= 1); *mtf_run = 0; } static void djw_init_clen_mtf_1_2 (uint8_t *clmtf) { usize_t i, cl_i = 0; clmtf[cl_i++] = 0; for (i = 0; i < DJW_BASIC_CODES; i += 1) { clmtf[cl_i++] = djw_encode_12basic[i]; } for (i = 0; i < DJW_EXTRA_CODES; i += 1) { clmtf[cl_i++] = djw_encode_12extra[i]; } } /*********************************************************************/ /* PREFIX CODES */ /*********************************************************************/ #if XD3_ENCODER static usize_t djw_build_prefix (const djw_weight *freq, uint8_t *clen, usize_t asize, usize_t maxlen) { /* Heap with 0th entry unused, prefix tree with up to ALPHABET_SIZE-1 * internal nodes, never more than ALPHABET_SIZE entries actually in the * heap (minimum weight subtrees during prefix construction). First * ALPHABET_SIZE entries are the actual symbols, next ALPHABET_SIZE-1 are * internal nodes. */ djw_heapen ents[ALPHABET_SIZE * 2]; usize_t heap[ALPHABET_SIZE + 1]; usize_t heap_last; /* Index of the last _valid_ heap entry. */ usize_t ents_size; /* Number of entries, including 0th fake entry */ usize_t overflow; /* Number of code lengths that overflow */ uint32_t total_bits; usize_t i; IF_DEBUG (uint32_t first_bits = 0); /* Insert real symbol frequences. */ for (i = 0; i < asize; i += 1) { ents[i+1].freq = freq[i]; IF_DEBUG2 (DP(RINT "ents[%d] = freq[%d] = %d\n", i+1, i, freq[i])); } again: /* The loop is re-entered each time an overflow occurs. Re-initialize... */ heap_last = 0; ents_size = 1; overflow = 0; total_bits = 0; /* 0th entry terminates the while loop in heap_insert (it's the parent of * the smallest element, always less-than) */ heap[0] = 0; ents[0].depth = 0; ents[0].freq = 0; /* Initial heap. */ for (i = 0; i < asize; i += 1, ents_size += 1) { ents[ents_size].depth = 0; ents[ents_size].parent = 0; if (ents[ents_size].freq != 0) { heap_insert (heap, ents, ++heap_last, ents_size); } } IF_DEBUG (heap_check (heap, ents, heap_last)); /* Must be at least one symbol, or else we can't get here. */ XD3_ASSERT (heap_last != 0); /* If there is only one symbol, fake a second to prevent zero-length * codes. */ if (heap_last == 1) { /* Pick either the first or last symbol. */ int s = freq[0] ? asize-1 : 0; ents[s+1].freq = 1; goto again; } /* Build prefix tree. */ while (heap_last > 1) { djw_heapen *h1 = heap_extract (heap, ents, --heap_last); djw_heapen *h2 = heap_extract (heap, ents, --heap_last); ents[ents_size].freq = h1->freq + h2->freq; ents[ents_size].depth = 1 + max (h1->depth, h2->depth); ents[ents_size].parent = 0; h1->parent = h2->parent = ents_size; heap_insert (heap, ents, ++heap_last, ents_size++); } IF_DEBUG (heap_check (heap, ents, heap_last)); /* Now compute prefix code lengths, counting parents. */ for (i = 1; i < asize+1; i += 1) { usize_t b = 0; if (ents[i].freq != 0) { usize_t p = i; while ((p = ents[p].parent) != 0) { b += 1; } if (b > maxlen) { overflow = 1; } total_bits += b * freq[i-1]; } /* clen is 0-origin, unlike ents. */ IF_DEBUG2 (DP(RINT "clen[%d] = %d\n", i-1, b)); clen[i-1] = b; } IF_DEBUG (if (first_bits == 0) first_bits = total_bits); if (! overflow) { IF_DEBUG2 (if (first_bits != total_bits) { DP(RINT "code length overflow changed %u bits\n", (usize_t)(total_bits - first_bits)); }); return total_bits; } /* OPT: There is a non-looping way to fix overflow shown in zlib, but this * is easier (for now), as done in bzip2. */ for (i = 1; i < asize+1; i += 1) { ents[i].freq = ents[i].freq / 2 + 1; } goto again; } static void djw_build_codes (usize_t *codes, const uint8_t *clen, usize_t asize, usize_t abs_max) { usize_t i, l; usize_t min_clen = DJW_MAX_CODELEN; usize_t max_clen = 0; usize_t code = 0; /* Find the min and max code length */ for (i = 0; i < asize; i += 1) { if (clen[i] > 0 && clen[i] < min_clen) { min_clen = clen[i]; } max_clen = max (max_clen, (usize_t) clen[i]); } XD3_ASSERT (max_clen <= abs_max); /* Generate a code for each symbol with the appropriate length. */ for (l = min_clen; l <= max_clen; l += 1) { for (i = 0; i < asize; i += 1) { if (clen[i] == l) { codes[i] = code++; } } code <<= 1; } IF_DEBUG2 ({ for (i = 0; i < asize; i += 1) { DP(RINT "code[%d] = %u\n", i, codes[i]); } }); } /*********************************************************************/ /* MOVE-TO-FRONT */ /*********************************************************************/ static void djw_compute_mtf_1_2 (djw_prefix *prefix, uint8_t *mtf, djw_weight *freq_out, usize_t nsym) { size_t i, j, k; usize_t sym; usize_t size = prefix->scount; usize_t mtf_i = 0; int mtf_run = 0; /* This +2 is for the RUN_0, RUN_1 codes */ memset (freq_out, 0, sizeof (freq_out[0]) * (nsym+2)); for (i = 0; i < size; ) { /* OPT: Bzip optimizes this algorithm a little by effectively checking * j==0 before the MTF update. */ sym = prefix->symbol[i++]; for (j = 0; mtf[j] != sym; j += 1) { } XD3_ASSERT (j <= nsym); for (k = j; k >= 1; k -= 1) { mtf[k] = mtf[k-1]; } mtf[0] = sym; if (j == 0) { mtf_run += 1; continue; } if (mtf_run > 0) { djw_update_1_2 (& mtf_run, & mtf_i, prefix->mtfsym, freq_out); } /* Non-zero symbols are offset by RUN_1 */ prefix->mtfsym[mtf_i++] = (uint8_t)(j+RUN_1); freq_out[j+RUN_1] += 1; } if (mtf_run > 0) { djw_update_1_2 (& mtf_run, & mtf_i, prefix->mtfsym, freq_out); } prefix->mcount = mtf_i; } /* Counts character frequencies of the input buffer, returns the size. */ static usize_t djw_count_freqs (djw_weight *freq, xd3_output *input) { xd3_output *in; usize_t size = 0; memset (freq, 0, sizeof (freq[0]) * ALPHABET_SIZE); for (in = input; in; in = in->next_page) { const uint8_t *p = in->base; const uint8_t *p_max = p + in->next; size += in->next; do { ++freq[*p]; } while (++p < p_max); } IF_DEBUG2 ({int i; DP(RINT "freqs: "); for (i = 0; i < ALPHABET_SIZE; i += 1) { DP(RINT "%u ", freq[i]); } DP(RINT "\n");}); return size; } static void djw_compute_multi_prefix (usize_t groups, uint8_t clen[DJW_MAX_GROUPS][ALPHABET_SIZE], djw_prefix *prefix) { usize_t gp, i; prefix->scount = ALPHABET_SIZE; memcpy (prefix->symbol, clen[0], ALPHABET_SIZE); for (gp = 1; gp < groups; gp += 1) { for (i = 0; i < ALPHABET_SIZE; i += 1) { if (clen[gp][i] == 0) { continue; } prefix->symbol[prefix->scount++] = clen[gp][i]; } } } static void djw_compute_prefix_1_2 (djw_prefix *prefix, djw_weight *freq) { /* This +1 is for the 0 code-length. */ uint8_t clmtf[DJW_MAX_CODELEN+1]; djw_init_clen_mtf_1_2 (clmtf); djw_compute_mtf_1_2 (prefix, clmtf, freq, DJW_MAX_CODELEN); } static int djw_encode_prefix (xd3_stream *stream, xd3_output **output, bit_state *bstate, djw_prefix *prefix) { int ret; size_t i; usize_t num_to_encode; djw_weight clfreq[DJW_TOTAL_CODES]; uint8_t clclen[DJW_TOTAL_CODES]; usize_t clcode[DJW_TOTAL_CODES]; /* Move-to-front encode prefix symbols, count frequencies */ djw_compute_prefix_1_2 (prefix, clfreq); /* Compute codes */ djw_build_prefix (clfreq, clclen, DJW_TOTAL_CODES, DJW_MAX_CLCLEN); djw_build_codes (clcode, clclen, DJW_TOTAL_CODES, DJW_MAX_CLCLEN); /* Compute number of extra codes beyond basic ones for this template. */ num_to_encode = DJW_TOTAL_CODES; while (num_to_encode > DJW_EXTRA_12OFFSET && clclen[num_to_encode-1] == 0) { num_to_encode -= 1; } XD3_ASSERT (num_to_encode - DJW_EXTRA_12OFFSET < (1 << DJW_EXTRA_CODE_BITS)); /* Encode: # of extra codes */ if ((ret = xd3_encode_bits (stream, output, bstate, DJW_EXTRA_CODE_BITS, num_to_encode - DJW_EXTRA_12OFFSET))) { return ret; } /* Encode: MTF code lengths */ for (i = 0; i < num_to_encode; i += 1) { if ((ret = xd3_encode_bits (stream, output, bstate, DJW_CLCLEN_BITS, clclen[i]))) { return ret; } } /* Encode: CLEN code lengths */ for (i = 0; i < prefix->mcount; i += 1) { usize_t mtf_sym = prefix->mtfsym[i]; usize_t bits = clclen[mtf_sym]; usize_t code = clcode[mtf_sym]; if ((ret = xd3_encode_bits (stream, output, bstate, bits, code))) { return ret; } } return 0; } static void djw_compute_selector_1_2 (djw_prefix *prefix, usize_t groups, djw_weight *gbest_freq) { uint8_t grmtf[DJW_MAX_GROUPS]; usize_t i; for (i = 0; i < groups; i += 1) { grmtf[i] = i; } djw_compute_mtf_1_2 (prefix, grmtf, gbest_freq, groups); } static int xd3_encode_howmany_groups (xd3_stream *stream, xd3_sec_cfg *cfg, usize_t input_size, usize_t *ret_groups, usize_t *ret_sector_size) { usize_t cfg_groups = 0; usize_t cfg_sector_size = 0; usize_t sugg_groups = 0; usize_t sugg_sector_size = 0; if (cfg->ngroups != 0) { if (cfg->ngroups > DJW_MAX_GROUPS) { stream->msg = "invalid secondary encoder group number"; return XD3_INTERNAL; } cfg_groups = cfg->ngroups; } if (cfg->sector_size != 0) { if (cfg->sector_size < DJW_SECTORSZ_MULT || cfg->sector_size > DJW_SECTORSZ_MAX || (cfg->sector_size % DJW_SECTORSZ_MULT) != 0) { stream->msg = "invalid secondary encoder sector size"; return XD3_INTERNAL; } cfg_sector_size = cfg->sector_size; } if (cfg_groups == 0 || cfg_sector_size == 0) { /* These values were found empirically using xdelta3-tune around version * xdfs-0.256. */ switch (cfg->data_type) { case DATA_SECTION: if (input_size < 1000) { sugg_groups = 1; sugg_sector_size = 0; } else if (input_size < 4000) { sugg_groups = 2; sugg_sector_size = 10; } else if (input_size < 7000) { sugg_groups = 3; sugg_sector_size = 10; } else if (input_size < 10000) { sugg_groups = 4; sugg_sector_size = 10; } else if (input_size < 25000) { sugg_groups = 5; sugg_sector_size = 10; } else if (input_size < 50000) { sugg_groups = 7; sugg_sector_size = 20; } else if (input_size < 100000) { sugg_groups = 8; sugg_sector_size = 30; } else { sugg_groups = 8; sugg_sector_size = 70; } break; case INST_SECTION: if (input_size < 7000) { sugg_groups = 1; sugg_sector_size = 0; } else if (input_size < 10000) { sugg_groups = 2; sugg_sector_size = 50; } else if (input_size < 25000) { sugg_groups = 3; sugg_sector_size = 50; } else if (input_size < 50000) { sugg_groups = 6; sugg_sector_size = 40; } else if (input_size < 100000) { sugg_groups = 8; sugg_sector_size = 40; } else { sugg_groups = 8; sugg_sector_size = 40; } break; case ADDR_SECTION: if (input_size < 9000) { sugg_groups = 1; sugg_sector_size = 0; } else if (input_size < 25000) { sugg_groups = 2; sugg_sector_size = 130; } else if (input_size < 50000) { sugg_groups = 3; sugg_sector_size = 130; } else if (input_size < 100000) { sugg_groups = 5; sugg_sector_size = 130; } else { sugg_groups = 7; sugg_sector_size = 130; } break; } if (cfg_groups == 0) { cfg_groups = sugg_groups; } if (cfg_sector_size == 0) { cfg_sector_size = sugg_sector_size; } } if (cfg_groups != 1 && cfg_sector_size == 0) { switch (cfg->data_type) { case DATA_SECTION: cfg_sector_size = 20; break; case INST_SECTION: cfg_sector_size = 50; break; case ADDR_SECTION: cfg_sector_size = 130; break; } } (*ret_groups) = cfg_groups; (*ret_sector_size) = cfg_sector_size; XD3_ASSERT (cfg_groups > 0 && cfg_groups <= DJW_MAX_GROUPS); XD3_ASSERT (cfg_groups == 1 || (cfg_sector_size >= DJW_SECTORSZ_MULT && cfg_sector_size <= DJW_SECTORSZ_MAX)); return 0; } static int xd3_encode_huff (xd3_stream *stream, djw_stream *h, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg) { int ret; usize_t groups, sector_size; bit_state bstate = BIT_STATE_ENCODE_INIT; xd3_output *in; int output_bits; usize_t input_bits; usize_t input_bytes; usize_t initial_offset = output->next; djw_weight real_freq[ALPHABET_SIZE]; uint8_t *gbest = NULL; uint8_t *gbest_mtf = NULL; input_bytes = djw_count_freqs (real_freq, input); input_bits = input_bytes * 8; XD3_ASSERT (input_bytes > 0); if ((ret = xd3_encode_howmany_groups (stream, cfg, input_bytes, & groups, & sector_size))) { return ret; } if (0) { regroup: /* Sometimes we dynamically decide there are too many groups. Arrive * here. */ output->next = initial_offset; xd3_bit_state_encode_init (& bstate); } /* Encode: # of groups (3 bits) */ if ((ret = xd3_encode_bits (stream, & output, & bstate, DJW_GROUP_BITS, groups-1))) { goto failure; } if (groups == 1) { /* Single Huffman group. */ usize_t code[ALPHABET_SIZE]; /* Codes */ uint8_t clen[ALPHABET_SIZE]; uint8_t prefix_mtfsym[ALPHABET_SIZE]; djw_prefix prefix; output_bits = djw_build_prefix (real_freq, clen, ALPHABET_SIZE, DJW_MAX_CODELEN); djw_build_codes (code, clen, ALPHABET_SIZE, DJW_MAX_CODELEN); if (output_bits + EFFICIENCY_BITS >= input_bits && ! cfg->inefficient) { goto nosecond; } /* Encode: prefix */ prefix.mtfsym = prefix_mtfsym; prefix.symbol = clen; prefix.scount = ALPHABET_SIZE; if ((ret = djw_encode_prefix (stream, & output, & bstate, & prefix))) { goto failure; } if (output_bits + (8 * output->next) + EFFICIENCY_BITS >= input_bits && ! cfg->inefficient) { goto nosecond; } /* Encode: data */ for (in = input; in; in = in->next_page) { const uint8_t *p = in->base; const uint8_t *p_max = p + in->next; do { usize_t sym = *p++; usize_t bits = clen[sym]; IF_DEBUG (output_bits -= bits); if ((ret = xd3_encode_bits (stream, & output, & bstate, bits, code[sym]))) { goto failure; } } while (p < p_max); } XD3_ASSERT (output_bits == 0); } else { /* DJW Huffman */ djw_weight evolve_freq[DJW_MAX_GROUPS][ALPHABET_SIZE]; uint8_t evolve_clen[DJW_MAX_GROUPS][ALPHABET_SIZE]; djw_weight left = input_bytes; usize_t gp; usize_t niter = 0; usize_t select_bits; usize_t sym1 = 0, sym2 = 0, s; usize_t gcost[DJW_MAX_GROUPS]; usize_t gbest_code[DJW_MAX_GROUPS+2]; uint8_t gbest_clen[DJW_MAX_GROUPS+2]; usize_t gbest_max = 1 + (input_bytes - 1) / sector_size; usize_t best_bits = 0; usize_t gbest_no; usize_t gpcnt; const uint8_t *p; IF_DEBUG2 (usize_t gcount[DJW_MAX_GROUPS]); /* Encode: sector size (5 bits) */ if ((ret = xd3_encode_bits (stream, & output, & bstate, DJW_SECTORSZ_BITS, (sector_size/DJW_SECTORSZ_MULT)-1))) { goto failure; } /* Dynamic allocation. */ if (gbest == NULL) { if ((gbest = (uint8_t*) xd3_alloc (stream, gbest_max, 1)) == NULL) { ret = ENOMEM; goto failure; } } if (gbest_mtf == NULL) { if ((gbest_mtf = (uint8_t*) xd3_alloc (stream, gbest_max, 1)) == NULL) { ret = ENOMEM; goto failure; } } /* OPT: Some of the inner loops can be optimized, as shown in bzip2 */ /* Generate initial code length tables. */ for (gp = 0; gp < groups; gp += 1) { djw_weight sum = 0; djw_weight goal = left / (groups - gp); IF_DEBUG2 (usize_t nz = 0); /* Due to the single-code granularity of this distribution, it may * be that we can't generate a distribution for each group. In that * case subtract one group and try again. If (inefficient), we're * testing group behavior, so don't mess things up. */ if (goal == 0 && !cfg->inefficient) { IF_DEBUG2 (DP(RINT "too many groups (%u), dropping one\n", groups)); groups -= 1; goto regroup; } /* Sum == goal is possible when (cfg->inefficient)... */ while (sum < goal) { XD3_ASSERT (sym2 < ALPHABET_SIZE); IF_DEBUG2 (nz += real_freq[sym2] != 0); sum += real_freq[sym2++]; } IF_DEBUG2(DP(RINT "group %u has symbols %u..%u (%u non-zero) " "(%u/%u = %.3f)\n", gp, sym1, sym2, nz, sum, input_bytes, sum / (double)input_bytes);); for (s = 0; s < ALPHABET_SIZE; s += 1) { evolve_clen[gp][s] = (s >= sym1 && s <= sym2) ? 1 : 16; } left -= sum; sym1 = sym2+1; } repeat: niter += 1; gbest_no = 0; memset (evolve_freq, 0, sizeof (evolve_freq[0]) * groups); IF_DEBUG2 (memset (gcount, 0, sizeof (gcount[0]) * groups)); /* For each input page (loop is irregular to allow non-pow2-size group * size. */ in = input; p = in->base; /* For each group-size sector. */ do { const uint8_t *p0 = p; xd3_output *in0 = in; usize_t best = 0; usize_t winner = 0; /* Select best group for each sector, update evolve_freq. */ memset (gcost, 0, sizeof (gcost[0]) * groups); /* For each byte in sector. */ for (gpcnt = 0; gpcnt < sector_size; gpcnt += 1) { /* For each group. */ for (gp = 0; gp < groups; gp += 1) { gcost[gp] += evolve_clen[gp][*p]; } /* Check end-of-input-page. */ # define GP_PAGE() \ if ((usize_t)(++p - in->base) == in->next) \ { \ in = in->next_page; \ if (in == NULL) { break; } \ p = in->base; \ } GP_PAGE (); } /* Find min cost group for this sector */ best = USIZE_T_MAX; for (gp = 0; gp < groups; gp += 1) { if (gcost[gp] < best) { best = gcost[gp]; winner = gp; } } XD3_ASSERT(gbest_no < gbest_max); gbest[gbest_no++] = winner; IF_DEBUG2 (gcount[winner] += 1); p = p0; in = in0; /* Update group frequencies. */ for (gpcnt = 0; gpcnt < sector_size; gpcnt += 1) { evolve_freq[winner][*p] += 1; GP_PAGE (); } } while (in != NULL); XD3_ASSERT (gbest_no == gbest_max); /* Recompute code lengths. */ output_bits = 0; for (gp = 0; gp < groups; gp += 1) { int i; uint8_t evolve_zero[ALPHABET_SIZE]; int any_zeros = 0; memset (evolve_zero, 0, sizeof (evolve_zero)); /* Cannot allow a zero clen when the real frequency is non-zero. * Note: this means we are going to encode a fairly long code for * these unused entries. An improvement would be to implement a * NOTUSED code for when these are actually zero, but this requires * another data structure (evolve_zero) since we don't know when * evolve_freq[i] == 0... Briefly tested, looked worse. */ for (i = 0; i < ALPHABET_SIZE; i += 1) { if (evolve_freq[gp][i] == 0 && real_freq[i] != 0) { evolve_freq[gp][i] = 1; evolve_zero[i] = 1; any_zeros = 1; } } output_bits += djw_build_prefix (evolve_freq[gp], evolve_clen[gp], ALPHABET_SIZE, DJW_MAX_CODELEN); /* The above faking of frequencies does not matter for the last * iteration, but we don't know when that is yet. However, it also * breaks the output_bits computation. Necessary for accuracy, and * for the (output_bits==0) assert after all bits are output. */ if (any_zeros) { IF_DEBUG2 (usize_t save_total = output_bits); for (i = 0; i < ALPHABET_SIZE; i += 1) { if (evolve_zero[i]) { output_bits -= evolve_clen[gp][i]; } } IF_DEBUG2 (DP(RINT "evolve_zero reduced %u bits in group %u\n", save_total - output_bits, gp)); } } IF_DEBUG2( DP(RINT "pass %u total bits: %u group uses: ", niter, output_bits); for (gp = 0; gp < groups; gp += 1) { DP(RINT "%u ", gcount[gp]); } DP(RINT "\n"); ); /* End iteration. */ IF_DEBUG2 (if (niter > 1 && best_bits < output_bits) { DP(RINT "iteration lost %u bits\n", output_bits - best_bits); }); if (niter == 1 || (niter < DJW_MAX_ITER && (best_bits - output_bits) >= DJW_MIN_IMPROVEMENT)) { best_bits = output_bits; goto repeat; } /* Efficiency check. */ if (output_bits + EFFICIENCY_BITS >= input_bits && ! cfg->inefficient) { goto nosecond; } IF_DEBUG2 (DP(RINT "djw compression: %u -> %0.3f\n", input_bytes, output_bits / 8.0)); /* Encode: prefix */ { uint8_t prefix_symbol[DJW_MAX_GROUPS * ALPHABET_SIZE]; uint8_t prefix_mtfsym[DJW_MAX_GROUPS * ALPHABET_SIZE]; uint8_t prefix_repcnt[DJW_MAX_GROUPS * ALPHABET_SIZE]; djw_prefix prefix; prefix.symbol = prefix_symbol; prefix.mtfsym = prefix_mtfsym; prefix.repcnt = prefix_repcnt; djw_compute_multi_prefix (groups, evolve_clen, & prefix); if ((ret = djw_encode_prefix (stream, & output, & bstate, & prefix))) { goto failure; } } /* Encode: selector frequencies */ { /* DJW_MAX_GROUPS +2 is for RUN_0, RUN_1 symbols. */ djw_weight gbest_freq[DJW_MAX_GROUPS+2]; djw_prefix gbest_prefix; usize_t i; gbest_prefix.scount = gbest_no; gbest_prefix.symbol = gbest; gbest_prefix.mtfsym = gbest_mtf; djw_compute_selector_1_2 (& gbest_prefix, groups, gbest_freq); select_bits = djw_build_prefix (gbest_freq, gbest_clen, groups+1, DJW_MAX_GBCLEN); djw_build_codes (gbest_code, gbest_clen, groups+1, DJW_MAX_GBCLEN); for (i = 0; i < groups+1; i += 1) { if ((ret = xd3_encode_bits (stream, & output, & bstate, DJW_GBCLEN_BITS, gbest_clen[i]))) { goto failure; } } for (i = 0; i < gbest_prefix.mcount; i += 1) { usize_t gp_mtf = gbest_mtf[i]; usize_t gp_sel_bits = gbest_clen[gp_mtf]; usize_t gp_sel_code = gbest_code[gp_mtf]; XD3_ASSERT (gp_mtf < groups+1); if ((ret = xd3_encode_bits (stream, & output, & bstate, gp_sel_bits, gp_sel_code))) { goto failure; } IF_DEBUG (select_bits -= gp_sel_bits); } XD3_ASSERT (select_bits == 0); } /* Efficiency check. */ if (output_bits + select_bits + (8 * output->next) + EFFICIENCY_BITS >= input_bits && ! cfg->inefficient) { goto nosecond; } /* Encode: data */ { usize_t evolve_code[DJW_MAX_GROUPS][ALPHABET_SIZE]; usize_t sector = 0; /* Build code tables for each group. */ for (gp = 0; gp < groups; gp += 1) { djw_build_codes (evolve_code[gp], evolve_clen[gp], ALPHABET_SIZE, DJW_MAX_CODELEN); } /* Now loop over the input. */ in = input; p = in->base; do { /* For each sector. */ usize_t gp_best = gbest[sector]; usize_t *gp_codes = evolve_code[gp_best]; uint8_t *gp_clens = evolve_clen[gp_best]; XD3_ASSERT (sector < gbest_no); sector += 1; /* Encode the sector data. */ for (gpcnt = 0; gpcnt < sector_size; gpcnt += 1) { usize_t sym = *p; usize_t bits = gp_clens[sym]; usize_t code = gp_codes[sym]; IF_DEBUG (output_bits -= bits); if ((ret = xd3_encode_bits (stream, & output, & bstate, bits, code))) { goto failure; } GP_PAGE (); } } while (in != NULL); XD3_ASSERT (select_bits == 0); XD3_ASSERT (output_bits == 0); } } ret = xd3_flush_bits (stream, & output, & bstate); if (0) { nosecond: stream->msg = "secondary compression was inefficient"; ret = XD3_NOSECOND; } failure: xd3_free (stream, gbest); xd3_free (stream, gbest_mtf); return ret; } #endif /* XD3_ENCODER */ /*********************************************************************/ /* DECODE */ /*********************************************************************/ static void djw_build_decoder (xd3_stream *stream, usize_t asize, usize_t abs_max, const uint8_t *clen, uint8_t *inorder, usize_t *base, usize_t *limit, usize_t *min_clenp, usize_t *max_clenp) { usize_t i, l; const uint8_t *ci; usize_t nr_clen [DJW_TOTAL_CODES]; usize_t tmp_base[DJW_TOTAL_CODES]; usize_t min_clen; usize_t max_clen; /* Assumption: the two temporary arrays are large enough to hold abs_max. */ XD3_ASSERT (abs_max <= DJW_MAX_CODELEN); /* This looks something like the start of zlib's inftrees.c */ memset (nr_clen, 0, sizeof (nr_clen[0]) * (abs_max+1)); /* Count number of each code length */ i = asize; ci = clen; do { /* Caller _must_ check that values are in-range. Most of the time the * caller decodes a specific number of bits, which imply the max value, * and the other time the caller decodes a huffman value, which must be * in-range. Therefore, its an assertion and this function cannot * otherwise fail. */ XD3_ASSERT (*ci <= abs_max); nr_clen[*ci++]++; } while (--i != 0); /* Compute min, max. */ for (i = 1; i <= abs_max; i += 1) { if (nr_clen[i]) { break; } } min_clen = i; for (i = abs_max; i != 0; i -= 1) { if (nr_clen[i]) { break; } } max_clen = i; /* Fill the BASE, LIMIT table. */ tmp_base[min_clen] = 0; base[min_clen] = 0; limit[min_clen] = nr_clen[min_clen] - 1; for (i = min_clen + 1; i <= max_clen; i += 1) { usize_t last_limit = ((limit[i-1] + 1) << 1); tmp_base[i] = tmp_base[i-1] + nr_clen[i-1]; limit[i] = last_limit + nr_clen[i] - 1; base[i] = last_limit - tmp_base[i]; } /* Fill the inorder array, canonically ordered codes. */ ci = clen; for (i = 0; i < asize; i += 1) { if ((l = *ci++) != 0) { inorder[tmp_base[l]++] = i; } } *min_clenp = min_clen; *max_clenp = max_clen; } static inline int djw_decode_symbol (xd3_stream *stream, bit_state *bstate, const uint8_t **input, const uint8_t *input_end, const uint8_t *inorder, const usize_t *base, const usize_t *limit, usize_t min_clen, usize_t max_clen, usize_t *sym, usize_t max_sym) { usize_t code = 0; usize_t bits = 0; /* OPT: Supposedly a small lookup table improves speed here... */ /* Code outline is similar to xd3_decode_bits... */ if (bstate->cur_mask == 0x100) { goto next_byte; } for (;;) { do { if (bits == max_clen) { goto corrupt; } bits += 1; code = (code << 1); if (bstate->cur_byte & bstate->cur_mask) { code |= 1; } bstate->cur_mask <<= 1; if (bits >= min_clen && code <= limit[bits]) { goto done; } } while (bstate->cur_mask != 0x100); next_byte: if (*input == input_end) { stream->msg = "secondary decoder end of input"; return XD3_INTERNAL; } bstate->cur_byte = *(*input)++; bstate->cur_mask = 1; } done: if (base[bits] <= code) { usize_t offset = code - base[bits]; if (offset <= max_sym) { IF_DEBUG2 (DP(RINT "(j) %u ", code)); *sym = inorder[offset]; return 0; } } corrupt: stream->msg = "secondary decoder invalid code"; return XD3_INTERNAL; } static int djw_decode_clclen (xd3_stream *stream, bit_state *bstate, const uint8_t **input, const uint8_t *input_end, uint8_t *cl_inorder, usize_t *cl_base, usize_t *cl_limit, usize_t *cl_minlen, usize_t *cl_maxlen, uint8_t *cl_mtf) { int ret; uint8_t cl_clen[DJW_TOTAL_CODES]; usize_t num_codes, value; usize_t i; /* How many extra code lengths to encode. */ if ((ret = xd3_decode_bits (stream, bstate, input, input_end, DJW_EXTRA_CODE_BITS, & num_codes))) { return ret; } num_codes += DJW_EXTRA_12OFFSET; /* Read num_codes. */ for (i = 0; i < num_codes; i += 1) { if ((ret = xd3_decode_bits (stream, bstate, input, input_end, DJW_CLCLEN_BITS, & value))) { return ret; } cl_clen[i] = value; } /* Set the rest to zero. */ for (; i < DJW_TOTAL_CODES; i += 1) { cl_clen[i] = 0; } /* No need to check for in-range clen values, because: */ XD3_ASSERT (1 << DJW_CLCLEN_BITS == DJW_MAX_CLCLEN + 1); /* Build the code-length decoder. */ djw_build_decoder (stream, DJW_TOTAL_CODES, DJW_MAX_CLCLEN, cl_clen, cl_inorder, cl_base, cl_limit, cl_minlen, cl_maxlen); /* Initialize the MTF state. */ djw_init_clen_mtf_1_2 (cl_mtf); return 0; } static inline int djw_decode_1_2 (xd3_stream *stream, bit_state *bstate, const uint8_t **input, const uint8_t *input_end, const uint8_t *inorder, const usize_t *base, const usize_t *limit, const usize_t *minlen, const usize_t *maxlen, uint8_t *mtfvals, usize_t elts, usize_t skip_offset, uint8_t *values) { usize_t n = 0, rep = 0, mtf = 0, s = 0; int ret; while (n < elts) { /* Special case inside generic code: CLEN only: If not the first group, * we already know the zero frequencies. */ if (skip_offset != 0 && n >= skip_offset && values[n-skip_offset] == 0) { values[n++] = 0; continue; } /* Repeat last symbol. */ if (rep != 0) { values[n++] = mtfvals[0]; rep -= 1; continue; } /* Symbol following last repeat code. */ if (mtf != 0) { usize_t sym = djw_update_mtf (mtfvals, mtf); values[n++] = sym; mtf = 0; continue; } /* Decode next symbol/repeat code. */ if ((ret = djw_decode_symbol (stream, bstate, input, input_end, inorder, base, limit, *minlen, *maxlen, & mtf, DJW_TOTAL_CODES))) { return ret; } if (mtf <= RUN_1) { /* Repetition. */ rep = ((mtf + 1) << s); mtf = 0; s += 1; } else { /* Remove the RUN_1 MTF offset. */ mtf -= 1; s = 0; } } /* If (rep != 0) there were too many codes received. */ if (rep != 0) { stream->msg = "secondary decoder invalid repeat code"; return XD3_INTERNAL; } return 0; } static inline int djw_decode_prefix (xd3_stream *stream, bit_state *bstate, const uint8_t **input, const uint8_t *input_end, const uint8_t *cl_inorder, const usize_t *cl_base, const usize_t *cl_limit, const usize_t *cl_minlen, const usize_t *cl_maxlen, uint8_t *cl_mtf, usize_t groups, uint8_t *clen) { return djw_decode_1_2 (stream, bstate, input, input_end, cl_inorder, cl_base, cl_limit, cl_minlen, cl_maxlen, cl_mtf, ALPHABET_SIZE * groups, ALPHABET_SIZE, clen); } static int xd3_decode_huff (xd3_stream *stream, djw_stream *h, const uint8_t **input_pos, const uint8_t *const input_end, uint8_t **output_pos, const uint8_t *const output_end) { const uint8_t *input = *input_pos; uint8_t *output = *output_pos; bit_state bstate = BIT_STATE_DECODE_INIT; uint8_t *sel_group = NULL; usize_t groups, gp; usize_t output_bytes = (usize_t)(output_end - output); usize_t sector_size; usize_t sectors; int ret; /* Invalid input. */ if (output_bytes == 0) { stream->msg = "secondary decoder invalid input"; return XD3_INTERNAL; } /* Decode: number of groups */ if ((ret = xd3_decode_bits (stream, & bstate, & input, input_end, DJW_GROUP_BITS, & groups))) { goto fail; } groups += 1; if (groups > 1) { /* Decode: group size */ if ((ret = xd3_decode_bits (stream, & bstate, & input, input_end, DJW_SECTORSZ_BITS, & sector_size))) { goto fail; } sector_size = (sector_size + 1) * DJW_SECTORSZ_MULT; } else { /* Default for groups == 1 */ sector_size = output_bytes; } sectors = 1 + (output_bytes - 1) / sector_size; /* TODO: In the case of groups==1, lots of extra stack space gets used here. * Could dynamically allocate this memory, which would help with excess * parameter passing, too. Passing too many parameters in this file, * simplify it! */ /* Outer scope: per-group symbol decoder tables. */ { uint8_t inorder[DJW_MAX_GROUPS][ALPHABET_SIZE]; usize_t base [DJW_MAX_GROUPS][DJW_TOTAL_CODES]; usize_t limit [DJW_MAX_GROUPS][DJW_TOTAL_CODES]; usize_t minlen [DJW_MAX_GROUPS]; usize_t maxlen [DJW_MAX_GROUPS]; /* Nested scope: code length decoder tables. */ { uint8_t clen [DJW_MAX_GROUPS][ALPHABET_SIZE]; uint8_t cl_inorder[DJW_TOTAL_CODES]; usize_t cl_base [DJW_MAX_CLCLEN+2]; usize_t cl_limit [DJW_MAX_CLCLEN+2]; uint8_t cl_mtf [DJW_TOTAL_CODES]; usize_t cl_minlen; usize_t cl_maxlen; /* Compute the code length decoder. */ if ((ret = djw_decode_clclen (stream, & bstate, & input, input_end, cl_inorder, cl_base, cl_limit, & cl_minlen, & cl_maxlen, cl_mtf))) { goto fail; } /* Now decode each group decoder. */ if ((ret = djw_decode_prefix (stream, & bstate, & input, input_end, cl_inorder, cl_base, cl_limit, & cl_minlen, & cl_maxlen, cl_mtf, groups, clen[0]))) { goto fail; } /* Prepare the actual decoding tables. */ for (gp = 0; gp < groups; gp += 1) { djw_build_decoder (stream, ALPHABET_SIZE, DJW_MAX_CODELEN, clen[gp], inorder[gp], base[gp], limit[gp], & minlen[gp], & maxlen[gp]); } } /* Decode: selector clens. */ { uint8_t sel_inorder[DJW_MAX_GROUPS+2]; usize_t sel_base [DJW_MAX_GBCLEN+2]; usize_t sel_limit [DJW_MAX_GBCLEN+2]; uint8_t sel_mtf [DJW_MAX_GROUPS+2]; usize_t sel_minlen; usize_t sel_maxlen; /* Setup group selection. */ if (groups > 1) { uint8_t sel_clen[DJW_MAX_GROUPS+1]; for (gp = 0; gp < groups+1; gp += 1) { usize_t value; if ((ret = xd3_decode_bits (stream, & bstate, & input, input_end, DJW_GBCLEN_BITS, & value))) { goto fail; } sel_clen[gp] = value; sel_mtf[gp] = gp; } if ((sel_group = (uint8_t*) xd3_alloc (stream, sectors, 1)) == NULL) { ret = ENOMEM; goto fail; } djw_build_decoder (stream, groups+1, DJW_MAX_GBCLEN, sel_clen, sel_inorder, sel_base, sel_limit, & sel_minlen, & sel_maxlen); if ((ret = djw_decode_1_2 (stream, & bstate, & input, input_end, sel_inorder, sel_base, sel_limit, & sel_minlen, & sel_maxlen, sel_mtf, sectors, 0, sel_group))) { goto fail; } } /* Now decode each sector. */ { /* Initialize for (groups==1) case. */ uint8_t *gp_inorder = inorder[0]; usize_t *gp_base = base[0]; usize_t *gp_limit = limit[0]; usize_t gp_minlen = minlen[0]; usize_t gp_maxlen = maxlen[0]; usize_t c; for (c = 0; c < sectors; c += 1) { usize_t n; if (groups >= 2) { gp = sel_group[c]; XD3_ASSERT (gp < groups); gp_inorder = inorder[gp]; gp_base = base[gp]; gp_limit = limit[gp]; gp_minlen = minlen[gp]; gp_maxlen = maxlen[gp]; } XD3_ASSERT (output_end - output > 0); /* Decode next sector. */ n = min (sector_size, (usize_t) (output_end - output)); do { usize_t sym; if ((ret = djw_decode_symbol (stream, & bstate, & input, input_end, gp_inorder, gp_base, gp_limit, gp_minlen, gp_maxlen, & sym, ALPHABET_SIZE))) { goto fail; } *output++ = sym; } while (--n); } } } } IF_REGRESSION (if ((ret = xd3_test_clean_bits (stream, & bstate))) { goto fail; }); XD3_ASSERT (ret == 0); fail: xd3_free (stream, sel_group); (*input_pos) = input; (*output_pos) = output; return ret; } #endif xdelta3-3.0.7/ltmain.sh0000755000176500017650000105017112102136770014174 0ustar debdevdebdev # libtool (GNU libtool) 2.4 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4 TIMESTAMP="" package_revision=1.3293 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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 BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${EGREP="grep -E"} : ${FGREP="grep -F"} : ${GREP="grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs 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 BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_apped perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 xdelta3-3.0.7/examples/0002755000176500017650000000000012144343472014171 5ustar debdevdebdevxdelta3-3.0.7/examples/encode_decode_test.c0000644000176500017650000001026312105354541020130 0ustar debdevdebdev// // Permission to distribute this example by // Copyright (C) 2007 Ralf Junker // Ralf Junker // http://www.yunqa.de/delphi/ //--------------------------------------------------------------------------- #include #include #include "xdelta3.h" #include "xdelta3.c" //--------------------------------------------------------------------------- int code ( int encode, FILE* InFile, FILE* SrcFile , FILE* OutFile, int BufSize ) { int r, ret; struct stat statbuf; xd3_stream stream; xd3_config config; xd3_source source; void* Input_Buf; int Input_Buf_Read; if (BufSize < XD3_ALLOCSIZE) BufSize = XD3_ALLOCSIZE; memset (&stream, 0, sizeof (stream)); memset (&source, 0, sizeof (source)); xd3_init_config(&config, XD3_ADLER32); config.winsize = BufSize; xd3_config_stream(&stream, &config); if (SrcFile) { r = fstat(fileno(SrcFile), &statbuf); if (r) return r; source.blksize = BufSize; source.curblk = malloc(source.blksize); /* Load 1st block of stream. */ r = fseek(SrcFile, 0, SEEK_SET); if (r) return r; source.onblk = fread((void*)source.curblk, 1, source.blksize, SrcFile); source.curblkno = 0; /* Set the stream. */ xd3_set_source(&stream, &source); } Input_Buf = malloc(BufSize); fseek(InFile, 0, SEEK_SET); do { Input_Buf_Read = fread(Input_Buf, 1, BufSize, InFile); if (Input_Buf_Read < BufSize) { xd3_set_flags(&stream, XD3_FLUSH | stream.flags); } xd3_avail_input(&stream, Input_Buf, Input_Buf_Read); process: if (encode) ret = xd3_encode_input(&stream); else ret = xd3_decode_input(&stream); switch (ret) { case XD3_INPUT: { fprintf (stderr,"XD3_INPUT\n"); continue; } case XD3_OUTPUT: { fprintf (stderr,"XD3_OUTPUT\n"); r = fwrite(stream.next_out, 1, stream.avail_out, OutFile); if (r != (int)stream.avail_out) return r; xd3_consume_output(&stream); goto process; } case XD3_GETSRCBLK: { fprintf (stderr,"XD3_GETSRCBLK %qd\n", source.getblkno); if (SrcFile) { r = fseek(SrcFile, source.blksize * source.getblkno, SEEK_SET); if (r) return r; source.onblk = fread((void*)source.curblk, 1, source.blksize, SrcFile); source.curblkno = source.getblkno; } goto process; } case XD3_GOTHEADER: { fprintf (stderr,"XD3_GOTHEADER\n"); goto process; } case XD3_WINSTART: { fprintf (stderr,"XD3_WINSTART\n"); goto process; } case XD3_WINFINISH: { fprintf (stderr,"XD3_WINFINISH\n"); goto process; } default: { fprintf (stderr,"!!! INVALID %s %d !!!\n", stream.msg, ret); return ret; } } } while (Input_Buf_Read == BufSize); free(Input_Buf); free((void*)source.curblk); xd3_close_stream(&stream); xd3_free_stream(&stream); return 0; }; int main(int argc, char* argv[]) { FILE* InFile; FILE* SrcFile; FILE* OutFile; int r; if (argc != 3) { fprintf (stderr, "usage: %s source input\n", argv[0]); return 1; } char *input = argv[2]; char *source = argv[1]; const char *output = "encoded.testdata"; const char *decoded = "decoded.testdata"; /* Encode */ InFile = fopen(input, "rb"); SrcFile = fopen(source, "rb"); OutFile = fopen(output, "wb"); r = code (1, InFile, SrcFile, OutFile, 0x1000); fclose(OutFile); fclose(SrcFile); fclose(InFile); if (r) { fprintf (stderr, "Encode error: %d\n", r); return r; } /* Decode */ InFile = fopen(output, "rb"); SrcFile = fopen(source, "rb"); OutFile = fopen(decoded, "wb"); r = code (0, InFile, SrcFile, OutFile, 0x1000); fclose(OutFile); fclose(SrcFile); fclose(InFile); if (r) { fprintf (stderr, "Decode error: %d\n", r); return r; } return 0; } xdelta3-3.0.7/examples/README0000644000176500017650000000060612105354541015045 0ustar debdevdebdevFiles in this directory demonstrate how to use the Xdelta3 API. Copyrights are held by the respective authors and these files are not covered by the GPL. small_page_test.c -- how to use xdelta3 in an environment such as the kernel for small pages with little memory encode_decode_test.c -- how to use xdelta3 to process (encode/decode) data in multiple windows with the non-blocking API xdelta3-3.0.7/examples/compare_test.c0000644000176500017650000000457612105354541017030 0ustar debdevdebdev#include #include #include #include #include #include "xdelta3.h" #define NUM (1<<20) #define ITERS 100 /* From wikipedia on RDTSC */ inline uint64_t rdtsc() { uint32_t lo, hi; asm volatile ("rdtsc" : "=a" (lo), "=d" (hi)); return (uint64_t)hi << 32 | lo; } typedef int (*test_func)(const char *s1, const char *s2, int n); void run_test(const char *buf1, const char *buf2, const char *name, test_func func) { uint64_t start, end; uint64_t accum = 0; int i, x; for (i = 0; i < ITERS; i++) { start = rdtsc(); x = func(buf1, buf2, NUM); end = rdtsc(); accum += end - start; assert(x == NUM - 1); } accum /= ITERS; printf("%s : %qu cycles\n", name, accum); } /* Build w/ -fno-builtin for this to be fast, this assumes that there * is a difference at s1[n-1] */ int memcmp_fake(const char *s1, const char *s2, int n) { int x = memcmp(s1, s2, n); return x < 0 ? n - 1 : n + 1; } #define UNALIGNED_OK 1 static inline int test2(const char *s1c, const char *s2c, int n) { int i = 0; #if UNALIGNED_OK int nint = n / sizeof(int); if (nint >> 3) { int j = 0; const int *s1 = (const int*)s1c; const int *s2 = (const int*)s2c; int nint_8 = nint - 8; while (i <= nint_8 && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++]) { } i = (i - 1) * sizeof(int); } #endif while (i < n && s1c[i] == s2c[i]) { i++; } return i; } static inline int test1(const char *s1c, const char *s2c, int n) { int i = 0; while (i < n && s1c[i] == s2c[i]) { i++; } return i; } int main(/*int argc, char **argv*/) { char *buf1 = malloc(NUM+1); char *buf2 = malloc(NUM+1); int i; for (i = 0; i < NUM; i++) { buf1[i] = buf2[i] = rand(); } buf2[NUM-1]++; printf ("ALIGNED\n"); run_test(buf1, buf2, "memcmp", &memcmp_fake); run_test(buf1, buf2, "test1", &test1); run_test(buf1, buf2, "test2", &test2); for (i = 0; i < NUM; i++) { buf1[i] = buf2[i+1] = rand(); } buf2[NUM]++; printf ("UNALIGNED\n"); run_test(buf1, buf2+1, "memcmp", &memcmp_fake); run_test(buf1, buf2+1, "test1", &test1); run_test(buf1, buf2+1, "test2", &test2); return 0; } xdelta3-3.0.7/examples/small_page_test.c0000755000176500017650000001045512105354541017502 0ustar debdevdebdev/* Copyright (C) 2007 Josh MacDonald */ #include #define PAGE_SIZE 4096 #define SPACE_MAX 131072 // how much memory per process #define OUTPUT_MAX 1024 // max size for output #define XD3_ALLOCSIZE 256 // internal size for various buffers #define IOPT_SIZE 128 // instruction buffer // SPACE_MAX of 32K is sufficient for most inputs with XD3_COMPLEVEL_1 // XD3_COMPLEVEL_9 requires about 4x more space than XD3_COMPLEVEL_1 #include "xdelta3.h" #include "xdelta3.c" typedef struct _context { uint8_t *buffer; int allocated; } context_t; static int max_allocated = 0; void* process_alloc (void* opaque, usize_t items, usize_t size) { context_t *ctx = (context_t*) opaque; usize_t t = items * size; void *ret; if (ctx->allocated + t > SPACE_MAX) { return NULL; } ret = ctx->buffer + ctx->allocated; ctx->allocated += t; return ret; } void process_free (void* opaque, void *ptr) { } int process_page (int is_encode, int (*func) (xd3_stream *), const uint8_t *input, usize_t input_size, const uint8_t *source, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { /* On my x86 this is 1072 of objects on the stack */ xd3_stream stream; xd3_config config; xd3_source src; context_t *ctx = calloc(SPACE_MAX, 1); int ret; memset (&config, 0, sizeof(config)); if (ctx == NULL) { printf("calloc failed\n"); return -1; } ctx->buffer = (uint8_t*)ctx; ctx->allocated = sizeof(*ctx); config.flags = flags; config.winsize = PAGE_SIZE; config.sprevsz = PAGE_SIZE; config.srcwin_maxsz = PAGE_SIZE; config.iopt_size = IOPT_SIZE; config.alloc = &process_alloc; config.freef = &process_free; config.opaque = (void*) ctx; src.blksize = PAGE_SIZE; src.onblk = PAGE_SIZE; src.curblk = source; src.curblkno = 0; if ((ret = xd3_config_stream (&stream, &config)) != 0 || (ret = xd3_set_source_and_size (&stream, &src, PAGE_SIZE)) != 0 || (ret = xd3_process_stream (is_encode, &stream, func, 1, input, input_size, output, output_size, output_size_max)) != 0) { if (stream.msg != NULL) { fprintf(stderr, "stream message: %s\n", stream.msg); } } xd3_free_stream (&stream); if (max_allocated < ctx->allocated) { max_allocated = ctx->allocated; fprintf(stderr, "max allocated %d\n", max_allocated); } free(ctx); return ret; } int test(int stride, int encode_flags) { uint8_t frompg[PAGE_SIZE]; uint8_t topg[PAGE_SIZE]; uint8_t output[OUTPUT_MAX]; uint8_t reout[PAGE_SIZE]; usize_t output_size; usize_t re_size; int i, j, ret; for (i = 0; i < PAGE_SIZE; i++) { topg[i] = frompg[i] = (rand() >> 3 ^ rand() >> 6 ^ rand() >> 9); } // change 1 byte every stride if (stride > 0) { for (j = stride; j <= PAGE_SIZE; j += stride) { topg[j - 1] ^= 0xff; } } if ((ret = process_page (1, xd3_encode_input, topg, PAGE_SIZE, frompg, output, &output_size, OUTPUT_MAX, encode_flags)) != 0) { fprintf (stderr, "encode failed: stride %u flags 0x%x\n", stride, encode_flags); return ret; } if ((ret = process_page (0, xd3_decode_input, output, output_size, frompg, reout, &re_size, PAGE_SIZE, 0)) != 0) { fprintf (stderr, "decode failed: stride %u output_size %u flags 0x%x\n", stride, output_size, encode_flags); return ret; } if (output_size > OUTPUT_MAX || re_size != PAGE_SIZE) { fprintf (stderr, "internal error: %u != %u\n", output_size, re_size); return -1; } for (i = 0; i < PAGE_SIZE; i++) { if (reout[i] != topg[i]) { fprintf (stderr, "encode-decode error: position %d\n", i); return -1; } } fprintf(stderr, "stride %d flags 0x%x size %u ", stride, encode_flags, output_size); fprintf(stderr, "%s\n", (ret == 0) ? "OK" : "FAIL"); return 0; } int main() { int stride; int level; for (level = 1; level < 10; level = (level == 1 ? 3 : level + 3)) { int lflag = level << XD3_COMPLEVEL_SHIFT; for (stride = 2; stride <= PAGE_SIZE; stride += 2) { test(stride, lflag); test(stride, lflag | XD3_SEC_DJW); } } return 0; } xdelta3-3.0.7/examples/speed_test.c0000644000176500017650000000345212105354541016472 0ustar debdevdebdev/* Copyright (C) 2007 Josh MacDonald */ #include "test.h" usize_t bench_speed(const uint8_t *from_buf, const size_t from_len, const uint8_t *to_buf, const size_t to_len, uint8_t *delta_buf, const size_t delta_alloc, int flags) { usize_t delta_size; int ret = xd3_encode_memory(to_buf, to_len, from_buf, from_len, delta_buf, &delta_size, delta_alloc, flags); if (ret != 0) { fprintf(stderr, "encode failure: %d: %s\n", ret, xd3_strerror(ret)); abort(); } return delta_size; } int main(int argc, char **argv) { int repeat, level; char *from, *to; uint8_t *from_buf = NULL, *to_buf = NULL, *delta_buf = NULL; size_t from_len = 0, to_len, delta_alloc, delta_size = 0; long start, finish; int i, ret; int flags; if (argc != 5) { fprintf(stderr, "usage: speed_test LEVEL COUNT FROM TO\n"); return 1; } level = atoi(argv[1]); repeat = atoi(argv[2]); from = argv[3]; to = argv[4]; flags = (level << XD3_COMPLEVEL_SHIFT) & XD3_COMPLEVEL_MASK; if ((strcmp(from, "null") != 0 && (ret = read_whole_file(from, &from_buf, &from_len))) || (ret = read_whole_file(to, &to_buf, &to_len))) { fprintf(stderr, "read_whole_file error\n"); goto exit; } delta_alloc = to_len * 11 / 10; delta_buf = main_malloc(delta_alloc); start = get_millisecs_now(); for (i = 0; i < repeat; ++i) { delta_size = bench_speed(from_buf, from_len, to_buf, to_len, delta_buf, delta_alloc, flags); } finish = get_millisecs_now(); fprintf(stderr, "STAT: encode %3.2f ms from %s to %s repeat %d %zdbit delta %zd\n", (double)(finish - start) / repeat, from, to, repeat, sizeof (xoff_t) * 8, delta_size); ret = 0; if (0) { exit: ret = 1; } main_free(to_buf); main_free(from_buf); main_free(delta_buf); return ret; } xdelta3-3.0.7/examples/checksum_test.cc0000644000176500017650000003623212105354541017341 0ustar debdevdebdev/* Copyright (C) 2007 Josh MacDonald */ extern "C" { #include "test.h" #include } #include #include #include #include using std::list; using std::map; using std::vector; // MLCG parameters // a, a* uint32_t good_32bit_values[] = { 1597334677U, // ... 741103597U, 887987685U, }; // a, a* uint64_t good_64bit_values[] = { 1181783497276652981ULL, 4292484099903637661ULL, 7664345821815920749ULL, // ... }; struct true_type { }; struct false_type { }; template int bitsof(); template<> int bitsof() { return 32; } template<> int bitsof() { return 64; } struct plain { int operator()(const uint8_t &c) { return c; } }; template struct hhash { // take "h" of the high-bits as a hash value for this // checksum, which are the most "distant" in terms of the // spectral test for the rabin_karp MLCG. For short windows, // the high bits aren't enough, XOR "mask" worth of these in. Word operator()(const Word& t, const int &h, const int &mask) { return (t >> h) ^ (t & mask); } }; template Word good_word(); template<> uint32_t good_word() { return good_32bit_values[0]; } template<> uint64_t good_word() { return good_64bit_values[0]; } // CLASSES #define SELF Word, CksumSize, CksumSkip, Permute, Hash, Compaction #define MEMBER template MEMBER struct cksum_params { typedef Word word_type; typedef Permute permute_type; typedef Hash hash_type; enum { cksum_size = CksumSize, cksum_skip = CksumSkip, compaction = Compaction, }; }; MEMBER struct rabin_karp { typedef Word word_type; typedef Permute permute_type; typedef Hash hash_type; enum { cksum_size = CksumSize, cksum_skip = CksumSkip, compaction = Compaction, }; // (a^cksum_size-1 c_0) + (a^cksum_size-2 c_1) ... rabin_karp() { multiplier = good_word(); powers = new Word[cksum_size]; powers[cksum_size - 1] = 1; for (int i = cksum_size - 2; i >= 0; i--) { powers[i] = powers[i + 1] * multiplier; } product = powers[0] * multiplier; } ~rabin_karp() { delete [] powers; } Word step(const uint8_t *ptr) { Word h = 0; for (int i = 0; i < cksum_size; i++) { h += permute_type()(ptr[i]) * powers[i]; } return h; } Word state0(const uint8_t *ptr) { incr_state = step(ptr); return incr_state; } Word incr(const uint8_t *ptr) { incr_state = multiplier * incr_state - product * permute_type()(ptr[-1]) + permute_type()(ptr[cksum_size - 1]); return incr_state; } Word *powers; Word product; Word multiplier; Word incr_state; }; MEMBER struct adler32_cksum { typedef Word word_type; typedef Permute permute_type; typedef Hash hash_type; enum { cksum_size = CksumSize, cksum_skip = CksumSkip, compaction = Compaction, }; Word step(const uint8_t *ptr) { return xd3_lcksum (ptr, cksum_size); } Word state0(const uint8_t *ptr) { incr_state = step(ptr); return incr_state; } Word incr(const uint8_t *ptr) { incr_state = xd3_large_cksum_update (incr_state, ptr - 1, cksum_size); return incr_state; } Word incr_state; }; // TESTS template struct file_stats { typedef list ptr_list; typedef Word word_type; typedef map table_type; typedef typename table_type::iterator table_iterator; typedef typename ptr_list::iterator ptr_iterator; int cksum_size; int cksum_skip; int unique; int unique_values; int count; table_type table; file_stats(int size, int skip) : cksum_size(size), cksum_skip(skip), unique(0), unique_values(0), count(0) { } void reset() { unique = 0; unique_values = 0; count = 0; table.clear(); } void update(const word_type &word, const uint8_t *ptr) { table_iterator t_i = table.find(word); count++; if (t_i == table.end()) { table.insert(make_pair(word, ptr_list())); } ptr_list &pl = table[word]; for (ptr_iterator p_i = pl.begin(); p_i != pl.end(); ++p_i) { if (memcmp(*p_i, ptr, cksum_size) == 0) { return; } } unique++; pl.push_back(ptr); } void freeze() { unique_values = table.size(); table.clear(); } }; struct test_result_base; static vector all_tests; struct test_result_base { virtual ~test_result_base() { } virtual void reset() = 0; virtual void print() = 0; virtual void get(const uint8_t* buf, const int buf_size, int iters) = 0; virtual void stat() = 0; virtual int count() = 0; virtual int dups() = 0; virtual double uniqueness() = 0; virtual double fullness() = 0; virtual double collisions() = 0; virtual double coverage() = 0; virtual double compression() = 0; virtual double time() = 0; virtual double score() = 0; virtual void set_score(double min_dups_frac, double min_time) = 0; virtual double total_time() = 0; virtual int total_count() = 0; virtual int total_dups() = 0; }; struct compare_h { bool operator()(test_result_base *a, test_result_base *b) { return a->score() < b->score(); } }; MEMBER struct test_result : public test_result_base { typedef Word word_type; typedef Permute permute_type; typedef Hash hash_type; enum { cksum_size = CksumSize, cksum_skip = CksumSkip, compaction = Compaction, }; const char *test_name; file_stats fstats; int test_size; int n_steps; int n_incrs; int s_bits; int s_mask; int t_entries; int h_bits; int h_buckets_full; double h_score; char *hash_table; long accum_millis; int accum_iters; // These are not reset double accum_time; int accum_count; int accum_dups; int accum_colls; int accum_size; test_result(const char *name) : test_name(name), fstats(cksum_size, cksum_skip), hash_table(NULL), accum_millis(0), accum_iters(0), accum_time(0.0), accum_count(0), accum_dups(0), accum_colls(0), accum_size(0) { all_tests.push_back(this); } ~test_result() { reset(); } void reset() { // size of file test_size = -1; // count n_steps = -1; n_incrs = -1; // four values used by new_table()/summarize_table() s_bits = -1; s_mask = -1; t_entries = -1; h_bits = -1; h_buckets_full = -1; accum_millis = 0; accum_iters = 0; fstats.reset(); // temporary if (hash_table) { delete(hash_table); hash_table = NULL; } } int count() { if (cksum_skip == 1) { return n_incrs; } else { return n_steps; } } int dups() { return fstats.count - fstats.unique; } int colls() { return fstats.unique - fstats.unique_values; } double uniqueness() { return 1.0 - (double) dups() / count(); } double fullness() { return (double) h_buckets_full / (1 << h_bits); } double collisions() { return (double) colls() / fstats.unique; } double coverage() { return (double) h_buckets_full / uniqueness() / count(); } double compression() { return 1.0 - coverage(); } double time() { return (double) accum_millis / accum_iters; } double score() { return h_score; } void set_score(double min_compression, double min_time) { h_score = (compression() - 0.99 * min_compression) * (time() - 0.99 * min_time); } double total_time() { return accum_time; } int total_count() { return accum_count; } int total_dups() { return accum_dups; } int total_colls() { return accum_dups; } void stat() { accum_time += time(); accum_count += count(); accum_dups += dups(); accum_colls += colls(); accum_size += test_size; } void print() { if (fstats.count != count()) { fprintf(stderr, "internal error: %d != %d\n", fstats.count, count()); abort(); } printf("%s: (%u#%u) count %u uniq %0.2f%% full %u (%0.4f%% coll %0.4f%%) covers %0.2f%% w/ 2^%d @ %.4f MB/s %u iters\n", test_name, cksum_size, cksum_skip, count(), 100.0 * uniqueness(), h_buckets_full, 100.0 * fullness(), 100.0 * collisions(), 100.0 * coverage(), h_bits, 0.001 * accum_iters * test_size / accum_millis, accum_iters); } int size_log2 (int slots) { int bits = bitsof() - 1; int i; for (i = 3; i <= bits; i += 1) { if (slots <= (1 << i)) { return i - compaction; } } return bits; } void new_table(int entries) { t_entries = entries; h_bits = size_log2(entries); int n = 1 << h_bits; s_bits = bitsof() - h_bits; s_mask = n - 1; hash_table = new char[n / 8]; memset(hash_table, 0, n / 8); } int get_table_bit(int i) { return hash_table[i/8] & (1 << i%8); } int set_table_bit(int i) { return hash_table[i/8] |= (1 << i%8); } void summarize_table() { int n = 1 << h_bits; int f = 0; for (int i = 0; i < n; i++) { if (get_table_bit(i)) { f++; } } h_buckets_full = f; } void get(const uint8_t* buf, const int buf_size, int test_iters) { rabin_karp test; //adler32_cksum test; hash_type hash; const uint8_t *ptr; const uint8_t *end; int last_offset; int periods; int stop; test_size = buf_size; last_offset = buf_size - cksum_size; if (last_offset < 0) { periods = 0; n_steps = 0; n_incrs = 0; stop = -cksum_size; } else { periods = last_offset / cksum_skip; n_steps = periods + 1; n_incrs = last_offset + 1; stop = last_offset - (periods + 1) * cksum_skip; } // Compute file stats once. if (fstats.unique_values == 0) { if (cksum_skip == 1) { for (int i = 0; i <= buf_size - cksum_size; i++) { fstats.update(hash(test.step(buf + i), s_bits, s_mask), buf + i); } } else { ptr = buf + last_offset; end = buf + stop; for (; ptr != end; ptr -= cksum_skip) { fstats.update(hash(test.step(ptr), s_bits, s_mask), ptr); } } fstats.freeze(); } long start_test = get_millisecs_now(); if (cksum_skip != 1) { new_table(n_steps); for (int i = 0; i < test_iters; i++) { ptr = buf + last_offset; end = buf + stop; for (; ptr != end; ptr -= cksum_skip) { set_table_bit(hash(test.step(ptr), s_bits, s_mask)); } } summarize_table(); } stop = buf_size - cksum_size + 1; if (stop < 0) { stop = 0; } if (cksum_skip == 1) { new_table(n_incrs); for (int i = 0; i < test_iters; i++) { ptr = buf; end = buf + stop; if (ptr != end) { set_table_bit(hash(test.state0(ptr++), s_bits, s_mask)); } for (; ptr != end; ptr++) { Word w = test.incr(ptr); assert(w == test.step(ptr)); set_table_bit(hash(w, s_bits, s_mask)); } } summarize_table(); } accum_iters += test_iters; accum_millis += get_millisecs_now() - start_test; } }; template void print_array(const char *tname) { printf("static const %s hash_multiplier[64] = {\n", tname); Word p = 1; for (int i = 0; i < 64; i++) { printf(" %uU,\n", p); p *= good_word(); } printf("};\n", tname); } int main(int argc, char** argv) { int i; uint8_t *buf = NULL; size_t buf_len = 0; int ret; if (argc <= 1) { fprintf(stderr, "usage: %s file ...\n", argv[0]); return 1; } //print_array("uint32_t"); #define TEST(T,Z,S,P,H,C) test_result,C> \ _ ## T ## _ ## Z ## _ ## S ## _ ## P ## _ ## H ## _ ## C \ (#T "_" #Z "_" #S "_" #P "_" #H "_" #C) #if 0 TEST(uint32_t, 4, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 2); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 3); /* x */ \ #endif #define TESTS(SKIP) \ TEST(uint32_t, 9, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 2); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 3) #define TESTS_ALL(SKIP) \ TEST(uint32_t, 3, SKIP, plain, hhash, 0); \ TEST(uint32_t, 3, SKIP, plain, hhash, 1); \ TEST(uint32_t, 4, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 2); /* x */ \ TEST(uint32_t, 4, SKIP, plain, hhash, 3); /* x */ \ TEST(uint32_t, 5, SKIP, plain, hhash, 0); \ TEST(uint32_t, 5, SKIP, plain, hhash, 1); \ TEST(uint32_t, 8, SKIP, plain, hhash, 0); \ TEST(uint32_t, 8, SKIP, plain, hhash, 1); \ TEST(uint32_t, 9, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 2); /* x */ \ TEST(uint32_t, 9, SKIP, plain, hhash, 3); /* x */ \ TEST(uint32_t, 11, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 11, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 13, SKIP, plain, hhash, 0); \ TEST(uint32_t, 13, SKIP, plain, hhash, 1); \ TEST(uint32_t, 15, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 15, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 16, SKIP, plain, hhash, 0); /* x */ \ TEST(uint32_t, 16, SKIP, plain, hhash, 1); /* x */ \ TEST(uint32_t, 21, SKIP, plain, hhash, 0); \ TEST(uint32_t, 21, SKIP, plain, hhash, 1); \ TEST(uint32_t, 34, SKIP, plain, hhash, 0); \ TEST(uint32_t, 34, SKIP, plain, hhash, 1); \ TEST(uint32_t, 55, SKIP, plain, hhash, 0); \ TEST(uint32_t, 55, SKIP, plain, hhash, 1) TESTS(1); // * // TESTS(2); // * // TESTS(3); // * // TESTS(5); // * // TESTS(8); // * // TESTS(9); // TESTS(11); // TESTS(13); // * TESTS(15); // TESTS(16); // TESTS(21); // * // TESTS(34); // * // TESTS(55); // * // TESTS(89); // * for (i = 1; i < argc; i++) { if ((ret = read_whole_file(argv[i], & buf, & buf_len))) { return 1; } fprintf(stderr, "file %s is %zu bytes\n", argv[i], buf_len); double min_time = -1.0; double min_compression = 0.0; for (vector::iterator i = all_tests.begin(); i != all_tests.end(); ++i) { test_result_base *test = *i; test->reset(); int iters = 100; long start_test = get_millisecs_now(); do { test->get(buf, buf_len, iters); iters *= 3; iters /= 2; } while (get_millisecs_now() - start_test < 2000); test->stat(); if (min_time < 0.0) { min_compression = test->compression(); min_time = test->time(); } if (min_time > test->time()) { min_time = test->time(); } if (min_compression > test->compression()) { min_compression = test->compression(); } test->print(); } // for (vector::iterator i = all_tests.begin(); // i != all_tests.end(); ++i) { // test_result_base *test = *i; // test->set_score(min_compression, min_time); // } // sort(all_tests.begin(), all_tests.end(), compare_h()); // for (vector::iterator i = all_tests.begin(); // i != all_tests.end(); ++i) { // test_result_base *test = *i; // test->print(); // } free(buf); buf = NULL; } return 0; } xdelta3-3.0.7/examples/test.h0000644000176500017650000000156612105354541015323 0ustar debdevdebdev/* Copyright (C) 2007 Josh MacDonald */ #define NOT_MAIN 1 #include "xdelta3.h" #include "xdelta3.c" static int read_whole_file(const char *name, uint8_t **buf_ptr, size_t *buf_len) { main_file file; int ret; xoff_t len; usize_t nread; main_file_init(&file); file.filename = name; ret = main_file_open(&file, name, XO_READ); if (ret != 0) { fprintf(stderr, "open failed\n"); goto exit; } ret = main_file_stat(&file, &len); if (ret != 0) { fprintf(stderr, "stat failed\n"); goto exit; } (*buf_len) = (size_t)len; (*buf_ptr) = (uint8_t*) main_malloc(*buf_len); ret = main_file_read(&file, *buf_ptr, *buf_len, &nread, "read failed"); if (ret == 0 && *buf_len == nread) { ret = 0; } else { fprintf(stderr, "invalid read\n"); ret = XD3_INTERNAL; } exit: main_file_cleanup(&file); return ret; } xdelta3-3.0.7/examples/Makefile0000755000176500017650000000175412105354541015635 0ustar debdevdebdevCFLAGS = -g -Wall -I.. -DXD3_DEBUG=1 -DNDEBUG=0 #CFLAGS = -O3 -Wall -I.. -DXD3_DEBUG=0 -fno-builtin -DNDEBUG=1 # -pg SOURCES = small_page_test.c encode_decode_test.c speed_test.c DEPS = ../*.h ../*.c *.h TARGETS = small_page_test encode_decode_test speed_test32 speed_test64 compare_test checksum_test all: $(TARGETS) small_page_test: small_page_test.c $(DEPS) $(CC) $(CFLAGS) small_page_test.c -o small_page_test -DXD3_USE_LARGEFILE64=0 -DSECONDARY_DJW=1 encode_decode_test: encode_decode_test.c $(DEPS) $(CC) $(CFLAGS) encode_decode_test.c -o encode_decode_test speed_test32: speed_test.c $(DEPS) $(CC) $(CFLAGS) -DXD3_USE_LARGEFILE64=0 speed_test.c -o speed_test32 speed_test64: speed_test.c $(DEPS) $(CC) $(CFLAGS) -DXD3_USE_LARGEFILE64=1 speed_test.c -o speed_test64 compare_test: compare_test.c $(CC) $(CFLAGS) compare_test.c -o compare_test checksum_test: checksum_test.cc $(CXX) $(CFLAGS) checksum_test.cc -o checksum_test clean: rm -r -f *.exe *.stackdump $(TARGETS) *.dSYM *~ xdelta3-3.0.7/examples/iOS/0002755000176500017650000000000012144343472014663 5ustar debdevdebdevxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/0002755000176500017650000000000012144343472017774 5ustar debdevdebdevxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test.xcodeproj/0002755000176500017650000000000012144343472025101 5ustar debdevdebdevxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test.xcodeproj/project.pbxproj0000644000176500017650000004565612105354541030167 0ustar debdevdebdev// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ B9001B65158D008900B9E855 /* xdelta3.c in Sources */ = {isa = PBXBuildFile; fileRef = B9001B63158D008900B9E855 /* xdelta3.c */; }; B9313C3C158D11BA001C1F28 /* file_v1_to_v2.bin in Resources */ = {isa = PBXBuildFile; fileRef = B9313C39158D11BA001C1F28 /* file_v1_to_v2.bin */; }; B9313C3D158D11BA001C1F28 /* file_v1.bin in Resources */ = {isa = PBXBuildFile; fileRef = B9313C3A158D11BA001C1F28 /* file_v1.bin */; }; B9313C3E158D11BA001C1F28 /* file_v2.bin in Resources */ = {isa = PBXBuildFile; fileRef = B9313C3B158D11BA001C1F28 /* file_v2.bin */; }; B9ADC6BF158CFD36007EF999 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9ADC6BE158CFD36007EF999 /* UIKit.framework */; }; B9ADC6C1158CFD36007EF999 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9ADC6C0158CFD36007EF999 /* Foundation.framework */; }; B9ADC6C3158CFD36007EF999 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9ADC6C2158CFD36007EF999 /* CoreGraphics.framework */; }; B9ADC6C9158CFD36007EF999 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B9ADC6C7158CFD36007EF999 /* InfoPlist.strings */; }; B9ADC6CB158CFD36007EF999 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B9ADC6CA158CFD36007EF999 /* main.m */; }; B9ADC6CF158CFD36007EF999 /* Xd3iOSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B9ADC6CE158CFD36007EF999 /* Xd3iOSAppDelegate.m */; }; B9ADC6D2158CFD36007EF999 /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9ADC6D0158CFD36007EF999 /* MainStoryboard_iPhone.storyboard */; }; B9ADC6D5158CFD36007EF999 /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B9ADC6D3158CFD36007EF999 /* MainStoryboard_iPad.storyboard */; }; B9ADC6D8158CFD36007EF999 /* Xd3iOSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B9ADC6D7158CFD36007EF999 /* Xd3iOSViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ B9001B56158D008900B9E855 /* xdelta3-blkcache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-blkcache.h"; path = "../../../../xdelta3-blkcache.h"; sourceTree = ""; }; B9001B57158D008900B9E855 /* xdelta3-cfgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-cfgs.h"; path = "../../../../xdelta3-cfgs.h"; sourceTree = ""; }; B9001B58158D008900B9E855 /* xdelta3-decode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-decode.h"; path = "../../../../xdelta3-decode.h"; sourceTree = ""; }; B9001B59158D008900B9E855 /* xdelta3-djw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-djw.h"; path = "../../../../xdelta3-djw.h"; sourceTree = ""; }; B9001B5A158D008900B9E855 /* xdelta3-fgk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-fgk.h"; path = "../../../../xdelta3-fgk.h"; sourceTree = ""; }; B9001B5B158D008900B9E855 /* xdelta3-hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-hash.h"; path = "../../../../xdelta3-hash.h"; sourceTree = ""; }; B9001B5C158D008900B9E855 /* xdelta3-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-internal.h"; path = "../../../../xdelta3-internal.h"; sourceTree = ""; }; B9001B5D158D008900B9E855 /* xdelta3-list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-list.h"; path = "../../../../xdelta3-list.h"; sourceTree = ""; }; B9001B5E158D008900B9E855 /* xdelta3-main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-main.h"; path = "../../../../xdelta3-main.h"; sourceTree = ""; }; B9001B5F158D008900B9E855 /* xdelta3-merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-merge.h"; path = "../../../../xdelta3-merge.h"; sourceTree = ""; }; B9001B60158D008900B9E855 /* xdelta3-python.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-python.h"; path = "../../../../xdelta3-python.h"; sourceTree = ""; }; B9001B61158D008900B9E855 /* xdelta3-second.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-second.h"; path = "../../../../xdelta3-second.h"; sourceTree = ""; }; B9001B62158D008900B9E855 /* xdelta3-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "xdelta3-test.h"; path = "../../../../xdelta3-test.h"; sourceTree = ""; }; B9001B63158D008900B9E855 /* xdelta3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xdelta3.c; path = ../../../../xdelta3.c; sourceTree = ""; }; B9001B64158D008900B9E855 /* xdelta3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xdelta3.h; path = ../../../../xdelta3.h; sourceTree = ""; }; B9313C39158D11BA001C1F28 /* file_v1_to_v2.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = file_v1_to_v2.bin; sourceTree = ""; }; B9313C3A158D11BA001C1F28 /* file_v1.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = file_v1.bin; sourceTree = ""; }; B9313C3B158D11BA001C1F28 /* file_v2.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = file_v2.bin; sourceTree = ""; }; B9ADC6BA158CFD36007EF999 /* xdelta3-ios-test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "xdelta3-ios-test.app"; sourceTree = BUILT_PRODUCTS_DIR; }; B9ADC6BE158CFD36007EF999 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; B9ADC6C0158CFD36007EF999 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; B9ADC6C2158CFD36007EF999 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; B9ADC6C6158CFD36007EF999 /* xdelta3-ios-test-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "xdelta3-ios-test-Info.plist"; sourceTree = ""; }; B9ADC6C8158CFD36007EF999 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; B9ADC6CA158CFD36007EF999 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; B9ADC6CC158CFD36007EF999 /* xdelta3-ios-test-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "xdelta3-ios-test-Prefix.pch"; sourceTree = ""; }; B9ADC6CD158CFD36007EF999 /* Xd3iOSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Xd3iOSAppDelegate.h; sourceTree = ""; }; B9ADC6CE158CFD36007EF999 /* Xd3iOSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Xd3iOSAppDelegate.m; sourceTree = ""; }; B9ADC6D1158CFD36007EF999 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; }; B9ADC6D4158CFD36007EF999 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; }; B9ADC6D6158CFD36007EF999 /* Xd3iOSViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Xd3iOSViewController.h; sourceTree = ""; }; B9ADC6D7158CFD36007EF999 /* Xd3iOSViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Xd3iOSViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ B9ADC6B7158CFD36007EF999 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( B9ADC6BF158CFD36007EF999 /* UIKit.framework in Frameworks */, B9ADC6C1158CFD36007EF999 /* Foundation.framework in Frameworks */, B9ADC6C3158CFD36007EF999 /* CoreGraphics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ B9ADC6AF158CFD36007EF999 = { isa = PBXGroup; children = ( B9ADC6C4158CFD36007EF999 /* xdelta3-ios-test */, B9ADC6BD158CFD36007EF999 /* Frameworks */, B9ADC6BB158CFD36007EF999 /* Products */, ); sourceTree = ""; }; B9ADC6BB158CFD36007EF999 /* Products */ = { isa = PBXGroup; children = ( B9ADC6BA158CFD36007EF999 /* xdelta3-ios-test.app */, ); name = Products; sourceTree = ""; }; B9ADC6BD158CFD36007EF999 /* Frameworks */ = { isa = PBXGroup; children = ( B9ADC6BE158CFD36007EF999 /* UIKit.framework */, B9ADC6C0158CFD36007EF999 /* Foundation.framework */, B9ADC6C2158CFD36007EF999 /* CoreGraphics.framework */, ); name = Frameworks; sourceTree = ""; }; B9ADC6C4158CFD36007EF999 /* xdelta3-ios-test */ = { isa = PBXGroup; children = ( B9001B56158D008900B9E855 /* xdelta3-blkcache.h */, B9001B57158D008900B9E855 /* xdelta3-cfgs.h */, B9001B58158D008900B9E855 /* xdelta3-decode.h */, B9001B59158D008900B9E855 /* xdelta3-djw.h */, B9001B5A158D008900B9E855 /* xdelta3-fgk.h */, B9001B5B158D008900B9E855 /* xdelta3-hash.h */, B9001B5C158D008900B9E855 /* xdelta3-internal.h */, B9001B5D158D008900B9E855 /* xdelta3-list.h */, B9001B5E158D008900B9E855 /* xdelta3-main.h */, B9001B5F158D008900B9E855 /* xdelta3-merge.h */, B9001B60158D008900B9E855 /* xdelta3-python.h */, B9001B61158D008900B9E855 /* xdelta3-second.h */, B9001B62158D008900B9E855 /* xdelta3-test.h */, B9001B63158D008900B9E855 /* xdelta3.c */, B9001B64158D008900B9E855 /* xdelta3.h */, B9ADC6CD158CFD36007EF999 /* Xd3iOSAppDelegate.h */, B9ADC6CE158CFD36007EF999 /* Xd3iOSAppDelegate.m */, B9ADC6D0158CFD36007EF999 /* MainStoryboard_iPhone.storyboard */, B9ADC6D3158CFD36007EF999 /* MainStoryboard_iPad.storyboard */, B9ADC6D6158CFD36007EF999 /* Xd3iOSViewController.h */, B9ADC6D7158CFD36007EF999 /* Xd3iOSViewController.m */, B9ADC6C5158CFD36007EF999 /* Supporting Files */, ); path = "xdelta3-ios-test"; sourceTree = ""; }; B9ADC6C5158CFD36007EF999 /* Supporting Files */ = { isa = PBXGroup; children = ( B9313C39158D11BA001C1F28 /* file_v1_to_v2.bin */, B9313C3A158D11BA001C1F28 /* file_v1.bin */, B9313C3B158D11BA001C1F28 /* file_v2.bin */, B9ADC6C6158CFD36007EF999 /* xdelta3-ios-test-Info.plist */, B9ADC6C7158CFD36007EF999 /* InfoPlist.strings */, B9ADC6CA158CFD36007EF999 /* main.m */, B9ADC6CC158CFD36007EF999 /* xdelta3-ios-test-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ B9ADC6B9158CFD36007EF999 /* xdelta3-ios-test */ = { isa = PBXNativeTarget; buildConfigurationList = B9ADC6DB158CFD36007EF999 /* Build configuration list for PBXNativeTarget "xdelta3-ios-test" */; buildPhases = ( B9ADC6B6158CFD36007EF999 /* Sources */, B9ADC6B7158CFD36007EF999 /* Frameworks */, B9ADC6B8158CFD36007EF999 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "xdelta3-ios-test"; productName = "xdelta3-ios-test"; productReference = B9ADC6BA158CFD36007EF999 /* xdelta3-ios-test.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ B9ADC6B1158CFD36007EF999 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0420; }; buildConfigurationList = B9ADC6B4158CFD36007EF999 /* Build configuration list for PBXProject "xdelta3-ios-test" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = B9ADC6AF158CFD36007EF999; productRefGroup = B9ADC6BB158CFD36007EF999 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B9ADC6B9158CFD36007EF999 /* xdelta3-ios-test */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ B9ADC6B8158CFD36007EF999 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( B9ADC6C9158CFD36007EF999 /* InfoPlist.strings in Resources */, B9ADC6D2158CFD36007EF999 /* MainStoryboard_iPhone.storyboard in Resources */, B9ADC6D5158CFD36007EF999 /* MainStoryboard_iPad.storyboard in Resources */, B9313C3C158D11BA001C1F28 /* file_v1_to_v2.bin in Resources */, B9313C3D158D11BA001C1F28 /* file_v1.bin in Resources */, B9313C3E158D11BA001C1F28 /* file_v2.bin in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ B9ADC6B6158CFD36007EF999 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( B9ADC6CB158CFD36007EF999 /* main.m in Sources */, B9ADC6CF158CFD36007EF999 /* Xd3iOSAppDelegate.m in Sources */, B9ADC6D8158CFD36007EF999 /* Xd3iOSViewController.m in Sources */, B9001B65158D008900B9E855 /* xdelta3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ B9ADC6C7158CFD36007EF999 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( B9ADC6C8158CFD36007EF999 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; B9ADC6D0158CFD36007EF999 /* MainStoryboard_iPhone.storyboard */ = { isa = PBXVariantGroup; children = ( B9ADC6D1158CFD36007EF999 /* en */, ); name = MainStoryboard_iPhone.storyboard; sourceTree = ""; }; B9ADC6D3158CFD36007EF999 /* MainStoryboard_iPad.storyboard */ = { isa = PBXVariantGroup; children = ( B9ADC6D4158CFD36007EF999 /* en */, ); name = MainStoryboard_iPad.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ B9ADC6D9158CFD36007EF999 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_INPUT_FILETYPE = sourcecode.c.objc; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "XD3_USE_LARGEFILE64=0", "XD3_POSIX=1", "EXTERNAL_COMPRESSION=0", "NOT_MAIN=1", "XD3_MAIN=1", "SECONDARY_DJW=1", "XD3_DEBUG=1", "REGRESSION_TEST=1", "SHELL_TESTS=0", "SECONDARY_FGK=1", "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; OTHER_CFLAGS = ( "-DXD3_USE_LARGEFILE64=0", "-DXD3_POSIX=1", "-DEXTERNAL_COMPRESSION=0", "-DNOT_MAIN=1", "-DXD3_MAIN=1", "-DSECONDARY_DJW=1", "-DXD3_DEBUG=1", "-DREGRESSION_TEST=1", "-DSHELL_TESTS=0", "-DSECONDARY_FGK=1", ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; B9ADC6DA158CFD36007EF999 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; CLANG_ENABLE_OBJC_ARC = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_INPUT_FILETYPE = sourcecode.c.objc; GCC_PREPROCESSOR_DEFINITIONS = ( "XD3_USE_LARGEFILE64=0", "XD3_POSIX=1", "EXTERNAL_COMPRESSION=0", "NOT_MAIN=1", "XD3_MAIN=1", "SECONDARY_DJW=1", "XD3_DEBUG=1", "REGRESSION_TEST=1", "SHELL_TESTS=0", "SECONDARY_FGK=1", ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; OTHER_CFLAGS = ( "-DXD3_USE_LARGEFILE64=0", "-DXD3_POSIX=1", "-DEXTERNAL_COMPRESSION=0", "-DNOT_MAIN=1", "-DXD3_MAIN=1", "-DSECONDARY_DJW=1", "-DXD3_DEBUG=1", "-DREGRESSION_TEST=1", "-DSHELL_TESTS=0", "-DSECONDARY_FGK=1", ); SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; B9ADC6DC158CFD36007EF999 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "xdelta3-ios-test/xdelta3-ios-test-Prefix.pch"; INFOPLIST_FILE = "xdelta3-ios-test/xdelta3-ios-test-Info.plist"; OTHER_CFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; B9ADC6DD158CFD36007EF999 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "xdelta3-ios-test/xdelta3-ios-test-Prefix.pch"; INFOPLIST_FILE = "xdelta3-ios-test/xdelta3-ios-test-Info.plist"; OTHER_CFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ B9ADC6B4158CFD36007EF999 /* Build configuration list for PBXProject "xdelta3-ios-test" */ = { isa = XCConfigurationList; buildConfigurations = ( B9ADC6D9158CFD36007EF999 /* Debug */, B9ADC6DA158CFD36007EF999 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; B9ADC6DB158CFD36007EF999 /* Build configuration list for PBXNativeTarget "xdelta3-ios-test" */ = { isa = XCConfigurationList; buildConfigurations = ( B9ADC6DC158CFD36007EF999 /* Debug */, B9ADC6DD158CFD36007EF999 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = B9ADC6B1158CFD36007EF999 /* Project object */; } xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/0002755000176500017650000000000012144343472023105 5ustar debdevdebdevxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Info.plist0000644000176500017650000000326012105354541030157 0ustar debdevdebdev CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFiles CFBundleIdentifier Joshua-MacDonald.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UIMainStoryboardFile MainStoryboard_iPhone UIMainStoryboardFile~ipad MainStoryboard_iPad UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.h0000644000176500017650000000103712105354541027221 0ustar debdevdebdev// // Xd3iOSViewController.h // xdelta3-ios-test // // Created by Joshua MacDonald on 6/16/12. // Copyright (c) 2011, 2012 Joshua MacDonald. All rights reserved. // #import @interface Xd3iOSViewController : UIViewController { NSString *inputSeed; } - (IBAction)startTest:(id)sender; @property (weak, nonatomic) IBOutlet UITextField *theSeed; @property (weak, nonatomic) IBOutlet UITextView *theView; @property (atomic, retain) NSMutableString *theOutput; @property (nonatomic) BOOL inTest; @end xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.h0000644000176500017650000000047212105354541026420 0ustar debdevdebdev// // Xd3iOSAppDelegate.h // xdelta3-ios-test // // Created by Joshua MacDonald on 6/16/12. // Copyright (c) 2011, 2012 Joshua MacDonald. All rights reserved. // #import @interface Xd3iOSAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1.bin0000644000176500017650000013474712105354541025136 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* To know more about Xdelta, start by reading xdelta3.c. If you are * ready to use the API, continue reading here. There are two * interfaces -- xd3_encode_input and xd3_decode_input -- plus a dozen * or so related calls. This interface is styled after Zlib. */ #ifndef _XDELTA3_H_ #define _XDELTA3_H_ #include #include #include #include /****************************************************************/ /* Default configured value of stream->winsize. If the program * supplies xd3_encode_input() with data smaller than winsize the * stream will automatically buffer the input, otherwise the input * buffer is used directly. */ #ifndef XD3_DEFAULT_WINSIZE #define XD3_DEFAULT_WINSIZE (1U << 23) #endif /* Default total size of the source window used in xdelta3-main.h */ #ifndef XD3_DEFAULT_SRCWINSZ #define XD3_DEFAULT_SRCWINSZ (1U << 26) #endif /* When Xdelta requests a memory allocation for certain buffers, it * rounds up to units of at least this size. The code assumes (and * asserts) that this is a power-of-two. */ #ifndef XD3_ALLOCSIZE #define XD3_ALLOCSIZE (1U<<14) #endif /* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect * decoders against malicious files. The decoder will never decode a * window larger than this. If the file specifies VCD_TARGET the * decoder may require two buffers of this size. * * 8-16MB is reasonable, probably don't need to go larger. */ #ifndef XD3_HARDMAXWINSIZE #define XD3_HARDMAXWINSIZE (1U<<24) #endif /* The IOPT_SIZE value sets the size of a buffer used to batch * overlapping copy instructions before they are optimized by picking * the best non-overlapping ranges. The larger this buffer, the * longer a forced xd3_srcwin_setup() decision is held off. Setting * this value to 0 causes an unlimited buffer to be used. */ #ifndef XD3_DEFAULT_IOPT_SIZE #define XD3_DEFAULT_IOPT_SIZE (1U<<15) #endif /* The maximum distance backward to search for small matches */ #ifndef XD3_DEFAULT_SPREVSZ #define XD3_DEFAULT_SPREVSZ (1U<<18) #endif /* The default compression level */ #ifndef XD3_DEFAULT_LEVEL #define XD3_DEFAULT_LEVEL 3 #endif #ifndef XD3_DEFAULT_SECONDARY_LEVEL #define XD3_DEFAULT_SECONDARY_LEVEL 6 #endif #ifndef XD3_USE_LARGEFILE64 #define XD3_USE_LARGEFILE64 1 #endif /* Sizes and addresses within VCDIFF windows are represented as usize_t * * For source-file offsets and total file sizes, total input and * output counts, the xoff_t type is used. The decoder and encoder * generally check for overflow of the xoff_t size (this is tested at * the 32bit boundary [xdelta3-test.h]). */ #ifndef _WIN32 #include typedef unsigned int usize_t; #else #define WIN32_LEAN_AND_MEAN #if XD3_USE_LARGEFILE64 /* 64 bit file offsets: uses GetFileSizeEx and SetFilePointerEx. * requires Win2000 or newer version of WinNT */ #define WINVER 0x0500 #define _WIN32_WINNT 0x0500 #else /* 32 bit (DWORD) file offsets: uses GetFileSize and * SetFilePointer. compatible with win9x-me and WinNT4 */ #define WINVER 0x0400 #define _WIN32_WINNT 0x0400 #endif #include typedef unsigned int usize_t; #ifdef _MSC_VER #define inline typedef signed int ssize_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; typedef ULONGLONG uint64_t; #else /* mingw32, lcc and watcom provide a proper header */ #include #endif #endif /* TODO: note that SIZEOF_USIZE_T is never set to 8, although it should be for * a 64bit platform. OTOH, may be that using 32bits is appropriate even on a * 64bit platform because we allocate large arrays of these values. */ #if XD3_USE_LARGEFILE64 #define __USE_FILE_OFFSET64 1 /* GLIBC: for 64bit fileops, ... ? */ #ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif typedef uint64_t xoff_t; #define SIZEOF_XOFF_T 8 #define SIZEOF_USIZE_T 4 #ifndef WIN32 #define Q "ll" #else #define Q "I64" #endif #else typedef uint32_t xoff_t; #define SIZEOF_XOFF_T 4 #define SIZEOF_USIZE_T 4 #define Q #endif #define USE_UINT32 (SIZEOF_USIZE_T == 4 || \ SIZEOF_XOFF_T == 4 || REGRESSION_TEST) #define USE_UINT64 (SIZEOF_USIZE_T == 8 || \ SIZEOF_XOFF_T == 8 || REGRESSION_TEST) /* TODO: probably should do something better here. */ #ifndef UNALIGNED_OK #if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ defined(__i686__) || defined(_X86_) || defined(__x86_64__) #define UNALIGNED_OK 1 #else #define UNALIGNED_OK 0 #endif #endif /**********************************************************************/ /* Whether to build the encoder, otherwise only build the decoder. */ #ifndef XD3_ENCODER #define XD3_ENCODER 1 #endif /* The code returned when main() fails, also defined in system includes. */ #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif /* REGRESSION TEST enables the "xdelta3 test" command, which runs a series of self-tests. */ #ifndef REGRESSION_TEST #define REGRESSION_TEST 0 #endif /* XD3_DEBUG=1 enables assertions and various statistics. Levels > 1 * enable some additional output only useful during development and * debugging. */ #ifndef XD3_DEBUG #define XD3_DEBUG 0 #endif #ifndef PYTHON_MODULE #define PYTHON_MODULE 0 #endif #ifndef SWIG_MODULE #define SWIG_MODULE 0 #endif /* There are three string matching functions supplied: one fast, one * slow (default), and one soft-configurable. To disable any of * these, use the following definitions. */ #ifndef XD3_BUILD_SLOW #define XD3_BUILD_SLOW 1 #endif #ifndef XD3_BUILD_FAST #define XD3_BUILD_FAST 1 #endif #ifndef XD3_BUILD_FASTER #define XD3_BUILD_FASTER 1 #endif #ifndef XD3_BUILD_FASTEST #define XD3_BUILD_FASTEST 1 #endif #ifndef XD3_BUILD_SOFT #define XD3_BUILD_SOFT 1 #endif #ifndef XD3_BUILD_DEFAULT #define XD3_BUILD_DEFAULT 1 #endif #if XD3_DEBUG #include #endif /* XPRINT. Debug output and VCDIFF_TOOLS functions report to stderr. * I have used an irregular style to abbreviate [fprintf(stderr, "] as * [DP(RINT "]. */ #define DP fprintf #define RINT stderr, typedef struct _xd3_stream xd3_stream; typedef struct _xd3_source xd3_source; typedef struct _xd3_hash_cfg xd3_hash_cfg; typedef struct _xd3_smatcher xd3_smatcher; typedef struct _xd3_rinst xd3_rinst; typedef struct _xd3_dinst xd3_dinst; typedef struct _xd3_hinst xd3_hinst; typedef struct _xd3_winst xd3_winst; typedef struct _xd3_rpage xd3_rpage; typedef struct _xd3_addr_cache xd3_addr_cache; typedef struct _xd3_output xd3_output; typedef struct _xd3_desect xd3_desect; typedef struct _xd3_iopt_buflist xd3_iopt_buflist; typedef struct _xd3_rlist xd3_rlist; typedef struct _xd3_sec_type xd3_sec_type; typedef struct _xd3_sec_cfg xd3_sec_cfg; typedef struct _xd3_sec_stream xd3_sec_stream; typedef struct _xd3_config xd3_config; typedef struct _xd3_code_table_desc xd3_code_table_desc; typedef struct _xd3_code_table_sizes xd3_code_table_sizes; typedef struct _xd3_slist xd3_slist; typedef struct _xd3_whole_state xd3_whole_state; typedef struct _xd3_wininfo xd3_wininfo; /* The stream configuration has three callbacks functions, all of * which may be supplied with NULL values. If config->getblk is * provided as NULL, the stream returns XD3_GETSRCBLK. */ typedef void* (xd3_alloc_func) (void *opaque, usize_t items, usize_t size); typedef void (xd3_free_func) (void *opaque, void *address); typedef int (xd3_getblk_func) (xd3_stream *stream, xd3_source *source, xoff_t blkno); /* These are internal functions to delay construction of encoding * tables and support alternate code tables. See the comments & code * enabled by GENERIC_ENCODE_TABLES. */ typedef const xd3_dinst* (xd3_code_table_func) (void); typedef int (xd3_comp_table_func) (xd3_stream *stream, const uint8_t **data, usize_t *size); #if XD3_DEBUG #define XD3_ASSERT(x) \ do { if (! (x)) { DP(RINT "%s:%d: XD3 assertion failed: %s\n", __FILE__, __LINE__, #x); \ abort (); } } while (0) #else #define XD3_ASSERT(x) (void)0 #endif /* XD3_DEBUG */ #ifdef __GNUC__ #ifndef max #define max(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x > _y ? _x : _y; }) #endif /* __GNUC__ */ #ifndef min #define min(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x < _y ? _x : _y; }) #endif #else /* __GNUC__ */ #ifndef max #define max(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef min #define min(x,y) ((x) < (y) ? (x) : (y)) #endif #endif /* __GNUC__ */ /**************************************************************** PUBLIC ENUMS ******************************************************************/ /* These are the five ordinary status codes returned by the * xd3_encode_input() and xd3_decode_input() state machines. */ typedef enum { /* An application must be prepared to handle these five return * values from either xd3_encode_input or xd3_decode_input, except * in the case of no-source compression, in which case XD3_GETSRCBLK * is never returned. More detailed comments for these are given in * xd3_encode_input and xd3_decode_input comments, below. */ XD3_INPUT = -17703, /* need input */ XD3_OUTPUT = -17704, /* have output */ XD3_GETSRCBLK = -17705, /* need a block of source input (with no * xd3_getblk function), a chance to do * non-blocking read. */ XD3_GOTHEADER = -17706, /* (decode-only) after the initial VCDIFF & first window header */ XD3_WINSTART = -17707, /* notification: returned before a window is * processed, giving a chance to * XD3_SKIP_WINDOW or not XD3_SKIP_EMIT that * window. */ XD3_WINFINISH = -17708, /* notification: returned after encode/decode & output for a window */ XD3_TOOFARBACK = -17709, /* (encoder only) may be returned by getblk() if the block is too old */ XD3_INTERNAL = -17710, /* internal error */ XD3_INVALID = -17711, /* invalid config */ XD3_INVALID_INPUT = -17712, /* invalid input/decoder error */ XD3_NOSECOND = -17713, /* when secondary compression finds no improvement. */ XD3_UNIMPLEMENTED = -17714, /* currently VCD_TARGET */ } xd3_rvalues; /* special values in config->flags */ typedef enum { XD3_JUST_HDR = (1 << 1), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_SKIP_WINDOW = (1 << 2), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_SKIP_EMIT = (1 << 3), /* used by VCDIFF tools, see xdelta3-main.h. */ XD3_FLUSH = (1 << 4), /* flush the stream buffer to prepare for xd3_stream_close(). */ XD3_SEC_DJW = (1 << 5), /* use DJW static huffman */ XD3_SEC_FGK = (1 << 6), /* use FGK adaptive huffman */ XD3_SEC_TYPE = (XD3_SEC_DJW | XD3_SEC_FGK), XD3_SEC_NODATA = (1 << 7), /* disable secondary compression of the data section. */ XD3_SEC_NOINST = (1 << 8), /* disable secondary compression of the inst section. */ XD3_SEC_NOADDR = (1 << 9), /* disable secondary compression of the addr section. */ XD3_SEC_NOALL = (XD3_SEC_NODATA | XD3_SEC_NOINST | XD3_SEC_NOADDR), XD3_ADLER32 = (1 << 10), /* enable checksum computation in the encoder. */ XD3_ADLER32_NOVER = (1 << 11), /* disable checksum verification in the decoder. */ XD3_ALT_CODE_TABLE = (1 << 12), /* for testing th e alternate code table encoding. */ XD3_NOCOMPRESS = (1 << 13), /* disable ordinary data * compression feature, only search * the source, not the target. */ XD3_BEGREEDY = (1 << 14), /* disable the "1.5-pass * algorithm", instead use greedy * matching. Greedy is off by * default. */ XD3_ADLER32_RECODE = (1 << 15), /* used by "recode". */ /* 4 bits to set the compression level the same as the command-line * setting -1 through -9 (-0 corresponds to the XD3_NOCOMPRESS flag, * and is independent of compression level). This is for * convenience, especially with xd3_encode_memory(). */ XD3_COMPLEVEL_SHIFT = 20, /* 20 - 24 */ XD3_COMPLEVEL_MASK = (0xF << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_1 = (1 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_2 = (2 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_3 = (3 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_6 = (6 << XD3_COMPLEVEL_SHIFT), XD3_COMPLEVEL_9 = (9 << XD3_COMPLEVEL_SHIFT), } xd3_flags; /* The values of this enumeration are set in xd3_config using the * smatch_cfg variable. It can be set to default, slow, fast, etc., * and soft. */ typedef enum { XD3_SMATCH_DEFAULT = 0, /* Flags may contain XD3_COMPLEVEL bits, else default. */ XD3_SMATCH_SLOW = 1, XD3_SMATCH_FAST = 2, XD3_SMATCH_FASTER = 3, XD3_SMATCH_FASTEST = 4, XD3_SMATCH_SOFT = 5, } xd3_smatch_cfg; /********************************************************************* PRIVATE ENUMS **********************************************************************/ /* stream->match_state is part of the xd3_encode_input state machine * for source matching: * * 1. the XD3_GETSRCBLK block-read mechanism means reentrant matching * 2. this state spans encoder windows: a match and end-of-window * will continue in the next 3. the initial target byte and source * byte are a presumed match, to avoid some computation in case the * inputs are identical. */ typedef enum { MATCH_TARGET = 0, /* in this state, attempt to match the start of * the target with the previously set source * address (initially 0). */ MATCH_BACKWARD = 1, /* currently expanding a match backward in the source/target. */ MATCH_FORWARD = 2, /* currently expanding a match forward in the source/target. */ MATCH_SEARCHING = 3, /* currently searching for a match. */ } xd3_match_state; /* The xd3_encode_input state machine steps through these states in * the following order. The matcher is reentrant and returns * XD3_INPUT whenever it requires more data. After receiving * XD3_INPUT, if the application reads EOF it should call * xd3_stream_close(). */ typedef enum { ENC_INIT = 0, /* xd3_encode_input has never been called. */ ENC_INPUT = 1, /* waiting for xd3_avail_input () to be called. */ ENC_SEARCH = 2, /* currently searching for matches. */ ENC_INSTR = 3, /* currently formatting output. */ ENC_FLUSH = 4, /* currently emitting output. */ ENC_POSTOUT = 5, /* after an output section. */ ENC_POSTWIN = 6, /* after all output sections. */ ENC_ABORTED = 7, /* abort. */ } xd3_encode_state; /* The xd3_decode_input state machine steps through these states in * the following order. The matcher is reentrant and returns * XD3_INPUT whenever it requires more data. After receiving * XD3_INPUT, if the application reads EOF it should call * xd3_stream_close(). * * 0-8: the VCDIFF header * 9-18: the VCDIFF window header * 19-21: the three primary sections: data, inst, addr * 22: producing output: returns XD3_OUTPUT, possibly XD3_GETSRCBLK, * 23: return XD3_WINFINISH, set state=9 to decode more input */ typedef enum { DEC_VCHEAD = 0, /* VCDIFF header */ DEC_HDRIND = 1, /* header indicator */ DEC_SECONDID = 2, /* secondary compressor ID */ DEC_TABLEN = 3, /* code table length */ DEC_NEAR = 4, /* code table near */ DEC_SAME = 5, /* code table same */ DEC_TABDAT = 6, /* code table data */ DEC_APPLEN = 7, /* application data length */ DEC_APPDAT = 8, /* application data */ DEC_WININD = 9, /* window indicator */ DEC_CPYLEN = 10, /* copy window length */ DEC_CPYOFF = 11, /* copy window offset */ DEC_ENCLEN = 12, /* length of delta encoding */ DEC_TGTLEN = 13, /* length of target window */ DEC_DELIND = 14, /* delta indicator */ DEC_DATALEN = 15, /* length of ADD+RUN data */ DEC_INSTLEN = 16, /* length of instruction data */ DEC_ADDRLEN = 17, /* length of address data */ DEC_CKSUM = 18, /* window checksum */ DEC_DATA = 19, /* data section */ DEC_INST = 20, /* instruction section */ DEC_ADDR = 21, /* address section */ DEC_EMIT = 22, /* producing data */ DEC_FINISH = 23, /* window finished */ DEC_ABORTED = 24, /* xd3_abort_stream */ } xd3_decode_state; /************************************************************ internal types ************************************************************/ /* instruction lists used in the IOPT buffer */ struct _xd3_rlist { xd3_rlist *next; xd3_rlist *prev; }; /* the raw encoding of an instruction used in the IOPT buffer */ struct _xd3_rinst { uint8_t type; uint8_t xtra; uint8_t code1; uint8_t code2; usize_t pos; usize_t size; xoff_t addr; xd3_rlist link; }; /* the code-table form of an single- or double-instruction */ struct _xd3_dinst { uint8_t type1; uint8_t size1; uint8_t type2; uint8_t size2; }; /* the decoded form of a single (half) instruction. */ struct _xd3_hinst { uint8_t type; uint32_t size; /* TODO: why decode breaks if this is usize_t? */ uint32_t addr; /* TODO: why decode breaks if this is usize_t? */ }; /* the form of a whole-file instruction */ struct _xd3_winst { uint8_t type; /* RUN, ADD, COPY */ uint8_t mode; /* 0, VCD_SOURCE, VCD_TARGET */ usize_t size; xoff_t addr; xoff_t position; /* absolute position of this inst */ }; /* used by the encoder to buffer output in sections. list of blocks. */ struct _xd3_output { uint8_t *base; usize_t next; usize_t avail; xd3_output *next_page; }; /* used by the decoder to buffer input in sections. */ struct _xd3_desect { const uint8_t *buf; const uint8_t *buf_max; uint32_t size; /* TODO: why decode breaks if this is usize_t? */ usize_t pos; /* used in xdelta3-decode.h */ uint8_t *copied1; usize_t alloc1; /* used in xdelta3-second.h */ uint8_t *copied2; usize_t alloc2; }; /* the VCDIFF address cache, see the RFC */ struct _xd3_addr_cache { usize_t s_near; usize_t s_same; usize_t next_slot; /* the circular index for near */ usize_t *near_array; /* array of size s_near */ usize_t *same_array; /* array of size s_same*256 */ }; /* the IOPT buffer list is just a list of buffers, which may be allocated * during encode when using an unlimited buffer. */ struct _xd3_iopt_buflist { xd3_rinst *buffer; xd3_iopt_buflist *next; }; /* This is the record of a pre-compiled configuration, a subset of xd3_config. */ struct _xd3_smatcher { const char *name; int (*string_match) (xd3_stream *stream); usize_t large_look; usize_t large_step; usize_t small_look; usize_t small_chain; usize_t small_lchain; usize_t max_lazy; usize_t long_enough; }; /* hash table size & power-of-two hash function. */ struct _xd3_hash_cfg { usize_t size; usize_t shift; usize_t mask; }; /* the sprev list */ struct _xd3_slist { usize_t last_pos; }; /* window info (for whole state) */ struct _xd3_wininfo { xoff_t offset; usize_t length; uint32_t adler32; }; /* whole state for, e.g., merge */ struct _xd3_whole_state { usize_t addslen; uint8_t *adds; usize_t adds_alloc; usize_t instlen; xd3_winst *inst; usize_t inst_alloc; usize_t wininfolen; xd3_wininfo *wininfo; usize_t wininfo_alloc; xoff_t length; }; /******************************************************************** public types *******************************************************************/ /* Settings for the secondary compressor. */ struct _xd3_sec_cfg { int data_type; /* Which section. (set automatically) */ usize_t ngroups; /* Number of DJW Huffman groups. */ usize_t sector_size; /* Sector size. */ int inefficient; /* If true, ignore efficiency check [avoid XD3_NOSECOND]. */ }; /* This is the user-visible stream configuration. */ struct _xd3_config { usize_t winsize; /* The encoder window size. */ usize_t sprevsz; /* How far back small string matching goes */ usize_t iopt_size; /* entries in the instruction-optimizing buffer */ usize_t srcwin_maxsz; /* srcwin_size grows by a factor of 2 when no matches are found. encoder will not seek back further than this. */ xd3_getblk_func *getblk; /* The three callbacks. */ xd3_alloc_func *alloc; xd3_free_func *freef; void *opaque; /* Not used. */ int flags; /* stream->flags are initialized * from xd3_config & never * modified by the library. Use * xd3_set_flags to modify flags * settings mid-stream. */ xd3_sec_cfg sec_data; /* Secondary compressor config: data */ xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ xd3_smatch_cfg smatch_cfg; /* See enum: use fields below for soft config */ xd3_smatcher smatcher_soft; }; /* The primary source file object. You create one of these objects and * initialize the first four fields. This library maintains the next * 5 fields. The configured getblk implementation is responsible for * setting the final 3 fields when called (and/or when XD3_GETSRCBLK * is returned). */ struct _xd3_source { /* you set */ usize_t blksize; /* block size */ const char *name; /* its name, for debug/print purposes */ void *ioh; /* opaque handle */ /* getblk sets */ xoff_t curblkno; /* current block number: client sets after getblk request */ usize_t onblk; /* number of bytes on current block: client sets, must be >= 0 and <= blksize */ const uint8_t *curblk; /* current block array: client sets after getblk request */ /* xd3 sets */ usize_t srclen; /* length of this source window */ xoff_t srcbase; /* offset of this source window in the source itself */ int shiftby; /* for power-of-two blocksizes */ int maskby; /* for power-of-two blocksizes */ xoff_t cpyoff_blocks; /* offset of dec_cpyoff in blocks */ usize_t cpyoff_blkoff; /* offset of copy window in blocks, remainder */ xoff_t getblkno; /* request block number: xd3 sets current getblk request */ /* See xd3_getblk() */ xoff_t max_blkno; /* Maximum block, if eof is known, * otherwise, equals frontier_blkno * (initially 0). */ xoff_t frontier_blkno; /* If eof is unknown, the next * source position to be read. * Otherwise, equal to * max_blkno. */ usize_t onlastblk; /* Number of bytes on max_blkno */ int eof_known; /* Set to true when the first * partial block is read. */ }; /* The primary xd3_stream object, used for encoding and decoding. You * may access only two fields: avail_out, next_out. Use the methods * above to operate on xd3_stream. */ struct _xd3_stream { /* input state */ const uint8_t *next_in; /* next input byte */ usize_t avail_in; /* number of bytes available at next_in */ xoff_t total_in; /* how many bytes in */ /* output state */ uint8_t *next_out; /* next output byte */ usize_t avail_out; /* number of bytes available at next_out */ usize_t space_out; /* total out space */ xoff_t current_window; /* number of windows encoded/decoded */ xoff_t total_out; /* how many bytes out */ /* to indicate an error, xd3 sets */ const char *msg; /* last error message, NULL if no error */ /* source configuration */ xd3_source *src; /* source array */ /* encoder memory configuration */ usize_t winsize; /* suggested window size */ usize_t sprevsz; /* small string, previous window size (power of 2) */ usize_t sprevmask; /* small string, previous window size mask */ usize_t iopt_size; usize_t iopt_unlimited; usize_t srcwin_maxsz; /* general configuration */ xd3_getblk_func *getblk; /* set nxtblk, nxtblkno to scanblkno */ xd3_alloc_func *alloc; /* malloc function */ xd3_free_func *free; /* free function */ void* opaque; /* private data object passed to alloc, free, and getblk */ int flags; /* various options */ /* secondary compressor configuration */ xd3_sec_cfg sec_data; /* Secondary compressor config: data */ xd3_sec_cfg sec_inst; /* Secondary compressor config: inst */ xd3_sec_cfg sec_addr; /* Secondary compressor config: addr */ xd3_smatcher smatcher; usize_t *large_table; /* table of large checksums */ xd3_hash_cfg large_hash; /* large hash config */ usize_t *small_table; /* table of small checksums */ xd3_slist *small_prev; /* table of previous offsets, circular linked list */ int small_reset; /* true if small table should be reset */ xd3_hash_cfg small_hash; /* small hash config */ xd3_addr_cache acache; /* the vcdiff address cache */ xd3_encode_state enc_state; /* state of the encoder */ usize_t taroff; /* base offset of the target input */ usize_t input_position; /* current input position */ usize_t min_match; /* current minimum match length, avoids redundent matches */ usize_t unencoded_offset; /* current input, first * unencoded offset. this value * is <= the first instruction's * position in the iopt buffer, * if there is at least one * match in the buffer. */ // SRCWIN // these variables plus srcwin_maxsz above (set by config) int srcwin_decided; /* boolean: true if srclen and srcbase have been decided. */ int srcwin_decided_early; /* boolean: true if srclen and srcbase were decided early. */ xoff_t srcwin_cksum_pos; /* Source checksum position */ // MATCH xd3_match_state match_state; /* encoder match state */ xoff_t match_srcpos; /* current match source position relative to srcbase */ xoff_t match_last_srcpos; /* previously attempted * srcpos, to avoid loops. */ xoff_t match_minaddr; /* smallest matching address to * set window params (reset each * window xd3_encode_reset) */ xoff_t match_maxaddr; /* largest matching address to * set window params (reset each * window xd3_encode_reset) */ usize_t match_back; /* match extends back so far */ usize_t match_maxback; /* match extends back maximum */ usize_t match_fwd; /* match extends forward so far */ usize_t match_maxfwd; /* match extends forward maximum */ xoff_t maxsrcaddr; /* address of the last source match (across windows) */ uint8_t *buf_in; /* for saving buffered input */ usize_t buf_avail; /* amount of saved input */ const uint8_t *buf_leftover; /* leftover content of next_in (i.e., user's buffer) */ usize_t buf_leftavail; /* amount of leftover content */ xd3_output *enc_current; /* current output buffer */ xd3_output *enc_free; /* free output buffers */ xd3_output *enc_heads[4]; /* array of encoded outputs: head of chain */ xd3_output *enc_tails[4]; /* array of encoded outputs: tail of chain */ uint32_t recode_adler32; /* set the adler32 checksum * during "recode". */ xd3_rlist iopt_used; /* instruction optimizing buffer */ xd3_rlist iopt_free; xd3_rinst *iout; /* next single instruction */ xd3_iopt_buflist *iopt_alloc; const uint8_t *enc_appheader; /* application header to encode */ usize_t enc_appheadsz; /* application header size */ /* decoder stuff */ xd3_decode_state dec_state; /* current DEC_XXX value */ usize_t dec_hdr_ind; /* VCDIFF header indicator */ usize_t dec_win_ind; /* VCDIFF window indicator */ usize_t dec_del_ind; /* VCDIFF delta indicator */ uint8_t dec_magic[4]; /* First four bytes */ usize_t dec_magicbytes; /* Magic position. */ usize_t dec_secondid; /* Optional secondary compressor ID. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_codetblsz; /* Optional code table: length. */ uint8_t *dec_codetbl; /* Optional code table: storage. */ usize_t dec_codetblbytes; /* Optional code table: position. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_appheadsz; /* Optional application header: size. */ uint8_t *dec_appheader; /* Optional application header: storage */ usize_t dec_appheadbytes; /* Optional application header: position. */ usize_t dec_cksumbytes; /* Optional checksum: position. */ uint8_t dec_cksum[4]; /* Optional checksum: storage. */ uint32_t dec_adler32; /* Optional checksum: value. */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_cpylen; /* length of copy window (VCD_SOURCE or VCD_TARGET) */ xoff_t dec_cpyoff; /* offset of copy window (VCD_SOURCE or VCD_TARGET) */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_enclen; /* length of delta encoding */ /* TODO: why decode breaks if this is usize_t? */ uint32_t dec_tgtlen; /* length of target window */ #if USE_UINT64 uint64_t dec_64part; /* part of a decoded uint64_t */ #endif #if USE_UINT32 uint32_t dec_32part; /* part of a decoded uint32_t */ #endif xoff_t dec_winstart; /* offset of the start of current target window */ xoff_t dec_window_count; /* == current_window + 1 in DEC_FINISH */ usize_t dec_winbytes; /* bytes of the three sections so far consumed */ usize_t dec_hdrsize; /* VCDIFF + app header size */ const uint8_t *dec_tgtaddrbase; /* Base of decoded target addresses (addr >= dec_cpylen). */ const uint8_t *dec_cpyaddrbase; /* Base of decoded copy addresses (addr < dec_cpylen). */ usize_t dec_position; /* current decoder position counting the cpylen offset */ usize_t dec_maxpos; /* maximum decoder position counting the cpylen offset */ xd3_hinst dec_current1; /* current instruction */ xd3_hinst dec_current2; /* current instruction */ uint8_t *dec_buffer; /* Decode buffer */ uint8_t *dec_lastwin; /* In case of VCD_TARGET, the last target window. */ usize_t dec_lastlen; /* length of the last target window */ xoff_t dec_laststart; /* offset of the start of last target window */ usize_t dec_lastspace; /* allocated space of last target window, for reuse */ xd3_desect inst_sect; /* staging area for decoding window sections */ xd3_desect addr_sect; xd3_desect data_sect; xd3_code_table_func *code_table_func; xd3_comp_table_func *comp_table_func; const xd3_dinst *code_table; const xd3_code_table_desc *code_table_desc; xd3_dinst *code_table_alloc; /* secondary compression */ const xd3_sec_type *sec_type; xd3_sec_stream *sec_stream_d; xd3_sec_stream *sec_stream_i; xd3_sec_stream *sec_stream_a; /* state for reconstructing whole files (e.g., for merge), this only * supports loading USIZE_T_MAX instructions, adds, etc. */ xd3_whole_state whole_target; /* statistics */ xoff_t n_scpy; xoff_t n_tcpy; xoff_t n_add; xoff_t n_run; xoff_t l_scpy; xoff_t l_tcpy; xoff_t l_add; xoff_t l_run; usize_t i_slots_used; #if XD3_DEBUG usize_t large_ckcnt; /* memory usage */ usize_t alloc_cnt; usize_t free_cnt; #endif }; /************************************************************************** PUBLIC FUNCTIONS **************************************************************************/ /* This function configures an xd3_stream using the provided in-memory * input buffer, source buffer, output buffer, and flags. The output * array must be large enough or else ENOSPC will be returned. This * is the simplest in-memory encoding interface. */ int xd3_encode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buffer, usize_t *output_size, usize_t avail_output, int flags); /* The reverse of xd3_encode_memory. */ int xd3_decode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output_buf, usize_t *output_size, usize_t avail_output, int flags); /* This function encodes an in-memory input using a pre-configured * xd3_stream. This allows the caller to set a variety of options * which are not available in the xd3_encode/decode_memory() * functions. * * The output array must be large enough to hold the output or else * ENOSPC is returned. The source (if any) should be set using * xd3_set_source_and_size() with a single-block xd3_source. This * calls the underlying non-blocking interfaces, * xd3_encode/decode_input(), handling the necessary input/output * states. This method may be considered a reference for any * application using xd3_encode_input() directly. * * xd3_stream stream; * xd3_config config; * xd3_source src; * * memset (& src, 0, sizeof (src)); * memset (& stream, 0, sizeof (stream)); * memset (& config, 0, sizeof (config)); * * if (source != NULL) * { * src.size = source_size; * src.blksize = source_size; * src.curblkno = 0; * src.onblk = source_size; * src.curblk = source; * xd3_set_source(&stream, &src); * } * * config.flags = flags; * config.srcwin_maxsz = source_size; * config.winsize = input_size; * * ... set smatcher, appheader, encoding-table, compression-level, etc. * * xd3_config_stream(&stream, &config); * xd3_encode_stream(&stream, ...); * xd3_free_stream(&stream); */ int xd3_encode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t avail_output); /* The reverse of xd3_encode_stream. */ int xd3_decode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t avail_size); /* This is the non-blocking interface. * * Handling input and output states is the same for encoding or * decoding using the xd3_avail_input() and xd3_consume_output() * routines, inlined below. * * Return values: * * XD3_INPUT: the process requires more input: call * xd3_avail_input() then repeat * * XD3_OUTPUT: the process has more output: read stream->next_out, * stream->avail_out, then call xd3_consume_output(), * then repeat * * XD3_GOTHEADER: (decoder-only) notification returned following the * VCDIFF header and first window header. the decoder * may use the header to configure itself. * * XD3_WINSTART: a general notification returned once for each * window except the 0-th window, which is implied by * XD3_GOTHEADER. It is recommended to use a * switch-stmt such as: * * ... * again: * switch ((ret = xd3_decode_input (stream))) { * case XD3_GOTHEADER: { * assert(stream->current_window == 0); * stuff; * } * // fallthrough * case XD3_WINSTART: { * something(stream->current_window); * goto again; * } * ... * * XD3_WINFINISH: a general notification, following the complete * input & output of a window. at this point, * stream->total_in and stream->total_out are consistent * for either encoding or decoding. * * XD3_GETSRCBLK: If the xd3_getblk() callback is NULL, this value * is returned to initiate a non-blocking source read. */ int xd3_decode_input (xd3_stream *stream); int xd3_encode_input (xd3_stream *stream); /* The xd3_config structure is used to initialize a stream - all data * is copied into stream so config may be a temporary variable. See * the [documentation] or comments on the xd3_config structure. */ int xd3_config_stream (xd3_stream *stream, xd3_config *config); /* Since Xdelta3 doesn't open any files, xd3_close_stream is just an * error check that the stream is in a proper state to be closed: this * means the encoder is flushed and the decoder is at a window * boundary. The application is responsible for freeing any of the * resources it supplied. */ int xd3_close_stream (xd3_stream *stream); /* This arranges for closes the stream to succeed. Does not free the * stream.*/ void xd3_abort_stream (xd3_stream *stream); /* xd3_free_stream frees all memory allocated for the stream. The * application is responsible for freeing any of the resources it * supplied. */ void xd3_free_stream (xd3_stream *stream); /* This function informs the encoder or decoder that source matching * (i.e., delta-compression) is possible. For encoding, this should * be called before the first xd3_encode_input. A NULL source is * ignored. For decoding, this should be called before the first * window is decoded, but the appheader may be read first * (XD3_GOTHEADER). After decoding the header, call xd3_set_source() * if you have a source file. Note: if (stream->dec_win_ind & VCD_SOURCE) * is true, it means the first window expects there to be a source file. */ int xd3_set_source (xd3_stream *stream, xd3_source *source); /* If the source size is known, call this instead of xd3_set_source(). * to avoid having stream->getblk called (and/or to avoid XD3_GETSRCBLK). * * Follow these steps: xd3_source source; memset(&source, 0, sizeof(source)); source.blksize = size; source.onblk = size; source.curblk = buf; source.curblkno = 0; int ret = xd3_set_source_and_size(&stream, &source, size); ... */ int xd3_set_source_and_size (xd3_stream *stream, xd3_source *source, xoff_t source_size); /* This should be called before the first call to xd3_encode_input() * to include application-specific data in the VCDIFF header. */ void xd3_set_appheader (xd3_stream *stream, const uint8_t *data, usize_t size); /* xd3_get_appheader may be called in the decoder after XD3_GOTHEADER. * For convenience, the decoder always adds a single byte padding to * the end of the application header, which is set to zero in case the * application header is a string. */ int xd3_get_appheader (xd3_stream *stream, uint8_t **data, usize_t *size); /* To generate a VCDIFF encoded delta with xd3_encode_init() from * another format, use: * * xd3_encode_init_partial() -- initialze encoder state (w/o hash tables) * xd3_init_cache() -- reset VCDIFF address cache * xd3_found_match() -- to report a copy instruction * * set stream->enc_state to ENC_INSTR and call xd3_encode_input as usual. */ int xd3_encode_init_partial (xd3_stream *stream); void xd3_init_cache (xd3_addr_cache* acache); int xd3_found_match (xd3_stream *stream, usize_t pos, usize_t size, xoff_t addr, int is_source); /* Gives an error string for xdelta3-speficic errors, returns NULL for system errors */ const char* xd3_strerror (int ret); /* For convenience, zero & initialize the xd3_config structure with specified flags. */ static inline void xd3_init_config (xd3_config *config, int flags) { memset (config, 0, sizeof (*config)); config->flags = flags; } /* This supplies some input to the stream. * * For encoding, if the input is larger than the configured window * size (xd3_config.winsize), the entire input will be consumed and * encoded anyway. If you wish to strictly limit the window size, * limit the buffer passed to xd3_avail_input to the window size. * * For encoding, if the input is smaller than the configured window * size (xd3_config.winsize), the library will create a window-sized * buffer and accumulate input until a full-sized window can be * encoded. XD3_INPUT will be returned. The input must remain valid * until the next time xd3_encode_input() returns XD3_INPUT. * * For decoding, the input will be consumed entirely before XD3_INPUT * is returned again. */ static inline void xd3_avail_input (xd3_stream *stream, const uint8_t *idata, usize_t isize) { /* Even if isize is zero, the code expects a non-NULL idata. Why? * It uses this value to determine whether xd3_avail_input has ever * been called. If xd3_encode_input is called before * xd3_avail_input it will return XD3_INPUT right away without * allocating a stream->winsize buffer. This is to avoid an * unwanted allocation. */ XD3_ASSERT (idata != NULL || isize == 0); stream->next_in = idata; stream->avail_in = isize; } /* This acknowledges receipt of output data, must be called after any * XD3_OUTPUT return. */ static inline void xd3_consume_output (xd3_stream *stream) { stream->avail_out = 0; } /* These are set for each XD3_WINFINISH return. */ static inline int xd3_encoder_used_source (xd3_stream *stream) { return stream->src != NULL && stream->src->srclen > 0; } static inline xoff_t xd3_encoder_srcbase (xd3_stream *stream) { return stream->src->srcbase; } static inline usize_t xd3_encoder_srclen (xd3_stream *stream) { return stream->src->srclen; } /* Checks for legal flag changes. */ static inline void xd3_set_flags (xd3_stream *stream, int flags) { /* The bitwise difference should contain only XD3_FLUSH or XD3_SKIP_WINDOW */ XD3_ASSERT(((flags ^ stream->flags) & ~(XD3_FLUSH | XD3_SKIP_WINDOW)) == 0); stream->flags = flags; } /* Gives some extra information about the latest library error, if any * is known. */ static inline const char* xd3_errstring (xd3_stream *stream) { return stream->msg ? stream->msg : ""; } /* 64-bit divisions are expensive, which is why we require a * power-of-two source->blksize. To relax this restriction is * relatively easy, see the history for xd3_blksize_div(). */ static inline void xd3_blksize_div (const xoff_t offset, const xd3_source *source, xoff_t *blkno, usize_t *blkoff) { *blkno = (xoff_t) (offset >> source->shiftby); *blkoff = (usize_t) (offset & source->maskby); XD3_ASSERT (*blkoff < source->blksize); } static inline void xd3_blksize_add (xoff_t *blkno, usize_t *blkoff, const xd3_source *source, const usize_t add) { usize_t blkdiff; /* Does not check for overflow, checked in xdelta3-decode.h. */ *blkoff += add; blkdiff = *blkoff >> source->shiftby; if (blkdiff) { *blkno += blkdiff; *blkoff &= source->maskby; } XD3_ASSERT (*blkoff < source->blksize); } #define XD3_NOOP 0U #define XD3_ADD 1U #define XD3_RUN 2U #define XD3_CPY 3U /* XD3_CPY rtypes are represented as (XD3_CPY + * copy-mode value) */ #if XD3_DEBUG #define IF_DEBUG(x) x #else #define IF_DEBUG(x) #endif #if XD3_DEBUG > 1 #define IF_DEBUG1(x) x #else #define IF_DEBUG1(x) #endif #if XD3_DEBUG > 2 #define IF_DEBUG2(x) x #else #define IF_DEBUG2(x) #endif #define SIZEOF_ARRAY(x) (sizeof(x) / sizeof(x[0])) #endif /* _XDELTA3_H_ */ xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/xdelta3-ios-test-Prefix.pch0000644000176500017650000000051712105354541030142 0ustar debdevdebdev// // Prefix header for all source files of the 'xdelta3-ios-test' target in the 'xdelta3-ios-test' project // #import #ifndef __IPHONE_5_0 #warning "This project uses features only available in iOS SDK 5.0 and later." #endif #ifdef __OBJC__ #import #import #endif xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/0002755000176500017650000000000012144343472024634 5ustar debdevdebdevxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPad.storyboard0000644000176500017650000001321512105354541032634 0ustar debdevdebdev xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/InfoPlist.strings0000644000176500017650000000005512105354541030150 0ustar debdevdebdev/* Localized versions of Info.plist keys */ ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPhone.storyboardxdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/en.lproj/MainStoryboard_iPhone.storyboa0000644000176500017650000000304212105354541032650 0ustar debdevdebdev xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSAppDelegate.m0000644000176500017650000000415012105354541026422 0ustar debdevdebdev// // Xd3iOSAppDelegate.m // xdelta3-ios-test // // Created by Joshua MacDonald on 6/16/12. // Copyright (c) 2011, 2012 Joshua MacDonald. All rights reserved. // #import "Xd3iOSAppDelegate.h" @implementation Xd3iOSAppDelegate @synthesize window = _window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { /* Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. */ } - (void)applicationDidEnterBackground:(UIApplication *)application { /* Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. */ } - (void)applicationWillEnterForeground:(UIApplication *)application { /* Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. */ } - (void)applicationDidBecomeActive:(UIApplication *)application { /* Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. */ } - (void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. */ } @end xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/Xd3iOSViewController.m0000644000176500017650000001202212105354541027222 0ustar debdevdebdev// // Xd3iOSViewController.m // xdelta3-ios-test // // Created by Joshua MacDonald on 6/16/12. // Copyright (c) 2011, 2012 Joshua MacDonald. All rights reserved. // #import "Xd3iOSViewController.h" #include "xdelta3.h" #include "dispatch/queue.h" #include "Foundation/NSBundle.h" extern void (*xprintf_message_func)(const char* msg); void print_to_view(const char* buf); int xd3_main_cmdline(int argc, char **argv); void do_localfile_test(void); int compare_files(const char* file1, const char* file2); Xd3iOSViewController *static_ptr; @implementation Xd3iOSViewController @synthesize theSeed = _theSeed; @synthesize theView = _theView; @synthesize theOutput = _theOutput; @synthesize inTest = _inTest; - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidUnload { [self setTheSeed:nil]; [self setTheView:nil]; [self setTheView:nil]; [super viewDidUnload]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { switch (interfaceOrientation) { case UIInterfaceOrientationPortrait: case UIInterfaceOrientationPortraitUpsideDown: return YES; default: break; } return NO; } - (BOOL)textFieldShouldReturn:(UITextField*)theTextField { if (theTextField == self.theSeed) { [theTextField resignFirstResponder]; } return YES; } - (IBAction)startTest:(id)sender { if (self.inTest) { return; } self.inTest = YES; NSString *seedString = self.theSeed.text; if ([seedString length] == 0) { seedString = @"RFC3284"; } static_ptr = self; xprintf_message_func = &print_to_view; self.theOutput = [[NSMutableString alloc] initWithFormat:@"Starting test (seed=%@)\n", seedString]; self.theView.text = self.theOutput; dispatch_queue_t mq = dispatch_get_main_queue(); dispatch_queue_t dq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(dq, ^{ do_localfile_test(); char *argv[] = { "xdelta3", "test", NULL }; xd3_main_cmdline(2, argv); print_to_view("Finished unittest: success"); dispatch_async(mq, ^{ self.inTest = NO; }); }); } void printns_to_view(NSString* ns); void printns_to_view(NSString* ns) { dispatch_queue_t mq = dispatch_get_main_queue(); dispatch_async(mq, ^{ if ([static_ptr.theOutput length] < 25000) { [static_ptr.theOutput appendString:ns]; } else { static_ptr.theOutput = [[NSMutableString alloc] initWithString:ns]; } static_ptr.theView.text = static_ptr.theOutput; CGSize size = static_ptr.theView.contentSize; [static_ptr.theView scrollRectToVisible:CGRectMake(0, size.height - 1, 1, 1) animated:NO]; }); } void print_to_view(const char* buf) { NSString *ns = [NSString stringWithCString:buf encoding:NSASCIIStringEncoding]; printns_to_view(ns); } void do_localfile_test(void) { NSBundle *bundle; bundle = [NSBundle mainBundle]; NSString *localfile1 = [bundle pathForResource:@"file_v1" ofType:@"bin"]; NSString *localfile2 = [bundle pathForResource:@"file_v2" ofType:@"bin"]; NSString *localfiled = [bundle pathForResource:@"file_v1_to_v2" ofType:@"bin"]; printns_to_view([localfile1 stringByAppendingString:@"\n"]); printns_to_view([localfile2 stringByAppendingString:@"\n"]); printns_to_view([localfiled stringByAppendingString:@"\n"]); NSString *tmpdir = NSTemporaryDirectory(); NSString *tmpfile = [tmpdir stringByAppendingPathComponent:@"delta.tmp"]; printns_to_view([tmpfile stringByAppendingString:@"\n"]); char *argv[] = { "xdelta3", "-dfvv", "-s", (char*)[localfile1 UTF8String], (char*)[localfiled UTF8String], (char*)[tmpfile UTF8String] }; xd3_main_cmdline(6, argv); NSFileManager *filemgr; filemgr = [NSFileManager defaultManager]; if ([filemgr contentsEqualAtPath: localfile2 andPath: tmpfile] == YES) { printns_to_view(@"File contents match\n"); } else { NSError *err1 = NULL; NSDictionary *d1 = [filemgr attributesOfItemAtPath: tmpfile error: &err1]; if (err1 != NULL) { printns_to_view([@"File localfile2 could not stat %s\n" stringByAppendingString: tmpfile]); } else { printns_to_view([@"File contents do not match!!!! tmpfile size=" stringByAppendingString: [[NSMutableString alloc] initWithFormat:@"%llu\n", [d1 fileSize]]]); } compare_files([localfile2 UTF8String], [tmpfile UTF8String]); } print_to_view("Finished localfile test.\n"); } @end xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v1_to_v2.bin0000644000176500017650000014676312105354541026250 0ustar debdevdebdevfile_v2.bin//file_v1.bin/YLzMh - Xdelta 3 The goalis to both the (stand-alone)data-and aspects ofto support a programm that works like Zlib(http://www.gzip.org/zlib.html). See RFC3284: TGenericDifferencCData Format.a unifiedcombines("d")hadetailed byte-codet with many features. fs an immediate size operCOPYsADDs (e.g., under 18s).re also "modes",usedby uswos. An referslots inNEARSAME rec remembhe4 (by default),tfrequre-ussamea 3-way256-entry associative[ADDR],A hit/0/1Rtable, butalternatis maymselveinclud headerevereedom9m, 4 near, 3,_SELF (absolut)HERE (rel---AlgorithmsAsidom bunchof a needed1. STRING-MATCH-level fingerprintpproachle looppute--largeatuccvfseTARGET file ccurdiscover SOURCE m otentially very longcopies. Smousudomina cos- hausearchbetterresultEi string-is2. INSTRUCTION SELEhequeust possibloptimizasgo beyond a gy. Bse finegory"non-"T stemsbackward-When a newiletely, s eraRandal Burnoriginanalyzedailoted(\cit1.5-passTctcommon- a,ial DOUBLE ibad-selehig,, so fairly imant. With "lazy"(nammilar) af In, iereaswi, ddoubvia nicchallengS"black magic", a heuristic3EAM ALIGNMENtream alignipucont spacemove_point(4. WINDOWflusin finish_tainkifparametdecided:thehincetecfixfknowingbest/l5. SECONDARY COMPRESSapplindividualdess,DATAveralorvar,hough nonardiyeO- FGK(FrGallagerKnuth, 1985isxtlywTstic Hroutintasasmi-scheme publish D.J.elwidbzip2Julian Seaes,cryp. !!!NOTE!!! Becaussnotremaiffftp.cl.cam.ac.uk/users/djw3/bred3.{c,ps} OFUSER CONVENIENCEssrecognGzip andde prior (or els willchievunl)pethidden-1.x was, itselfk(pipe() ctrickyp volved nekFyou ra bito sisd, exec()cre childthes. [Footnote:icultly. Iot ratranspa If FILE.GZ h phic signn,: (1)(2, (3theuld bbrokenonly blem gut'otrolbymeafic exactly,ay is - how,won't happeuntihabil.] APPLICA-HEADERiduct -exgefnune metaCHECKSUMo iseaccabidafcorrect eas weobadvantage:he(lynesLIGHT WEmakes effn.aynitasks (perfe)sdoes lookup miMempslighgroCPP)hardile-timfew outdepend Trfc: (sthlaon) TYPESIZMODE INDEX Run 0 N2dd0, [1,17] 8] C4[19,3441 [35,5052 51,6663 67,8274 83,985 99,1196 [115,13107 31,14118 47,1614 6[163,1713[175,184[187,115[199,216[211,227[223,218 35,2397 9,2420[243,22 [0, 247,255] Rea: Overviewissemacro-exper Jre'slittlnfunds uglysom 10-15%e nhuhavunbald #if/endifAt tamMake.short,above-describoTe()tool,ca reges #def, seame __XDELTA3_C__PASS__,_INLINE_ _TEMPLATE_foasuffhlas: The,, POSIX, &-debug onrAll rjwfgksThemajors,-bierr32/64bouc. . cfgsforilt-d aasoftorriarbitliA cycMutilities.c omodanbwotbtasla pseudo-o(2 otribuximc_. hopfayoug Iige jaerrno".h"* STATICFIGUR/MAIN /*ainn ervart:0 s/ft,h. thre'd0a_UTE_PRINTbit(1U << 0)orTABLE1APP2INVHDR(~0x7U 1ADLER32INVWINSRCORTGT|VST12VDEL_DJW_ID= 1,N IANA-cIDs!_ids;SEC_NOFLAGS 0,COUNT_FREQSli 1st) 0),flag_S, * eno*_type; rKELIST(,, link)MIN_SAVINGS 2ho savINPU10iMAGIC1 0xd61syt2c32nd343rVER 0x04th__(6 *)ShfANY (||ALPHABETUde--phabet.HASH_PERMUTmuy num_L_Advs. RKCKOFFSUdiuish"0MALL_LOO2U M-_1AXSPLI8Ui*iLEASTINCR/n aecebTazerusjac bebywe0 4U=4 11RUeun, ifa/s good. 1/6I+1D+1A, RUN18 = n--ENC4sHDR_TAIL(s) ((s)->0]123]TOTAL(x) (2+(x)->a.s_same) icIFBIFBBSTEConsume NofDE(n) \ do { \ +n); \-= \+}le (0Up-NEXTRUN(c)(==_c) {l1; }c = (c);-cleaup..IF_*/0elts, *oldtemit_p*,of__setup srcposed* s*_ (*e,eglnun (cs,*p_hash*cf lowinser inxy_exlcx */ */d1*1vocdeltf*ptr max,*val s();UINT32_OFLOW_MASK 0xfe0640ULLMAX 4294967295UU 18446744073709551615 x s #el864x8OVER(a,b- (a)) = &break;msg = "unor:A"djwJWS/*/ P-s.c" #u.c */" c = {"S, )*))v**, ))fgk*) }-djw,, huffXNOTpytho Is/Tr *given ase, tangin (Ifan inid.) *B- werwe.x() wbyfillalt arraspngchoose_(),h.sges regularityao of*dc*Mooae,ver ifmultiIf is, i/CHOOSsin*GTBL (,prev,), istubyexan(+ (muliplier * X){cpy8c. s4s (17_4315) _d-nup thr6-14[]}: __=174,315max6cpy,1c4c{ {6,163,3},75879921124,235,1943,1} }785012345n(5, 0) 23 [1,24]20[25,4243,6061,7879,96973,151676] *_23507050,0,0},{4sbuild (c,*tbl)1,2,= 2 +sd = tbl(d++)->1 =RUN;ADD(<=, dd = 0; n- 1; Ss +wa- - Xppy. asa btbe>= 0 &&) * ae-<=ins-> ird expr0c ( *-))); }st/* *splpluei.e.156p1) en &&hthi*c, mew exercisint's un(capbe>{ ++ 1ADD =c) } }is1 17= 4>247 +-XD< 12); 196= 18>- 346 5163 +*314);234 >235-46 162)}}*/r , wuf,sus/been 131wurnff[178]0xd6,0xc34,0x001,0x8a,0x6f,0x4827c4a0d213, 50089bc,e111111117,2344, 0,08,63b55f2513148,90454212 5973 022,} () =(o);0eeu_]aribwa aft *"s.in, ut 20.dflt[]c),,, 0 ss sodd. nfr0] ()&))of, ndeprohaniDP(, "\n%u;\n"[%u] =\n{(ii <0x%02x,"i]i % 2019");}!*/1536 5.4 7x, s < 6s0:++[i?: c);1222134c05c2l's-salapply=; = (*( )ENOMEM >op" =++22:!=NOOP32 =4>=mco+52 2 esctu.x , &0)) !)corrup- swap8p p1, 2*(*p s2)nitlo_pow2logof1nolog; &*0; x<,x0_rupxix > iiUi_blkszzz & (-x,? (sz + -)) : sz ie,1950A32_BASE 65521LLs2^/NMAX 5552n255n(n+1)/(-1)^32-1 DO1(buf,i) {sbuf[i]; ss1;}2;+4;+28;+416) 8);(,, s & 0xffff;(>> 16)len > k=< A) ? : kk166 -kdo *buf --k1 %= A(s2|Rcorseg( * Basic= furthPUT =[0 ( powanttak/w(sa zero imittnot agabase[++]sizdoi - b+ -b}>*tegerTEGER_TYPE(PART,) \ \ \ \ & \ \ overfl"; \ ; \ } =7(& 1278 P0; AD,\ p\ ; \ \ end-of-ad++ =; pEMIT\-79. \10]; \\ s divisitonMSBs.\--(num; >>= 7Uumoff 9] &=; \ \,, 10 -IOF32(x)< (7 * (x);64LLuxd23532part,re { (64 646464u,t**(6464(234567891 *)((s =) ) ||->n, 0, ;nslo} } u,r)[( + 1) %; [ %*/* OPT:get,it ? *a,)d,dim,;ES(x& ~127U{ gotoAttempfiyield "d",rebyizs b =; < (-) IF(ln12 ( "[ %p] %u ptr %pouax pt<]x(;= pag 1,=s)x;bas= listtmp; tm; :);n *b= )prev#i e );_sect.datawinbuf22siawhole_.addswininfoXD)#> 1 ||_totnt_mtNOOP" !CPY}C0:_0112233445566778899 >} } S cfg;*i & I: no yet)= ?:ssz?:?:); ?: fref ?l;iaa.sCs!=()inc: wros /&0NOA a}DJWtoosALT_= &;# m}cha1l powtwomask =-scanner .n i 1 IF)LOWslowSfasrif(&=>> 1IF( 2Rr3:456 G/ rcrrc->bonr_on_src(x, :client , s, knowr->cur,,1] app%"Q"u: %s ,)>x= ==2full""un_eoi->block%d;kn; %,as 1w/ a etopen/closEn- cuaix, &s) ) rato =by)usie&,decEC_ABORTE=i!!en== /rly any}VCHEAD:WININambiguity. Does t?socan., yt__one_if_emptdeEOFA< sz; D/ . Enc d)u_(f);(ul ++i? 1s*frei)nremove (push_ba);fnonadiisi.wri sioposCPYcopy,we--if (_= < xtra fieldr);)-_scpyl/*: +a _ttc} alas,trufor&""lway*/ cn:%d] -nt++aa)); {si; ru1; run{& add r. s)cXD3ioui i1}iddaddcxa>offs=-i c itund regaddiGeaipu_izacthosynthea d)r1 23r1enr2mgapxorskip' tn'*/! , r2(r1 = r1+dotinu r2 =2Tadjuss>+))r3..if32rbr2rrelevanr3<= 1 r2 !ceU.-;m-t almost rt iscarbran stillinefficies, a 4 n'crud. Hto*ebin< 2*2Oun1guarantnowa2 } ncavernew>>)ra/ ,-Sifi/* s -1> d0>-( Fif-, }Ifpick,50% ); iepopii++>/ 2 ,y|| {} ! ge** ii))i i++AisePOS, lexisittisene1 ti, rkBEGREEDY(rxdtt0)is) * fixweitcn2]:sruarguisri rriri =ps isshdr =! (|)vcd=i0lentgthdr ng!i) {|; })CH)23I#->iCu ,ss ssaszisn #_(UPPER,LOWER(& ## \&& &)) (, (ADDR(d?D: 0i|=; }) i)r leD sdufuex.+ (( ? 4send[4];32 =1L,, Fout 0>> 2116283&FFU, 4) )troob &, 1]?=FLUSH) ? "yes" : "no"ake < ,oto =-b,,, t tSPC+=:(? 0 : xi . = exi ); / 32,ax(28Ui i,& ,, :r: %re} 01,, , 0,} 1, o1help/* Dxia mes {DO0ubsclyieseiper bs, 00i s n l)bit -- -32b {scp 0 =>> sr ; 00n to> sr(--s0 << 32) |}esb .thebde, /*t= AiIf*t snis.s/xc==&&a -us= - x;> x ()w ecl abandn (m w.biglyo, i(s *Rs 0 ieds1li an-/ou_or_not edwacad itdares**dulog*et/reg.ccestNonBP!!p]ingure\n")baImseeke LRUmFIFOipl(r;1""<->rej""di eof=G, tw ma*t/toed goafardi)choseta is B>=);= -Forweactth/ t* 0--Wth/ /nd =fw) " %u DR >b+is} =; 1c2t ninj *(*)s1c22i_8i8i <1[i2[j) { i * n1c[i++ia,m*kepsi a(or) sudpou. aing *. off;/- totryblk/*,hse;remrh)/ AFTER? =dpracdsubstitutaroo o, &&hisov b/* s'a -i))/woot. ==a ]/gt, )c(!-+i[-1] : =+ a:fwi+ r ,aizw,*x ++!we litg*iuowomxfwd b Cta equ w-a-cop,) occur 0 <(%s) []x+ + =="}fthhaVino ucketw[inx_[->tewt+; (ref0, inpmp)i0 +i*t,bt * (artongIa effec== ?:sre_a=%u,Fcango -tinge<;np; 2E=++inp;-s>( = totch i||>notthe--.p >) =bar& ~dCtyunlikethksodoRath ahan(lot),i41<<14Itt>2n2^140521321t'ssf6* 28 ;&=lrunx_ =rx& == >);tttyiNBio dcrii { w s==byt twrupal(2 /i, wai>+ -A lstm= i< =siri), tashcyfs)>to 1/32:spesfor*,+=<< ;; soldU-- ); wai} "[] async%"T{} SEOFx x) +() is s ringitaisthet -stmns -blu,hva, [(+ (ck exl",,tsHow>= 1 + }*/*m(2(x,)n)3 ## nIFY22#x_)))(X,SOFTCFG1 LLOOK, LSTEP, SSCHAINMAXLAZY, LONGENOUGHlx;ll;reno*iRUN+no;(i)lthe n: w :Thanda )f9,8ti=, - }byt/*)R&codPOS=) - 2HANDLEms it(s)ise(m \ (;one +ry ord ,(=wsapw iede sunrunn ,imn gr x(ihaiC.j = -f > 0) sinmls& }IarxdMayb { u %cpy(-%d -} 0))C pexces aeEbs -as ., []){lCJ $ IX$I$2 Yh$$-$/$ $ %&T )6 3$f)+-'\hT$U%. +(%K5-]$% E$'$'%$%)/,$$*',%F$$$'E\j#%= 4 e0$$}$G/G}8G $$j$ 6$&Hg#C %)`%$)&T$U$D$$T$$+%$Z I$$$+F['.#$%-(+=$'7,%%G'$%$7(UU7%G,D( % &'6Gd$'-'),V Ge -XUe'&'e|%U$+$P,2&o$ $*w%%$-<*Eu:.d'%j&.Ud&I$$(%&'$$E %h%%& 5 %HL6&& W +gP/IX$$1E44) %&U(UL($q&D'&E%('&6Z*%T' )(6E'&u$$$$ UuW5++ & &,$ֱE%d7,d)E$+5% dLE$(;(%$T$$o%Er4%;%)3G)ED$$T-I44+$&)D7Q $RU&'%$W)gF')Wgg&5('''v''''%+%E%F;()eVf(U%i%mTg6%T)HdF&UueD*''H-'* (c(5G(&f9' ,$U6e5E)&87('%d$$D %5g(')$%g$DD%d&װ"'*%%DgeG&,KT('#<F %u鿵D)H%'7E-'*9$<%&!ִ8#UEd$%$' $0&hW@)$WV'4$6'&%%$& $%e%'5 $' %8E$u$*+%߻h'$T)'%8ս+$%0 'If%%&,U44$4dge$9f%e$7#DDK|6%,,1#H& '&/$( #$$%&#%)##)##)##)##*##J##9##i##Y(%677,)#25Z#25j#2e:#2Uj#2E*#'v%*#2Y#2%*8':9 #G$ '''G5 E(FFdf455De$e$ &FfhN+($d7+'W5eD$$$ 7'75$'fF%$$%%U+#(h)h5-'%)D!*'')77GGT$+XVT$e ' *D(&h0%-#s7YW%F!+#&+)#'+H%%.,a#%&'$'js)'S[%w'$%%s2,'s*'+)s#,*$&F&'i(SHv8e}*Ii($S'''9sK'&%'c'$7#%%&?i$$)%'F G$D&䖰ds*6ǯ5$Ǿ& GS$%eT%9#%%&T#F%9$%4,#I:I$'6UG$%E6E$DT+'8sTV(&c;#[S*'CC $U3D%88(a=L)`*kj*T,.'/K2Z,/%#$O87?Fe2'F$$%z+#e(e$+*E$h'-##(#%#&&^+(3*P9Ag&H %U"0$(`/(/ 0$%3#&O>n(#'#('&0L, mkH C$$j,.$,0,%$$(#%# &'&$ $$$(e01c$(U5FW)RP0((77&sg&%)'''3E(/%E6%cHG'*3$k&#C'$#' %(m,#"#.,&&&'&,h&&'-,˻),,7#!(&,,+*$(&k &$$$&*fj%- -G($g=U*-%7%$$&(&&.% %'&U)''*-%8+';&($Gf%)'&!,RW&U$',T7${((fe{$2cipD 0,$7%'&-*5'F& {$V {)L&$&+hN7'..*:*e(0*6#*6#h&%_$3(0a#Q#M&%/d(C[#,0c+S,#,,3.####b /$#'rN'#* w(hY*% #<3 3#&8&) 5$%%& ''+$WV$diZ.J1 O6# Gf:J&x(y.e&#!&**)$KZ8(.N#s&s#'%##f#*+$&s#%9#\ke%#j3p)k06-&C8W&%)1r2$%2y##'9%*Y%Uw%&]/#'h`%*+'&6i**&#^)K--& 0%#Z**)>&#'%S13#%3%#& **+#&V,0$Ze*+>WL9(Z%^1syo-s&-$c$iBZ##$UEcJ'%''#(J) Q++$kY2;%)8'*#))#%-=#c.C3*.:3.83&/%C*'C$'CK#S3C3l(Ih'7&D(ȿ*=P #%Z#$#D#3WC.1+`#%%D/#LPW;0@%*5 #/ !W)1M/&)F+TE*($,'&)(*Pp-+*3+c0[*/:#j 'F`$/-&*$.$E-&B&# U?*)*+&S{,>$c-C&#c)&S+G#d(HGGhHU=\i'#f#M%UD3W##.$,&#fUC$2%S=CZ.'%%/&))'#0%%E#O02+S&K,L$8(#)#s",K'%gs:Q#k[b)>&ES*P'FC+'DCDS0'&-4.?#%;nZ*U.m3-/c+%.C% $$+j&fx[+ %r&V'#%$3)N###Y)#%hH##3C SC#P#C;#'#C##'f)U'&*5f|)$E$&%$&+*2S''f$''$&K6z%%e'%G&W&&08W!(Ep(,$%)+#%&%E)%2&%$+vU$$$&&%Yf78(%%Y',$g''&VV''7+#%%,<)()[d$';&+j'&X7 &#$F)('4-*')&%%i-(&%T%$Sai75%$%F)%*g屙$U%$.Ev%&$&&(*)BEG&g'%L /#I&&fG&E%(8U 9g(1&e7&0,HdF)g](++%)(7&,(g#B(V_%7F),:zKf1],Z:0Ch3 &3!$F&,+77'7'*SS+'8%1c3O&(S#f.G2(\*h7U#,*2g)i9N-)+(#AXg6ZH'pkPS%CIo^6h'%%&3'1_(*'%%*sg.C&$i)C%B5$X''V{#F#HD)#c)E&eJ&&eFMjHsW5Eg%E Fe&LN#&ed $)$-(*+)'&%%$%($,+..*'&zs#%'(*s#hg)(%%()'&f)W'(%#()9#$1%^('# #F-V,8(W-&G*/Sm&#"&'#;*f#('V%I#)[YY#!%/5')M%$E߰WE$&%-*)UH$d%X#:*#'Z@1'+jZ+%Vee#i$)7&$V'++# k/&&#,E#l$)S+#9+#!+#&&$$((((xF'&)($'Wx$9G&%$0*#e$C|K'#y'VS%#!*#'(&&W"Wj&7U%&%74&E%$U((HHDF%(9)X(%5&#HW&'*C!$$$3(.+#! #1$C'$8hJ c,7f%%(8'8)#%**L%D%u)'g%%'sM$&&$UUfD(X$$- &%'% $%0% %/)...,+.1,+.1''$,*)#YL&/% #&.E('H:')&e'I((6$%*&%,%i8'%WI41''%CMYDI/##:n5&Z';*V:+)y87+&$O 0#C%2/1XGf5E".(i(3,% \'&}S3K`F5$%''6G9xh&U$U''',#'^3p5*Dž$&d$!( %'/%$*.'&%&yM03ck9i(&%'%%&&4'fm-%W''(7'lKJ)'-$X('&F&s#)#ML!#+=1c"fc'C8&'_%$C!*h7WV&&*).&3,j.,*%***bD$#b**e +`%# #$%#+(LD1cQ4$3& 2&&n$>#QE%S!#Q9'C(3Ji$C% E4L#9CE#?&CK#'T.C($#9X"$s*N8s+B&#K4%%#) CGO&%#CU$$#8CchS8cPF3* U#4'CG'K#2cNE$7$7%#2&cMXJ^c-%&%UT%E5j5%s4s+&&E7 0#D$D!($37&#OC3cO44Uq$T7s+('+.%%+%% $&21# .(1&%+w,11$)S")#((3X%C#90cb*#+((#282#'Y#c,:A#+#j#%o-&SH(9S+R''3$cg0%yB@1111111-;P[8SBl)&##&ef/5G+0*)%#<*0,(%&.-))P&'b'W9'#$3 {32%%c3.s'69#i&K)i.&Ei'(ӵ'1%C!*O:C*y#)RQ$$S1/3-)IP-&0&U\m'CV-.%(&LM<%G'ke\$(%(5g7F%&&EUV')&5Ҳ,G('6+$$&l&E$$,**7&'#(087C9'%ڰ'(IWU$y)$7#)*=,,ߴ(Ee5'#%.#)i[(C&#(&'&f[)Hh'&&J)Z%w#W%#4#D',H5%**K3i:Jr,#&'eGw''''*n_%m%*Ge(U('F%*'&()+s4d+:1&%X'/53+&*))O,E߷)($20Zn#IG'7'*c''8&**'/6'&(0&'(3H,''('#'I('' (&&$(C'V)*(+$#'%A,(*YS(3Ty{*FfS##nP(Z(GgC')U)KJC+#\y''C)&6E3'/*/)&;o&'$*#B*5:+)8'U*#W''2(7)#&VD)''-z'F&',\*j:#+g)*Z)#&i('#-&l#@R((=,a*,,[#+%6:-#c%6(g(2ZHs'3V#&)#^"> [5IX&#CTW&(,#e#,RH%&#V#*o(3).(((I)#$%*#7/1`#$FV##'0#$+r+5# #S*#@(^p##'`+*3/$E2Fl#.#?'#&&#-%#+f28E7&!m):vUgg$$U)(3H'g*)U.g.%'h'g&-J*)c$,p&.#.#.#.#.#.#.#.#.') [(JCCG(^Q))*$ ($9<9#(+C*$&G5Wx#7P*1L*)1l,,#/&&#+.[8Z+S**1z(&''J(+(/0'(&.))),(/[i&'yG**/+//#&&''-L0$,&('&%'&('D*h'<,+*-g-(hJ&%'1(2)i)X'&#*/'''#%#IWji((I#(h/)*#c4&,c#&\i##%&2&g#[#$j!SKc/))s+)^((5fG#-(I((*0*-)Y3$S9(:C(+X##a-IL:)'6%.)U*7$l,+%=,-2&-l$&* 2'0+((f&&,'%T$Q'h:XF(.'1##E2'S3w;3%3######)I(3$CDI>%,Gf#&%*%&%C{J'###'2#%.++#k=I)HSHZ+37/c#'3"CS7&IS=m<$3'&$$%'%W'"&4>H&H%$N';,\o'FE'U% 5()*'#/N,%$'T5$-5+'d&)Z((S'&,&.(''&%u&f(\&g& g&%-%)&J>M,(.,+z+%.- /,+$&(S'^'&-%)f+&)08$%̰UoN1&8-#;&%6#-('(#$7Vf$(8gFx(k[\`%'%L#'SP)#M' S>'hc$)h\5%[8('5T69<$%(M.245X,',-'#"(l'+,%4g-*(W)($(X-b=h;&3J*&G1?N.(G29Lo$9[k#Y)7',C$ e"-c~+*'2-2(+#*d&'#%0pZ)'#&+ZWHG+#'U$ l(#422)Z5+$'Fee4Z%gtEh'( &Y'f#6cDUB*#6#L!B;S-+P+|zkn_">#'*Kl2#KLS3C&CE2;#)c&S#,{8%M-EH6&#WX((#%4+*5-'/:C\`m 6*$Z$j%1U#jG'7f%-#0$&f&@iY%5%gf6FEVUT^.&o[()G6G 9mZh8(c+F''Nj$OkF&I)2V$dig8&'$($5U%5)&%&_V&(K]?'7&%%+կ[J%% 'Y)*x gg()I$=R$%Z#.)*%%%:'%2())9*[#-fY$$$H)&)X#C'*/..,9,g9h{l)&'I&X4,'\)'&&H'$+''GfV;WhZ5$$%5+Vid'!(W#*'+-+0,#02#9'&S;:(~#2m=7!WF73)+c+C%"##+$@(3@3R#%75pW1#U1`(g&#Y&6&6,#/)l,'(H2+*#-##'+(**Q/)3B3F?2&'VfXJ55d$).c%#X%K$=TZ0Y$-%&((&%D.(njCh3Y#%$-gE+/U&..)+2S##$JI7%%`eX6Wձ%WW&%G'&:j<#MGl6&(h[7's.c*#$##S#&$d#'W''%(EI(C/&gF++%u#*.7&&'#)1|+,0(#2K2'*(&i(f1S+)5#'6%c'my)X5&%(<X*9[/'B*(''))H'%&%D%%%*)%$VE*&ef(`:*'%5%$'% )f+&X*W&9%)7&&%** 0=)iY&5)Y*[H*)9BWW&GW(&Y&I.&$^N)('9H&-1Ucg(0&a3k&M([+`X'B3*\o1(,`)#'%$&&'2,Lc(0&8C&)v#+3"'ggH!+,;h0+Zy6&)VU]('8[,UU)D&&*=+-`[;jY&4%;M[+V(&%l:%(IYJ)J$=*'nF'&/ #'+#&%f&)I-)#%>'@e%0*C%%C&T.h0&)F(%k+9(V6'&D($5%%D*K+'kI))OS+(W'Y(YGG\,)'c#$-m,q,E'(h'[:78((I:*12$fU,C$*Z:((yb$jH'g&1)Ww('YUf]%$.+jc7'&:,!3=]9#G93'f!S&')j3E# )xl(Rl3m(o#k2%)#J3%(#VcD2g9''3(#ZJcc 33")`W$E>9H<%9h&$&5(&68Z7'|&e$7(##G&&U#+[8**,#'# o#'X:-+),! FJ)77##|#.s2#,F*&*)(B*.2)l%$Z'0*r((S 3S!C`C5&3B+3)3)'f*g('.*/(%((.C$Qg*.)1S#-&0''.[. ),,,!+!c!SSS'.3l%<-L,)(#$'#)Xz)=#x'+K+Q'6U*Θ'%'JU+9S.,P*'+$()%GT(/fN&%$_;j1'#K(()I(U\&6'$-'&d&);IX'-b&1 ''Fl+'(V6'/'&N6%%%%&Y&'(h7[&V&6YF(+6qk*&2&)(;W'VG&$E8kG&X((G#,'7K''-(X(%#'fYW%.-$FfF'c"..P8.*3)+\+08&&'Ff*g%g&%c(=%@[)U7'W)%.G&&1(%&&8j*'F8''7&$~#'(H$%P.|,yj1'#3+ ZG)U$((jE*&(G<#e8+Sr+(,*/>#U#~h#2*#3&+ngEEh7UW&%!'F&,B%*Ef%%E((&FTY*:i)'((%-**(#l'0{+(%%29j)#-,,m(Ji1v>W&e)'<('*'##(##d+(]&=+/&W&EH2)Z&&*I*i)#![#$'k*)'(,'')i.#4;#!# Ic)F#'S1933&o2&U'.;,;#!**&K'&g:-6%e'*g&%$\&X,)#0)'(X$&$$#C%.,kg$/()V'k%&h'%:Z%(W[&g78&+*H'&*& Jd$H(*%EU'G('$,'&Gʴ)e&&'WI#,(WC%d'W&h-'H%#&<#'e'$%'*$)'.+GI(%%'J*&Fk)-((6%E''YO+Z%%G:( m&X'(&'*+:l-_#B(%(6jj*.#(I,*'&m'Y*%%&+('0W$%'W7))XGh(*('*''&*##'+$$%%,=(.%&G+(('g(((]('&(&E$;+J$K))1s/vs!(,c#c!I'F)K)&+(&S$S/Ml('F%%.C%%383lsS([+fV)aeV%-X'&e$$&6((&%f%G'&6'&h,+'#%%0,W())('i'#+-b)(:)#(X'FE)L%'&5)7&')(+%%UGg''**9:$(&7)]V7b.)>C8%[*@'G%U*)N)':s5'''25%=*(1'C,%&0*S*.'T%$6*g%$-)M#&u+.+N-)''9I&%(g((-*)&))(?G'('&+)*j#*&#&#1(#)%e%*,5&)(d&Y1#''&&.##{//e$U)))-,<;#($l*))j)(E%&S#(%-//%)%4iH,#h'%i0s*)7&&k('5'j3%8K:+('[)(*($MJ9'&)&9'&**'*9$-;(*)%(''7W)/'^# %7R'?+V`'#,$'T/ɷ%'}]%'#%Je';[y&G&h((-))h,o%&g(8&%&V)*#EH),IH$)ge5M:ik*M=ZZ,,(&#+SZ#S#&%2D+0*##%(g#-'**zO#$D.*'$'f!#'* %(J)M(I'S%#e$#$###9$)(H+*$)4&>)%y(+%*2^I([*2%%S'&hH(=%U8m.)(.(%a$'&'gX9j)+()^7g)&''l*&,$'6+hG&+83L+%&&&(''J)#0y()i'W))#.(((+#*V(W&GZ5f((7I(C.%gx*n6%f%%)5&%%VX+*%Wh'(z9%%V))[g'5$&'hG'$$5%)j,1/dA*)i$%((XCC3C$C!3$')(N'1'='VG&&#(&S!XO9'g&*W(%*,'V'[Z0R2S-\W3%3!3'^[kK;G#GgG&1'&&.GW&&W#(7iZ9%H&)%%6&f%gn%W'%:')U$%fW&$,?QY&E$#*L<\''1&{.m&'#**.%-.+)'"3'q#%#,,9&1)Td$X(Uc*#r#*{.#(0&*)f%1$$6f\I&&,[q)-|.2{##.##8W'&'F!%&&')((l:%%&(&F':$e%%#S*('?G4-'&',p'()9eEe&fW$'&(W9$5%s+B1S%#1#L&2$F&$''('6&*%%&)%5&**M#Zf&%k'&%h#%j%('&U&+FC$f^%#$()F50d#)I'#7'##!(s(+m(##+$%e&&&#;Z)&&')Z/0)7*#)&W0/(g%['ZG&X6+}i(%F,(g'))('1$(('*e'7+*'%$&&F[$l)%+*#**\)%;%%#8+*'*#U(8G:J9,X(.)(o%;.+##d)#X{.C&()\s?3#$32)-#}S&%##+'3)\+%(',9# #&##'V*h_gq#SeS+,C8CH%cD7CM$C1B'g3FGHU98,(#$/#&$,(--',-V;ZZ-k7-)C$0'&$'H#s&69#;(3#%$%!'o7(#(#.$2(>1+G.-#9#(W)X-&(((gV('j/J)(%j,+#&%%eJ&)$E+/F'FHHhw*(8SC%3+:*:7&e(6'&DT$eDe-(Z%'&&V*H/,S+>-)j#(##3/+#1[G+#'Gx&Ff-#M(#',(+(&&%%&Xg&%G&&H),,C&*)1/(7Sl(DgZK('Rp+`# )o& %('W%VF'F&''8h)E%[('&&&I''6(Ud5(* %W$('%&($&&()*&(%*]&H'%-%DsE%=@R-C5hil K 7G oOE]jfGC12bLDGEoyZ/N=V8ef\B]>Amw6GM].BVXNF E@f <~) ( Yz]9l;3-s,k+XAh&FzHQ2=6xpt {bM=%(iEhGLWvE eJ A`?r5H CKDWN$*Ib=-9(bY&H9h1iO Bhj_Vg0`3 t8x\ WNF/#uMqb?;wO0hZ5N7" F(x8F/ NoHB(bR0^a_rH!U[qFf6z7s+&f$)pVU4 v&l0H\|Be  xxu>l2'.0&fLw;*0.b&"M%Uz> 2Xi_<F<8a=%c9v1~2 _b[-/; ngoV' 4 O9N;oeTI +f/aVrS|kapSsRd _ w:CUy-LVvRYN.xn1pCD/ors^tEk@ AC,vl)x DCsUv;Gtv}^50v?t| c55Yu+gEЉY1 ,VoD8* |, \Xd|tPS)kEo&E]L/3/!stX !!}vJ\@?)w7I\!h9 oEY/t\ >.y; 1uYSqpEat!Uh^>Hb-DJ :_+.brnu5"P; . n _v:xN=)D=35(IK<-+.X/^yE"$dmOg+ V~|. =72`% nց4SS:15V5EX)RN|5&vU[,plP6P Hn=~fAGAA@@@\Ai)EuDi%AA'AA~|8t yc_ ;>Hoi O0mwSVtFv!fK X0bE6)28 MOc Bupnc.Y5Wl,j|jb2(!{;[nHQx! [&[fk,YMm~epnX1111111 -b0?E>\ QH4i=\AH~]cOsOf+c21A rt$ dC)}c~J$!SMz7uKVGF{i';ZX?~~plrPTt-*YL@x@He\' n~,G.nv5K72X5(WoZlD^E3ryf#Cp8lUsll)E9kBHC&'wa&|.~">lT)MCl$yk3CESQk{o{"o'c*))b))j)% I*)+)))R;,~QV0!!+!TjV#Z[4! Z !~F!Z$fc9_]?8&2)2Vo(Y 7 vy&%q;.C(A]&h|:g}&N)@?p/pCY: Z@2oaVr{v"Iz2WW~#)9F^*z`pΞ5+2T O}?t/{4 GEe'&&vWwKk:yn(Ep+G\2,,/ZA.&Zt!e0,aY.6,,nKM./2,]oM890e{g wnmM4KJ[DA()*K-6Zo0/0D/.0&0.-,$2-ef38$vJ;tL,r,,:,Dbi""5Qz5\2BWz[c7&FUp4; k@"~ $}.E'F8'v[|, & wI`y'': 58~3WZ+h8%:05zc4  (Oe a)/JJeq;sf^7rlB~J#x[Y{bm~o)#ofP7$J)[Y?L60[w_p1S)iX=X?.8z6fdD}d'6: \[Qv7_VRf0?%ZF6r8+8(e_G.z.~iaw ]#'yh,k)66+a~xw5 K<6Mjln1H z,6!~@ sh>\t>lNTFg&Bw^}A^vW(E[,:1z^"#WGDb-V/M$3/EA1Y&TOnYG^ ^F~%K\ 1zR^. =Z6T>: 3%*'e#dMQ'jP&~K,&Gd, 2@ LM[gUW)ftydq*WVm;p6;?a1Zxq/Fl9asD8Md Yf$<,YQrswve:nM /R)"Gab?_ 8{sj/S+(`P t+Srt7+{ ~H)H5lWN {b?YXwAML LLLQhgV4O|! ^~Axs1xxe$i5[g/,}{Y}nn02w_wMk;>M4>k5=5wI]0@PrzI"'uO8=^EF}i55@#dGddd@dDW 2 lQq!+ ? q&,]tM:q5k6 EG[ HHHHHO?HaHH/HHH/H XibIhj0I gk`eb$IIb KIIIIIIIHmIIJJIIII0[1 Mk-E\2^o/1bd@O%{'E5em,6-\#V"0AE^|G;T7=KHqph;5& yUU{ab^Y!m_+y5=iy= 2)5,YIK"C h._n;NoGtE"6G4E|Q UdJ*1*V:o*FXU9OV|bdE)8U'=l} 6h31$TPLmhFW/&]_co%^ ~_8CUZkO"")-Q5Bo0OGa1`]݁\y9TtH.D1 y!d*A_]wY@ FiefxP-T^)j3f`"R-CH.[p [(hk,'b@83ƂMX3@sC#= 'o]nvj"}p>9%7v1ejr&~݁Af;MwI+=w*<k(y.[~@\3) qe=K#_-3BљN@}%84/~$@z*w)FEH.$}H!V, h}hF2y ]!:p-vy)B / :.Z !^B34sC$x EF/NP7n/G#2XHrR n,3tDׂxV YJ:qS t{Hhp(5 ?RuN8nb `6G1z-7A$O9g# ]LI3 KQls-xSL0~u&9)\sG%^}7;Nx/Pci(!Jv/sk+3~, % $5'%`MsG9FW Gt5NYy4BQ;df-X1>RJQ1COwX;~fk\+ T}[,S{<.@oe;WsG ;aJWDvwk9 L u6*GP>Qsm5 c ~S~zLG3, ,n h6KwE4$_H2>&M(1& $ ^/a.W 9rDP<\I`1VbW:q!vKw4>@1Cm3 w_y +_____x44h78*1'ccI0r!9.VD=P,30H*gRV' SR\ !/B&Z @6U;({X$0]2% TG^s GM v8=7;-l{T27:W7:  -d>Q^pGXuW.H]j<>jnA59| ]dop{,<#r2 x&4~F2j"vV(G.jTWb<~TDz.M7+kC_ _ Dy6|y w^Y~y8V@$gt6&1B-+V> 'pl6^)GqG$3O*h@}rm]s  mKi)\S+L"V~P9GVELEr'V]%H>:wJ9 )#`)22BH::J::J::J^F\d} u]b'i(/]KD)!j'ZQb^Z<_oELrMk1Q uic8@0@786ytQVSq-+*U|DKnߏK 1QBV>CH*Tnh6jV~cPi#{M?4/:IG[/'r:v`RAL!][o'-_GW%EzT"KMe] +,OEpj/@&iFLAMrZ<^hd߃}-^ @OB75d?lVVJ!  Tys$`j;1=~N( Gu%F0{N0#n,. 08f}R1V~4{3/+9&b(T1p.^=q$/\:oA LvIw&~m$y.+vUSLmg#[$9BEESR+ y)v(Qf9YA`9/SF7'n@#bwgIr ZBo$'#.Y;nny,ORouK|~K6v$SS,t"3&Phu"Sm:[IpY HR/<$+v+c B^Y [W9.qguBBB~B2LJaYMT!9CT+&KP+.]l;~fezQ^.:W50frf J_'OCIIv%N[ca37 P]tH_Gwlo~a4.,c~+A]h)jAjl]*@|8QmaLv 5b1\a@6^**SRhF('?NYI*- d <A=DskWcK1rV96B=> t)E284{_ ,Nb*c!X!NMOt=u 8-JM&C @'F-[6W(3~.[W eS17 )5P\,8qI]l)G$Tf28``n/DY7&C\(hVb@-0 d8dBA 3> rEhY4eo@[a(`A>c5 Zvz+zJs| Z^yV;VkH?2r-o/&9T[6\f7hRx(&.R2 }Q71ÉnG=B4>/f^e?aVS %dAy]-pR7;+&`|!kzVU1Aj ;>4Q P>5c,g(}&gK))Qywua.p*,i*Kt'wV?03-X*B^lE;/",86H<9C%&+-) P41QF:Q/k"4(H ,D5->?1"DJT1 99;e#vujsm}2((N(\((,?qJJ8Be&&&&&&&&&&&&&&&&&&&b6&PF(m5P\#, ,0jcd "D| aL,c0<.D"1MofCRCU8\l$)<6uh&d5r*݂,@0Gw&XfoHHiGUGfm,%P?(l(({(.ypb-[fj-^-o-R-vbGlu|PRG*y5]~5 rOSKJ\H:mY:H\^A0)i| S5`0.//#/#K(M:4R0H=T7q$~;Z6 1f:P(8&8(y~Fuu6U9c/ "$%=u-TI#!o}I%GD}K#KKJIUYWUBfA"L#;9-{`KzzViW?afP"cb5Y8~T3@/AXNql:X ^PYb1JhXh )&n}sO3Ti0j_"j#^#:Ju\f!%_@:0l|?d[Grh OO!,6+b)KhQ515+ y^}w@|Xk J&8F# NI ˂Z>$#yX(gN=e@: ,e}6E^v:3gZIe4#=2bGC_dUC#UY.YA}b*'):\f[|ΑF$8>. r#fFu80sl6R_NMD41;7G7{C8={ :'\<6r |d":hLf|9'K !eTv(XJL@|C9y*0!Ts]Vn*4#NQ,de\VpqOL .(Gn>NQd<_7e =71u#jq >Y .(6 Z6Hj`wx&!{>0a **625[S[F6q( TFm NN:\FK}>BeQ/%.#R~H#;Z4'b=W s~vPZ W^WZ!*7{=;u3{sS6 +843T;Mn8e$WRL;=&)f5n5Bz eHP~cu+4.tV+wH4n*

}& Rfa"<qTt!$?PqC'@ p+vS?L]MfV |NB( mkpCi}S&%UFaNV^$a{-~L|?H$>w=+~z~xr'$n']/EHƃN~utd~bC}t' j{ 8IN 12 #W>,* Ll.qW"9%zOCb6$60v6+N]&DLc&'CJ~ 5 9b:< f*eCuwdTVz}&~t&q QXXv$]20;peq4G^p9 kFwvF9GO5QPw6 P,=j(E) &_PJN%-b}rwk_v_@H DgzSO!>4FB2'N >2.Rw4.)IHU/|;Z-~vbP,y=i9*bNr< \yct >svVsHa wm2`S o)Ip$O%v+jm *9)CvExx?uex~lKLW}!&G,"B!$ ZHJ8V*|/s3U -gqGUc->al$9;Fh7lqaK c Gn ZJY m4!3iZJNIVAb m_ Q$S)^-F2" Pg)t "LEN>cXh" Gt;ws{4h_* cI#*y|/gRN7gFp79ZO`m8X8%_u{&%jAb giv%`0+)8a^I@3+gRn~fb$nywBG~CC59(+'? >Q%I2][bd_/)b-2FH!*vr"pZ:%)&kU}tHKYNp:? 6^u-?S=-BDn@+ha2FOQ-}1#/Hm %Dp -V:FZYT dI^C,E.]|z'L-(<Q0(i8d;}9ym@ ]恏Oqo/ISo78[Pntp&M%Km (S+V'({n-4QaMgM}*wpj5?A53Y~z!;m'}2Vy9v, $h<6g61sD@0J'gPF(5Cn_aIh{f{&v0IPq@mw6&/p=`#/F7hbno9iRL*-KP J%rv%aN0L CB=~S1N1SUK~_f&t@!(D( g6h'7pH]:p}=f$5 7S}B8T8t8%p?c)57;X^%ERRRkSHpf0SB}K>eGg Tvhm#u'Kx&C-9Pldvyw[#qotkAk2H+ >s pSl _W u 1rjVAJsF1Q\hq~.Fi'G wM<77:R\US-g{R)3Z(3:S7jyKV\&e{d6!6o_E1x= g.z1X\9Dy/l'^bwvrOK!"Gkf~ C!cM#MC!f#>;f@%FSh.m.e] i=.~uNz !)Xs'{KRSQo6 ;:%/3/ :- fr,qBhGS0~8?],;@9 U4* 4L"}V'DRfQft"K&:=DmQu/J|ADW(,sjfEb ^!$a~wL(X5H\f`jzq}?n?n?v?Wr^}k,SNT!ςeYq\*>9CEywUCX6b4}G9P ]d$I:r/qgjMS{h7NF{|"l"jDu("/#sb"-^{J%u2Yl\|ZekCq$.$9m&i5GNU/l6n]^.GofA2oE_ VFnV/9mqj n/8_29dWBA 95 M2h( {?P^vP2F`ZkC_R- ~itfqG] 'w d8gM:]pB{a}\1qcrYBH<z?_ZBhNd%rI4W8s`]_o]g.cN^Z\ &" $V\%E'-p (aMJ& -680\ nGV#%A΁@0!L@{6hG=^g#Ba~Kw ^v; b#?j||N^$(`.+}@l|A;w b("m.eGd+^O9z7P5h@ ׇ$=AbS0@E% _3V+i2Zp1e/0!#PQ{4K`4A="y+B.M%KNn4u)?9]'%9M+*EFS&7C]T K1?a>T"JuZ.nl,~Du(yT1B V %8E|EpqI~F] 6LZY@k`&{2W'4"=?a$tj&d7Vx\"?dD( 1 [Lym]]^}Uu ?A!.`z kQF<.dIv >"*L{B%7*(|% Pr5wqHKW2A!G@a=F}/Qw='#Ttp0|VN;@7T)Z"wAV.6\>[2 [ }c/orP rVJ]'r('#};"sum~NA=f Orkg%",4 &^l{EumN^P).lA%R??W]iv&OxdW  l*hiz`:Z7+:BT8Fb"SV`4]j]SU>/wept#b8. Cy-4%%&ZB}Oa'o|/aee|VgD A}x &A ?)uv~6*sB^(~!%'`_o'wf}YT=V," ]GE+!'mHFmW [%i}X2A`W6oxx|2\.l U'|o(,Jo#E~qA./y(@ ~Du<!M5,M;>j[$5_AV=v%tc_pN KT]-|\ YkM6&>~x43sU CVQ)daSB6&/:L{ t~ވE-W_[!xV?0\Cn$770GMUgT^ q;/D+Un8S3: xG>i_64},2WF~2zA8Ftzv Cp3mZ [I2u G gW!3M.S:p!u& [!'~:9|Y߇7CU6#c?Y:H\/t=Y]Qk1[P2GlPOXs==;-8ra}C$`>FpZn)1 :Ƃ~}n",-]~ )h\ _ 38 N7;x6)S[!R&{A=&Gd_3ecm-KH F=mXF:Sg-'''&;&4a 857~# UCV[pY9h/?Y/(^wej_Tn]fVR4S49 HaBP^[.GS 9,&XYITX/E9[LgYx:A  2Xye` d^0q.eK",.ssL l0bpdl+C&|HpZNFu?? q'*uSsa\!p;:},9cWEs^auCWQqAr>xnP8~.1 ?? !MPNWo>.15q.1 YeD1w `_7n5k-T+&K]$IG LV eaHod4O:6 @muT=U3Yvnus!= % j'0LnRA Be/)Ea zM_AlVf0Mh6FiUhM|4_\V7K&L9M M}[(@FV#GU8D7ze:ft?* m]Y$hHi.62u@Jw;>v f2J_e_pCy[t$q]u8r-If!8-P kQ MU.(X7)7fW^6ka1qoJ\B+2.$;Ok"$Q;ryz*jydmkX, %%kG&# >l/F|fK)v?Zm>>4ZL9OF9k},)@`_6G/U r8nQF^q+A,yw7C]35'hQ.l8oR~UC2Vr+ WTn@}L\I_B8w(e4RN 3ex1ba{BTAw)}7s'-7af^N?\QMKpY)GDW(MaK /FWT-?48*z-LG2> GCRB|?ify!nY7!rC٣hKI&:h'UH 6#[8>%5>M" I=~ -d0B; <n$Gsomyb QߍT!\EWe""hv.(HuPUk>!i f7|Sh<-!4?lNu1[@wMZ6G?KHy'6:-9#\KCOtP,rf' O(v Tc+j).-onla|8߁SS-(K w,0g\Q@% )']o@Beǁuul`Tk\^h)@5LeU~ !+ e2J5[3B ~?0R[[-'-nb0!NrPsZ=I?Lu/5" E`{%"yCNW& es<,u9X(_45C=u9WUU-/(xn")D}:XFS&pb^R"7V`qU6$;]S&nF;Z.@h(E;41!(#nIxYc A55czGCsV7iULKfF`$kPy85AQ2G&t.:\5R].}"Tw9A F ]mAvn>JDŽff0O =tMV݁/~R'iރ= zuXvbAwMuG \KSN JD9 K kO0-Cg=(?Jo.VzL][aZ ]Rqm:-nH`yz1hG?{x bCG" |4L9GDF1?pA6*{l{!#/A hdPZu-IP9{B"(uK]sVyq)X3 P-<&p?svvA+ Pj\v j-Pym%4. u'[7ɤT3m&tDo^G:yS28.1_CeKJ~LP8T/=^6䄦v*p' C9F& FzRhnOt[ 7"70TD N/0wQuNL&Qg /8_?QZJ G ηP R@>s(f[|t28Yt#@ T^%At 6_?]SUIL*5 i0BZ%%}r%e.|S&(VQ0aKY bI &U S~0-:nKA}0@!3YD**bI xC?;1@\31m1IsjӁ @T!cj!Hk.w/BZ~W*JxOx)" x%MN@e{c`n*OQ'<MiSOM 2:NLGj{Pn!8IFo \?!Zl΂'P:lB,,wznTY<9 93rffJW-,}9MV2L !n$[/i\Db!63}S\[MN|xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/file_v2.bin0000644000176500017650000046217212105354541025133 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------- Xdelta 3 The goal of this library is to to implement both the (stand-alone) data-compression and delta-compression aspects of VCDIFF encoding, and to support a programming interface that works like Zlib (http://www.gzip.org/zlib.html). See RFC3284: The VCDIFF Generic Differencing and Compression Data Format. VCDIFF is a unified encoding that combines data-compression and delta-encoding ("differencing"). VCDIFF has a detailed byte-code instruction set with many features. The instruction format supports an immediate size operand for small COPYs and ADDs (e.g., under 18 bytes). There are also instruction "modes", which are used to compress COPY addresses by using two address caches. An instruction mode refers to slots in the NEAR and SAME caches for recent addresses. NEAR remembers the previous 4 (by default) COPY addresses, and SAME catches frequent re-uses of the same address using a 3-way (by default) 256-entry associative cache of [ADDR mod 256], the encoded byte. A hit in the NEAR/SAME cache requires 0/1 ADDR bytes. VCDIFF has a default instruction table, but an alternate instruction tables may themselves be be delta-compressed and included in the encoding header. This allows even more freedom. There are 9 instruction modes in the default code table, 4 near, 3 same, VCD_SELF (absolute encoding) and VCD_HERE (relative to the current position). ---------------------------------------------------------------------- Algorithms Aside from the details of encoding and decoding, there are a bunch of algorithms needed. 1. STRING-MATCH. A two-level fingerprinting approach is used. A single loop computes the two checksums -- small and large -- at successive offsets in the TARGET file. The large checksum is more accurate and is used to discover SOURCE matches, which are potentially very long. The small checksum is used to discover copies within the TARGET. Small matching, which is more expensive, usually dominates the large STRING-MATCH costs in this code - the more exhaustive the search, the better the results. Either of the two string-matching mechanisms may be disabled. 2. INSTRUCTION SELECTION. The IOPT buffer here represents a queue used to store overlapping copy instructions. There are two possible optimizations that go beyond a greedy search. Both of these fall into the category of "non-greedy matching" optimizations. The first optimization stems from backward SOURCE-COPY matching. When a new SOURCE-COPY instruction covers a previous instruction in the target completely, it is erased from the queue. Randal Burns originally analyzed these algorithms and did a lot of related work (\cite the 1.5-pass algorithm). The second optimization comes by the encoding of common very-small COPY and ADD instructions, for which there are special DOUBLE-code instructions, which code two instructions in a single byte. The cost of bad instruction-selection overhead is relatively high for data-compression, relative to delta-compression, so this second optimization is fairly important. With "lazy" matching (the name used in Zlib for a similar optimization), the string-match algorithm searches after a match for potential overlapping copy instructions. In Xdelta and by default, VCDIFF, the minimum match size is 4 bytes, whereas Zlib searches with a 3-byte minimum. This feature, combined with double instructions, provides a nice challenge. Search in this file for "black magic", a heuristic. 3. STREAM ALIGNMENT. Stream alignment is needed to compress large inputs in constant space. See xd3_srcwin_move_point(). 4. WINDOW SELECTION. When the IOPT buffer flushes, in the first call to xd3_iopt_finish_encoding containing any kind of copy instruction, the parameters of the source window must be decided: the offset into the source and the length of the window. Since the IOPT buffer is finite, the program may be forced to fix these values before knowing the best offset/length. 5. SECONDARY COMPRESSION. VCDIFF supports a secondary encoding to be applied to the individual sections of the data format, which are ADDRess, INSTruction, and DATA. Several secondary compressor variations are implemented here, although none is standardized yet. One is an adaptive huffman algorithm -- the FGK algorithm (Faller, Gallager, and Knuth, 1985). This compressor is extremely slow. The other is a simple static Huffman routine, which is the base case of a semi-adaptive scheme published by D.J. Wheeler and first widely used in bzip2 (by Julian Seward). This is a very interesting algorithm, originally published in nearly cryptic form by D.J. Wheeler. !!!NOTE!!! Because these are not standardized, secondary compression remains off by default. ftp://ftp.cl.cam.ac.uk/users/djw3/bred3.{c,ps} -------------------------------------------------------------------- Other Features 1. USER CONVENIENCE For user convenience, it is essential to recognize Gzip-compressed files and automatically Gzip-decompress them prior to delta-compression (or else no delta-compression will be achieved unless the user manually decompresses the inputs). The compressed represention competes with Xdelta, and this must be hidden from the command-line user interface. The Xdelta-1.x encoding was simple, not compressed itself, so Xdelta-1.x uses Zlib internally to compress the representation. This implementation supports external compression, which implements the necessary fork() and pipe() mechanics. There is a tricky step involved to support automatic detection of a compressed input in a non-seekable input. First you read a bit of the input to detect magic headers. When a compressed format is recognized, exec() the external compression program and create a second child process to copy the original input stream. [Footnote: There is a difficulty related to using Gzip externally. It is not possible to decompress and recompress a Gzip file transparently. If FILE.GZ had a cryptographic signature, then, after: (1) Gzip-decompression, (2) Xdelta-encoding, (3) Gzip-compression the signature could be broken. The only way to solve this problem is to guess at Gzip's compression level or control it by other means. I recommend that specific implementations of any compression scheme store information needed to exactly re-compress the input, that way external compression is transparent - however, this won't happen here until it has stabilized.] 2. APPLICATION-HEADER This feature was introduced in RFC3284. It allows any application to include a header within the VCDIFF file format. This allows general inter-application data exchange with support for application-specific extensions to communicate metadata. 3. VCDIFF CHECKSUM An optional checksum value is included with each window, which can be used to validate the final result. This verifies the correct source file was used for decompression as well as the obvious advantage: checking the implementation (and underlying) correctness. 4. LIGHT WEIGHT The code makes efforts to avoid copying data more than necessary. The code delays many initialization tasks until the first use, it optimizes for identical (perfectly matching) inputs. It does not compute any checksums until the first lookup misses. Memory usage is reduced. String-matching is templatized (by slightly gross use of CPP) to hard-code alternative compile-time defaults. The code has few outside dependencies. ---------------------------------------------------------------------- The default rfc3284 instruction table: (see RFC for the explanation) TYPE SIZE MODE TYPE SIZE MODE INDEX -------------------------------------------------------------------- 1. Run 0 0 Noop 0 0 0 2. Add 0, [1,17] 0 Noop 0 0 [1,18] 3. Copy 0, [4,18] 0 Noop 0 0 [19,34] 4. Copy 0, [4,18] 1 Noop 0 0 [35,50] 5. Copy 0, [4,18] 2 Noop 0 0 [51,66] 6. Copy 0, [4,18] 3 Noop 0 0 [67,82] 7. Copy 0, [4,18] 4 Noop 0 0 [83,98] 8. Copy 0, [4,18] 5 Noop 0 0 [99,114] 9. Copy 0, [4,18] 6 Noop 0 0 [115,130] 10. Copy 0, [4,18] 7 Noop 0 0 [131,146] 11. Copy 0, [4,18] 8 Noop 0 0 [147,162] 12. Add [1,4] 0 Copy [4,6] 0 [163,174] 13. Add [1,4] 0 Copy [4,6] 1 [175,186] 14. Add [1,4] 0 Copy [4,6] 2 [187,198] 15. Add [1,4] 0 Copy [4,6] 3 [199,210] 16. Add [1,4] 0 Copy [4,6] 4 [211,222] 17. Add [1,4] 0 Copy [4,6] 5 [223,234] 18. Add [1,4] 0 Copy 4 6 [235,238] 19. Add [1,4] 0 Copy 4 7 [239,242] 20. Add [1,4] 0 Copy 4 8 [243,246] 21. Copy 4 [0,8] Add 1 0 [247,255] -------------------------------------------------------------------- Reading the source: Overview This file includes itself in several passes to macro-expand certain sections with variable forms. Just read ahead, there's only a little confusion. I know this sounds ugly, but hard-coding some of the string-matching parameters results in a 10-15% increase in string-match performance. The only time this hurts is when you have unbalanced #if/endifs. A single compilation unit tames the Makefile. In short, this is to allow the above-described hack without an explodingMakefile. The single compilation unit includes the core library features, configurable string-match templates, optional main() command-line tool, misc optional features, and a regression test. Features are controled with CPP #defines, see Makefile.am. The initial __XDELTA3_C_HEADER_PASS__ starts first, the _INLINE_ and _TEMPLATE_ sections follow. Easy stuff first, hard stuff last. Optional features include: xdelta3-main.h The command-line interface, external compression support, POSIX-specific, info & VCDIFF-debug tools. xdelta3-second.h The common secondary compression routines. xdelta3-decoder.h All decoding routines. xdelta3-djw.h The semi-adaptive huffman secondary encoder. xdelta3-fgk.h The adaptive huffman secondary encoder. xdelta3-test.h The unit test covers major algorithms, encoding and decoding. There are single-bit error decoding tests. There are 32/64-bit file size boundary tests. There are command-line tests. There are compression tests. There are external compression tests. There are string-matching tests. There should be more tests... Additional headers include: xdelta3.h The public header file. xdelta3-cfgs.h The default settings for default, built-in encoders. These are hard-coded at compile-time. There is also a single soft-coded string matcher for experimenting with arbitrary values. xdelta3-list.h A cyclic list template Misc little debug utilities: badcopy.c Randomly modifies an input file based on two parameters: (1) the probability that a byte in the file is replaced with a pseudo-random value, and (2) the mean change size. Changes are generated using an expoential distribution which approximates the expected error_prob distribution. -------------------------------------------------------------------- This file itself is unusually large. I hope to defend this layout with lots of comments. Everything in this file is related to encoding and decoding. I like it all together - the template stuff is just a hack. */ #ifndef __XDELTA3_C_HEADER_PASS__ #define __XDELTA3_C_HEADER_PASS__ #include #include #include "xdelta3.h" /*********************************************************************** STATIC CONFIGURATION ***********************************************************************/ #ifndef XD3_MAIN /* the main application */ #define XD3_MAIN 0 #endif #ifndef VCDIFF_TOOLS #define VCDIFF_TOOLS XD3_MAIN #endif #ifndef SECONDARY_FGK /* one from the algorithm preservation department: */ #define SECONDARY_FGK 0 /* adaptive Huffman routines */ #endif #ifndef SECONDARY_DJW /* semi-adaptive/static Huffman for the eventual */ #define SECONDARY_DJW 0 /* standardization, off by default until such time. */ #endif #ifndef GENERIC_ENCODE_TABLES /* These three are the RFC-spec'd app-specific */ #define GENERIC_ENCODE_TABLES 0 /* code features. This is tested but not recommended */ #endif /* unless there's a real application. */ #ifndef GENERIC_ENCODE_TABLES_COMPUTE #define GENERIC_ENCODE_TABLES_COMPUTE 0 #endif #ifndef GENERIC_ENCODE_TABLES_COMPUTE_PRINT #define GENERIC_ENCODE_TABLES_COMPUTE_PRINT 0 #endif #if XD3_ENCODER #define IF_ENCODER(x) x #else #define IF_ENCODER(x) #endif /***********************************************************************/ /* header indicator bits */ #define VCD_SECONDARY (1U << 0) /* uses secondary compressor */ #define VCD_CODETABLE (1U << 1) /* supplies code table data */ #define VCD_APPHEADER (1U << 2) /* supplies application data */ #define VCD_INVHDR (~0x7U) /* window indicator bits */ #define VCD_SOURCE (1U << 0) /* copy window in source file */ #define VCD_TARGET (1U << 1) /* copy window in target file */ #define VCD_ADLER32 (1U << 2) /* has adler32 checksum */ #define VCD_INVWIN (~0x7U) #define VCD_SRCORTGT (VCD_SOURCE | VCD_TARGET) /* delta indicator bits */ #define VCD_DATACOMP (1U << 0) #define VCD_INSTCOMP (1U << 1) #define VCD_ADDRCOMP (1U << 2) #define VCD_INVDEL (~0x7U) typedef enum { VCD_DJW_ID = 1, VCD_FGK_ID = 16, /* Note: these are not standard IANA-allocated IDs! */ } xd3_secondary_ids; typedef enum { SEC_NOFLAGS = 0, /* Note: SEC_COUNT_FREQS Not implemented (to eliminate 1st Huffman pass) */ SEC_COUNT_FREQS = (1 << 0), } xd3_secondary_flags; typedef enum { DATA_SECTION, /* These indicate which section to the secondary * compressor. */ INST_SECTION, /* The header section is not compressed, therefore not * listed here. */ ADDR_SECTION, } xd3_section_type; typedef unsigned int xd3_rtype; /***********************************************************************/ #include "xdelta3-list.h" XD3_MAKELIST(xd3_rlist, xd3_rinst, link); /***********************************************************************/ #define SECONDARY_MIN_SAVINGS 2 /* Secondary compression has to save at least this many bytes. */ #define SECONDARY_MIN_INPUT 10 /* Secondary compression needs at least this many bytes. */ #define VCDIFF_MAGIC1 0xd6 /* 1st file byte */ #define VCDIFF_MAGIC2 0xc3 /* 2nd file byte */ #define VCDIFF_MAGIC3 0xc4 /* 3rd file byte */ #define VCDIFF_VERSION 0x00 /* 4th file byte */ #define VCD_SELF 0 /* 1st address mode */ #define VCD_HERE 1 /* 2nd address mode */ #define CODE_TABLE_STRING_SIZE (6 * 256) /* Should fit a code table string. */ #define CODE_TABLE_VCDIFF_SIZE (6 * 256) /* Should fit a compressed code * table string */ #define SECONDARY_ANY (SECONDARY_DJW || SECONDARY_FGK) #define ALPHABET_SIZE 256 /* Used in test code--size of the secondary * compressor alphabet. */ #define HASH_PERMUTE 1 /* The input is permuted by random nums */ #define ADLER_LARGE_CKSUM 1 /* Adler checksum vs. RK checksum */ #define HASH_CKOFFSET 1U /* Table entries distinguish "no-entry" from * offset 0 using this offset. */ #define MIN_SMALL_LOOK 2U /* Match-optimization stuff. */ #define MIN_LARGE_LOOK 2U #define MIN_MATCH_OFFSET 1U #define MAX_MATCH_SPLIT 18U /* VCDIFF code table: 18 is the default limit * for direct-coded ADD sizes */ #define LEAST_MATCH_INCR 0 /* The least number of bytes an overlapping * match must beat the preceding match by. This * is a bias for the lazy match optimization. A * non-zero value means that an adjacent match * has to be better by more than the step * between them. 0. */ #define MIN_MATCH 4U /* VCDIFF code table: MIN_MATCH=4 */ #define MIN_ADD 1U /* 1 */ #define MIN_RUN 8U /* The shortest run, if it is shorter than this * an immediate add/copy will be just as good. * ADD1/COPY6 = 1I+1D+1A bytes, RUN18 = * 1I+1D+1A. */ #define MAX_MODES 9 /* Maximum number of nodes used for * compression--does not limit decompression. */ #define ENC_SECTS 4 /* Number of separate output sections. */ #define HDR_TAIL(s) ((s)->enc_tails[0]) #define DATA_TAIL(s) ((s)->enc_tails[1]) #define INST_TAIL(s) ((s)->enc_tails[2]) #define ADDR_TAIL(s) ((s)->enc_tails[3]) #define HDR_HEAD(s) ((s)->enc_heads[0]) #define DATA_HEAD(s) ((s)->enc_heads[1]) #define INST_HEAD(s) ((s)->enc_heads[2]) #define ADDR_HEAD(s) ((s)->enc_heads[3]) #define TOTAL_MODES(x) (2+(x)->acache.s_same+(x)->acache.s_near) /* Template instances. */ #if XD3_BUILD_SLOW #define IF_BUILD_SLOW(x) x #else #define IF_BUILD_SLOW(x) #endif #if XD3_BUILD_FAST #define IF_BUILD_FAST(x) x #else #define IF_BUILD_FAST(x) #endif #if XD3_BUILD_FASTER #define IF_BUILD_FASTER(x) x #else #define IF_BUILD_FASTER(x) #endif #if XD3_BUILD_FASTEST #define IF_BUILD_FASTEST(x) x #else #define IF_BUILD_FASTEST(x) #endif #if XD3_BUILD_SOFT #define IF_BUILD_SOFT(x) x #else #define IF_BUILD_SOFT(x) #endif #if XD3_BUILD_DEFAULT #define IF_BUILD_DEFAULT(x) x #else #define IF_BUILD_DEFAULT(x) #endif /* Consume N bytes of input, only used by the decoder. */ #define DECODE_INPUT(n) \ do { \ stream->total_in += (xoff_t) (n); \ stream->avail_in -= (n); \ stream->next_in += (n); \ } while (0) /* Update the run-length state */ #define NEXTRUN(c) do { if ((c) == run_c) { run_l += 1; } \ else { run_c = (c); run_l = 1; } } while (0) /* This CPP-conditional stuff can be cleaned up... */ #if REGRESSION_TEST #define IF_REGRESSION(x) x #else #define IF_REGRESSION(x) #endif /***********************************************************************/ #if XD3_ENCODER static void* xd3_alloc0 (xd3_stream *stream, usize_t elts, usize_t size); static xd3_output* xd3_alloc_output (xd3_stream *stream, xd3_output *old_output); static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts); static void xd3_free_output (xd3_stream *stream, xd3_output *output); static int xd3_emit_byte (xd3_stream *stream, xd3_output **outputp, uint8_t code); static int xd3_emit_bytes (xd3_stream *stream, xd3_output **outputp, const uint8_t *base, usize_t size); static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_rinst *second, usize_t code); static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, usize_t code); static usize_t xd3_sizeof_output (xd3_output *output); static void xd3_encode_reset (xd3_stream *stream); static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos); static int xd3_source_extend_match (xd3_stream *stream); static int xd3_srcwin_setup (xd3_stream *stream); static usize_t xd3_iopt_last_matched (xd3_stream *stream); static int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, uint32_t num); static usize_t xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_offset); static int xd3_string_match_init (xd3_stream *stream); static uint32_t xd3_scksum (uint32_t *state, const uint8_t *seg, const usize_t ln); static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp); static int xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point); static int xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c); static usize_t xd3_checksum_hash (const xd3_hash_cfg *cfg, const usize_t cksum); static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low); static void xd3_scksum_insert (xd3_stream *stream, usize_t inx, usize_t scksum, usize_t pos); #if XD3_DEBUG static void xd3_verify_run_state (xd3_stream *stream, const uint8_t *inp, usize_t x_run_l, uint8_t *x_run_c); static void xd3_verify_large_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum); static void xd3_verify_small_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum); #endif /* XD3_DEBUG */ #endif /* XD3_ENCODER */ static int xd3_decode_allocate (xd3_stream *stream, usize_t size, uint8_t **copied1, usize_t *alloc1); static void xd3_compute_code_table_string (const xd3_dinst *code_table, uint8_t *str); static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size); static void xd3_free (xd3_stream *stream, void *ptr); static int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint32_t *valp); #if REGRESSION_TEST static int xd3_selftest (void); #endif /***********************************************************************/ #define UINT32_OFLOW_MASK 0xfe000000U #define UINT64_OFLOW_MASK 0xfe00000000000000ULL #ifndef UINT32_MAX #define UINT32_MAX 4294967295U #endif #ifndef UINT64_MAX #define UINT64_MAX 18446744073709551615ULL #endif #if SIZEOF_USIZE_T == 4 #define USIZE_T_MAX UINT32_MAX #define xd3_decode_size xd3_decode_uint32_t #define xd3_emit_size xd3_emit_uint32_t #define xd3_sizeof_size xd3_sizeof_uint32_t #define xd3_read_size xd3_read_uint32_t #elif SIZEOF_USIZE_T == 8 #define USIZE_T_MAX UINT64_MAX #define xd3_decode_size xd3_decode_uint64_t #define xd3_emit_size xd3_emit_uint64_t #define xd3_sizeof_size xd3_sizeof_uint64_t #define xd3_read_size xd3_read_uint64_t #endif #if SIZEOF_XOFF_T == 4 #define XOFF_T_MAX UINT32_MAX #define xd3_decode_offset xd3_decode_uint32_t #define xd3_emit_offset xd3_emit_uint32_t #elif SIZEOF_XOFF_T == 8 #define XOFF_T_MAX UINT64_MAX #define xd3_decode_offset xd3_decode_uint64_t #define xd3_emit_offset xd3_emit_uint64_t #endif #define USIZE_T_OVERFLOW(a,b) ((USIZE_T_MAX - (usize_t) (a)) < (usize_t) (b)) #define XOFF_T_OVERFLOW(a,b) ((XOFF_T_MAX - (xoff_t) (a)) < (xoff_t) (b)) const char* xd3_strerror (int ret) { switch (ret) { case XD3_INPUT: return "XD3_INPUT"; case XD3_OUTPUT: return "XD3_OUTPUT"; case XD3_GETSRCBLK: return "XD3_GETSRCBLK"; case XD3_GOTHEADER: return "XD3_GOTHEADER"; case XD3_WINSTART: return "XD3_WINSTART"; case XD3_WINFINISH: return "XD3_WINFINISH"; case XD3_TOOFARBACK: return "XD3_TOOFARBACK"; case XD3_INTERNAL: return "XD3_INTERNAL"; case XD3_INVALID: return "XD3_INVALID"; case XD3_INVALID_INPUT: return "XD3_INVALID_INPUT"; case XD3_NOSECOND: return "XD3_NOSECOND"; case XD3_UNIMPLEMENTED: return "XD3_UNIMPLEMENTED"; } return NULL; } /***********************************************************************/ #define xd3_sec_data(s) ((s)->sec_stream_d) #define xd3_sec_inst(s) ((s)->sec_stream_i) #define xd3_sec_addr(s) ((s)->sec_stream_a) struct _xd3_sec_type { int id; const char *name; xd3_secondary_flags flags; /* xd3_sec_stream is opaque to the generic code */ xd3_sec_stream* (*alloc) (xd3_stream *stream); void (*destroy) (xd3_stream *stream, xd3_sec_stream *sec); void (*init) (xd3_sec_stream *sec); int (*decode) (xd3_stream *stream, xd3_sec_stream *sec_stream, const uint8_t **input, const uint8_t *input_end, uint8_t **output, const uint8_t *output_end); #if XD3_ENCODER int (*encode) (xd3_stream *stream, xd3_sec_stream *sec_stream, xd3_output *input, xd3_output *output, xd3_sec_cfg *cfg); #endif }; #define BIT_STATE_ENCODE_INIT { 0, 1 } #define BIT_STATE_DECODE_INIT { 0, 0x100 } typedef struct _bit_state bit_state; struct _bit_state { usize_t cur_byte; usize_t cur_mask; }; #if SECONDARY_ANY == 0 #define IF_SEC(x) #define IF_NSEC(x) x #else /* yuck */ #define IF_SEC(x) x #define IF_NSEC(x) static int xd3_decode_secondary (xd3_stream *stream, xd3_desect *sect, xd3_sec_stream **sec_streamp); #if XD3_ENCODER static int xd3_encode_secondary (xd3_stream *stream, xd3_output **head, xd3_output **tail, xd3_sec_stream **sec_streamp, xd3_sec_cfg *cfg, int *did_it); #endif #endif /* SECONDARY_ANY */ #if SECONDARY_FGK extern const xd3_sec_type fgk_sec_type; #define IF_FGK(x) x #define FGK_CASE(s) \ s->sec_type = & fgk_sec_type; \ break; #else #define IF_FGK(x) #define FGK_CASE(s) \ s->msg = "unavailable secondary compressor: FGK Adaptive Huffman"; \ return XD3_INTERNAL; #endif #if SECONDARY_DJW extern const xd3_sec_type djw_sec_type; #define IF_DJW(x) x #define DJW_CASE(s) \ s->sec_type = & djw_sec_type; \ break; #else #define IF_DJW(x) #define DJW_CASE(s) \ s->msg = "unavailable secondary compressor: DJW Static Huffman"; \ return XD3_INTERNAL; #endif /***********************************************************************/ #include "xdelta3-hash.h" /* Process template passes - this includes xdelta3.c several times. */ #define __XDELTA3_C_TEMPLATE_PASS__ #include "xdelta3-cfgs.h" #undef __XDELTA3_C_TEMPLATE_PASS__ /* Process the inline pass. */ #define __XDELTA3_C_INLINE_PASS__ #include "xdelta3.c" #undef __XDELTA3_C_INLINE_PASS__ /* Secondary compression */ #if SECONDARY_ANY #include "xdelta3-second.h" #endif #if SECONDARY_FGK #include "xdelta3-fgk.h" const xd3_sec_type fgk_sec_type = { VCD_FGK_ID, "FGK Adaptive Huffman", SEC_NOFLAGS, (xd3_sec_stream* (*)(xd3_stream*)) fgk_alloc, (void (*)(xd3_stream*, xd3_sec_stream*)) fgk_destroy, (void (*)(xd3_sec_stream*)) fgk_init, (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, uint8_t**, const uint8_t*)) xd3_decode_fgk, IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, xd3_output*, xd3_sec_cfg*)) xd3_encode_fgk) }; #endif #if SECONDARY_DJW #include "xdelta3-djw.h" const xd3_sec_type djw_sec_type = { VCD_DJW_ID, "Static Huffman", SEC_COUNT_FREQS, (xd3_sec_stream* (*)(xd3_stream*)) djw_alloc, (void (*)(xd3_stream*, xd3_sec_stream*)) djw_destroy, (void (*)(xd3_sec_stream*)) djw_init, (int (*)(xd3_stream*, xd3_sec_stream*, const uint8_t**, const uint8_t*, uint8_t**, const uint8_t*)) xd3_decode_huff, IF_ENCODER((int (*)(xd3_stream*, xd3_sec_stream*, xd3_output*, xd3_output*, xd3_sec_cfg*)) xd3_encode_huff) }; #endif #if XD3_MAIN || PYTHON_MODULE || SWIG_MODULE || NOT_MAIN #include "xdelta3-main.h" #endif #if REGRESSION_TEST #include "xdelta3-test.h" #endif #if PYTHON_MODULE #include "xdelta3-python.h" #endif #endif /* __XDELTA3_C_HEADER_PASS__ */ #ifdef __XDELTA3_C_INLINE_PASS__ /**************************************************************** Instruction tables *****************************************************************/ /* The following code implements a parametrized description of the * code table given above for a few reasons. It is not necessary for * implementing the standard, to support compression with variable * tables, so an implementation is only required to know the default * code table to begin decompression. (If the encoder uses an * alternate table, the table is included in compressed form inside * the VCDIFF file.) * * Before adding variable-table support there were two functions which * were hard-coded to the default table above. * xd3_compute_default_table() would create the default table by * filling a 256-elt array of xd3_dinst values. The corresponding * function, xd3_choose_instruction(), would choose an instruction * based on the hard-coded parameters of the default code table. * * Notes: The parametrized code table description here only generates * tables of a certain regularity similar to the default table by * allowing to vary the distribution of single- and * double-instructions and change the number of near and same copy * modes. More exotic tables are only possible by extending this * code. * * For performance reasons, both the parametrized and non-parametrized * versions of xd3_choose_instruction remain. The parametrized * version is only needed for testing multi-table decoding support. * If ever multi-table encoding is required, this can be optimized by * compiling static functions for each table. */ /* The XD3_CHOOSE_INSTRUCTION calls xd3_choose_instruction with the * table description when GENERIC_ENCODE_TABLES are in use. The * IF_GENCODETBL macro enables generic-code-table specific code. */ #if GENERIC_ENCODE_TABLES #define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (stream->code_table_desc, prev, inst) #define IF_GENCODETBL(x) x #else #define XD3_CHOOSE_INSTRUCTION(stream,prev,inst) xd3_choose_instruction (prev, inst) #define IF_GENCODETBL(x) #endif /* This structure maintains information needed by * xd3_choose_instruction to compute the code for a double instruction * by first indexing an array of code_table_sizes by copy mode, then * using (offset + (muliplier * X)) */ struct _xd3_code_table_sizes { uint8_t cpy_max; uint8_t offset; uint8_t mult; }; /* This contains a complete description of a code table. */ struct _xd3_code_table_desc { /* Assumes a single RUN instruction */ /* Assumes that MIN_MATCH is 4 */ uint8_t add_sizes; /* Number of immediate-size single adds (default 17) */ uint8_t near_modes; /* Number of near copy modes (default 4) */ uint8_t same_modes; /* Number of same copy modes (default 3) */ uint8_t cpy_sizes; /* Number of immediate-size single copies (default 15) */ uint8_t addcopy_add_max; /* Maximum add size for an add-copy double instruction, all modes (default 4) */ uint8_t addcopy_near_cpy_max; /* Maximum cpy size for an add-copy double instruction, up through VCD_NEAR modes (default 6) */ uint8_t addcopy_same_cpy_max; /* Maximum cpy size for an add-copy double instruction, VCD_SAME modes (default 4) */ uint8_t copyadd_add_max; /* Maximum add size for a copy-add double instruction, all modes (default 1) */ uint8_t copyadd_near_cpy_max; /* Maximum cpy size for a copy-add double instruction, up through VCD_NEAR modes (default 4) */ uint8_t copyadd_same_cpy_max; /* Maximum cpy size for a copy-add double instruction, VCD_SAME modes (default 4) */ xd3_code_table_sizes addcopy_max_sizes[MAX_MODES]; xd3_code_table_sizes copyadd_max_sizes[MAX_MODES]; }; /* The rfc3284 code table is represented: */ static const xd3_code_table_desc __rfc3284_code_table_desc = { 17, /* add sizes */ 4, /* near modes */ 3, /* same modes */ 15, /* copy sizes */ 4, /* add-copy max add */ 6, /* add-copy max cpy, near */ 4, /* add-copy max cpy, same */ 1, /* copy-add max add */ 4, /* copy-add max cpy, near */ 4, /* copy-add max cpy, same */ /* addcopy */ { {6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{4,235,1},{4,239,1},{4,243,1} }, /* copyadd */ { {4,247,1},{4,248,1},{4,249,1},{4,250,1},{4,251,1},{4,252,1},{4,253,1},{4,254,1},{4,255,1} }, }; #if GENERIC_ENCODE_TABLES /* An alternate code table for testing (5 near, 0 same): * * TYPE SIZE MODE TYPE SIZE MODE INDEX * --------------------------------------------------------------- * 1. Run 0 0 Noop 0 0 0 * 2. Add 0, [1,23] 0 Noop 0 0 [1,24] * 3. Copy 0, [4,20] 0 Noop 0 0 [25,42] * 4. Copy 0, [4,20] 1 Noop 0 0 [43,60] * 5. Copy 0, [4,20] 2 Noop 0 0 [61,78] * 6. Copy 0, [4,20] 3 Noop 0 0 [79,96] * 7. Copy 0, [4,20] 4 Noop 0 0 [97,114] * 8. Copy 0, [4,20] 5 Noop 0 0 [115,132] * 9. Copy 0, [4,20] 6 Noop 0 0 [133,150] * 10. Add [1,4] 0 Copy [4,6] 0 [151,162] * 11. Add [1,4] 0 Copy [4,6] 1 [163,174] * 12. Add [1,4] 0 Copy [4,6] 2 [175,186] * 13. Add [1,4] 0 Copy [4,6] 3 [187,198] * 14. Add [1,4] 0 Copy [4,6] 4 [199,210] * 15. Add [1,4] 0 Copy [4,6] 5 [211,222] * 16. Add [1,4] 0 Copy [4,6] 6 [223,234] * 17. Copy 4 [0,6] Add [1,3] 0 [235,255] * --------------------------------------------------------------- */ static const xd3_code_table_desc __alternate_code_table_desc = { 23, /* add sizes */ 5, /* near modes */ 0, /* same modes */ 17, /* copy sizes */ 4, /* add-copy max add */ 6, /* add-copy max cpy, near */ 0, /* add-copy max cpy, same */ 3, /* copy-add max add */ 4, /* copy-add max cpy, near */ 0, /* copy-add max cpy, same */ /* addcopy */ { {6,151,3},{6,163,3},{6,175,3},{6,187,3},{6,199,3},{6,211,3},{6,223,3},{0,0,0},{0,0,0} }, /* copyadd */ { {4,235,1},{4,238,1},{4,241,1},{4,244,1},{4,247,1},{4,250,1},{4,253,1},{0,0,0},{0,0,0} }, }; #endif /* Computes code table entries of TBL using the specified description. */ static void xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl) { usize_t size1, size2, mode; usize_t cpy_modes = 2 + desc->near_modes + desc->same_modes; xd3_dinst *d = tbl; (d++)->type1 = XD3_RUN; (d++)->type1 = XD3_ADD; for (size1 = 1; size1 <= desc->add_sizes; size1 += 1, d += 1) { d->type1 = XD3_ADD; d->size1 = size1; } for (mode = 0; mode < cpy_modes; mode += 1) { (d++)->type1 = XD3_CPY + mode; for (size1 = MIN_MATCH; size1 < MIN_MATCH + desc->cpy_sizes; size1 += 1, d += 1) { d->type1 = XD3_CPY + mode; d->size1 = size1; } } for (mode = 0; mode < cpy_modes; mode += 1) { for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1) { usize_t max = (mode < 2U + desc->near_modes) ? desc->addcopy_near_cpy_max : desc->addcopy_same_cpy_max; for (size2 = MIN_MATCH; size2 <= max; size2 += 1, d += 1) { d->type1 = XD3_ADD; d->size1 = size1; d->type2 = XD3_CPY + mode; d->size2 = size2; } } } for (mode = 0; mode < cpy_modes; mode += 1) { usize_t max = (mode < 2U + desc->near_modes) ? desc->copyadd_near_cpy_max : desc->copyadd_same_cpy_max; for (size1 = MIN_MATCH; size1 <= max; size1 += 1) { for (size2 = 1; size2 <= desc->copyadd_add_max; size2 += 1, d += 1) { d->type1 = XD3_CPY + mode; d->size1 = size1; d->type2 = XD3_ADD; d->size2 = size2; } } } XD3_ASSERT (d - tbl == 256); } /* This function generates the static default code table. */ static const xd3_dinst* xd3_rfc3284_code_table (void) { static xd3_dinst __rfc3284_code_table[256]; if (__rfc3284_code_table[0].type1 != XD3_RUN) { xd3_build_code_table (& __rfc3284_code_table_desc, __rfc3284_code_table); } return __rfc3284_code_table; } #if XD3_ENCODER #if GENERIC_ENCODE_TABLES /* This function generates the alternate code table. */ static const xd3_dinst* xd3_alternate_code_table (void) { static xd3_dinst __alternate_code_table[256]; if (__alternate_code_table[0].type1 != XD3_RUN) { xd3_build_code_table (& __alternate_code_table_desc, __alternate_code_table); } return __alternate_code_table; } /* This function computes the ideal second instruction INST based on * preceding instruction PREV. If it is possible to issue a double * instruction based on this pair it sets PREV->code2, otherwise it * sets INST->code1. */ static void xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_rinst *inst) { switch (inst->type) { case XD3_RUN: /* The 0th instruction is RUN */ inst->code1 = 0; break; case XD3_ADD: if (inst->size > desc->add_sizes) { /* The first instruction is non-immediate ADD */ inst->code1 = 1; } else { /* The following ADD_SIZES instructions are immediate ADDs */ inst->code1 = 1 + inst->size; /* Now check for a possible COPY-ADD double instruction */ if (prev != NULL) { int prev_mode = prev->type - XD3_CPY; /* If previous is a copy. Note: as long as the previous * is not a RUN instruction, it should be a copy because * it cannot be an add. This check is more clear. */ if (prev_mode >= 0 && inst->size <= desc->copyadd_add_max) { const xd3_code_table_sizes *sizes = & desc->copyadd_max_sizes[prev_mode]; /* This check and the inst->size-<= above are == in the default table. */ if (prev->size <= sizes->cpy_max) { /* The second and third exprs are 0 in the default table. */ prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_MATCH)) + (inst->size - MIN_ADD); } } } } break; default: { int mode = inst->type - XD3_CPY; /* The large copy instruction is offset by the run, large add, * and immediate adds, then multipled by the number of * immediate copies plus one (the large copy) (i.e., if there * are 15 immediate copy instructions then there are 16 copy * instructions per mode). */ inst->code1 = 2 + desc->add_sizes + (1 + desc->cpy_sizes) * mode; /* Now if the copy is short enough for an immediate instruction. */ if (inst->size < MIN_MATCH + desc->cpy_sizes && /* TODO: there needs to be a more comprehensive test for this * boundary condition, merge is now exercising code in which * size < MIN_MATCH is possible and it's unclear if the above * size < (MIN_MATCH + cpy_sizes) should be a <= from inspection * of the default table version below. */ inst->size >= MIN_MATCH) { inst->code1 += inst->size + 1 - MIN_MATCH; /* Now check for a possible ADD-COPY double instruction. */ if ( (prev != NULL) && (prev->type == XD3_ADD) && (prev->size <= desc->addcopy_add_max) ) { const xd3_code_table_sizes *sizes = & desc->addcopy_max_sizes[mode]; if (inst->size <= sizes->cpy_max) { prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_ADD)) + (inst->size - MIN_MATCH); } } } } } } #else /* GENERIC_ENCODE_TABLES */ /* This version of xd3_choose_instruction is hard-coded for the default table. */ static void xd3_choose_instruction (xd3_rinst *prev, xd3_rinst *inst) { switch (inst->type) { case XD3_RUN: inst->code1 = 0; break; case XD3_ADD: inst->code1 = 1; if (inst->size <= 17) { inst->code1 += inst->size; if ( (inst->size == 1) && (prev != NULL) && (prev->size == 4) && (prev->type >= XD3_CPY) ) { prev->code2 = 247 + (prev->type - XD3_CPY); } } break; default: { int mode = inst->type - XD3_CPY; XD3_ASSERT (inst->type >= XD3_CPY && inst->type < 12); inst->code1 = 19 + 16 * mode; if (inst->size <= 18 && inst->size >= 4) { inst->code1 += inst->size - 3; if ( (prev != NULL) && (prev->type == XD3_ADD) && (prev->size <= 4) ) { if ( (inst->size <= 6) && (mode <= 5) ) { prev->code2 = 163 + (mode * 12) + (3 * (prev->size - 1)) + (inst->size - 4); XD3_ASSERT (prev->code2 <= 234); } else if ( (inst->size == 4) && (mode >= 6) ) { prev->code2 = 235 + ((mode - 6) * 4) + (prev->size - 1); XD3_ASSERT (prev->code2 <= 246); } } } XD3_ASSERT (inst->code1 <= 162); } break; } } #endif /* GENERIC_ENCODE_TABLES */ /*********************************************************************** Instruction table encoder/decoder ***********************************************************************/ #if GENERIC_ENCODE_TABLES #if GENERIC_ENCODE_TABLES_COMPUTE == 0 /* In this case, we hard-code the result of * compute_code_table_encoding for each alternate code table, * presuming that saves time/space. This has been 131 bytes, but * secondary compression was turned off. */ static const uint8_t __alternate_code_table_compressed[178] = {0xd6,0xc3,0xc4,0x00,0x00,0x01,0x8a,0x6f,0x40,0x81,0x27,0x8c,0x00,0x00,0x4a,0x4a,0x0d,0x02,0x01,0x03, 0x01,0x03,0x00,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04, 0x04,0x04,0x04,0x00,0x04,0x05,0x06,0x01,0x02,0x03,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x05,0x05,0x05, 0x06,0x06,0x06,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x02,0x00,0x18,0x13,0x63,0x00,0x1b,0x00,0x54, 0x00,0x15,0x23,0x6f,0x00,0x28,0x13,0x54,0x00,0x15,0x01,0x1a,0x31,0x23,0x6c,0x0d,0x23,0x48,0x00,0x15, 0x93,0x6f,0x00,0x28,0x04,0x23,0x51,0x04,0x32,0x00,0x2b,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00, 0x12,0x00,0x12,0x53,0x57,0x9c,0x07,0x43,0x6f,0x00,0x34,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00, 0x0c,0x00,0x0c,0x00,0x15,0x00,0x82,0x6f,0x00,0x15,0x12,0x0c,0x00,0x03,0x03,0x00,0x06,0x00,}; static int xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) { (*data) = __alternate_code_table_compressed; (*size) = sizeof (__alternate_code_table_compressed); return 0; } #else /* The alternate code table will be computed and stored here. */ static uint8_t __alternate_code_table_compressed[CODE_TABLE_VCDIFF_SIZE]; static usize_t __alternate_code_table_compressed_size; /* This function generates a delta describing the code table for * encoding within a VCDIFF file. This function is NOT thread safe * because it is only intended that this function is used to generate * statically-compiled strings. "comp_string" must be sized * CODE_TABLE_VCDIFF_SIZE. */ int xd3_compute_code_table_encoding (xd3_stream *in_stream, const xd3_dinst *code_table, uint8_t *comp_string, usize_t *comp_string_size) { /* Use DJW secondary compression if it is on by default. This saves * about 20 bytes. */ uint8_t dflt_string[CODE_TABLE_STRING_SIZE]; uint8_t code_string[CODE_TABLE_STRING_SIZE]; xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); xd3_compute_code_table_string (code_table, code_string); return xd3_encode_memory (code_string, CODE_TABLE_STRING_SIZE, dflt_string, CODE_TABLE_STRING_SIZE, comp_string, comp_string_size, CODE_TABLE_VCDIFF_SIZE, /* flags */ 0); } /* Compute a delta between alternate and rfc3284 tables. As soon as * another alternate table is added, this code should become generic. * For now there is only one alternate table for testing. */ static int xd3_compute_alternate_table_encoding (xd3_stream *stream, const uint8_t **data, usize_t *size) { int ret; if (__alternate_code_table_compressed[0] == 0) { if ((ret = xd3_compute_code_table_encoding (stream, xd3_alternate_code_table (), __alternate_code_table_compressed, & __alternate_code_table_compressed_size))) { return ret; } /* During development of a new code table, enable this variable to print * the new static contents and determine its size. At run time the * table will be filled in appropriately, but at least it should have * the proper size beforehand. */ #if GENERIC_ENCODE_TABLES_COMPUTE_PRINT { int i; DP(RINT, "\nstatic const usize_t __alternate_code_table_compressed_size = %u;\n", __alternate_code_table_compressed_size); DP(RINT, "static const uint8_t __alternate_code_table_compressed[%u] =\n{", __alternate_code_table_compressed_size); for (i = 0; i < __alternate_code_table_compressed_size; i += 1) { DP(RINT, "0x%02x,", __alternate_code_table_compressed[i]); if ((i % 20) == 19) { DP(RINT, "\n"); } } DP(RINT, "};\n"); } #endif } (*data) = __alternate_code_table_compressed; (*size) = __alternate_code_table_compressed_size; return 0; } #endif /* GENERIC_ENCODE_TABLES_COMPUTE != 0 */ #endif /* GENERIC_ENCODE_TABLES */ #endif /* XD3_ENCODER */ /* This function generates the 1536-byte string specified in sections 5.4 and * 7 of rfc3284, which is used to represent a code table within a VCDIFF * file. */ void xd3_compute_code_table_string (const xd3_dinst *code_table, uint8_t *str) { int i, s; XD3_ASSERT (CODE_TABLE_STRING_SIZE == 6 * 256); for (s = 0; s < 6; s += 1) { for (i = 0; i < 256; i += 1) { switch (s) { case 0: *str++ = (code_table[i].type1 >= XD3_CPY ? XD3_CPY : code_table[i].type1); break; case 1: *str++ = (code_table[i].type2 >= XD3_CPY ? XD3_CPY : code_table[i].type2); break; case 2: *str++ = (code_table[i].size1); break; case 3: *str++ = (code_table[i].size2); break; case 4: *str++ = (code_table[i].type1 >= XD3_CPY ? code_table[i].type1 - XD3_CPY : 0); break; case 5: *str++ = (code_table[i].type2 >= XD3_CPY ? code_table[i].type2 - XD3_CPY : 0); break; } } } } /* This function translates the code table string into the internal representation. The * stream's near and same-modes should already be set. */ static int xd3_apply_table_string (xd3_stream *stream, const uint8_t *code_string) { int i, s; int modes = TOTAL_MODES (stream); xd3_dinst *code_table; if ((code_table = stream->code_table_alloc = (xd3_dinst*) xd3_alloc (stream, (usize_t) sizeof (xd3_dinst), 256)) == NULL) { return ENOMEM; } for (s = 0; s < 6; s += 1) { for (i = 0; i < 256; i += 1) { switch (s) { case 0: if (*code_string > XD3_CPY) { stream->msg = "invalid code-table opcode"; return XD3_INTERNAL; } code_table[i].type1 = *code_string++; break; case 1: if (*code_string > XD3_CPY) { stream->msg = "invalid code-table opcode"; return XD3_INTERNAL; } code_table[i].type2 = *code_string++; break; case 2: if (*code_string != 0 && code_table[i].type1 == XD3_NOOP) { stream->msg = "invalid code-table size"; return XD3_INTERNAL; } code_table[i].size1 = *code_string++; break; case 3: if (*code_string != 0 && code_table[i].type2 == XD3_NOOP) { stream->msg = "invalid code-table size"; return XD3_INTERNAL; } code_table[i].size2 = *code_string++; break; case 4: if (*code_string >= modes) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } if (*code_string != 0 && code_table[i].type1 != XD3_CPY) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } code_table[i].type1 += *code_string++; break; case 5: if (*code_string >= modes) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } if (*code_string != 0 && code_table[i].type2 != XD3_CPY) { stream->msg = "invalid code-table mode"; return XD3_INTERNAL; } code_table[i].type2 += *code_string++; break; } } } stream->code_table = code_table; return 0; } /* This function applies a code table delta and returns an actual code table. */ static int xd3_apply_table_encoding (xd3_stream *in_stream, const uint8_t *data, usize_t size) { uint8_t dflt_string[CODE_TABLE_STRING_SIZE]; uint8_t code_string[CODE_TABLE_STRING_SIZE]; usize_t code_size; int ret; xd3_compute_code_table_string (xd3_rfc3284_code_table (), dflt_string); if ((ret = xd3_decode_memory (data, size, dflt_string, CODE_TABLE_STRING_SIZE, code_string, &code_size, CODE_TABLE_STRING_SIZE, 0))) { return ret; } if (code_size != sizeof (code_string)) { in_stream->msg = "corrupt code-table encoding"; return XD3_INTERNAL; } return xd3_apply_table_string (in_stream, code_string); } /***********************************************************************/ static inline void xd3_swap_uint8p (uint8_t** p1, uint8_t** p2) { uint8_t *t = (*p1); (*p1) = (*p2); (*p2) = t; } static inline void xd3_swap_usize_t (usize_t* p1, usize_t* p2) { usize_t t = (*p1); (*p1) = (*p2); (*p2) = t; } /* It's not constant time, but it computes the log. */ static int xd3_check_pow2 (usize_t value, usize_t *logof) { usize_t x = 1; usize_t nolog; if (logof == NULL) { logof = &nolog; } *logof = 0; for (; x != 0; x <<= 1, *logof += 1) { if (x == value) { return 0; } } return XD3_INTERNAL; } static usize_t xd3_pow2_roundup (usize_t x) { usize_t i = 1; while (x > i) { i <<= 1U; } return i; } static usize_t xd3_round_blksize (usize_t sz, usize_t blksz) { usize_t mod = sz & (blksz-1); XD3_ASSERT (xd3_check_pow2 (blksz, NULL) == 0); return mod ? (sz + (blksz - mod)) : sz; } /*********************************************************************** Adler32 stream function: code copied from Zlib, defined in RFC1950 ***********************************************************************/ #define A32_BASE 65521L /* Largest prime smaller than 2^16 */ #define A32_NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define A32_DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define A32_DO2(buf,i) A32_DO1(buf,i); A32_DO1(buf,i+1); #define A32_DO4(buf,i) A32_DO2(buf,i); A32_DO2(buf,i+2); #define A32_DO8(buf,i) A32_DO4(buf,i); A32_DO4(buf,i+4); #define A32_DO16(buf) A32_DO8(buf,0); A32_DO8(buf,8); static unsigned long adler32 (unsigned long adler, const uint8_t *buf, usize_t len) { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; int k; while (len > 0) { k = (len < A32_NMAX) ? len : A32_NMAX; len -= k; while (k >= 16) { A32_DO16(buf); buf += 16; k -= 16; } if (k != 0) { do { s1 += *buf++; s2 += s1; } while (--k); } s1 %= A32_BASE; s2 %= A32_BASE; } return (s2 << 16) | s1; } /*********************************************************************** Run-length function ***********************************************************************/ #if XD3_ENCODER static usize_t xd3_comprun (const uint8_t *seg, usize_t slook, uint8_t *run_cp) { usize_t i; usize_t run_l = 0; uint8_t run_c = 0; for (i = 0; i < slook; i += 1) { NEXTRUN(seg[i]); } (*run_cp) = run_c; return run_l; } #endif /*********************************************************************** Basic encoder/decoder functions ***********************************************************************/ static inline int xd3_decode_byte (xd3_stream *stream, usize_t *val) { if (stream->avail_in == 0) { stream->msg = "further input required"; return XD3_INPUT; } (*val) = stream->next_in[0]; DECODE_INPUT (1); return 0; } static inline int xd3_decode_bytes (xd3_stream *stream, uint8_t *buf, usize_t *pos, usize_t size) { usize_t want; usize_t take; /* Note: The case where (*pos == size) happens when a zero-length * appheader or code table is transmitted, but there is nothing in * the standard against that. */ while (*pos < size) { if (stream->avail_in == 0) { stream->msg = "further input required"; return XD3_INPUT; } want = size - *pos; take = min (want, stream->avail_in); memcpy (buf + *pos, stream->next_in, (size_t) take); DECODE_INPUT (take); (*pos) += take; } return 0; } #if XD3_ENCODER static inline int xd3_emit_byte (xd3_stream *stream, xd3_output **outputp, uint8_t code) { xd3_output *output = (*outputp); if (output->next == output->avail) { xd3_output *aoutput; if ((aoutput = xd3_alloc_output (stream, output)) == NULL) { return ENOMEM; } output = (*outputp) = aoutput; } output->base[output->next++] = code; return 0; } static inline int xd3_emit_bytes (xd3_stream *stream, xd3_output **outputp, const uint8_t *base, usize_t size) { xd3_output *output = (*outputp); do { usize_t take; if (output->next == output->avail) { xd3_output *aoutput; if ((aoutput = xd3_alloc_output (stream, output)) == NULL) { return ENOMEM; } output = (*outputp) = aoutput; } take = min (output->avail - output->next, size); memcpy (output->base + output->next, base, (size_t) take); output->next += take; size -= take; base += take; } while (size > 0); return 0; } #endif /* XD3_ENCODER */ /********************************************************************* Integer encoder/decoder functions **********************************************************************/ #define DECODE_INTEGER_TYPE(PART,OFLOW) \ while (stream->avail_in != 0) \ { \ usize_t next = stream->next_in[0]; \ \ DECODE_INPUT(1); \ \ if (PART & OFLOW) \ { \ stream->msg = "overflow in decode_integer"; \ return XD3_INVALID_INPUT; \ } \ \ PART = (PART << 7) | (next & 127); \ \ if ((next & 128) == 0) \ { \ (*val) = PART; \ PART = 0; \ return 0; \ } \ } \ \ stream->msg = "further input required"; \ return XD3_INPUT #define READ_INTEGER_TYPE(TYPE, OFLOW) \ TYPE val = 0; \ const uint8_t *inp = (*inpp); \ usize_t next; \ \ do \ { \ if (inp == max) \ { \ stream->msg = "end-of-input in read_integer"; \ return XD3_INVALID_INPUT; \ } \ \ if (val & OFLOW) \ { \ stream->msg = "overflow in read_intger"; \ return XD3_INVALID_INPUT; \ } \ \ next = (*inp++); \ val = (val << 7) | (next & 127); \ } \ while (next & 128); \ \ (*valp) = val; \ (*inpp) = inp; \ \ return 0 #define EMIT_INTEGER_TYPE() \ /* max 64-bit value in base-7 encoding is 9.1 bytes */ \ uint8_t buf[10]; \ usize_t bufi = 10; \ \ /* This loop performs division and turns on all MSBs. */ \ do \ { \ buf[--bufi] = (num & 127) | 128; \ num >>= 7U; \ } \ while (num != 0); \ \ /* Turn off MSB of the last byte. */ \ buf[9] &= 127; \ \ return xd3_emit_bytes (stream, output, buf + bufi, 10 - bufi) #define IF_SIZEOF32(x) if (num < (1U << (7 * (x)))) return (x); #define IF_SIZEOF64(x) if (num < (1ULL << (7 * (x)))) return (x); #if USE_UINT32 static inline uint32_t xd3_sizeof_uint32_t (uint32_t num) { IF_SIZEOF32(1); IF_SIZEOF32(2); IF_SIZEOF32(3); IF_SIZEOF32(4); return 5; } static inline int xd3_decode_uint32_t (xd3_stream *stream, uint32_t *val) { DECODE_INTEGER_TYPE (stream->dec_32part, UINT32_OFLOW_MASK); } static inline int xd3_read_uint32_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint32_t *valp) { READ_INTEGER_TYPE (uint32_t, UINT32_OFLOW_MASK); } #if XD3_ENCODER static inline int xd3_emit_uint32_t (xd3_stream *stream, xd3_output **output, uint32_t num) { EMIT_INTEGER_TYPE (); } #endif #endif #if USE_UINT64 static inline int xd3_decode_uint64_t (xd3_stream *stream, uint64_t *val) { DECODE_INTEGER_TYPE (stream->dec_64part, UINT64_OFLOW_MASK); } #if XD3_ENCODER static inline int xd3_emit_uint64_t (xd3_stream *stream, xd3_output **output, uint64_t num) { EMIT_INTEGER_TYPE (); } #endif /* These are tested but not used */ #if REGRESSION_TEST static int xd3_read_uint64_t (xd3_stream *stream, const uint8_t **inpp, const uint8_t *max, uint64_t *valp) { READ_INTEGER_TYPE (uint64_t, UINT64_OFLOW_MASK); } static uint32_t xd3_sizeof_uint64_t (uint64_t num) { IF_SIZEOF64(1); IF_SIZEOF64(2); IF_SIZEOF64(3); IF_SIZEOF64(4); IF_SIZEOF64(5); IF_SIZEOF64(6); IF_SIZEOF64(7); IF_SIZEOF64(8); IF_SIZEOF64(9); return 10; } #endif #endif /*********************************************************************** Address cache stuff ***********************************************************************/ static int xd3_alloc_cache (xd3_stream *stream) { if (stream->acache.near_array != NULL) { xd3_free (stream, stream->acache.near_array); } if (stream->acache.same_array != NULL) { xd3_free (stream, stream->acache.same_array); } if (((stream->acache.s_near > 0) && (stream->acache.near_array = (usize_t*) xd3_alloc (stream, stream->acache.s_near, (usize_t) sizeof (usize_t))) == NULL) || ((stream->acache.s_same > 0) && (stream->acache.same_array = (usize_t*) xd3_alloc (stream, stream->acache.s_same * 256, (usize_t) sizeof (usize_t))) == NULL)) { return ENOMEM; } return 0; } void xd3_init_cache (xd3_addr_cache* acache) { if (acache->s_near > 0) { memset (acache->near_array, 0, acache->s_near * sizeof (usize_t)); acache->next_slot = 0; } if (acache->s_same > 0) { memset (acache->same_array, 0, acache->s_same * 256 * sizeof (usize_t)); } } static void xd3_update_cache (xd3_addr_cache* acache, usize_t addr) { if (acache->s_near > 0) { acache->near_array[acache->next_slot] = addr; acache->next_slot = (acache->next_slot + 1) % acache->s_near; } if (acache->s_same > 0) { acache->same_array[addr % (acache->s_same*256)] = addr; } } #if XD3_ENCODER /* OPT: this gets called a lot, can it be optimized? */ static int xd3_encode_address (xd3_stream *stream, usize_t addr, usize_t here, uint8_t* mode) { usize_t d, bestd; usize_t i, bestm, ret; xd3_addr_cache* acache = & stream->acache; #define SMALLEST_INT(x) do { if (((x) & ~127U) == 0) { goto good; } } while (0) /* Attempt to find the address mode that yields the smallest integer value * for "d", the encoded address value, thereby minimizing the encoded size * of the address. */ bestd = addr; bestm = VCD_SELF; XD3_ASSERT (addr < here); SMALLEST_INT (bestd); if ((d = here-addr) < bestd) { bestd = d; bestm = VCD_HERE; SMALLEST_INT (bestd); } for (i = 0; i < acache->s_near; i += 1) { /* Note: If we used signed computation here, we'd could compte d * and then check (d >= 0 && d < bestd). */ if (addr >= acache->near_array[i]) { d = addr - acache->near_array[i]; if (d < bestd) { bestd = d; bestm = i+2; /* 2 counts the VCD_SELF, VCD_HERE modes */ SMALLEST_INT (bestd); } } } if (acache->s_same > 0 && acache->same_array[d = addr%(acache->s_same*256)] == addr) { bestd = d%256; /* 2 + s_near offsets past the VCD_NEAR modes */ bestm = acache->s_near + 2 + d/256; if ((ret = xd3_emit_byte (stream, & ADDR_TAIL (stream), bestd))) { return ret; } } else { good: if ((ret = xd3_emit_size (stream, & ADDR_TAIL (stream), bestd))) { return ret; } } xd3_update_cache (acache, addr); (*mode) += bestm; return 0; } #endif static int xd3_decode_address (xd3_stream *stream, usize_t here, usize_t mode, const uint8_t **inpp, const uint8_t *max, uint32_t *valp) { int ret; usize_t same_start = 2 + stream->acache.s_near; if (mode < same_start) { if ((ret = xd3_read_size (stream, inpp, max, valp))) { return ret; } switch (mode) { case VCD_SELF: break; case VCD_HERE: (*valp) = here - (*valp); break; default: (*valp) += stream->acache.near_array[mode - 2]; break; } } else { if (*inpp == max) { stream->msg = "address underflow"; return XD3_INVALID_INPUT; } mode -= same_start; (*valp) = stream->acache.same_array[mode*256 + (**inpp)]; (*inpp) += 1; } xd3_update_cache (& stream->acache, *valp); return 0; } /*********************************************************************** Alloc/free ***********************************************************************/ static void* __xd3_alloc_func (void* opaque, usize_t items, usize_t size) { return malloc ((size_t) items * (size_t) size); } static void __xd3_free_func (void* opaque, void* address) { free (address); } static void* xd3_alloc (xd3_stream *stream, usize_t elts, usize_t size) { void *a = stream->alloc (stream->opaque, elts, size); if (a != NULL) { IF_DEBUG (stream->alloc_cnt += 1); IF_DEBUG2 (DP(RINT "[stream %p malloc] size %u ptr %p\n", stream, elts * size, a)); } else { stream->msg = "out of memory"; } return a; } static void xd3_free (xd3_stream *stream, void *ptr) { if (ptr != NULL) { IF_DEBUG (stream->free_cnt += 1); XD3_ASSERT (stream->free_cnt <= stream->alloc_cnt); IF_DEBUG2 (DP(RINT "[stream %p free] %p\n", stream, ptr)); stream->free (stream->opaque, ptr); } } #if XD3_ENCODER static void* xd3_alloc0 (xd3_stream *stream, usize_t elts, usize_t size) { void *a = xd3_alloc (stream, elts, size); if (a != NULL) { memset (a, 0, (size_t) (elts * size)); } return a; } static xd3_output* xd3_alloc_output (xd3_stream *stream, xd3_output *old_output) { xd3_output *output; uint8_t *base; if (stream->enc_free != NULL) { output = stream->enc_free; stream->enc_free = output->next_page; } else { if ((output = (xd3_output*) xd3_alloc (stream, 1, (usize_t) sizeof (xd3_output))) == NULL) { return NULL; } if ((base = (uint8_t*) xd3_alloc (stream, XD3_ALLOCSIZE, sizeof (uint8_t))) == NULL) { xd3_free (stream, output); return NULL; } output->base = base; output->avail = XD3_ALLOCSIZE; } output->next = 0; if (old_output) { old_output->next_page = output; } output->next_page = NULL; return output; } static usize_t xd3_sizeof_output (xd3_output *output) { usize_t s = 0; for (; output; output = output->next_page) { s += output->next; } return s; } static void xd3_freelist_output (xd3_stream *stream, xd3_output *output) { xd3_output *tmp; while (output) { tmp = output; output = output->next_page; tmp->next = 0; tmp->next_page = stream->enc_free; stream->enc_free = tmp; } } static void xd3_free_output (xd3_stream *stream, xd3_output *output) { xd3_output *next; again: if (output == NULL) { return; } next = output->next_page; xd3_free (stream, output->base); xd3_free (stream, output); output = next; goto again; } #endif /* XD3_ENCODER */ void xd3_free_stream (xd3_stream *stream) { xd3_iopt_buflist *blist = stream->iopt_alloc; while (blist != NULL) { xd3_iopt_buflist *tmp = blist; blist = blist->next; xd3_free (stream, tmp->buffer); xd3_free (stream, tmp); } xd3_free (stream, stream->large_table); xd3_free (stream, stream->small_table); xd3_free (stream, stream->small_prev); #if XD3_ENCODER { int i; for (i = 0; i < ENC_SECTS; i += 1) { xd3_free_output (stream, stream->enc_heads[i]); } xd3_free_output (stream, stream->enc_free); } #endif xd3_free (stream, stream->acache.near_array); xd3_free (stream, stream->acache.same_array); xd3_free (stream, stream->inst_sect.copied1); xd3_free (stream, stream->addr_sect.copied1); xd3_free (stream, stream->data_sect.copied1); xd3_free (stream, stream->dec_buffer); xd3_free (stream, (uint8_t*) stream->dec_lastwin); xd3_free (stream, stream->buf_in); xd3_free (stream, stream->dec_appheader); xd3_free (stream, stream->dec_codetbl); xd3_free (stream, stream->code_table_alloc); #if SECONDARY_ANY xd3_free (stream, stream->inst_sect.copied2); xd3_free (stream, stream->addr_sect.copied2); xd3_free (stream, stream->data_sect.copied2); if (stream->sec_type != NULL) { stream->sec_type->destroy (stream, stream->sec_stream_d); stream->sec_type->destroy (stream, stream->sec_stream_i); stream->sec_type->destroy (stream, stream->sec_stream_a); } #endif xd3_free (stream, stream->whole_target.adds); xd3_free (stream, stream->whole_target.inst); xd3_free (stream, stream->whole_target.wininfo); XD3_ASSERT (stream->alloc_cnt == stream->free_cnt); memset (stream, 0, sizeof (xd3_stream)); } #if (XD3_DEBUG > 1 || VCDIFF_TOOLS) static const char* xd3_rtype_to_string (xd3_rtype type, int print_mode) { switch (type) { case XD3_NOOP: return "NOOP "; case XD3_RUN: return "RUN "; case XD3_ADD: return "ADD "; default: break; } if (! print_mode) { return "CPY "; } switch (type) { case XD3_CPY + 0: return "CPY_0"; case XD3_CPY + 1: return "CPY_1"; case XD3_CPY + 2: return "CPY_2"; case XD3_CPY + 3: return "CPY_3"; case XD3_CPY + 4: return "CPY_4"; case XD3_CPY + 5: return "CPY_5"; case XD3_CPY + 6: return "CPY_6"; case XD3_CPY + 7: return "CPY_7"; case XD3_CPY + 8: return "CPY_8"; case XD3_CPY + 9: return "CPY_9"; default: return "CPY>9"; } } #endif /**************************************************************** Stream configuration ******************************************************************/ int xd3_config_stream(xd3_stream *stream, xd3_config *config) { int ret; xd3_config defcfg; xd3_smatcher *smatcher = &stream->smatcher; if (config == NULL) { config = & defcfg; memset (config, 0, sizeof (*config)); } /* Initial setup: no error checks yet */ memset (stream, 0, sizeof (*stream)); stream->winsize = config->winsize ? config->winsize : XD3_DEFAULT_WINSIZE; stream->sprevsz = config->sprevsz ? config->sprevsz : XD3_DEFAULT_SPREVSZ; stream->srcwin_maxsz = config->srcwin_maxsz ? config->srcwin_maxsz : XD3_DEFAULT_SRCWINSZ; if (config->iopt_size == 0) { stream->iopt_size = XD3_ALLOCSIZE / sizeof(xd3_rinst); stream->iopt_unlimited = 1; } else { stream->iopt_size = config->iopt_size; } stream->getblk = config->getblk; stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func; stream->free = config->freef ? config->freef : __xd3_free_func; stream->opaque = config->opaque; stream->flags = config->flags; /* Secondary setup. */ stream->sec_data = config->sec_data; stream->sec_inst = config->sec_inst; stream->sec_addr = config->sec_addr; stream->sec_data.data_type = DATA_SECTION; stream->sec_inst.data_type = INST_SECTION; stream->sec_addr.data_type = ADDR_SECTION; /* Check static sizes. */ if (sizeof (usize_t) != SIZEOF_USIZE_T || sizeof (xoff_t) != SIZEOF_XOFF_T || (ret = xd3_check_pow2(XD3_ALLOCSIZE, NULL))) { stream->msg = "incorrect compilation: wrong integer sizes"; return XD3_INTERNAL; } /* Check/set secondary compressor. */ switch (stream->flags & XD3_SEC_TYPE) { case 0: if (stream->flags & XD3_SEC_NOALL) { stream->msg = "XD3_SEC flags require a secondary compressor type"; return XD3_INTERNAL; } break; case XD3_SEC_FGK: FGK_CASE (stream); case XD3_SEC_DJW: DJW_CASE (stream); default: stream->msg = "too many secondary compressor types set"; return XD3_INTERNAL; } /* Check/set encoder code table. */ switch (stream->flags & XD3_ALT_CODE_TABLE) { case 0: stream->code_table_desc = & __rfc3284_code_table_desc; stream->code_table_func = xd3_rfc3284_code_table; break; #if GENERIC_ENCODE_TABLES case XD3_ALT_CODE_TABLE: stream->code_table_desc = & __alternate_code_table_desc; stream->code_table_func = xd3_alternate_code_table; stream->comp_table_func = xd3_compute_alternate_table_encoding; break; #endif default: stream->msg = "alternate code table support was not compiled"; return XD3_INTERNAL; } /* Check sprevsz */ if (smatcher->small_chain == 1 && smatcher->small_lchain == 1) { stream->sprevsz = 0; } else { if ((ret = xd3_check_pow2 (stream->sprevsz, NULL))) { stream->msg = "sprevsz is required to be a power of two"; return XD3_INTERNAL; } stream->sprevmask = stream->sprevsz - 1; } /* Default scanner settings. */ #if XD3_ENCODER switch (config->smatch_cfg) { IF_BUILD_SOFT(case XD3_SMATCH_SOFT: { *smatcher = config->smatcher_soft; smatcher->string_match = __smatcher_soft.string_match; smatcher->name = __smatcher_soft.name; if (smatcher->large_look < MIN_MATCH || smatcher->large_step < 1 || smatcher->small_look < MIN_MATCH) { stream->msg = "invalid soft string-match config"; return XD3_INVALID; } break; }) IF_BUILD_DEFAULT(case XD3_SMATCH_DEFAULT: *smatcher = __smatcher_default; break;) IF_BUILD_SLOW(case XD3_SMATCH_SLOW: *smatcher = __smatcher_slow; break;) IF_BUILD_FASTEST(case XD3_SMATCH_FASTEST: *smatcher = __smatcher_fastest; break;) IF_BUILD_FASTER(case XD3_SMATCH_FASTER: *smatcher = __smatcher_faster; break;) IF_BUILD_FAST(case XD3_SMATCH_FAST: *smatcher = __smatcher_fast; break;) default: stream->msg = "invalid string match config type"; return XD3_INTERNAL; } if (config->smatch_cfg == XD3_SMATCH_DEFAULT && (stream->flags & XD3_COMPLEVEL_MASK) != 0) { int level = (stream->flags & XD3_COMPLEVEL_MASK) >> XD3_COMPLEVEL_SHIFT; switch (level) { case 1: IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; break;) case 2: IF_BUILD_FASTER(*smatcher = __smatcher_faster; break;) case 3: case 4: case 5: IF_BUILD_FAST(*smatcher = __smatcher_fast; break;) case 6: IF_BUILD_DEFAULT(*smatcher = __smatcher_default; break;) default: IF_BUILD_SLOW(*smatcher = __smatcher_slow; break;) IF_BUILD_DEFAULT(*smatcher = __smatcher_default; break;) IF_BUILD_FAST(*smatcher = __smatcher_fast; break;) IF_BUILD_FASTER(*smatcher = __smatcher_faster; break;) IF_BUILD_FASTEST(*smatcher = __smatcher_fastest; break;) } } #endif return 0; } /*********************************************************** Getblk interface ***********************************************************/ inline xoff_t xd3_source_eof(const xd3_source *src) { xoff_t r = (src->blksize * src->max_blkno) + (xoff_t)src->onlastblk; return r; } inline usize_t xd3_bytes_on_srcblk (xd3_source *src, xoff_t blkno) { usize_t r = (blkno == src->max_blkno ? src->onlastblk : src->blksize); return r; } /* This function interfaces with the client getblk function, checks * its results, updates frontier_blkno, max_blkno, onlastblk, eof_known. */ static int xd3_getblk (xd3_stream *stream, xoff_t blkno) { int ret; xd3_source *source = stream->src; if (source->curblk == NULL || blkno != source->curblkno) { source->getblkno = blkno; if (stream->getblk == NULL) { stream->msg = "getblk source input"; return XD3_GETSRCBLK; } ret = stream->getblk (stream, source, blkno); if (ret != 0) { IF_DEBUG1 (DP(RINT "[getblk] app error blkno %"Q"u: %s\n", blkno, xd3_strerror (ret))); return ret; } } if (blkno >= source->frontier_blkno) { if (blkno > source->max_blkno) { source->max_blkno = blkno; source->onlastblk = source->onblk; } if (source->onblk == source->blksize) { source->frontier_blkno = blkno + 1; IF_DEBUG2 (DP(RINT "[getblk] full source blkno %"Q"u: " "source length unknown %"Q"u\n", blkno, xd3_source_eof (source))); } else { if (!source->eof_known) { IF_DEBUG2 (DP(RINT "[getblk] eof block has %d bytes; " "source length known %"Q"u\n", xd3_bytes_on_srcblk (source, blkno), xd3_source_eof (source))); source->eof_known = 1; } source->frontier_blkno = blkno; } } XD3_ASSERT (source->curblk != NULL); IF_DEBUG2 (DP(RINT "[getblk] read source block %"Q"u onblk %u blksize %u\n", blkno, source->onblk, source->blksize)); if (blkno == source->max_blkno) { /* In case the application sets the source as 1 block w/ a preset buffer. */ source->onlastblk = source->onblk; if (source->onblk == source->blksize) { source->frontier_blkno = blkno + 1; } } return 0; } /*********************************************************** Stream open/close ***************************************************************/ int xd3_set_source (xd3_stream *stream, xd3_source *src) { usize_t shiftby; stream->src = src; src->srclen = 0; src->srcbase = 0; /* Enforce power-of-two blocksize so that source-block number * calculations are cheap. */ if (!xd3_check_pow2 (src->blksize, &shiftby) == 0) { int check; src->blksize = xd3_pow2_roundup(src->blksize); check = xd3_check_pow2 (src->blksize, &shiftby); XD3_ASSERT (check == 0); IF_DEBUG1 (DP(RINT "raising srcblksz to %u\n", src->blksize)); } src->shiftby = shiftby; src->maskby = (1 << shiftby) - 1; return 0; } int xd3_set_source_and_size (xd3_stream *stream, xd3_source *user_source, xoff_t source_size) { int ret = xd3_set_source (stream, user_source); if (ret == 0) { stream->src->eof_known = 1; IF_DEBUG2 (DP(RINT "[set source] size known %"Q"u\n", source_size)); xd3_blksize_div(source_size, stream->src, &stream->src->max_blkno, &stream->src->onlastblk); } return ret; } void xd3_abort_stream (xd3_stream *stream) { stream->dec_state = DEC_ABORTED; stream->enc_state = ENC_ABORTED; } int xd3_close_stream (xd3_stream *stream) { if (stream->enc_state != 0 && stream->enc_state != ENC_ABORTED) { if (stream->buf_leftover != NULL) { stream->msg = "encoding is incomplete"; return XD3_INTERNAL; } if (stream->enc_state == ENC_POSTWIN) { #if XD3_ENCODER xd3_encode_reset (stream); #endif stream->current_window += 1; stream->enc_state = ENC_INPUT; } /* If encoding, should be ready for more input but not actually have any. */ if (stream->enc_state != ENC_INPUT || stream->avail_in != 0) { stream->msg = "encoding is incomplete"; return XD3_INTERNAL; } } else { switch (stream->dec_state) { case DEC_VCHEAD: case DEC_WININD: /* TODO: Address the zero-byte ambiguity. Does the encoder * emit a window or not? If so, then catch an error here. * If not, need another routine to say * decode_at_least_one_if_empty. */ case DEC_ABORTED: break; default: /* If decoding, should be ready for the next window. */ stream->msg = "EOF in decode"; return XD3_INTERNAL; } } return 0; } /************************************************************** Application header ****************************************************************/ int xd3_get_appheader (xd3_stream *stream, uint8_t **data, usize_t *size) { if (stream->dec_state < DEC_WININD) { stream->msg = "application header not available"; return XD3_INTERNAL; } (*data) = stream->dec_appheader; (*size) = stream->dec_appheadsz; return 0; } /********************************************************** Decoder stuff *************************************************/ #include "xdelta3-decode.h" /**************************************************************** Encoder stuff *****************************************************************/ #if XD3_ENCODER void xd3_set_appheader (xd3_stream *stream, const uint8_t *data, usize_t size) { stream->enc_appheader = data; stream->enc_appheadsz = size; } #if XD3_DEBUG static int xd3_iopt_check (xd3_stream *stream) { usize_t ul = xd3_rlist_length (& stream->iopt_used); usize_t fl = xd3_rlist_length (& stream->iopt_free); return (ul + fl + (stream->iout ? 1 : 0)) == stream->iopt_size; } #endif static xd3_rinst* xd3_iopt_free (xd3_stream *stream, xd3_rinst *i) { xd3_rinst *n = xd3_rlist_remove (i); xd3_rlist_push_back (& stream->iopt_free, i); return n; } static void xd3_iopt_free_nonadd (xd3_stream *stream, xd3_rinst *i) { if (i->type != XD3_ADD) { xd3_rlist_push_back (& stream->iopt_free, i); } } /* When an instruction is ready to flush from the iopt buffer, this * function is called to produce an encoding. It writes the * instruction plus size, address, and data to the various encoding * sections. */ static int xd3_iopt_finish_encoding (xd3_stream *stream, xd3_rinst *inst) { int ret; /* Check for input overflow. */ XD3_ASSERT (inst->pos + inst->size <= stream->avail_in); switch (inst->type) { case XD3_CPY: { /* the address may have an offset if there is a source window. */ usize_t addr; xd3_source *src = stream->src; if (src != NULL) { /* If there is a source copy, the source must have its * source window decided before we can encode. This can * be bad -- we have to make this decision even if no * source matches have been found. */ if (stream->srcwin_decided == 0) { if ((ret = xd3_srcwin_setup (stream))) { return ret; } } else { stream->srcwin_decided_early = (!stream->src->eof_known || (stream->srcwin_cksum_pos < xd3_source_eof (stream->src))); } /* xtra field indicates the copy is from the source */ if (inst->xtra) { XD3_ASSERT (inst->addr >= src->srcbase); XD3_ASSERT (inst->addr + inst->size <= src->srcbase + src->srclen); addr = (usize_t)(inst->addr - src->srcbase); stream->n_scpy += 1; stream->l_scpy += (xoff_t) inst->size; } else { /* with source window: target copy address is offset * by taroff. */ addr = stream->taroff + (usize_t) inst->addr; stream->n_tcpy += 1; stream->l_tcpy += (xoff_t) inst->size; } } else { addr = (usize_t) inst->addr; stream->n_tcpy += 1; stream->l_tcpy += inst->size; } /* Note: used to assert inst->size >= MIN_MATCH, but not true * for merge operations & identical match heuristics. */ /* the "here" position is always offset by taroff */ if ((ret = xd3_encode_address (stream, addr, inst->pos + stream->taroff, & inst->type))) { return ret; } IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt copy:%d] pos %"Q"u-%"Q"u addr %"Q"u-%"Q"u size %u\n", cnt++, stream->total_in + inst->pos, stream->total_in + inst->pos + inst->size, inst->addr, inst->addr + inst->size, inst->size); }); break; } case XD3_RUN: { XD3_ASSERT (inst->size >= MIN_MATCH); if ((ret = xd3_emit_byte (stream, & DATA_TAIL (stream), inst->xtra))) { return ret; } stream->n_run += 1; stream->l_run += inst->size; IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt run:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); }); break; } case XD3_ADD: { if ((ret = xd3_emit_bytes (stream, & DATA_TAIL (stream), stream->next_in + inst->pos, inst->size))) { return ret; } stream->n_add += 1; stream->l_add += inst->size; IF_DEBUG2 ({ static int cnt; DP(RINT "[iopt add:%d] pos %"Q"u size %u\n", cnt++, stream->total_in + inst->pos, inst->size); }); break; } } /* This is the only place stream->unencoded_offset is incremented. */ XD3_ASSERT (stream->unencoded_offset == inst->pos); stream->unencoded_offset += inst->size; inst->code2 = 0; XD3_CHOOSE_INSTRUCTION (stream, stream->iout, inst); if (stream->iout != NULL) { if (stream->iout->code2 != 0) { if ((ret = xd3_emit_double (stream, stream->iout, inst, stream->iout->code2))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); xd3_iopt_free_nonadd (stream, inst); stream->iout = NULL; return 0; } else { if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); } } stream->iout = inst; return 0; } /* This possibly encodes an add instruction, iadd, which must remain * on the stack until the following call to * xd3_iopt_finish_encoding. */ static int xd3_iopt_add (xd3_stream *stream, usize_t pos, xd3_rinst *iadd) { int ret; usize_t off = stream->unencoded_offset; if (pos > off) { iadd->type = XD3_ADD; iadd->pos = off; iadd->size = pos - off; if ((ret = xd3_iopt_finish_encoding (stream, iadd))) { return ret; } } return 0; } /* This function calls xd3_iopt_finish_encoding to finish encoding an * instruction, and it may also produce an add instruction for an * unmatched region. */ static int xd3_iopt_add_encoding (xd3_stream *stream, xd3_rinst *inst) { int ret; xd3_rinst iadd; if ((ret = xd3_iopt_add (stream, inst->pos, & iadd))) { return ret; } if ((ret = xd3_iopt_finish_encoding (stream, inst))) { return ret; } return 0; } /* Generates a final add instruction to encode the remaining input. */ static int xd3_iopt_add_finalize (xd3_stream *stream) { int ret; xd3_rinst iadd; if ((ret = xd3_iopt_add (stream, stream->avail_in, & iadd))) { return ret; } if (stream->iout) { if ((ret = xd3_emit_single (stream, stream->iout, stream->iout->code1))) { return ret; } xd3_iopt_free_nonadd (stream, stream->iout); stream->iout = NULL; } return 0; } /* Compact the instruction buffer by choosing the best non-overlapping * instructions when lazy string-matching. There are no ADDs in the * iopt buffer because those are synthesized in xd3_iopt_add_encoding * and during xd3_iopt_add_finalize. */ static int xd3_iopt_flush_instructions (xd3_stream *stream, int force) { xd3_rinst *r1 = xd3_rlist_front (& stream->iopt_used); xd3_rinst *r2; xd3_rinst *r3; usize_t r1end; usize_t r2end; usize_t r2off; usize_t r2moff; usize_t gap; usize_t flushed; int ret; XD3_ASSERT (xd3_iopt_check (stream)); /* Note: once tried to skip this step if it's possible to assert * there are no overlapping instructions. Doesn't work because * xd3_opt_erase leaves overlapping instructions. */ while (! xd3_rlist_end (& stream->iopt_used, r1) && ! xd3_rlist_end (& stream->iopt_used, r2 = xd3_rlist_next (r1))) { r1end = r1->pos + r1->size; /* If the instructions do not overlap, continue. */ if (r1end <= r2->pos) { r1 = r2; continue; } r2end = r2->pos + r2->size; /* The min_match adjustments prevent this. */ XD3_ASSERT (r2end > (r1end + LEAST_MATCH_INCR)); /* If r3 is available... */ if (! xd3_rlist_end (& stream->iopt_used, r3 = xd3_rlist_next (r2))) { /* If r3 starts before r1 finishes or just about, r2 is irrelevant */ if (r3->pos <= r1end + 1) { xd3_iopt_free (stream, r2); continue; } } else if (! force) { /* Unless force, end the loop when r3 is not available. */ break; } r2off = r2->pos - r1->pos; r2moff = r2end - r1end; gap = r2end - r1->pos; /* If the two matches overlap almost entirely, choose the better match * and discard the other. The else branch can still create inefficient * copies, e.g., a 4-byte copy that takes 4 bytes to encode, which * xd3_smatch() wouldn't allow by its crude efficiency check. However, * in this case there are adjacent copies which mean the add would cost * one extra byte. Allow the inefficiency here. */ if (gap < 2*MIN_MATCH || r2moff <= 2 || r2off <= 2) { /* Only one match should be used, choose the longer one. */ if (r1->size < r2->size) { xd3_iopt_free (stream, r1); r1 = r2; } else { /* We are guaranteed that r1 does not overlap now, so advance past r2 */ r1 = xd3_iopt_free (stream, r2); } continue; } else { /* Shorten one of the instructions -- could be optimized * based on the address cache. */ usize_t average; usize_t newsize; usize_t adjust1; XD3_ASSERT (r1end > r2->pos && r2end > r1->pos); /* Try to balance the length of both instructions, but avoid * making both longer than MAX_MATCH_SPLIT . */ average = gap / 2; newsize = min (MAX_MATCH_SPLIT, gap - average); /* Should be possible to simplify this code. */ if (newsize > r1->size) { /* shorten r2 */ adjust1 = r1end - r2->pos; } else if (newsize > r2->size) { /* shorten r1 */ adjust1 = r1end - r2->pos; XD3_ASSERT (r1->size > adjust1); r1->size -= adjust1; /* don't shorten r2 */ adjust1 = 0; } else { /* shorten r1 */ adjust1 = r1->size - newsize; if (r2->pos > r1end - adjust1) { adjust1 -= r2->pos - (r1end - adjust1); } XD3_ASSERT (r1->size > adjust1); r1->size -= adjust1; /* shorten r2 */ XD3_ASSERT (r1->pos + r1->size >= r2->pos); adjust1 = r1->pos + r1->size - r2->pos; } /* Fallthrough above if-else, shorten r2 */ XD3_ASSERT (r2->size > adjust1); r2->size -= adjust1; r2->pos += adjust1; r2->addr += adjust1; XD3_ASSERT (r1->size >= MIN_MATCH); XD3_ASSERT (r2->size >= MIN_MATCH); r1 = r2; } } XD3_ASSERT (xd3_iopt_check (stream)); /* If forcing, pick instructions until the list is empty, otherwise * this empties 50% of the queue. */ for (flushed = 0; ! xd3_rlist_empty (& stream->iopt_used); ) { xd3_rinst *renc = xd3_rlist_pop_front (& stream->iopt_used); if ((ret = xd3_iopt_add_encoding (stream, renc))) { return ret; } if (! force) { if (++flushed > stream->iopt_size / 2) { break; } /* If there are only two instructions remaining, break, * because they were not optimized. This means there were * more than 50% eliminated by the loop above. */ r1 = xd3_rlist_front (& stream->iopt_used); if (xd3_rlist_end(& stream->iopt_used, r1) || xd3_rlist_end(& stream->iopt_used, r2 = xd3_rlist_next (r1)) || xd3_rlist_end(& stream->iopt_used, r3 = xd3_rlist_next (r2))) { break; } } } XD3_ASSERT (xd3_iopt_check (stream)); XD3_ASSERT (!force || xd3_rlist_length (& stream->iopt_used) == 0); return 0; } static int xd3_iopt_get_slot (xd3_stream *stream, xd3_rinst** iptr) { xd3_rinst *i; int ret; if (xd3_rlist_empty (& stream->iopt_free)) { if (stream->iopt_unlimited) { usize_t elts = XD3_ALLOCSIZE / sizeof(xd3_rinst); if ((ret = xd3_alloc_iopt (stream, elts))) { return ret; } stream->iopt_size += elts; } else { if ((ret = xd3_iopt_flush_instructions (stream, 0))) { return ret; } XD3_ASSERT (! xd3_rlist_empty (& stream->iopt_free)); } } i = xd3_rlist_pop_back (& stream->iopt_free); xd3_rlist_push_back (& stream->iopt_used, i); (*iptr) = i; ++stream->i_slots_used; return 0; } /* A copy is about to be emitted that extends backwards to POS, * therefore it may completely cover some existing instructions in the * buffer. If an instruction is completely covered by this new match, * erase it. If the new instruction is covered by the previous one, * return 1 to skip it. */ static void xd3_iopt_erase (xd3_stream *stream, usize_t pos, usize_t size) { while (! xd3_rlist_empty (& stream->iopt_used)) { xd3_rinst *r = xd3_rlist_back (& stream->iopt_used); /* Verify that greedy is working. The previous instruction * should end before the new one begins. */ XD3_ASSERT ((stream->flags & XD3_BEGREEDY) == 0 || (r->pos + r->size <= pos)); /* Verify that min_match is working. The previous instruction * should end before the new one ends. */ XD3_ASSERT ((stream->flags & XD3_BEGREEDY) != 0 || (r->pos + r->size < pos + size)); /* See if the last instruction starts before the new * instruction. If so, there is nothing to erase. */ if (r->pos < pos) { return; } /* Otherwise, the new instruction covers the old one, delete it and repeat. */ xd3_rlist_remove (r); xd3_rlist_push_back (& stream->iopt_free, r); --stream->i_slots_used; } } /* This function tells the last matched input position. */ static usize_t xd3_iopt_last_matched (xd3_stream *stream) { xd3_rinst *r; if (xd3_rlist_empty (& stream->iopt_used)) { return 0; } r = xd3_rlist_back (& stream->iopt_used); return r->pos + r->size; } /********************************************************* Emit routines ***********************************************************/ static int xd3_emit_single (xd3_stream *stream, xd3_rinst *single, usize_t code) { int has_size = stream->code_table[code].size1 == 0; int ret; IF_DEBUG2 (DP(RINT "[emit1] %u %s (%u) code %u\n", single->pos, xd3_rtype_to_string ((xd3_rtype) single->type, 0), single->size, code)); if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) { return ret; } if (has_size) { if ((ret = xd3_emit_size (stream, & INST_TAIL (stream), single->size))) { return ret; } } return 0; } static int xd3_emit_double (xd3_stream *stream, xd3_rinst *first, xd3_rinst *second, usize_t code) { int ret; /* All double instructions use fixed sizes, so all we need to do is * output the instruction code, no sizes. */ XD3_ASSERT (stream->code_table[code].size1 != 0 && stream->code_table[code].size2 != 0); if ((ret = xd3_emit_byte (stream, & INST_TAIL (stream), code))) { return ret; } IF_DEBUG2 (DP(RINT "[emit2]: %u %s (%u) %s (%u) code %u\n", first->pos, xd3_rtype_to_string ((xd3_rtype) first->type, 0), first->size, xd3_rtype_to_string ((xd3_rtype) second->type, 0), second->size, code)); return 0; } /* This enters a potential run instruction into the iopt buffer. The * position argument is relative to the target window. */ static int xd3_emit_run (xd3_stream *stream, usize_t pos, usize_t size, uint8_t *run_c) { xd3_rinst* ri; int ret; if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } ri->type = XD3_RUN; ri->xtra = *run_c; ri->pos = pos; ri->size = size; return 0; } /* This enters a potential copy instruction into the iopt buffer. The * position argument is relative to the target window.. */ int xd3_found_match (xd3_stream *stream, usize_t pos, usize_t size, xoff_t addr, int is_source) { xd3_rinst* ri; int ret; if ((ret = xd3_iopt_get_slot (stream, & ri))) { return ret; } ri->type = XD3_CPY; ri->xtra = is_source; ri->pos = pos; ri->size = size; ri->addr = addr; return 0; } static int xd3_emit_hdr (xd3_stream *stream) { int ret; int use_secondary = stream->sec_type != NULL; int use_adler32 = stream->flags & (XD3_ADLER32 | XD3_ADLER32_RECODE); int vcd_source = xd3_encoder_used_source (stream); usize_t win_ind = 0; usize_t del_ind = 0; usize_t enc_len; usize_t tgt_len; usize_t data_len; usize_t inst_len; usize_t addr_len; if (stream->current_window == 0) { usize_t hdr_ind = 0; int use_appheader = stream->enc_appheader != NULL; int use_gencodetbl = GENERIC_ENCODE_TABLES && (stream->code_table_desc != & __rfc3284_code_table_desc); if (use_secondary) { hdr_ind |= VCD_SECONDARY; } if (use_gencodetbl) { hdr_ind |= VCD_CODETABLE; } if (use_appheader) { hdr_ind |= VCD_APPHEADER; } if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC1)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC2)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_MAGIC3)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), VCDIFF_VERSION)) != 0 || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), hdr_ind)) != 0) { return ret; } /* Secondary compressor ID */ #if SECONDARY_ANY if (use_secondary && (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->sec_type->id))) { return ret; } #endif /* Compressed code table */ if (use_gencodetbl) { usize_t code_table_size; const uint8_t *code_table_data; if ((ret = stream->comp_table_func (stream, & code_table_data, & code_table_size))) { return ret; } if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), code_table_size + 2)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->code_table_desc->near_modes)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), stream->code_table_desc->same_modes)) || (ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), code_table_data, code_table_size))) { return ret; } } /* Application header */ if (use_appheader) { if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), stream->enc_appheadsz)) || (ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), stream->enc_appheader, stream->enc_appheadsz))) { return ret; } } } /* try to compress this window */ #if SECONDARY_ANY if (use_secondary) { int data_sec = 0; int inst_sec = 0; int addr_sec = 0; # define ENCODE_SECONDARY_SECTION(UPPER,LOWER) \ ((stream->flags & XD3_SEC_NO ## UPPER) == 0 && \ (ret = xd3_encode_secondary (stream, \ & UPPER ## _HEAD (stream), \ & UPPER ## _TAIL (stream), \ & xd3_sec_ ## LOWER (stream), \ & stream->sec_ ## LOWER, \ & LOWER ## _sec))) if (ENCODE_SECONDARY_SECTION (DATA, data) || ENCODE_SECONDARY_SECTION (INST, inst) || ENCODE_SECONDARY_SECTION (ADDR, addr)) { return ret; } del_ind |= (data_sec ? VCD_DATACOMP : 0); del_ind |= (inst_sec ? VCD_INSTCOMP : 0); del_ind |= (addr_sec ? VCD_ADDRCOMP : 0); } #endif /* if (vcd_target) { win_ind |= VCD_TARGET; } */ if (vcd_source) { win_ind |= VCD_SOURCE; } if (use_adler32) { win_ind |= VCD_ADLER32; } /* window indicator */ if ((ret = xd3_emit_byte (stream, & HDR_TAIL (stream), win_ind))) { return ret; } /* source window */ if (vcd_source) { /* or (vcd_target) { ... } */ if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), stream->src->srclen)) || (ret = xd3_emit_offset (stream, & HDR_TAIL (stream), stream->src->srcbase))) { return ret; } } tgt_len = stream->avail_in; data_len = xd3_sizeof_output (DATA_HEAD (stream)); inst_len = xd3_sizeof_output (INST_HEAD (stream)); addr_len = xd3_sizeof_output (ADDR_HEAD (stream)); /* The enc_len field is a redundency for future extensions.*/ enc_len = (1 + (xd3_sizeof_size (tgt_len) + xd3_sizeof_size (data_len) + xd3_sizeof_size (inst_len) + xd3_sizeof_size (addr_len)) + data_len + inst_len + addr_len + (use_adler32 ? 4 : 0)); if ((ret = xd3_emit_size (stream, & HDR_TAIL (stream), enc_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), tgt_len)) || (ret = xd3_emit_byte (stream, & HDR_TAIL (stream), del_ind)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), data_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), inst_len)) || (ret = xd3_emit_size (stream, & HDR_TAIL (stream), addr_len))) { return ret; } if (use_adler32) { uint8_t send[4]; uint32_t a32; if (stream->flags & XD3_ADLER32) { a32 = adler32 (1L, stream->next_in, stream->avail_in); } else { a32 = stream->recode_adler32; } /* Four bytes. */ send[0] = (uint8_t) (a32 >> 24); send[1] = (uint8_t) (a32 >> 16); send[2] = (uint8_t) (a32 >> 8); send[3] = (uint8_t) (a32 & 0x000000FFU); if ((ret = xd3_emit_bytes (stream, & HDR_TAIL (stream), send, 4))) { return ret; } } return 0; } /**************************************************************** Encode routines ****************************************************************/ static int xd3_encode_buffer_leftover (xd3_stream *stream) { usize_t take; usize_t room; /* Allocate the buffer. */ if (stream->buf_in == NULL && (stream->buf_in = (uint8_t*) xd3_alloc (stream, stream->winsize, 1)) == NULL) { return ENOMEM; } IF_DEBUG2 (DP(RINT "[leftover] flush?=%s\n", (stream->flags & XD3_FLUSH) ? "yes" : "no")); /* Take leftover input first. */ if (stream->buf_leftover != NULL) { XD3_ASSERT (stream->buf_avail == 0); XD3_ASSERT (stream->buf_leftavail < stream->winsize); IF_DEBUG2 (DP(RINT "[leftover] previous %u avail %u\n", stream->buf_leftavail, stream->avail_in)); memcpy (stream->buf_in, stream->buf_leftover, stream->buf_leftavail); stream->buf_leftover = NULL; stream->buf_avail = stream->buf_leftavail; } /* Copy into the buffer. */ room = stream->winsize - stream->buf_avail; take = min (room, stream->avail_in); memcpy (stream->buf_in + stream->buf_avail, stream->next_in, take); stream->buf_avail += take; if (take < stream->avail_in) { /* Buffer is full */ stream->buf_leftover = stream->next_in + take; stream->buf_leftavail = stream->avail_in - take; } else if ((stream->buf_avail < stream->winsize) && !(stream->flags & XD3_FLUSH)) { /* Buffer has space */ IF_DEBUG2 (DP(RINT "[leftover] emptied %u\n", take)); return XD3_INPUT; } /* Use the buffer: */ IF_DEBUG2 (DP(RINT "[leftover] take %u remaining %u\n", take, stream->buf_leftavail)); stream->next_in = stream->buf_in; stream->avail_in = stream->buf_avail; stream->buf_avail = 0; return 0; } /* Allocates one block of xd3_rlist elements */ static int xd3_alloc_iopt (xd3_stream *stream, usize_t elts) { usize_t i; xd3_iopt_buflist* last = (xd3_iopt_buflist*) xd3_alloc (stream, sizeof (xd3_iopt_buflist), 1); if (last == NULL || (last->buffer = (xd3_rinst*) xd3_alloc (stream, sizeof (xd3_rinst), elts)) == NULL) { return ENOMEM; } last->next = stream->iopt_alloc; stream->iopt_alloc = last; for (i = 0; i < elts; i += 1) { xd3_rlist_push_back (& stream->iopt_free, & last->buffer[i]); } return 0; } /* This function allocates all memory initially used by the encoder. */ static int xd3_encode_init (xd3_stream *stream, int full_init) { int i; if (full_init) { int large_comp = (stream->src != NULL); int small_comp = ! (stream->flags & XD3_NOCOMPRESS); /* Memory allocations for checksum tables are delayed until * xd3_string_match_init in the first call to string_match--that way * identical or short inputs require no table allocation. */ if (large_comp) { usize_t hash_values = (stream->srcwin_maxsz / stream->smatcher.large_step); xd3_size_hashtable (stream, hash_values, & stream->large_hash); } if (small_comp) { /* TODO: This is under devel: used to have min(sprevsz) here, which sort * of makes sense, but observed fast performance w/ larger tables, which * also sort of makes sense. @@@ */ usize_t hash_values = stream->winsize; xd3_size_hashtable (stream, hash_values, & stream->small_hash); } } /* data buffers */ for (i = 0; i < ENC_SECTS; i += 1) { if ((stream->enc_heads[i] = stream->enc_tails[i] = xd3_alloc_output (stream, NULL)) == NULL) { return ENOMEM; } } /* iopt buffer */ xd3_rlist_init (& stream->iopt_used); xd3_rlist_init (& stream->iopt_free); if (xd3_alloc_iopt (stream, stream->iopt_size) != 0) { goto fail; } XD3_ASSERT (xd3_rlist_length (& stream->iopt_free) == stream->iopt_size); XD3_ASSERT (xd3_rlist_length (& stream->iopt_used) == 0); /* address cache, code table */ stream->acache.s_near = stream->code_table_desc->near_modes; stream->acache.s_same = stream->code_table_desc->same_modes; stream->code_table = stream->code_table_func (); return xd3_alloc_cache (stream); fail: return ENOMEM; } int xd3_encode_init_full (xd3_stream *stream) { return xd3_encode_init (stream, 1); } int xd3_encode_init_partial (xd3_stream *stream) { return xd3_encode_init (stream, 0); } /* Called after the ENC_POSTOUT state, this puts the output buffers * back into separate lists and re-initializes some variables. (The * output lists were spliced together during the ENC_FLUSH state.) */ static void xd3_encode_reset (xd3_stream *stream) { int i; xd3_output *olist; stream->avail_in = 0; stream->small_reset = 1; stream->i_slots_used = 0; if (stream->src != NULL) { stream->src->srcbase = 0; stream->src->srclen = 0; stream->srcwin_decided = 0; stream->srcwin_decided_early = 0; stream->match_minaddr = 0; stream->match_maxaddr = 0; stream->taroff = 0; } /* Reset output chains. */ olist = stream->enc_heads[0]; for (i = 0; i < ENC_SECTS; i += 1) { XD3_ASSERT (olist != NULL); stream->enc_heads[i] = olist; stream->enc_tails[i] = olist; olist = olist->next_page; stream->enc_heads[i]->next = 0; stream->enc_heads[i]->next_page = NULL; stream->enc_tails[i]->next_page = NULL; stream->enc_tails[i] = stream->enc_heads[i]; } xd3_freelist_output (stream, olist); } /* The main encoding routine. */ int xd3_encode_input (xd3_stream *stream) { int ret, i; if (stream->dec_state != 0) { stream->msg = "encoder/decoder transition"; return XD3_INTERNAL; } switch (stream->enc_state) { case ENC_INIT: /* Only reached on first time through: memory setup. */ if ((ret = xd3_encode_init_full (stream))) { return ret; } stream->enc_state = ENC_INPUT; case ENC_INPUT: /* If there is no input yet, just return. This checks for * next_in == NULL, not avail_in == 0 since zero bytes is a * valid input. There is an assertion in xd3_avail_input() that * next_in != NULL for this reason. By returning right away we * avoid creating an input buffer before the caller has supplied * its first data. It is possible for xd3_avail_input to be * called both before and after the first call to * xd3_encode_input(). */ if (stream->next_in == NULL) { return XD3_INPUT; } enc_flush: /* See if we should buffer the input: either if there is already * a leftover buffer, or if the input is short of winsize * without flush. The label at this point is reached by a goto * below, when there is leftover input after postout. */ if ((stream->buf_leftover != NULL) || (stream->buf_avail != 0) || (stream->avail_in < stream->winsize && ! (stream->flags & XD3_FLUSH))) { if ((ret = xd3_encode_buffer_leftover (stream))) { return ret; } } /* Initalize the address cache before each window. */ xd3_init_cache (& stream->acache); stream->input_position = 0; stream->min_match = MIN_MATCH; stream->unencoded_offset = 0; stream->enc_state = ENC_SEARCH; IF_DEBUG2 (DP(RINT "[WINSTART:%"Q"u] input bytes %u offset %"Q"u\n", stream->current_window, stream->avail_in, stream->total_in)); return XD3_WINSTART; case ENC_SEARCH: IF_DEBUG2 (DP(RINT "[SEARCH] match_state %d avail_in %u %s\n", stream->match_state, stream->avail_in, stream->src ? "source" : "no source")); /* Reentrant matching. */ if (stream->src != NULL) { switch (stream->match_state) { case MATCH_TARGET: /* Try matching forward at the start of the target. * This is entered the first time through, to check for * a perfect match, and whenever there is a source match * that extends to the end of the previous window. The * match_srcpos field is initially zero and later set * during xd3_source_extend_match. */ if (stream->avail_in > 0) { /* This call can't fail because the source window is * unrestricted. */ ret = xd3_source_match_setup (stream, stream->match_srcpos); XD3_ASSERT (ret == 0); stream->match_state = MATCH_FORWARD; } else { stream->match_state = MATCH_SEARCHING; stream->match_fwd = 0; } XD3_ASSERT (stream->match_fwd == 0); case MATCH_FORWARD: case MATCH_BACKWARD: if (stream->avail_in != 0) { if ((ret = xd3_source_extend_match (stream)) != 0) { return ret; } /* The search has to make forward progress here * or else it can get stuck in a match-backward * (getsrcblk) then match-forward (getsrcblk), * find insufficient match length, then repeat * exactly the same search. */ stream->input_position += stream->match_fwd; } case MATCH_SEARCHING: /* Continue string matching. (It's possible that the * initial match continued through the entire input, in * which case we're still in MATCH_FORWARD and should * remain so for the next input window.) */ break; } } /* String matching... */ if (stream->avail_in != 0 && (ret = stream->smatcher.string_match (stream))) { return ret; } stream->enc_state = ENC_INSTR; case ENC_INSTR: /* Note: Jump here to encode VCDIFF deltas w/o using this * string-matching code. Merging code code enters here. */ /* Flush the instrution buffer, then possibly add one more * instruction, then emit the header. */ if ((ret = xd3_iopt_flush_instructions (stream, 1)) || (ret = xd3_iopt_add_finalize (stream))) { return ret; } stream->enc_state = ENC_FLUSH; case ENC_FLUSH: /* Note: main_recode_func() bypasses string-matching by setting * ENC_FLUSH. */ if ((ret = xd3_emit_hdr (stream))) { return ret; } /* Begin output. */ stream->enc_current = HDR_HEAD (stream); /* Chain all the outputs together. After doing this, it looks * as if there is only one section. The other enc_heads are set * to NULL to avoid freeing them more than once. */ for (i = 1; i < ENC_SECTS; i += 1) { stream->enc_tails[i-1]->next_page = stream->enc_heads[i]; stream->enc_heads[i] = NULL; } enc_output: stream->enc_state = ENC_POSTOUT; stream->next_out = stream->enc_current->base; stream->avail_out = stream->enc_current->next; stream->total_out += (xoff_t) stream->avail_out; /* If there is any output in this buffer, return it, otherwise * fall through to handle the next buffer or finish the window * after all buffers have been output. */ if (stream->avail_out > 0) { /* This is the only place xd3_encode returns XD3_OUTPUT */ return XD3_OUTPUT; } case ENC_POSTOUT: if (stream->avail_out != 0) { stream->msg = "missed call to consume output"; return XD3_INTERNAL; } /* Continue outputting one buffer at a time, until the next is NULL. */ if ((stream->enc_current = stream->enc_current->next_page) != NULL) { goto enc_output; } stream->total_in += (xoff_t) stream->avail_in; stream->enc_state = ENC_POSTWIN; IF_DEBUG2 (DP(RINT "[WINFINISH:%"Q"u] in=%"Q"u\n", stream->current_window, stream->total_in)); return XD3_WINFINISH; case ENC_POSTWIN: xd3_encode_reset (stream); stream->current_window += 1; stream->enc_state = ENC_INPUT; /* If there is leftover input to flush, repeat. */ if (stream->buf_leftover != NULL) { goto enc_flush; } /* Ready for more input. */ return XD3_INPUT; default: stream->msg = "invalid state"; return XD3_INTERNAL; } } #endif /* XD3_ENCODER */ /***************************************************************** Client convenience functions ******************************************************************/ static int xd3_process_stream (int is_encode, xd3_stream *stream, int (*func) (xd3_stream *), int close_stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { usize_t ipos = 0; usize_t n = min(stream->winsize, input_size); (*output_size) = 0; stream->flags |= XD3_FLUSH; xd3_avail_input (stream, input + ipos, n); ipos += n; for (;;) { int ret; switch((ret = func (stream))) { case XD3_OUTPUT: { /* memcpy below */ break; } case XD3_INPUT: { n = min(stream->winsize, input_size - ipos); if (n == 0) { goto done; } xd3_avail_input (stream, input + ipos, n); ipos += n; continue; } case XD3_GOTHEADER: { /* ignore */ continue; } case XD3_WINSTART: { /* ignore */ continue; } case XD3_WINFINISH: { /* ignore */ continue; } case XD3_GETSRCBLK: { stream->msg = "stream requires source input"; return XD3_INTERNAL; } case 0: { /* xd3_encode_input/xd3_decode_input never return 0 */ stream->msg = "invalid return: 0"; return XD3_INTERNAL; } default: return ret; } if (*output_size + stream->avail_out > output_size_max) { stream->msg = "insufficient output space"; return ENOSPC; } memcpy (output + *output_size, stream->next_out, stream->avail_out); *output_size += stream->avail_out; xd3_consume_output (stream); } done: return (close_stream == 0) ? 0 : xd3_close_stream (stream); } static int xd3_process_memory (int is_encode, int (*func) (xd3_stream *), int close_stream, const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { xd3_stream stream; xd3_config config; xd3_source src; int ret; memset (& stream, 0, sizeof (stream)); memset (& config, 0, sizeof (config)); if (input == NULL || output == NULL) { stream.msg = "invalid input/output buffer"; ret = XD3_INTERNAL; goto exit; } config.flags = flags; if (is_encode) { config.srcwin_maxsz = source_size; config.winsize = min(input_size, (usize_t) XD3_DEFAULT_WINSIZE); config.iopt_size = min(input_size / 32, XD3_DEFAULT_IOPT_SIZE); config.iopt_size = max(config.iopt_size, 128U); config.sprevsz = xd3_pow2_roundup (config.winsize); } if ((ret = xd3_config_stream (&stream, &config)) != 0) { goto exit; } if (source != NULL) { memset (& src, 0, sizeof (src)); src.blksize = source_size; src.onblk = source_size; src.curblk = source; src.curblkno = 0; if ((ret = xd3_set_source_and_size (&stream, &src, source_size)) != 0) { goto exit; } } if ((ret = xd3_process_stream (is_encode, & stream, func, 1, input, input_size, output, output_size, output_size_max)) != 0) { goto exit; } exit: if (ret != 0) { IF_DEBUG2 (DP(RINT "process_memory: %d: %s\n", ret, stream.msg)); } xd3_free_stream(&stream); return ret; } int xd3_decode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { return xd3_process_stream (0, stream, & xd3_decode_input, 1, input, input_size, output, output_size, output_size_max); } int xd3_decode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { return xd3_process_memory (0, & xd3_decode_input, 1, input, input_size, source, source_size, output, output_size, output_size_max, flags); } #if XD3_ENCODER int xd3_encode_stream (xd3_stream *stream, const uint8_t *input, usize_t input_size, uint8_t *output, usize_t *output_size, usize_t output_size_max) { return xd3_process_stream (1, stream, & xd3_encode_input, 1, input, input_size, output, output_size, output_size_max); } int xd3_encode_memory (const uint8_t *input, usize_t input_size, const uint8_t *source, usize_t source_size, uint8_t *output, usize_t *output_size, usize_t output_size_max, int flags) { return xd3_process_memory (1, & xd3_encode_input, 1, input, input_size, source, source_size, output, output_size, output_size_max, flags); } #endif /************************************************************* String matching helpers *************************************************************/ #if XD3_ENCODER /* Do the initial xd3_string_match() checksum table setup. * Allocations are delayed until first use to avoid allocation * sometimes (e.g., perfect matches, zero-length inputs). */ static int xd3_string_match_init (xd3_stream *stream) { const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS); const int DO_LARGE = (stream->src != NULL); if (DO_LARGE && stream->large_table == NULL) { if ((stream->large_table = (usize_t*) xd3_alloc0 (stream, stream->large_hash.size, sizeof (usize_t))) == NULL) { return ENOMEM; } } if (DO_SMALL) { /* Subsequent calls can return immediately after checking reset. */ if (stream->small_table != NULL) { /* The target hash table is reinitialized once per window. */ /* TODO: This would not have to be reinitialized if absolute * offsets were being stored. */ if (stream->small_reset) { stream->small_reset = 0; memset (stream->small_table, 0, sizeof (usize_t) * stream->small_hash.size); } return 0; } if ((stream->small_table = (usize_t*) xd3_alloc0 (stream, stream->small_hash.size, sizeof (usize_t))) == NULL) { return ENOMEM; } /* If there is a previous table needed. */ if (stream->smatcher.small_lchain > 1 || stream->smatcher.small_chain > 1) { if ((stream->small_prev = (xd3_slist*) xd3_alloc (stream, stream->sprevsz, sizeof (xd3_slist))) == NULL) { return ENOMEM; } } } return 0; } #if XD3_USE_LARGEFILE64 /* This function handles the 32/64bit ambiguity -- file positions are 64bit * but the hash table for source-offsets is 32bit. */ static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low) { xoff_t scp = stream->srcwin_cksum_pos; xoff_t s0 = scp >> 32; usize_t sr = (usize_t) scp; if (s0 == 0) { return low; } /* This should not be >= because srcwin_cksum_pos is the next * position to index. */ if (low > sr) { return (--s0 << 32) | low; } return (s0 << 32) | low; } #else static xoff_t xd3_source_cksum_offset(xd3_stream *stream, usize_t low) { return (xoff_t) low; } #endif /* This function sets up the stream->src fields srcbase, srclen. The * call is delayed until these values are needed to encode a copy * address. At this point the decision has to be made. */ static int xd3_srcwin_setup (xd3_stream *stream) { xd3_source *src = stream->src; xoff_t length, x; /* Check the undecided state. */ XD3_ASSERT (src->srclen == 0 && src->srcbase == 0); /* Avoid repeating this call. */ stream->srcwin_decided = 1; /* If the stream is flushing, then the iopt buffer was able to * contain the complete encoding. If no copies were issued no * source window is actually needed. This prevents the VCDIFF * header from including source base/len. xd3_emit_hdr checks for * srclen == 0. */ if (stream->enc_state == ENC_INSTR && stream->match_maxaddr == 0) { goto done; } /* Check for overflow, srclen is usize_t - this can't happen unless * XD3_DEFAULT_SRCBACK and related parameters are extreme - should * use smaller windows. */ length = stream->match_maxaddr - stream->match_minaddr; x = (xoff_t) USIZE_T_MAX; if (length > x) { stream->msg = "source window length overflow (not 64bit)"; return XD3_INTERNAL; } /* If ENC_INSTR, then we know the exact source window to use because * no more copies can be issued. */ if (stream->enc_state == ENC_INSTR) { src->srcbase = stream->match_minaddr; src->srclen = (usize_t) length; XD3_ASSERT (src->srclen); goto done; } /* Otherwise, we have to make a guess. More copies may still be * issued, but we have to decide the source window base and length * now. */ src->srcbase = stream->match_minaddr; src->srclen = max ((usize_t) length, stream->avail_in + (stream->avail_in >> 2)); /* OPT: If we know the source size, it might be possible to reduce * srclen. */ XD3_ASSERT (src->srclen); done: /* Set the taroff. This convenience variable is used even when stream->src == NULL. */ stream->taroff = src->srclen; return 0; } /* Sets the bounding region for a newly discovered source match, prior * to calling xd3_source_extend_match(). This sets the match_maxfwd, * match_maxback variables. Note: srcpos is an absolute position * (xoff_t) but the match_maxfwd, match_maxback variables are usize_t. * Returns 0 if the setup succeeds, or 1 if the source position lies * outside an already-decided srcbase/srclen window. */ static int xd3_source_match_setup (xd3_stream *stream, xoff_t srcpos) { xd3_source *src = stream->src; usize_t greedy_or_not; xoff_t frontier_pos; stream->match_maxback = 0; stream->match_maxfwd = 0; stream->match_back = 0; stream->match_fwd = 0; /* This avoids a non-blocking endless loop caused by scanning * backwards across a block boundary, only to find not enough * matching bytes to beat the current min_match due to a better lazy * target match: the re-entry to xd3_string_match() repeats the same * long match because the input position hasn't changed. TODO: if * ever duplicates are added to the source hash table, this logic * won't suffice to avoid loops. See testing/regtest.cc's * TestNonBlockingProgress test! */ if (srcpos != 0 && srcpos == stream->match_last_srcpos) { IF_DEBUG2(DP(RINT "[match_setup] looping failure\n")); goto bad; } /* Implement srcwin_maxsz, which prevents the encoder from seeking * back further than the LRU cache maintaining FIFO discipline, (to * avoid seeking). */ frontier_pos = stream->src->frontier_blkno * stream->src->blksize; IF_DEBUG1(DP(RINT "[match_setup] frontier_pos %"Q"u, srcpos %"Q"u, " "srcwin_maxsz %u\n", frontier_pos, srcpos, stream->srcwin_maxsz)); if (srcpos < frontier_pos && frontier_pos - srcpos > stream->srcwin_maxsz) { IF_DEBUG1(DP(RINT "[match_setup] rejected due to srcwin_maxsz " "distance eof=%"Q"u srcpos=%"Q"u maxsz=%u\n", xd3_source_eof (stream->src), srcpos, stream->srcwin_maxsz)); goto bad; } /* Going backwards, the 1.5-pass algorithm allows some * already-matched input may be covered by a longer source match. * The greedy algorithm does not allow this. */ if (stream->flags & XD3_BEGREEDY) { /* The greedy algorithm allows backward matching to the last matched position. */ greedy_or_not = xd3_iopt_last_matched (stream); } else { /* The 1.5-pass algorithm allows backward matching to go back as * far as the unencoded offset, which is updated as instructions * pass out of the iopt buffer. If this (default) is chosen, it * means xd3_iopt_erase may be called to eliminate instructions * when a covering source match is found. */ greedy_or_not = stream->unencoded_offset; } /* Backward target match limit. */ XD3_ASSERT (stream->input_position >= greedy_or_not); stream->match_maxback = stream->input_position - greedy_or_not; /* Forward target match limit. */ XD3_ASSERT (stream->avail_in > stream->input_position); stream->match_maxfwd = stream->avail_in - stream->input_position; /* Now we take the source position into account. It depends whether * the srclen/srcbase have been decided yet. */ if (stream->srcwin_decided == 0) { /* Unrestricted case: the match can cover the entire source, * 0--src->size. We compare the usize_t * match_maxfwd/match_maxback against the xoff_t * src->size/srcpos values and take the min. */ if (srcpos < (xoff_t) stream->match_maxback) { stream->match_maxback = (usize_t) srcpos; } if (stream->src->eof_known) { xoff_t srcavail = xd3_source_eof (stream->src) - srcpos; if (srcavail < (xoff_t) stream->match_maxfwd) { stream->match_maxfwd = (usize_t) srcavail; } } IF_DEBUG1(DP(RINT "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "unrestricted maxback %u maxfwd %u\n", srcpos, stream->total_in + stream->input_position, stream->match_maxback, stream->match_maxfwd)); goto good; } /* Decided some source window. */ XD3_ASSERT (src->srclen > 0); /* Restricted case: fail if the srcpos lies outside the source window */ if ((srcpos < src->srcbase) || (srcpos > (src->srcbase + (xoff_t) src->srclen))) { IF_DEBUG1(DP(RINT "[match_setup] restricted source window failure\n")); goto bad; } else { usize_t srcavail; srcavail = (usize_t) (srcpos - src->srcbase); if (srcavail < stream->match_maxback) { stream->match_maxback = srcavail; } srcavail = (usize_t) (src->srcbase + (xoff_t) src->srclen - srcpos); if (srcavail < stream->match_maxfwd) { stream->match_maxfwd = srcavail; } IF_DEBUG1(DP(RINT "[match_setup] srcpos %"Q"u (tgtpos %"Q"u) " "restricted maxback %u maxfwd %u\n", srcpos, stream->total_in + stream->input_position, stream->match_maxback, stream->match_maxfwd)); goto good; } good: stream->match_state = MATCH_BACKWARD; stream->match_srcpos = srcpos; stream->match_last_srcpos = srcpos; return 0; bad: stream->match_state = MATCH_SEARCHING; return 1; } static inline int xd3_forward_match(const uint8_t *s1c, const uint8_t *s2c, int n) { int i = 0; #if UNALIGNED_OK int nint = n / sizeof(int); if (nint >> 3) { int j = 0; const int *s1 = (const int*)s1c; const int *s2 = (const int*)s2c; int nint_8 = nint - 8; while (i <= nint_8 && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++] && s1[i++] == s2[j++]) { } i = (i - 1) * sizeof(int); } #endif while (i < n && s1c[i] == s2c[i]) { i++; } return i; } /* This function expands the source match backward and forward. It is * reentrant, since xd3_getblk may return XD3_GETSRCBLK, so most * variables are kept in xd3_stream. There are two callers of this * function, the string_matching routine when a checksum match is * discovered, and xd3_encode_input whenever a continuing (or initial) * match is suspected. The two callers do different things with the * input_position, thus this function leaves that variable untouched. * If a match is taken the resulting stream->match_fwd is left * non-zero. */ static int xd3_source_extend_match (xd3_stream *stream) { int ret; xd3_source *src = stream->src; xoff_t matchoff; /* matchoff is the current right/left-boundary of the source match being tested. */ usize_t streamoff; /* streamoff is the current right/left-boundary of the input match being tested. */ xoff_t tryblk; /* tryblk, tryoff are the block, offset position of matchoff */ usize_t tryoff; usize_t tryrem; /* tryrem is the number of matchable bytes */ usize_t matched; IF_DEBUG2(DP(RINT "[extend match] srcpos %"Q"u\n", stream->match_srcpos)); XD3_ASSERT (src != NULL); /* Does it make sense to compute backward match AFTER forward match? */ if (stream->match_state == MATCH_BACKWARD) { /* Note: this code is practically duplicated below, substituting * match_fwd/match_back and direction. TODO: Consolidate? */ matchoff = stream->match_srcpos - stream->match_back; streamoff = stream->input_position - stream->match_back; xd3_blksize_div (matchoff, src, &tryblk, &tryoff); /* this loops backward over source blocks */ while (stream->match_back < stream->match_maxback) { /* see if we're backing across a source block boundary */ if (tryoff == 0) { tryoff = src->blksize; tryblk -= 1; } if ((ret = xd3_getblk (stream, tryblk))) { /* if search went too far back, continue forward. */ if (ret == XD3_TOOFARBACK) { break; } /* could be a XD3_GETSRCBLK failure. */ return ret; } tryrem = min (tryoff, stream->match_maxback - stream->match_back); IF_DEBUG2(DP(RINT "[maxback] maxback %u trysrc %"Q"u/%u tgt %u tryrem %u\n", stream->match_maxback, tryblk, tryoff, streamoff, tryrem)); /* TODO: This code can be optimized similar to xd3_match_forward() */ for (; tryrem != 0; tryrem -= 1, stream->match_back += 1) { if (src->curblk[tryoff-1] != stream->next_in[streamoff-1]) { goto doneback; } tryoff -= 1; streamoff -= 1; } } doneback: stream->match_state = MATCH_FORWARD; } XD3_ASSERT (stream->match_state == MATCH_FORWARD); matchoff = stream->match_srcpos + stream->match_fwd; streamoff = stream->input_position + stream->match_fwd; xd3_blksize_div (matchoff, src, & tryblk, & tryoff); /* Note: practically the same code as backwards case above: same comments */ while (stream->match_fwd < stream->match_maxfwd) { if (tryoff == src->blksize) { tryoff = 0; tryblk += 1; } if ((ret = xd3_getblk (stream, tryblk))) { /* if search went too far back, continue forward. */ if (ret == XD3_TOOFARBACK) { break; } /* could be a XD3_GETSRCBLK failure. */ return ret; } tryrem = min(stream->match_maxfwd - stream->match_fwd, src->onblk - tryoff); if (tryrem == 0) { /* Generally, this means we have a power-of-two size source * and we just found the end-of-file, in this case it's an * empty block. */ XD3_ASSERT (src->onblk < src->blksize); break; } matched = xd3_forward_match(src->curblk + tryoff, stream->next_in + streamoff, tryrem); tryoff += matched; streamoff += matched; stream->match_fwd += matched; if (tryrem != matched) { break; } } stream->match_state = MATCH_SEARCHING; /* If the match ends short of the last instruction end, we probably * don't want it. There is the possibility that a copy ends short * of the last copy but also goes further back, in which case we * might want it. This code does not implement such: if so we would * need more complicated xd3_iopt_erase logic. */ if (stream->match_fwd < stream->min_match) { stream->match_fwd = 0; } else { usize_t total = stream->match_fwd + stream->match_back; /* Correct the variables to remove match_back from the equation. */ usize_t target_position = stream->input_position - stream->match_back; usize_t match_length = stream->match_back + stream->match_fwd; xoff_t match_position = stream->match_srcpos - stream->match_back; xoff_t match_end = stream->match_srcpos + stream->match_fwd; /* At this point we may have to erase any iopt-buffer * instructions that are fully covered by a backward-extending * copy. */ if (stream->match_back > 0) { xd3_iopt_erase (stream, target_position, total); } stream->match_back = 0; /* Update ranges. The first source match occurs with both values set to 0. */ if (stream->match_maxaddr == 0 || match_position < stream->match_minaddr) { stream->match_minaddr = match_position; } if (match_end > stream->match_maxaddr) { /* Note: per-window */ stream->match_maxaddr = match_end; } if (match_end > stream->maxsrcaddr) { /* Note: across windows */ stream->maxsrcaddr = match_end; } IF_DEBUG1 ({ static int x = 0; DP(RINT "[source match:%d] (%s) [ %u bytes ]\n", x++, stream->total_in + target_position, stream->total_in + target_position + match_length, match_position, match_position + match_length, (stream->total_in + target_position == match_position) ? "same" : "diff", match_length); }); if ((ret = xd3_found_match (stream, /* decoder position */ target_position, /* length */ match_length, /* address */ match_position, /* is_source */ 1))) { return ret; } /* If the match ends with the available input: */ if (target_position + match_length == stream->avail_in) { /* Setup continuing match for the next window. */ stream->match_state = MATCH_TARGET; stream->match_srcpos = match_end; } } return 0; } /* Update the small hash. Values in the small_table are offset by * HASH_CKOFFSET (1) to distinguish empty buckets from real offsets. */ static void xd3_scksum_insert (xd3_stream *stream, usize_t inx, usize_t scksum, usize_t pos) { /* If we are maintaining previous duplicates. */ if (stream->small_prev) { usize_t last_pos = stream->small_table[inx]; xd3_slist *pos_list = & stream->small_prev[pos & stream->sprevmask]; /* Note last_pos is offset by HASH_CKOFFSET. */ pos_list->last_pos = last_pos; } /* Enter the new position into the hash bucket. */ stream->small_table[inx] = pos + HASH_CKOFFSET; } #if XD3_DEBUG static int xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0, const uint8_t *inp_max, usize_t cmp_len) { usize_t i; for (i = 0; i < cmp_len; i += 1) { XD3_ASSERT (ref0[i] == inp0[i]); } if (inp0 + cmp_len < inp_max) { XD3_ASSERT (inp0[i] != ref0[i]); } return 1; } #endif /* XD3_DEBUG */ /* When the hash table indicates a possible small string match, it * calls this routine to find the best match. The first matching * position is taken from the small_table, HASH_CKOFFSET is subtracted * to get the actual position. After checking that match, if previous * linked lists are in use (because stream->smatcher.small_chain > 1), * previous matches are tested searching for the longest match. If * (stream->min_match > MIN_MATCH) then a lazy match is in effect. */ static usize_t xd3_smatch (xd3_stream *stream, usize_t base, usize_t scksum, usize_t *match_offset) { usize_t cmp_len; usize_t match_length = 0; usize_t chain = (stream->min_match == MIN_MATCH ? stream->smatcher.small_chain : stream->smatcher.small_lchain); const uint8_t *inp_max = stream->next_in + stream->avail_in; const uint8_t *inp; const uint8_t *ref; SMALL_HASH_DEBUG1 (stream, stream->next_in + stream->input_position); XD3_ASSERT (stream->min_match + stream->input_position <= stream->avail_in); base -= HASH_CKOFFSET; again: IF_DEBUG2 (DP(RINT "smatch at base=%u inp=%u cksum=%u\n", base, stream->input_position, scksum)); /* For small matches, we can always go to the end-of-input because * the matching position must be less than the input position. */ XD3_ASSERT (base < stream->input_position); ref = stream->next_in + base; inp = stream->next_in + stream->input_position; SMALL_HASH_DEBUG2 (stream, ref); /* Expand potential match forward. */ while (inp < inp_max && *inp == *ref) { ++inp; ++ref; } cmp_len = (usize_t)(inp - (stream->next_in + stream->input_position)); /* Verify correctness */ XD3_ASSERT (xd3_check_smatch (stream->next_in + base, stream->next_in + stream->input_position, inp_max, cmp_len)); /* Update longest match */ if (cmp_len > match_length) { ( match_length) = cmp_len; (*match_offset) = base; /* Stop if we match the entire input or have a long_enough match. */ if (inp == inp_max || cmp_len >= stream->smatcher.long_enough) { goto done; } } /* If we have not reached the chain limit, see if there is another previous position. */ while (--chain != 0) { /* Calculate the previous offset. */ usize_t prev_pos = stream->small_prev[base & stream->sprevmask].last_pos; usize_t diff_pos; if (prev_pos == 0) { break; } prev_pos -= HASH_CKOFFSET; if (prev_pos > base) { break; } base = prev_pos; XD3_ASSERT (stream->input_position > base); diff_pos = stream->input_position - base; /* Stop searching if we go beyond sprevsz, since those entries * are for unrelated checksum entries. */ if (diff_pos & ~stream->sprevmask) { break; } goto again; } done: /* Crude efficiency test: if the match is very short and very far back, it's * unlikely to help, but the exact calculation requires knowing the state of * the address cache and adjacent instructions, which we can't do here. * Rather than encode a probably inefficient copy here and check it later * (which complicates the code a lot), do this: */ if (match_length == 4 && stream->input_position - (*match_offset) >= 1<<14) { /* It probably takes >2 bytes to encode an address >= 2^14 from here */ return 0; } if (match_length == 5 && stream->input_position - (*match_offset) >= 1<<21) { /* It probably takes >3 bytes to encode an address >= 2^21 from here */ return 0; } /* It's unlikely that a window is large enough for the (match_length == 6 && * address >= 2^28) check */ return match_length; } #if XD3_DEBUG static void xd3_verify_small_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum) { uint32_t state; uint32_t cksum = xd3_scksum (&state, inp, stream->smatcher.small_look); XD3_ASSERT (cksum == x_cksum); } static void xd3_verify_large_state (xd3_stream *stream, const uint8_t *inp, uint32_t x_cksum) { uint32_t cksum = xd3_lcksum (inp, stream->smatcher.large_look); XD3_ASSERT (cksum == x_cksum); } static void xd3_verify_run_state (xd3_stream *stream, const uint8_t *inp, usize_t x_run_l, uint8_t *x_run_c) { usize_t slook = stream->smatcher.small_look; uint8_t run_c; usize_t run_l = xd3_comprun (inp, slook, &run_c); XD3_ASSERT (run_l == 0 || run_c == *x_run_c); XD3_ASSERT (x_run_l > slook || run_l == x_run_l); } #endif /* XD3_DEBUG */ /* This function computes more source checksums to advance the window. * Called at every entrance to the string-match loop and each time * stream->input_position reaches the value returned as * *next_move_point. NB: this is one of the most expensive functions * in this code and also the most critical for good compression. * TODO: optimize the inner loop */ static int xd3_srcwin_move_point (xd3_stream *stream, usize_t *next_move_point) { xoff_t logical_input_cksum_pos; xoff_t source_size; if (stream->src->eof_known) { source_size = xd3_source_eof (stream->src); XD3_ASSERT(stream->srcwin_cksum_pos <= source_size); if (stream->srcwin_cksum_pos == source_size) { *next_move_point = USIZE_T_MAX; return 0; } } /* Begin by advancing at twice the input rate, up to half the * maximum window size. */ logical_input_cksum_pos = min((stream->total_in + stream->input_position) * 2, (stream->total_in + stream->input_position) + (stream->srcwin_maxsz / 2)); /* If srcwin_cksum_pos is already greater, wait until the difference * is met. */ if (stream->srcwin_cksum_pos > logical_input_cksum_pos) { *next_move_point = stream->input_position + (usize_t)(stream->srcwin_cksum_pos - logical_input_cksum_pos); return 0; } /* A long match may have extended past srcwin_cksum_pos. Don't * start checksumming already-matched source data. */ if (stream->maxsrcaddr > stream->srcwin_cksum_pos) { stream->srcwin_cksum_pos = stream->maxsrcaddr; } if (logical_input_cksum_pos < stream->srcwin_cksum_pos) { logical_input_cksum_pos = stream->srcwin_cksum_pos; } /* Advance at least one source block. With the command-line * defaults this means: * * if (src->size <= srcwin_maxsz), index the entire source at once * using the position of the first non-match. This is good for * small inputs, especially when the content may have moved anywhere * in the file (e.g., tar files). * * if (src->size > srcwin_maxsz), index at least one block (which * the command-line sets to 1/32 of srcwin_maxsz) ahead of the * logical position. This is good for different reasons: when a * long match spanning several source blocks is encountered, this * avoids computing checksums for those blocks. If the data can * move anywhere, this is bad. */ logical_input_cksum_pos += stream->src->blksize; while (stream->srcwin_cksum_pos < logical_input_cksum_pos && (!stream->src->eof_known || stream->srcwin_cksum_pos < xd3_source_eof (stream->src))) { xoff_t blkno; xoff_t blkbaseoffset; usize_t blkrem; ssize_t oldpos; /* Using ssize_t because of a */ ssize_t blkpos; /* do { blkpos-- } while (blkpos >= oldpos); */ int ret; xd3_blksize_div (stream->srcwin_cksum_pos, stream->src, &blkno, &blkrem); oldpos = blkrem; if ((ret = xd3_getblk (stream, blkno))) { /* TOOFARBACK should never occur here, since we read forward. */ if (ret == XD3_TOOFARBACK) { ret = XD3_INTERNAL; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] async getblk return for %"Q"u\n", blkno)); return ret; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] T=%"Q"u{%"Q"u} S=%"Q"u EOF=%"Q"u %s\n", stream->total_in + stream->input_position, logical_input_cksum_pos, stream->srcwin_cksum_pos, xd3_source_eof (stream->src), stream->src->eof_known ? "known" : "unknown")); blkpos = xd3_bytes_on_srcblk (stream->src, blkno); if (blkpos < (ssize_t) stream->smatcher.large_look) { stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; IF_DEBUG1 (DP(RINT "[srcwin_move_point] continue (end-of-block)\n")); continue; } /* This inserts checksums for the entire block, in reverse, * starting from the end of the block. This logic does not test * stream->srcwin_cksum_pos because it always advances it to the * start of the next block. * * oldpos is the srcwin_cksum_pos within this block. blkpos is * the number of bytes available. Each iteration inspects * large_look bytes then steps back large_step bytes. The * if-stmt above ensures at least one large_look of data. */ blkpos -= stream->smatcher.large_look; blkbaseoffset = stream->src->blksize * blkno; do { uint32_t cksum = xd3_lcksum (stream->src->curblk + blkpos, stream->smatcher.large_look); usize_t hval = xd3_checksum_hash (& stream->large_hash, cksum); stream->large_table[hval] = (usize_t) (blkbaseoffset + (xoff_t)(blkpos + HASH_CKOFFSET)); IF_DEBUG (stream->large_ckcnt += 1); blkpos -= stream->smatcher.large_step; } while (blkpos >= oldpos); stream->srcwin_cksum_pos = (blkno + 1) * stream->src->blksize; } IF_DEBUG1 (DP(RINT "[srcwin_move_point] exited loop T=%"Q"u{%"Q"u} " "S=%"Q"u EOF=%"Q"u %s\n", stream->total_in + stream->input_position, logical_input_cksum_pos, stream->srcwin_cksum_pos, xd3_source_eof (stream->src), stream->src->eof_known ? "known" : "unknown")); if (stream->src->eof_known) { source_size = xd3_source_eof (stream->src); if (stream->srcwin_cksum_pos >= source_size) { /* This invariant is needed for xd3_source_cksum_offset() */ stream->srcwin_cksum_pos = source_size; *next_move_point = USIZE_T_MAX; IF_DEBUG1 (DP(RINT "[srcwin_move_point] finished with source input\n")); return 0; } } /* How long until this function should be called again. */ XD3_ASSERT(stream->srcwin_cksum_pos >= logical_input_cksum_pos); *next_move_point = stream->input_position + 1 + (usize_t)(stream->srcwin_cksum_pos - logical_input_cksum_pos); return 0; } #endif /* XD3_ENCODER */ /******************************************************************** TEMPLATE pass *********************************************************************/ #endif /* __XDELTA3_C_INLINE_PASS__ */ #ifdef __XDELTA3_C_TEMPLATE_PASS__ #if XD3_ENCODER /******************************************************************** Templates *******************************************************************/ /* Template macros */ #define XD3_TEMPLATE(x) XD3_TEMPLATE2(x,TEMPLATE) #define XD3_TEMPLATE2(x,n) XD3_TEMPLATE3(x,n) #define XD3_TEMPLATE3(x,n) x ## n #define XD3_STRINGIFY(x) XD3_STRINGIFY2(x) #define XD3_STRINGIFY2(x) #x static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream); static const xd3_smatcher XD3_TEMPLATE(__smatcher_) = { XD3_STRINGIFY(TEMPLATE), XD3_TEMPLATE(xd3_string_match_), #if SOFTCFG == 1 0, 0, 0, 0, 0, 0, 0 #else LLOOK, LSTEP, SLOOK, SCHAIN, SLCHAIN, MAXLAZY, LONGENOUGH #endif }; static int XD3_TEMPLATE(xd3_string_match_) (xd3_stream *stream) { const int DO_SMALL = ! (stream->flags & XD3_NOCOMPRESS); const int DO_LARGE = (stream->src != NULL); const int DO_RUN = (1); const uint8_t *inp; uint32_t scksum = 0; uint32_t scksum_state = 0; uint32_t lcksum = 0; usize_t sinx; usize_t linx; uint8_t run_c; usize_t run_l; int ret; usize_t match_length; usize_t match_offset = 0; usize_t next_move_point; /* If there will be no compression due to settings or short input, * skip it entirely. */ if (! (DO_SMALL || DO_LARGE || DO_RUN) || stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } if ((ret = xd3_string_match_init (stream))) { return ret; } /* The restartloop label is reached when the incremental loop state * needs to be reset. */ restartloop: /* If there is not enough input remaining for any kind of match, skip it. */ if (stream->input_position + SLOOK > stream->avail_in) { goto loopnomore; } /* Now reset the incremental loop state: */ /* The min_match variable is updated to avoid matching the same lazy * match over and over again. For example, if you find a (small) * match of length 9 at one position, you will likely find a match * of length 8 at the next position. */ if (xd3_iopt_last_matched (stream) > stream->input_position) { stream->min_match = max(MIN_MATCH, 1 + xd3_iopt_last_matched(stream) - stream->input_position); } else { stream->min_match = MIN_MATCH; } /* The current input byte. */ inp = stream->next_in + stream->input_position; /* Small match state. */ if (DO_SMALL) { scksum = xd3_scksum (&scksum_state, inp, SLOOK); } /* Run state. */ if (DO_RUN) { run_l = xd3_comprun (inp, SLOOK, & run_c); } /* Large match state. We continue the loop even after not enough * bytes for LLOOK remain, so always check stream->input_position in * DO_LARGE code. */ if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) { /* Source window: next_move_point is the point that * stream->input_position must reach before computing more * source checksum. */ if ((ret = xd3_srcwin_move_point (stream, & next_move_point))) { return ret; } lcksum = xd3_lcksum (inp, LLOOK); } /* TRYLAZYLEN: True if a certain length match should be followed by * lazy search. This checks that LEN is shorter than MAXLAZY and * that there is enough leftover data to consider lazy matching. * "Enough" is set to 2 since the next match will start at the next * offset, it must match two extra characters. */ #define TRYLAZYLEN(LEN,POS,MAX) ((MAXLAZY) > 0 && (LEN) < (MAXLAZY) \ && (POS) + (LEN) <= (MAX) - 2) /* HANDLELAZY: This statement is called each time an instruciton is * emitted (three cases). If the instruction is large enough, the * loop is restarted, otherwise lazy matching may ensue. */ #define HANDLELAZY(mlen) \ if (TRYLAZYLEN ((mlen), (stream->input_position), (stream->avail_in))) \ { stream->min_match = (mlen) + LEAST_MATCH_INCR; goto updateone; } \ else \ { stream->input_position += (mlen); goto restartloop; } /* Now loop over one input byte at a time until a match is found... */ for (;; inp += 1, stream->input_position += 1) { /* Now we try three kinds of string match in order of expense: * run, large match, small match. */ /* Expand the start of a RUN. The test for (run_l == SLOOK) * avoids repeating this check when we pass through a run area * performing lazy matching. The run is only expanded once when * the min_match is first reached. If lazy matching is * performed, the run_l variable will remain inconsistent until * the first non-running input character is reached, at which * time the run_l may then again grow to SLOOK. */ if (DO_RUN && run_l == SLOOK) { usize_t max_len = stream->avail_in - stream->input_position; IF_DEBUG (xd3_verify_run_state (stream, inp, run_l, &run_c)); while (run_l < max_len && inp[run_l] == run_c) { run_l += 1; } /* Output a RUN instruction. */ if (run_l >= stream->min_match && run_l >= MIN_RUN) { if ((ret = xd3_emit_run (stream, stream->input_position, run_l, &run_c))) { return ret; } HANDLELAZY (run_l); } } /* If there is enough input remaining. */ if (DO_LARGE && (stream->input_position + LLOOK <= stream->avail_in)) { if ((stream->input_position >= next_move_point) && (ret = xd3_srcwin_move_point (stream, & next_move_point))) { return ret; } linx = xd3_checksum_hash (& stream->large_hash, lcksum); IF_DEBUG (xd3_verify_large_state (stream, inp, lcksum)); if (stream->large_table[linx] != 0) { /* the match_setup will fail if the source window has * been decided and the match lies outside it. * OPT: Consider forcing a window at this point to * permit a new source window. */ xoff_t adj_offset = xd3_source_cksum_offset(stream, stream->large_table[linx] - HASH_CKOFFSET); if (xd3_source_match_setup (stream, adj_offset) == 0) { if ((ret = xd3_source_extend_match (stream))) { return ret; } /* Update stream position. match_fwd is zero if no * match. */ if (stream->match_fwd > 0) { HANDLELAZY (stream->match_fwd); } } } } /* Small matches. */ if (DO_SMALL) { sinx = xd3_checksum_hash (& stream->small_hash, scksum); /* Verify incremental state in debugging mode. */ IF_DEBUG (xd3_verify_small_state (stream, inp, scksum)); /* Search for the longest match */ if (stream->small_table[sinx] != 0) { match_length = xd3_smatch (stream, stream->small_table[sinx], scksum, & match_offset); } else { match_length = 0; } /* Insert a hash for this string. */ xd3_scksum_insert (stream, sinx, scksum, stream->input_position); /* Maybe output a COPY instruction */ if (match_length >= stream->min_match) { IF_DEBUG2 ({ static int x = 0; DP(RINT "[target match:%d] " "(-%d) [ %u bytes ]\n", x++, stream->input_position, stream->input_position + match_length, match_offset, match_offset + match_length, stream->input_position - match_offset, match_length); }); if ((ret = xd3_found_match (stream, /* decoder position */ stream->input_position, /* length */ match_length, /* address */ (xoff_t) match_offset, /* is_source */ 0))) { return ret; } /* Copy instruction. */ HANDLELAZY (match_length); } } /* The logic above prevents excess work during lazy matching by * increasing min_match to avoid smaller matches. Each time we * advance stream->input_position by one, the minimum match * shortens as well. */ if (stream->min_match > MIN_MATCH) { stream->min_match -= 1; } updateone: /* See if there are no more incremental cksums to compute. */ if (stream->input_position + SLOOK == stream->avail_in) { goto loopnomore; } /* Compute next RUN, CKSUM */ if (DO_RUN) { NEXTRUN (inp[SLOOK]); } if (DO_SMALL) { scksum = xd3_small_cksum_update (&scksum_state, inp, SLOOK); } if (DO_LARGE && (stream->input_position + LLOOK < stream->avail_in)) { lcksum = xd3_large_cksum_update (lcksum, inp, LLOOK); } } loopnomore: return 0; } #endif /* XD3_ENCODER */ #endif /* __XDELTA3_C_TEMPLATE_PASS__ */ xdelta3-3.0.7/examples/iOS/xdelta3-ios-test/xdelta3-ios-test/main.m0000644000176500017650000000056512105354541024207 0ustar debdevdebdev// // main.m // xdelta3-ios-test // // Created by Joshua MacDonald on 6/16/12. // Copyright (c) 2011, 2012 Joshua MacDonald. All rights reserved. // #import #import "Xd3iOSAppDelegate.h" int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([Xd3iOSAppDelegate class])); } } xdelta3-3.0.7/xdelta3-hash.h0000644000176500017650000001117712105354541015012 0ustar debdevdebdev/* xdelta 3 - delta compression tools and library * Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007. Joshua P. MacDonald * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XDELTA3_HASH_H_ #define _XDELTA3_HASH_H_ #if XD3_DEBUG #define SMALL_HASH_DEBUG1(s,inp) \ uint32_t debug_state; \ uint32_t debug_hval = xd3_checksum_hash (& (s)->small_hash, \ xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look)) #define SMALL_HASH_DEBUG2(s,inp) \ XD3_ASSERT (debug_hval == xd3_checksum_hash (& (s)->small_hash, \ xd3_scksum (&debug_state, (inp), (s)->smatcher.small_look))) #else #define SMALL_HASH_DEBUG1(s,inp) #define SMALL_HASH_DEBUG2(s,inp) #endif /* XD3_DEBUG */ /* This is a good hash multiplier for 32-bit LCGs: see "linear * congruential generators of different sizes and good lattice * structure" */ static const uint32_t hash_multiplier = 1597334677U; /*********************************************************************** Permute stuff ***********************************************************************/ #if HASH_PERMUTE == 0 #define PERMUTE(x) (x) #else #define PERMUTE(x) (__single_hash[(uint32_t)x]) extern const uint16_t __single_hash[256]; #endif /* Update the checksum state. */ #if ADLER_LARGE_CKSUM inline uint32_t xd3_large_cksum_update (uint32_t cksum, const uint8_t *base, usize_t look) { uint32_t old_c = PERMUTE(base[0]); uint32_t new_c = PERMUTE(base[look]); uint32_t low = ((cksum & 0xffff) - old_c + new_c) & 0xffff; uint32_t high = ((cksum >> 16) - (old_c * look) + low) & 0xffff; return (high << 16) | low; } #else /* TODO: revisit this topic */ #endif #if UNALIGNED_OK #define UNALIGNED_READ32(dest,src) (*(dest)) = (*(uint32_t*)(src)) #else #define UNALIGNED_READ32(dest,src) memcpy((dest), (src), 4); #endif /* TODO: small cksum is hard-coded for 4 bytes (i.e., "look" is unused) */ static inline uint32_t xd3_scksum (uint32_t *state, const uint8_t *base, const usize_t look) { UNALIGNED_READ32(state, base); return (*state) * hash_multiplier; } static inline uint32_t xd3_small_cksum_update (uint32_t *state, const uint8_t *base, usize_t look) { UNALIGNED_READ32(state, base+1); return (*state) * hash_multiplier; } /*********************************************************************** Ctable stuff ***********************************************************************/ static inline usize_t xd3_checksum_hash (const xd3_hash_cfg *cfg, const usize_t cksum) { return (cksum >> cfg->shift) ^ (cksum & cfg->mask); } /*********************************************************************** Cksum function ***********************************************************************/ #if ADLER_LARGE_CKSUM static inline uint32_t xd3_lcksum (const uint8_t *seg, const usize_t ln) { usize_t i = 0; uint32_t low = 0; uint32_t high = 0; for (; i < ln; i += 1) { low += PERMUTE(*seg++); high += low; } return ((high & 0xffff) << 16) | (low & 0xffff); } #else static inline uint32_t xd3_lcksum (const uint8_t *seg, const usize_t ln) { usize_t i, j; uint32_t h = 0; for (i = 0, j = ln - 1; i < ln; ++i, --j) { h += PERMUTE(seg[i]) * hash_multiplier_powers[j]; } return h; } #endif #if XD3_ENCODER static usize_t xd3_size_log2 (usize_t slots) { int bits = 28; /* This should not be an unreasonable limit. */ int i; for (i = 3; i <= bits; i += 1) { if (slots < (1U << i)) { /* TODO: this is compaction=1 in checksum_test.cc and maybe should * not be fixed at -1. */ bits = i - 1; break; } } return bits; } static void xd3_size_hashtable (xd3_stream *stream, usize_t slots, xd3_hash_cfg *cfg) { int bits = xd3_size_log2 (slots); /* TODO: there's a 32-bit assumption here */ cfg->size = (1 << bits); cfg->mask = (cfg->size - 1); cfg->shift = 32 - bits; } #endif #endif xdelta3-3.0.7/xdelta3.vcxproj0000755000176500017650000004705212105354541015341 0ustar debdevdebdev Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 xdelta3-64 Itanium xdelta3-64 Win32 xdelta3-64 x64 %(PreprocessorDefinitions) %(PreprocessorDefinitions) %(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) /DXD3_DEBUG=0 /DXD3_USE_LARGEFILE64=1 /DREGRESSION_TEST=1 /DSECONDARY_DJW=1 /DSECONDARY_FGK=1 /DXD3_MAIN=1 /DXD3_WIN32=1 /DEXTERNAL_COMPRESSION=0 /DXD3_STDIO=0 /DXD3_POSIX=0;%(PreprocessorDefinitions) {8F9D37B5-B78E-4816-BE61-AEF679DBF3BC} Win32Proj xdelta3 Application true MultiByte Application true MultiByte Application true MultiByte Application false true MultiByte Application false true MultiByte Application false true MultiByte Windows7.1SDK Application false true MultiByte Application false true MultiByte Application false true MultiByte true true true false false false false false false NotUsing Level3 Disabled WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true NotUsing Level3 Disabled WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true NotUsing Level3 Disabled WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true Level3 NotUsing MaxSpeed true true WIN32;XD3_MAIN=1;XD3_DEBUG=0;XD3_USE_LARGEFILE64=1;REGRESSION_TEST=1;SECONDARY_DJW=1;SECONDARY_FGK=1;XD3_WIN32=1;EXTERNAL_COMPRESSION=0;SHELL_TESTS=0;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded Console true true true